]>
Commit | Line | Data |
---|---|---|
f20569fa XL |
1 | |
2 | ||
3 | use std::iter::Fuse; | |
4 | use std::collections::VecDeque; | |
5 | use size_hint; | |
6 | use PeekingNext; | |
7 | ||
8 | /// See [`multipeek()`](../fn.multipeek.html) 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 | pub 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 | ||
30 | impl<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 | ||
39 | impl<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 | ||
61 | impl<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 | ||
80 | impl<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 | |
100 | impl<I> ExactSizeIterator for MultiPeek<I> | |
101 | where I: ExactSizeIterator | |
102 | {} | |
103 | ||
104 |