itertools/
multipeek_impl.rs

1
2
3use std::iter::Fuse;
4use std::collections::VecDeque;
5use size_hint;
6use PeekingNext;
7
8/// See [`multipeek()`](../fn.multipeek.html) for more information.
9#[derive(Clone, Debug)]
10pub 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.
20pub 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
30impl<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
39impl<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
61impl<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
80impl<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
100impl<I> ExactSizeIterator for MultiPeek<I>
101    where I: ExactSizeIterator
102{}
103
104