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,
{
}

View File

@@ -0,0 +1,243 @@
use std::fmt;
use std::iter::FusedIterator;
use super::lazy_buffer::LazyBuffer;
use alloc::vec::Vec;
use crate::adaptors::checked_binomial;
/// An iterator to iterate through all the `k`-length combinations in an iterator.
///
/// See [`.combinations()`](crate::Itertools::combinations) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct Combinations<I: Iterator> {
indices: Vec<usize>,
pool: LazyBuffer<I>,
first: bool,
}
impl<I> Clone for Combinations<I>
where
I: Clone + Iterator,
I::Item: Clone,
{
clone_fields!(indices, pool, first);
}
impl<I> fmt::Debug for Combinations<I>
where
I: Iterator + fmt::Debug,
I::Item: fmt::Debug,
{
debug_fmt_fields!(Combinations, indices, pool, first);
}
/// Create a new `Combinations` from a clonable iterator.
pub fn combinations<I>(iter: I, k: usize) -> Combinations<I>
where
I: Iterator,
{
Combinations {
indices: (0..k).collect(),
pool: LazyBuffer::new(iter),
first: true,
}
}
impl<I: Iterator> Combinations<I> {
/// Returns the length of a combination produced by this iterator.
#[inline]
pub fn k(&self) -> usize {
self.indices.len()
}
/// Returns the (current) length of the pool from which combination elements are
/// selected. This value can change between invocations of [`next`](Combinations::next).
#[inline]
pub fn n(&self) -> usize {
self.pool.len()
}
/// Returns a reference to the source pool.
#[inline]
pub(crate) fn src(&self) -> &LazyBuffer<I> {
&self.pool
}
/// Resets this `Combinations` back to an initial state for combinations of length
/// `k` over the same pool data source. If `k` is larger than the current length
/// of the data pool an attempt is made to prefill the pool so that it holds `k`
/// elements.
pub(crate) fn reset(&mut self, k: usize) {
self.first = true;
if k < self.indices.len() {
self.indices.truncate(k);
for i in 0..k {
self.indices[i] = i;
}
} else {
for i in 0..self.indices.len() {
self.indices[i] = i;
}
self.indices.extend(self.indices.len()..k);
self.pool.prefill(k);
}
}
pub(crate) fn n_and_count(self) -> (usize, usize) {
let Self {
indices,
pool,
first,
} = self;
let n = pool.count();
(n, remaining_for(n, first, &indices).unwrap())
}
/// Initialises the iterator by filling a buffer with elements from the
/// iterator. Returns true if there are no combinations, false otherwise.
fn init(&mut self) -> bool {
self.pool.prefill(self.k());
let done = self.k() > self.n();
if !done {
self.first = false;
}
done
}
/// Increments indices representing the combination to advance to the next
/// (in lexicographic order by increasing sequence) combination. For example
/// if we have n=4 & k=2 then `[0, 1] -> [0, 2] -> [0, 3] -> [1, 2] -> ...`
///
/// Returns true if we've run out of combinations, false otherwise.
fn increment_indices(&mut self) -> bool {
if self.indices.is_empty() {
return true; // Done
}
// Scan from the end, looking for an index to increment
let mut i: usize = self.indices.len() - 1;
// Check if we need to consume more from the iterator
if self.indices[i] == self.pool.len() - 1 {
self.pool.get_next(); // may change pool size
}
while self.indices[i] == i + self.pool.len() - self.indices.len() {
if i > 0 {
i -= 1;
} else {
// Reached the last combination
return true;
}
}
// Increment index, and reset the ones to its right
self.indices[i] += 1;
for j in i + 1..self.indices.len() {
self.indices[j] = self.indices[j - 1] + 1;
}
// If we've made it this far, we haven't run out of combos
false
}
/// Returns the n-th item or the number of successful steps.
pub(crate) fn try_nth(&mut self, n: usize) -> Result<<Self as Iterator>::Item, usize>
where
I::Item: Clone,
{
let done = if self.first {
self.init()
} else {
self.increment_indices()
};
if done {
return Err(0);
}
for i in 0..n {
if self.increment_indices() {
return Err(i + 1);
}
}
Ok(self.pool.get_at(&self.indices))
}
}
impl<I> Iterator for Combinations<I>
where
I: Iterator,
I::Item: Clone,
{
type Item = Vec<I::Item>;
fn next(&mut self) -> Option<Self::Item> {
let done = if self.first {
self.init()
} else {
self.increment_indices()
};
if done {
return None;
}
Some(self.pool.get_at(&self.indices))
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.try_nth(n).ok()
}
fn size_hint(&self) -> (usize, Option<usize>) {
let (mut low, mut upp) = self.pool.size_hint();
low = remaining_for(low, self.first, &self.indices).unwrap_or(usize::MAX);
upp = upp.and_then(|upp| remaining_for(upp, self.first, &self.indices));
(low, upp)
}
#[inline]
fn count(self) -> usize {
self.n_and_count().1
}
}
impl<I> FusedIterator for Combinations<I>
where
I: Iterator,
I::Item: Clone,
{
}
/// For a given size `n`, return the count of remaining combinations or None if it would overflow.
fn remaining_for(n: usize, first: bool, indices: &[usize]) -> Option<usize> {
let k = indices.len();
if n < k {
Some(0)
} else if first {
checked_binomial(n, k)
} else {
// https://en.wikipedia.org/wiki/Combinatorial_number_system
// http://www.site.uottawa.ca/~lucia/courses/5165-09/GenCombObj.pdf
// The combinations generated after the current one can be counted by counting as follows:
// - The subsequent combinations that differ in indices[0]:
// If subsequent combinations differ in indices[0], then their value for indices[0]
// must be at least 1 greater than the current indices[0].
// As indices is strictly monotonically sorted, this means we can effectively choose k values
// from (n - 1 - indices[0]), leading to binomial(n - 1 - indices[0], k) possibilities.
// - The subsequent combinations with same indices[0], but differing indices[1]:
// Here we can choose k - 1 values from (n - 1 - indices[1]) values,
// leading to binomial(n - 1 - indices[1], k - 1) possibilities.
// - (...)
// - The subsequent combinations with same indices[0..=i], but differing indices[i]:
// Here we can choose k - i values from (n - 1 - indices[i]) values: binomial(n - 1 - indices[i], k - i).
// Since subsequent combinations can in any index, we must sum up the aforementioned binomial coefficients.
// Below, `n0` resembles indices[i].
indices.iter().enumerate().try_fold(0usize, |sum, (i, n0)| {
sum.checked_add(checked_binomial(n - 1 - *n0, k - i)?)
})
}
}

View File

@@ -0,0 +1,192 @@
use alloc::boxed::Box;
use alloc::vec::Vec;
use std::fmt;
use std::iter::FusedIterator;
use super::lazy_buffer::LazyBuffer;
use crate::adaptors::checked_binomial;
/// An iterator to iterate through all the `n`-length combinations in an iterator, with replacement.
///
/// See [`.combinations_with_replacement()`](crate::Itertools::combinations_with_replacement)
/// for more information.
#[derive(Clone)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct CombinationsWithReplacement<I>
where
I: Iterator,
I::Item: Clone,
{
indices: Box<[usize]>,
pool: LazyBuffer<I>,
first: bool,
}
impl<I> fmt::Debug for CombinationsWithReplacement<I>
where
I: Iterator + fmt::Debug,
I::Item: fmt::Debug + Clone,
{
debug_fmt_fields!(CombinationsWithReplacement, indices, pool, first);
}
/// Create a new `CombinationsWithReplacement` from a clonable iterator.
pub fn combinations_with_replacement<I>(iter: I, k: usize) -> CombinationsWithReplacement<I>
where
I: Iterator,
I::Item: Clone,
{
let indices = alloc::vec![0; k].into_boxed_slice();
let pool: LazyBuffer<I> = LazyBuffer::new(iter);
CombinationsWithReplacement {
indices,
pool,
first: true,
}
}
impl<I> CombinationsWithReplacement<I>
where
I: Iterator,
I::Item: Clone,
{
/// Increments indices representing the combination to advance to the next
/// (in lexicographic order by increasing sequence) combination.
///
/// Returns true if we've run out of combinations, false otherwise.
fn increment_indices(&mut self) -> bool {
// Check if we need to consume more from the iterator
// This will run while we increment our first index digit
self.pool.get_next();
// Work out where we need to update our indices
let mut increment = None;
for (i, indices_int) in self.indices.iter().enumerate().rev() {
if *indices_int < self.pool.len() - 1 {
increment = Some((i, indices_int + 1));
break;
}
}
match increment {
// If we can update the indices further
Some((increment_from, increment_value)) => {
// We need to update the rightmost non-max value
// and all those to the right
for i in &mut self.indices[increment_from..] {
*i = increment_value;
}
// TODO: once MSRV >= 1.50, use `fill` instead:
// self.indices[increment_from..].fill(increment_value);
false
}
// Otherwise, we're done
None => true,
}
}
}
impl<I> Iterator for CombinationsWithReplacement<I>
where
I: Iterator,
I::Item: Clone,
{
type Item = Vec<I::Item>;
fn next(&mut self) -> Option<Self::Item> {
if self.first {
// In empty edge cases, stop iterating immediately
if !(self.indices.is_empty() || self.pool.get_next()) {
return None;
}
self.first = false;
} else if self.increment_indices() {
return None;
}
Some(self.pool.get_at(&self.indices))
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
if self.first {
// In empty edge cases, stop iterating immediately
if !(self.indices.is_empty() || self.pool.get_next()) {
return None;
}
self.first = false;
} else if self.increment_indices() {
return None;
}
for _ in 0..n {
if self.increment_indices() {
return None;
}
}
Some(self.pool.get_at(&self.indices))
}
fn size_hint(&self) -> (usize, Option<usize>) {
let (mut low, mut upp) = self.pool.size_hint();
low = remaining_for(low, self.first, &self.indices).unwrap_or(usize::MAX);
upp = upp.and_then(|upp| remaining_for(upp, self.first, &self.indices));
(low, upp)
}
fn count(self) -> usize {
let Self {
indices,
pool,
first,
} = self;
let n = pool.count();
remaining_for(n, first, &indices).unwrap()
}
}
impl<I> FusedIterator for CombinationsWithReplacement<I>
where
I: Iterator,
I::Item: Clone,
{
}
/// For a given size `n`, return the count of remaining combinations with replacement or None if it would overflow.
fn remaining_for(n: usize, first: bool, indices: &[usize]) -> Option<usize> {
// With a "stars and bars" representation, choose k values with replacement from n values is
// like choosing k out of k + n 1 positions (hence binomial(k + n - 1, k) possibilities)
// to place k stars and therefore n - 1 bars.
// Example (n=4, k=6): ***|*||** represents [0,0,0,1,3,3].
let count = |n: usize, k: usize| {
let positions = if n == 0 {
k.saturating_sub(1)
} else {
(n - 1).checked_add(k)?
};
checked_binomial(positions, k)
};
let k = indices.len();
if first {
count(n, k)
} else {
// The algorithm is similar to the one for combinations *without replacement*,
// except we choose values *with replacement* and indices are *non-strictly* monotonically sorted.
// The combinations generated after the current one can be counted by counting as follows:
// - The subsequent combinations that differ in indices[0]:
// If subsequent combinations differ in indices[0], then their value for indices[0]
// must be at least 1 greater than the current indices[0].
// As indices is monotonically sorted, this means we can effectively choose k values with
// replacement from (n - 1 - indices[0]), leading to count(n - 1 - indices[0], k) possibilities.
// - The subsequent combinations with same indices[0], but differing indices[1]:
// Here we can choose k - 1 values with replacement from (n - 1 - indices[1]) values,
// leading to count(n - 1 - indices[1], k - 1) possibilities.
// - (...)
// - The subsequent combinations with same indices[0..=i], but differing indices[i]:
// Here we can choose k - i values with replacement from (n - 1 - indices[i]) values: count(n - 1 - indices[i], k - i).
// Since subsequent combinations can in any index, we must sum up the aforementioned binomial coefficients.
// Below, `n0` resembles indices[i].
indices.iter().enumerate().try_fold(0usize, |sum, (i, n0)| {
sum.checked_add(count(n - 1 - *n0, k - i)?)
})
}
}

View File

@@ -0,0 +1,30 @@
use crate::Itertools;
/// Combine all an iterator's elements into one element by using [`Extend`].
///
/// [`IntoIterator`]-enabled version of [`Itertools::concat`].
///
/// This combinator will extend the first item with each of the rest of the
/// items of the iterator. If the iterator is empty, the default value of
/// `I::Item` is returned.
///
/// ```rust
/// use itertools::concat;
///
/// let input = vec![vec![1], vec![2, 3], vec![4, 5, 6]];
/// assert_eq!(concat(input), vec![1, 2, 3, 4, 5, 6]);
/// ```
pub fn concat<I>(iterable: I) -> I::Item
where
I: IntoIterator,
I::Item: Extend<<<I as IntoIterator>::Item as IntoIterator>::Item> + IntoIterator + Default,
{
#[allow(deprecated)] //TODO: once msrv hits 1.51. replace `fold1` with `reduce`
iterable
.into_iter()
.fold1(|mut a, b| {
a.extend(b);
a
})
.unwrap_or_default()
}

View File

@@ -0,0 +1,58 @@
macro_rules! impl_cons_iter(
($_A:ident, $_B:ident, ) => (); // stop
($A:ident, $($B:ident,)*) => (
impl_cons_iter!($($B,)*);
#[allow(non_snake_case)]
impl<X, Iter, $($B),*> Iterator for ConsTuples<Iter, (($($B,)*), X)>
where Iter: Iterator<Item = (($($B,)*), X)>,
{
type Item = ($($B,)* X, );
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|(($($B,)*), x)| ($($B,)* x, ))
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
fn fold<Acc, Fold>(self, accum: Acc, mut f: Fold) -> Acc
where Fold: FnMut(Acc, Self::Item) -> Acc,
{
self.iter.fold(accum, move |acc, (($($B,)*), x)| f(acc, ($($B,)* x, )))
}
}
);
);
impl_cons_iter!(A, B, C, D, E, F, G, H, I, J, K, L,);
/// An iterator that maps an iterator of tuples like
/// `((A, B), C)` to an iterator of `(A, B, C)`.
///
/// Used by the `iproduct!()` macro.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Debug)]
pub struct ConsTuples<I, J>
where
I: Iterator<Item = J>,
{
iter: I,
}
impl<I, J> Clone for ConsTuples<I, J>
where
I: Clone + Iterator<Item = J>,
{
clone_fields!(iter);
}
/// Create an iterator that maps for example iterators of
/// `((A, B), C)` to `(A, B, C)`.
pub fn cons_tuples<I, J>(iterable: I) -> ConsTuples<I::IntoIter, J>
where
I: IntoIterator<Item = J>,
{
ConsTuples {
iter: iterable.into_iter(),
}
}

104
vendor/itertools-0.13.0/src/diff.rs vendored Normal file
View File

@@ -0,0 +1,104 @@
//! "Diff"ing iterators for caching elements to sequential collections without requiring the new
//! elements' iterator to be `Clone`.
//!
//! - [`Diff`] (produced by the [`diff_with`] function)
//! describes the difference between two non-`Clone` iterators `I` and `J` after breaking ASAP from
//! a lock-step comparison.
use std::fmt;
use crate::free::put_back;
use crate::structs::PutBack;
/// A type returned by the [`diff_with`] function.
///
/// `Diff` represents the way in which the elements yielded by the iterator `I` differ to some
/// iterator `J`.
pub enum Diff<I, J>
where
I: Iterator,
J: Iterator,
{
/// The index of the first non-matching element along with both iterator's remaining elements
/// starting with the first mis-match.
FirstMismatch(usize, PutBack<I>, PutBack<J>),
/// The total number of elements that were in `J` along with the remaining elements of `I`.
Shorter(usize, PutBack<I>),
/// The total number of elements that were in `I` along with the remaining elements of `J`.
Longer(usize, PutBack<J>),
}
impl<I, J> fmt::Debug for Diff<I, J>
where
I: Iterator,
J: Iterator,
PutBack<I>: fmt::Debug,
PutBack<J>: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::FirstMismatch(idx, i, j) => f
.debug_tuple("FirstMismatch")
.field(idx)
.field(i)
.field(j)
.finish(),
Self::Shorter(idx, i) => f.debug_tuple("Shorter").field(idx).field(i).finish(),
Self::Longer(idx, j) => f.debug_tuple("Longer").field(idx).field(j).finish(),
}
}
}
impl<I, J> Clone for Diff<I, J>
where
I: Iterator,
J: Iterator,
PutBack<I>: Clone,
PutBack<J>: Clone,
{
fn clone(&self) -> Self {
match self {
Self::FirstMismatch(idx, i, j) => Self::FirstMismatch(*idx, i.clone(), j.clone()),
Self::Shorter(idx, i) => Self::Shorter(*idx, i.clone()),
Self::Longer(idx, j) => Self::Longer(*idx, j.clone()),
}
}
}
/// Compares every element yielded by both `i` and `j` with the given function in lock-step and
/// returns a [`Diff`] which describes how `j` differs from `i`.
///
/// If the number of elements yielded by `j` is less than the number of elements yielded by `i`,
/// the number of `j` elements yielded will be returned along with `i`'s remaining elements as
/// `Diff::Shorter`.
///
/// If the two elements of a step differ, the index of those elements along with the remaining
/// elements of both `i` and `j` are returned as `Diff::FirstMismatch`.
///
/// If `i` becomes exhausted before `j` becomes exhausted, the number of elements in `i` along with
/// the remaining `j` elements will be returned as `Diff::Longer`.
pub fn diff_with<I, J, F>(i: I, j: J, mut is_equal: F) -> Option<Diff<I::IntoIter, J::IntoIter>>
where
I: IntoIterator,
J: IntoIterator,
F: FnMut(&I::Item, &J::Item) -> bool,
{
let mut i = i.into_iter();
let mut j = j.into_iter();
let mut idx = 0;
while let Some(i_elem) = i.next() {
match j.next() {
None => return Some(Diff::Shorter(idx, put_back(i).with_value(i_elem))),
Some(j_elem) => {
if !is_equal(&i_elem, &j_elem) {
let remaining_i = put_back(i).with_value(i_elem);
let remaining_j = put_back(j).with_value(j_elem);
return Some(Diff::FirstMismatch(idx, remaining_i, remaining_j));
}
}
}
idx += 1;
}
j.next()
.map(|j_elem| Diff::Longer(idx, put_back(j).with_value(j_elem)))
}

View File

@@ -0,0 +1,216 @@
use std::hash::Hash;
mod private {
use std::collections::HashMap;
use std::fmt;
use std::hash::Hash;
#[derive(Clone)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct DuplicatesBy<I: Iterator, Key, F> {
pub(crate) iter: I,
pub(crate) meta: Meta<Key, F>,
}
impl<I, V, F> fmt::Debug for DuplicatesBy<I, V, F>
where
I: Iterator + fmt::Debug,
V: fmt::Debug + Hash + Eq,
{
debug_fmt_fields!(DuplicatesBy, iter, meta.used);
}
impl<I: Iterator, Key: Eq + Hash, F> DuplicatesBy<I, Key, F> {
pub(crate) fn new(iter: I, key_method: F) -> Self {
Self {
iter,
meta: Meta {
used: HashMap::new(),
pending: 0,
key_method,
},
}
}
}
#[derive(Clone)]
pub struct Meta<Key, F> {
used: HashMap<Key, bool>,
pending: usize,
key_method: F,
}
impl<Key, F> Meta<Key, F>
where
Key: Eq + Hash,
{
/// Takes an item and returns it back to the caller if it's the second time we see it.
/// Otherwise the item is consumed and None is returned
#[inline(always)]
fn filter<I>(&mut self, item: I) -> Option<I>
where
F: KeyMethod<Key, I>,
{
let kv = self.key_method.make(item);
match self.used.get_mut(kv.key_ref()) {
None => {
self.used.insert(kv.key(), false);
self.pending += 1;
None
}
Some(true) => None,
Some(produced) => {
*produced = true;
self.pending -= 1;
Some(kv.value())
}
}
}
}
impl<I, Key, F> Iterator for DuplicatesBy<I, Key, F>
where
I: Iterator,
Key: Eq + Hash,
F: KeyMethod<Key, I::Item>,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
let Self { iter, meta } = self;
iter.find_map(|v| meta.filter(v))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let (_, hi) = self.iter.size_hint();
let hi = hi.map(|hi| {
if hi <= self.meta.pending {
// fewer or equally many iter-remaining elements than pending elements
// => at most, each iter-remaining element is matched
hi
} else {
// fewer pending elements than iter-remaining elements
// => at most:
// * each pending element is matched
// * the other iter-remaining elements come in pairs
self.meta.pending + (hi - self.meta.pending) / 2
}
});
// The lower bound is always 0 since we might only get unique items from now on
(0, hi)
}
}
impl<I, Key, F> DoubleEndedIterator for DuplicatesBy<I, Key, F>
where
I: DoubleEndedIterator,
Key: Eq + Hash,
F: KeyMethod<Key, I::Item>,
{
fn next_back(&mut self) -> Option<Self::Item> {
let Self { iter, meta } = self;
iter.rev().find_map(|v| meta.filter(v))
}
}
/// A keying method for use with `DuplicatesBy`
pub trait KeyMethod<K, V> {
type Container: KeyXorValue<K, V>;
fn make(&mut self, value: V) -> Self::Container;
}
/// Apply the identity function to elements before checking them for equality.
#[derive(Debug, Clone)]
pub struct ById;
impl<V> KeyMethod<V, V> for ById {
type Container = JustValue<V>;
fn make(&mut self, v: V) -> Self::Container {
JustValue(v)
}
}
/// Apply a user-supplied function to elements before checking them for equality.
#[derive(Clone)]
pub struct ByFn<F>(pub(crate) F);
impl<F> fmt::Debug for ByFn<F> {
debug_fmt_fields!(ByFn,);
}
impl<K, V, F> KeyMethod<K, V> for ByFn<F>
where
F: FnMut(&V) -> K,
{
type Container = KeyValue<K, V>;
fn make(&mut self, v: V) -> Self::Container {
KeyValue((self.0)(&v), v)
}
}
// Implementors of this trait can hold onto a key and a value but only give access to one of them
// at a time. This allows the key and the value to be the same value internally
pub trait KeyXorValue<K, V> {
fn key_ref(&self) -> &K;
fn key(self) -> K;
fn value(self) -> V;
}
#[derive(Debug)]
pub struct KeyValue<K, V>(K, V);
impl<K, V> KeyXorValue<K, V> for KeyValue<K, V> {
fn key_ref(&self) -> &K {
&self.0
}
fn key(self) -> K {
self.0
}
fn value(self) -> V {
self.1
}
}
#[derive(Debug)]
pub struct JustValue<V>(V);
impl<V> KeyXorValue<V, V> for JustValue<V> {
fn key_ref(&self) -> &V {
&self.0
}
fn key(self) -> V {
self.0
}
fn value(self) -> V {
self.0
}
}
}
/// An iterator adapter to filter for duplicate elements.
///
/// See [`.duplicates_by()`](crate::Itertools::duplicates_by) for more information.
pub type DuplicatesBy<I, V, F> = private::DuplicatesBy<I, V, private::ByFn<F>>;
/// Create a new `DuplicatesBy` iterator.
pub fn duplicates_by<I, Key, F>(iter: I, f: F) -> DuplicatesBy<I, Key, F>
where
Key: Eq + Hash,
F: FnMut(&I::Item) -> Key,
I: Iterator,
{
DuplicatesBy::new(iter, private::ByFn(f))
}
/// An iterator adapter to filter out duplicate elements.
///
/// See [`.duplicates()`](crate::Itertools::duplicates) for more information.
pub type Duplicates<I> = private::DuplicatesBy<I, <I as Iterator>::Item, private::ById>;
/// Create a new `Duplicates` iterator.
pub fn duplicates<I>(iter: I) -> Duplicates<I>
where
I: Iterator,
I::Item: Eq + Hash,
{
Duplicates::new(iter, private::ById)
}

View File

