Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

View File

@@ -0,0 +1,286 @@
use std::fmt;
use std::iter::FusedIterator;
use crate::size_hint;
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct CoalesceBy<I, F, C>
where
I: Iterator,
C: CountItem<I::Item>,
{
iter: I,
/// `last` is `None` while no item have been taken out of `iter` (at definition).
/// Then `last` will be `Some(Some(item))` until `iter` is exhausted,
/// in which case `last` will be `Some(None)`.
last: Option<Option<C::CItem>>,
f: F,
}
impl<I, F, C> Clone for CoalesceBy<I, F, C>
where
I: Clone + Iterator,
F: Clone,
C: CountItem<I::Item>,
C::CItem: Clone,
{
clone_fields!(last, iter, f);
}
impl<I, F, C> fmt::Debug for CoalesceBy<I, F, C>
where
I: Iterator + fmt::Debug,
C: CountItem<I::Item>,
C::CItem: fmt::Debug,
{
debug_fmt_fields!(CoalesceBy, iter, last);
}
pub trait CoalescePredicate<Item, T> {
fn coalesce_pair(&mut self, t: T, item: Item) -> Result<T, (T, T)>;
}
impl<I, F, C> Iterator for CoalesceBy<I, F, C>
where
I: Iterator,
F: CoalescePredicate<I::Item, C::CItem>,
C: CountItem<I::Item>,
{
type Item = C::CItem;
fn next(&mut self) -> Option<Self::Item> {
let Self { iter, last, f } = self;
// this fuses the iterator
let init = match last {
Some(elt) => elt.take(),
None => {
*last = Some(None);
iter.next().map(C::new)
}
}?;
Some(
iter.try_fold(init, |accum, next| match f.coalesce_pair(accum, next) {
Ok(joined) => Ok(joined),
Err((last_, next_)) => {
*last = Some(Some(next_));
Err(last_)
}
})
.unwrap_or_else(|x| x),
)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let (low, hi) = size_hint::add_scalar(
self.iter.size_hint(),
matches!(self.last, Some(Some(_))) as usize,
);
((low > 0) as usize, hi)
}
fn fold<Acc, FnAcc>(self, acc: Acc, mut fn_acc: FnAcc) -> Acc
where
FnAcc: FnMut(Acc, Self::Item) -> Acc,
{
let Self {
mut iter,
last,
mut f,
} = self;
if let Some(last) = last.unwrap_or_else(|| iter.next().map(C::new)) {
let (last, acc) = iter.fold((last, acc), |(last, acc), elt| {
match f.coalesce_pair(last, elt) {
Ok(joined) => (joined, acc),
Err((last_, next_)) => (next_, fn_acc(acc, last_)),
}
});
fn_acc(acc, last)
} else {
acc
}
}
}
impl<I, F, C> FusedIterator for CoalesceBy<I, F, C>
where
I: Iterator,
F: CoalescePredicate<I::Item, C::CItem>,
C: CountItem<I::Item>,
{
}
pub struct NoCount;
pub struct WithCount;
pub trait CountItem<T> {
type CItem;
fn new(t: T) -> Self::CItem;
}
impl<T> CountItem<T> for NoCount {
type CItem = T;
#[inline(always)]
fn new(t: T) -> T {
t
}
}
impl<T> CountItem<T> for WithCount {
type CItem = (usize, T);
#[inline(always)]
fn new(t: T) -> (usize, T) {
(1, t)
}
}
/// An iterator adaptor that may join together adjacent elements.
///
/// See [`.coalesce()`](crate::Itertools::coalesce) for more information.
pub type Coalesce<I, F> = CoalesceBy<I, F, NoCount>;
impl<F, Item, T> CoalescePredicate<Item, T> for F
where
F: FnMut(T, Item) -> Result<T, (T, T)>,
{
fn coalesce_pair(&mut self, t: T, item: Item) -> Result<T, (T, T)> {
self(t, item)
}
}
/// Create a new `Coalesce`.
pub fn coalesce<I, F>(iter: I, f: F) -> Coalesce<I, F>
where
I: Iterator,
{
Coalesce {
last: None,
iter,
f,
}
}
/// An iterator adaptor that removes repeated duplicates, determining equality using a comparison function.
///
/// See [`.dedup_by()`](crate::Itertools::dedup_by) or [`.dedup()`](crate::Itertools::dedup) for more information.
pub type DedupBy<I, Pred> = CoalesceBy<I, DedupPred2CoalescePred<Pred>, NoCount>;
#[derive(Clone)]
pub struct DedupPred2CoalescePred<DP>(DP);
impl<DP> fmt::Debug for DedupPred2CoalescePred<DP> {
debug_fmt_fields!(DedupPred2CoalescePred,);
}
pub trait DedupPredicate<T> {
// TODO replace by Fn(&T, &T)->bool once Rust supports it
fn dedup_pair(&mut self, a: &T, b: &T) -> bool;
}
impl<DP, T> CoalescePredicate<T, T> for DedupPred2CoalescePred<DP>
where
DP: DedupPredicate<T>,
{
fn coalesce_pair(&mut self, t: T, item: T) -> Result<T, (T, T)> {
if self.0.dedup_pair(&t, &item) {
Ok(t)
} else {
Err((t, item))
}
}
}
#[derive(Clone, Debug)]
pub struct DedupEq;
impl<T: PartialEq> DedupPredicate<T> for DedupEq {
fn dedup_pair(&mut self, a: &T, b: &T) -> bool {
a == b
}
}
impl<T, F: FnMut(&T, &T) -> bool> DedupPredicate<T> for F {
fn dedup_pair(&mut self, a: &T, b: &T) -> bool {
self(a, b)
}
}
/// Create a new `DedupBy`.
pub fn dedup_by<I, Pred>(iter: I, dedup_pred: Pred) -> DedupBy<I, Pred>
where
I: Iterator,
{
DedupBy {
last: None,
iter,
f: DedupPred2CoalescePred(dedup_pred),
}
}
/// An iterator adaptor that removes repeated duplicates.
///
/// See [`.dedup()`](crate::Itertools::dedup) for more information.
pub type Dedup<I> = DedupBy<I, DedupEq>;
/// Create a new `Dedup`.
pub fn dedup<I>(iter: I) -> Dedup<I>
where
I: Iterator,
{
dedup_by(iter, DedupEq)
}
/// An iterator adaptor that removes repeated duplicates, while keeping a count of how many
/// repeated elements were present. This will determine equality using a comparison function.
///
/// See [`.dedup_by_with_count()`](crate::Itertools::dedup_by_with_count) or
/// [`.dedup_with_count()`](crate::Itertools::dedup_with_count) for more information.
pub type DedupByWithCount<I, Pred> =
CoalesceBy<I, DedupPredWithCount2CoalescePred<Pred>, WithCount>;
#[derive(Clone, Debug)]
pub struct DedupPredWithCount2CoalescePred<DP>(DP);
impl<DP, T> CoalescePredicate<T, (usize, T)> for DedupPredWithCount2CoalescePred<DP>
where
DP: DedupPredicate<T>,
{
fn coalesce_pair(
&mut self,
(c, t): (usize, T),
item: T,
) -> Result<(usize, T), ((usize, T), (usize, T))> {
if self.0.dedup_pair(&t, &item) {
Ok((c + 1, t))
} else {
Err(((c, t), (1, item)))
}
}
}
/// An iterator adaptor that removes repeated duplicates, while keeping a count of how many
/// repeated elements were present.
///
/// See [`.dedup_with_count()`](crate::Itertools::dedup_with_count) for more information.
pub type DedupWithCount<I> = DedupByWithCount<I, DedupEq>;
/// Create a new `DedupByWithCount`.
pub fn dedup_by_with_count<I, Pred>(iter: I, dedup_pred: Pred) -> DedupByWithCount<I, Pred>
where
I: Iterator,
{
DedupByWithCount {
last: None,
iter,
f: DedupPredWithCount2CoalescePred(dedup_pred),
}
}
/// Create a new `DedupWithCount`.
pub fn dedup_with_count<I>(iter: I) -> DedupWithCount<I>
where
I: Iterator,
{
dedup_by_with_count(iter, DedupEq)
}

