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}