@@ -0,0 +1,514 @@
use core::ops::{Deref, DerefMut};
use crate::EitherOrBoth::*;
use either::Either;
/// Value that either holds a single A or B, or both.
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub enum EitherOrBoth<A, B = A> {
/// Both values are present.
Both(A, B),
/// Only the left value of type `A` is present.
Left(A),
/// Only the right value of type `B` is present.
Right(B),
}
impl<A, B> EitherOrBoth<A, B> {
/// If `Left`, or `Both`, return true. Otherwise, return false.
pub fn has_left(&self) -> bool {
self.as_ref().left().is_some()
}
/// If `Right`, or `Both`, return true, otherwise, return false.
pub fn has_right(&self) -> bool {
self.as_ref().right().is_some()
}
/// If `Left`, return true. Otherwise, return false.
/// Exclusive version of [`has_left`](EitherOrBoth::has_left).
pub fn is_left(&self) -> bool {
matches!(self, Left(_))
}
/// If `Right`, return true. Otherwise, return false.
/// Exclusive version of [`has_right`](EitherOrBoth::has_right).
pub fn is_right(&self) -> bool {
matches!(self, Right(_))
}
/// 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`.
pub fn left(self) -> Option<A> {
match self {
Left(left) | Both(left, _) => Some(left),
_ => 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),
_ => None,
}
}
/// Return tuple of options corresponding to the left and right value respectively
///
/// If `Left` return `(Some(..), None)`, if `Right` return `(None,Some(..))`, else return
/// `(Some(..),Some(..))`
pub fn left_and_right(self) -> (Option<A>, Option<B>) {
self.map_any(Some, Some).or_default()
}
/// 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)),
_ => None,
}
}
/// 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 {
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 A, &mut B>`.
pub fn as_mut(&mut self) -> EitherOrBoth<&mut A, &mut B> {
match *self {
Left(ref mut left) => Left(left),
Right(ref mut right) => Right(right),
Both(ref mut left, ref mut right) => Both(left, right),
}
}
/// 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 {
Left(a) => Right(a),
Right(b) => Left(b),
Both(a, b) => Both(b, a),
}
}
/// Apply the function `f` on the value `a` in `Left(a)` or `Both(a, b)` variants. If it is
/// present rewrapping the result in `self`'s original variant.
pub fn map_left<F, M>(self, f: F) -> EitherOrBoth<M, B>
where
F: FnOnce(A) -> M,
{
match self {
Both(a, b) => Both(f(a), b),
Left(a) => Left(f(a)),
Right(b) => Right(b),
}
}
/// Apply the function `f` on the value `b` in `Right(b)` or `Both(a, b)` variants.
/// If it is present rewrapping the result in `self`'s original variant.
pub fn map_right<F, M>(self, f: F) -> EitherOrBoth<A, M>
where
F: FnOnce(B) -> M,
{
match self {
Left(a) => Left(a),
Right(b) => Right(f(b)),
Both(a, b) => Both(a, f(b)),
}
}
/// Apply the functions `f` and `g` on the value `a` and `b` respectively;
/// found in `Left(a)`, `Right(b)`, or `Both(a, b)` variants.
/// The Result is rewrapped `self`'s original variant.
pub fn map_any<F, L, G, R>(self, f: F, g: G) -> EitherOrBoth<L, R>
where
F: FnOnce(A) -> L,
G: FnOnce(B) -> R,
{
match self {
Left(a) => Left(f(a)),
Right(b) => Right(g(b)),
Both(a, b) => Both(f(a), g(b)),
}
}
/// Apply the function `f` on the value `a` in `Left(a)` or `Both(a, _)` variants if it is
/// present.
pub fn left_and_then<F, L>(self, f: F) -> EitherOrBoth<L, B>
where
F: FnOnce(A) -> EitherOrBoth<L, B>,
{
match self {
Left(a) | Both(a, _) => f(a),
Right(b) => Right(b),
}
}
/// Apply the function `f` on the value `b`
/// in `Right(b)` or `Both(_, b)` variants if it is present.
pub fn right_and_then<F, R>(self, f: F) -> EitherOrBoth<A, R>
where
F: FnOnce(B) -> EitherOrBoth<A, R>,
{
match self {
Left(a) => Left(a),
Right(b) | Both(_, b) => f(b),
}
}
/// Returns a tuple consisting of the `l` and `r` in `Both(l, r)`, if present.
/// Otherwise, returns the wrapped value for the present element, and the supplied
/// value for the other. The first (`l`) argument is used for a missing `Left`
/// value. The second (`r`) argument is used for a missing `Right` value.
///
/// Arguments passed to `or` are eagerly evaluated; if you are passing
/// the result of a function call, it is recommended to use [`or_else`],
/// which is lazily evaluated.
///
/// [`or_else`]: EitherOrBoth::or_else
///
/// # Examples
///
/// ```
/// # use itertools::EitherOrBoth;
/// assert_eq!(EitherOrBoth::Both("tree", 1).or("stone", 5), ("tree", 1));
/// assert_eq!(EitherOrBoth::Left("tree").or("stone", 5), ("tree", 5));
/// assert_eq!(EitherOrBoth::Right(1).or("stone", 5), ("stone", 1));
/// ```
pub fn or(self, l: A, r: B) -> (A, B) {
match self {
Left(inner_l) => (inner_l, r),
Right(inner_r) => (l, inner_r),
Both(inner_l, inner_r) => (inner_l, inner_r),
}
}
/// Returns a tuple consisting of the `l` and `r` in `Both(l, r)`, if present.
/// Otherwise, returns the wrapped value for the present element, and the [`default`](Default::default)
/// for the other.
pub fn or_default(self) -> (A, B)
where
A: Default,
B: Default,
{
match self {
Left(l) => (l, B::default()),
Right(r) => (A::default(), r),
Both(l, r) => (l, r),
}
}
/// Returns a tuple consisting of the `l` and `r` in `Both(l, r)`, if present.
/// Otherwise, returns the wrapped value for the present element, and computes the
/// missing value with the supplied closure. The first argument (`l`) is used for a
/// missing `Left` value. The second argument (`r`) is used for a missing `Right` value.
///
/// # Examples
///
/// ```
/// # use itertools::EitherOrBoth;
/// let k = 10;
/// assert_eq!(EitherOrBoth::Both("tree", 1).or_else(|| "stone", || 2 * k), ("tree", 1));
/// assert_eq!(EitherOrBoth::Left("tree").or_else(|| "stone", || 2 * k), ("tree", 20));
/// assert_eq!(EitherOrBoth::Right(1).or_else(|| "stone", || 2 * k), ("stone", 1));
/// ```
pub fn or_else<L: FnOnce() -> A, R: FnOnce() -> B>(self, l: L, r: R) -> (A, B) {
match self {
Left(inner_l) => (inner_l, r()),
Right(inner_r) => (l(), inner_r),
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 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.
///
/// This function can be used to preferrably extract the left resp. right value,
/// but fall back to the other (i.e. right resp. left) if the preferred one is not present.
///
/// # 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);
///
/// // Extract the left value if present, fall back to the right otherwise.
/// assert_eq!(EitherOrBoth::Left("left").reduce(|l, _r| l), "left");
/// assert_eq!(EitherOrBoth::Right("right").reduce(|l, _r| l), "right");
/// assert_eq!(EitherOrBoth::Both("left", "right").reduce(|l, _r| l), "left");
/// ```
pub fn reduce<F>(self, f: F) -> T
where
F: FnOnce(T, T) -> T,
{
match self {
Left(a) => a,
Right(b) => b,
Both(a, b) => f(a, b),
}
}
}
impl<A, B> From<EitherOrBoth<A, B>> for Option<Either<A, B>> {
fn from(value: EitherOrBoth<A, B>) -> Self {
match value {
Left(l) => Some(Either::Left(l)),
Right(r) => Some(Either::Right(r)),
Both(..) => None,
}
}
}
impl<A, B> From<Either<A, B>> for EitherOrBoth<A, B> {
fn from(either: Either<A, B>) -> Self {
match either {
Either::Left(l) => Left(l),
Either::Right(l) => Right(l),
}
}
}

View File

@@ -0,0 +1,125 @@
#[cfg(feature = "use_std")]
use std::error::Error;
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
use std::iter::ExactSizeIterator;
use either::Either;
use crate::size_hint;
/// Iterator returned for the error case of `Itertools::exactly_one()`
/// This iterator yields exactly the same elements as the input iterator.
///
/// During the execution of `exactly_one` the iterator must be mutated. This wrapper
/// effectively "restores" the state of the input iterator when it's handed back.
///
/// This is very similar to `PutBackN` except this iterator only supports 0-2 elements and does not
/// use a `Vec`.
#[derive(Clone)]
pub struct ExactlyOneError<I>
where
I: Iterator,
{
first_two: Option<Either<[I::Item; 2], I::Item>>,
inner: I,
}
impl<I> ExactlyOneError<I>
where
I: Iterator,
{
/// Creates a new `ExactlyOneErr` iterator.
pub(crate) fn new(first_two: Option<Either<[I::Item; 2], I::Item>>, inner: I) -> Self {
Self { first_two, inner }
}
fn additional_len(&self) -> usize {
match self.first_two {
Some(Either::Left(_)) => 2,
Some(Either::Right(_)) => 1,
None => 0,
}
}
}
impl<I> Iterator for ExactlyOneError<I>
where
I: Iterator,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
match self.first_two.take() {
Some(Either::Left([first, second])) => {
self.first_two = Some(Either::Right(second));
Some(first)
}
Some(Either::Right(second)) => Some(second),
None => self.inner.next(),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
size_hint::add_scalar(self.inner.size_hint(), self.additional_len())
}
fn fold<B, F>(self, mut init: B, mut f: F) -> B
where
F: FnMut(B, Self::Item) -> B,
{
match self.first_two {
Some(Either::Left([first, second])) => {
init = f(init, first);
init = f(init, second);
}
Some(Either::Right(second)) => init = f(init, second),
None => {}
}
self.inner.fold(init, f)
}
}
impl<I> ExactSizeIterator for ExactlyOneError<I> where I: ExactSizeIterator {}
impl<I> Display for ExactlyOneError<I>
where
I: Iterator,
{
fn fmt(&self, f: &mut Formatter) -> FmtResult {
let additional = self.additional_len();
if additional > 0 {
write!(f, "got at least 2 elements when exactly one was expected")
} else {
write!(f, "got zero elements when exactly one was expected")
}
}
}
impl<I> Debug for ExactlyOneError<I>
where
I: Iterator + Debug,
I::Item: Debug,
{
fn fmt(&self, f: &mut Formatter) -> FmtResult {
let mut dbg = f.debug_struct("ExactlyOneError");
match &self.first_two {
Some(Either::Left([first, second])) => {
dbg.field("first", first).field("second", second);
}
Some(Either::Right(second)) => {
dbg.field("second", second);
}
None => {}
}
dbg.field("inner", &self.inner).finish()
}
}
#[cfg(feature = "use_std")]
impl<I> Error for ExactlyOneError<I>
where
I: Iterator + Debug,
I::Item: Debug,
{
}

View File

@@ -0,0 +1,50 @@
#![cfg(feature = "use_alloc")]
use alloc::{vec, vec::Vec};
use std::cmp::Ordering;
/// Implementation guts for `min_set`, `min_set_by`, and `min_set_by_key`.
pub fn min_set_impl<I, K, F, Compare>(
mut it: I,
mut key_for: F,
mut compare: Compare,
) -> Vec<I::Item>
where
I: Iterator,
F: FnMut(&I::Item) -> K,
Compare: FnMut(&I::Item, &I::Item, &K, &K) -> Ordering,
{
match it.next() {
None => Vec::new(),
Some(element) => {
let mut current_key = key_for(&element);
let mut result = vec![element];
it.for_each(|element| {
let key = key_for(&element);
match compare(&element, &result[0], &key, &current_key) {
Ordering::Less => {
result.clear();
result.push(element);
current_key = key;
}
Ordering::Equal => {
result.push(element);
}
Ordering::Greater => {}
}
});
result
}
}
}
/// Implementation guts for `ax_set`, `max_set_by`, and `max_set_by_key`.
pub fn max_set_impl<I, K, F, Compare>(it: I, key_for: F, mut compare: Compare) -> Vec<I::Item>
where
I: Iterator,
F: FnMut(&I::Item) -> K,
Compare: FnMut(&I::Item, &I::Item, &K, &K) -> Ordering,
{
min_set_impl(it, key_for, |it1, it2, key1, key2| {
compare(it2, it1, key2, key1)
})
}

View File

@@ -0,0 +1,205 @@
use crate::size_hint;
use std::{
fmt,
iter::{DoubleEndedIterator, FusedIterator},
};
pub fn flatten_ok<I, T, E>(iter: I) -> FlattenOk<I, T, E>
where
I: Iterator<Item = Result<T, E>>,
T: IntoIterator,
{
FlattenOk {
iter,
inner_front: None,
inner_back: None,
}
}
/// An iterator adaptor that flattens `Result::Ok` values and
/// allows `Result::Err` values through unchanged.
///
/// See [`.flatten_ok()`](crate::Itertools::flatten_ok) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct FlattenOk<I, T, E>
where
I: Iterator<Item = Result<T, E>>,
T: IntoIterator,
{
iter: I,
inner_front: Option<T::IntoIter>,
inner_back: Option<T::IntoIter>,
}
impl<I, T, E> Iterator for FlattenOk<I, T, E>
where
I: Iterator<Item = Result<T, E>>,
T: IntoIterator,
{
type Item = Result<T::Item, E>;
fn next(&mut self) -> Option<Self::Item> {
loop {
// Handle the front inner iterator.
if let Some(inner) = &mut self.inner_front {
if let Some(item) = inner.next() {
return Some(Ok(item));
}
// This is necessary for the iterator to implement `FusedIterator`
// with only the original iterator being fused.
self.inner_front = None;
}
match self.iter.next() {
Some(Ok(ok)) => self.inner_front = Some(ok.into_iter()),
Some(Err(e)) => return Some(Err(e)),
None => {
// Handle the back inner iterator.
if let Some(inner) = &mut self.inner_back {
if let Some(item) = inner.next() {
return Some(Ok(item));
}
// This is necessary for the iterator to implement `FusedIterator`
// with only the original iterator being fused.
self.inner_back = None;
} else {
return None;
}
}
}
}
}
fn fold<B, F>(self, init: B, mut f: F) -> B
where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
{
// Front
let mut acc = match self.inner_front {
Some(x) => x.fold(init, |a, o| f(a, Ok(o))),
None => init,
};
acc = self.iter.fold(acc, |acc, x| match x {
Ok(it) => it.into_iter().fold(acc, |a, o| f(a, Ok(o))),
Err(e) => f(acc, Err(e)),
});
// Back
match self.inner_back {
Some(x) => x.fold(acc, |a, o| f(a, Ok(o))),
None => acc,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let inner_hint = |inner: &Option<T::IntoIter>| {
inner
.as_ref()
.map(Iterator::size_hint)
.unwrap_or((0, Some(0)))
};
let inner_front = inner_hint(&self.inner_front);
let inner_back = inner_hint(&self.inner_back);
// The outer iterator `Ok` case could be (0, None) as we don't know its size_hint yet.
let outer = match self.iter.size_hint() {
(0, Some(0)) => (0, Some(0)),
_ => (0, None),
};
size_hint::add(size_hint::add(inner_front, inner_back), outer)
}
}
impl<I, T, E> DoubleEndedIterator for FlattenOk<I, T, E>
where
I: DoubleEndedIterator<Item = Result<T, E>>,
T: IntoIterator,
T::IntoIter: DoubleEndedIterator,
{
fn next_back(&mut self) -> Option<Self::Item> {
loop {
// Handle the back inner iterator.
if let Some(inner) = &mut self.inner_back {
if let Some(item) = inner.next_back() {
return Some(Ok(item));
}
// This is necessary for the iterator to implement `FusedIterator`
// with only the original iterator being fused.
self.inner_back = None;
}
match self.iter.next_back() {
Some(Ok(ok)) => self.inner_back = Some(ok.into_iter()),
Some(Err(e)) => return Some(Err(e)),
None => {
// Handle the front inner iterator.
if let Some(inner) = &mut self.inner_front {
if let Some(item) = inner.next_back() {
return Some(Ok(item));
}
// This is necessary for the iterator to implement `FusedIterator`
// with only the original iterator being fused.
self.inner_front = None;
} else {
return None;
}
}
}
}
}
fn rfold<B, F>(self, init: B, mut f: F) -> B
where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
{
// Back
let mut acc = match self.inner_back {
Some(x) => x.rfold(init, |a, o| f(a, Ok(o))),
None => init,
};
acc = self.iter.rfold(acc, |acc, x| match x {
Ok(it) => it.into_iter().rfold(acc, |a, o| f(a, Ok(o))),
Err(e) => f(acc, Err(e)),
});
// Front
match self.inner_front {
Some(x) => x.rfold(acc, |a, o| f(a, Ok(o))),
None => acc,
}
}
}
impl<I, T, E> Clone for FlattenOk<I, T, E>
where
I: Iterator<Item = Result<T, E>> + Clone,
T: IntoIterator,
T::IntoIter: Clone,
{
clone_fields!(iter, inner_front, inner_back);
}
impl<I, T, E> fmt::Debug for FlattenOk<I, T, E>
where
I: Iterator<Item = Result<T, E>> + fmt::Debug,
T: IntoIterator,
T::IntoIter: fmt::Debug,
{
debug_fmt_fields!(FlattenOk, iter, inner_front, inner_back);
}
/// Only the iterator being flattened needs to implement [`FusedIterator`].
impl<I, T, E> FusedIterator for FlattenOk<I, T, E>
where
I: FusedIterator<Item = Result<T, E>>,
T: IntoIterator,
{
}

178
vendor/itertools-0.13.0/src/format.rs vendored Normal file
View File

@@ -0,0 +1,178 @@
use std::cell::Cell;
use std::fmt;
/// Format all iterator elements lazily, separated by `sep`.
///
/// The format value can only be formatted once, after that the iterator is
/// exhausted.
///
/// See [`.format_with()`](crate::Itertools::format_with) for more information.
pub struct FormatWith<'a, I, F> {
sep: &'a str,
/// `FormatWith` uses interior mutability because `Display::fmt` takes `&self`.
inner: Cell<Option<(I, F)>>,
}
/// Format all iterator elements lazily, separated by `sep`.
///
/// The format value can only be formatted once, after that the iterator is
/// exhausted.
///
/// See [`.format()`](crate::Itertools::format)
/// for more information.
pub struct Format<'a, I> {
sep: &'a str,
/// `Format` uses interior mutability because `Display::fmt` takes `&self`.
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,
{
FormatWith {
sep: separator,
inner: Cell::new(Some((iter, f))),
}
}
pub fn new_format_default<I>(iter: I, separator: &str) -> Format<'_, I>
where
I: Iterator,
{
Format {
sep: separator,
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,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let (mut iter, mut format) = match self.inner.take() {
Some(t) => t,
None => panic!("FormatWith: was already formatted once"),
};
if let Some(fst) = iter.next() {
format(fst, &mut |disp: &dyn fmt::Display| disp.fmt(f))?;
iter.try_for_each(|elt| {
if !self.sep.is_empty() {
f.write_str(self.sep)?;
}
format(elt, &mut |disp: &dyn fmt::Display| disp.fmt(f))
})?;
}
Ok(())
}
}
impl<'a, I, F> fmt::Debug for FormatWith<'a, I, F>
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 {
fmt::Display::fmt(self, f)
}
}
impl<'a, I> Format<'a, I>
where
I: Iterator,
{
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"),
};
if let Some(fst) = iter.next() {
cb(&fst, f)?;
iter.try_for_each(|elt| {
if !self.sep.is_empty() {
f.write_str(self.sep)?;
}
cb(&elt, f)
})?;
}
Ok(())
}
}
macro_rules! impl_format {
($($fmt_trait:ident)*) => {
$(
impl<'a, I> fmt::$fmt_trait for Format<'a, I>
where I: Iterator,
I::Item: fmt::$fmt_trait,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.format(f, fmt::$fmt_trait::fmt)
}
}
)*
}
}
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,
}
}
}

317
vendor/itertools-0.13.0/src/free.rs vendored Normal file
View File

