1use crate::PutBack;
2#[cfg(feature = "use_alloc")]
3use crate::PutBackN;
4use crate::RepeatN;
5use std::iter::Peekable;
6
7pub trait PeekingNext: Iterator {
16 fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
20 where
21 Self: Sized,
22 F: FnOnce(&Self::Item) -> bool;
23}
24
25impl<I> PeekingNext for &mut I
26where
27 I: PeekingNext,
28{
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
37impl<I> PeekingNext for Peekable<I>
38where
39 I: Iterator,
40{
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
54impl<I> PeekingNext for PutBack<I>
55where
56 I: Iterator,
57{
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")]
75impl<I> PeekingNext for PutBackN<I>
76where
77 I: Iterator,
78{
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#[cfg(feature = "use_alloc")]
96impl<T> PeekingNext for ::alloc::vec::IntoIter<T> {
97 fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
98 where
99 F: FnOnce(&Self::Item) -> bool,
100 {
101 match accept(self.as_slice().first()?) {
102 true => self.next(),
103 false => None,
104 }
105 }
106}
107
108#[cfg(feature = "use_alloc")]
109impl<'a, T> PeekingNext for ::alloc::vec::Drain<'a, T> {
110 fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
111 where
112 F: FnOnce(&Self::Item) -> bool,
113 {
114 match accept(self.as_slice().first()?) {
115 true => self.next(),
116 false => None,
117 }
118 }
119}
120
121#[cfg(feature = "use_alloc")]
122impl<'a> PeekingNext for ::alloc::string::Drain<'a> {
123 fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
124 where
125 F: FnOnce(&Self::Item) -> bool,
126 {
127 match accept(&self.as_str().chars().next()?) {
128 true => self.next(),
129 false => None,
130 }
131 }
132}
133
134impl<T, const N: usize> PeekingNext for ::core::array::IntoIter<T, N> {
135 fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
136 where
137 F: FnOnce(&Self::Item) -> bool,
138 {
139 match accept(self.as_slice().first()?) {
140 true => self.next(),
141 false => None,
142 }
143 }
144}
145
146impl<T: Clone> PeekingNext for RepeatN<T> {
147 fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
148 where
149 F: FnOnce(&Self::Item) -> bool,
150 {
151 let r = self.elt.as_ref()?;
152 if !accept(r) {
153 return None;
154 }
155 self.next()
156 }
157}
158
159#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
164pub struct PeekingTakeWhile<'a, I, F>
165where
166 I: Iterator + 'a,
167{
168 iter: &'a mut I,
169 f: F,
170}
171
172impl<'a, I, F> std::fmt::Debug for PeekingTakeWhile<'a, I, F>
173where
174 I: Iterator + std::fmt::Debug + 'a,
175{
176 debug_fmt_fields!(PeekingTakeWhile, iter);
177}
178
179pub fn peeking_take_while<I, F>(iter: &mut I, f: F) -> PeekingTakeWhile<'_, I, F>
181where
182 I: Iterator,
183{
184 PeekingTakeWhile { iter, f }
185}
186
187impl<I, F> Iterator for PeekingTakeWhile<'_, I, F>
188where
189 I: PeekingNext,
190 F: FnMut(&I::Item) -> bool,
191{
192 type Item = I::Item;
193 fn next(&mut self) -> Option<Self::Item> {
194 self.iter.peeking_next(&mut self.f)
195 }
196
197 fn size_hint(&self) -> (usize, Option<usize>) {
198 (0, self.iter.size_hint().1)
199 }
200}
201
202impl<I, F> PeekingNext for PeekingTakeWhile<'_, I, F>
203where
204 I: PeekingNext,
205 F: FnMut(&I::Item) -> bool,
206{
207 fn peeking_next<G>(&mut self, g: G) -> Option<Self::Item>
208 where
209 G: FnOnce(&Self::Item) -> bool,
210 {
211 let f = &mut self.f;
212 self.iter.peeking_next(|r| f(r) && g(r))
213 }
214}
215
216macro_rules! peeking_next_by_clone {
219 ([$($typarm:tt)*] $type_:ty) => {
220 impl<$($typarm)*> PeekingNext for $type_ {
221 fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
222 where F: FnOnce(&Self::Item) -> bool
223 {
224 let saved_state = self.clone();
225 if let Some(r) = self.next() {
226 if !accept(&r) {
227 *self = saved_state;
228 } else {
229 return Some(r)
230 }
231 }
232 None
233 }
234 }
235 }
236}
237
238peeking_next_by_clone! { ['a, T] ::std::slice::Iter<'a, T> }
239peeking_next_by_clone! { ['a] ::std::str::Chars<'a> }
240peeking_next_by_clone! { ['a] ::std::str::CharIndices<'a> }
241peeking_next_by_clone! { ['a] ::std::str::Bytes<'a> }
242peeking_next_by_clone! { ['a, T] ::std::option::Iter<'a, T> }
243peeking_next_by_clone! { ['a, T] ::std::result::Iter<'a, T> }
244peeking_next_by_clone! { [T] ::std::iter::Empty<T> }
245
246#[cfg(feature = "use_alloc")]
247peeking_next_by_clone! { ['a, T] alloc::collections::linked_list::Iter<'a, T> }
248#[cfg(feature = "use_alloc")]
249peeking_next_by_clone! { ['a, T] alloc::collections::vec_deque::Iter<'a, T> }
250
251#[cfg(feature = "use_alloc")]
252peeking_next_by_clone! { ['a, K, V] alloc::collections::btree_map::Iter<'a, K, V> }
253#[cfg(feature = "use_alloc")]
254peeking_next_by_clone! { ['a, K, V] alloc::collections::btree_map::Keys<'a, K, V> }
255#[cfg(feature = "use_alloc")]
256peeking_next_by_clone! { ['a, K, V] alloc::collections::btree_map::Values<'a, K, V> }
257
258#[cfg(feature = "use_alloc")]
259peeking_next_by_clone! { ['a, T] alloc::collections::btree_set::Iter<'a, T> }
260#[cfg(feature = "use_alloc")]
261peeking_next_by_clone! { ['a, T] alloc::collections::binary_heap::Iter<'a, T> }
262
263#[cfg(feature = "use_std")]
264peeking_next_by_clone! { ['a, K, V] std::collections::hash_map::Iter<'a, K, V> }
265#[cfg(feature = "use_std")]
266peeking_next_by_clone! { ['a, K, V] std::collections::hash_map::Keys<'a, K, V> }
267#[cfg(feature = "use_std")]
268peeking_next_by_clone! { ['a, K, V] std::collections::hash_map::Values<'a, K, V> }
269#[cfg(feature = "use_std")]
270peeking_next_by_clone! { ['a, T] std::collections::hash_set::Iter<'a, T> }
271
272peeking_next_by_clone! { [I: Clone + PeekingNext + DoubleEndedIterator]
274::std::iter::Rev<I> }