1 use std::iter::Peekable;
2 use crate::PutBack;
3 #[cfg(feature = "use_alloc")]
4 use crate::PutBackN;
5 
6 /// An iterator that allows peeking at an element before deciding to accept it.
7 ///
8 /// See [`.peeking_take_while()`](crate::Itertools::peeking_take_while)
9 /// for more information.
10 ///
11 /// This is implemented by peeking adaptors like peekable and put back,
12 /// but also by a few iterators that can be peeked natively, like the slice’s
13 /// by reference iterator (`std::slice::Iter`).
14 pub trait PeekingNext : Iterator {
15     /// Pass a reference to the next iterator element to the closure `accept`;
16     /// if `accept` returns true, return it as the next element,
17     /// else None.
peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> where F: FnOnce(&Self::Item) -> bool18     fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
19         where F: FnOnce(&Self::Item) -> bool;
20 }
21 
22 impl<I> PeekingNext for Peekable<I>
23     where I: Iterator,
24 {
peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> where F: FnOnce(&Self::Item) -> bool25     fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
26         where F: FnOnce(&Self::Item) -> bool
27     {
28         if let Some(r) = self.peek() {
29             if !accept(r) {
30                 return None;
31             }
32         }
33         self.next()
34     }
35 }
36 
37 impl<I> PeekingNext for PutBack<I>
38     where I: Iterator,
39 {
peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> where F: FnOnce(&Self::Item) -> bool40     fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
41         where F: FnOnce(&Self::Item) -> bool
42     {
43         if let Some(r) = self.next() {
44             if !accept(&r) {
45                 self.put_back(r);
46                 return None;
47             }
48             Some(r)
49         } else {
50             None
51         }
52     }
53 }
54 
55 #[cfg(feature = "use_alloc")]
56 impl<I> PeekingNext for PutBackN<I>
57     where I: Iterator,
58 {
peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> where F: FnOnce(&Self::Item) -> bool59     fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
60         where 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 /// An iterator adaptor that takes items while a closure returns `true`.
75 ///
76 /// See [`.peeking_take_while()`](crate::Itertools::peeking_take_while)
77 /// for more information.
78 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
79 pub struct PeekingTakeWhile<'a, I: 'a, F>
80     where I: Iterator,
81 {
82     iter: &'a mut I,
83     f: F,
84 }
85 
86 impl<'a, I: 'a, F> std::fmt::Debug for PeekingTakeWhile<'a, I, F>
87 where
88     I: Iterator + std::fmt::Debug,
89 {
90     debug_fmt_fields!(PeekingTakeWhile, iter);
91 }
92 
93 /// Create a PeekingTakeWhile
peeking_take_while<I, F>(iter: &mut I, f: F) -> PeekingTakeWhile<I, F> where I: Iterator,94 pub fn peeking_take_while<I, F>(iter: &mut I, f: F) -> PeekingTakeWhile<I, F>
95     where I: Iterator,
96 {
97     PeekingTakeWhile {
98         iter,
99         f,
100     }
101 }
102 
103 impl<'a, I, F> Iterator for PeekingTakeWhile<'a, I, F>
104     where I: PeekingNext,
105           F: FnMut(&I::Item) -> bool,
106 
107 {
108     type Item = I::Item;
next(&mut self) -> Option<Self::Item>109     fn next(&mut self) -> Option<Self::Item> {
110         self.iter.peeking_next(&mut self.f)
111     }
112 
size_hint(&self) -> (usize, Option<usize>)113     fn size_hint(&self) -> (usize, Option<usize>) {
114         (0, self.iter.size_hint().1)
115     }
116 }
117 
118 // Some iterators are so lightweight we can simply clone them to save their
119 // state and use that for peeking.
120 macro_rules! peeking_next_by_clone {
121     ([$($typarm:tt)*] $type_:ty) => {
122         impl<$($typarm)*> PeekingNext for $type_ {
123             fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
124                 where F: FnOnce(&Self::Item) -> bool
125             {
126                 let saved_state = self.clone();
127                 if let Some(r) = self.next() {
128                     if !accept(&r) {
129                         *self = saved_state;
130                     } else {
131                         return Some(r)
132                     }
133                 }
134                 None
135             }
136         }
137     }
138 }
139 
140 peeking_next_by_clone! { ['a, T] ::std::slice::Iter<'a, T> }
141 peeking_next_by_clone! { ['a] ::std::str::Chars<'a> }
142 peeking_next_by_clone! { ['a] ::std::str::CharIndices<'a> }
143 peeking_next_by_clone! { ['a] ::std::str::Bytes<'a> }
144 peeking_next_by_clone! { ['a, T] ::std::option::Iter<'a, T> }
145 peeking_next_by_clone! { ['a, T] ::std::result::Iter<'a, T> }
146 peeking_next_by_clone! { [T] ::std::iter::Empty<T> }
147 #[cfg(feature = "use_alloc")]
148 peeking_next_by_clone! { ['a, T] alloc::collections::linked_list::Iter<'a, T> }
149 #[cfg(feature = "use_alloc")]
150 peeking_next_by_clone! { ['a, T] alloc::collections::vec_deque::Iter<'a, T> }
151 
152 // cloning a Rev has no extra overhead; peekable and put backs are never DEI.
153 peeking_next_by_clone! { [I: Clone + PeekingNext + DoubleEndedIterator]
154                          ::std::iter::Rev<I> }
155