@@ -0,0 +1,317 @@
//! Free functions that create iterator adaptors or call iterator methods.
//!
//! The benefit of free functions is that they accept any [`IntoIterator`] as
//! argument, so the resulting code may be easier to read.
#[cfg(feature = "use_alloc")]
use std::fmt::Display;
use std::iter::{self, Zip};
#[cfg(feature = "use_alloc")]
type VecIntoIter<T> = alloc::vec::IntoIter<T>;
#[cfg(feature = "use_alloc")]
use alloc::string::String;
use crate::intersperse::{Intersperse, IntersperseWith};
use crate::Itertools;
pub use crate::adaptors::{interleave, put_back};
#[cfg(feature = "use_alloc")]
pub use crate::kmerge_impl::kmerge;
pub use crate::merge_join::{merge, merge_join_by};
#[cfg(feature = "use_alloc")]
pub use crate::multipeek_impl::multipeek;
#[cfg(feature = "use_alloc")]
pub use crate::peek_nth::peek_nth;
#[cfg(feature = "use_alloc")]
pub use crate::put_back_n_impl::put_back_n;
#[cfg(feature = "use_alloc")]
pub use crate::rciter_impl::rciter;
pub use crate::zip_eq_impl::zip_eq;
/// Iterate `iterable` with a particular value inserted between each element.
///
/// [`IntoIterator`] enabled version of [`Iterator::intersperse`].
///
/// ```
/// use itertools::intersperse;
///
/// itertools::assert_equal(intersperse((0..3), 8), vec![0, 8, 1, 8, 2]);
/// ```
pub fn intersperse<I>(iterable: I, element: I::Item) -> Intersperse<I::IntoIter>
where
I: IntoIterator,
<I as IntoIterator>::Item: Clone,
{
Itertools::intersperse(iterable.into_iter(), element)
}
/// Iterate `iterable` with a particular value created by a function inserted
/// between each element.
///
/// [`IntoIterator`] enabled version of [`Iterator::intersperse_with`].
///
/// ```
/// use itertools::intersperse_with;
///
/// let mut i = 10;
/// itertools::assert_equal(intersperse_with((0..3), || { i -= 1; i }), vec![0, 9, 1, 8, 2]);
/// assert_eq!(i, 8);
/// ```
pub fn intersperse_with<I, F>(iterable: I, element: F) -> IntersperseWith<I::IntoIter, F>
where
I: IntoIterator,
F: FnMut() -> I::Item,
{
Itertools::intersperse_with(iterable.into_iter(), element)
}
/// Iterate `iterable` with a running index.
///
/// [`IntoIterator`] enabled version of [`Iterator::enumerate`].
///
/// ```
/// use itertools::enumerate;
///
/// for (i, elt) in enumerate(&[1, 2, 3]) {
/// /* loop body */
/// }
/// ```
pub fn enumerate<I>(iterable: I) -> iter::Enumerate<I::IntoIter>
where
I: IntoIterator,
{
iterable.into_iter().enumerate()
}
/// Iterate `iterable` in reverse.
///
/// [`IntoIterator`] enabled version of [`Iterator::rev`].
///
/// ```
/// use itertools::rev;
///
/// for elt in rev(&[1, 2, 3]) {
/// /* loop body */
/// }
/// ```
pub fn rev<I>(iterable: I) -> iter::Rev<I::IntoIter>
where
I: IntoIterator,
I::IntoIter: DoubleEndedIterator,
{
iterable.into_iter().rev()
}
/// Converts the arguments to iterators and zips them.
///
/// [`IntoIterator`] enabled version of [`Iterator::zip`].
///
/// ## Example
///
/// ```
/// use itertools::zip;
///
/// let mut result: Vec<(i32, char)> = Vec::new();
///
/// for (a, b) in zip(&[1, 2, 3, 4, 5], &['a', 'b', 'c']) {
/// result.push((*a, *b));
/// }
/// assert_eq!(result, vec![(1, 'a'),(2, 'b'),(3, 'c')]);
/// ```
#[deprecated(
note = "Use [std::iter::zip](https://doc.rust-lang.org/std/iter/fn.zip.html) instead",
since = "0.10.4"
)]
pub fn zip<I, J>(i: I, j: J) -> Zip<I::IntoIter, J::IntoIter>
where
I: IntoIterator,
J: IntoIterator,
{
i.into_iter().zip(j)
}
/// Takes two iterables and creates a new iterator over both in sequence.
///
/// [`IntoIterator`] enabled version of [`Iterator::chain`].
///
/// ## Example
/// ```
/// use itertools::chain;
///
/// let mut result:Vec<i32> = Vec::new();
///
/// for element in chain(&[1, 2, 3], &[4]) {
/// result.push(*element);
/// }
/// assert_eq!(result, vec![1, 2, 3, 4]);
/// ```
pub fn chain<I, J>(
i: I,
j: J,
) -> iter::Chain<<I as IntoIterator>::IntoIter, <J as IntoIterator>::IntoIter>
where
I: IntoIterator,
J: IntoIterator<Item = I::Item>,
{
i.into_iter().chain(j)
}
/// Create an iterator that clones each element from `&T` to `T`.
///
/// [`IntoIterator`] enabled version of [`Iterator::cloned`].
///
/// ```
/// use itertools::cloned;
///
/// assert_eq!(cloned(b"abc").next(), Some(b'a'));
/// ```
pub fn cloned<'a, I, T>(iterable: I) -> iter::Cloned<I::IntoIter>
where
I: IntoIterator<Item = &'a T>,
T: Clone + 'a,
{
iterable.into_iter().cloned()
}
/// Perform a fold operation over the iterable.
///
/// [`IntoIterator`] enabled version of [`Iterator::fold`].
///
/// ```
/// use itertools::fold;
///
/// assert_eq!(fold(&[1., 2., 3.], 0., |a, &b| f32::max(a, b)), 3.);
/// ```
pub fn fold<I, B, F>(iterable: I, init: B, f: F) -> B
where
I: IntoIterator,
F: FnMut(B, I::Item) -> B,
{
iterable.into_iter().fold(init, f)
}
/// Test whether the predicate holds for all elements in the iterable.
///
/// [`IntoIterator`] enabled version of [`Iterator::all`].
///
/// ```
/// use itertools::all;
///
/// assert!(all(&[1, 2, 3], |elt| *elt > 0));
/// ```
pub fn all<I, F>(iterable: I, f: F) -> bool
where
I: IntoIterator,
F: FnMut(I::Item) -> bool,
{
iterable.into_iter().all(f)
}
/// Test whether the predicate holds for any elements in the iterable.
///
/// [`IntoIterator`] enabled version of [`Iterator::any`].
///
/// ```
/// use itertools::any;
///
/// assert!(any(&[0, -1, 2], |elt| *elt > 0));
/// ```
pub fn any<I, F>(iterable: I, f: F) -> bool
where
I: IntoIterator,
F: FnMut(I::Item) -> bool,
{
iterable.into_iter().any(f)
}
/// Return the maximum value of the iterable.
///
/// [`IntoIterator`] enabled version of [`Iterator::max`].
///
/// ```
/// use itertools::max;
///
/// assert_eq!(max(0..10), Some(9));
/// ```
pub fn max<I>(iterable: I) -> Option<I::Item>
where
I: IntoIterator,
I::Item: Ord,
{
iterable.into_iter().max()
}
/// Return the minimum value of the iterable.
///
/// [`IntoIterator`] enabled version of [`Iterator::min`].
///
/// ```
/// use itertools::min;
///
/// assert_eq!(min(0..10), Some(0));
/// ```
pub fn min<I>(iterable: I) -> Option<I::Item>
where
I: IntoIterator,
I::Item: Ord,
{
iterable.into_iter().min()
}
/// Combine all iterator elements into one `String`, separated by `sep`.
///
/// [`IntoIterator`] enabled version of [`Itertools::join`].
///
/// ```
/// use itertools::join;
///
/// assert_eq!(join(&[1, 2, 3], ", "), "1, 2, 3");
/// ```
#[cfg(feature = "use_alloc")]
pub fn join<I>(iterable: I, sep: &str) -> String
where
I: IntoIterator,
I::Item: Display,
{
iterable.into_iter().join(sep)
}
/// Sort all iterator elements into a new iterator in ascending order.
///
/// [`IntoIterator`] enabled version of [`Itertools::sorted`].
///
/// ```
/// use itertools::sorted;
/// use itertools::assert_equal;
///
/// assert_equal(sorted("rust".chars()), "rstu".chars());
/// ```
#[cfg(feature = "use_alloc")]
pub fn sorted<I>(iterable: I) -> VecIntoIter<I::Item>
where
I: IntoIterator,
I::Item: Ord,
{
iterable.into_iter().sorted()
}
/// Sort all iterator elements into a new iterator in ascending order.
/// This sort is unstable (i.e., may reorder equal elements).
///
/// [`IntoIterator`] enabled version of [`Itertools::sorted_unstable`].
///
/// ```
/// use itertools::sorted_unstable;
/// use itertools::assert_equal;
///
/// assert_equal(sorted_unstable("rust".chars()), "rstu".chars());
/// ```
#[cfg(feature = "use_alloc")]
pub fn sorted_unstable<I>(iterable: I) -> VecIntoIter<I::Item>
where
I: IntoIterator,
I::Item: Ord,
{
iterable.into_iter().sorted_unstable()
}

View File

@@ -0,0 +1,32 @@
#![cfg(feature = "use_std")]
use std::collections::HashMap;
use std::hash::Hash;
use std::iter::Iterator;
/// Return a `HashMap` of keys mapped to a list of their corresponding values.
///
/// See [`.into_group_map()`](crate::Itertools::into_group_map)
/// for more information.
pub fn into_group_map<I, K, V>(iter: I) -> HashMap<K, Vec<V>>
where
I: Iterator<Item = (K, V)>,
K: Hash + Eq,
{
let mut lookup = HashMap::new();
iter.for_each(|(key, val)| {
lookup.entry(key).or_insert_with(Vec::new).push(val);
});
lookup
}
pub fn into_group_map_by<I, K, V, F>(iter: I, mut f: F) -> HashMap<K, Vec<V>>
where
I: Iterator<Item = V>,
K: Hash + Eq,
F: FnMut(&V) -> K,
{
into_group_map(iter.map(|v| (f(&v), v)))
}

View File

@@ -0,0 +1,613 @@
use alloc::vec::{self, Vec};
use std::cell::{Cell, RefCell};
/// A trait to unify `FnMut` for `ChunkBy` with the chunk key in `IntoChunks`
trait KeyFunction<A> {
type Key;
fn call_mut(&mut self, arg: A) -> Self::Key;
}
impl<A, K, F> KeyFunction<A> for F
where
F: FnMut(A) -> K + ?Sized,
{
type Key = K;
#[inline]
fn call_mut(&mut self, arg: A) -> Self::Key {
(*self)(arg)
}
}
/// `ChunkIndex` acts like the grouping key function for `IntoChunks`
#[derive(Debug, Clone)]
struct ChunkIndex {
size: usize,
index: usize,
key: usize,
}
impl ChunkIndex {
#[inline(always)]
fn new(size: usize) -> Self {
Self {
size,
index: 0,
key: 0,
}
}
}
impl<A> KeyFunction<A> for ChunkIndex {
type Key = usize;
#[inline(always)]
fn call_mut(&mut self, _arg: A) -> Self::Key {
if self.index == self.size {
self.key += 1;
self.index = 0;
}
self.index += 1;
self.key
}
}
#[derive(Clone)]
struct GroupInner<K, I, F>
where
I: Iterator,
{
key: F,
iter: I,
current_key: Option<K>,
current_elt: Option<I::Item>,
/// flag set if iterator is exhausted
done: bool,
/// Index of group we are currently buffering or visiting
top_group: usize,
/// Least index for which we still have elements buffered
oldest_buffered_group: usize,
/// Group index for `buffer[0]` -- the slots
/// `bottom_group..oldest_buffered_group` are unused and will be erased when
/// that range is large enough.
bottom_group: usize,
/// Buffered groups, from `bottom_group` (index 0) to `top_group`.
buffer: Vec<vec::IntoIter<I::Item>>,
/// index of last group iter that was dropped,
/// `usize::MAX` initially when no group was dropped
dropped_group: usize,
}
impl<K, I, F> GroupInner<K, I, F>
where
I: Iterator,
F: for<'a> KeyFunction<&'a I::Item, Key = K>,
K: PartialEq,
{
/// `client`: Index of group that requests next element
#[inline(always)]
fn step(&mut self, client: usize) -> Option<I::Item> {
/*
println!("client={}, bottom_group={}, oldest_buffered_group={}, top_group={}, buffers=[{}]",
client, self.bottom_group, self.oldest_buffered_group,
self.top_group,
self.buffer.iter().map(|elt| elt.len()).format(", "));
*/
if client < self.oldest_buffered_group {
None
} else if client < self.top_group
|| (client == self.top_group && self.buffer.len() > self.top_group - self.bottom_group)
{
self.lookup_buffer(client)
} else if self.done {
None
} else if self.top_group == client {
self.step_current()
} else {
self.step_buffering(client)
}
}
#[inline(never)]
fn lookup_buffer(&mut self, client: usize) -> Option<I::Item> {
// if `bufidx` doesn't exist in self.buffer, it might be empty
let bufidx = client - self.bottom_group;
if client < self.oldest_buffered_group {
return None;
}
let elt = self.buffer.get_mut(bufidx).and_then(|queue| queue.next());
if elt.is_none() && client == self.oldest_buffered_group {
// FIXME: VecDeque is unfortunately not zero allocation when empty,
// so we do this job manually.
// `bottom_group..oldest_buffered_group` is unused, and if it's large enough, erase it.
self.oldest_buffered_group += 1;
// skip forward further empty queues too
while self
.buffer
.get(self.oldest_buffered_group - self.bottom_group)
.map_or(false, |buf| buf.len() == 0)
{
self.oldest_buffered_group += 1;
}
let nclear = self.oldest_buffered_group - self.bottom_group;
if nclear > 0 && nclear >= self.buffer.len() / 2 {
let mut i = 0;
self.buffer.retain(|buf| {
i += 1;
debug_assert!(buf.len() == 0 || i > nclear);
i > nclear
});
self.bottom_group = self.oldest_buffered_group;
}
}
elt
}
/// Take the next element from the iterator, and set the done
/// flag if exhausted. Must not be called after done.
#[inline(always)]
fn next_element(&mut self) -> Option<I::Item> {
debug_assert!(!self.done);
match self.iter.next() {
None => {
self.done = true;
None
}
otherwise => otherwise,
}
}
#[inline(never)]
fn step_buffering(&mut self, client: usize) -> Option<I::Item> {
// requested a later group -- walk through the current group up to
// the requested group index, and buffer the elements (unless
// the group is marked as dropped).
// Because the `Groups` iterator is always the first to request
// each group index, client is the next index efter top_group.
debug_assert!(self.top_group + 1 == client);
let mut group = Vec::new();
if let Some(elt) = self.current_elt.take() {
if self.top_group != self.dropped_group {
group.push(elt);
}
}
let mut first_elt = None; // first element of the next group
while let Some(elt) = self.next_element() {
let key = self.key.call_mut(&elt);
match self.current_key.take() {
None => {}
Some(old_key) => {
if old_key != key {
self.current_key = Some(key);
first_elt = Some(elt);
break;
}
}
}
self.current_key = Some(key);
if self.top_group != self.dropped_group {
group.push(elt);
}
}
if self.top_group != self.dropped_group {
self.push_next_group(group);
}
if first_elt.is_some() {
self.top_group += 1;
debug_assert!(self.top_group == client);
}
first_elt
}
fn push_next_group(&mut self, group: Vec<I::Item>) {
// When we add a new buffered group, fill up slots between oldest_buffered_group and top_group
while self.top_group - self.bottom_group > self.buffer.len() {
if self.buffer.is_empty() {
self.bottom_group += 1;
self.oldest_buffered_group += 1;
} else {
self.buffer.push(Vec::new().into_iter());
}
}
self.buffer.push(group.into_iter());
debug_assert!(self.top_group + 1 - self.bottom_group == self.buffer.len());
}
/// This is the immediate case, where we use no buffering
#[inline]
fn step_current(&mut self) -> Option<I::Item> {
debug_assert!(!self.done);
if let elt @ Some(..) = self.current_elt.take() {
return elt;
}
match self.next_element() {
None => None,
Some(elt) => {
let key = self.key.call_mut(&elt);
match self.current_key.take() {
None => {}
Some(old_key) => {
if old_key != key {
self.current_key = Some(key);
self.current_elt = Some(elt);
self.top_group += 1;
return None;
}
}
}
self.current_key = Some(key);
Some(elt)
}
}
}
/// Request the just started groups' key.
///
/// `client`: Index of group
///
/// **Panics** if no group key is available.
fn group_key(&mut self, client: usize) -> K {
// This can only be called after we have just returned the first
// element of a group.
// Perform this by simply buffering one more element, grabbing the
// next key.
debug_assert!(!self.done);
debug_assert!(client == self.top_group);
debug_assert!(self.current_key.is_some());
debug_assert!(self.current_elt.is_none());
let old_key = self.current_key.take().unwrap();
if let Some(elt) = self.next_element() {
let key = self.key.call_mut(&elt);
if old_key != key {
self.top_group += 1;
}
self.current_key = Some(key);
self.current_elt = Some(elt);
}
old_key
}
}
impl<K, I, F> GroupInner<K, I, F>
where
I: Iterator,
{
/// Called when a group is dropped
fn drop_group(&mut self, client: usize) {
// It's only useful to track the maximal index
if self.dropped_group == !0 || client > self.dropped_group {
self.dropped_group = client;
}
}
}
#[deprecated(note = "Use `ChunkBy` instead", since = "0.13.0")]
/// See [`ChunkBy`](crate::structs::ChunkBy).
pub type GroupBy<K, I, F> = ChunkBy<K, I, F>;
/// `ChunkBy` is the storage for the lazy grouping operation.
///
/// If the groups are consumed in their original order, or if each
/// group is dropped without keeping it around, then `ChunkBy` uses
/// no allocations. It needs allocations only if several group iterators
/// are alive at the same time.
///
/// This type implements [`IntoIterator`] (it is **not** an iterator
/// itself), because the group iterators need to borrow from this
/// value. It should be stored in a local variable or temporary and
/// iterated.
///
/// See [`.chunk_by()`](crate::Itertools::chunk_by) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct ChunkBy<K, I, F>
where
I: Iterator,
{
inner: RefCell<GroupInner<K, I, F>>,
// the group iterator's current index. Keep this in the main value
// so that simultaneous iterators all use the same state.
index: Cell<usize>,
}
/// Create a new
pub fn new<K, J, F>(iter: J, f: F) -> ChunkBy<K, J::IntoIter, F>
where
J: IntoIterator,
F: FnMut(&J::Item) -> K,
{
ChunkBy {
inner: RefCell::new(GroupInner {
key: f,
iter: iter.into_iter(),
current_key: None,
current_elt: None,
done: false,
top_group: 0,
oldest_buffered_group: 0,
bottom_group: 0,
buffer: Vec::new(),
dropped_group: !0,
}),
index: Cell::new(0),
}
}
impl<K, I, F> ChunkBy<K, I, F>
where
I: Iterator,
{
/// `client`: Index of group that requests next element
fn step(&self, client: usize) -> Option<I::Item>
where
F: FnMut(&I::Item) -> K,
K: PartialEq,
{
self.inner.borrow_mut().step(client)
}
/// `client`: Index of group
fn drop_group(&self, client: usize) {
self.inner.borrow_mut().drop_group(client);
}
}
impl<'a, K, I, F> IntoIterator for &'a ChunkBy<K, I, F>
where
I: Iterator,
I::Item: 'a,
F: FnMut(&I::Item) -> K,
K: PartialEq,
{
type Item = (K, Group<'a, K, I, F>);
type IntoIter = Groups<'a, K, I, F>;
fn into_iter(self) -> Self::IntoIter {
Groups { parent: self }
}
}
/// An iterator that yields the Group iterators.
///
/// Iterator element type is `(K, Group)`:
/// the group's key `K` and the group's iterator.
///
/// See [`.chunk_by()`](crate::Itertools::chunk_by) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct Groups<'a, K, I, F>
where
I: Iterator + 'a,
I::Item: 'a,
K: 'a,
F: 'a,
{
parent: &'a ChunkBy<K, I, F>,
}
impl<'a, K, I, F> Iterator for Groups<'a, K, I, F>
where
I: Iterator,
I::Item: 'a,
F: FnMut(&I::Item) -> K,
K: PartialEq,
{
type Item = (K, Group<'a, K, I, F>);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let index = self.parent.index.get();
self.parent.index.set(index + 1);
let inner = &mut *self.parent.inner.borrow_mut();
inner.step(index).map(|elt| {
let key = inner.group_key(index);
(
key,
Group {
parent: self.parent,
index,
first: Some(elt),
},
)
})
}
}
/// An iterator for the elements in a single group.
///
/// Iterator element type is `I::Item`.
pub struct Group<'a, K, I, F>
where
I: Iterator + 'a,
I::Item: 'a,
K: 'a,
F: 'a,
{
parent: &'a ChunkBy<K, I, F>,
index: usize,
first: Option<I::Item>,
}
impl<'a, K, I, F> Drop for Group<'a, K, I, F>
where
I: Iterator,
I::Item: 'a,
{
fn drop(&mut self) {
self.parent.drop_group(self.index);
}
}
impl<'a, K, I, F> Iterator for Group<'a, K, I, F>
where
I: Iterator,
I::Item: 'a,
F: FnMut(&I::Item) -> K,
K: PartialEq,
{
type Item = I::Item;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if let elt @ Some(..) = self.first.take() {
return elt;
}
self.parent.step(self.index)
}
}
///// IntoChunks /////
/// Create a new
pub fn new_chunks<J>(iter: J, size: usize) -> IntoChunks<J::IntoIter>
where
J: IntoIterator,
{
IntoChunks {
inner: RefCell::new(GroupInner {
key: ChunkIndex::new(size),
iter: iter.into_iter(),
current_key: None,
current_elt: None,
done: false,
top_group: 0,
oldest_buffered_group: 0,
bottom_group: 0,
buffer: Vec::new(),
dropped_group: !0,
}),
index: Cell::new(0),
}
}
/// `ChunkLazy` is the storage for a lazy chunking operation.
///
/// `IntoChunks` behaves just like `ChunkBy`: it is iterable, and
/// it only buffers if several chunk iterators are alive at the same time.
///
/// This type implements [`IntoIterator`] (it is **not** an iterator
/// itself), because the chunk iterators need to borrow from this
/// value. It should be stored in a local variable or temporary and
/// iterated.
///
/// Iterator element type is `Chunk`, each chunk's iterator.
///
/// See [`.chunks()`](crate::Itertools::chunks) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct IntoChunks<I>
where
I: Iterator,
{
inner: RefCell<GroupInner<usize, I, ChunkIndex>>,
// the chunk iterator's current index. Keep this in the main value
// so that simultaneous iterators all use the same state.
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,
{
/// `client`: Index of chunk that requests next element
fn step(&self, client: usize) -> Option<I::Item> {
self.inner.borrow_mut().step(client)
}
/// `client`: Index of chunk
fn drop_group(&self, client: usize) {
self.inner.borrow_mut().drop_group(client);
}
}
impl<'a, I> IntoIterator for &'a IntoChunks<I>
where
I: Iterator,
I::Item: 'a,
{
type Item = Chunk<'a, I>;
type IntoIter = Chunks<'a, I>;
fn into_iter(self) -> Self::IntoIter {
Chunks { parent: self }
}
}
/// An iterator that yields the Chunk iterators.
///
/// Iterator element type is `Chunk`.
///
/// 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>
where
I: Iterator + 'a,
I::Item: 'a,
{
parent: &'a IntoChunks<I>,
}
impl<'a, I> Iterator for Chunks<'a, I>
where
I: Iterator,
I::Item: 'a,
{
type Item = Chunk<'a, I>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let index = self.parent.index.get();
self.parent.index.set(index + 1);
let inner = &mut *self.parent.inner.borrow_mut();
inner.step(index).map(|elt| Chunk {
parent: self.parent,
index,
first: Some(elt),
})
}
}
/// An iterator for the elements in a single chunk.
///
/// Iterator element type is `I::Item`.
pub struct Chunk<'a, I>
where
I: Iterator + 'a,
I::Item: 'a,
{
parent: &'a IntoChunks<I>,
index: usize,
first: Option<I::Item>,
}
impl<'a, I> Drop for Chunk<'a, I>
where
I: Iterator,
I::Item: 'a,
{
fn drop(&mut self) {
self.parent.drop_group(self.index);
}
}
impl<'a, I> Iterator for Chunk<'a, I>
where
I: Iterator,
I::Item: 'a,
{
type Item = I::Item;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if let elt @ Some(..) = self.first.take() {
return elt;
}
self.parent.step(self.index)
}
}

View File