View File

@@ -0,0 +1,130 @@
use std::iter::FromIterator;
use std::marker::PhantomData;
#[derive(Clone, Debug)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct MapSpecialCase<I, F> {
pub(crate) iter: I,
pub(crate) f: F,
}
pub trait MapSpecialCaseFn<T> {
type Out;
fn call(&mut self, t: T) -> Self::Out;
}
impl<I, R> Iterator for MapSpecialCase<I, R>
where
I: Iterator,
R: MapSpecialCaseFn<I::Item>,
{
type Item = R::Out;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|i| self.f.call(i))
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
fn fold<Acc, Fold>(self, init: Acc, mut fold_f: Fold) -> Acc
where
Fold: FnMut(Acc, Self::Item) -> Acc,
{
let mut f = self.f;
self.iter.fold(init, move |acc, v| fold_f(acc, f.call(v)))
}
fn collect<C>(self) -> C
where
C: FromIterator<Self::Item>,
{
let mut f = self.f;
self.iter.map(move |v| f.call(v)).collect()
}
}
impl<I, R> DoubleEndedIterator for MapSpecialCase<I, R>
where
I: DoubleEndedIterator,
R: MapSpecialCaseFn<I::Item>,
{
fn next_back(&mut self) -> Option<Self::Item> {
self.iter.next_back().map(|i| self.f.call(i))
}
}
impl<I, R> ExactSizeIterator for MapSpecialCase<I, R>
where
I: ExactSizeIterator,
R: MapSpecialCaseFn<I::Item>,
{
}
/// An iterator adapter to apply a transformation within a nested `Result::Ok`.
///
/// See [`.map_ok()`](crate::Itertools::map_ok) for more information.
pub type MapOk<I, F> = MapSpecialCase<I, MapSpecialCaseFnOk<F>>;
impl<F, T, U, E> MapSpecialCaseFn<Result<T, E>> for MapSpecialCaseFnOk<F>
where
F: FnMut(T) -> U,
{
type Out = Result<U, E>;
fn call(&mut self, t: Result<T, E>) -> Self::Out {
t.map(|v| self.0(v))
}
}
#[derive(Clone)]
pub struct MapSpecialCaseFnOk<F>(F);
impl<F> std::fmt::Debug for MapSpecialCaseFnOk<F> {
debug_fmt_fields!(MapSpecialCaseFnOk,);
}
/// Create a new `MapOk` iterator.
pub fn map_ok<I, F, T, U, E>(iter: I, f: F) -> MapOk<I, F>
where
I: Iterator<Item = Result<T, E>>,
F: FnMut(T) -> U,
{
MapSpecialCase {
iter,
f: MapSpecialCaseFnOk(f),
}
}
/// An iterator adapter to apply `Into` conversion to each element.
///
/// See [`.map_into()`](crate::Itertools::map_into) for more information.
pub type MapInto<I, R> = MapSpecialCase<I, MapSpecialCaseFnInto<R>>;
impl<T: Into<U>, U> MapSpecialCaseFn<T> for MapSpecialCaseFnInto<U> {
type Out = U;
fn call(&mut self, t: T) -> Self::Out {
t.into()
}
}
pub struct MapSpecialCaseFnInto<U>(PhantomData<U>);
impl<U> std::fmt::Debug for MapSpecialCaseFnInto<U> {
debug_fmt_fields!(MapSpecialCaseFnInto, 0);
}
impl<U> Clone for MapSpecialCaseFnInto<U> {
#[inline]
fn clone(&self) -> Self {
Self(PhantomData)
}
}
/// Create a new [`MapInto`] iterator.
pub fn map_into<I, R>(iter: I) -> MapInto<I, R> {
MapSpecialCase {
iter,
f: MapSpecialCaseFnInto(PhantomData),
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,231 @@
#![cfg(feature = "use_alloc")]
use Option::{self as State, None as ProductEnded, Some as ProductInProgress};
use Option::{self as CurrentItems, None as NotYetPopulated, Some as Populated};
use alloc::vec::Vec;
use crate::size_hint;
#[derive(Clone)]
/// An iterator adaptor that iterates over the cartesian product of
/// multiple iterators of type `I`.
///
/// An iterator element type is `Vec<I::Item>`.
///
/// See [`.multi_cartesian_product()`](crate::Itertools::multi_cartesian_product)
/// for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct MultiProduct<I>(State<MultiProductInner<I>>)
where
I: Iterator + Clone,
I::Item: Clone;
#[derive(Clone)]
/// Internals for `MultiProduct`.
struct MultiProductInner<I>
where
I: Iterator + Clone,
I::Item: Clone,
{
/// Holds the iterators.
iters: Vec<MultiProductIter<I>>,
/// Not populated at the beginning then it holds the current item of each iterator.
cur: CurrentItems<Vec<I::Item>>,
}
impl<I> std::fmt::Debug for MultiProduct<I>
where
I: Iterator + Clone + std::fmt::Debug,
I::Item: Clone + std::fmt::Debug,
{
debug_fmt_fields!(MultiProduct, 0);
}
impl<I> std::fmt::Debug for MultiProductInner<I>
where
I: Iterator + Clone + std::fmt::Debug,
I::Item: Clone + std::fmt::Debug,
{
debug_fmt_fields!(MultiProductInner, iters, cur);
}
/// Create a new cartesian product iterator over an arbitrary number
/// of iterators of the same type.
///
/// Iterator element is of type `Vec<H::Item::Item>`.
pub fn multi_cartesian_product<H>(iters: H) -> MultiProduct<<H::Item as IntoIterator>::IntoIter>
where
H: Iterator,
H::Item: IntoIterator,
<H::Item as IntoIterator>::IntoIter: Clone,
<H::Item as IntoIterator>::Item: Clone,
{
let inner = MultiProductInner {
iters: iters
.map(|i| MultiProductIter::new(i.into_iter()))
.collect(),
cur: NotYetPopulated,
};
MultiProduct(ProductInProgress(inner))
}
#[derive(Clone, Debug)]
/// Holds the state of a single iterator within a `MultiProduct`.
struct MultiProductIter<I>
where
I: Iterator + Clone,
I::Item: Clone,
{
iter: I,
iter_orig: I,
}
impl<I> MultiProductIter<I>
where
I: Iterator + Clone,
I::Item: Clone,
{
fn new(iter: I) -> Self {
Self {
iter: iter.clone(),
iter_orig: iter,
}
}
}
impl<I> Iterator for MultiProduct<I>
where
I: Iterator + Clone,
I::Item: Clone,
{
type Item = Vec<I::Item>;
fn next(&mut self) -> Option<Self::Item> {
// This fuses the iterator.
let inner = self.0.as_mut()?;
match &mut inner.cur {
Populated(values) => {
debug_assert!(!inner.iters.is_empty());
// Find (from the right) a non-finished iterator and
// reset the finished ones encountered.
for (iter, item) in inner.iters.iter_mut().zip(values.iter_mut()).rev() {
if let Some(new) = iter.iter.next() {
*item = new;
return Some(values.clone());
} else {
iter.iter = iter.iter_orig.clone();
// `cur` is populated so the untouched `iter_orig` can not be empty.
*item = iter.iter.next().unwrap();
}
}
self.0 = ProductEnded;
None
}
// Only the first time.
NotYetPopulated => {
let next: Option<Vec<_>> = inner.iters.iter_mut().map(|i| i.iter.next()).collect();
if next.is_none() || inner.iters.is_empty() {
// This cartesian product had at most one item to generate and now ends.
self.0 = ProductEnded;
} else {
inner.cur.clone_from(&next);
}
next
}
}
}
fn count(self) -> usize {
match self.0 {
ProductEnded => 0,
// The iterator is fresh so the count is the product of the length of each iterator:
// - If one of them is empty, stop counting.
// - Less `count()` calls than the general case.
ProductInProgress(MultiProductInner {
iters,
cur: NotYetPopulated,
}) => iters
.into_iter()
.map(|iter| iter.iter_orig.count())
.try_fold(1, |product, count| {
if count == 0 {
None
} else {
Some(product * count)
}
})
.unwrap_or_default(),
// The general case.
ProductInProgress(MultiProductInner {
iters,
cur: Populated(_),
}) => iters.into_iter().fold(0, |mut acc, iter| {
if acc != 0 {
acc *= iter.iter_orig.count();
}
acc + iter.iter.count()
}),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
match &self.0 {
ProductEnded => (0, Some(0)),
ProductInProgress(MultiProductInner {
iters,
cur: NotYetPopulated,
}) => iters
.iter()
.map(|iter| iter.iter_orig.size_hint())
.fold((1, Some(1)), size_hint::mul),
ProductInProgress(MultiProductInner {
iters,
cur: Populated(_),
}) => {
if let [first, tail @ ..] = &iters[..] {
tail.iter().fold(first.iter.size_hint(), |mut sh, iter| {
sh = size_hint::mul(sh, iter.iter_orig.size_hint());
size_hint::add(sh, iter.iter.size_hint())
})
} else {
// Since it is populated, this cartesian product has started so `iters` is not empty.
unreachable!()
}
}
}
}
fn last(self) -> Option<Self::Item> {
let MultiProductInner { iters, cur } = self.0?;
// Collect the last item of each iterator of the product.
if let Populated(values) = cur {
let mut count = iters.len();
let last = iters
.into_iter()
.zip(values)
.map(|(i, value)| {
i.iter.last().unwrap_or_else(|| {
// The iterator is empty, use its current `value`.
count -= 1;
value
})
})
.collect();
if count == 0 {
// `values` was the last item.
None
} else {
Some(last)
}
} else {
iters.into_iter().map(|i| i.iter.last()).collect()
}
}
}
impl<I> std::iter::FusedIterator for MultiProduct<I>
where
I: Iterator + Clone,
I::Item: Clone,
{
}