1 use crate::PutBack;
2 #[cfg(feature = "use_alloc")]
3 use crate::PutBackN;
4 use crate::RepeatN;
5 use std::iter::Peekable;
6 
7 /// An iterator that allows peeking at an element before deciding to accept it.
8 ///
9 /// See [`.peeking_take_while()`](crate::Itertools::peeking_take_while)
10 /// for more information.
11 ///
12 /// This is implemented by peeking adaptors like peekable and put back,
13 /// but also by a few iterators that can be peeked natively, like the slice’s
14 /// by reference iterator ([`std::slice::Iter`]).
15 pub trait PeekingNext: Iterator {
16     /// Pass a reference to the next iterator element to the closure `accept`;
17     /// if `accept` returns `true`, return it as the next element,
18     /// else `None`.
peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> where Self: Sized, F: FnOnce(&Self::Item) -> bool19     fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
20     where
21         Self: Sized,
22         F: FnOnce(&Self::Item) -> bool;
23 }
24 
25 impl<'a, I> PeekingNext for &'a mut I
26 where
27     I: PeekingNext,
28 {
peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> where F: FnOnce(&Self::Item) -> bool,29     fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
30     where
31         F: FnOnce(&Self::Item) -> bool,
32     {
33         (*self).peeking_next(accept)
34     }
35 }
36 
37 impl<I> PeekingNext for Peekable<I>
38 where
39     I: Iterator,
40 {
peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> where F: FnOnce(&Self::Item) -> bool,41     fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
42     where
43         F: FnOnce(&Self::Item) -> bool,
44     {
45         if let Some(r) = self.peek() {
46             if !accept(r) {
47                 return None;
48             }
49         }
50         self.next()
51     }
52 }
53 
54 impl<I> PeekingNext for PutBack<I>
55 where
56     I: Iterator,
57 {
peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> where F: FnOnce(&Self::Item) -> bool,58     fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
59     where
60         F: FnOnce(&Self::Item) -> bool,
61     {
62         if let Some(r) = self.next() {
63             if !accept(&r) {
64                 self.put_back(r);
65                 return None;
66             }
67             Some(r)
68         } else {
69             None
70         }
71     }
72 }
73 
74 #[cfg(feature = "use_alloc")]
75 impl<I> PeekingNext for PutBackN<I>
76 where
77     I: Iterator,
78 {
peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> where F: FnOnce(&Self::Item) -> bool,79     fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
80     where
81         F: FnOnce(&Self::Item) -> bool,
82     {
83         if let Some(r) = self.next() {
84             if !accept(&r) {
85                 self.put_back(r);
86                 return None;
87             }
88             Some(r)
89         } else {
90             None
91         }
92     }
93 }
94 
95 impl<T: Clone> PeekingNext for RepeatN<T> {
peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> where F: FnOnce(&Self::Item) -> bool,96     fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
97     where
98         F: FnOnce(&Self::Item) -> bool,
99     {
100         let r = self.elt.as_ref()?;
101         if !accept(r) {
102             return None;
103         }
104         self.next()
105     }
106 }
107 
108 /// An iterator adaptor that takes items while a closure returns `true`.
109 ///
110 /// See [`.peeking_take_while()`](crate::Itertools::peeking_take_while)
111 /// for more information.
112 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
113 pub struct PeekingTakeWhile<'a, I, F>
114 where
115     I: Iterator + 'a,
116 {
117     iter: &'a mut I,
118     f: F,
119 }
120 
121 impl<'a, I, F> std::fmt::Debug for PeekingTakeWhile<'a, I, F>
122 where
123     I: Iterator + std::fmt::Debug + 'a,
124 {
125     debug_fmt_fields!(PeekingTakeWhile, iter);
126 }
127 
128 /// Create a `PeekingTakeWhile`
peeking_take_while<I, F>(iter: &mut I, f: F) -> PeekingTakeWhile<I, F> where I: Iterator,129 pub fn peeking_take_while<I, F>(iter: &mut I, f: F) -> PeekingTakeWhile<I, F>
130 where
131     I: Iterator,
132 {
133     PeekingTakeWhile { iter, f }
134 }
135 
136 impl<'a, I, F> Iterator for PeekingTakeWhile<'a, I, F>
137 where
138     I: PeekingNext,
139     F: FnMut(&I::Item) -> bool,
140 {
141     type Item = I::Item;
next(&mut self) -> Option<Self::Item>142     fn next(&mut self) -> Option<Self::Item> {
143         self.iter.peeking_next(&mut self.f)
144     }
145 
size_hint(&self) -> (usize, Option<usize>)146     fn size_hint(&self) -> (usize, Option<usize>) {
147         (0, self.iter.size_hint().1)
148     }
149 }
150 
151 impl<'a, I, F> PeekingNext for PeekingTakeWhile<'a, I, F>
152 where
153     I: PeekingNext,
154     F: FnMut(&I::Item) -> bool,
155 {
peeking_next<G>(&mut self, g: G) -> Option<Self::Item> where G: FnOnce(&Self::Item) -> bool,156     fn peeking_next<G>(&mut self, g: G) -> Option<Self::Item>
157     where
158         G: FnOnce(&Self::Item) -> bool,
159     {
160         let f = &mut self.f;
161         self.iter.peeking_next(|r| f(r) && g(r))
162     }
163 }
164 
165 // Some iterators are so lightweight we can simply clone them to save their
166 // state and use that for peeking.
167 macro_rules! peeking_next_by_clone {
168     ([$($typarm:tt)*] $type_:ty) => {
169         impl<$($typarm)*> PeekingNext for $type_ {
170             fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
171                 where F: FnOnce(&Self::Item) -> bool
172             {
173                 let saved_state = self.clone();
174                 if let Some(r) = self.next() {
175                     if !accept(&r) {
176                         *self = saved_state;
177                     } else {
178                         return Some(r)
179                     }
180                 }
181                 None
182             }
183         }
184     }
185 }
186 
187 peeking_next_by_clone! { ['a, T] ::std::slice::Iter<'a, T> }
188 peeking_next_by_clone! { ['a] ::std::str::Chars<'a> }
189 peeking_next_by_clone! { ['a] ::std::str::CharIndices<'a> }
190 peeking_next_by_clone! { ['a] ::std::str::Bytes<'a> }
191 peeking_next_by_clone! { ['a, T] ::std::option::Iter<'a, T> }
192 peeking_next_by_clone! { ['a, T] ::std::result::Iter<'a, T> }
193 peeking_next_by_clone! { [T] ::std::iter::Empty<T> }
194 #[cfg(feature = "use_alloc")]
195 peeking_next_by_clone! { ['a, T] alloc::collections::linked_list::Iter<'a, T> }
196 #[cfg(feature = "use_alloc")]
197 peeking_next_by_clone! { ['a, T] alloc::collections::vec_deque::Iter<'a, T> }
198 
199 // cloning a Rev has no extra overhead; peekable and put backs are never DEI.
200 peeking_next_by_clone! { [I: Clone + PeekingNext + DoubleEndedIterator]
201 ::std::iter::Rev<I> }
202