@@ -0,0 +1,614 @@
#![cfg(feature = "use_std")]
use crate::{
adaptors::map::{MapSpecialCase, MapSpecialCaseFn},
MinMaxResult,
};
use std::cmp::Ordering;
use std::collections::HashMap;
use std::hash::Hash;
use std::iter::Iterator;
use std::ops::{Add, Mul};
/// A wrapper to allow for an easy [`into_grouping_map_by`](crate::Itertools::into_grouping_map_by)
pub type MapForGrouping<I, F> = MapSpecialCase<I, GroupingMapFn<F>>;
#[derive(Clone)]
pub struct GroupingMapFn<F>(F);
impl<F> std::fmt::Debug for GroupingMapFn<F> {
debug_fmt_fields!(GroupingMapFn,);
}
impl<V, K, F: FnMut(&V) -> K> MapSpecialCaseFn<V> for GroupingMapFn<F> {
type Out = (K, V);
fn call(&mut self, v: V) -> Self::Out {
((self.0)(&v), v)
}
}
pub(crate) fn new_map_for_grouping<K, I: Iterator, F: FnMut(&I::Item) -> K>(
iter: I,
key_mapper: F,
) -> MapForGrouping<I, F> {
MapSpecialCase {
iter,
f: GroupingMapFn(key_mapper),
}
}
/// Creates a new `GroupingMap` from `iter`
pub fn new<I, K, V>(iter: I) -> GroupingMap<I>
where
I: Iterator<Item = (K, V)>,
K: Hash + Eq,
{
GroupingMap { iter }
}
/// `GroupingMapBy` is an intermediate struct for efficient group-and-fold operations.
///
/// See [`GroupingMap`] for more informations.
pub type GroupingMapBy<I, F> = GroupingMap<MapForGrouping<I, F>>;
/// `GroupingMap` is an intermediate struct for efficient group-and-fold operations.
/// It groups elements by their key and at the same time fold each group
/// using some aggregating operation.
///
/// No method on this struct performs temporary allocations.
#[derive(Clone, Debug)]
#[must_use = "GroupingMap is lazy and do nothing unless consumed"]
pub struct GroupingMap<I> {
iter: I,
}
impl<I, K, V> GroupingMap<I>
where
I: Iterator<Item = (K, V)>,
K: Hash + Eq,
{
/// This is the generic way to perform any operation on a `GroupingMap`.
/// It's suggested to use this method only to implement custom operations
/// when the already provided ones are not enough.
///
/// Groups elements from the `GroupingMap` source by key and applies `operation` to the elements
/// of each group sequentially, passing the previously accumulated value, a reference to the key
/// and the current element as arguments, and stores the results in an `HashMap`.
///
/// The `operation` function is invoked on each element with the following parameters:
/// - the current value of the accumulator of the group if there is currently one;
/// - a reference to the key of the group this element belongs to;
/// - the element from the source being aggregated;
///
/// If `operation` returns `Some(element)` then the accumulator is updated with `element`,
/// otherwise the previous accumulation is discarded.
///
/// Return a `HashMap` associating the key of each group with the result of aggregation of
/// that group's elements. If the aggregation of the last element of a group discards the
/// accumulator then there won't be an entry associated to that group's key.
///
/// ```
/// use itertools::Itertools;
///
/// let data = vec![2, 8, 5, 7, 9, 0, 4, 10];
/// let lookup = data.into_iter()
/// .into_grouping_map_by(|&n| n % 4)
/// .aggregate(|acc, _key, val| {
/// if val == 0 || val == 10 {
/// None
/// } else {
/// Some(acc.unwrap_or(0) + val)
/// }
/// });
///
/// assert_eq!(lookup[&0], 4); // 0 resets the accumulator so only 4 is summed
/// assert_eq!(lookup[&1], 5 + 9);
/// assert_eq!(lookup.get(&2), None); // 10 resets the accumulator and nothing is summed afterward
/// assert_eq!(lookup[&3], 7);
/// assert_eq!(lookup.len(), 3); // The final keys are only 0, 1 and 2
/// ```
pub fn aggregate<FO, R>(self, mut operation: FO) -> HashMap<K, R>
where
FO: FnMut(Option<R>, &K, V) -> Option<R>,
{
let mut destination_map = HashMap::new();
self.iter.for_each(|(key, val)| {
let acc = destination_map.remove(&key);
if let Some(op_res) = operation(acc, &key, val) {
destination_map.insert(key, op_res);
}
});
destination_map
}
/// Groups elements from the `GroupingMap` source by key and applies `operation` to the elements
/// of each group sequentially, passing the previously accumulated value, a reference to the key
/// and the current element as arguments, and stores the results in a new map.
///
/// `init` is called to obtain the initial value of each accumulator.
///
/// `operation` is a function that is invoked on each element with the following parameters:
/// - the current value of the accumulator of the group;
/// - a reference to the key of the group this element belongs to;
/// - the element from the source being accumulated.
///
/// Return a `HashMap` associating the key of each group with the result of folding that group's elements.
///
/// ```
/// use itertools::Itertools;
///
/// #[derive(Debug, Default)]
/// struct Accumulator {
/// acc: usize,
/// }
///
/// let lookup = (1..=7)
/// .into_grouping_map_by(|&n| n % 3)
/// .fold_with(|_key, _val| Default::default(), |Accumulator { acc }, _key, val| {
/// let acc = acc + val;
/// Accumulator { acc }
/// });
///
/// assert_eq!(lookup[&0].acc, 3 + 6);
/// assert_eq!(lookup[&1].acc, 1 + 4 + 7);
/// assert_eq!(lookup[&2].acc, 2 + 5);
/// assert_eq!(lookup.len(), 3);
/// ```
pub fn fold_with<FI, FO, R>(self, mut init: FI, mut operation: FO) -> HashMap<K, R>
where
FI: FnMut(&K, &V) -> R,
FO: FnMut(R, &K, V) -> R,
{
self.aggregate(|acc, key, val| {
let acc = acc.unwrap_or_else(|| init(key, &val));
Some(operation(acc, key, val))
})
}
/// Groups elements from the `GroupingMap` source by key and applies `operation` to the elements
/// of each group sequentially, passing the previously accumulated value, a reference to the key
/// and the current element as arguments, and stores the results in a new map.
///
/// `init` is the value from which will be cloned the initial value of each accumulator.
///
/// `operation` is a function that is invoked on each element with the following parameters:
/// - the current value of the accumulator of the group;
/// - a reference to the key of the group this element belongs to;
/// - the element from the source being accumulated.
///
/// Return a `HashMap` associating the key of each group with the result of folding that group's elements.
///
/// ```
/// use itertools::Itertools;
///
/// let lookup = (1..=7)
/// .into_grouping_map_by(|&n| n % 3)
/// .fold(0, |acc, _key, val| acc + val);
///
/// assert_eq!(lookup[&0], 3 + 6);
/// assert_eq!(lookup[&1], 1 + 4 + 7);
/// assert_eq!(lookup[&2], 2 + 5);
/// assert_eq!(lookup.len(), 3);
/// ```
pub fn fold<FO, R>(self, init: R, operation: FO) -> HashMap<K, R>
where
R: Clone,
FO: FnMut(R, &K, V) -> R,
{
self.fold_with(|_, _| init.clone(), operation)
}
/// Groups elements from the `GroupingMap` source by key and applies `operation` to the elements
/// of each group sequentially, passing the previously accumulated value, a reference to the key
/// and the current element as arguments, and stores the results in a new map.
///
/// This is similar to [`fold`] but the initial value of the accumulator is the first element of the group.
///
/// `operation` is a function that is invoked on each element with the following parameters:
/// - the current value of the accumulator of the group;
/// - a reference to the key of the group this element belongs to;
/// - the element from the source being accumulated.
///
/// Return a `HashMap` associating the key of each group with the result of folding that group's elements.
///
/// [`fold`]: GroupingMap::fold
///
/// ```
/// use itertools::Itertools;
///
/// let lookup = (1..=7)
/// .into_grouping_map_by(|&n| n % 3)
/// .reduce(|acc, _key, val| acc + val);
///
/// assert_eq!(lookup[&0], 3 + 6);
/// assert_eq!(lookup[&1], 1 + 4 + 7);
/// assert_eq!(lookup[&2], 2 + 5);
/// assert_eq!(lookup.len(), 3);
/// ```
pub fn reduce<FO>(self, mut operation: FO) -> HashMap<K, V>
where
FO: FnMut(V, &K, V) -> V,
{
self.aggregate(|acc, key, val| {
Some(match acc {
Some(acc) => operation(acc, key, val),
None => val,
})
})
}
/// See [`.reduce()`](GroupingMap::reduce).
#[deprecated(note = "Use .reduce() instead", since = "0.13.0")]
pub fn fold_first<FO>(self, operation: FO) -> HashMap<K, V>
where
FO: FnMut(V, &K, V) -> V,
{
self.reduce(operation)
}
/// Groups elements from the `GroupingMap` source by key and collects the elements of each group in
/// an instance of `C`. The iteration order is preserved when inserting elements.
///
/// Return a `HashMap` associating the key of each group with the collection containing that group's elements.
///
/// ```
/// use itertools::Itertools;
/// use std::collections::HashSet;
///
/// let lookup = vec![0, 1, 2, 3, 4, 5, 6, 2, 3, 6].into_iter()
/// .into_grouping_map_by(|&n| n % 3)
/// .collect::<HashSet<_>>();
///
/// assert_eq!(lookup[&0], vec![0, 3, 6].into_iter().collect::<HashSet<_>>());
/// assert_eq!(lookup[&1], vec![1, 4].into_iter().collect::<HashSet<_>>());
/// assert_eq!(lookup[&2], vec![2, 5].into_iter().collect::<HashSet<_>>());
/// assert_eq!(lookup.len(), 3);
/// ```
pub fn collect<C>(self) -> HashMap<K, C>
where
C: Default + Extend<V>,
{
let mut destination_map = HashMap::new();
self.iter.for_each(|(key, val)| {
destination_map
.entry(key)
.or_insert_with(C::default)
.extend(Some(val));
});
destination_map
}
/// Groups elements from the `GroupingMap` source by key and finds the maximum of each group.
///
/// If several elements are equally maximum, the last element is picked.
///
/// Returns a `HashMap` associating the key of each group with the maximum of that group's elements.
///
/// ```
/// use itertools::Itertools;
///
/// let lookup = vec![1, 3, 4, 5, 7, 8, 9, 12].into_iter()
/// .into_grouping_map_by(|&n| n % 3)
/// .max();
///
/// assert_eq!(lookup[&0], 12);
/// assert_eq!(lookup[&1], 7);
/// assert_eq!(lookup[&2], 8);
/// assert_eq!(lookup.len(), 3);
/// ```
pub fn max(self) -> HashMap<K, V>
where
V: Ord,
{
self.max_by(|_, v1, v2| V::cmp(v1, v2))
}
/// Groups elements from the `GroupingMap` source by key and finds the maximum of each group
/// with respect to the specified comparison function.
///
/// If several elements are equally maximum, the last element is picked.
///
/// Returns a `HashMap` associating the key of each group with the maximum of that group's elements.
///
/// ```
/// use itertools::Itertools;
///
/// let lookup = vec![1, 3, 4, 5, 7, 8, 9, 12].into_iter()
/// .into_grouping_map_by(|&n| n % 3)
/// .max_by(|_key, x, y| y.cmp(x));
///
/// assert_eq!(lookup[&0], 3);
/// assert_eq!(lookup[&1], 1);
/// assert_eq!(lookup[&2], 5);
/// assert_eq!(lookup.len(), 3);
/// ```
pub fn max_by<F>(self, mut compare: F) -> HashMap<K, V>
where
F: FnMut(&K, &V, &V) -> Ordering,
{
self.reduce(|acc, key, val| match compare(key, &acc, &val) {
Ordering::Less | Ordering::Equal => val,
Ordering::Greater => acc,
})
}
/// Groups elements from the `GroupingMap` source by key and finds the element of each group
/// that gives the maximum from the specified function.
///
/// If several elements are equally maximum, the last element is picked.
///
/// Returns a `HashMap` associating the key of each group with the maximum of that group's elements.
///
/// ```
/// use itertools::Itertools;
///
/// let lookup = vec![1, 3, 4, 5, 7, 8, 9, 12].into_iter()
/// .into_grouping_map_by(|&n| n % 3)
/// .max_by_key(|_key, &val| val % 4);
///
/// assert_eq!(lookup[&0], 3);
/// assert_eq!(lookup[&1], 7);
/// assert_eq!(lookup[&2], 5);
/// assert_eq!(lookup.len(), 3);
/// ```
pub fn max_by_key<F, CK>(self, mut f: F) -> HashMap<K, V>
where
F: FnMut(&K, &V) -> CK,
CK: Ord,
{
self.max_by(|key, v1, v2| f(key, v1).cmp(&f(key, v2)))
}
/// Groups elements from the `GroupingMap` source by key and finds the minimum of each group.
///
/// If several elements are equally minimum, the first element is picked.
///
/// Returns a `HashMap` associating the key of each group with the minimum of that group's elements.
///
/// ```
/// use itertools::Itertools;
///
/// let lookup = vec![1, 3, 4, 5, 7, 8, 9, 12].into_iter()
/// .into_grouping_map_by(|&n| n % 3)
/// .min();
///
/// assert_eq!(lookup[&0], 3);
/// assert_eq!(lookup[&1], 1);
/// assert_eq!(lookup[&2], 5);
/// assert_eq!(lookup.len(), 3);
/// ```
pub fn min(self) -> HashMap<K, V>
where
V: Ord,
{
self.min_by(|_, v1, v2| V::cmp(v1, v2))
}
/// Groups elements from the `GroupingMap` source by key and finds the minimum of each group
/// with respect to the specified comparison function.
///
/// If several elements are equally minimum, the first element is picked.
///
/// Returns a `HashMap` associating the key of each group with the minimum of that group's elements.
///
/// ```
/// use itertools::Itertools;
///
/// let lookup = vec![1, 3, 4, 5, 7, 8, 9, 12].into_iter()
/// .into_grouping_map_by(|&n| n % 3)
/// .min_by(|_key, x, y| y.cmp(x));
///
/// assert_eq!(lookup[&0], 12);
/// assert_eq!(lookup[&1], 7);
/// assert_eq!(lookup[&2], 8);
/// assert_eq!(lookup.len(), 3);
/// ```
pub fn min_by<F>(self, mut compare: F) -> HashMap<K, V>
where
F: FnMut(&K, &V, &V) -> Ordering,
{
self.reduce(|acc, key, val| match compare(key, &acc, &val) {
Ordering::Less | Ordering::Equal => acc,
Ordering::Greater => val,
})
}
/// Groups elements from the `GroupingMap` source by key and finds the element of each group
/// that gives the minimum from the specified function.
///
/// If several elements are equally minimum, the first element is picked.
///
/// Returns a `HashMap` associating the key of each group with the minimum of that group's elements.
///
/// ```
/// use itertools::Itertools;
///
/// let lookup = vec![1, 3, 4, 5, 7, 8, 9, 12].into_iter()
/// .into_grouping_map_by(|&n| n % 3)
/// .min_by_key(|_key, &val| val % 4);
///
/// assert_eq!(lookup[&0], 12);
/// assert_eq!(lookup[&1], 4);
/// assert_eq!(lookup[&2], 8);
/// assert_eq!(lookup.len(), 3);
/// ```
pub fn min_by_key<F, CK>(self, mut f: F) -> HashMap<K, V>
where
F: FnMut(&K, &V) -> CK,
CK: Ord,
{
self.min_by(|key, v1, v2| f(key, v1).cmp(&f(key, v2)))
}
/// Groups elements from the `GroupingMap` source by key and find the maximum and minimum of
/// each group.
///
/// If several elements are equally maximum, the last element is picked.
/// If several elements are equally minimum, the first element is picked.
///
/// See [`Itertools::minmax`](crate::Itertools::minmax) for the non-grouping version.
///
/// Differences from the non grouping version:
/// - It never produces a `MinMaxResult::NoElements`
/// - It doesn't have any speedup
///
/// Returns a `HashMap` associating the key of each group with the minimum and maximum of that group's elements.
///
/// ```
/// use itertools::Itertools;
/// use itertools::MinMaxResult::{OneElement, MinMax};
///
/// let lookup = vec![1, 3, 4, 5, 7, 9, 12].into_iter()
/// .into_grouping_map_by(|&n| n % 3)
/// .minmax();
///
/// assert_eq!(lookup[&0], MinMax(3, 12));
/// assert_eq!(lookup[&1], MinMax(1, 7));
/// assert_eq!(lookup[&2], OneElement(5));
/// assert_eq!(lookup.len(), 3);
/// ```
pub fn minmax(self) -> HashMap<K, MinMaxResult<V>>
where
V: Ord,
{
self.minmax_by(|_, v1, v2| V::cmp(v1, v2))
}
/// Groups elements from the `GroupingMap` source by key and find the maximum and minimum of
/// each group with respect to the specified comparison function.
///
/// If several elements are equally maximum, the last element is picked.
/// If several elements are equally minimum, the first element is picked.
///
/// It has the same differences from the non-grouping version as `minmax`.
///
/// Returns a `HashMap` associating the key of each group with the minimum and maximum of that group's elements.
///
/// ```
/// use itertools::Itertools;
/// use itertools::MinMaxResult::{OneElement, MinMax};
///
/// let lookup = vec![1, 3, 4, 5, 7, 9, 12].into_iter()
/// .into_grouping_map_by(|&n| n % 3)
/// .minmax_by(|_key, x, y| y.cmp(x));
///
/// assert_eq!(lookup[&0], MinMax(12, 3));
/// assert_eq!(lookup[&1], MinMax(7, 1));
/// assert_eq!(lookup[&2], OneElement(5));
/// assert_eq!(lookup.len(), 3);
/// ```
pub fn minmax_by<F>(self, mut compare: F) -> HashMap<K, MinMaxResult<V>>
where
F: FnMut(&K, &V, &V) -> Ordering,
{
self.aggregate(|acc, key, val| {
Some(match acc {
Some(MinMaxResult::OneElement(e)) => {
if compare(key, &val, &e) == Ordering::Less {
MinMaxResult::MinMax(val, e)
} else {
MinMaxResult::MinMax(e, val)
}
}
Some(MinMaxResult::MinMax(min, max)) => {
if compare(key, &val, &min) == Ordering::Less {
MinMaxResult::MinMax(val, max)
} else if compare(key, &val, &max) != Ordering::Less {
MinMaxResult::MinMax(min, val)
} else {
MinMaxResult::MinMax(min, max)
}
}
None => MinMaxResult::OneElement(val),
Some(MinMaxResult::NoElements) => unreachable!(),
})
})
}
/// Groups elements from the `GroupingMap` source by key and find the elements of each group
/// that gives the minimum and maximum from the specified function.
///
/// If several elements are equally maximum, the last element is picked.
/// If several elements are equally minimum, the first element is picked.
///
/// It has the same differences from the non-grouping version as `minmax`.
///
/// Returns a `HashMap` associating the key of each group with the minimum and maximum of that group's elements.
///
/// ```
/// use itertools::Itertools;
/// use itertools::MinMaxResult::{OneElement, MinMax};
///
/// let lookup = vec![1, 3, 4, 5, 7, 9, 12].into_iter()
/// .into_grouping_map_by(|&n| n % 3)
/// .minmax_by_key(|_key, &val| val % 4);
///
/// assert_eq!(lookup[&0], MinMax(12, 3));
/// assert_eq!(lookup[&1], MinMax(4, 7));
/// assert_eq!(lookup[&2], OneElement(5));
/// assert_eq!(lookup.len(), 3);
/// ```
pub fn minmax_by_key<F, CK>(self, mut f: F) -> HashMap<K, MinMaxResult<V>>
where
F: FnMut(&K, &V) -> CK,
CK: Ord,
{
self.minmax_by(|key, v1, v2| f(key, v1).cmp(&f(key, v2)))
}
/// Groups elements from the `GroupingMap` source by key and sums them.
///
/// This is just a shorthand for `self.reduce(|acc, _, val| acc + val)`.
/// It is more limited than `Iterator::sum` since it doesn't use the `Sum` trait.
///
/// Returns a `HashMap` associating the key of each group with the sum of that group's elements.
///
/// ```
/// use itertools::Itertools;
///
/// let lookup = vec![1, 3, 4, 5, 7, 8, 9, 12].into_iter()
/// .into_grouping_map_by(|&n| n % 3)
/// .sum();
///
/// assert_eq!(lookup[&0], 3 + 9 + 12);
/// assert_eq!(lookup[&1], 1 + 4 + 7);
/// assert_eq!(lookup[&2], 5 + 8);
/// assert_eq!(lookup.len(), 3);
/// ```
pub fn sum(self) -> HashMap<K, V>
where
V: Add<V, Output = V>,
{
self.reduce(|acc, _, val| acc + val)
}
/// Groups elements from the `GroupingMap` source by key and multiply them.
///
/// This is just a shorthand for `self.reduce(|acc, _, val| acc * val)`.
/// It is more limited than `Iterator::product` since it doesn't use the `Product` trait.
///
/// Returns a `HashMap` associating the key of each group with the product of that group's elements.
///
/// ```
/// use itertools::Itertools;
///
/// let lookup = vec![1, 3, 4, 5, 7, 8, 9, 12].into_iter()
/// .into_grouping_map_by(|&n| n % 3)
/// .product();
///
/// assert_eq!(lookup[&0], 3 * 9 * 12);
/// assert_eq!(lookup[&1], 1 * 4 * 7);
/// assert_eq!(lookup[&2], 5 * 8);
/// assert_eq!(lookup.len(), 3);
/// ```
pub fn product(self) -> HashMap<K, V>
where
V: Mul<V, Output = V>,
{
self.reduce(|acc, _, val| acc * val)
}
}

View File

@@ -0,0 +1,34 @@
//!
//! Implementation's internal macros
macro_rules! debug_fmt_fields {
($tyname:ident, $($($field:tt/*TODO ideally we would accept ident or tuple element here*/).+),*) => {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
f.debug_struct(stringify!($tyname))
$(
.field(stringify!($($field).+), &self.$($field).+)
)*
.finish()
}
}
}
macro_rules! clone_fields {
($($field:ident),*) => {
#[inline] // TODO is this sensible?
fn clone(&self) -> Self {
Self {
$($field: self.$field.clone(),)*
}
}
}
}
macro_rules! ignore_ident{
($id:ident, $($t:tt)*) => {$($t)*};
}
macro_rules! count_ident {
() => {0};
($i0:ident $($i:ident)*) => {1 + count_ident!($($i)*)};
}

View File

