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