blob: 5917681fca2805df32873bebd9b0b76c416f3d98 [file] [log] [blame]
Jakub Kotura425e552020-12-21 17:28:15 +01001use std::iter::Fuse;
Joel Galenson6f798712021-04-01 17:03:06 -07002use alloc::collections::VecDeque;
Jakub Kotura425e552020-12-21 17:28:15 +01003use crate::size_hint;
4use crate::PeekingNext;
5
Joel Galensonb593e252021-06-21 13:15:57 -07006/// See [`multipeek()`] for more information.
Jakub Kotura425e552020-12-21 17:28:15 +01007#[derive(Clone, Debug)]
8pub 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.
18pub 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
28impl<I> MultiPeek<I>
29 where I: Iterator
30{
31 /// Reset the peeking “cursor”
32 pub fn reset_peek(&mut self) {
33 self.index = 0;
34 }
35}
36
37impl<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.
David LeGareb72e9052022-03-02 16:21:08 +000041 /// When `.next()` is called, reset the peeking “cursor”.
Jakub Kotura425e552020-12-21 17:28:15 +010042 pub fn peek(&mut self) -> Option<&I::Item> {
43 let ret = if self.index < self.buf.len() {
44 Some(&self.buf[self.index])
45 } else {
46 match self.iter.next() {
47 Some(x) => {
48 self.buf.push_back(x);
49 Some(&self.buf[self.index])
50 }
51 None => return None,
52 }
53 };
54
55 self.index += 1;
56 ret
57 }
58}
59
60impl<I> PeekingNext for MultiPeek<I>
61 where I: Iterator,
62{
63 fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
64 where F: FnOnce(&Self::Item) -> bool
65 {
66 if self.buf.is_empty() {
67 if let Some(r) = self.peek() {
68 if !accept(r) { return None }
69 }
70 } else {
71 if let Some(r) = self.buf.get(0) {
72 if !accept(r) { return None }
73 }
74 }
75 self.next()
76 }
77}
78
79impl<I> Iterator for MultiPeek<I>
80 where I: Iterator
81{
82 type Item = I::Item;
83
Joel Galenson6f798712021-04-01 17:03:06 -070084 fn next(&mut self) -> Option<Self::Item> {
Jakub Kotura425e552020-12-21 17:28:15 +010085 self.index = 0;
Joel Galenson6f798712021-04-01 17:03:06 -070086 self.buf.pop_front().or_else(|| self.iter.next())
Jakub Kotura425e552020-12-21 17:28:15 +010087 }
88
89 fn size_hint(&self) -> (usize, Option<usize>) {
90 size_hint::add_scalar(self.iter.size_hint(), self.buf.len())
91 }
92}
93
94// Same size
95impl<I> ExactSizeIterator for MultiPeek<I>
96 where I: ExactSizeIterator
97{}
98
99