@@ -0,0 +1,142 @@
use super::size_hint;
use std::iter::{Fuse, FusedIterator};
pub trait IntersperseElement<Item> {
fn generate(&mut self) -> Item;
}
#[derive(Debug, Clone)]
pub struct IntersperseElementSimple<Item>(Item);
impl<Item: Clone> IntersperseElement<Item> for IntersperseElementSimple<Item> {
fn generate(&mut self) -> Item {
self.0.clone()
}
}
/// An iterator adaptor to insert a particular value
/// between each element of the adapted iterator.
///
/// Iterator element type is `I::Item`
///
/// This iterator is *fused*.
///
/// See [`.intersperse()`](crate::Itertools::intersperse) for more information.
pub type Intersperse<I> = IntersperseWith<I, IntersperseElementSimple<<I as Iterator>::Item>>;
/// Create a new Intersperse iterator
pub fn intersperse<I>(iter: I, elt: I::Item) -> Intersperse<I>
where
I: Iterator,
{
intersperse_with(iter, IntersperseElementSimple(elt))
}
impl<Item, F: FnMut() -> Item> IntersperseElement<Item> for F {
fn generate(&mut self) -> Item {
self()
}
}
/// An iterator adaptor to insert a particular value created by a function
/// between each element of the adapted iterator.
///
/// Iterator element type is `I::Item`
///
/// This iterator is *fused*.
///
/// See [`.intersperse_with()`](crate::Itertools::intersperse_with) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Clone, Debug)]
pub struct IntersperseWith<I, ElemF>
where
I: Iterator,
{
element: ElemF,
iter: Fuse<I>,
/// `peek` is None while no item have been taken out of `iter` (at definition).
/// Then `peek` will alternatively be `Some(None)` and `Some(Some(item))`,
/// where `None` indicates it's time to generate from `element` (unless `iter` is empty).
peek: Option<Option<I::Item>>,
}
/// Create a new `IntersperseWith` iterator
pub fn intersperse_with<I, ElemF>(iter: I, elt: ElemF) -> IntersperseWith<I, ElemF>
where
I: Iterator,
{
IntersperseWith {
peek: None,
iter: iter.fuse(),
element: elt,
}
}
impl<I, ElemF> Iterator for IntersperseWith<I, ElemF>
where
I: Iterator,
ElemF: IntersperseElement<I::Item>,
{
type Item = I::Item;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let Self {
element,
iter,
peek,
} = self;
match peek {
Some(item @ Some(_)) => item.take(),
Some(None) => match iter.next() {
new @ Some(_) => {
*peek = Some(new);
Some(element.generate())
}
None => None,
},
None => {
*peek = Some(None);
iter.next()
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let mut sh = self.iter.size_hint();
sh = size_hint::add(sh, sh);
match self.peek {
Some(Some(_)) => size_hint::add_scalar(sh, 1),
Some(None) => sh,
None => size_hint::sub_scalar(sh, 1),
}
}
fn fold<B, F>(self, init: B, mut f: F) -> B
where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
{
let Self {
mut element,
mut iter,
peek,
} = self;
let mut accum = init;
if let Some(x) = peek.unwrap_or_else(|| iter.next()) {
accum = f(accum, x);
}
iter.fold(accum, |accum, x| {
let accum = f(accum, element.generate());
f(accum, x)
})
}
}
impl<I, ElemF> FusedIterator for IntersperseWith<I, ElemF>
where
I: Iterator,
ElemF: IntersperseElement<I::Item>,
{
}

View File

@@ -0,0 +1,116 @@
use core::iter::{Skip, Take};
use core::ops::{Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive};
#[cfg(doc)]
use crate::Itertools;
mod private_iter_index {
use core::ops;
pub trait Sealed {}
impl Sealed for ops::Range<usize> {}
impl Sealed for ops::RangeInclusive<usize> {}
impl Sealed for ops::RangeTo<usize> {}
impl Sealed for ops::RangeToInclusive<usize> {}
impl Sealed for ops::RangeFrom<usize> {}
impl Sealed for ops::RangeFull {}
}
/// Used by [`Itertools::get`] to know which iterator
/// to turn different ranges into.
pub trait IteratorIndex<I>: private_iter_index::Sealed
where
I: Iterator,
{
/// The type returned for this type of index.
type Output: Iterator<Item = I::Item>;
/// Returns an adapted iterator for the current index.
///
/// Prefer calling [`Itertools::get`] instead
/// of calling this directly.
fn index(self, from: I) -> Self::Output;
}
impl<I> IteratorIndex<I> for Range<usize>
where
I: Iterator,
{
type Output = Skip<Take<I>>;
fn index(self, iter: I) -> Self::Output {
iter.take(self.end).skip(self.start)
}
}
impl<I> IteratorIndex<I> for RangeInclusive<usize>
where
I: Iterator,
{
type Output = Take<Skip<I>>;
fn index(self, iter: I) -> Self::Output {
// end - start + 1 without overflowing if possible
let length = if *self.end() == usize::MAX {
assert_ne!(*self.start(), 0);
self.end() - self.start() + 1
} else {
(self.end() + 1).saturating_sub(*self.start())
};
iter.skip(*self.start()).take(length)
}
}
impl<I> IteratorIndex<I> for RangeTo<usize>
where
I: Iterator,
{
type Output = Take<I>;
fn index(self, iter: I) -> Self::Output {
iter.take(self.end)
}
}
impl<I> IteratorIndex<I> for RangeToInclusive<usize>
where
I: Iterator,
{
type Output = Take<I>;
fn index(self, iter: I) -> Self::Output {
assert_ne!(self.end, usize::MAX);
iter.take(self.end + 1)
}
}
impl<I> IteratorIndex<I> for RangeFrom<usize>
where
I: Iterator,
{
type Output = Skip<I>;
fn index(self, iter: I) -> Self::Output {
iter.skip(self.start)
}
}
impl<I> IteratorIndex<I> for RangeFull
where
I: Iterator,
{
type Output = I;
fn index(self, iter: I) -> Self::Output {
iter
}
}
pub fn get<I, R>(iter: I, index: R) -> R::Output
where
I: IntoIterator,
R: IteratorIndex<I::IntoIter>,
{
index.index(iter.into_iter())
}

View File

@@ -0,0 +1,98 @@
use alloc::vec::Vec;
use core::cmp::Ordering;
/// Consumes a given iterator, returning the minimum elements in **ascending** order.
pub(crate) fn k_smallest_general<I, F>(iter: I, k: usize, mut comparator: F) -> Vec<I::Item>
where
I: Iterator,
F: FnMut(&I::Item, &I::Item) -> Ordering,
{
/// Sift the element currently at `origin` away from the root until it is properly ordered.
///
/// This will leave **larger** elements closer to the root of the heap.
fn sift_down<T, F>(heap: &mut [T], is_less_than: &mut F, mut origin: usize)
where
F: FnMut(&T, &T) -> bool,
{
#[inline]
fn children_of(n: usize) -> (usize, usize) {
(2 * n + 1, 2 * n + 2)
}
while origin < heap.len() {
let (left_idx, right_idx) = children_of(origin);
if left_idx >= heap.len() {
return;
}
let replacement_idx =
if right_idx < heap.len() && is_less_than(&heap[left_idx], &heap[right_idx]) {
right_idx
} else {
left_idx
};
if is_less_than(&heap[origin], &heap[replacement_idx]) {
heap.swap(origin, replacement_idx);
origin = replacement_idx;
} else {
return;
}
}
}
if k == 0 {
iter.last();
return Vec::new();
}
if k == 1 {
return iter.min_by(comparator).into_iter().collect();
}
let mut iter = iter.fuse();
let mut storage: Vec<I::Item> = iter.by_ref().take(k).collect();
let mut is_less_than = move |a: &_, b: &_| comparator(a, b) == Ordering::Less;
// Rearrange the storage into a valid heap by reordering from the second-bottom-most layer up to the root.
// Slightly faster than ordering on each insert, but only by a factor of lg(k).
// The resulting heap has the **largest** item on top.
for i in (0..=(storage.len() / 2)).rev() {
sift_down(&mut storage, &mut is_less_than, i);
}
iter.for_each(|val| {
debug_assert_eq!(storage.len(), k);
if is_less_than(&val, &storage[0]) {
// Treating this as an push-and-pop saves having to write a sift-up implementation.
// https://en.wikipedia.org/wiki/Binary_heap#Insert_then_extract
storage[0] = val;
// We retain the smallest items we've seen so far, but ordered largest first so we can drop the largest efficiently.
sift_down(&mut storage, &mut is_less_than, 0);
}
});
// Ultimately the items need to be in least-first, strict order, but the heap is currently largest-first.
// To achieve this, repeatedly,
// 1) "pop" the largest item off the heap into the tail slot of the underlying storage,
// 2) shrink the logical size of the heap by 1,
// 3) restore the heap property over the remaining items.
let mut heap = &mut storage[..];
while heap.len() > 1 {
let last_idx = heap.len() - 1;
heap.swap(0, last_idx);
// Sifting over a truncated slice means that the sifting will not disturb already popped elements.
heap = &mut heap[..last_idx];
sift_down(heap, &mut is_less_than, 0);
}
storage
}
#[inline]
pub(crate) fn key_to_cmp<T, K, F>(mut key: F) -> impl FnMut(&T, &T) -> Ordering
where
F: FnMut(&T) -> K,
K: Ord,
{
move |a, b| key(a).cmp(&key(b))
}

View File

@@ -0,0 +1,240 @@
use crate::size_hint;
use crate::Itertools;
use alloc::vec::Vec;
use std::fmt;
use std::iter::FusedIterator;
use std::mem::replace;
/// Head element and Tail iterator pair
///
/// `PartialEq`, `Eq`, `PartialOrd` and `Ord` are implemented by comparing sequences based on
/// first items (which are guaranteed to exist).
///
/// The meanings of `PartialOrd` and `Ord` are reversed so as to turn the heap used in
/// `KMerge` into a min-heap.
#[derive(Debug)]
struct HeadTail<I>
where
I: Iterator,
{
head: I::Item,
tail: I,
}
impl<I> HeadTail<I>
where
I: Iterator,
{
/// Constructs a `HeadTail` from an `Iterator`. Returns `None` if the `Iterator` is empty.
fn new(mut it: I) -> Option<Self> {
let head = it.next();
head.map(|h| Self { head: h, tail: it })
}
/// Get the next element and update `head`, returning the old head in `Some`.
///
/// Returns `None` when the tail is exhausted (only `head` then remains).
fn next(&mut self) -> Option<I::Item> {
if let Some(next) = self.tail.next() {
Some(replace(&mut self.head, next))
} else {
None
}
}
/// Hints at the size of the sequence, same as the `Iterator` method.
fn size_hint(&self) -> (usize, Option<usize>) {
size_hint::add_scalar(self.tail.size_hint(), 1)
}
}
impl<I> Clone for HeadTail<I>
where
I: Iterator + Clone,
I::Item: Clone,
{
clone_fields!(head, tail);
}
/// Make `data` a heap (min-heap w.r.t the sorting).
fn heapify<T, S>(data: &mut [T], mut less_than: S)
where
S: FnMut(&T, &T) -> bool,
{
for i in (0..data.len() / 2).rev() {
sift_down(data, i, &mut less_than);
}
}
/// Sift down element at `index` (`heap` is a min-heap wrt the ordering)
fn sift_down<T, S>(heap: &mut [T], index: usize, mut less_than: S)
where
S: FnMut(&T, &T) -> bool,
{
debug_assert!(index <= heap.len());
let mut pos = index;
let mut child = 2 * pos + 1;
// Require the right child to be present
// This allows to find the index of the smallest child without a branch
// that wouldn't be predicted if present
while child + 1 < heap.len() {
// pick the smaller of the two children
// use arithmetic to avoid an unpredictable branch
child += less_than(&heap[child + 1], &heap[child]) as usize;
// sift down is done if we are already in order
if !less_than(&heap[child], &heap[pos]) {
return;
}
heap.swap(pos, child);
pos = child;
child = 2 * pos + 1;
}
// Check if the last (left) child was an only child
// if it is then it has to be compared with the parent
if child + 1 == heap.len() && less_than(&heap[child], &heap[pos]) {
heap.swap(pos, child);
}
}
/// An iterator adaptor that merges an abitrary number of base iterators in ascending order.
/// If all base iterators are sorted (ascending), the result is sorted.
///
/// Iterator element type is `I::Item`.
///
/// See [`.kmerge()`](crate::Itertools::kmerge) for more information.
pub type KMerge<I> = KMergeBy<I, KMergeByLt>;
pub trait KMergePredicate<T> {
fn kmerge_pred(&mut self, a: &T, b: &T) -> bool;
}
#[derive(Clone, Debug)]
pub struct KMergeByLt;
impl<T: PartialOrd> KMergePredicate<T> for KMergeByLt {
fn kmerge_pred(&mut self, a: &T, b: &T) -> bool {
a < b
}
}
impl<T, F: FnMut(&T, &T) -> bool> KMergePredicate<T> for F {
fn kmerge_pred(&mut self, a: &T, b: &T) -> bool {
self(a, b)
}
}
/// Create an iterator that merges elements of the contained iterators using
/// the ordering function.
///
/// [`IntoIterator`] enabled version of [`Itertools::kmerge`].
///
/// ```
/// use itertools::kmerge;
///
/// for elt in kmerge(vec![vec![0, 2, 4], vec![1, 3, 5], vec![6, 7]]) {
/// /* loop body */
/// }
/// ```
pub fn kmerge<I>(iterable: I) -> KMerge<<I::Item as IntoIterator>::IntoIter>
where
I: IntoIterator,
I::Item: IntoIterator,
<<I as IntoIterator>::Item as IntoIterator>::Item: PartialOrd,
{
kmerge_by(iterable, KMergeByLt)
}
/// An iterator adaptor that merges an abitrary number of base iterators
/// according to an ordering function.
///
/// Iterator element type is `I::Item`.
///
/// See [`.kmerge_by()`](crate::Itertools::kmerge_by) for more
/// information.
#[must_use = "this iterator adaptor is not lazy but does nearly nothing unless consumed"]
pub struct KMergeBy<I, F>
where
I: Iterator,
{
heap: Vec<HeadTail<I>>,
less_than: F,
}
impl<I, F> fmt::Debug for KMergeBy<I, F>
where
I: Iterator + fmt::Debug,
I::Item: fmt::Debug,
{
debug_fmt_fields!(KMergeBy, heap);
}
/// Create an iterator that merges elements of the contained iterators.
///
/// [`IntoIterator`] enabled version of [`Itertools::kmerge_by`].
pub fn kmerge_by<I, F>(
iterable: I,
mut less_than: F,
) -> KMergeBy<<I::Item as IntoIterator>::IntoIter, F>
where
I: IntoIterator,
I::Item: IntoIterator,
F: KMergePredicate<<<I as IntoIterator>::Item as IntoIterator>::Item>,
{
let iter = iterable.into_iter();
let (lower, _) = iter.size_hint();
let mut heap: Vec<_> = Vec::with_capacity(lower);
heap.extend(iter.filter_map(|it| HeadTail::new(it.into_iter())));
heapify(&mut heap, |a, b| less_than.kmerge_pred(&a.head, &b.head));
KMergeBy { heap, less_than }
}
impl<I, F> Clone for KMergeBy<I, F>
where
I: Iterator + Clone,
I::Item: Clone,
F: Clone,
{
clone_fields!(heap, less_than);
}
impl<I, F> Iterator for KMergeBy<I, F>
where
I: Iterator,
F: KMergePredicate<I::Item>,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
if self.heap.is_empty() {
return None;
}
let result = if let Some(next) = self.heap[0].next() {
next
} else {
self.heap.swap_remove(0).head
};
let less_than = &mut self.less_than;
sift_down(&mut self.heap, 0, |a, b| {
less_than.kmerge_pred(&a.head, &b.head)
});
Some(result)
}
fn size_hint(&self) -> (usize, Option<usize>) {
#[allow(deprecated)] //TODO: once msrv hits 1.51. replace `fold1` with `reduce`
self.heap
.iter()
.map(|i| i.size_hint())
.fold1(size_hint::add)
.unwrap_or((0, Some(0)))
}
}
impl<I, F> FusedIterator for KMergeBy<I, F>
where
I: Iterator,
F: KMergePredicate<I::Item>,
{
}

View File

@@ -0,0 +1,75 @@
use alloc::vec::Vec;
use std::iter::Fuse;
use std::ops::Index;
use crate::size_hint::{self, SizeHint};
#[derive(Debug, Clone)]
pub struct LazyBuffer<I: Iterator> {
it: Fuse<I>,
buffer: Vec<I::Item>,
}
impl<I> LazyBuffer<I>
where
I: Iterator,
{
pub fn new(it: I) -> Self {
Self {
it: it.fuse(),
buffer: Vec::new(),
}
}
pub fn len(&self) -> usize {
self.buffer.len()
}
pub fn size_hint(&self) -> SizeHint {
size_hint::add_scalar(self.it.size_hint(), self.len())
}
pub fn count(self) -> usize {
self.len() + self.it.count()
}
pub fn get_next(&mut self) -> bool {
if let Some(x) = self.it.next() {
self.buffer.push(x);
true
} else {
false
}
}
pub fn prefill(&mut self, len: usize) {
let buffer_len = self.buffer.len();
if len > buffer_len {
let delta = len - buffer_len;
self.buffer.extend(self.it.by_ref().take(delta));
}
}
}
impl<I> LazyBuffer<I>
where
I: Iterator,
I::Item: Clone,
{
pub fn get_at(&self, indices: &[usize]) -> Vec<I::Item> {
indices.iter().map(|i| self.buffer[*i].clone()).collect()
}
}
impl<I, J> Index<J> for LazyBuffer<I>
where
I: Iterator,
I::Item: Sized,
Vec<I::Item>: Index<J>,
{
type Output = <Vec<I::Item> as Index<J>>::Output;
fn index(&self, index: J) -> &Self::Output {
self.buffer.index(index)
}
}

