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