summaryrefslogtreecommitdiffstats
path: root/vendor/itertools/src
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/itertools/src')
-rw-r--r--vendor/itertools/src/either_or_both.rs259
-rw-r--r--vendor/itertools/src/format.rs95
-rw-r--r--vendor/itertools/src/groupbylazy.rs12
-rw-r--r--vendor/itertools/src/lib.rs261
-rw-r--r--vendor/itertools/src/merge_join.rs163
-rw-r--r--vendor/itertools/src/peeking_take_while.rs25
-rw-r--r--vendor/itertools/src/process_results_impl.rs35
-rw-r--r--vendor/itertools/src/take_while_inclusive.rs68
-rw-r--r--vendor/itertools/src/tuple_impl.rs4
-rw-r--r--vendor/itertools/src/with_position.rs36
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)),
}
}
}