diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /third_party/rust/itertools/src/multipeek_impl.rs | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/itertools/src/multipeek_impl.rs')
-rw-r--r-- | third_party/rust/itertools/src/multipeek_impl.rs | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/third_party/rust/itertools/src/multipeek_impl.rs b/third_party/rust/itertools/src/multipeek_impl.rs new file mode 100644 index 0000000000..8b49c695eb --- /dev/null +++ b/third_party/rust/itertools/src/multipeek_impl.rs @@ -0,0 +1,101 @@ +use std::iter::Fuse; +use alloc::collections::VecDeque; +use crate::size_hint; +use crate::PeekingNext; +#[cfg(doc)] +use crate::Itertools; + +/// See [`multipeek()`] for more information. +#[derive(Clone, Debug)] +pub struct MultiPeek<I> + where I: Iterator +{ + iter: Fuse<I>, + buf: VecDeque<I::Item>, + index: usize, +} + +/// An iterator adaptor that allows the user to peek at multiple `.next()` +/// values without advancing the base iterator. +/// +/// [`IntoIterator`] enabled version of [`Itertools::multipeek`]. +pub fn multipeek<I>(iterable: I) -> MultiPeek<I::IntoIter> + where I: IntoIterator +{ + MultiPeek { + iter: iterable.into_iter().fuse(), + buf: VecDeque::new(), + index: 0, + } +} + +impl<I> MultiPeek<I> + where I: Iterator +{ + /// Reset the peeking “cursor” + pub fn reset_peek(&mut self) { + self.index = 0; + } +} + +impl<I: Iterator> MultiPeek<I> { + /// Works exactly like `.next()` with the only difference that it doesn't + /// advance itself. `.peek()` can be called multiple times, to peek + /// further ahead. + /// When `.next()` is called, reset the peeking “cursor”. + pub fn peek(&mut self) -> Option<&I::Item> { + let ret = if self.index < self.buf.len() { + Some(&self.buf[self.index]) + } else { + match self.iter.next() { + Some(x) => { + self.buf.push_back(x); + Some(&self.buf[self.index]) + } + None => return None, + } + }; + + self.index += 1; + ret + } +} + +impl<I> PeekingNext for MultiPeek<I> + where I: Iterator, +{ + fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> + where F: FnOnce(&Self::Item) -> bool + { + if self.buf.is_empty() { + if let Some(r) = self.peek() { + if !accept(r) { return None } + } + } else if let Some(r) = self.buf.get(0) { + if !accept(r) { return None } + } + self.next() + } +} + +impl<I> Iterator for MultiPeek<I> + where I: Iterator +{ + type Item = I::Item; + + fn next(&mut self) -> Option<Self::Item> { + self.index = 0; + self.buf.pop_front().or_else(|| self.iter.next()) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + size_hint::add_scalar(self.iter.size_hint(), self.buf.len()) + } +} + +// Same size +impl<I> ExactSizeIterator for MultiPeek<I> + where I: ExactSizeIterator +{} + + |