peeking_iter/
peeking.rs

1//! Main iterator type and traits that enable peeking.
2
3/// Iterator adapter that enables infinitely-deep peeking.
4///
5/// First call to [`peek()`] returns the next element, further calls
6/// return further elements without advancing the inner iterator.
7///
8/// The inner iterator is required to implement [`Clone`].
9///
10/// Also see [`Peeking`] for more detailed documentation of most methods.
11///
12/// # Performance
13/// If you don't call [`peek()`] at all, this is just as performant as the
14/// original iterator.
15///
16/// When using [`peek()`], this adapter is ~1.5x faster than
17/// [`itertools::MultiPeek`] (see `/benches/bench.rs`).
18///
19/// All operations are `O(1)`, unless they specifically iterate over multiple
20/// elements (e.g. [`peek_nth()`], [`next_while()`], etc.)
21///
22/// [`peek()`]: PeekingIter::peek()
23/// [`peek_nth()`]: PeekingIter::peek_nth()
24/// [`next_while()`]: PeekingIter::next_while()
25/// [`itertools::MultiPeek`]:
26/// https://docs.rs/itertools/latest/itertools/structs/struct.MultiPeek.html
27pub struct PeekingIter<I> {
28    iter: I,
29    peeking: Option<I>,
30}
31
32/// Enables peeking functionality.
33///
34/// Requires the type to implement [`Iterator`] as well as `peek()`,
35/// `advance_to_peeked()`, and `rewind_peeking()`.
36///
37/// Implemented by default on [`PeekingIter`] and [`Parser`](crate::Parser).
38pub trait Peeking: Iterator {
39    /// Peeks the next item in the iterator.
40    ///
41    /// Subsequent calls return subsequent items.
42    ///
43    /// ```rust
44    /// # use peeking_iter::peeking::{PeekingIter, Peeking};
45    /// let mut it = PeekingIter::new(0..=2);
46    ///
47    /// assert_eq!(it.next(), Some(0));
48    /// assert_eq!(it.peek(), Some(1));
49    /// assert_eq!(it.peek(), Some(2));
50    /// assert_eq!(it.next(), Some(1));
51    /// assert_eq!(it.peek(), Some(2));
52    /// assert_eq!(it.peek(), None);
53    /// ```
54    fn peek(&mut self) -> Option<Self::Item>;
55
56    /// Advances the inner iterator to the be aligned with the peeking one.
57    ///
58    /// ```rust
59    /// # use peeking_iter::peeking::{PeekingIter, Peeking};
60    /// let mut it = PeekingIter::new(0..=2);
61    ///
62    /// assert_eq!(it.peek(), Some(0));
63    /// assert_eq!(it.peek(), Some(1));
64    ///
65    /// it.advance_to_peeked();
66    ///
67    /// assert_eq!(it.next(), Some(2));
68    /// assert_eq!(it.next(), None);
69    /// ```
70    fn advance_to_peeked(&mut self);
71
72    /// Rewind the peeking iterator to align with the inner.
73    ///
74    /// ```rust
75    /// # use peeking_iter::peeking::{PeekingIter, Peeking};
76    /// let mut it = PeekingIter::new(0..=2);
77    ///
78    /// assert_eq!(it.peek(), Some(0));
79    /// assert_eq!(it.peek(), Some(1));
80    ///
81    /// it.rewind_peeking();
82    ///
83    /// assert_eq!(it.peek(), Some(0));
84    /// ```
85    fn rewind_peeking(&mut self);
86
87    /// Peek the `n`th value in the iterator.
88    ///
89    /// ```rust
90    /// # use peeking_iter::peeking::{PeekingIter, Peeking};
91    /// let mut it = PeekingIter::new(0..=2);
92    ///
93    /// assert_eq!(it.peek_nth(2), Some(2));
94    /// assert_eq!(it.next(), Some(0));
95    /// ```
96    fn peek_nth(&mut self, n: usize) -> Option<Self::Item> {
97        for _ in 0..n {
98            self.peek();
99        }
100
101        self.peek()
102    }
103
104    /// Returns a `Vec<T>` containing all continuous elements that satisfy the
105    /// predicate.
106    ///
107    /// ```rust
108    /// # use peeking_iter::peeking::{PeekingIter, Peeking};
109    /// let mut it = PeekingIter::new(0..=3);
110    ///
111    /// assert_eq!(it.next_while(|x| *x < 2), vec![0, 1]);
112    /// assert_eq!(it.peek(), Some(2));
113    /// assert_eq!(it.next(), Some(2));
114    /// ```
115    fn next_while<F: Fn(&Self::Item) -> bool>(&mut self, pred: F) -> Vec<Self::Item> {
116        let mut result = vec![];
117
118        // If `peeking` had already diverged, bring it back
119        self.rewind_peeking();
120
121        loop {
122            match self.peek() {
123                None => break,
124                Some(x) => {
125                    if pred(&x) {
126                        result.push(x);
127                        self.next();
128                    } else {
129                        break;
130                    }
131                }
132            }
133        }
134
135        self.rewind_peeking();
136
137        result
138    }
139
140    /// Like [`next_while()`](Peeking::next_while()), except consumes the first
141    /// element that doesn't suffice (without returning it).
142    ///
143    /// Doesn't [`peek()`](Self::peek()) at all, so it is faster than
144    /// [`next_while()`](Self::next_while()).
145    ///
146    /// ```rust
147    /// # use peeking_iter::peeking::{PeekingIter, Peeking};
148    /// let mut it = PeekingIter::new(0..=3);
149    ///
150    /// assert_eq!(it.next_while1(|x| *x < 2), vec![0, 1]);
151    /// assert_eq!(it.peek(), Some(3));
152    /// assert_eq!(it.next(), Some(3));
153    /// ```
154    /// Note the `Some(3)`, instead of `Some(2)`.
155    fn next_while1<F: Fn(&Self::Item) -> bool>(&mut self, pred: F) -> Vec<Self::Item> {
156        let mut result = vec![];
157
158        loop {
159            match self.next() {
160                None => break,
161                Some(x) => {
162                    if pred(&x) {
163                        result.push(x)
164                    } else {
165                        break;
166                    }
167                }
168            }
169        }
170
171        result
172    }
173}
174
175/// Allows converting any iterator to a peeking one (typically by wrapping around it).
176pub trait ToPeeking
177where
178    Self: Sized,
179{
180    fn to_peeking(self) -> PeekingIter<Self>;
181}
182
183impl<I: Iterator> PeekingIter<I> {
184    /// Wraps the given iterator.
185    pub fn new(iter: I) -> Self {
186        Self {
187            iter,
188            peeking: None,
189        }
190    }
191
192    /// Returns the next item in the iterator.
193    ///
194    /// Resets the peeking iterator.
195    pub fn next(&mut self) -> Option<I::Item> {
196        self.peeking = None;
197
198        self.iter.next()
199    }
200
201    /// Consumes `self` and returns the inner iterator.
202    pub fn into_inner(value: Self) -> I {
203        value.iter
204    }
205}
206
207impl<I: Iterator + Clone> Peeking for PeekingIter<I> {
208    fn peek(&mut self) -> Option<Self::Item> {
209        self.peeking.get_or_insert_with(|| self.iter.clone()).next()
210    }
211
212    fn advance_to_peeked(&mut self) {
213        if let Some(ref peeking) = self.peeking {
214            self.iter = peeking.clone();
215        }
216    }
217
218    fn rewind_peeking(&mut self) {
219        self.peeking = None;
220    }
221
222    // OPTIM?: Potentially more optimal implementation?
223    fn peek_nth(&mut self, n: usize) -> Option<I::Item> {
224        self.peeking
225            .get_or_insert_with(|| self.iter.clone())
226            .skip(n)
227            .next()
228    }
229}
230
231impl<I: Iterator + Clone> Iterator for PeekingIter<I> {
232    type Item = I::Item;
233
234    fn next(&mut self) -> Option<Self::Item> {
235        PeekingIter::next(self)
236    }
237}
238
239impl<I: Iterator + Clone> ToPeeking for I {
240    fn to_peeking(self) -> PeekingIter<Self> {
241        PeekingIter::new(self)
242    }
243}