diff options
Diffstat (limited to 'vendor/itertools/src')
-rw-r--r-- | vendor/itertools/src/either_or_both.rs | 259 | ||||
-rw-r--r-- | vendor/itertools/src/format.rs | 95 | ||||
-rw-r--r-- | vendor/itertools/src/groupbylazy.rs | 12 | ||||
-rw-r--r-- | vendor/itertools/src/lib.rs | 261 | ||||
-rw-r--r-- | vendor/itertools/src/merge_join.rs | 163 | ||||
-rw-r--r-- | vendor/itertools/src/peeking_take_while.rs | 25 | ||||
-rw-r--r-- | vendor/itertools/src/process_results_impl.rs | 35 | ||||
-rw-r--r-- | vendor/itertools/src/take_while_inclusive.rs | 68 | ||||
-rw-r--r-- | vendor/itertools/src/tuple_impl.rs | 4 | ||||
-rw-r--r-- | vendor/itertools/src/with_position.rs | 36 |
10 files changed, 773 insertions, 185 deletions
diff --git a/vendor/itertools/src/either_or_both.rs b/vendor/itertools/src/either_or_both.rs index ef3985f75..cf65fe788 100644 --- a/vendor/itertools/src/either_or_both.rs +++ b/vendor/itertools/src/either_or_both.rs @@ -1,3 +1,5 @@ +use core::ops::{Deref, DerefMut}; + use crate::EitherOrBoth::*; use either::Either; @@ -14,7 +16,7 @@ pub enum EitherOrBoth<A, B> { } impl<A, B> EitherOrBoth<A, B> { - /// If `Left`, or `Both`, return true, otherwise, return false. + /// If `Left`, or `Both`, return true. Otherwise, return false. pub fn has_left(&self) -> bool { self.as_ref().left().is_some() } @@ -24,7 +26,7 @@ impl<A, B> EitherOrBoth<A, B> { self.as_ref().right().is_some() } - /// If Left, return true otherwise, return false. + /// If `Left`, return true. Otherwise, return false. /// Exclusive version of [`has_left`](EitherOrBoth::has_left). pub fn is_left(&self) -> bool { match *self { @@ -33,7 +35,7 @@ impl<A, B> EitherOrBoth<A, B> { } } - /// If Right, return true otherwise, return false. + /// If `Right`, return true. Otherwise, return false. /// Exclusive version of [`has_right`](EitherOrBoth::has_right). pub fn is_right(&self) -> bool { match *self { @@ -42,13 +44,12 @@ impl<A, B> EitherOrBoth<A, B> { } } - /// If Right, return true otherwise, return false. - /// Equivalent to `self.as_ref().both().is_some()`. + /// If `Both`, return true. Otherwise, return false. pub fn is_both(&self) -> bool { self.as_ref().both().is_some() } - /// If `Left`, or `Both`, return `Some` with the left value, otherwise, return `None`. + /// If `Left`, or `Both`, return `Some` with the left value. Otherwise, return `None`. pub fn left(self) -> Option<A> { match self { Left(left) | Both(left, _) => Some(left), @@ -56,7 +57,7 @@ impl<A, B> EitherOrBoth<A, B> { } } - /// If `Right`, or `Both`, return `Some` with the right value, otherwise, return `None`. + /// If `Right`, or `Both`, return `Some` with the right value. Otherwise, return `None`. pub fn right(self) -> Option<B> { match self { Right(right) | Both(_, right) => Some(right), @@ -64,7 +65,57 @@ impl<A, B> EitherOrBoth<A, B> { } } - /// If Both, return `Some` tuple containing left and right. + /// If `Left`, return `Some` with the left value. If `Right` or `Both`, return `None`. + /// + /// # Examples + /// + /// ``` + /// // On the `Left` variant. + /// # use itertools::{EitherOrBoth, EitherOrBoth::{Left, Right, Both}}; + /// let x: EitherOrBoth<_, ()> = Left("bonjour"); + /// assert_eq!(x.just_left(), Some("bonjour")); + /// + /// // On the `Right` variant. + /// let x: EitherOrBoth<(), _> = Right("hola"); + /// assert_eq!(x.just_left(), None); + /// + /// // On the `Both` variant. + /// let x = Both("bonjour", "hola"); + /// assert_eq!(x.just_left(), None); + /// ``` + pub fn just_left(self) -> Option<A> { + match self { + Left(left) => Some(left), + _ => None, + } + } + + /// If `Right`, return `Some` with the right value. If `Left` or `Both`, return `None`. + /// + /// # Examples + /// + /// ``` + /// // On the `Left` variant. + /// # use itertools::{EitherOrBoth::{Left, Right, Both}, EitherOrBoth}; + /// let x: EitherOrBoth<_, ()> = Left("auf wiedersehen"); + /// assert_eq!(x.just_left(), Some("auf wiedersehen")); + /// + /// // On the `Right` variant. + /// let x: EitherOrBoth<(), _> = Right("adios"); + /// assert_eq!(x.just_left(), None); + /// + /// // On the `Both` variant. + /// let x = Both("auf wiedersehen", "adios"); + /// assert_eq!(x.just_left(), None); + /// ``` + pub fn just_right(self) -> Option<B> { + match self { + Right(right) => Some(right), + _ => None, + } + } + + /// If `Both`, return `Some` containing the left and right values. Otherwise, return `None`. pub fn both(self) -> Option<(A, B)> { match self { Both(a, b) => Some((a, b)), @@ -72,6 +123,28 @@ impl<A, B> EitherOrBoth<A, B> { } } + /// If `Left` or `Both`, return the left value. Otherwise, convert the right value and return it. + pub fn into_left(self) -> A + where + B: Into<A>, + { + match self { + Left(a) | Both(a, _) => a, + Right(b) => b.into(), + } + } + + /// If `Right` or `Both`, return the right value. Otherwise, convert the left value and return it. + pub fn into_right(self) -> B + where + A: Into<B>, + { + match self { + Right(b) | Both(_, b) => b, + Left(a) => a.into(), + } + } + /// Converts from `&EitherOrBoth<A, B>` to `EitherOrBoth<&A, &B>`. pub fn as_ref(&self) -> EitherOrBoth<&A, &B> { match *self { @@ -90,6 +163,32 @@ impl<A, B> EitherOrBoth<A, B> { } } + /// Converts from `&EitherOrBoth<A, B>` to `EitherOrBoth<&_, &_>` using the [`Deref`] trait. + pub fn as_deref(&self) -> EitherOrBoth<&A::Target, &B::Target> + where + A: Deref, + B: Deref, + { + match *self { + Left(ref left) => Left(left), + Right(ref right) => Right(right), + Both(ref left, ref right) => Both(left, right), + } + } + + /// Converts from `&mut EitherOrBoth<A, B>` to `EitherOrBoth<&mut _, &mut _>` using the [`DerefMut`] trait. + pub fn as_deref_mut(&mut self) -> EitherOrBoth<&mut A::Target, &mut B::Target> + where + A: DerefMut, + B: DerefMut, + { + match *self { + Left(ref mut left) => Left(left), + Right(ref mut right) => Right(right), + Both(ref mut left, ref mut right) => Both(left, right), + } + } + /// Convert `EitherOrBoth<A, B>` to `EitherOrBoth<B, A>`. pub fn flip(self) -> EitherOrBoth<B, A> { match self { @@ -227,10 +326,152 @@ impl<A, B> EitherOrBoth<A, B> { Both(inner_l, inner_r) => (inner_l, inner_r), } } + + /// Returns a mutable reference to the left value. If the left value is not present, + /// it is replaced with `val`. + pub fn left_or_insert(&mut self, val: A) -> &mut A { + self.left_or_insert_with(|| val) + } + + /// Returns a mutable reference to the right value. If the right value is not present, + /// it is replaced with `val`. + pub fn right_or_insert(&mut self, val: B) -> &mut B { + self.right_or_insert_with(|| val) + } + + /// If the left value is not present, replace it the value computed by the closure `f`. + /// Returns a mutable reference to the now-present left value. + pub fn left_or_insert_with<F>(&mut self, f: F) -> &mut A + where + F: FnOnce() -> A, + { + match self { + Left(left) | Both(left, _) => left, + Right(_) => self.insert_left(f()), + } + } + + /// If the right value is not present, replace it the value computed by the closure `f`. + /// Returns a mutable reference to the now-present right value. + pub fn right_or_insert_with<F>(&mut self, f: F) -> &mut B + where + F: FnOnce() -> B, + { + match self { + Right(right) | Both(_, right) => right, + Left(_) => self.insert_right(f()), + } + } + + /// Sets the `left` value of this instance, and returns a mutable reference to it. + /// Does not affect the `right` value. + /// + /// # Examples + /// ``` + /// # use itertools::{EitherOrBoth, EitherOrBoth::{Left, Right, Both}}; + /// + /// // Overwriting a pre-existing value. + /// let mut either: EitherOrBoth<_, ()> = Left(0_u32); + /// assert_eq!(*either.insert_left(69), 69); + /// + /// // Inserting a second value. + /// let mut either = Right("no"); + /// assert_eq!(*either.insert_left("yes"), "yes"); + /// assert_eq!(either, Both("yes", "no")); + /// ``` + pub fn insert_left(&mut self, val: A) -> &mut A { + match self { + Left(left) | Both(left, _) => { + *left = val; + left + } + Right(right) => { + // This is like a map in place operation. We move out of the reference, + // change the value, and then move back into the reference. + unsafe { + // SAFETY: We know this pointer is valid for reading since we got it from a reference. + let right = std::ptr::read(right as *mut _); + // SAFETY: Again, we know the pointer is valid since we got it from a reference. + std::ptr::write(self as *mut _, Both(val, right)); + } + + if let Both(left, _) = self { + left + } else { + // SAFETY: The above pattern will always match, since we just + // set `self` equal to `Both`. + unsafe { std::hint::unreachable_unchecked() } + } + } + } + } + + /// Sets the `right` value of this instance, and returns a mutable reference to it. + /// Does not affect the `left` value. + /// + /// # Examples + /// ``` + /// # use itertools::{EitherOrBoth, EitherOrBoth::{Left, Both}}; + /// // Overwriting a pre-existing value. + /// let mut either: EitherOrBoth<_, ()> = Left(0_u32); + /// assert_eq!(*either.insert_left(69), 69); + /// + /// // Inserting a second value. + /// let mut either = Left("what's"); + /// assert_eq!(*either.insert_right(9 + 10), 21 - 2); + /// assert_eq!(either, Both("what's", 9+10)); + /// ``` + pub fn insert_right(&mut self, val: B) -> &mut B { + match self { + Right(right) | Both(_, right) => { + *right = val; + right + } + Left(left) => { + // This is like a map in place operation. We move out of the reference, + // change the value, and then move back into the reference. + unsafe { + // SAFETY: We know this pointer is valid for reading since we got it from a reference. + let left = std::ptr::read(left as *mut _); + // SAFETY: Again, we know the pointer is valid since we got it from a reference. + std::ptr::write(self as *mut _, Both(left, val)); + } + if let Both(_, right) = self { + right + } else { + // SAFETY: The above pattern will always match, since we just + // set `self` equal to `Both`. + unsafe { std::hint::unreachable_unchecked() } + } + } + } + } + + /// Set `self` to `Both(..)`, containing the specified left and right values, + /// and returns a mutable reference to those values. + pub fn insert_both(&mut self, left: A, right: B) -> (&mut A, &mut B) { + *self = Both(left, right); + if let Both(left, right) = self { + (left, right) + } else { + // SAFETY: The above pattern will always match, since we just + // set `self` equal to `Both`. + unsafe { std::hint::unreachable_unchecked() } + } + } } impl<T> EitherOrBoth<T, T> { - /// Return either value of left, right, or the product of `f` applied where `Both` are present. + /// Return either value of left, right, or apply a function `f` to both values if both are present. + /// The input function has to return the same type as both Right and Left carry. + /// + /// # Examples + /// ``` + /// # use itertools::EitherOrBoth; + /// assert_eq!(EitherOrBoth::Both(3, 7).reduce(u32::max), 7); + /// assert_eq!(EitherOrBoth::Left(3).reduce(u32::max), 3); + /// assert_eq!(EitherOrBoth::Right(7).reduce(u32::max), 7); + /// ``` pub fn reduce<F>(self, f: F) -> T where F: FnOnce(T, T) -> T, diff --git a/vendor/itertools/src/format.rs b/vendor/itertools/src/format.rs index d87cee950..c4cb65dcb 100644 --- a/vendor/itertools/src/format.rs +++ b/vendor/itertools/src/format.rs @@ -1,5 +1,5 @@ +use std::cell::Cell; use std::fmt; -use std::cell::RefCell; /// Format all iterator elements lazily, separated by `sep`. /// @@ -7,11 +7,10 @@ use std::cell::RefCell; /// exhausted. /// /// See [`.format_with()`](crate::Itertools::format_with) for more information. -#[derive(Clone)] pub struct FormatWith<'a, I, F> { sep: &'a str, /// FormatWith uses interior mutability because Display::fmt takes &self. - inner: RefCell<Option<(I, F)>>, + inner: Cell<Option<(I, F)>>, } /// Format all iterator elements lazily, separated by `sep`. @@ -21,38 +20,40 @@ pub struct FormatWith<'a, I, F> { /// /// See [`.format()`](crate::Itertools::format) /// for more information. -#[derive(Clone)] pub struct Format<'a, I> { sep: &'a str, /// Format uses interior mutability because Display::fmt takes &self. - inner: RefCell<Option<I>>, + inner: Cell<Option<I>>, } pub fn new_format<I, F>(iter: I, separator: &str, f: F) -> FormatWith<'_, I, F> - where I: Iterator, - F: FnMut(I::Item, &mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result +where + I: Iterator, + F: FnMut(I::Item, &mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result, { FormatWith { sep: separator, - inner: RefCell::new(Some((iter, f))), + inner: Cell::new(Some((iter, f))), } } pub fn new_format_default<I>(iter: I, separator: &str) -> Format<'_, I> - where I: Iterator, +where + I: Iterator, { Format { sep: separator, - inner: RefCell::new(Some(iter)), + inner: Cell::new(Some(iter)), } } impl<'a, I, F> fmt::Display for FormatWith<'a, I, F> - where I: Iterator, - F: FnMut(I::Item, &mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result +where + I: Iterator, + F: FnMut(I::Item, &mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let (mut iter, mut format) = match self.inner.borrow_mut().take() { + let (mut iter, mut format) = match self.inner.take() { Some(t) => t, None => panic!("FormatWith: was already formatted once"), }; @@ -71,12 +72,15 @@ impl<'a, I, F> fmt::Display for FormatWith<'a, I, F> } impl<'a, I> Format<'a, I> - where I: Iterator, +where + I: Iterator, { - fn format<F>(&self, f: &mut fmt::Formatter, mut cb: F) -> fmt::Result - where F: FnMut(&I::Item, &mut fmt::Formatter) -> fmt::Result, - { - let mut iter = match self.inner.borrow_mut().take() { + fn format( + &self, + f: &mut fmt::Formatter, + cb: fn(&I::Item, &mut fmt::Formatter) -> fmt::Result, + ) -> fmt::Result { + let mut iter = match self.inner.take() { Some(t) => t, None => panic!("Format: was already formatted once"), }; @@ -109,5 +113,56 @@ macro_rules! impl_format { } } -impl_format!{Display Debug - UpperExp LowerExp UpperHex LowerHex Octal Binary Pointer} +impl_format! {Display Debug UpperExp LowerExp UpperHex LowerHex Octal Binary Pointer} + +impl<'a, I, F> Clone for FormatWith<'a, I, F> +where + (I, F): Clone, +{ + fn clone(&self) -> Self { + struct PutBackOnDrop<'r, 'a, I, F> { + into: &'r FormatWith<'a, I, F>, + inner: Option<(I, F)>, + } + // This ensures we preserve the state of the original `FormatWith` if `Clone` panics + impl<'r, 'a, I, F> Drop for PutBackOnDrop<'r, 'a, I, F> { + fn drop(&mut self) { + self.into.inner.set(self.inner.take()) + } + } + let pbod = PutBackOnDrop { + inner: self.inner.take(), + into: self, + }; + Self { + inner: Cell::new(pbod.inner.clone()), + sep: self.sep, + } + } +} + +impl<'a, I> Clone for Format<'a, I> +where + I: Clone, +{ + fn clone(&self) -> Self { + struct PutBackOnDrop<'r, 'a, I> { + into: &'r Format<'a, I>, + inner: Option<I>, + } + // This ensures we preserve the state of the original `FormatWith` if `Clone` panics + impl<'r, 'a, I> Drop for PutBackOnDrop<'r, 'a, I> { + fn drop(&mut self) { + self.into.inner.set(self.inner.take()) + } + } + let pbod = PutBackOnDrop { + inner: self.inner.take(), + into: self, + }; + Self { + inner: Cell::new(pbod.inner.clone()), + sep: self.sep, + } + } +} diff --git a/vendor/itertools/src/groupbylazy.rs b/vendor/itertools/src/groupbylazy.rs index a5a321df4..80c6f09f3 100644 --- a/vendor/itertools/src/groupbylazy.rs +++ b/vendor/itertools/src/groupbylazy.rs @@ -19,7 +19,7 @@ impl<A, K, F: ?Sized> KeyFunction<A> for F /// `ChunkIndex` acts like the grouping key function for `IntoChunks` -#[derive(Debug)] +#[derive(Debug, Clone)] struct ChunkIndex { size: usize, index: usize, @@ -50,7 +50,7 @@ impl<A> KeyFunction<A> for ChunkIndex { } } - +#[derive(Clone)] struct GroupInner<K, I, F> where I: Iterator { @@ -471,6 +471,13 @@ pub struct IntoChunks<I> index: Cell<usize>, } +impl<I> Clone for IntoChunks<I> + where I: Clone + Iterator, + I::Item: Clone, +{ + clone_fields!(inner, index); +} + impl<I> IntoChunks<I> where I: Iterator, @@ -507,6 +514,7 @@ impl<'a, I> IntoIterator for &'a IntoChunks<I> /// /// See [`.chunks()`](crate::Itertools::chunks) for more information. #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +#[derive(Clone)] pub struct Chunks<'a, I: 'a> where I: Iterator, I::Item: 'a, diff --git a/vendor/itertools/src/lib.rs b/vendor/itertools/src/lib.rs index f91968870..c23a65db5 100644 --- a/vendor/itertools/src/lib.rs +++ b/vendor/itertools/src/lib.rs @@ -146,6 +146,7 @@ pub mod structs { pub use crate::repeatn::RepeatN; #[allow(deprecated)] pub use crate::sources::{RepeatCall, Unfold, Iterate}; + pub use crate::take_while_inclusive::TakeWhileInclusive; #[cfg(feature = "use_alloc")] pub use crate::tee::Tee; pub use crate::tuple_impl::{TupleBuffer, TupleWindows, CircularTupleWindows, Tuples}; @@ -233,6 +234,7 @@ mod rciter_impl; mod repeatn; mod size_hint; mod sources; +mod take_while_inclusive; #[cfg(feature = "use_alloc")] mod tee; mod tuple_impl; @@ -904,7 +906,7 @@ pub trait Itertools : Iterator { /// Return an iterator adaptor that flattens every `Result::Ok` value into /// a series of `Result::Ok` values. `Result::Err` values are unchanged. - /// + /// /// This is useful when you have some common error type for your crate and /// need to propagate it upwards, but the `Result::Ok` case needs to be flattened. /// @@ -914,7 +916,7 @@ pub trait Itertools : Iterator { /// let input = vec![Ok(0..2), Err(false), Ok(2..4)]; /// let it = input.iter().cloned().flatten_ok(); /// itertools::assert_equal(it.clone(), vec![Ok(0), Ok(1), Err(false), Ok(2), Ok(3)]); - /// + /// /// // This can also be used to propagate errors when collecting. /// let output_result: Result<Vec<i32>, bool> = it.collect(); /// assert_eq!(output_result, Err(false)); @@ -926,6 +928,43 @@ pub trait Itertools : Iterator { flatten_ok::flatten_ok(self) } + /// “Lift” a function of the values of the current iterator so as to process + /// an iterator of `Result` values instead. + /// + /// `processor` is a closure that receives an adapted version of the iterator + /// as the only argument — the adapted iterator produces elements of type `T`, + /// as long as the original iterator produces `Ok` values. + /// + /// If the original iterable produces an error at any point, the adapted + /// iterator ends and it will return the error iself. + /// + /// Otherwise, the return value from the closure is returned wrapped + /// inside `Ok`. + /// + /// # Example + /// + /// ``` + /// use itertools::Itertools; + /// + /// type Item = Result<i32, &'static str>; + /// + /// let first_values: Vec<Item> = vec![Ok(1), Ok(0), Ok(3)]; + /// let second_values: Vec<Item> = vec![Ok(2), Ok(1), Err("overflow")]; + /// + /// // “Lift” the iterator .max() method to work on the Ok-values. + /// let first_max = first_values.into_iter().process_results(|iter| iter.max().unwrap_or(0)); + /// let second_max = second_values.into_iter().process_results(|iter| iter.max().unwrap_or(0)); + /// + /// assert_eq!(first_max, Ok(3)); + /// assert!(second_max.is_err()); + /// ``` + fn process_results<F, T, E, R>(self, processor: F) -> Result<R, E> + where Self: Iterator<Item = Result<T, E>> + Sized, + F: FnOnce(ProcessResults<Self, E>) -> R + { + process_results(self, processor) + } + /// Return an iterator adaptor that merges the two base iterators in /// ascending order. If both base iterators are sorted (ascending), the /// result is sorted. @@ -935,8 +974,8 @@ pub trait Itertools : Iterator { /// ``` /// use itertools::Itertools; /// - /// let a = (0..11).step(3); - /// let b = (0..11).step(5); + /// let a = (0..11).step_by(3); + /// let b = (0..11).step_by(5); /// let it = a.merge(b); /// itertools::assert_equal(it, vec![0, 0, 3, 5, 6, 9, 10]); /// ``` @@ -975,7 +1014,10 @@ pub trait Itertools : Iterator { /// Create an iterator that merges items from both this and the specified /// iterator in ascending order. /// - /// It chooses whether to pair elements based on the `Ordering` returned by the + /// The function can either return an `Ordering` variant or a boolean. + /// + /// If `cmp_fn` returns `Ordering`, + /// it chooses whether to pair elements based on the `Ordering` returned by the /// specified compare function. At any point, inspecting the tip of the /// iterators `I` and `J` as items `i` of type `I::Item` and `j` of type /// `J::Item` respectively, the resulting iterator will: @@ -991,18 +1033,46 @@ pub trait Itertools : Iterator { /// use itertools::Itertools; /// use itertools::EitherOrBoth::{Left, Right, Both}; /// - /// let multiples_of_2 = (0..10).step(2); - /// let multiples_of_3 = (0..10).step(3); + /// let a = vec![0, 2, 4, 6, 1].into_iter(); + /// let b = (0..10).step_by(3); /// /// itertools::assert_equal( - /// multiples_of_2.merge_join_by(multiples_of_3, |i, j| i.cmp(j)), - /// vec![Both(0, 0), Left(2), Right(3), Left(4), Both(6, 6), Left(8), Right(9)] + /// a.merge_join_by(b, |i, j| i.cmp(j)), + /// vec![Both(0, 0), Left(2), Right(3), Left(4), Both(6, 6), Left(1), Right(9)] + /// ); + /// ``` + /// + /// If `cmp_fn` returns `bool`, + /// it chooses whether to pair elements based on the boolean returned by the + /// specified function. At any point, inspecting the tip of the + /// iterators `I` and `J` as items `i` of type `I::Item` and `j` of type + /// `J::Item` respectively, the resulting iterator will: + /// + /// - Emit `Either::Left(i)` when `true`, + /// and remove `i` from its source iterator + /// - Emit `Either::Right(j)` when `false`, + /// and remove `j` from its source iterator + /// + /// It is similar to the `Ordering` case if the first argument is considered + /// "less" than the second argument. + /// + /// ``` + /// use itertools::Itertools; + /// use itertools::Either::{Left, Right}; + /// + /// let a = vec![0, 2, 4, 6, 1].into_iter(); + /// let b = (0..10).step_by(3); + /// + /// itertools::assert_equal( + /// a.merge_join_by(b, |i, j| i <= j), + /// vec![Left(0), Right(0), Left(2), Right(3), Left(4), Left(6), Left(1), Right(6), Right(9)] /// ); /// ``` #[inline] - fn merge_join_by<J, F>(self, other: J, cmp_fn: F) -> MergeJoinBy<Self, J::IntoIter, F> + fn merge_join_by<J, F, T>(self, other: J, cmp_fn: F) -> MergeJoinBy<Self, J::IntoIter, F> where J: IntoIterator, - F: FnMut(&Self::Item, &J::Item) -> std::cmp::Ordering, + F: FnMut(&Self::Item, &J::Item) -> T, + T: merge_join::OrderingOrBool<Self::Item, J::Item>, Self: Sized { merge_join_by(self, other, cmp_fn) @@ -1018,9 +1088,9 @@ pub trait Itertools : Iterator { /// ``` /// use itertools::Itertools; /// - /// let a = (0..6).step(3); - /// let b = (1..6).step(3); - /// let c = (2..6).step(3); + /// let a = (0..6).step_by(3); + /// let b = (1..6).step_by(3); + /// let c = (2..6).step_by(3); /// let it = vec![a, b, c].into_iter().kmerge(); /// itertools::assert_equal(it, vec![0, 1, 2, 3, 4, 5]); /// ``` @@ -1389,6 +1459,74 @@ pub trait Itertools : Iterator { adaptors::take_while_ref(self, accept) } + /// Returns an iterator adaptor that consumes elements while the given + /// predicate is `true`, *including* the element for which the predicate + /// first returned `false`. + /// + /// The [`.take_while()`][std::iter::Iterator::take_while] adaptor is useful + /// when you want items satisfying a predicate, but to know when to stop + /// taking elements, we have to consume that first element that doesn't + /// satisfy the predicate. This adaptor includes that element where + /// [`.take_while()`][std::iter::Iterator::take_while] would drop it. + /// + /// The [`.take_while_ref()`][crate::Itertools::take_while_ref] adaptor + /// serves a similar purpose, but this adaptor doesn't require [`Clone`]ing + /// the underlying elements. + /// + /// ```rust + /// # use itertools::Itertools; + /// let items = vec![1, 2, 3, 4, 5]; + /// let filtered: Vec<_> = items + /// .into_iter() + /// .take_while_inclusive(|&n| n % 3 != 0) + /// .collect(); + /// + /// assert_eq!(filtered, vec![1, 2, 3]); + /// ``` + /// + /// ```rust + /// # use itertools::Itertools; + /// let items = vec![1, 2, 3, 4, 5]; + /// + /// let take_while_inclusive_result: Vec<_> = items + /// .iter() + /// .copied() + /// .take_while_inclusive(|&n| n % 3 != 0) + /// .collect(); + /// let take_while_result: Vec<_> = items + /// .into_iter() + /// .take_while(|&n| n % 3 != 0) + /// .collect(); + /// + /// assert_eq!(take_while_inclusive_result, vec![1, 2, 3]); + /// assert_eq!(take_while_result, vec![1, 2]); + /// // both iterators have the same items remaining at this point---the 3 + /// // is lost from the `take_while` vec + /// ``` + /// + /// ```rust + /// # use itertools::Itertools; + /// #[derive(Debug, PartialEq)] + /// struct NoCloneImpl(i32); + /// + /// let non_clonable_items: Vec<_> = vec![1, 2, 3, 4, 5] + /// .into_iter() + /// .map(NoCloneImpl) + /// .collect(); + /// let filtered: Vec<_> = non_clonable_items + /// .into_iter() + /// .take_while_inclusive(|n| n.0 % 3 != 0) + /// .collect(); + /// let expected: Vec<_> = vec![1, 2, 3].into_iter().map(NoCloneImpl).collect(); + /// assert_eq!(filtered, expected); + fn take_while_inclusive<F>(&mut self, accept: F) -> TakeWhileInclusive<Self, F> + where + Self: Sized, + F: FnMut(&Self::Item) -> bool, + { + take_while_inclusive::TakeWhileInclusive::new(self, accept) + } + /// Return an iterator adaptor that filters `Option<A>` iterator elements /// and produces `A`. Stops on the first `None` encountered. /// @@ -1620,24 +1758,24 @@ pub trait Itertools : Iterator { pad_tail::pad_using(self, min, f) } - /// Return an iterator adaptor that wraps each element in a `Position` to + /// Return an iterator adaptor that combines each element with a `Position` to /// ease special-case handling of the first or last elements. /// /// Iterator element type is - /// [`Position<Self::Item>`](Position) + /// [`(Position, Self::Item)`](Position) /// /// ``` /// use itertools::{Itertools, Position}; /// /// let it = (0..4).with_position(); /// itertools::assert_equal(it, - /// vec![Position::First(0), - /// Position::Middle(1), - /// Position::Middle(2), - /// Position::Last(3)]); + /// vec![(Position::First, 0), + /// (Position::Middle, 1), + /// (Position::Middle, 2), + /// (Position::Last, 3)]); /// /// let it = (0..1).with_position(); - /// itertools::assert_equal(it, vec![Position::Only(0)]); + /// itertools::assert_equal(it, vec![(Position::Only, 0)]); /// ``` fn with_position(self) -> WithPosition<Self> where Self: Sized, @@ -1810,14 +1948,14 @@ pub trait Itertools : Iterator { /// /// #[derive(PartialEq, Debug)] /// enum Enum { A, B, C, D, E, } - /// + /// /// let mut iter = vec![Enum::A, Enum::B, Enum::C, Enum::D].into_iter(); - /// + /// /// // search `iter` for `B` /// assert_eq!(iter.contains(&Enum::B), true); /// // `B` was found, so the iterator now rests at the item after `B` (i.e, `C`). /// assert_eq!(iter.next(), Some(Enum::C)); - /// + /// /// // search `iter` for `E` /// assert_eq!(iter.contains(&Enum::E), false); /// // `E` wasn't found, so `iter` is now exhausted @@ -1858,6 +1996,37 @@ pub trait Itertools : Iterator { } } + /// If there are elements and they are all equal, return a single copy of that element. + /// If there are no elements, return an Error containing None. + /// If there are elements and they are not all equal, return a tuple containing the first + /// two non-equal elements found. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let data = vec![1, 1, 1, 2, 2, 3, 3, 3, 4, 5, 5]; + /// assert_eq!(data.iter().all_equal_value(), Err(Some((&1, &2)))); + /// assert_eq!(data[0..3].iter().all_equal_value(), Ok(&1)); + /// assert_eq!(data[3..5].iter().all_equal_value(), Ok(&2)); + /// assert_eq!(data[5..8].iter().all_equal_value(), Ok(&3)); + /// + /// let data : Option<usize> = None; + /// assert_eq!(data.into_iter().all_equal_value(), Err(None)); + /// ``` + fn all_equal_value(&mut self) -> Result<Self::Item, Option<(Self::Item, Self::Item)>> + where + Self: Sized, + Self::Item: PartialEq + { + let first = self.next().ok_or(None)?; + let other = self.find(|x| x != &first); + if let Some(other) = other { + Err(Some((first, other))) + } else { + Ok(first) + } + } + /// Check whether all elements are unique (non equal). /// /// Empty iterators are considered to have unique elements: @@ -2481,6 +2650,8 @@ pub trait Itertools : Iterator { /// **Note:** This consumes the entire iterator, uses the /// [`slice::sort_unstable`] method and returns the result as a new /// iterator that owns its elements. + /// + /// This sort is unstable (i.e., may reorder equal elements). /// /// The sorted iterator, if directly collected to a `Vec`, is converted /// without any extra copying or allocation cost. @@ -2510,6 +2681,8 @@ pub trait Itertools : Iterator { /// **Note:** This consumes the entire iterator, uses the /// [`slice::sort_unstable_by`] method and returns the result as a new /// iterator that owns its elements. + /// + /// This sort is unstable (i.e., may reorder equal elements). /// /// The sorted iterator, if directly collected to a `Vec`, is converted /// without any extra copying or allocation cost. @@ -2543,6 +2716,8 @@ pub trait Itertools : Iterator { /// **Note:** This consumes the entire iterator, uses the /// [`slice::sort_unstable_by_key`] method and returns the result as a new /// iterator that owns its elements. + /// + /// This sort is unstable (i.e., may reorder equal elements). /// /// The sorted iterator, if directly collected to a `Vec`, is converted /// without any extra copying or allocation cost. @@ -2577,6 +2752,8 @@ pub trait Itertools : Iterator { /// **Note:** This consumes the entire iterator, uses the /// [`slice::sort`] method and returns the result as a new /// iterator that owns its elements. + /// + /// This sort is stable (i.e., does not reorder equal elements). /// /// The sorted iterator, if directly collected to a `Vec`, is converted /// without any extra copying or allocation cost. @@ -2606,6 +2783,8 @@ pub trait Itertools : Iterator { /// **Note:** This consumes the entire iterator, uses the /// [`slice::sort_by`] method and returns the result as a new /// iterator that owns its elements. + /// + /// This sort is stable (i.e., does not reorder equal elements). /// /// The sorted iterator, if directly collected to a `Vec`, is converted /// without any extra copying or allocation cost. @@ -2614,7 +2793,7 @@ pub trait Itertools : Iterator { /// use itertools::Itertools; /// /// // sort people in descending order by age - /// let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 27)]; + /// let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 30)]; /// /// let oldest_people_first = people /// .into_iter() @@ -2639,6 +2818,8 @@ pub trait Itertools : Iterator { /// **Note:** This consumes the entire iterator, uses the /// [`slice::sort_by_key`] method and returns the result as a new /// iterator that owns its elements. + /// + /// This sort is stable (i.e., does not reorder equal elements). /// /// The sorted iterator, if directly collected to a `Vec`, is converted /// without any extra copying or allocation cost. @@ -2647,7 +2828,7 @@ pub trait Itertools : Iterator { /// use itertools::Itertools; /// /// // sort people in descending order by age - /// let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 27)]; + /// let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 30)]; /// /// let oldest_people_first = people /// .into_iter() @@ -2674,6 +2855,8 @@ pub trait Itertools : Iterator { /// **Note:** This consumes the entire iterator, uses the /// [`slice::sort_by_cached_key`] method and returns the result as a new /// iterator that owns its elements. + /// + /// This sort is stable (i.e., does not reorder equal elements). /// /// The sorted iterator, if directly collected to a `Vec`, is converted /// without any extra copying or allocation cost. @@ -2682,7 +2865,7 @@ pub trait Itertools : Iterator { /// use itertools::Itertools; /// /// // sort people in descending order by age - /// let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 27)]; + /// let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 30)]; /// /// let oldest_people_first = people /// .into_iter() @@ -2867,13 +3050,13 @@ pub trait Itertools : Iterator { group_map::into_group_map_by(self, f) } - /// Constructs a `GroupingMap` to be used later with one of the efficient + /// Constructs a `GroupingMap` to be used later with one of the efficient /// group-and-fold operations it allows to perform. - /// + /// /// The input iterator must yield item in the form of `(K, V)` where the /// value of type `K` will be used as key to identify the groups and the /// value of type `V` as value for the folding operation. - /// + /// /// See [`GroupingMap`] for more informations /// on what operations are available. #[cfg(feature = "use_std")] @@ -2884,12 +3067,12 @@ pub trait Itertools : Iterator { grouping_map::new(self) } - /// Constructs a `GroupingMap` to be used later with one of the efficient + /// Constructs a `GroupingMap` to be used later with one of the efficient /// group-and-fold operations it allows to perform. - /// + /// /// The values from this iterator will be used as values for the folding operation /// while the keys will be obtained from the values by calling `key_mapper`. - /// + /// /// See [`GroupingMap`] for more informations /// on what operations are available. #[cfg(feature = "use_std")] @@ -3059,7 +3242,7 @@ pub trait Itertools : Iterator { ) } - /// Return all minimum elements of an iterator, as determined by + /// Return all maximum elements of an iterator, as determined by /// the specified function. /// /// # Examples @@ -3600,7 +3783,7 @@ pub trait Itertools : Iterator { /// first_name: &'static str, /// last_name: &'static str, /// } - /// + /// /// let characters = /// vec![ /// Character { first_name: "Amy", last_name: "Pond" }, @@ -3611,12 +3794,12 @@ pub trait Itertools : Iterator { /// Character { first_name: "James", last_name: "Norington" }, /// Character { first_name: "James", last_name: "Kirk" }, /// ]; - /// - /// let first_name_frequency = + /// + /// let first_name_frequency = /// characters /// .into_iter() /// .counts_by(|c| c.first_name); - /// + /// /// assert_eq!(first_name_frequency["Amy"], 3); /// assert_eq!(first_name_frequency["James"], 4); /// assert_eq!(first_name_frequency.contains_key("Asha"), false); @@ -3637,7 +3820,7 @@ pub trait Itertools : Iterator { /// column. /// /// This function is, in some sense, the opposite of [`multizip`]. - /// + /// /// ``` /// use itertools::Itertools; /// diff --git a/vendor/itertools/src/merge_join.rs b/vendor/itertools/src/merge_join.rs index f2fbdea2c..84f7d0333 100644 --- a/vendor/itertools/src/merge_join.rs +++ b/vendor/itertools/src/merge_join.rs @@ -2,19 +2,23 @@ use std::cmp::Ordering; use std::iter::Fuse; use std::fmt; +use either::Either; + use super::adaptors::{PutBack, put_back}; use crate::either_or_both::EitherOrBoth; +use crate::size_hint::{self, SizeHint}; #[cfg(doc)] use crate::Itertools; /// Return an iterator adaptor that merge-joins items from the two base iterators in ascending order. /// /// [`IntoIterator`] enabled version of [`Itertools::merge_join_by`]. -pub fn merge_join_by<I, J, F>(left: I, right: J, cmp_fn: F) +pub fn merge_join_by<I, J, F, T>(left: I, right: J, cmp_fn: F) -> MergeJoinBy<I::IntoIter, J::IntoIter, F> where I: IntoIterator, J: IntoIterator, - F: FnMut(&I::Item, &J::Item) -> Ordering + F: FnMut(&I::Item, &J::Item) -> T, + T: OrderingOrBool<I::Item, J::Item>, { MergeJoinBy { left: put_back(left.into_iter().fuse()), @@ -30,7 +34,66 @@ pub fn merge_join_by<I, J, F>(left: I, right: J, cmp_fn: F) pub struct MergeJoinBy<I: Iterator, J: Iterator, F> { left: PutBack<Fuse<I>>, right: PutBack<Fuse<J>>, - cmp_fn: F + cmp_fn: F, +} + +pub trait OrderingOrBool<L, R> { + type MergeResult; + fn left(left: L) -> Self::MergeResult; + fn right(right: R) -> Self::MergeResult; + // "merge" never returns (Some(...), Some(...), ...) so Option<Either<I::Item, J::Item>> + // is appealing but it is always followed by two put_backs, so we think the compiler is + // smart enough to optimize it. Or we could move put_backs into "merge". + fn merge(self, left: L, right: R) -> (Option<L>, Option<R>, Self::MergeResult); + fn size_hint(left: SizeHint, right: SizeHint) -> SizeHint; +} + +impl<L, R> OrderingOrBool<L, R> for Ordering { + type MergeResult = EitherOrBoth<L, R>; + fn left(left: L) -> Self::MergeResult { + EitherOrBoth::Left(left) + } + fn right(right: R) -> Self::MergeResult { + EitherOrBoth::Right(right) + } + fn merge(self, left: L, right: R) -> (Option<L>, Option<R>, Self::MergeResult) { + match self { + Ordering::Equal => (None, None, EitherOrBoth::Both(left, right)), + Ordering::Less => (None, Some(right), EitherOrBoth::Left(left)), + Ordering::Greater => (Some(left), None, EitherOrBoth::Right(right)), + } + } + fn size_hint(left: SizeHint, right: SizeHint) -> SizeHint { + let (a_lower, a_upper) = left; + let (b_lower, b_upper) = right; + let lower = ::std::cmp::max(a_lower, b_lower); + let upper = match (a_upper, b_upper) { + (Some(x), Some(y)) => x.checked_add(y), + _ => None, + }; + (lower, upper) + } +} + +impl<L, R> OrderingOrBool<L, R> for bool { + type MergeResult = Either<L, R>; + fn left(left: L) -> Self::MergeResult { + Either::Left(left) + } + fn right(right: R) -> Self::MergeResult { + Either::Right(right) + } + fn merge(self, left: L, right: R) -> (Option<L>, Option<R>, Self::MergeResult) { + if self { + (None, Some(right), Either::Left(left)) + } else { + (Some(left), None, Either::Right(right)) + } + } + fn size_hint(left: SizeHint, right: SizeHint) -> SizeHint { + // Not ExactSizeIterator because size may be larger than usize + size_hint::add(left, right) + } } impl<I, J, F> Clone for MergeJoinBy<I, J, F> @@ -52,49 +115,34 @@ impl<I, J, F> fmt::Debug for MergeJoinBy<I, J, F> debug_fmt_fields!(MergeJoinBy, left, right); } -impl<I, J, F> Iterator for MergeJoinBy<I, J, F> +impl<I, J, F, T> Iterator for MergeJoinBy<I, J, F> where I: Iterator, J: Iterator, - F: FnMut(&I::Item, &J::Item) -> Ordering + F: FnMut(&I::Item, &J::Item) -> T, + T: OrderingOrBool<I::Item, J::Item>, { - type Item = EitherOrBoth<I::Item, J::Item>; + type Item = T::MergeResult; fn next(&mut self) -> Option<Self::Item> { match (self.left.next(), self.right.next()) { (None, None) => None, - (Some(left), None) => - Some(EitherOrBoth::Left(left)), - (None, Some(right)) => - Some(EitherOrBoth::Right(right)), + (Some(left), None) => Some(T::left(left)), + (None, Some(right)) => Some(T::right(right)), (Some(left), Some(right)) => { - match (self.cmp_fn)(&left, &right) { - Ordering::Equal => - Some(EitherOrBoth::Both(left, right)), - Ordering::Less => { - self.right.put_back(right); - Some(EitherOrBoth::Left(left)) - }, - Ordering::Greater => { - self.left.put_back(left); - Some(EitherOrBoth::Right(right)) - } + let (left, right, next) = (self.cmp_fn)(&left, &right).merge(left, right); + if let Some(left) = left { + self.left.put_back(left); + } + if let Some(right) = right { + self.right.put_back(right); } + Some(next) } } } - fn size_hint(&self) -> (usize, Option<usize>) { - let (a_lower, a_upper) = self.left.size_hint(); - let (b_lower, b_upper) = self.right.size_hint(); - - let lower = ::std::cmp::max(a_lower, b_lower); - - let upper = match (a_upper, b_upper) { - (Some(x), Some(y)) => x.checked_add(y), - _ => None, - }; - - (lower, upper) + fn size_hint(&self) -> SizeHint { + T::size_hint(self.left.size_hint(), self.right.size_hint()) } fn count(mut self) -> usize { @@ -106,10 +154,12 @@ impl<I, J, F> Iterator for MergeJoinBy<I, J, F> (None, Some(_right)) => break count + 1 + self.right.into_parts().1.count(), (Some(left), Some(right)) => { count += 1; - match (self.cmp_fn)(&left, &right) { - Ordering::Equal => {} - Ordering::Less => self.right.put_back(right), - Ordering::Greater => self.left.put_back(left), + let (left, right, _) = (self.cmp_fn)(&left, &right).merge(left, right); + if let Some(left) = left { + self.left.put_back(left); + } + if let Some(right) = right { + self.right.put_back(right); } } } @@ -122,27 +172,24 @@ impl<I, J, F> Iterator for MergeJoinBy<I, J, F> match (self.left.next(), self.right.next()) { (None, None) => break previous_element, (Some(left), None) => { - break Some(EitherOrBoth::Left( + break Some(T::left( self.left.into_parts().1.last().unwrap_or(left), )) } (None, Some(right)) => { - break Some(EitherOrBoth::Right( + break Some(T::right( self.right.into_parts().1.last().unwrap_or(right), )) } (Some(left), Some(right)) => { - previous_element = match (self.cmp_fn)(&left, &right) { - Ordering::Equal => Some(EitherOrBoth::Both(left, right)), - Ordering::Less => { - self.right.put_back(right); - Some(EitherOrBoth::Left(left)) - } - Ordering::Greater => { - self.left.put_back(left); - Some(EitherOrBoth::Right(right)) - } + let (left, right, elem) = (self.cmp_fn)(&left, &right).merge(left, right); + if let Some(left) = left { + self.left.put_back(left); + } + if let Some(right) = right { + self.right.put_back(right); } + previous_element = Some(elem); } } } @@ -156,13 +203,17 @@ impl<I, J, F> Iterator for MergeJoinBy<I, J, F> n -= 1; match (self.left.next(), self.right.next()) { (None, None) => break None, - (Some(_left), None) => break self.left.nth(n).map(EitherOrBoth::Left), - (None, Some(_right)) => break self.right.nth(n).map(EitherOrBoth::Right), - (Some(left), Some(right)) => match (self.cmp_fn)(&left, &right) { - Ordering::Equal => {} - Ordering::Less => self.right.put_back(right), - Ordering::Greater => self.left.put_back(left), - }, + (Some(_left), None) => break self.left.nth(n).map(T::left), + (None, Some(_right)) => break self.right.nth(n).map(T::right), + (Some(left), Some(right)) => { + let (left, right, _) = (self.cmp_fn)(&left, &right).merge(left, right); + if let Some(left) = left { + self.left.put_back(left); + } + if let Some(right) = right { + self.right.put_back(right); + } + } } } } diff --git a/vendor/itertools/src/peeking_take_while.rs b/vendor/itertools/src/peeking_take_while.rs index b3a9c5ccb..3a3722812 100644 --- a/vendor/itertools/src/peeking_take_while.rs +++ b/vendor/itertools/src/peeking_take_while.rs @@ -16,7 +16,18 @@ pub trait PeekingNext : Iterator { /// if `accept` returns true, return it as the next element, /// else None. fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> - where F: FnOnce(&Self::Item) -> bool; + where Self: Sized, + F: FnOnce(&Self::Item) -> bool; +} + +impl<'a, I> PeekingNext for &'a mut I + where I: PeekingNext, +{ + fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> + where F: FnOnce(&Self::Item) -> bool + { + (*self).peeking_next(accept) + } } impl<I> PeekingNext for Peekable<I> @@ -115,6 +126,18 @@ impl<'a, I, F> Iterator for PeekingTakeWhile<'a, I, F> } } +impl<'a, I, F> PeekingNext for PeekingTakeWhile<'a, I, F> + where I: PeekingNext, + F: FnMut(&I::Item) -> bool, +{ + fn peeking_next<G>(&mut self, g: G) -> Option<Self::Item> + where G: FnOnce(&Self::Item) -> bool, + { + let f = &mut self.f; + self.iter.peeking_next(|r| f(r) && g(r)) + } +} + // Some iterators are so lightweight we can simply clone them to save their // state and use that for peeking. macro_rules! peeking_next_by_clone { diff --git a/vendor/itertools/src/process_results_impl.rs b/vendor/itertools/src/process_results_impl.rs index 44308f378..713db4551 100644 --- a/vendor/itertools/src/process_results_impl.rs +++ b/vendor/itertools/src/process_results_impl.rs @@ -1,3 +1,5 @@ +#[cfg(doc)] +use crate::Itertools; /// An iterator that produces only the `T` values as long as the /// inner iterator produces `Ok(T)`. @@ -52,38 +54,7 @@ impl<'a, I, T, E> Iterator for ProcessResults<'a, I, E> /// “Lift” a function of the values of an iterator so that it can process /// an iterator of `Result` values instead. /// -/// `iterable` is an iterator or iterable with `Result<T, E>` elements, where -/// `T` is the value type and `E` the error type. -/// -/// `processor` is a closure that receives an adapted version of the iterable -/// as the only argument — the adapted iterator produces elements of type `T`, -/// as long as the original iterator produces `Ok` values. -/// -/// If the original iterable produces an error at any point, the adapted -/// iterator ends and the `process_results` function will return the -/// error iself. -/// -/// Otherwise, the return value from the closure is returned wrapped -/// inside `Ok`. -/// -/// # Example -/// -/// ``` -/// use itertools::process_results; -/// -/// type R = Result<i32, &'static str>; -/// -/// let first_values: Vec<R> = vec![Ok(1), Ok(0), Ok(3)]; -/// let second_values: Vec<R> = vec![Ok(2), Ok(1), Err("overflow")]; -/// -/// // “Lift” the iterator .max() method to work on the values in Results using process_results -/// -/// let first_max = process_results(first_values, |iter| iter.max().unwrap_or(0)); -/// let second_max = process_results(second_values, |iter| iter.max().unwrap_or(0)); -/// -/// assert_eq!(first_max, Ok(3)); -/// assert!(second_max.is_err()); -/// ``` +/// [`IntoIterator`] enabled version of [`Itertools::process_results`]. pub fn process_results<I, F, T, E, R>(iterable: I, processor: F) -> Result<R, E> where I: IntoIterator<Item = Result<T, E>>, F: FnOnce(ProcessResults<I::IntoIter, E>) -> R diff --git a/vendor/itertools/src/take_while_inclusive.rs b/vendor/itertools/src/take_while_inclusive.rs new file mode 100644 index 000000000..e2a7479e0 --- /dev/null +++ b/vendor/itertools/src/take_while_inclusive.rs @@ -0,0 +1,68 @@ +use core::iter::FusedIterator; +use std::fmt; + +/// An iterator adaptor that consumes elements while the given predicate is +/// `true`, including the element for which the predicate first returned +/// `false`. +/// +/// See [`.take_while_inclusive()`](crate::Itertools::take_while_inclusive) +/// for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct TakeWhileInclusive<'a, I: 'a, F> { + iter: &'a mut I, + predicate: F, + done: bool, +} + +impl<'a, I, F> TakeWhileInclusive<'a, I, F> +where + I: Iterator, + F: FnMut(&I::Item) -> bool, +{ + /// Create a new [`TakeWhileInclusive`] from an iterator and a predicate. + pub fn new(iter: &'a mut I, predicate: F) -> Self { + Self { iter, predicate, done: false} + } +} + +impl<'a, I, F> fmt::Debug for TakeWhileInclusive<'a, I, F> + where I: Iterator + fmt::Debug, +{ + debug_fmt_fields!(TakeWhileInclusive, iter); +} + +impl<'a, I, F> Iterator for TakeWhileInclusive<'a, I, F> +where + I: Iterator, + F: FnMut(&I::Item) -> bool +{ + type Item = I::Item; + + fn next(&mut self) -> Option<Self::Item> { + if self.done { + None + } else { + self.iter.next().map(|item| { + if !(self.predicate)(&item) { + self.done = true; + } + item + }) + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + if self.done { + (0, Some(0)) + } else { + (0, self.iter.size_hint().1) + } + } +} + +impl<I, F> FusedIterator for TakeWhileInclusive<'_, I, F> +where + I: Iterator, + F: FnMut(&I::Item) -> bool +{ +}
\ No newline at end of file diff --git a/vendor/itertools/src/tuple_impl.rs b/vendor/itertools/src/tuple_impl.rs index 06b5c13cb..fdf086585 100644 --- a/vendor/itertools/src/tuple_impl.rs +++ b/vendor/itertools/src/tuple_impl.rs @@ -194,14 +194,14 @@ impl<I, T> FusedIterator for TupleWindows<I, T> T::Item: Clone {} -/// An iterator over all windows,wrapping back to the first elements when the +/// An iterator over all windows, wrapping back to the first elements when the /// window would otherwise exceed the length of the iterator, producing tuples /// of a specific size. /// /// See [`.circular_tuple_windows()`](crate::Itertools::circular_tuple_windows) for more /// information. #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct CircularTupleWindows<I, T: Clone> where I: Iterator<Item = T::Item> + Clone, T: TupleCollect + Clone diff --git a/vendor/itertools/src/with_position.rs b/vendor/itertools/src/with_position.rs index 1388503d1..dda9b25dc 100644 --- a/vendor/itertools/src/with_position.rs +++ b/vendor/itertools/src/with_position.rs @@ -2,7 +2,7 @@ use std::iter::{Fuse,Peekable, FusedIterator}; /// An iterator adaptor that wraps each element in an [`Position`]. /// -/// Iterator element type is `Position<I::Item>`. +/// Iterator element type is `(Position, I::Item)`. /// /// See [`.with_position()`](crate::Itertools::with_position) for more information. #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] @@ -30,36 +30,24 @@ pub fn with_position<I>(iter: I) -> WithPosition<I> } } -/// A value yielded by `WithPosition`. +/// The first component of the value yielded by `WithPosition`. /// 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)] -pub enum Position<T> { +pub enum Position { /// This is the first element. - First(T), + First, /// This is neither the first nor the last element. - Middle(T), + Middle, /// This is the last element. - Last(T), + Last, /// This is the only element. - Only(T), -} - -impl<T> Position<T> { - /// Return the inner value. - pub fn into_inner(self) -> T { - match self { - Position::First(x) | - Position::Middle(x) | - Position::Last(x) | - Position::Only(x) => x, - } - } + Only, } impl<I: Iterator> Iterator for WithPosition<I> { - type Item = Position<I::Item>; + type Item = (Position, I::Item); fn next(&mut self) -> Option<Self::Item> { match self.peekable.next() { @@ -70,15 +58,15 @@ impl<I: Iterator> Iterator for WithPosition<I> { // Peek to see if this is also the last item, // in which case tag it as `Only`. match self.peekable.peek() { - Some(_) => Some(Position::First(item)), - None => Some(Position::Only(item)), + Some(_) => Some((Position::First, item)), + None => Some((Position::Only, item)), } } else { // Have seen the first item, and there's something left. // Peek to see if this is the last item. match self.peekable.peek() { - Some(_) => Some(Position::Middle(item)), - None => Some(Position::Last(item)), + Some(_) => Some((Position::Middle, item)), + None => Some((Position::Last, item)), } } } |