diff options
Diffstat (limited to 'vendor/itertools/src/with_position.rs')
-rw-r--r-- | vendor/itertools/src/with_position.rs | 49 |
1 files changed, 38 insertions, 11 deletions
diff --git a/vendor/itertools/src/with_position.rs b/vendor/itertools/src/with_position.rs index dda9b25dc..89cddeb8a 100644 --- a/vendor/itertools/src/with_position.rs +++ b/vendor/itertools/src/with_position.rs @@ -1,4 +1,4 @@ -use std::iter::{Fuse,Peekable, FusedIterator}; +use std::iter::{Fuse, FusedIterator, Peekable}; /// An iterator adaptor that wraps each element in an [`Position`]. /// @@ -7,22 +7,25 @@ use std::iter::{Fuse,Peekable, FusedIterator}; /// See [`.with_position()`](crate::Itertools::with_position) for more information. #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pub struct WithPosition<I> - where I: Iterator, +where + I: Iterator, { handled_first: bool, peekable: Peekable<Fuse<I>>, } impl<I> Clone for WithPosition<I> - where I: Clone + Iterator, - I::Item: Clone, +where + I: Clone + Iterator, + I::Item: Clone, { clone_fields!(handled_first, peekable); } /// Create a new `WithPosition` iterator. pub fn with_position<I>(iter: I) -> WithPosition<I> - where I: Iterator, +where + I: Iterator, { WithPosition { handled_first: false, @@ -34,7 +37,7 @@ pub fn with_position<I>(iter: I) -> WithPosition<I> /// Indicates the position of this element in the iterator results. /// /// See [`.with_position()`](crate::Itertools::with_position) for more information. -#[derive(Copy, Clone, Debug, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Position { /// This is the first element. First, @@ -78,11 +81,35 @@ impl<I: Iterator> Iterator for WithPosition<I> { fn size_hint(&self) -> (usize, Option<usize>) { self.peekable.size_hint() } + + fn fold<B, F>(mut self, mut init: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + if let Some(mut head) = self.peekable.next() { + if !self.handled_first { + // The current head is `First` or `Only`, + // it depends if there is another item or not. + match self.peekable.next() { + Some(second) => { + let first = std::mem::replace(&mut head, second); + init = f(init, (Position::First, first)); + } + None => return f(init, (Position::Only, head)), + } + } + // Have seen the first item, and there's something left. + init = self.peekable.fold(init, |acc, mut item| { + std::mem::swap(&mut head, &mut item); + f(acc, (Position::Middle, item)) + }); + // The "head" is now the last item. + init = f(init, (Position::Last, head)); + } + init + } } -impl<I> ExactSizeIterator for WithPosition<I> - where I: ExactSizeIterator, -{ } +impl<I> ExactSizeIterator for WithPosition<I> where I: ExactSizeIterator {} -impl<I: Iterator> FusedIterator for WithPosition<I> -{} +impl<I: Iterator> FusedIterator for WithPosition<I> {} |