1 use std::iter::Fuse;
2 use std::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<I::Item>83     fn next(&mut self) -> Option<I::Item> {
84         self.index = 0;
85         if self.buf.is_empty() {
86             self.iter.next()
87         } else {
88             self.buf.pop_front()
89         }
90     }
91 
size_hint(&self) -> (usize, Option<usize>)92     fn size_hint(&self) -> (usize, Option<usize>) {
93         size_hint::add_scalar(self.iter.size_hint(), self.buf.len())
94     }
95 }
96 
97 // Same size
98 impl<I> ExactSizeIterator for MultiPeek<I>
99     where I: ExactSizeIterator
100 {}
101 
102 
103