Skip to content

Commit 3b01562

Browse files
committed
Add Peekable::peek_mut
1 parent d9a105f commit 3b01562

File tree

3 files changed

+49
-0
lines changed

3 files changed

+49
-0
lines changed

library/core/src/iter/adapters/peekable.rs

+37
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,43 @@ impl<I: Iterator> Peekable<I> {
216216
self.peeked.get_or_insert_with(|| iter.next()).as_ref()
217217
}
218218

219+
/// Returns a mutable reference to the next() value without advancing the iterator.
220+
///
221+
/// Like [`next`], if there is a value, it is wrapped in a `Some(T)`.
222+
/// But if the iteration is over, `None` is returned.
223+
///
224+
/// Because `peek_mut()` returns a reference, and many iterators iterate over
225+
/// references, there can be a possibly confusing situation where the
226+
/// return value is a double reference. You can see this effect in the examples
227+
/// below.
228+
///
229+
/// [`next`]: Iterator::next
230+
///
231+
/// # Examples
232+
///
233+
/// ```
234+
/// #![feature(peekable_peek_mut)]
235+
/// let mut iter = [1, 2, 3].iter().peekable();
236+
///
237+
/// assert_eq!(iter.peek_mut(), Some(&mut &1));
238+
/// assert_eq!(iter.next(), Some(&1));
239+
///
240+
/// // Peek into the iterator and modify the value which will be returned next
241+
/// if let Some(mut p) = iter.peek_mut() {
242+
/// if *p == &2 {
243+
/// *p = &5;
244+
/// }
245+
/// }
246+
///
247+
/// assert_eq!(iter.collect::<Vec<_>>(), vec![&5, &3]);
248+
/// ```
249+
#[inline]
250+
#[unstable(feature = "peekable_peek_mut", issue = "78302")]
251+
pub fn peek_mut(&mut self) -> Option<&mut I::Item> {
252+
let iter = &mut self.iter;
253+
self.peeked.get_or_insert_with(|| iter.next()).as_mut()
254+
}
255+
219256
/// Consume and return the next value of this iterator if a condition is true.
220257
///
221258
/// If `func` returns `true` for the next value of this iterator, consume and return it.

library/core/tests/iter.rs

+11
Original file line numberDiff line numberDiff line change
@@ -1134,6 +1134,17 @@ fn test_iterator_peekable_next_if_eq() {
11341134
assert_eq!(it.next_if_eq(""), None);
11351135
}
11361136

1137+
#[test]
1138+
fn test_iterator_peekable_mut() {
1139+
let mut it = vec![1, 2, 3].into_iter().peekable();
1140+
if let Some(p) = it.peek_mut() {
1141+
if *p == 1 {
1142+
*p = 5;
1143+
}
1144+
}
1145+
assert_eq!(it.collect::<Vec<_>>(), vec![5, 2, 3]);
1146+
}
1147+
11371148
/// This is an iterator that follows the Iterator contract,
11381149
/// but it is not fused. After having returned None once, it will start
11391150
/// producing elements if .next() is called again.

library/core/tests/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
#![feature(unwrap_infallible)]
5757
#![feature(option_unwrap_none)]
5858
#![feature(peekable_next_if)]
59+
#![feature(peekable_peek_mut)]
5960
#![feature(partition_point)]
6061
#![feature(once_cell)]
6162
#![feature(unsafe_block_in_unsafe_fn)]

0 commit comments

Comments
 (0)