4365
vendor/itertools-0.13.0/src/lib.rs vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,347 @@
use std::cmp::Ordering;
use std::fmt;
use std::iter::{Fuse, FusedIterator};
use std::marker::PhantomData;
use either::Either;
use super::adaptors::{put_back, PutBack};
use crate::either_or_both::EitherOrBoth;
use crate::size_hint::{self, SizeHint};
#[cfg(doc)]
use crate::Itertools;
#[derive(Clone, Debug)]
pub struct MergeLte;
/// An iterator adaptor that merges the two base iterators in ascending order.
/// If both base iterators are sorted (ascending), the result is sorted.
///
/// Iterator element type is `I::Item`.
///
/// See [`.merge()`](crate::Itertools::merge_by) for more information.
pub type Merge<I, J> = MergeBy<I, J, MergeLte>;
/// Create an iterator that merges elements in `i` and `j`.
///
/// [`IntoIterator`] enabled version of [`Itertools::merge`](crate::Itertools::merge).
///
/// ```
/// use itertools::merge;
///
/// for elt in merge(&[1, 2, 3], &[2, 3, 4]) {
/// /* loop body */
/// }
/// ```
pub fn merge<I, J>(
i: I,
j: J,
) -> Merge<<I as IntoIterator>::IntoIter, <J as IntoIterator>::IntoIter>
where
I: IntoIterator,
J: IntoIterator<Item = I::Item>,
I::Item: PartialOrd,
{
merge_by_new(i, j, MergeLte)
}
/// An iterator adaptor that merges the two base iterators in ascending order.
/// If both base iterators are sorted (ascending), the result is sorted.
///
/// Iterator element type is `I::Item`.
///
/// See [`.merge_by()`](crate::Itertools::merge_by) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct MergeBy<I: Iterator, J: Iterator, F> {
left: PutBack<Fuse<I>>,
right: PutBack<Fuse<J>>,
cmp_fn: F,
}
/// Create a `MergeBy` iterator.
pub fn merge_by_new<I, J, F>(a: I, b: J, cmp: F) -> MergeBy<I::IntoIter, J::IntoIter, F>
where
I: IntoIterator,
J: IntoIterator<Item = I::Item>,
{
MergeBy {
left: put_back(a.into_iter().fuse()),
right: put_back(b.into_iter().fuse()),
cmp_fn: cmp,
}
}
/// 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, 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) -> T,
{
MergeBy {
left: put_back(left.into_iter().fuse()),
right: put_back(right.into_iter().fuse()),
cmp_fn: MergeFuncLR(cmp_fn, PhantomData),
}
}
/// An iterator adaptor that merge-joins items from the two base iterators in ascending order.
///
/// See [`.merge_join_by()`](crate::Itertools::merge_join_by) for more information.
pub type MergeJoinBy<I, J, F> =
MergeBy<I, J, MergeFuncLR<F, <F as FuncLR<<I as Iterator>::Item, <J as Iterator>::Item>>::T>>;
#[derive(Clone, Debug)]
pub struct MergeFuncLR<F, T>(F, PhantomData<T>);
pub trait FuncLR<L, R> {
type T;
}
impl<L, R, T, F: FnMut(&L, &R) -> T> FuncLR<L, R> for F {
type T = T;
}
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(&mut self, left: L, right: R) -> (Option<Either<L, R>>, Self::MergeResult);
fn size_hint(left: SizeHint, right: SizeHint) -> SizeHint;
}
impl<L, R, F: FnMut(&L, &R) -> Ordering> OrderingOrBool<L, R> for MergeFuncLR<F, 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(&mut self, left: L, right: R) -> (Option<Either<L, R>>, Self::MergeResult) {
match self.0(&left, &right) {
Ordering::Equal => (None, EitherOrBoth::Both(left, right)),
Ordering::Less => (Some(Either::Right(right)), EitherOrBoth::Left(left)),
Ordering::Greater => (Some(Either::Left(left)), 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, F: FnMut(&L, &R) -> bool> OrderingOrBool<L, R> for MergeFuncLR<F, 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(&mut self, left: L, right: R) -> (Option<Either<L, R>>, Self::MergeResult) {
if self.0(&left, &right) {
(Some(Either::Right(right)), Either::Left(left))
} else {
(Some(Either::Left(left)), 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<T, F: FnMut(&T, &T) -> bool> OrderingOrBool<T, T> for F {
type MergeResult = T;
fn left(left: T) -> Self::MergeResult {
left
}
fn right(right: T) -> Self::MergeResult {
right
}
fn merge(&mut self, left: T, right: T) -> (Option<Either<T, T>>, Self::MergeResult) {
if self(&left, &right) {
(Some(Either::Right(right)), left)
} else {
(Some(Either::Left(left)), right)
}
}
fn size_hint(left: SizeHint, right: SizeHint) -> SizeHint {
// Not ExactSizeIterator because size may be larger than usize
size_hint::add(left, right)
}
}
impl<T: PartialOrd> OrderingOrBool<T, T> for MergeLte {
type MergeResult = T;
fn left(left: T) -> Self::MergeResult {
left
}
fn right(right: T) -> Self::MergeResult {
right
}
fn merge(&mut self, left: T, right: T) -> (Option<Either<T, T>>, Self::MergeResult) {
if left <= right {
(Some(Either::Right(right)), left)
} else {
(Some(Either::Left(left)), 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 MergeBy<I, J, F>
where
I: Iterator,
J: Iterator,
PutBack<Fuse<I>>: Clone,
PutBack<Fuse<J>>: Clone,
F: Clone,
{
clone_fields!(left, right, cmp_fn);
}
impl<I, J, F> fmt::Debug for MergeBy<I, J, F>
where
I: Iterator + fmt::Debug,
I::Item: fmt::Debug,
J: Iterator + fmt::Debug,
J::Item: fmt::Debug,
{
debug_fmt_fields!(MergeBy, left, right);
}
impl<I, J, F> Iterator for MergeBy<I, J, F>
where
I: Iterator,
J: Iterator,
F: OrderingOrBool<I::Item, J::Item>,
{
type Item = F::MergeResult;
fn next(&mut self) -> Option<Self::Item> {
match (self.left.next(), self.right.next()) {
(None, None) => None,
(Some(left), None) => Some(F::left(left)),
(None, Some(right)) => Some(F::right(right)),
(Some(left), Some(right)) => {
let (not_next, next) = self.cmp_fn.merge(left, right);
match not_next {
Some(Either::Left(l)) => {
self.left.put_back(l);
}
Some(Either::Right(r)) => {
self.right.put_back(r);
}
None => (),
}
Some(next)
}
}
}
fn fold<B, G>(mut self, init: B, mut f: G) -> B
where
Self: Sized,
G: FnMut(B, Self::Item) -> B,
{
let mut acc = init;
let mut left = self.left.next();
let mut right = self.right.next();
loop {
match (left, right) {
(Some(l), Some(r)) => match self.cmp_fn.merge(l, r) {
(Some(Either::Right(r)), x) => {
acc = f(acc, x);
left = self.left.next();
right = Some(r);
}
(Some(Either::Left(l)), x) => {
acc = f(acc, x);
left = Some(l);
right = self.right.next();
}
(None, x) => {
acc = f(acc, x);
left = self.left.next();
right = self.right.next();
}
},
(Some(l), None) => {
self.left.put_back(l);
acc = self.left.fold(acc, |acc, x| f(acc, F::left(x)));
break;
}
(None, Some(r)) => {
self.right.put_back(r);
acc = self.right.fold(acc, |acc, x| f(acc, F::right(x)));
break;
}
(None, None) => {
break;
}
}
}
acc
}
fn size_hint(&self) -> SizeHint {
F::size_hint(self.left.size_hint(), self.right.size_hint())
}
fn nth(&mut self, mut n: usize) -> Option<Self::Item> {
loop {
if n == 0 {
break self.next();
}
n -= 1;
match (self.left.next(), self.right.next()) {
(None, None) => break None,
(Some(_left), None) => break self.left.nth(n).map(F::left),
(None, Some(_right)) => break self.right.nth(n).map(F::right),
(Some(left), Some(right)) => {
let (not_next, _) = self.cmp_fn.merge(left, right);
match not_next {
Some(Either::Left(l)) => {
self.left.put_back(l);
}
Some(Either::Right(r)) => {
self.right.put_back(r);
}
None => (),
}
}
}
}
}
}
impl<I, J, F> FusedIterator for MergeBy<I, J, F>
where
I: Iterator,
J: Iterator,
F: OrderingOrBool<I::Item, J::Item>,
{
}

116
vendor/itertools-0.13.0/src/minmax.rs vendored Normal file
View File

@@ -0,0 +1,116 @@
/// `MinMaxResult` is an enum returned by `minmax`.
///
/// See [`.minmax()`](crate::Itertools::minmax) for more detail.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum MinMaxResult<T> {
/// Empty iterator
NoElements,
/// Iterator with one element, so the minimum and maximum are the same
OneElement(T),
/// More than one element in the iterator, the first element is not larger
/// than the second
MinMax(T, T),
}
impl<T: Clone> MinMaxResult<T> {
/// `into_option` creates an `Option` of type `(T, T)`. The returned `Option`
/// has variant `None` if and only if the `MinMaxResult` has variant
/// `NoElements`. Otherwise `Some((x, y))` is returned where `x <= y`.
/// If the `MinMaxResult` has variant `OneElement(x)`, performing this
/// operation will make one clone of `x`.
///
/// # Examples
///
/// ```
/// use itertools::MinMaxResult::{self, NoElements, OneElement, MinMax};
///
/// let r: MinMaxResult<i32> = NoElements;
/// assert_eq!(r.into_option(), None);
///
/// let r = OneElement(1);
/// assert_eq!(r.into_option(), Some((1, 1)));
///
/// let r = MinMax(1, 2);
/// assert_eq!(r.into_option(), Some((1, 2)));
/// ```
pub fn into_option(self) -> Option<(T, T)> {
match self {
Self::NoElements => None,
Self::OneElement(x) => Some((x.clone(), x)),
Self::MinMax(x, y) => Some((x, y)),
}
}
}
/// Implementation guts for `minmax` and `minmax_by_key`.
pub fn minmax_impl<I, K, F, L>(mut it: I, mut key_for: F, mut lt: L) -> MinMaxResult<I::Item>
where
I: Iterator,
F: FnMut(&I::Item) -> K,
L: FnMut(&I::Item, &I::Item, &K, &K) -> bool,
{
let (mut min, mut max, mut min_key, mut max_key) = match it.next() {
None => return MinMaxResult::NoElements,
Some(x) => match it.next() {
None => return MinMaxResult::OneElement(x),
Some(y) => {
let xk = key_for(&x);
let yk = key_for(&y);
if !lt(&y, &x, &yk, &xk) {
(x, y, xk, yk)
} else {
(y, x, yk, xk)
}
}
},
};
loop {
// `first` and `second` are the two next elements we want to look
// at. We first compare `first` and `second` (#1). The smaller one
// is then compared to current minimum (#2). The larger one is
// compared to current maximum (#3). This way we do 3 comparisons
// for 2 elements.
let first = match it.next() {
None => break,
Some(x) => x,
};
let second = match it.next() {
None => {
let first_key = key_for(&first);
if lt(&first, &min, &first_key, &min_key) {
min = first;
} else if !lt(&first, &max, &first_key, &max_key) {
max = first;
}
break;
}
Some(x) => x,
};
let first_key = key_for(&first);
let second_key = key_for(&second);
if !lt(&second, &first, &second_key, &first_key) {
if lt(&first, &min, &first_key, &min_key) {
min = first;
min_key = first_key;
}
if !lt(&second, &max, &second_key, &max_key) {
max = second;
max_key = second_key;
}
} else {
if lt(&second, &min, &second_key, &min_key) {
min = second;
min_key = second_key;
}
if !lt(&first, &max, &first_key, &max_key) {
max = first;
max_key = first_key;
}
}
}
MinMaxResult::MinMax(min, max)
}

View File

@@ -0,0 +1,116 @@
use crate::size_hint;
#[cfg(doc)]
use crate::Itertools;
use crate::PeekingNext;
use alloc::collections::VecDeque;
use std::iter::Fuse;
/// See [`multipeek()`] for more information.
#[derive(Clone, Debug)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct MultiPeek<I>
where
I: Iterator,
{
iter: Fuse<I>,
buf: VecDeque<I::Item>,
index: usize,
}
/// An iterator adaptor that allows the user to peek at multiple `.next()`
/// values without advancing the base iterator.
///
/// [`IntoIterator`] enabled version of [`Itertools::multipeek`].
pub fn multipeek<I>(iterable: I) -> MultiPeek<I::IntoIter>
where
I: IntoIterator,
{
MultiPeek {
iter: iterable.into_iter().fuse(),
buf: VecDeque::new(),
index: 0,
}
}
impl<I> MultiPeek<I>
where
I: Iterator,
{
/// Reset the peeking “cursor”
pub fn reset_peek(&mut self) {
self.index = 0;
}
}
impl<I: Iterator> MultiPeek<I> {
/// Works exactly like `.next()` with the only difference that it doesn't
/// advance itself. `.peek()` can be called multiple times, to peek
/// further ahead.
/// When `.next()` is called, reset the peeking “cursor”.
pub fn peek(&mut self) -> Option<&I::Item> {
let ret = if self.index < self.buf.len() {
Some(&self.buf[self.index])
} else {
match self.iter.next() {
Some(x) => {
self.buf.push_back(x);
Some(&self.buf[self.index])
}
None => return None,
}
};
self.index += 1;
ret
}
}
impl<I> PeekingNext for MultiPeek<I>
where
I: Iterator,
{
fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
where
F: FnOnce(&Self::Item) -> bool,
{
if self.buf.is_empty() {
if let Some(r) = self.peek() {
if !accept(r) {
return None;
}
}
} else if let Some(r) = self.buf.front() {
if !accept(r) {
return None;
}
}
self.next()
}
}
impl<I> Iterator for MultiPeek<I>
where
I: Iterator,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
self.index = 0;
self.buf.pop_front().or_else(|| self.iter.next())
}
fn size_hint(&self) -> (usize, Option<usize>) {
size_hint::add_scalar(self.iter.size_hint(), self.buf.len())
}
fn fold<B, F>(self, mut init: B, mut f: F) -> B
where
F: FnMut(B, Self::Item) -> B,
{
init = self.buf.into_iter().fold(init, &mut f);
self.iter.fold(init, f)
}
}
// Same size
impl<I> ExactSizeIterator for MultiPeek<I> where I: ExactSizeIterator {}

124
vendor/itertools-0.13.0/src/pad_tail.rs vendored Normal file
View File

@@ -0,0 +1,124 @@
use crate::size_hint;
use std::iter::{Fuse, FusedIterator};
/// An iterator adaptor that pads a sequence to a minimum length by filling
/// missing elements using a closure.
///
/// Iterator element type is `I::Item`.
///
/// See [`.pad_using()`](crate::Itertools::pad_using) for more information.
#[derive(Clone)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct PadUsing<I, F> {
iter: Fuse<I>,
min: usize,
pos: usize,
filler: F,
}
impl<I, F> std::fmt::Debug for PadUsing<I, F>
where
I: std::fmt::Debug,
{
debug_fmt_fields!(PadUsing, iter, min, pos);
}
/// Create a new `PadUsing` iterator.
pub fn pad_using<I, F>(iter: I, min: usize, filler: F) -> PadUsing<I, F>
where
I: Iterator,
F: FnMut(usize) -> I::Item,
{
PadUsing {
iter: iter.fuse(),
min,
pos: 0,
filler,
}
}
impl<I, F> Iterator for PadUsing<I, F>
where
I: Iterator,
F: FnMut(usize) -> I::Item,
{
type Item = I::Item;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
match self.iter.next() {
None => {
if self.pos < self.min {
let e = Some((self.filler)(self.pos));
self.pos += 1;
e
} else {
None
}
}
e => {
self.pos += 1;
e
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let tail = self.min.saturating_sub(self.pos);
size_hint::max(self.iter.size_hint(), (tail, Some(tail)))
}
fn fold<B, G>(self, mut init: B, mut f: G) -> B
where
G: FnMut(B, Self::Item) -> B,
{
let mut pos = self.pos;
init = self.iter.fold(init, |acc, item| {
pos += 1;
f(acc, item)
});
(pos..self.min).map(self.filler).fold(init, f)
}
}
impl<I, F> DoubleEndedIterator for PadUsing<I, F>
where
I: DoubleEndedIterator + ExactSizeIterator,
F: FnMut(usize) -> I::Item,
{
fn next_back(&mut self) -> Option<Self::Item> {
if self.min == 0 {
self.iter.next_back()
} else if self.iter.len() >= self.min {
self.min -= 1;
self.iter.next_back()
} else {
self.min -= 1;
Some((self.filler)(self.min))
}
}
fn rfold<B, G>(self, mut init: B, mut f: G) -> B
where
G: FnMut(B, Self::Item) -> B,
{
init = (self.iter.len()..self.min)
.map(self.filler)
.rfold(init, &mut f);
self.iter.rfold(init, f)
}
}
impl<I, F> ExactSizeIterator for PadUsing<I, F>
where
I: ExactSizeIterator,
F: FnMut(usize) -> I::Item,
{
}
impl<I, F> FusedIterator for PadUsing<I, F>
where
I: FusedIterator,
F: FnMut(usize) -> I::Item,
{
}

178
vendor/itertools-0.13.0/src/peek_nth.rs vendored Normal file
View File

@@ -0,0 +1,178 @@
use crate::size_hint;
use crate::PeekingNext;
use alloc::collections::VecDeque;
use std::iter::Fuse;
/// See [`peek_nth()`] for more information.
#[derive(Clone, Debug)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct PeekNth<I>
where
I: Iterator,
{
iter: Fuse<I>,
buf: VecDeque<I::Item>,
}
/// A drop-in replacement for [`std::iter::Peekable`] which adds a `peek_nth`
/// method allowing the user to `peek` at a value several iterations forward
/// without advancing the base iterator.
///
/// This differs from `multipeek` in that subsequent calls to `peek` or
/// `peek_nth` will always return the same value until `next` is called
/// (making `reset_peek` unnecessary).
pub fn peek_nth<I>(iterable: I) -> PeekNth<I::IntoIter>
where
I: IntoIterator,
{
PeekNth {
iter: iterable.into_iter().fuse(),
buf: VecDeque::new(),
}
}
impl<I> PeekNth<I>
where
I: Iterator,
{
/// Works exactly like the `peek` method in [`std::iter::Peekable`].
pub fn peek(&mut self) -> Option<&I::Item> {
self.peek_nth(0)
}
/// Works exactly like the `peek_mut` method in [`std::iter::Peekable`].
pub fn peek_mut(&mut self) -> Option<&mut I::Item> {
self.peek_nth_mut(0)
}
/// Returns a reference to the `nth` value without advancing the iterator.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use itertools::peek_nth;
///
/// let xs = vec![1, 2, 3];
/// let mut iter = peek_nth(xs.into_iter());
///
/// assert_eq!(iter.peek_nth(0), Some(&1));
/// assert_eq!(iter.next(), Some(1));
///
/// // The iterator does not advance even if we call `peek_nth` multiple times
/// assert_eq!(iter.peek_nth(0), Some(&2));
/// assert_eq!(iter.peek_nth(1), Some(&3));
/// assert_eq!(iter.next(), Some(2));
///
/// // Calling `peek_nth` past the end of the iterator will return `None`
/// assert_eq!(iter.peek_nth(1), None);
/// ```
pub fn peek_nth(&mut self, n: usize) -> Option<&I::Item> {
let unbuffered_items = (n + 1).saturating_sub(self.buf.len());
self.buf.extend(self.iter.by_ref().take(unbuffered_items));
self.buf.get(n)
}
/// Returns a mutable reference to the `nth` value without advancing the iterator.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use itertools::peek_nth;
///
/// let xs = vec![1, 2, 3, 4, 5];
/// let mut iter = peek_nth(xs.into_iter());
///
/// assert_eq!(iter.peek_nth_mut(0), Some(&mut 1));
/// assert_eq!(iter.next(), Some(1));
///
/// // The iterator does not advance even if we call `peek_nth_mut` multiple times
/// assert_eq!(iter.peek_nth_mut(0), Some(&mut 2));
/// assert_eq!(iter.peek_nth_mut(1), Some(&mut 3));
/// assert_eq!(iter.next(), Some(2));
///
/// // Peek into the iterator and set the value behind the mutable reference.
/// if let Some(p) = iter.peek_nth_mut(1) {
/// assert_eq!(*p, 4);
/// *p = 9;
/// }
///
/// // The value we put in reappears as the iterator continues.
/// assert_eq!(iter.next(), Some(3));
/// assert_eq!(iter.next(), Some(9));
///
/// // Calling `peek_nth_mut` past the end of the iterator will return `None`
/// assert_eq!(iter.peek_nth_mut(1), None);
/// ```
pub fn peek_nth_mut(&mut self, n: usize) -> Option<&mut I::Item> {
let unbuffered_items = (n + 1).saturating_sub(self.buf.len());
self.buf.extend(self.iter.by_ref().take(unbuffered_items));
self.buf.get_mut(n)
}
/// Works exactly like the `next_if` method in [`std::iter::Peekable`].
pub fn next_if(&mut self, func: impl FnOnce(&I::Item) -> bool) -> Option<I::Item> {
match self.next() {
Some(item) if func(&item) => Some(item),
Some(item) => {
self.buf.push_front(item);
None
}
_ => None,
}
}
/// Works exactly like the `next_if_eq` method in [`std::iter::Peekable`].
pub fn next_if_eq<T>(&mut self, expected: &T) -> Option<I::Item>
where
T: ?Sized,
I::Item: PartialEq<T>,
{
self.next_if(|next| next == expected)
}
}
impl<I> Iterator for PeekNth<I>
where
I: Iterator,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
self.buf.pop_front().or_else(|| self.iter.next())
}
fn size_hint(&self) -> (usize, Option<usize>) {
size_hint::add_scalar(self.iter.size_hint(), self.buf.len())
}
fn fold<B, F>(self, mut init: B, mut f: F) -> B
where
F: FnMut(B, Self::Item) -> B,
{
init = self.buf.into_iter().fold(init, &mut f);
self.iter.fold(init, f)
}
}
impl<I> ExactSizeIterator for PeekNth<I> where I: ExactSizeIterator {}
impl<I> PeekingNext for PeekNth<I>
where
I: Iterator,
{
fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
where
F: FnOnce(&Self::Item) -> bool,
{
self.peek().filter(|item| accept(item))?;
self.next()
}
}

View File

@@ -0,0 +1,201 @@
use crate::PutBack;
#[cfg(feature = "use_alloc")]
use crate::PutBackN;
use crate::RepeatN;
use std::iter::Peekable;
/// An iterator that allows peeking at an element before deciding to accept it.
///
/// See [`.peeking_take_while()`](crate::Itertools::peeking_take_while)
/// for more information.
///
/// This is implemented by peeking adaptors like peekable and put back,
/// but also by a few iterators that can be peeked natively, like the slices
/// by reference iterator ([`std::slice::Iter`]).
pub trait PeekingNext: Iterator {
/// Pass a reference to the next iterator element to the closure `accept`;
/// if `accept` returns `true`, return it as the next element,
/// else `None`.
fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
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>
where
I: Iterator,
{
fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
where
F: FnOnce(&Self::Item) -> bool,
{
if let Some(r) = self.peek() {
if !accept(r) {
return None;
}
}
self.next()
}
}
impl<I> PeekingNext for PutBack<I>
where
I: Iterator,
{
fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
where
F: FnOnce(&Self::Item) -> bool,
{
if let Some(r) = self.next() {
if !accept(&r) {
self.put_back(r);
return None;
}
Some(r)
} else {
None
}
}
}
#[cfg(feature = "use_alloc")]
impl<I> PeekingNext for PutBackN<I>
where
I: Iterator,
{
fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
where
F: FnOnce(&Self::Item) -> bool,
{
if let Some(r) = self.next() {
if !accept(&r) {
self.put_back(r);
return None;
}
Some(r)
} else {
None
}
}
}
impl<T: Clone> PeekingNext for RepeatN<T> {
fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
where
F: FnOnce(&Self::Item) -> bool,
{
let r = self.elt.as_ref()?;
if !accept(r) {
return None;
}
self.next()
}
}
/// An iterator adaptor that takes items while a closure returns `true`.
///
/// See [`.peeking_take_while()`](crate::Itertools::peeking_take_while)
/// for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct PeekingTakeWhile<'a, I, F>
where
I: Iterator + 'a,
{
iter: &'a mut I,
f: F,
}
impl<'a, I, F> std::fmt::Debug for PeekingTakeWhile<'a, I, F>
where
I: Iterator + std::fmt::Debug + 'a,
{
debug_fmt_fields!(PeekingTakeWhile, iter);
}
/// Create a `PeekingTakeWhile`
pub fn peeking_take_while<I, F>(iter: &mut I, f: F) -> PeekingTakeWhile<I, F>
where
I: Iterator,
{
PeekingTakeWhile { iter, f }
}
impl<'a, I, F> Iterator for PeekingTakeWhile<'a, I, F>
where
I: PeekingNext,
F: FnMut(&I::Item) -> bool,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
self.iter.peeking_next(&mut self.f)
}
fn size_hint(&self) -> (usize, Option<usize>) {
(0, self.iter.size_hint().1)
}
}
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 {
([$($typarm:tt)*] $type_:ty) => {
impl<$($typarm)*> PeekingNext for $type_ {
fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
where F: FnOnce(&Self::Item) -> bool
{
let saved_state = self.clone();
if let Some(r) = self.next() {
if !accept(&r) {
*self = saved_state;
} else {
return Some(r)
}
}
None
}
}
}
}
peeking_next_by_clone! { ['a, T] ::std::slice::Iter<'a, T> }
peeking_next_by_clone! { ['a] ::std::str::Chars<'a> }
peeking_next_by_clone! { ['a] ::std::str::CharIndices<'a> }
peeking_next_by_clone! { ['a] ::std::str::Bytes<'a> }
peeking_next_by_clone! { ['a, T] ::std::option::Iter<'a, T> }
peeking_next_by_clone! { ['a, T] ::std::result::Iter<'a, T> }
peeking_next_by_clone! { [T] ::std::iter::Empty<T> }
#[cfg(feature = "use_alloc")]
peeking_next_by_clone! { ['a, T] alloc::collections::linked_list::Iter<'a, T> }
#[cfg(feature = "use_alloc")]
peeking_next_by_clone! { ['a, T] alloc::collections::vec_deque::Iter<'a, T> }
// cloning a Rev has no extra overhead; peekable and put backs are never DEI.
peeking_next_by_clone! { [I: Clone + PeekingNext + DoubleEndedIterator]
::std::iter::Rev<I> }

View File

@@ -0,0 +1,186 @@
use alloc::boxed::Box;
use alloc::vec::Vec;
use std::fmt;
use std::iter::once;
use std::iter::FusedIterator;
use super::lazy_buffer::LazyBuffer;
use crate::size_hint::{self, SizeHint};
/// An iterator adaptor that iterates through all the `k`-permutations of the
/// elements from an iterator.
///
/// See [`.permutations()`](crate::Itertools::permutations) for
/// more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct Permutations<I: Iterator> {
vals: LazyBuffer<I>,
state: PermutationState,
}
impl<I> Clone for Permutations<I>
where
I: Clone + Iterator,
I::Item: Clone,
{
clone_fields!(vals, state);
}
#[derive(Clone, Debug)]
enum PermutationState {
/// No permutation generated yet.
Start { k: usize },
/// Values from the iterator are not fully loaded yet so `n` is still unknown.
Buffered { k: usize, min_n: usize },
/// All values from the iterator are known so `n` is known.
Loaded {
indices: Box<[usize]>,
cycles: Box<[usize]>,
},
/// No permutation left to generate.
End,
}
impl<I> fmt::Debug for Permutations<I>
where
I: Iterator + fmt::Debug,
I::Item: fmt::Debug,
{
debug_fmt_fields!(Permutations, vals, state);
}
pub fn permutations<I: Iterator>(iter: I, k: usize) -> Permutations<I> {
Permutations {
vals: LazyBuffer::new(iter),
state: PermutationState::Start { k },
}
}
impl<I> Iterator for Permutations<I>
where
I: Iterator,
I::Item: Clone,
{
type Item = Vec<I::Item>;
fn next(&mut self) -> Option<Self::Item> {
let Self { vals, state } = self;
match state {
PermutationState::Start { k: 0 } => {
*state = PermutationState::End;
Some(Vec::new())
}
&mut PermutationState::Start { k } => {
vals.prefill(k);
if vals.len() != k {
*state = PermutationState::End;
return None;
}
*state = PermutationState::Buffered { k, min_n: k };
Some(vals[0..k].to_vec())
}
PermutationState::Buffered { ref k, min_n } => {
if vals.get_next() {
let item = (0..*k - 1)
.chain(once(*min_n))
.map(|i| vals[i].clone())
.collect();
*min_n += 1;
Some(item)
} else {
let n = *min_n;
let prev_iteration_count = n - *k + 1;
let mut indices: Box<[_]> = (0..n).collect();
let mut cycles: Box<[_]> = (n - k..n).rev().collect();
// Advance the state to the correct point.
for _ in 0..prev_iteration_count {
if advance(&mut indices, &mut cycles) {
*state = PermutationState::End;
return None;
}
}
let item = vals.get_at(&indices[0..*k]);
*state = PermutationState::Loaded { indices, cycles };
Some(item)
}
}
PermutationState::Loaded { indices, cycles } => {
if advance(indices, cycles) {
*state = PermutationState::End;
return None;
}
let k = cycles.len();
Some(vals.get_at(&indices[0..k]))
}
PermutationState::End => None,
}
}
fn count(self) -> usize {
let Self { vals, state } = self;
let n = vals.count();
state.size_hint_for(n).1.unwrap()
}
fn size_hint(&self) -> SizeHint {
let (mut low, mut upp) = self.vals.size_hint();
low = self.state.size_hint_for(low).0;
upp = upp.and_then(|n| self.state.size_hint_for(n).1);
(low, upp)
}
}
impl<I> FusedIterator for Permutations<I>
where
I: Iterator,
I::Item: Clone,
{
}
fn advance(indices: &mut [usize], cycles: &mut [usize]) -> bool {
let n = indices.len();
let k = cycles.len();
// NOTE: if `cycles` are only zeros, then we reached the last permutation.
for i in (0..k).rev() {
if cycles[i] == 0 {
cycles[i] = n - i - 1;
indices[i..].rotate_left(1);
} else {
let swap_index = n - cycles[i];
indices.swap(i, swap_index);
cycles[i] -= 1;
return false;
}
}
true
}
impl PermutationState {
fn size_hint_for(&self, n: usize) -> SizeHint {
// At the beginning, there are `n!/(n-k)!` items to come.
let at_start = |n, k| {
debug_assert!(n >= k);
let total = (n - k + 1..=n).try_fold(1usize, |acc, i| acc.checked_mul(i));
(total.unwrap_or(usize::MAX), total)
};
match *self {
Self::Start { k } if n < k => (0, Some(0)),
Self::Start { k } => at_start(n, k),
Self::Buffered { k, min_n } => {
// Same as `Start` minus the previously generated items.
size_hint::sub_scalar(at_start(n, k), min_n - k + 1)
}
Self::Loaded {
ref indices,
ref cycles,
} => {
let count = cycles.iter().enumerate().try_fold(0usize, |acc, (i, &c)| {
acc.checked_mul(indices.len() - i)
.and_then(|count| count.checked_add(c))
});
(count.unwrap_or(usize::MAX), count)
}
Self::End => (0, Some(0)),
}
}
}

131
vendor/itertools-0.13.0/src/powerset.rs vendored Normal file
View File

@@ -0,0 +1,131 @@
use alloc::vec::Vec;
use std::fmt;
use std::iter::FusedIterator;
use super::combinations::{combinations, Combinations};
use crate::adaptors::checked_binomial;
use crate::size_hint::{self, SizeHint};
/// An iterator to iterate through the powerset of the elements from an iterator.
///
/// See [`.powerset()`](crate::Itertools::powerset) for more
/// information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct Powerset<I: Iterator> {
combs: Combinations<I>,
}
impl<I> Clone for Powerset<I>
where
I: Clone + Iterator,
I::Item: Clone,
{
clone_fields!(combs);
}
impl<I> fmt::Debug for Powerset<I>
where
I: Iterator + fmt::Debug,
I::Item: fmt::Debug,
{
debug_fmt_fields!(Powerset, combs);
}
/// Create a new `Powerset` from a clonable iterator.
pub fn powerset<I>(src: I) -> Powerset<I>
where
I: Iterator,
I::Item: Clone,
{
Powerset {
combs: combinations(src, 0),
}
}
impl<I: Iterator> Powerset<I> {
/// Returns true if `k` has been incremented, false otherwise.
fn increment_k(&mut self) -> bool {
if self.combs.k() < self.combs.n() || self.combs.k() == 0 {
self.combs.reset(self.combs.k() + 1);
true
} else {
false
}
}
}
impl<I> Iterator for Powerset<I>
where
I: Iterator,
I::Item: Clone,
{
type Item = Vec<I::Item>;
fn next(&mut self) -> Option<Self::Item> {
if let Some(elt) = self.combs.next() {
Some(elt)
} else if self.increment_k() {
self.combs.next()
} else {
None
}
}
fn nth(&mut self, mut n: usize) -> Option<Self::Item> {
loop {
match self.combs.try_nth(n) {
Ok(item) => return Some(item),
Err(steps) => {
if !self.increment_k() {
return None;
}
n -= steps;
}
}
}
}
fn size_hint(&self) -> SizeHint {
let k = self.combs.k();
// Total bounds for source iterator.
let (n_min, n_max) = self.combs.src().size_hint();
let low = remaining_for(n_min, k).unwrap_or(usize::MAX);
let upp = n_max.and_then(|n| remaining_for(n, k));
size_hint::add(self.combs.size_hint(), (low, upp))
}
fn count(self) -> usize {
let k = self.combs.k();
let (n, combs_count) = self.combs.n_and_count();
combs_count + remaining_for(n, k).unwrap()
}
fn fold<B, F>(self, mut init: B, mut f: F) -> B
where
F: FnMut(B, Self::Item) -> B,
{
let mut it = self.combs;
if it.k() == 0 {
init = it.by_ref().fold(init, &mut f);
it.reset(1);
}
init = it.by_ref().fold(init, &mut f);
// n is now known for sure because k >= 1 and all k-combinations have been generated.
for k in it.k() + 1..=it.n() {
it.reset(k);
init = it.by_ref().fold(init, &mut f);
}
init
}
}
impl<I> FusedIterator for Powerset<I>
where
I: Iterator,
I::Item: Clone,
{
}
fn remaining_for(n: usize, k: usize) -> Option<usize> {
(k + 1..=n).try_fold(0usize, |sum, i| sum.checked_add(checked_binomial(n, i)?))
}

View File

@@ -0,0 +1,108 @@
#[cfg(doc)]
use crate::Itertools;
/// An iterator that produces only the `T` values as long as the
/// inner iterator produces `Ok(T)`.
///
/// Used by [`process_results`](crate::process_results), see its docs
/// for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Debug)]
pub struct ProcessResults<'a, I, E: 'a> {
error: &'a mut Result<(), E>,
iter: I,
}
impl<'a, I, E> ProcessResults<'a, I, E> {
#[inline(always)]
fn next_body<T>(&mut self, item: Option<Result<T, E>>) -> Option<T> {
match item {
Some(Ok(x)) => Some(x),
Some(Err(e)) => {
*self.error = Err(e);
None
}
None => None,
}
}
}
impl<'a, I, T, E> Iterator for ProcessResults<'a, I, E>
where
I: Iterator<Item = Result<T, E>>,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let item = self.iter.next();
self.next_body(item)
}
fn size_hint(&self) -> (usize, Option<usize>) {
(0, self.iter.size_hint().1)
}
fn fold<B, F>(mut self, init: B, mut f: F) -> B
where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
{
let error = self.error;
self.iter
.try_fold(init, |acc, opt| match opt {
Ok(x) => Ok(f(acc, x)),
Err(e) => {
*error = Err(e);
Err(acc)
}
})
.unwrap_or_else(|e| e)
}
}
impl<'a, I, T, E> DoubleEndedIterator for ProcessResults<'a, I, E>
where
I: Iterator<Item = Result<T, E>>,
I: DoubleEndedIterator,
{
fn next_back(&mut self) -> Option<Self::Item> {
let item = self.iter.next_back();
self.next_body(item)
}
fn rfold<B, F>(mut self, init: B, mut f: F) -> B
where
F: FnMut(B, Self::Item) -> B,
{
let error = self.error;
self.iter
.try_rfold(init, |acc, opt| match opt {
Ok(x) => Ok(f(acc, x)),
Err(e) => {
*error = Err(e);
Err(acc)
}
})
.unwrap_or_else(|e| e)
}
}
/// “Lift” a function of the values of an iterator so that it can process
/// an iterator of `Result` values instead.
///
/// [`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,
{
let iter = iterable.into_iter();
let mut error = Ok(());
let result = processor(ProcessResults {
error: &mut error,
iter,
});
error.map(|_| result)
}

View File

@@ -0,0 +1,71 @@
use alloc::vec::Vec;
use crate::size_hint;
/// An iterator adaptor that allows putting multiple
/// items in front of the iterator.
///
/// Iterator element type is `I::Item`.
#[derive(Debug, Clone)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct PutBackN<I: Iterator> {
top: Vec<I::Item>,
iter: I,
}
/// Create an iterator where you can put back multiple values to the front
/// of the iteration.
///
/// Iterator element type is `I::Item`.
pub fn put_back_n<I>(iterable: I) -> PutBackN<I::IntoIter>
where
I: IntoIterator,
{
PutBackN {
top: Vec::new(),
iter: iterable.into_iter(),
}
}
impl<I: Iterator> PutBackN<I> {
/// Puts `x` in front of the iterator.
///
/// The values are yielded in order of the most recently put back
/// values first.
///
/// ```rust
/// use itertools::put_back_n;
///
/// let mut it = put_back_n(1..5);
/// it.next();
/// it.put_back(1);
/// it.put_back(0);
///
/// assert!(itertools::equal(it, 0..5));
/// ```
#[inline]
pub fn put_back(&mut self, x: I::Item) {
self.top.push(x);
}
}
impl<I: Iterator> Iterator for PutBackN<I> {
type Item = I::Item;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.top.pop().or_else(|| self.iter.next())
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
size_hint::add_scalar(self.iter.size_hint(), self.top.len())
}
fn fold<B, F>(self, mut init: B, mut f: F) -> B
where
F: FnMut(B, Self::Item) -> B,
{
init = self.top.into_iter().rfold(init, &mut f);
self.iter.fold(init, f)
}
}

View File

@@ -0,0 +1,102 @@
use alloc::rc::Rc;
use std::cell::RefCell;
use std::iter::{FusedIterator, IntoIterator};
/// A wrapper for `Rc<RefCell<I>>`, that implements the `Iterator` trait.
#[derive(Debug)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct RcIter<I> {
/// The boxed iterator.
pub rciter: Rc<RefCell<I>>,
}
/// Return an iterator inside a `Rc<RefCell<_>>` wrapper.
///
/// The returned `RcIter` can be cloned, and each clone will refer back to the
/// same original iterator.
///
/// `RcIter` allows doing interesting things like using `.zip()` on an iterator with
/// itself, at the cost of runtime borrow checking which may have a performance
/// penalty.
///
/// Iterator element type is `Self::Item`.
///
/// ```
/// use itertools::rciter;
/// use itertools::zip;
///
/// // In this example a range iterator is created and we iterate it using
/// // three separate handles (two of them given to zip).
/// // We also use the IntoIterator implementation for `&RcIter`.
///
/// let mut iter = rciter(0..9);
/// let mut z = zip(&iter, &iter);
///
/// assert_eq!(z.next(), Some((0, 1)));
/// assert_eq!(z.next(), Some((2, 3)));
/// assert_eq!(z.next(), Some((4, 5)));
/// assert_eq!(iter.next(), Some(6));
/// assert_eq!(z.next(), Some((7, 8)));
/// assert_eq!(z.next(), None);
/// ```
///
/// **Panics** in iterator methods if a borrow error is encountered in the
/// iterator methods. It can only happen if the `RcIter` is reentered in
/// `.next()`, i.e. if it somehow participates in an “iterator knot”
/// where it is an adaptor of itself.
pub fn rciter<I>(iterable: I) -> RcIter<I::IntoIter>
where
I: IntoIterator,
{
RcIter {
rciter: Rc::new(RefCell::new(iterable.into_iter())),
}
}
impl<I> Clone for RcIter<I> {
clone_fields!(rciter);
}
impl<A, I> Iterator for RcIter<I>
where
I: Iterator<Item = A>,
{
type Item = A;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.rciter.borrow_mut().next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
// To work sanely with other API that assume they own an iterator,
// so it can't change in other places, we can't guarantee as much
// in our size_hint. Other clones may drain values under our feet.
(0, self.rciter.borrow().size_hint().1)
}
}
impl<I> DoubleEndedIterator for RcIter<I>
where
I: DoubleEndedIterator,
{
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.rciter.borrow_mut().next_back()
}
}
/// Return an iterator from `&RcIter<I>` (by simply cloning it).
impl<'a, I> IntoIterator for &'a RcIter<I>
where
I: Iterator,
{
type Item = I::Item;
type IntoIter = RcIter<I>;
fn into_iter(self) -> RcIter<I> {
self.clone()
}
}
impl<A, I> FusedIterator for RcIter<I> where I: FusedIterator<Item = A> {}

83
vendor/itertools-0.13.0/src/repeatn.rs vendored Normal file
View File

@@ -0,0 +1,83 @@
use std::iter::FusedIterator;
/// An iterator that produces *n* repetitions of an element.
///
/// See [`repeat_n()`](crate::repeat_n) for more information.
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[derive(Clone, Debug)]
pub struct RepeatN<A> {
pub(crate) elt: Option<A>,
n: usize,
}
/// Create an iterator that produces `n` repetitions of `element`.
pub fn repeat_n<A>(element: A, n: usize) -> RepeatN<A>
where
A: Clone,
{
if n == 0 {
RepeatN { elt: None, n }
} else {
RepeatN {
elt: Some(element),
n,
}
}
}
impl<A> Iterator for RepeatN<A>
where
A: Clone,
{
type Item = A;
fn next(&mut self) -> Option<Self::Item> {
if self.n > 1 {
self.n -= 1;
self.elt.as_ref().cloned()
} else {
self.n = 0;
self.elt.take()
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.n, Some(self.n))
}
fn fold<B, F>(self, mut init: B, mut f: F) -> B
where
F: FnMut(B, Self::Item) -> B,
{
match self {
Self { elt: Some(elt), n } => {
debug_assert!(n > 0);
init = (1..n).map(|_| elt.clone()).fold(init, &mut f);
f(init, elt)
}
_ => init,
}
}
}
impl<A> DoubleEndedIterator for RepeatN<A>
where
A: Clone,
{
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.next()
}
#[inline]
fn rfold<B, F>(self, init: B, f: F) -> B
where
F: FnMut(B, Self::Item) -> B,
{
self.fold(init, f)
}
}
impl<A> ExactSizeIterator for RepeatN<A> where A: Clone {}
impl<A> FusedIterator for RepeatN<A> where A: Clone {}

View File

@@ -0,0 +1,94 @@
//! Arithmetic on `Iterator.size_hint()` values.
//!
use std::cmp;
/// `SizeHint` is the return type of `Iterator::size_hint()`.
pub type SizeHint = (usize, Option<usize>);
/// Add `SizeHint` correctly.
#[inline]
pub fn add(a: SizeHint, b: SizeHint) -> SizeHint {
let min = a.0.saturating_add(b.0);
let max = match (a.1, b.1) {
(Some(x), Some(y)) => x.checked_add(y),
_ => None,
};
(min, max)
}
/// Add `x` correctly to a `SizeHint`.
#[inline]
pub fn add_scalar(sh: SizeHint, x: usize) -> SizeHint {
let (mut low, mut hi) = sh;
low = low.saturating_add(x);
hi = hi.and_then(|elt| elt.checked_add(x));
(low, hi)
}
/// Subtract `x` correctly from a `SizeHint`.
#[inline]
pub fn sub_scalar(sh: SizeHint, x: usize) -> SizeHint {
let (mut low, mut hi) = sh;
low = low.saturating_sub(x);
hi = hi.map(|elt| elt.saturating_sub(x));
(low, hi)
}
/// Multiply `SizeHint` correctly
#[inline]
pub fn mul(a: SizeHint, b: SizeHint) -> SizeHint {
let low = a.0.saturating_mul(b.0);
let hi = match (a.1, b.1) {
(Some(x), Some(y)) => x.checked_mul(y),
(Some(0), None) | (None, Some(0)) => Some(0),
_ => None,
};
(low, hi)
}
/// Multiply `x` correctly with a `SizeHint`.
#[inline]
pub fn mul_scalar(sh: SizeHint, x: usize) -> SizeHint {
let (mut low, mut hi) = sh;
low = low.saturating_mul(x);
hi = hi.and_then(|elt| elt.checked_mul(x));
(low, hi)
}
/// Return the maximum
#[inline]
pub fn max(a: SizeHint, b: SizeHint) -> SizeHint {
let (a_lower, a_upper) = a;
let (b_lower, b_upper) = b;
let lower = cmp::max(a_lower, b_lower);
let upper = match (a_upper, b_upper) {
(Some(x), Some(y)) => Some(cmp::max(x, y)),
_ => None,
};
(lower, upper)
}
/// Return the minimum
#[inline]
pub fn min(a: SizeHint, b: SizeHint) -> SizeHint {
let (a_lower, a_upper) = a;
let (b_lower, b_upper) = b;
let lower = cmp::min(a_lower, b_lower);
let upper = match (a_upper, b_upper) {
(Some(u1), Some(u2)) => Some(cmp::min(u1, u2)),
_ => a_upper.or(b_upper),
};
(lower, upper)
}
#[test]
fn mul_size_hints() {
assert_eq!(mul((3, Some(4)), (3, Some(4))), (9, Some(16)));
assert_eq!(mul((3, Some(4)), (usize::MAX, None)), (usize::MAX, None));
assert_eq!(mul((3, None), (0, Some(0))), (0, Some(0)));
}

153
vendor/itertools-0.13.0/src/sources.rs vendored Normal file
View File

@@ -0,0 +1,153 @@
//! Iterators that are sources (produce elements from parameters,
//! not from another iterator).
#![allow(deprecated)]
use std::fmt;
use std::mem;
/// Creates a new unfold source with the specified closure as the "iterator
/// function" and an initial state to eventually pass to the closure
///
/// `unfold` is a general iterator builder: it has a mutable state value,
/// and a closure with access to the state that produces the next value.
///
/// This more or less equivalent to a regular struct with an [`Iterator`]
/// implementation, and is useful for one-off iterators.
///
/// ```
/// // an iterator that yields sequential Fibonacci numbers,
/// // and stops at the maximum representable value.
///
/// use itertools::unfold;
///
/// let mut fibonacci = unfold((1u32, 1u32), |(x1, x2)| {
/// // Attempt to get the next Fibonacci number
/// let next = x1.saturating_add(*x2);
///
/// // Shift left: ret <- x1 <- x2 <- next
/// let ret = *x1;
/// *x1 = *x2;
/// *x2 = next;
///
/// // If addition has saturated at the maximum, we are finished
/// if ret == *x1 && ret > 1 {
/// None
/// } else {
/// Some(ret)
/// }
/// });
///
/// itertools::assert_equal(fibonacci.by_ref().take(8),
/// vec![1, 1, 2, 3, 5, 8, 13, 21]);
/// assert_eq!(fibonacci.last(), Some(2_971_215_073))
/// ```
#[deprecated(
note = "Use [std::iter::from_fn](https://doc.rust-lang.org/std/iter/fn.from_fn.html) instead",
since = "0.13.0"
)]
pub fn unfold<A, St, F>(initial_state: St, f: F) -> Unfold<St, F>
where
F: FnMut(&mut St) -> Option<A>,
{
Unfold {
f,
state: initial_state,
}
}
impl<St, F> fmt::Debug for Unfold<St, F>
where
St: fmt::Debug,
{
debug_fmt_fields!(Unfold, state);
}
/// See [`unfold`](crate::unfold) for more information.
#[derive(Clone)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[deprecated(
note = "Use [std::iter::FromFn](https://doc.rust-lang.org/std/iter/struct.FromFn.html) instead",
since = "0.13.0"
)]
pub struct Unfold<St, F> {
f: F,
/// Internal state that will be passed to the closure on the next iteration
pub state: St,
}
impl<A, St, F> Iterator for Unfold<St, F>
where
F: FnMut(&mut St) -> Option<A>,
{
type Item = A;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
(self.f)(&mut self.state)
}
}
/// An iterator that infinitely applies function to value and yields results.
///
/// This `struct` is created by the [`iterate()`](crate::iterate) function.
/// See its documentation for more.
#[derive(Clone)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct Iterate<St, F> {
state: St,
f: F,
}
impl<St, F> fmt::Debug for Iterate<St, F>
where
St: fmt::Debug,
{
debug_fmt_fields!(Iterate, state);
}
impl<St, F> Iterator for Iterate<St, F>
where
F: FnMut(&St) -> St,
{
type Item = St;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let next_state = (self.f)(&self.state);
Some(mem::replace(&mut self.state, next_state))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(usize::MAX, None)
}
}
/// Creates a new iterator that infinitely applies function to value and yields results.
///
/// ```
/// use itertools::iterate;
///
/// itertools::assert_equal(iterate(1, |i| i % 3 + 1).take(5), vec![1, 2, 3, 1, 2]);
/// ```
///
/// **Panics** if compute the next value does.
///
/// ```should_panic
/// # use itertools::iterate;
/// let mut it = iterate(25u32, |x| x - 10).take_while(|&x| x > 10);
/// assert_eq!(it.next(), Some(25)); // `Iterate` holds 15.
/// assert_eq!(it.next(), Some(15)); // `Iterate` holds 5.
/// it.next(); // `5 - 10` overflows.
/// ```
///
/// You can alternatively use [`core::iter::successors`] as it better describes a finite iterator.
pub fn iterate<St, F>(initial_value: St, f: F) -> Iterate<St, F>
where
F: FnMut(&St) -> St,
{
Iterate {
state: initial_value,
f,
}
}

