]> git.proxmox.com Git - rustc.git/blob - vendor/itertools-0.7.8/src/multipeek_impl.rs
New upstream version 1.41.1+dfsg1
[rustc.git] / vendor / itertools-0.7.8 / src / multipeek_impl.rs
1
2
3 use std::iter::Fuse;
4 use std::collections::VecDeque;
5 use size_hint;
6 use PeekingNext;
7
8 /// See [`multipeek()`](../fn.multipeek.html) for more information.
9 #[derive(Clone, Debug)]
10 pub struct MultiPeek<I>
11 where I: Iterator
12 {
13 iter: Fuse<I>,
14 buf: VecDeque<I::Item>,
15 index: usize,
16 }
17
18 /// An iterator adaptor that allows the user to peek at multiple `.next()`
19 /// values without advancing the base iterator.
20 pub fn multipeek<I>(iterable: I) -> MultiPeek<I::IntoIter>
21 where I: IntoIterator
22 {
23 MultiPeek {
24 iter: iterable.into_iter().fuse(),
25 buf: VecDeque::new(),
26 index: 0,
27 }
28 }
29
30 impl<I> MultiPeek<I>
31 where I: Iterator
32 {
33 /// Reset the peeking “cursor”
34 pub fn reset_peek(&mut self) {
35 self.index = 0;
36 }
37 }
38
39 impl<I: Iterator> MultiPeek<I> {
40 /// Works exactly like `.next()` with the only difference that it doesn't
41 /// advance itself. `.peek()` can be called multiple times, to peek
42 /// further ahead.
43 pub fn peek(&mut self) -> Option<&I::Item> {
44 let ret = if self.index < self.buf.len() {
45 Some(&self.buf[self.index])
46 } else {
47 match self.iter.next() {
48 Some(x) => {
49 self.buf.push_back(x);
50 Some(&self.buf[self.index])
51 }
52 None => return None,
53 }
54 };
55
56 self.index += 1;
57 ret
58 }
59 }
60
61 impl<I> PeekingNext for MultiPeek<I>
62 where I: Iterator,
63 {
64 fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
65 where F: FnOnce(&Self::Item) -> bool
66 {
67 if self.buf.is_empty() {
68 if let Some(r) = self.peek() {
69 if !accept(r) { return None }
70 }
71 } else {
72 if let Some(r) = self.buf.get(0) {
73 if !accept(r) { return None }
74 }
75 }
76 self.next()
77 }
78 }
79
80 impl<I> Iterator for MultiPeek<I>
81 where I: Iterator
82 {
83 type Item = I::Item;
84
85 fn next(&mut self) -> Option<I::Item> {
86 self.index = 0;
87 if self.buf.is_empty() {
88 self.iter.next()
89 } else {
90 self.buf.pop_front()
91 }
92 }
93
94 fn size_hint(&self) -> (usize, Option<usize>) {
95 size_hint::add_scalar(self.iter.size_hint(), self.buf.len())
96 }
97 }
98
99 // Same size
100 impl<I> ExactSizeIterator for MultiPeek<I>
101 where I: ExactSizeIterator
102 {}
103
104