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