View File

@@ -0,0 +1,96 @@
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"]
#[derive(Clone)]
pub struct TakeWhileInclusive<I, F> {
iter: I,
predicate: F,
done: bool,
}
impl<I, F> TakeWhileInclusive<I, F>
where
I: Iterator,
F: FnMut(&I::Item) -> bool,
{
/// Create a new [`TakeWhileInclusive`] from an iterator and a predicate.
pub(crate) fn new(iter: I, predicate: F) -> Self {
Self {
iter,
predicate,
done: false,
}
}
}
impl<I, F> fmt::Debug for TakeWhileInclusive<I, F>
where
I: Iterator + fmt::Debug,
{
debug_fmt_fields!(TakeWhileInclusive, iter, done);
}
impl<I, F> Iterator for TakeWhileInclusive<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)
}
}
fn fold<B, Fold>(mut self, init: B, mut f: Fold) -> B
where
Fold: FnMut(B, Self::Item) -> B,
{
if self.done {
init
} else {
let predicate = &mut self.predicate;
self.iter
.try_fold(init, |mut acc, item| {
let is_ok = predicate(&item);
acc = f(acc, item);
if is_ok {
Ok(acc)
} else {
Err(acc)
}
})
.unwrap_or_else(|err| err)
}
}
}
impl<I, F> FusedIterator for TakeWhileInclusive<I, F>
where
I: Iterator,
F: FnMut(&I::Item) -> bool,
{
}

93
vendor/itertools-0.13.0/src/tee.rs vendored Normal file
View File

@@ -0,0 +1,93 @@
use super::size_hint;
use alloc::collections::VecDeque;
use alloc::rc::Rc;
use std::cell::RefCell;
/// Common buffer object for the two tee halves
#[derive(Debug)]
struct TeeBuffer<A, I> {
backlog: VecDeque<A>,
iter: I,
/// The owner field indicates which id should read from the backlog
owner: bool,
}
/// One half of an iterator pair where both return the same elements.
///
/// See [`.tee()`](crate::Itertools::tee) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Debug)]
pub struct Tee<I>
where
I: Iterator,
{
rcbuffer: Rc<RefCell<TeeBuffer<I::Item, I>>>,
id: bool,
}
pub fn new<I>(iter: I) -> (Tee<I>, Tee<I>)
where
I: Iterator,
{
let buffer = TeeBuffer {
backlog: VecDeque::new(),
iter,
owner: false,
};
let t1 = Tee {
rcbuffer: Rc::new(RefCell::new(buffer)),
id: true,
};
let t2 = Tee {
rcbuffer: t1.rcbuffer.clone(),
id: false,
};
(t1, t2)
}
impl<I> Iterator for Tee<I>
where
I: Iterator,
I::Item: Clone,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
// .borrow_mut may fail here -- but only if the user has tied some kind of weird
// knot where the iterator refers back to itself.
let mut buffer = self.rcbuffer.borrow_mut();
if buffer.owner == self.id {
match buffer.backlog.pop_front() {
None => {}
some_elt => return some_elt,
}
}
match buffer.iter.next() {
None => None,
Some(elt) => {
buffer.backlog.push_back(elt.clone());
buffer.owner = !self.id;
Some(elt)
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let buffer = self.rcbuffer.borrow();
let sh = buffer.iter.size_hint();
if buffer.owner == self.id {
let log_len = buffer.backlog.len();
size_hint::add_scalar(sh, log_len)
} else {
sh
}
}
}
impl<I> ExactSizeIterator for Tee<I>
where
I: ExactSizeIterator,
I::Item: Clone,
{
}

View File

