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}