wagon_utils/peek.rs
1use std::iter::Peekable;
2
3/// A trait version of the functionality that [`Peekable`] provides.
4///
5/// Something like this has been in RFC for a while, but it's not getting implemented.
6/// For our own purposes, we implement it ourselves.
7///
8/// [`Peekable`] implements this trait by calling inner methods of the same name.
9///
10/// NOTE: The documentation of these methods are taken directly from the [`Peekable`] documentation.
11/// your implementation of these methods may work differently. This is fine and expected, as long as you
12/// know and document what you're doing and why.
13pub trait Peek: Iterator {
14 /// Returns a reference to the `next()` value without advancing the iterator.
15 ///
16 /// Like [`next`], if there is a value, it is wrapped in a `Some(T)`.
17 /// But if the iteration is over, `None` is returned.
18 ///
19 /// [`next`]: Iterator::next
20 ///
21 /// Because `peek()` returns a reference, and many iterators iterate over
22 /// references, there can be a possibly confusing situation where the
23 /// return value is a double reference. You can see this effect in the
24 /// examples below.
25 ///
26 /// # Examples
27 ///
28 /// Basic usage:
29 ///
30 /// ```
31 /// let xs = [1, 2, 3];
32 ///
33 /// let mut iter = xs.iter().peekable();
34 ///
35 /// // peek() lets us see into the future
36 /// assert_eq!(iter.peek(), Some(&&1));
37 /// assert_eq!(iter.next(), Some(&1));
38 ///
39 /// assert_eq!(iter.next(), Some(&2));
40 ///
41 /// // The iterator does not advance even if we `peek` multiple times
42 /// assert_eq!(iter.peek(), Some(&&3));
43 /// assert_eq!(iter.peek(), Some(&&3));
44 ///
45 /// assert_eq!(iter.next(), Some(&3));
46 ///
47 /// // After the iterator is finished, so is `peek()`
48 /// assert_eq!(iter.peek(), None);
49 /// assert_eq!(iter.next(), None);
50 /// ```
51 fn peek(&mut self) -> Option<&Self::Item>;
52 /// Returns a mutable reference to the `next()` value without advancing the iterator.
53 ///
54 /// Like [`next`], if there is a value, it is wrapped in a `Some(T)`.
55 /// But if the iteration is over, `None` is returned.
56 ///
57 /// Because `peek_mut()` returns a reference, and many iterators iterate over
58 /// references, there can be a possibly confusing situation where the
59 /// return value is a double reference. You can see this effect in the examples
60 /// below.
61 ///
62 /// [`next`]: Iterator::next
63 ///
64 /// # Examples
65 ///
66 /// Basic usage:
67 ///
68 /// ```
69 /// let mut iter = [1, 2, 3].iter().peekable();
70 ///
71 /// // Like with `peek()`, we can see into the future without advancing the iterator.
72 /// assert_eq!(iter.peek_mut(), Some(&mut &1));
73 /// assert_eq!(iter.peek_mut(), Some(&mut &1));
74 /// assert_eq!(iter.next(), Some(&1));
75 ///
76 /// // Peek into the iterator and set the value behind the mutable reference.
77 /// if let Some(p) = iter.peek_mut() {
78 /// assert_eq!(*p, &2);
79 /// *p = &5;
80 /// }
81 ///
82 /// // The value we put in reappears as the iterator continues.
83 /// assert_eq!(iter.collect::<Vec<_>>(), vec![&5, &3]);
84 /// ```
85 fn peek_mut(&mut self) -> Option<&mut Self::Item>;
86 /// Consume and return the next value of this iterator if a condition is true.
87 ///
88 /// If `func` returns `true` for the next value of this iterator, consume and return it.
89 /// Otherwise, return `None`.
90 ///
91 /// # Examples
92 /// Consume a number if it's equal to 0.
93 /// ```
94 /// let mut iter = (0..5).peekable();
95 /// // The first item of the iterator is 0; consume it.
96 /// assert_eq!(iter.next_if(|&x| x == 0), Some(0));
97 /// // The next item returned is now 1, so `consume` will return `false`.
98 /// assert_eq!(iter.next_if(|&x| x == 0), None);
99 /// // `next_if` saves the value of the next item if it was not equal to `expected`.
100 /// assert_eq!(iter.next(), Some(1));
101 /// ```
102 ///
103 /// Consume any number less than 10.
104 /// ```
105 /// let mut iter = (1..20).peekable();
106 /// // Consume all numbers less than 10
107 /// while iter.next_if(|&x| x < 10).is_some() {}
108 /// // The next value returned will be 10
109 /// assert_eq!(iter.next(), Some(10));
110 /// ```
111 fn next_if(&mut self, func: impl FnOnce(&Self::Item) -> bool) -> Option<Self::Item> {
112 match self.peek() {
113 Some(matched) if func(matched) => Some(self.next()?),
114 _ => None
115 }
116 }
117 /// Consume and return the next item if it is equal to `expected`.
118 ///
119 /// # Example
120 /// Consume a number if it's equal to 0.
121 /// ```
122 /// let mut iter = (0..5).peekable();
123 /// // The first item of the iterator is 0; consume it.
124 /// assert_eq!(iter.next_if_eq(&0), Some(0));
125 /// // The next item returned is now 1, so `consume` will return `false`.
126 /// assert_eq!(iter.next_if_eq(&0), None);
127 /// // `next_if_eq` saves the value of the next item if it was not equal to `expected`.
128 /// assert_eq!(iter.next(), Some(1));
129 /// ```
130 fn next_if_eq<T>(&mut self, expected: &T) -> Option<Self::Item>
131 where
132 T: ?Sized,
133 Self::Item: PartialEq<T>,
134 {
135 self.next_if(|next| next == expected)
136 }
137}
138
139impl<I: Iterator> Peek for Peekable<I> {
140 fn peek(&mut self) -> Option<&Self::Item> {
141 self.peek()
142 }
143
144 fn peek_mut(&mut self) -> Option<&mut Self::Item> {
145 self.peek_mut()
146 }
147
148 fn next_if(&mut self, func: impl FnOnce(&Self::Item) -> bool) -> Option<Self::Item> {
149 self.next_if(func)
150 }
151}