@@ -0,0 +1,401 @@
//! Some iterator that produces tuples
use std::iter::Cycle;
use std::iter::Fuse;
use std::iter::FusedIterator;
use crate::size_hint;
// `HomogeneousTuple` is a public facade for `TupleCollect`, allowing
// tuple-related methods to be used by clients in generic contexts, while
// hiding the implementation details of `TupleCollect`.
// See https://github.com/rust-itertools/itertools/issues/387
/// Implemented for homogeneous tuples of size up to 12.
pub trait HomogeneousTuple: TupleCollect {}
impl<T: TupleCollect> HomogeneousTuple for T {}
/// An iterator over a incomplete tuple.
///
/// See [`.tuples()`](crate::Itertools::tuples) and
/// [`Tuples::into_buffer()`].
#[derive(Clone, Debug)]
pub struct TupleBuffer<T>
where
T: HomogeneousTuple,
{
cur: usize,
buf: T::Buffer,
}
impl<T> TupleBuffer<T>
where
T: HomogeneousTuple,
{
fn new(buf: T::Buffer) -> Self {
Self { cur: 0, buf }
}
}
impl<T> Iterator for TupleBuffer<T>
where
T: HomogeneousTuple,
{
type Item = T::Item;
fn next(&mut self) -> Option<Self::Item> {
let s = self.buf.as_mut();
if let Some(ref mut item) = s.get_mut(self.cur) {
self.cur += 1;
item.take()
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let buffer = &self.buf.as_ref()[self.cur..];
let len = if buffer.is_empty() {
0
} else {
buffer
.iter()
.position(|x| x.is_none())
.unwrap_or(buffer.len())
};
(len, Some(len))
}
}
impl<T> ExactSizeIterator for TupleBuffer<T> where T: HomogeneousTuple {}
/// An iterator that groups the items in tuples of a specific size.
///
/// See [`.tuples()`](crate::Itertools::tuples) for more information.
#[derive(Clone, Debug)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct Tuples<I, T>
where
I: Iterator<Item = T::Item>,
T: HomogeneousTuple,
{
iter: Fuse<I>,
buf: T::Buffer,
}
/// Create a new tuples iterator.
pub fn tuples<I, T>(iter: I) -> Tuples<I, T>
where
I: Iterator<Item = T::Item>,
T: HomogeneousTuple,
{
Tuples {
iter: iter.fuse(),
buf: Default::default(),
}
}
impl<I, T> Iterator for Tuples<I, T>
where
I: Iterator<Item = T::Item>,
T: HomogeneousTuple,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
T::collect_from_iter(&mut self.iter, &mut self.buf)
}
fn size_hint(&self) -> (usize, Option<usize>) {
// The number of elts we've drawn from the underlying iterator, but have
// not yet produced as a tuple.
let buffered = T::buffer_len(&self.buf);
// To that, we must add the size estimates of the underlying iterator.
let (unbuffered_lo, unbuffered_hi) = self.iter.size_hint();
// The total low estimate is the sum of the already-buffered elements,
// plus the low estimate of remaining unbuffered elements, divided by
// the tuple size.
let total_lo = add_then_div(unbuffered_lo, buffered, T::num_items()).unwrap_or(usize::MAX);
// And likewise for the total high estimate, but using the high estimate
// of the remaining unbuffered elements.
let total_hi = unbuffered_hi.and_then(|hi| add_then_div(hi, buffered, T::num_items()));
(total_lo, total_hi)
}
}
/// `(n + a) / d` avoiding overflow when possible, returns `None` if it overflows.
fn add_then_div(n: usize, a: usize, d: usize) -> Option<usize> {
debug_assert_ne!(d, 0);
(n / d).checked_add(a / d)?.checked_add((n % d + a % d) / d)
}
impl<I, T> ExactSizeIterator for Tuples<I, T>
where
I: ExactSizeIterator<Item = T::Item>,
T: HomogeneousTuple,
{
}
impl<I, T> Tuples<I, T>
where
I: Iterator<Item = T::Item>,
T: HomogeneousTuple,
{
/// Return a buffer with the produced items that was not enough to be grouped in a tuple.
///
/// ```
/// use itertools::Itertools;
///
/// let mut iter = (0..5).tuples();
/// assert_eq!(Some((0, 1, 2)), iter.next());
/// assert_eq!(None, iter.next());
/// itertools::assert_equal(vec![3, 4], iter.into_buffer());
/// ```
pub fn into_buffer(self) -> TupleBuffer<T> {
TupleBuffer::new(self.buf)
}
}
/// An iterator over all contiguous windows that produces tuples of a specific size.
///
/// See [`.tuple_windows()`](crate::Itertools::tuple_windows) for more
/// information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Clone, Debug)]
pub struct TupleWindows<I, T>
where
I: Iterator<Item = T::Item>,
T: HomogeneousTuple,
{
iter: I,
last: Option<T>,
}
/// Create a new tuple windows iterator.
pub fn tuple_windows<I, T>(iter: I) -> TupleWindows<I, T>
where
I: Iterator<Item = T::Item>,
T: HomogeneousTuple,
T::Item: Clone,
{
TupleWindows { last: None, iter }
}
impl<I, T> Iterator for TupleWindows<I, T>
where
I: Iterator<Item = T::Item>,
T: HomogeneousTuple + Clone,
T::Item: Clone,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if T::num_items() == 1 {
return T::collect_from_iter_no_buf(&mut self.iter);
}
if let Some(new) = self.iter.next() {
if let Some(ref mut last) = self.last {
last.left_shift_push(new);
Some(last.clone())
} else {
use std::iter::once;
let iter = once(new).chain(&mut self.iter);
self.last = T::collect_from_iter_no_buf(iter);
self.last.clone()
}
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let mut sh = self.iter.size_hint();
// Adjust the size hint at the beginning
// OR when `num_items == 1` (but it does not change the size hint).
if self.last.is_none() {
sh = size_hint::sub_scalar(sh, T::num_items() - 1);
}
sh
}
}
impl<I, T> ExactSizeIterator for TupleWindows<I, T>
where
I: ExactSizeIterator<Item = T::Item>,
T: HomogeneousTuple + Clone,
T::Item: Clone,
{
}
impl<I, T> FusedIterator for TupleWindows<I, T>
where
I: FusedIterator<Item = T::Item>,
T: HomogeneousTuple + Clone,
T::Item: Clone,
{
}
/// 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, Clone)]
pub struct CircularTupleWindows<I, T>
where
I: Iterator<Item = T::Item> + Clone,
T: TupleCollect + Clone,
{
iter: TupleWindows<Cycle<I>, T>,
len: usize,
}
pub fn circular_tuple_windows<I, T>(iter: I) -> CircularTupleWindows<I, T>
where
I: Iterator<Item = T::Item> + Clone + ExactSizeIterator,
T: TupleCollect + Clone,
T::Item: Clone,
{
let len = iter.len();
let iter = tuple_windows(iter.cycle());
CircularTupleWindows { iter, len }
}
impl<I, T> Iterator for CircularTupleWindows<I, T>
where
I: Iterator<Item = T::Item> + Clone,
T: TupleCollect + Clone,
T::Item: Clone,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.len != 0 {
self.len -= 1;
self.iter.next()
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
impl<I, T> ExactSizeIterator for CircularTupleWindows<I, T>
where
I: Iterator<Item = T::Item> + Clone,
T: TupleCollect + Clone,
T::Item: Clone,
{
}
impl<I, T> FusedIterator for CircularTupleWindows<I, T>
where
I: Iterator<Item = T::Item> + Clone,
T: TupleCollect + Clone,
T::Item: Clone,
{
}
pub trait TupleCollect: Sized {
type Item;
type Buffer: Default + AsRef<[Option<Self::Item>]> + AsMut<[Option<Self::Item>]>;
fn buffer_len(buf: &Self::Buffer) -> usize {
let s = buf.as_ref();
s.iter().position(Option::is_none).unwrap_or(s.len())
}
fn collect_from_iter<I>(iter: I, buf: &mut Self::Buffer) -> Option<Self>
where
I: IntoIterator<Item = Self::Item>;
fn collect_from_iter_no_buf<I>(iter: I) -> Option<Self>
where
I: IntoIterator<Item = Self::Item>;
fn num_items() -> usize;
fn left_shift_push(&mut self, item: Self::Item);
}
macro_rules! rev_for_each_ident{
($m:ident, ) => {};
($m:ident, $i0:ident, $($i:ident,)*) => {
rev_for_each_ident!($m, $($i,)*);
$m!($i0);
};
}
macro_rules! impl_tuple_collect {
($dummy:ident,) => {}; // stop
($dummy:ident, $($Y:ident,)*) => (
impl_tuple_collect!($($Y,)*);
impl<A> TupleCollect for ($(ignore_ident!($Y, A),)*) {
type Item = A;
type Buffer = [Option<A>; count_ident!($($Y)*) - 1];
#[allow(unused_assignments, unused_mut)]
fn collect_from_iter<I>(iter: I, buf: &mut Self::Buffer) -> Option<Self>
where I: IntoIterator<Item = A>
{
let mut iter = iter.into_iter();
$(
let mut $Y = None;
)*
loop {
$(
$Y = iter.next();
if $Y.is_none() {
break
}
)*
return Some(($($Y.unwrap()),*,))
}
let mut i = 0;
let mut s = buf.as_mut();
$(
if i < s.len() {
s[i] = $Y;
i += 1;
}
)*
return None;
}
fn collect_from_iter_no_buf<I>(iter: I) -> Option<Self>
where I: IntoIterator<Item = A>
{
let mut iter = iter.into_iter();
Some(($(
{ let $Y = iter.next()?; $Y },
)*))
}
fn num_items() -> usize {
count_ident!($($Y)*)
}
fn left_shift_push(&mut self, mut item: A) {
use std::mem::replace;
let &mut ($(ref mut $Y),*,) = self;
macro_rules! replace_item{($i:ident) => {
item = replace($i, item);
}}
rev_for_each_ident!(replace_item, $($Y,)*);
drop(item);
}
}
)
}
impl_tuple_collect!(dummy, a, b, c, d, e, f, g, h, i, j, k, l,);

View File

@@ -0,0 +1,188 @@
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::fmt;
use std::hash::Hash;
use std::iter::FusedIterator;
/// An iterator adapter to filter out duplicate elements.
///
/// See [`.unique_by()`](crate::Itertools::unique) for more information.
#[derive(Clone)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct UniqueBy<I: Iterator, V, F> {
iter: I,
// Use a Hashmap for the Entry API in order to prevent hashing twice.
// This can maybe be replaced with a HashSet once `get_or_insert_with`
// or a proper Entry API for Hashset is stable and meets this msrv
used: HashMap<V, ()>,
f: F,
}
impl<I, V, F> fmt::Debug for UniqueBy<I, V, F>
where
I: Iterator + fmt::Debug,
V: fmt::Debug + Hash + Eq,
{
debug_fmt_fields!(UniqueBy, iter, used);
}
/// Create a new `UniqueBy` iterator.
pub fn unique_by<I, V, F>(iter: I, f: F) -> UniqueBy<I, V, F>
where
V: Eq + Hash,
F: FnMut(&I::Item) -> V,
I: Iterator,
{
UniqueBy {
iter,
used: HashMap::new(),
f,
}
}
// count the number of new unique keys in iterable (`used` is the set already seen)
fn count_new_keys<I, K>(mut used: HashMap<K, ()>, iterable: I) -> usize
where
I: IntoIterator<Item = K>,
K: Hash + Eq,
{
let iter = iterable.into_iter();
let current_used = used.len();
used.extend(iter.map(|key| (key, ())));
used.len() - current_used
}
impl<I, V, F> Iterator for UniqueBy<I, V, F>
where
I: Iterator,
V: Eq + Hash,
F: FnMut(&I::Item) -> V,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
let Self { iter, used, f } = self;
iter.find(|v| used.insert(f(v), ()).is_none())
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let (low, hi) = self.iter.size_hint();
((low > 0 && self.used.is_empty()) as usize, hi)
}
fn count(self) -> usize {
let mut key_f = self.f;
count_new_keys(self.used, self.iter.map(move |elt| key_f(&elt)))
}
}
impl<I, V, F> DoubleEndedIterator for UniqueBy<I, V, F>
where
I: DoubleEndedIterator,
V: Eq + Hash,
F: FnMut(&I::Item) -> V,
{
fn next_back(&mut self) -> Option<Self::Item> {
let Self { iter, used, f } = self;
iter.rfind(|v| used.insert(f(v), ()).is_none())
}
}
impl<I, V, F> FusedIterator for UniqueBy<I, V, F>
where
I: FusedIterator,
V: Eq + Hash,
F: FnMut(&I::Item) -> V,
{
}
impl<I> Iterator for Unique<I>
where
I: Iterator,
I::Item: Eq + Hash + Clone,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
let UniqueBy { iter, used, .. } = &mut self.iter;
iter.find_map(|v| {
if let Entry::Vacant(entry) = used.entry(v) {
let elt = entry.key().clone();
entry.insert(());
return Some(elt);
}
None
})
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let (low, hi) = self.iter.iter.size_hint();
((low > 0 && self.iter.used.is_empty()) as usize, hi)
}
fn count(self) -> usize {
count_new_keys(self.iter.used, self.iter.iter)
}
}
impl<I> DoubleEndedIterator for Unique<I>
where
I: DoubleEndedIterator,
I::Item: Eq + Hash + Clone,
{
fn next_back(&mut self) -> Option<Self::Item> {
let UniqueBy { iter, used, .. } = &mut self.iter;
iter.rev().find_map(|v| {
if let Entry::Vacant(entry) = used.entry(v) {
let elt = entry.key().clone();
entry.insert(());
return Some(elt);
}
None
})
}
}
impl<I> FusedIterator for Unique<I>
where
I: FusedIterator,
I::Item: Eq + Hash + Clone,
{
}
/// An iterator adapter to filter out duplicate elements.
///
/// See [`.unique()`](crate::Itertools::unique) for more information.
#[derive(Clone)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct Unique<I>
where
I: Iterator,
I::Item: Eq + Hash + Clone,
{
iter: UniqueBy<I, I::Item, ()>,
}
impl<I> fmt::Debug for Unique<I>
where
I: Iterator + fmt::Debug,
I::Item: Hash + Eq + fmt::Debug + Clone,
{
debug_fmt_fields!(Unique, iter);
}
pub fn unique<I>(iter: I) -> Unique<I>
where
I: Iterator,
I::Item: Eq + Hash + Clone,
{
Unique {
iter: UniqueBy {
iter,
used: HashMap::new(),
f: (),
},
}
}

View File

@@ -0,0 +1,80 @@
/// Converts an iterator of tuples into a tuple of containers.
///
/// `multiunzip()` consumes an entire iterator of n-ary tuples, producing `n` collections, one for each
/// column.
///
/// This function is, in some sense, the opposite of [`multizip`].
///
/// ```
/// use itertools::multiunzip;
///
/// let inputs = vec![(1, 2, 3), (4, 5, 6), (7, 8, 9)];
///
/// let (a, b, c): (Vec<_>, Vec<_>, Vec<_>) = multiunzip(inputs);
///
/// assert_eq!(a, vec![1, 4, 7]);
/// assert_eq!(b, vec![2, 5, 8]);
/// assert_eq!(c, vec![3, 6, 9]);
/// ```
///
/// [`multizip`]: crate::multizip
pub fn multiunzip<FromI, I>(i: I) -> FromI
where
I: IntoIterator,
I::IntoIter: MultiUnzip<FromI>,
{
i.into_iter().multiunzip()
}
/// An iterator that can be unzipped into multiple collections.
///
/// See [`.multiunzip()`](crate::Itertools::multiunzip) for more information.
pub trait MultiUnzip<FromI>: Iterator {
/// Unzip this iterator into multiple collections.
fn multiunzip(self) -> FromI;
}
macro_rules! impl_unzip_iter {
($($T:ident => $FromT:ident),*) => (
#[allow(non_snake_case)]
impl<IT: Iterator<Item = ($($T,)*)>, $($T, $FromT: Default + Extend<$T>),* > MultiUnzip<($($FromT,)*)> for IT {
fn multiunzip(self) -> ($($FromT,)*) {
// This implementation mirrors the logic of Iterator::unzip resp. Extend for (A, B) as close as possible.
// Unfortunately a lot of the used api there is still unstable (https://github.com/rust-lang/rust/issues/72631).
//
// Iterator::unzip: https://doc.rust-lang.org/src/core/iter/traits/iterator.rs.html#2825-2865
// Extend for (A, B): https://doc.rust-lang.org/src/core/iter/traits/collect.rs.html#370-411
let mut res = ($($FromT::default(),)*);
let ($($FromT,)*) = &mut res;
// Still unstable #72631
// let (lower_bound, _) = self.size_hint();
// if lower_bound > 0 {
// $($FromT.extend_reserve(lower_bound);)*
// }
self.fold((), |(), ($($T,)*)| {
// Still unstable #72631
// $( $FromT.extend_one($T); )*
$( $FromT.extend(std::iter::once($T)); )*
});
res
}
}
);
}
impl_unzip_iter!();
impl_unzip_iter!(A => FromA);
impl_unzip_iter!(A => FromA, B => FromB);
impl_unzip_iter!(A => FromA, B => FromB, C => FromC);
impl_unzip_iter!(A => FromA, B => FromB, C => FromC, D => FromD);
impl_unzip_iter!(A => FromA, B => FromB, C => FromC, D => FromD, E => FromE);
impl_unzip_iter!(A => FromA, B => FromB, C => FromC, D => FromD, E => FromE, F => FromF);
impl_unzip_iter!(A => FromA, B => FromB, C => FromC, D => FromD, E => FromE, F => FromF, G => FromG);
impl_unzip_iter!(A => FromA, B => FromB, C => FromC, D => FromD, E => FromE, F => FromF, G => FromG, H => FromH);
impl_unzip_iter!(A => FromA, B => FromB, C => FromC, D => FromD, E => FromE, F => FromF, G => FromG, H => FromH, I => FromI);
impl_unzip_iter!(A => FromA, B => FromB, C => FromC, D => FromD, E => FromE, F => FromF, G => FromG, H => FromH, I => FromI, J => FromJ);
impl_unzip_iter!(A => FromA, B => FromB, C => FromC, D => FromD, E => FromE, F => FromF, G => FromG, H => FromH, I => FromI, J => FromJ, K => FromK);
impl_unzip_iter!(A => FromA, B => FromB, C => FromC, D => FromD, E => FromE, F => FromF, G => FromG, H => FromH, I => FromI, J => FromJ, K => FromK, L => FromL);

View File

@@ -0,0 +1,124 @@
use std::fmt;
use std::iter::{Fuse, FusedIterator, Peekable};
/// An iterator adaptor that wraps each element in an [`Position`].
///
/// 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"]
pub struct WithPosition<I>
where
I: Iterator,
{
handled_first: bool,
peekable: Peekable<Fuse<I>>,
}
impl<I> fmt::Debug for WithPosition<I>
where
I: Iterator,
Peekable<Fuse<I>>: fmt::Debug,
{
debug_fmt_fields!(WithPosition, handled_first, peekable);
}
impl<I> Clone for WithPosition<I>
where
I: Clone + Iterator,
I::Item: Clone,
{
clone_fields!(handled_first, peekable);
}
/// Create a new `WithPosition` iterator.
pub fn with_position<I>(iter: I) -> WithPosition<I>
where
I: Iterator,
{
WithPosition {
handled_first: false,
peekable: iter.fuse().peekable(),
}
}
/// 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, Eq)]
pub enum Position {
/// This is the first element.
First,
/// This is neither the first nor the last element.
Middle,
/// This is the last element.
Last,
/// This is the only element.
Only,
}
impl<I: Iterator> Iterator for WithPosition<I> {
type Item = (Position, I::Item);
fn next(&mut self) -> Option<Self::Item> {
match self.peekable.next() {
Some(item) => {
if !self.handled_first {
// Haven't seen the first item yet, and there is one to give.
self.handled_first = true;
// 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)),
}
} 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)),
}
}
}
// Iterator is finished.
None => None,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.peekable.size_hint()
}
fn fold<B, F>(mut self, mut init: B, mut f: F) -> B
where
F: FnMut(B, Self::Item) -> B,
{
if let Some(mut head) = self.peekable.next() {
if !self.handled_first {
// The current head is `First` or `Only`,
// it depends if there is another item or not.
match self.peekable.next() {
Some(second) => {
let first = std::mem::replace(&mut head, second);
init = f(init, (Position::First, first));
}
None => return f(init, (Position::Only, head)),
}
}
// Have seen the first item, and there's something left.
init = self.peekable.fold(init, |acc, mut item| {
std::mem::swap(&mut head, &mut item);
f(acc, (Position::Middle, item))
});
// The "head" is now the last item.
init = f(init, (Position::Last, head));
}
init
}
}
impl<I> ExactSizeIterator for WithPosition<I> where I: ExactSizeIterator {}
impl<I: Iterator> FusedIterator for WithPosition<I> {}

View File

@@ -0,0 +1,64 @@
use super::size_hint;
/// An iterator which iterates two other iterators simultaneously
/// and panic if they have different lengths.
///
/// See [`.zip_eq()`](crate::Itertools::zip_eq) for more information.
#[derive(Clone, Debug)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct ZipEq<I, J> {
a: I,
b: J,
}
/// Zips two iterators but **panics** if they are not of the same length.
///
/// [`IntoIterator`] enabled version of [`Itertools::zip_eq`](crate::Itertools::zip_eq).
///
/// ```
/// use itertools::zip_eq;
///
/// let data = [1, 2, 3, 4, 5];
/// for (a, b) in zip_eq(&data[..data.len() - 1], &data[1..]) {
/// /* loop body */
/// }
/// ```
pub fn zip_eq<I, J>(i: I, j: J) -> ZipEq<I::IntoIter, J::IntoIter>
where
I: IntoIterator,
J: IntoIterator,
{
ZipEq {
a: i.into_iter(),
b: j.into_iter(),
}
}
impl<I, J> Iterator for ZipEq<I, J>
where
I: Iterator,
J: Iterator,
{
type Item = (I::Item, J::Item);
fn next(&mut self) -> Option<Self::Item> {
match (self.a.next(), self.b.next()) {
(None, None) => None,
(Some(a), Some(b)) => Some((a, b)),
(None, Some(_)) | (Some(_), None) => {
panic!("itertools: .zip_eq() reached end of one iterator before the other")
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
size_hint::min(self.a.size_hint(), self.b.size_hint())
}
}
impl<I, J> ExactSizeIterator for ZipEq<I, J>
where
I: ExactSizeIterator,
J: ExactSizeIterator,
{
}

View File

@@ -0,0 +1,139 @@
use super::size_hint;
use std::cmp::Ordering::{Equal, Greater, Less};
use std::iter::{Fuse, FusedIterator};
use crate::either_or_both::EitherOrBoth;
// ZipLongest originally written by SimonSapin,
// and dedicated to itertools https://github.com/rust-lang/rust/pull/19283
/// An iterator which iterates two other iterators simultaneously
/// and wraps the elements in [`EitherOrBoth`].
///
/// This iterator is *fused*.
///
/// See [`.zip_longest()`](crate::Itertools::zip_longest) for more information.
#[derive(Clone, Debug)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct ZipLongest<T, U> {
a: Fuse<T>,
b: Fuse<U>,
}
/// Create a new `ZipLongest` iterator.
pub fn zip_longest<T, U>(a: T, b: U) -> ZipLongest<T, U>
where
T: Iterator,
U: Iterator,
{
ZipLongest {
a: a.fuse(),
b: b.fuse(),
}
}
impl<T, U> Iterator for ZipLongest<T, U>
where
T: Iterator,
U: Iterator,
{
type Item = EitherOrBoth<T::Item, U::Item>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
match (self.a.next(), self.b.next()) {
(None, None) => None,
(Some(a), None) => Some(EitherOrBoth::Left(a)),
(None, Some(b)) => Some(EitherOrBoth::Right(b)),
(Some(a), Some(b)) => Some(EitherOrBoth::Both(a, b)),
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
size_hint::max(self.a.size_hint(), self.b.size_hint())
}
#[inline]
fn fold<B, F>(self, init: B, mut f: F) -> B
where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
{
let Self { mut a, mut b } = self;
let res = a.try_fold(init, |init, a| match b.next() {
Some(b) => Ok(f(init, EitherOrBoth::Both(a, b))),
None => Err(f(init, EitherOrBoth::Left(a))),
});
match res {
Ok(acc) => b.map(EitherOrBoth::Right).fold(acc, f),
Err(acc) => a.map(EitherOrBoth::Left).fold(acc, f),
}
}
}
impl<T, U> DoubleEndedIterator for ZipLongest<T, U>
where
T: DoubleEndedIterator + ExactSizeIterator,
U: DoubleEndedIterator + ExactSizeIterator,
{
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
match self.a.len().cmp(&self.b.len()) {
Equal => match (self.a.next_back(), self.b.next_back()) {
(None, None) => None,
(Some(a), Some(b)) => Some(EitherOrBoth::Both(a, b)),
// These can only happen if .len() is inconsistent with .next_back()
(Some(a), None) => Some(EitherOrBoth::Left(a)),
(None, Some(b)) => Some(EitherOrBoth::Right(b)),
},
Greater => self.a.next_back().map(EitherOrBoth::Left),
Less => self.b.next_back().map(EitherOrBoth::Right),
}
}
fn rfold<B, F>(self, mut init: B, mut f: F) -> B
where
F: FnMut(B, Self::Item) -> B,
{
let Self { mut a, mut b } = self;
let a_len = a.len();
let b_len = b.len();
match a_len.cmp(&b_len) {
Equal => {}
Greater => {
init = a
.by_ref()
.rev()
.take(a_len - b_len)
.map(EitherOrBoth::Left)
.fold(init, &mut f)
}
Less => {
init = b
.by_ref()
.rev()
.take(b_len - a_len)
.map(EitherOrBoth::Right)
.fold(init, &mut f)
}
}
a.rfold(init, |acc, item_a| {
f(acc, EitherOrBoth::Both(item_a, b.next_back().unwrap()))
})
}
}
impl<T, U> ExactSizeIterator for ZipLongest<T, U>
where
T: ExactSizeIterator,
U: ExactSizeIterator,
{
}
impl<T, U> FusedIterator for ZipLongest<T, U>
where
T: Iterator,
U: Iterator,
{
}

137
vendor/itertools-0.13.0/src/ziptuple.rs vendored Normal file
View File

@@ -0,0 +1,137 @@
use super::size_hint;
/// See [`multizip`] for more information.
#[derive(Clone, Debug)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct Zip<T> {
t: T,
}
/// An iterator that generalizes `.zip()` and allows running multiple iterators in lockstep.
///
/// The iterator `Zip<(I, J, ..., M)>` is formed from a tuple of iterators (or values that
/// implement [`IntoIterator`]) and yields elements
/// until any of the subiterators yields `None`.
///
/// The iterator element type is a tuple like like `(A, B, ..., E)` where `A` to `E` are the
/// element types of the subiterator.
///
/// **Note:** The result of this function is a value of a named type (`Zip<(I, J,
/// ..)>` of each component iterator `I, J, ...`) if each component iterator is
/// nameable.
///
/// Prefer [`izip!()`](crate::izip) over `multizip` for the performance benefits of using the
/// standard library `.zip()`. Prefer `multizip` if a nameable type is needed.
///
/// ```
/// use itertools::multizip;
///
/// // iterate over three sequences side-by-side
/// let mut results = [0, 0, 0, 0];
/// let inputs = [3, 7, 9, 6];
///
/// for (r, index, input) in multizip((&mut results, 0..10, &inputs)) {
/// *r = index * 10 + input;
/// }
///
/// assert_eq!(results, [0 + 3, 10 + 7, 29, 36]);
/// ```
pub fn multizip<T, U>(t: U) -> Zip<T>
where
Zip<T>: From<U> + Iterator,
{
Zip::from(t)
}
macro_rules! impl_zip_iter {
($($B:ident),*) => (
#[allow(non_snake_case)]
impl<$($B: IntoIterator),*> From<($($B,)*)> for Zip<($($B::IntoIter,)*)> {
fn from(t: ($($B,)*)) -> Self {
let ($($B,)*) = t;
Zip { t: ($($B.into_iter(),)*) }
}
}
#[allow(non_snake_case)]
#[allow(unused_assignments)]
impl<$($B),*> Iterator for Zip<($($B,)*)>
where
$(
$B: Iterator,
)*
{
type Item = ($($B::Item,)*);
fn next(&mut self) -> Option<Self::Item>
{
let ($(ref mut $B,)*) = self.t;
// NOTE: Just like iter::Zip, we check the iterators
// for None in order. We may finish unevenly (some
// iterators gave n + 1 elements, some only n).
$(
let $B = match $B.next() {
None => return None,
Some(elt) => elt
};
)*
Some(($($B,)*))
}
fn size_hint(&self) -> (usize, Option<usize>)
{
let sh = (usize::MAX, None);
let ($(ref $B,)*) = self.t;
$(
let sh = size_hint::min($B.size_hint(), sh);
)*
sh
}
}
#[allow(non_snake_case)]
impl<$($B),*> ExactSizeIterator for Zip<($($B,)*)> where
$(
$B: ExactSizeIterator,
)*
{ }
#[allow(non_snake_case)]
impl<$($B),*> DoubleEndedIterator for Zip<($($B,)*)> where
$(
$B: DoubleEndedIterator + ExactSizeIterator,
)*
{
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
let ($(ref mut $B,)*) = self.t;
let size = *[$( $B.len(), )*].iter().min().unwrap();
$(
if $B.len() != size {
for _ in 0..$B.len() - size { $B.next_back(); }
}
)*
match ($($B.next_back(),)*) {
($(Some($B),)*) => Some(($($B,)*)),
_ => None,
}
}
}
);
}
impl_zip_iter!(A);
impl_zip_iter!(A, B);
impl_zip_iter!(A, B, C);
impl_zip_iter!(A, B, C, D);
impl_zip_iter!(A, B, C, D, E);
impl_zip_iter!(A, B, C, D, E, F);
impl_zip_iter!(A, B, C, D, E, F, G);
impl_zip_iter!(A, B, C, D, E, F, G, H);
impl_zip_iter!(A, B, C, D, E, F, G, H, I);
impl_zip_iter!(A, B, C, D, E, F, G, H, I, J);
impl_zip_iter!(A, B, C, D, E, F, G, H, I, J, K);
impl_zip_iter!(A, B, C, D, E, F, G, H, I, J, K, L);