itertools/
multipeek_impl.rs1use crate::size_hint;
2#[cfg(doc)]
3use crate::Itertools;
4use crate::PeekingNext;
5use alloc::collections::VecDeque;
6use std::iter::Fuse;
7
8#[derive(Clone, Debug)]
10#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
11pub struct MultiPeek<I>
12where
13    I: Iterator,
14{
15    iter: Fuse<I>,
16    buf: VecDeque<I::Item>,
17    index: usize,
18}
19
20pub fn multipeek<I>(iterable: I) -> MultiPeek<I::IntoIter>
25where
26    I: IntoIterator,
27{
28    MultiPeek {
29        iter: iterable.into_iter().fuse(),
30        buf: VecDeque::new(),
31        index: 0,
32    }
33}
34
35impl<I> MultiPeek<I>
36where
37    I: Iterator,
38{
39    pub fn reset_peek(&mut self) {
41        self.index = 0;
42    }
43}
44
45impl<I: Iterator> MultiPeek<I> {
46    pub fn peek(&mut self) -> Option<&I::Item> {
51        let ret = if self.index < self.buf.len() {
52            Some(&self.buf[self.index])
53        } else {
54            match self.iter.next() {
55                Some(x) => {
56                    self.buf.push_back(x);
57                    Some(&self.buf[self.index])
58                }
59                None => return None,
60            }
61        };
62
63        self.index += 1;
64        ret
65    }
66}
67
68impl<I> PeekingNext for MultiPeek<I>
69where
70    I: Iterator,
71{
72    fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
73    where
74        F: FnOnce(&Self::Item) -> bool,
75    {
76        if self.buf.is_empty() {
77            if let Some(r) = self.peek() {
78                if !accept(r) {
79                    return None;
80                }
81            }
82        } else if let Some(r) = self.buf.front() {
83            if !accept(r) {
84                return None;
85            }
86        }
87        self.next()
88    }
89}
90
91impl<I> Iterator for MultiPeek<I>
92where
93    I: Iterator,
94{
95    type Item = I::Item;
96
97    fn next(&mut self) -> Option<Self::Item> {
98        self.index = 0;
99        self.buf.pop_front().or_else(|| self.iter.next())
100    }
101
102    fn size_hint(&self) -> (usize, Option<usize>) {
103        size_hint::add_scalar(self.iter.size_hint(), self.buf.len())
104    }
105
106    fn fold<B, F>(self, mut init: B, mut f: F) -> B
107    where
108        F: FnMut(B, Self::Item) -> B,
109    {
110        init = self.buf.into_iter().fold(init, &mut f);
111        self.iter.fold(init, f)
112    }
113}
114
115impl<I> ExactSizeIterator for MultiPeek<I> where I: ExactSizeIterator {}