]> git.proxmox.com Git - rustc.git/blame - vendor/itertools-0.8.2/src/peeking_take_while.rs
Update upstream source from tag 'upstream/1.52.1+dfsg1'
[rustc.git] / vendor / itertools-0.8.2 / src / peeking_take_while.rs
CommitLineData
f20569fa
XL
1
2use std::iter::Peekable;
3use PutBack;
4#[cfg(feature = "use_std")]
5use 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`).
15pub 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.
19 fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
20 where F: FnOnce(&Self::Item) -> bool;
21}
22
23impl<I> PeekingNext for Peekable<I>
24 where I: Iterator,
25{
26 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
38impl<I> PeekingNext for PutBack<I>
39 where I: Iterator,
40{
41 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")]
57impl<I> PeekingNext for PutBackN<I>
58 where I: Iterator,
59{
60 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"]
80pub 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
88pub 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
97impl<'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;
103 fn next(&mut self) -> Option<Self::Item> {
104 self.iter.peeking_next(&mut self.f)
105 }
106
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.
115macro_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
135peeking_next_by_clone! { ['a, T] ::std::slice::Iter<'a, T> }
136peeking_next_by_clone! { ['a] ::std::str::Chars<'a> }
137peeking_next_by_clone! { ['a] ::std::str::CharIndices<'a> }
138peeking_next_by_clone! { ['a] ::std::str::Bytes<'a> }
139peeking_next_by_clone! { ['a, T] ::std::option::Iter<'a, T> }
140peeking_next_by_clone! { ['a, T] ::std::result::Iter<'a, T> }
141peeking_next_by_clone! { [T] ::std::iter::Empty<T> }
142#[cfg(feature = "use_std")]
143peeking_next_by_clone! { ['a, T] ::std::collections::linked_list::Iter<'a, T> }
144#[cfg(feature = "use_std")]
145peeking_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.
148peeking_next_by_clone! { [I: Clone + PeekingNext + DoubleEndedIterator]
149 ::std::iter::Rev<I> }