1 
2 use std::iter::Peekable;
3 use PutBack;
4 #[cfg(feature = "use_std")]
5 use PutBackN;
6 
7 /// An iterator that allows peeking at an element before deciding to accept it.
8 ///
9 /// See [`.peeking_take_while()`](trait.Itertools.html#method.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 F: FnOnce(&Self::Item) -> bool19     fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
20         where F: FnOnce(&Self::Item) -> bool;
21 }
22 
23 impl<I> PeekingNext for Peekable<I>
24     where I: Iterator,
25 {
peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> where F: FnOnce(&Self::Item) -> bool26     fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
27         where F: FnOnce(&Self::Item) -> bool
28     {
29         if let Some(r) = self.peek() {
30             if !accept(r) {
31                 return None;
32             }
33         }
34         self.next()
35     }
36 }
37 
38 impl<I> PeekingNext for PutBack<I>
39     where I: Iterator,
40 {
peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> where F: FnOnce(&Self::Item) -> bool41     fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
42         where F: FnOnce(&Self::Item) -> bool
43     {
44         if let Some(r) = self.next() {
45             if !accept(&r) {
46                 self.put_back(r);
47                 return None;
48             }
49             Some(r)
50         } else {
51             None
52         }
53     }
54 }
55 
56 #[cfg(feature = "use_std")]
57 impl<I> PeekingNext for PutBackN<I>
58     where I: Iterator,
59 {
peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> where F: FnOnce(&Self::Item) -> bool60     fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
61         where F: FnOnce(&Self::Item) -> bool
62     {
63         if let Some(r) = self.next() {
64             if !accept(&r) {
65                 self.put_back(r);
66                 return None;
67             }
68             Some(r)
69         } else {
70             None
71         }
72     }
73 }
74 
75 /// An iterator adaptor that takes items while a closure returns `true`.
76 ///
77 /// See [`.peeking_take_while()`](../trait.Itertools.html#method.peeking_take_while)
78 /// for more information.
79 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
80 pub struct PeekingTakeWhile<'a, I: 'a, F>
81     where I: Iterator,
82 {
83     iter: &'a mut I,
84     f: F,
85 }
86 
87 /// Create a PeekingTakeWhile
peeking_take_while<I, F>(iter: &mut I, f: F) -> PeekingTakeWhile<I, F> where I: Iterator,88 pub fn peeking_take_while<I, F>(iter: &mut I, f: F) -> PeekingTakeWhile<I, F>
89     where I: Iterator,
90 {
91     PeekingTakeWhile {
92         iter: iter,
93         f: f,
94     }
95 }
96 
97 impl<'a, I, F> Iterator for PeekingTakeWhile<'a, I, F>
98     where I: PeekingNext,
99           F: FnMut(&I::Item) -> bool,
100 
101 {
102     type Item = I::Item;
next(&mut self) -> Option<Self::Item>103     fn next(&mut self) -> Option<Self::Item> {
104         self.iter.peeking_next(&mut self.f)
105     }
106 
size_hint(&self) -> (usize, Option<usize>)107     fn size_hint(&self) -> (usize, Option<usize>) {
108         let (_, hi) = self.iter.size_hint();
109         (0, hi)
110     }
111 }
112 
113 // Some iterators are so lightweight we can simply clone them to save their
114 // state and use that for peeking.
115 macro_rules! peeking_next_by_clone {
116     ([$($typarm:tt)*] $type_:ty) => {
117         impl<$($typarm)*> PeekingNext for $type_ {
118             fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
119                 where F: FnOnce(&Self::Item) -> bool
120             {
121                 let saved_state = self.clone();
122                 if let Some(r) = self.next() {
123                     if !accept(&r) {
124                         *self = saved_state;
125                     } else {
126                         return Some(r)
127                     }
128                 }
129                 None
130             }
131         }
132     }
133 }
134 
135 peeking_next_by_clone! { ['a, T] ::std::slice::Iter<'a, T> }
136 peeking_next_by_clone! { ['a] ::std::str::Chars<'a> }
137 peeking_next_by_clone! { ['a] ::std::str::CharIndices<'a> }
138 peeking_next_by_clone! { ['a] ::std::str::Bytes<'a> }
139 peeking_next_by_clone! { ['a, T] ::std::option::Iter<'a, T> }
140 peeking_next_by_clone! { ['a, T] ::std::result::Iter<'a, T> }
141 peeking_next_by_clone! { [T] ::std::iter::Empty<T> }
142 #[cfg(feature = "use_std")]
143 peeking_next_by_clone! { ['a, T] ::std::collections::linked_list::Iter<'a, T> }
144 #[cfg(feature = "use_std")]
145 peeking_next_by_clone! { ['a, T] ::std::collections::vec_deque::Iter<'a, T> }
146 
147 // cloning a Rev has no extra overhead; peekable and put backs are never DEI.
148 peeking_next_by_clone! { [I: Clone + PeekingNext + DoubleEndedIterator]
149                          ::std::iter::Rev<I> }
150