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 /// Create a PeekingTakeWhile
peeking_take_while<I, F>(iter: &mut I, f: F) -> PeekingTakeWhile<I, F> where I: Iterator,87 pub fn peeking_take_while<I, F>(iter: &mut I, f: F) -> PeekingTakeWhile<I, F>
88     where I: Iterator,
89 {
90     PeekingTakeWhile {
91         iter,
92         f,
93     }
94 }
95 
96 impl<'a, I, F> Iterator for PeekingTakeWhile<'a, I, F>
97     where I: PeekingNext,
98           F: FnMut(&I::Item) -> bool,
99 
100 {
101     type Item = I::Item;
next(&mut self) -> Option<Self::Item>102     fn next(&mut self) -> Option<Self::Item> {
103         self.iter.peeking_next(&mut self.f)
104     }
105 
size_hint(&self) -> (usize, Option<usize>)106     fn size_hint(&self) -> (usize, Option<usize>) {
107         (0, self.iter.size_hint().1)
108     }
109 }
110 
111 // Some iterators are so lightweight we can simply clone them to save their
112 // state and use that for peeking.
113 macro_rules! peeking_next_by_clone {
114     ([$($typarm:tt)*] $type_:ty) => {
115         impl<$($typarm)*> PeekingNext for $type_ {
116             fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
117                 where F: FnOnce(&Self::Item) -> bool
118             {
119                 let saved_state = self.clone();
120                 if let Some(r) = self.next() {
121                     if !accept(&r) {
122                         *self = saved_state;
123                     } else {
124                         return Some(r)
125                     }
126                 }
127                 None
128             }
129         }
130     }
131 }
132 
133 peeking_next_by_clone! { ['a, T] ::std::slice::Iter<'a, T> }
134 peeking_next_by_clone! { ['a] ::std::str::Chars<'a> }
135 peeking_next_by_clone! { ['a] ::std::str::CharIndices<'a> }
136 peeking_next_by_clone! { ['a] ::std::str::Bytes<'a> }
137 peeking_next_by_clone! { ['a, T] ::std::option::Iter<'a, T> }
138 peeking_next_by_clone! { ['a, T] ::std::result::Iter<'a, T> }
139 peeking_next_by_clone! { [T] ::std::iter::Empty<T> }
140 #[cfg(feature = "use_alloc")]
141 peeking_next_by_clone! { ['a, T] alloc::collections::linked_list::Iter<'a, T> }
142 #[cfg(feature = "use_alloc")]
143 peeking_next_by_clone! { ['a, T] alloc::collections::vec_deque::Iter<'a, T> }
144 
145 // cloning a Rev has no extra overhead; peekable and put backs are never DEI.
146 peeking_next_by_clone! { [I: Clone + PeekingNext + DoubleEndedIterator]
147                          ::std::iter::Rev<I> }
148