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