RPM build fix (reverted CI changes which will need to be un-reverted or made conditional) and vendor Rust dependencies to make builds much faster in any CI system.
This commit is contained in:
237
zeroidc/vendor/itertools/src/adaptors/coalesce.rs
vendored
Normal file
237
zeroidc/vendor/itertools/src/adaptors/coalesce.rs
vendored
Normal file
@@ -0,0 +1,237 @@
|
||||
use std::fmt;
|
||||
use std::iter::FusedIterator;
|
||||
|
||||
use crate::size_hint;
|
||||
|
||||
pub struct CoalesceBy<I, F, T>
|
||||
where
|
||||
I: Iterator,
|
||||
{
|
||||
iter: I,
|
||||
last: Option<T>,
|
||||
f: F,
|
||||
}
|
||||
|
||||
impl<I: Clone, F: Clone, T: Clone> Clone for CoalesceBy<I, F, T>
|
||||
where
|
||||
I: Iterator,
|
||||
{
|
||||
clone_fields!(last, iter, f);
|
||||
}
|
||||
|
||||
impl<I, F, T> fmt::Debug for CoalesceBy<I, F, T>
|
||||
where
|
||||
I: Iterator + fmt::Debug,
|
||||
T: fmt::Debug,
|
||||
{
|
||||
debug_fmt_fields!(CoalesceBy, iter);
|
||||
}
|
||||
|
||||
pub trait CoalescePredicate<Item, T> {
|
||||
fn coalesce_pair(&mut self, t: T, item: Item) -> Result<T, (T, T)>;
|
||||
}
|
||||
|
||||
impl<I, F, T> Iterator for CoalesceBy<I, F, T>
|
||||
where
|
||||
I: Iterator,
|
||||
F: CoalescePredicate<I::Item, T>,
|
||||
{
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
// this fuses the iterator
|
||||
let last = self.last.take()?;
|
||||
|
||||
let self_last = &mut self.last;
|
||||
let self_f = &mut self.f;
|
||||
Some(
|
||||
self.iter
|
||||
.try_fold(last, |last, next| match self_f.coalesce_pair(last, next) {
|
||||
Ok(joined) => Ok(joined),
|
||||
Err((last_, next_)) => {
|
||||
*self_last = 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(), self.last.is_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,
|
||||
{
|
||||
if let Some(last) = self.last {
|
||||
let mut f = self.f;
|
||||
let (last, acc) = self.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: Iterator, F: CoalescePredicate<I::Item, T>, T> FusedIterator for CoalesceBy<I, F, T> {}
|
||||
|
||||
/// An iterator adaptor that may join together adjacent elements.
|
||||
///
|
||||
/// See [`.coalesce()`](crate::Itertools::coalesce) for more information.
|
||||
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
|
||||
pub type Coalesce<I, F> = CoalesceBy<I, F, <I as Iterator>::Item>;
|
||||
|
||||
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>(mut iter: I, f: F) -> Coalesce<I, F>
|
||||
where
|
||||
I: Iterator,
|
||||
{
|
||||
Coalesce {
|
||||
last: iter.next(),
|
||||
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.
|
||||
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
|
||||
pub type DedupBy<I, Pred> = CoalesceBy<I, DedupPred2CoalescePred<Pred>, <I as Iterator>::Item>;
|
||||
|
||||
#[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>(mut iter: I, dedup_pred: Pred) -> DedupBy<I, Pred>
|
||||
where
|
||||
I: Iterator,
|
||||
{
|
||||
DedupBy {
|
||||
last: iter.next(),
|
||||
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.
|
||||
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
|
||||
pub type DedupByWithCount<I, Pred> =
|
||||
CoalesceBy<I, DedupPredWithCount2CoalescePred<Pred>, (usize, <I as Iterator>::Item)>;
|
||||
|
||||
#[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>(mut iter: I, dedup_pred: Pred) -> DedupByWithCount<I, Pred>
|
||||
where
|
||||
I: Iterator,
|
||||
{
|
||||
DedupByWithCount {
|
||||
last: iter.next().map(|v| (1, v)),
|
||||
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)
|
||||
}
|
||||
124
zeroidc/vendor/itertools/src/adaptors/map.rs
vendored
Normal file
124
zeroidc/vendor/itertools/src/adaptors/map.rs
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
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> {
|
||||
iter: I,
|
||||
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>>;
|
||||
|
||||
/// See [`MapOk`].
|
||||
#[deprecated(note = "Use MapOk instead", since = "0.10.0")]
|
||||
pub type MapResults<I, F> = MapOk<I, 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()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MapSpecialCaseFnInto<U>(PhantomData<U>);
|
||||
|
||||
/// Create a new [`MapInto`] iterator.
|
||||
pub fn map_into<I, R>(iter: I) -> MapInto<I, R> {
|
||||
MapSpecialCase {
|
||||
iter,
|
||||
f: MapSpecialCaseFnInto(PhantomData),
|
||||
}
|
||||
}
|
||||
1159
zeroidc/vendor/itertools/src/adaptors/mod.rs
vendored
Normal file
1159
zeroidc/vendor/itertools/src/adaptors/mod.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
230
zeroidc/vendor/itertools/src/adaptors/multi_product.rs
vendored
Normal file
230
zeroidc/vendor/itertools/src/adaptors/multi_product.rs
vendored
Normal file
@@ -0,0 +1,230 @@
|
||||
#![cfg(feature = "use_alloc")]
|
||||
|
||||
use crate::size_hint;
|
||||
use crate::Itertools;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
|
||||
#[derive(Clone)]
|
||||
/// An iterator adaptor that iterates over the cartesian product of
|
||||
/// multiple iterators of type `I`.
|
||||
///
|
||||
/// An iterator element type is `Vec<I>`.
|
||||
///
|
||||
/// 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>(Vec<MultiProductIter<I>>)
|
||||
where I: Iterator + Clone,
|
||||
I::Item: Clone;
|
||||
|
||||
impl<I> std::fmt::Debug for MultiProduct<I>
|
||||
where
|
||||
I: Iterator + Clone + std::fmt::Debug,
|
||||
I::Item: Clone + std::fmt::Debug,
|
||||
{
|
||||
debug_fmt_fields!(CoalesceBy, 0);
|
||||
}
|
||||
|
||||
/// 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
|
||||
{
|
||||
MultiProduct(iters.map(|i| MultiProductIter::new(i.into_iter())).collect())
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
/// Holds the state of a single iterator within a MultiProduct.
|
||||
struct MultiProductIter<I>
|
||||
where I: Iterator + Clone,
|
||||
I::Item: Clone
|
||||
{
|
||||
cur: Option<I::Item>,
|
||||
iter: I,
|
||||
iter_orig: I,
|
||||
}
|
||||
|
||||
/// Holds the current state during an iteration of a MultiProduct.
|
||||
#[derive(Debug)]
|
||||
enum MultiProductIterState {
|
||||
StartOfIter,
|
||||
MidIter { on_first_iter: bool },
|
||||
}
|
||||
|
||||
impl<I> MultiProduct<I>
|
||||
where I: Iterator + Clone,
|
||||
I::Item: Clone
|
||||
{
|
||||
/// Iterates the rightmost iterator, then recursively iterates iterators
|
||||
/// to the left if necessary.
|
||||
///
|
||||
/// Returns true if the iteration succeeded, else false.
|
||||
fn iterate_last(
|
||||
multi_iters: &mut [MultiProductIter<I>],
|
||||
mut state: MultiProductIterState
|
||||
) -> bool {
|
||||
use self::MultiProductIterState::*;
|
||||
|
||||
if let Some((last, rest)) = multi_iters.split_last_mut() {
|
||||
let on_first_iter = match state {
|
||||
StartOfIter => {
|
||||
let on_first_iter = !last.in_progress();
|
||||
state = MidIter { on_first_iter };
|
||||
on_first_iter
|
||||
},
|
||||
MidIter { on_first_iter } => on_first_iter
|
||||
};
|
||||
|
||||
if !on_first_iter {
|
||||
last.iterate();
|
||||
}
|
||||
|
||||
if last.in_progress() {
|
||||
true
|
||||
} else if MultiProduct::iterate_last(rest, state) {
|
||||
last.reset();
|
||||
last.iterate();
|
||||
// If iterator is None twice consecutively, then iterator is
|
||||
// empty; whole product is empty.
|
||||
last.in_progress()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
// Reached end of iterator list. On initialisation, return true.
|
||||
// At end of iteration (final iterator finishes), finish.
|
||||
match state {
|
||||
StartOfIter => false,
|
||||
MidIter { on_first_iter } => on_first_iter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the unwrapped value of the next iteration.
|
||||
fn curr_iterator(&self) -> Vec<I::Item> {
|
||||
self.0.iter().map(|multi_iter| {
|
||||
multi_iter.cur.clone().unwrap()
|
||||
}).collect()
|
||||
}
|
||||
|
||||
/// Returns true if iteration has started and has not yet finished; false
|
||||
/// otherwise.
|
||||
fn in_progress(&self) -> bool {
|
||||
if let Some(last) = self.0.last() {
|
||||
last.in_progress()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> MultiProductIter<I>
|
||||
where I: Iterator + Clone,
|
||||
I::Item: Clone
|
||||
{
|
||||
fn new(iter: I) -> Self {
|
||||
MultiProductIter {
|
||||
cur: None,
|
||||
iter: iter.clone(),
|
||||
iter_orig: iter
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterate the managed iterator.
|
||||
fn iterate(&mut self) {
|
||||
self.cur = self.iter.next();
|
||||
}
|
||||
|
||||
/// Reset the managed iterator.
|
||||
fn reset(&mut self) {
|
||||
self.iter = self.iter_orig.clone();
|
||||
}
|
||||
|
||||
/// Returns true if the current iterator has been started and has not yet
|
||||
/// finished; false otherwise.
|
||||
fn in_progress(&self) -> bool {
|
||||
self.cur.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
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> {
|
||||
if MultiProduct::iterate_last(
|
||||
&mut self.0,
|
||||
MultiProductIterState::StartOfIter
|
||||
) {
|
||||
Some(self.curr_iterator())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn count(self) -> usize {
|
||||
if self.0.is_empty() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if !self.in_progress() {
|
||||
return self.0.into_iter().fold(1, |acc, multi_iter| {
|
||||
acc * multi_iter.iter.count()
|
||||
});
|
||||
}
|
||||
|
||||
self.0.into_iter().fold(
|
||||
0,
|
||||
|acc, MultiProductIter { iter, iter_orig, cur: _ }| {
|
||||
let total_count = iter_orig.count();
|
||||
let cur_count = iter.count();
|
||||
acc * total_count + cur_count
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
// Not ExactSizeIterator because size may be larger than usize
|
||||
if self.0.is_empty() {
|
||||
return (0, Some(0));
|
||||
}
|
||||
|
||||
if !self.in_progress() {
|
||||
return self.0.iter().fold((1, Some(1)), |acc, multi_iter| {
|
||||
size_hint::mul(acc, multi_iter.iter.size_hint())
|
||||
});
|
||||
}
|
||||
|
||||
self.0.iter().fold(
|
||||
(0, Some(0)),
|
||||
|acc, &MultiProductIter { ref iter, ref iter_orig, cur: _ }| {
|
||||
let cur_size = iter.size_hint();
|
||||
let total_size = iter_orig.size_hint();
|
||||
size_hint::add(size_hint::mul(acc, total_size), cur_size)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fn last(self) -> Option<Self::Item> {
|
||||
let iter_count = self.0.len();
|
||||
|
||||
let lasts: Self::Item = self.0.into_iter()
|
||||
.map(|multi_iter| multi_iter.iter.last())
|
||||
.while_some()
|
||||
.collect();
|
||||
|
||||
if lasts.len() == iter_count {
|
||||
Some(lasts)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
128
zeroidc/vendor/itertools/src/combinations.rs
vendored
Normal file
128
zeroidc/vendor/itertools/src/combinations.rs
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
use std::fmt;
|
||||
use std::iter::FusedIterator;
|
||||
|
||||
use super::lazy_buffer::LazyBuffer;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
/// 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
|
||||
{
|
||||
let mut pool = LazyBuffer::new(iter);
|
||||
pool.prefill(k);
|
||||
|
||||
Combinations {
|
||||
indices: (0..k).collect(),
|
||||
pool,
|
||||
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 iterator.
|
||||
#[inline]
|
||||
pub(crate) fn src(&self) -> &I { &self.pool.it }
|
||||
|
||||
/// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> Iterator for Combinations<I>
|
||||
where I: Iterator,
|
||||
I::Item: Clone
|
||||
{
|
||||
type Item = Vec<I::Item>;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.first {
|
||||
if self.k() > self.n() {
|
||||
return None;
|
||||
}
|
||||
self.first = false;
|
||||
} else if self.indices.is_empty() {
|
||||
return None;
|
||||
} else {
|
||||
// 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 None;
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
// Create result vector based on the indices
|
||||
Some(self.indices.iter().map(|i| self.pool[*i].clone()).collect())
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> FusedIterator for Combinations<I>
|
||||
where I: Iterator,
|
||||
I::Item: Clone
|
||||
{}
|
||||
109
zeroidc/vendor/itertools/src/combinations_with_replacement.rs
vendored
Normal file
109
zeroidc/vendor/itertools/src/combinations_with_replacement.rs
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
use alloc::vec::Vec;
|
||||
use std::fmt;
|
||||
use std::iter::FusedIterator;
|
||||
|
||||
use super::lazy_buffer::LazyBuffer;
|
||||
|
||||
/// 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)]
|
||||
pub struct CombinationsWithReplacement<I>
|
||||
where
|
||||
I: Iterator,
|
||||
I::Item: Clone,
|
||||
{
|
||||
indices: Vec<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!(Combinations, indices, pool, first);
|
||||
}
|
||||
|
||||
impl<I> CombinationsWithReplacement<I>
|
||||
where
|
||||
I: Iterator,
|
||||
I::Item: Clone,
|
||||
{
|
||||
/// Map the current mask over the pool to get an output combination
|
||||
fn current(&self) -> Vec<I::Item> {
|
||||
self.indices.iter().map(|i| self.pool[*i].clone()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
/// 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: Vec<usize> = alloc::vec![0; k];
|
||||
let pool: LazyBuffer<I> = LazyBuffer::new(iter);
|
||||
|
||||
CombinationsWithReplacement {
|
||||
indices,
|
||||
pool,
|
||||
first: 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 this is the first iteration, return early
|
||||
if self.first {
|
||||
// In empty edge cases, stop iterating immediately
|
||||
return if self.indices.len() != 0 && !self.pool.get_next() {
|
||||
None
|
||||
// Otherwise, yield the initial state
|
||||
} else {
|
||||
self.first = false;
|
||||
Some(self.current())
|
||||
};
|
||||
}
|
||||
|
||||
// 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: Option<(usize, usize)> = 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 indices_index in increment_from..self.indices.len() {
|
||||
self.indices[indices_index] = increment_value
|
||||
}
|
||||
Some(self.current())
|
||||
}
|
||||
// Otherwise, we're done
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> FusedIterator for CombinationsWithReplacement<I>
|
||||
where
|
||||
I: Iterator,
|
||||
I::Item: Clone,
|
||||
{}
|
||||
22
zeroidc/vendor/itertools/src/concat_impl.rs
vendored
Normal file
22
zeroidc/vendor/itertools/src/concat_impl.rs
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
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
|
||||
{
|
||||
iterable.into_iter().fold1(|mut a, b| { a.extend(b); a }).unwrap_or_else(<_>::default)
|
||||
}
|
||||
64
zeroidc/vendor/itertools/src/cons_tuples_impl.rs
vendored
Normal file
64
zeroidc/vendor/itertools/src/cons_tuples_impl.rs
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
|
||||
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, )))
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
impl<X, Iter, $($B),*> DoubleEndedIterator for ConsTuples<Iter, (($($B,)*), X)>
|
||||
where Iter: DoubleEndedIterator<Item = (($($B,)*), X)>,
|
||||
{
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
self.iter.next().map(|(($($B,)*), x)| ($($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() }
|
||||
}
|
||||
61
zeroidc/vendor/itertools/src/diff.rs
vendored
Normal file
61
zeroidc/vendor/itertools/src/diff.rs
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
//! "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 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>),
|
||||
}
|
||||
|
||||
/// 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, is_equal: F)
|
||||
-> Option<Diff<I::IntoIter, J::IntoIter>>
|
||||
where I: IntoIterator,
|
||||
J: IntoIterator,
|
||||
F: Fn(&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)))
|
||||
}
|
||||
217
zeroidc/vendor/itertools/src/duplicates_impl.rs
vendored
Normal file
217
zeroidc/vendor/itertools/src/duplicates_impl.rs
vendored
Normal file
@@ -0,0 +1,217 @@
|
||||
use std::hash::Hash;
|
||||
|
||||
mod private {
|
||||
use std::collections::HashMap;
|
||||
use std::hash::Hash;
|
||||
use std::fmt;
|
||||
|
||||
#[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 {
|
||||
DuplicatesBy {
|
||||
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 DuplicatesBy { 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 DuplicatesBy { 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)]
|
||||
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.
|
||||
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.
|
||||
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
|
||||
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)
|
||||
}
|
||||
|
||||
205
zeroidc/vendor/itertools/src/either_or_both.rs
vendored
Normal file
205
zeroidc/vendor/itertools/src/either_or_both.rs
vendored
Normal file
@@ -0,0 +1,205 @@
|
||||
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> {
|
||||
/// 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 {
|
||||
match *self {
|
||||
Left(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// If Right, return true otherwise, return false.
|
||||
/// Exclusive version of [`has_right`](EitherOrBoth::has_right).
|
||||
pub fn is_right(&self) -> bool {
|
||||
match *self {
|
||||
Right(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// If Right, return true otherwise, return false.
|
||||
/// Equivalent to `self.as_ref().both().is_some()`.
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
/// If Both, return `Some` tuple containing left and right.
|
||||
pub fn both(self) -> Option<(A, B)> {
|
||||
match self {
|
||||
Both(a, b) => Some((a, b)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// 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),
|
||||
}
|
||||
}
|
||||
|
||||
/// 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 [`default`](Default::default)
|
||||
/// for the other.
|
||||
pub fn or_default(self) -> (A, B)
|
||||
where
|
||||
A: Default,
|
||||
B: Default,
|
||||
{
|
||||
match self {
|
||||
EitherOrBoth::Left(l) => (l, B::default()),
|
||||
EitherOrBoth::Right(r) => (A::default(), r),
|
||||
EitherOrBoth::Both(l, r) => (l, r),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> EitherOrBoth<T, T> {
|
||||
/// Return either value of left, right, or the product of `f` applied where `Both` are present.
|
||||
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> Into<Option<Either<A, B>>> for EitherOrBoth<A, B> {
|
||||
fn into(self) -> Option<Either<A, B>> {
|
||||
match self {
|
||||
EitherOrBoth::Left(l) => Some(Either::Left(l)),
|
||||
EitherOrBoth::Right(r) => Some(Either::Right(r)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
110
zeroidc/vendor/itertools/src/exactly_one_err.rs
vendored
Normal file
110
zeroidc/vendor/itertools/src/exactly_one_err.rs
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
#[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())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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 {
|
||||
match &self.first_two {
|
||||
Some(Either::Left([first, second])) => {
|
||||
write!(f, "ExactlyOneError[First: {:?}, Second: {:?}, RemainingIter: {:?}]", first, second, self.inner)
|
||||
},
|
||||
Some(Either::Right(second)) => {
|
||||
write!(f, "ExactlyOneError[Second: {:?}, RemainingIter: {:?}]", second, self.inner)
|
||||
}
|
||||
None => {
|
||||
write!(f, "ExactlyOneError[RemainingIter: {:?}]", self.inner)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "use_std")]
|
||||
impl<I> Error for ExactlyOneError<I> where I: Iterator + Debug, I::Item: Debug, {}
|
||||
|
||||
|
||||
166
zeroidc/vendor/itertools/src/flatten_ok.rs
vendored
Normal file
166
zeroidc/vendor/itertools/src/flatten_ok.rs
vendored
Normal file
@@ -0,0 +1,166 @@
|
||||
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));
|
||||
} else {
|
||||
// This is necessary for the iterator to implement `FusedIterator`
|
||||
// with only the orginal 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));
|
||||
} else {
|
||||
// This is necessary for the iterator to implement `FusedIterator`
|
||||
// with only the orginal iterator being fused.
|
||||
self.inner_back = None;
|
||||
}
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
} else {
|
||||
// This is necessary for the iterator to implement `FusedIterator`
|
||||
// with only the orginal 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));
|
||||
} else {
|
||||
// This is necessary for the iterator to implement `FusedIterator`
|
||||
// with only the orginal iterator being fused.
|
||||
self.inner_front = None;
|
||||
}
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, T, E> Clone for FlattenOk<I, T, E>
|
||||
where
|
||||
I: Iterator<Item = Result<T, E>> + Clone,
|
||||
T: IntoIterator,
|
||||
T::IntoIter: Clone,
|
||||
{
|
||||
#[inline]
|
||||
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,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("FlattenOk")
|
||||
.field("iter", &self.iter)
|
||||
.field("inner_front", &self.inner_front)
|
||||
.field("inner_back", &self.inner_back)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// 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,
|
||||
{
|
||||
}
|
||||
113
zeroidc/vendor/itertools/src/format.rs
vendored
Normal file
113
zeroidc/vendor/itertools/src/format.rs
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
use std::fmt;
|
||||
use std::cell::RefCell;
|
||||
|
||||
/// 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.
|
||||
#[derive(Clone)]
|
||||
pub struct FormatWith<'a, I, F> {
|
||||
sep: &'a str,
|
||||
/// FormatWith uses interior mutability because Display::fmt takes &self.
|
||||
inner: RefCell<Option<(I, F)>>,
|
||||
}
|
||||
|
||||
/// 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.
|
||||
#[derive(Clone)]
|
||||
pub struct Format<'a, I> {
|
||||
sep: &'a str,
|
||||
/// Format uses interior mutability because Display::fmt takes &self.
|
||||
inner: RefCell<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: RefCell::new(Some((iter, f))),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_format_default<I>(iter: I, separator: &str) -> Format<'_, I>
|
||||
where I: Iterator,
|
||||
{
|
||||
Format {
|
||||
sep: separator,
|
||||
inner: RefCell::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.borrow_mut().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> Format<'a, I>
|
||||
where I: Iterator,
|
||||
{
|
||||
fn format<F>(&self, f: &mut fmt::Formatter, mut cb: F) -> fmt::Result
|
||||
where F: FnMut(&I::Item, &mut fmt::Formatter) -> fmt::Result,
|
||||
{
|
||||
let mut iter = match self.inner.borrow_mut().take() {
|
||||
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}
|
||||
276
zeroidc/vendor/itertools/src/free.rs
vendored
Normal file
276
zeroidc/vendor/itertools/src/free.rs
vendored
Normal file
@@ -0,0 +1,276 @@
|
||||
//! 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::Itertools;
|
||||
use crate::intersperse::{Intersperse, IntersperseWith};
|
||||
|
||||
pub use crate::adaptors::{
|
||||
interleave,
|
||||
merge,
|
||||
put_back,
|
||||
};
|
||||
#[cfg(feature = "use_alloc")]
|
||||
pub use crate::put_back_n_impl::put_back_n;
|
||||
#[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::kmerge_impl::kmerge;
|
||||
pub use crate::zip_eq_impl::zip_eq;
|
||||
pub use crate::merge_join::merge_join_by;
|
||||
#[cfg(feature = "use_alloc")]
|
||||
pub use crate::rciter_impl::rciter;
|
||||
|
||||
/// 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()
|
||||
}
|
||||
|
||||
/// Iterate `i` and `j` in lock step.
|
||||
///
|
||||
/// [`IntoIterator`] enabled version of [`Iterator::zip`].
|
||||
///
|
||||
/// ```
|
||||
/// use itertools::zip;
|
||||
///
|
||||
/// let data = [1, 2, 3, 4, 5];
|
||||
/// for (a, b) in zip(&data, &data[1..]) {
|
||||
/// /* loop body */
|
||||
/// }
|
||||
/// ```
|
||||
pub fn zip<I, J>(i: I, j: J) -> Zip<I::IntoIter, J::IntoIter>
|
||||
where I: IntoIterator,
|
||||
J: IntoIterator
|
||||
{
|
||||
i.into_iter().zip(j)
|
||||
}
|
||||
|
||||
/// Create an iterator that first iterates `i` and then `j`.
|
||||
///
|
||||
/// [`IntoIterator`] enabled version of [`Iterator::chain`].
|
||||
///
|
||||
/// ```
|
||||
/// use itertools::chain;
|
||||
///
|
||||
/// for elt in chain(&[1, 2, 3], &[4]) {
|
||||
/// /* loop body */
|
||||
/// }
|
||||
/// ```
|
||||
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: 'a>(iterable: I) -> iter::Cloned<I::IntoIter>
|
||||
where I: IntoIterator<Item=&'a T>,
|
||||
T: Clone,
|
||||
{
|
||||
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, seperated 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()
|
||||
}
|
||||
|
||||
32
zeroidc/vendor/itertools/src/group_map.rs
vendored
Normal file
32
zeroidc/vendor/itertools/src/group_map.rs
vendored
Normal 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>(iter: I, f: impl Fn(&V) -> K) -> HashMap<K, Vec<V>>
|
||||
where
|
||||
I: Iterator<Item=V>,
|
||||
K: Hash + Eq,
|
||||
{
|
||||
into_group_map(
|
||||
iter.map(|v| (f(&v), v))
|
||||
)
|
||||
}
|
||||
571
zeroidc/vendor/itertools/src/groupbylazy.rs
vendored
Normal file
571
zeroidc/vendor/itertools/src/groupbylazy.rs
vendored
Normal file
@@ -0,0 +1,571 @@
|
||||
use std::cell::{Cell, RefCell};
|
||||
use alloc::vec::{self, Vec};
|
||||
|
||||
/// A trait to unify FnMut for GroupBy with the chunk key in IntoChunks
|
||||
trait KeyFunction<A> {
|
||||
type Key;
|
||||
fn call_mut(&mut self, arg: A) -> Self::Key;
|
||||
}
|
||||
|
||||
impl<'a, A, K, F: ?Sized> KeyFunction<A> for F
|
||||
where F: FnMut(A) -> K
|
||||
{
|
||||
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)]
|
||||
struct ChunkIndex {
|
||||
size: usize,
|
||||
index: usize,
|
||||
key: usize,
|
||||
}
|
||||
|
||||
impl ChunkIndex {
|
||||
#[inline(always)]
|
||||
fn new(size: usize) -> Self {
|
||||
ChunkIndex {
|
||||
size,
|
||||
index: 0,
|
||||
key: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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 == none
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// `GroupBy` 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 `GroupBy` 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 [`.group_by()`](crate::Itertools::group_by) for more information.
|
||||
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
|
||||
pub struct GroupBy<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) -> GroupBy<K, J::IntoIter, F>
|
||||
where J: IntoIterator,
|
||||
F: FnMut(&J::Item) -> K,
|
||||
{
|
||||
GroupBy {
|
||||
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> GroupBy<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 GroupBy<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 [`.group_by()`](crate::Itertools::group_by) for more information.
|
||||
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
|
||||
pub struct Groups<'a, K: 'a, I: 'a, F: 'a>
|
||||
where I: Iterator,
|
||||
I::Item: 'a
|
||||
{
|
||||
parent: &'a GroupBy<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: 'a, I: 'a, F: 'a>
|
||||
where I: Iterator,
|
||||
I::Item: 'a,
|
||||
{
|
||||
parent: &'a GroupBy<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 `GroupBy`: 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> 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"]
|
||||
pub struct Chunks<'a, I: 'a>
|
||||
where I: Iterator,
|
||||
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: 'a>
|
||||
where I: Iterator,
|
||||
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)
|
||||
}
|
||||
}
|
||||
536
zeroidc/vendor/itertools/src/grouping_map.rs
vendored
Normal file
536
zeroidc/vendor/itertools/src/grouping_map.rs
vendored
Normal file
@@ -0,0 +1,536 @@
|
||||
#![cfg(feature = "use_std")]
|
||||
|
||||
use crate::MinMaxResult;
|
||||
use std::collections::HashMap;
|
||||
use std::cmp::Ordering;
|
||||
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)
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MapForGrouping<I, F>(I, F);
|
||||
|
||||
impl<I, F> MapForGrouping<I, F> {
|
||||
pub(crate) fn new(iter: I, key_mapper: F) -> Self {
|
||||
Self(iter, key_mapper)
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V, I, F> Iterator for MapForGrouping<I, F>
|
||||
where I: Iterator<Item = V>,
|
||||
K: Hash + Eq,
|
||||
F: FnMut(&V) -> K,
|
||||
{
|
||||
type Item = (K, V);
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.0.next().map(|val| ((self.1)(&val), val))
|
||||
}
|
||||
}
|
||||
|
||||
/// 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.
|
||||
#[must_use = "GroupingMapBy is lazy and do nothing unless consumed"]
|
||||
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 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, mut operation: FO) -> HashMap<K, R>
|
||||
where R: Clone,
|
||||
FO: FnMut(R, &K, V) -> R,
|
||||
{
|
||||
self.aggregate(|acc, key, val| {
|
||||
let acc = acc.unwrap_or_else(|| init.clone());
|
||||
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.
|
||||
///
|
||||
/// 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)
|
||||
/// .fold_first(|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_first<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,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/// 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.fold_first(|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.fold_first(|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 [.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.fold_first(|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.fold_first(|acc, _, val| acc + val)
|
||||
}
|
||||
|
||||
/// Groups elements from the `GroupingMap` source by key and multiply them.
|
||||
///
|
||||
/// This is just a shorthand for `self.fold_first(|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.fold_first(|acc, _, val| acc * val)
|
||||
}
|
||||
}
|
||||
28
zeroidc/vendor/itertools/src/impl_macros.rs
vendored
Normal file
28
zeroidc/vendor/itertools/src/impl_macros.rs
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
//!
|
||||
//! 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),*) => {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
$($field: self.$field.clone(),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! ignore_ident{
|
||||
($id:ident, $($t:tt)*) => {$($t)*};
|
||||
}
|
||||
119
zeroidc/vendor/itertools/src/intersperse.rs
vendored
Normal file
119
zeroidc/vendor/itertools/src/intersperse.rs
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
use std::iter::{Fuse, FusedIterator};
|
||||
use super::size_hint;
|
||||
|
||||
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: Option<I::Item>,
|
||||
}
|
||||
|
||||
/// Create a new IntersperseWith iterator
|
||||
pub fn intersperse_with<I, ElemF>(iter: I, elt: ElemF) -> IntersperseWith<I, ElemF>
|
||||
where I: Iterator,
|
||||
{
|
||||
let mut iter = iter.fuse();
|
||||
IntersperseWith {
|
||||
peek: iter.next(),
|
||||
iter,
|
||||
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> {
|
||||
if self.peek.is_some() {
|
||||
self.peek.take()
|
||||
} else {
|
||||
self.peek = self.iter.next();
|
||||
if self.peek.is_some() {
|
||||
Some(self.element.generate())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
// 2 * SH + { 1 or 0 }
|
||||
let has_peek = self.peek.is_some() as usize;
|
||||
let sh = self.iter.size_hint();
|
||||
size_hint::add_scalar(size_hint::add(sh, sh), has_peek)
|
||||
}
|
||||
|
||||
fn fold<B, F>(mut self, init: B, mut f: F) -> B where
|
||||
Self: Sized, F: FnMut(B, Self::Item) -> B,
|
||||
{
|
||||
let mut accum = init;
|
||||
|
||||
if let Some(x) = self.peek.take() {
|
||||
accum = f(accum, x);
|
||||
}
|
||||
|
||||
let element = &mut self.element;
|
||||
|
||||
self.iter.fold(accum,
|
||||
|accum, x| {
|
||||
let accum = f(accum, element.generate());
|
||||
let accum = f(accum, x);
|
||||
accum
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, ElemF> FusedIterator for IntersperseWith<I, ElemF>
|
||||
where I: Iterator,
|
||||
ElemF: IntersperseElement<I::Item>
|
||||
{}
|
||||
20
zeroidc/vendor/itertools/src/k_smallest.rs
vendored
Normal file
20
zeroidc/vendor/itertools/src/k_smallest.rs
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
use alloc::collections::BinaryHeap;
|
||||
use core::cmp::Ord;
|
||||
|
||||
pub(crate) fn k_smallest<T: Ord, I: Iterator<Item = T>>(mut iter: I, k: usize) -> BinaryHeap<T> {
|
||||
if k == 0 { return BinaryHeap::new(); }
|
||||
|
||||
let mut heap = iter.by_ref().take(k).collect::<BinaryHeap<_>>();
|
||||
|
||||
iter.for_each(|i| {
|
||||
debug_assert_eq!(heap.len(), k);
|
||||
// Equivalent to heap.push(min(i, heap.pop())) but more efficient.
|
||||
// This should be done with a single `.peek_mut().unwrap()` but
|
||||
// `PeekMut` sifts-down unconditionally on Rust 1.46.0 and prior.
|
||||
if *heap.peek().unwrap() > i {
|
||||
*heap.peek_mut().unwrap() = i;
|
||||
}
|
||||
});
|
||||
|
||||
heap
|
||||
}
|
||||
227
zeroidc/vendor/itertools/src/kmerge_impl.rs
vendored
Normal file
227
zeroidc/vendor/itertools/src/kmerge_impl.rs
vendored
Normal file
@@ -0,0 +1,227 @@
|
||||
use crate::size_hint;
|
||||
use crate::Itertools;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use std::iter::FusedIterator;
|
||||
use std::mem::replace;
|
||||
use std::fmt;
|
||||
|
||||
/// 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<HeadTail<I>> {
|
||||
let head = it.next();
|
||||
head.map(|h| {
|
||||
HeadTail {
|
||||
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 aritmethic 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.
|
||||
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
|
||||
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.
|
||||
///
|
||||
/// Equivalent to `iterable.into_iter().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 = "iterator adaptors are lazy and do 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.
|
||||
///
|
||||
/// Equivalent to `iterable.into_iter().kmerge_by(less_than)`.
|
||||
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>) {
|
||||
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>
|
||||
{}
|
||||
67
zeroidc/vendor/itertools/src/lazy_buffer.rs
vendored
Normal file
67
zeroidc/vendor/itertools/src/lazy_buffer.rs
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
use std::ops::Index;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct LazyBuffer<I: Iterator> {
|
||||
pub it: I,
|
||||
done: bool,
|
||||
buffer: Vec<I::Item>,
|
||||
}
|
||||
|
||||
impl<I> LazyBuffer<I>
|
||||
where
|
||||
I: Iterator,
|
||||
{
|
||||
pub fn new(it: I) -> LazyBuffer<I> {
|
||||
LazyBuffer {
|
||||
it,
|
||||
done: false,
|
||||
buffer: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.buffer.len()
|
||||
}
|
||||
|
||||
pub fn get_next(&mut self) -> bool {
|
||||
if self.done {
|
||||
return false;
|
||||
}
|
||||
let next_item = self.it.next();
|
||||
match next_item {
|
||||
Some(x) => {
|
||||
self.buffer.push(x);
|
||||
true
|
||||
}
|
||||
None => {
|
||||
self.done = true;
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn prefill(&mut self, len: usize) {
|
||||
let buffer_len = self.buffer.len();
|
||||
|
||||
if !self.done && len > buffer_len {
|
||||
let delta = len - buffer_len;
|
||||
|
||||
self.buffer.extend(self.it.by_ref().take(delta));
|
||||
self.done = self.buffer.len() < len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
3608
zeroidc/vendor/itertools/src/lib.rs
vendored
Normal file
3608
zeroidc/vendor/itertools/src/lib.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
167
zeroidc/vendor/itertools/src/merge_join.rs
vendored
Normal file
167
zeroidc/vendor/itertools/src/merge_join.rs
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
use std::cmp::Ordering;
|
||||
use std::iter::Fuse;
|
||||
use std::fmt;
|
||||
|
||||
use super::adaptors::{PutBack, put_back};
|
||||
use crate::either_or_both::EitherOrBoth;
|
||||
|
||||
/// Return 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 fn merge_join_by<I, J, F>(left: I, right: J, cmp_fn: F)
|
||||
-> MergeJoinBy<I::IntoIter, J::IntoIter, F>
|
||||
where I: IntoIterator,
|
||||
J: IntoIterator,
|
||||
F: FnMut(&I::Item, &J::Item) -> Ordering
|
||||
{
|
||||
MergeJoinBy {
|
||||
left: put_back(left.into_iter().fuse()),
|
||||
right: put_back(right.into_iter().fuse()),
|
||||
cmp_fn,
|
||||
}
|
||||
}
|
||||
|
||||
/// 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.
|
||||
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
|
||||
pub struct MergeJoinBy<I: Iterator, J: Iterator, F> {
|
||||
left: PutBack<Fuse<I>>,
|
||||
right: PutBack<Fuse<J>>,
|
||||
cmp_fn: F
|
||||
}
|
||||
|
||||
impl<I, J, F> Clone for MergeJoinBy<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 MergeJoinBy<I, J, F>
|
||||
where I: Iterator + fmt::Debug,
|
||||
I::Item: fmt::Debug,
|
||||
J: Iterator + fmt::Debug,
|
||||
J::Item: fmt::Debug,
|
||||
{
|
||||
debug_fmt_fields!(MergeJoinBy, left, right);
|
||||
}
|
||||
|
||||
impl<I, J, F> Iterator for MergeJoinBy<I, J, F>
|
||||
where I: Iterator,
|
||||
J: Iterator,
|
||||
F: FnMut(&I::Item, &J::Item) -> Ordering
|
||||
{
|
||||
type Item = EitherOrBoth<I::Item, J::Item>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
match (self.left.next(), self.right.next()) {
|
||||
(None, None) => None,
|
||||
(Some(left), None) =>
|
||||
Some(EitherOrBoth::Left(left)),
|
||||
(None, Some(right)) =>
|
||||
Some(EitherOrBoth::Right(right)),
|
||||
(Some(left), Some(right)) => {
|
||||
match (self.cmp_fn)(&left, &right) {
|
||||
Ordering::Equal =>
|
||||
Some(EitherOrBoth::Both(left, right)),
|
||||
Ordering::Less => {
|
||||
self.right.put_back(right);
|
||||
Some(EitherOrBoth::Left(left))
|
||||
},
|
||||
Ordering::Greater => {
|
||||
self.left.put_back(left);
|
||||
Some(EitherOrBoth::Right(right))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let (a_lower, a_upper) = self.left.size_hint();
|
||||
let (b_lower, b_upper) = self.right.size_hint();
|
||||
|
||||
let lower = ::std::cmp::max(a_lower, b_lower);
|
||||
|
||||
let upper = match (a_upper, b_upper) {
|
||||
(Some(x), Some(y)) => x.checked_add(y),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
(lower, upper)
|
||||
}
|
||||
|
||||
fn count(mut self) -> usize {
|
||||
let mut count = 0;
|
||||
loop {
|
||||
match (self.left.next(), self.right.next()) {
|
||||
(None, None) => break count,
|
||||
(Some(_left), None) => break count + 1 + self.left.into_parts().1.count(),
|
||||
(None, Some(_right)) => break count + 1 + self.right.into_parts().1.count(),
|
||||
(Some(left), Some(right)) => {
|
||||
count += 1;
|
||||
match (self.cmp_fn)(&left, &right) {
|
||||
Ordering::Equal => {}
|
||||
Ordering::Less => self.right.put_back(right),
|
||||
Ordering::Greater => self.left.put_back(left),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn last(mut self) -> Option<Self::Item> {
|
||||
let mut previous_element = None;
|
||||
loop {
|
||||
match (self.left.next(), self.right.next()) {
|
||||
(None, None) => break previous_element,
|
||||
(Some(left), None) => {
|
||||
break Some(EitherOrBoth::Left(
|
||||
self.left.into_parts().1.last().unwrap_or(left),
|
||||
))
|
||||
}
|
||||
(None, Some(right)) => {
|
||||
break Some(EitherOrBoth::Right(
|
||||
self.right.into_parts().1.last().unwrap_or(right),
|
||||
))
|
||||
}
|
||||
(Some(left), Some(right)) => {
|
||||
previous_element = match (self.cmp_fn)(&left, &right) {
|
||||
Ordering::Equal => Some(EitherOrBoth::Both(left, right)),
|
||||
Ordering::Less => {
|
||||
self.right.put_back(right);
|
||||
Some(EitherOrBoth::Left(left))
|
||||
}
|
||||
Ordering::Greater => {
|
||||
self.left.put_back(left);
|
||||
Some(EitherOrBoth::Right(right))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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(EitherOrBoth::Left),
|
||||
(None, Some(_right)) => break self.right.nth(n).map(EitherOrBoth::Right),
|
||||
(Some(left), Some(right)) => match (self.cmp_fn)(&left, &right) {
|
||||
Ordering::Equal => {}
|
||||
Ordering::Less => self.right.put_back(right),
|
||||
Ordering::Greater => self.left.put_back(left),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
115
zeroidc/vendor/itertools/src/minmax.rs
vendored
Normal file
115
zeroidc/vendor/itertools/src/minmax.rs
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
|
||||
/// `MinMaxResult` is an enum returned by `minmax`.
|
||||
///
|
||||
/// See [`.minmax()`](crate::Itertools::minmax) for more detail.
|
||||
#[derive(Copy, Clone, PartialEq, 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 {
|
||||
MinMaxResult::NoElements => None,
|
||||
MinMaxResult::OneElement(x) => Some((x.clone(), x)),
|
||||
MinMaxResult::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)
|
||||
}
|
||||
99
zeroidc/vendor/itertools/src/multipeek_impl.rs
vendored
Normal file
99
zeroidc/vendor/itertools/src/multipeek_impl.rs
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
use std::iter::Fuse;
|
||||
use alloc::collections::VecDeque;
|
||||
use crate::size_hint;
|
||||
use crate::PeekingNext;
|
||||
|
||||
/// See [`multipeek()`] for more information.
|
||||
#[derive(Clone, Debug)]
|
||||
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.
|
||||
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.get(0) {
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
||||
// Same size
|
||||
impl<I> ExactSizeIterator for MultiPeek<I>
|
||||
where I: ExactSizeIterator
|
||||
{}
|
||||
|
||||
|
||||
96
zeroidc/vendor/itertools/src/pad_tail.rs
vendored
Normal file
96
zeroidc/vendor/itertools/src/pad_tail.rs
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
use std::iter::{Fuse, FusedIterator};
|
||||
use crate::size_hint;
|
||||
|
||||
/// 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)))
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
{}
|
||||
102
zeroidc/vendor/itertools/src/peek_nth.rs
vendored
Normal file
102
zeroidc/vendor/itertools/src/peek_nth.rs
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
use crate::size_hint;
|
||||
use crate::PeekingNext;
|
||||
use alloc::collections::VecDeque;
|
||||
use std::iter::Fuse;
|
||||
|
||||
/// See [`peek_nth()`] for more information.
|
||||
#[derive(Clone, Debug)]
|
||||
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)
|
||||
}
|
||||
|
||||
/// Returns a reference to the `nth` value without advancing the iterator.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```rust
|
||||
/// use itertools::peek_nth;
|
||||
///
|
||||
/// let xs = vec![1,2,3];
|
||||
/// let mut iter = peek_nth(xs.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)
|
||||
}
|
||||
}
|
||||
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
154
zeroidc/vendor/itertools/src/peeking_take_while.rs
vendored
Normal file
154
zeroidc/vendor/itertools/src/peeking_take_while.rs
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
use std::iter::Peekable;
|
||||
use crate::PutBack;
|
||||
#[cfg(feature = "use_alloc")]
|
||||
use crate::PutBackN;
|
||||
|
||||
/// 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 slice’s
|
||||
/// 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 F: FnOnce(&Self::Item) -> bool;
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 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: 'a, F>
|
||||
where I: Iterator,
|
||||
{
|
||||
iter: &'a mut I,
|
||||
f: F,
|
||||
}
|
||||
|
||||
impl<'a, I: 'a, F> std::fmt::Debug for PeekingTakeWhile<'a, I, F>
|
||||
where
|
||||
I: Iterator + std::fmt::Debug,
|
||||
{
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
// 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> }
|
||||
280
zeroidc/vendor/itertools/src/permutations.rs
vendored
Normal file
280
zeroidc/vendor/itertools/src/permutations.rs
vendored
Normal file
@@ -0,0 +1,280 @@
|
||||
use alloc::vec::Vec;
|
||||
use std::fmt;
|
||||
use std::iter::once;
|
||||
|
||||
use super::lazy_buffer::LazyBuffer;
|
||||
|
||||
/// 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 {
|
||||
StartUnknownLen {
|
||||
k: usize,
|
||||
},
|
||||
OngoingUnknownLen {
|
||||
k: usize,
|
||||
min_n: usize,
|
||||
},
|
||||
Complete(CompleteState),
|
||||
Empty,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
enum CompleteState {
|
||||
Start {
|
||||
n: usize,
|
||||
k: usize,
|
||||
},
|
||||
Ongoing {
|
||||
indices: Vec<usize>,
|
||||
cycles: Vec<usize>,
|
||||
}
|
||||
}
|
||||
|
||||
enum CompleteStateRemaining {
|
||||
Known(usize),
|
||||
Overflow,
|
||||
}
|
||||
|
||||
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> {
|
||||
let mut vals = LazyBuffer::new(iter);
|
||||
|
||||
if k == 0 {
|
||||
// Special case, yields single empty vec; `n` is irrelevant
|
||||
let state = PermutationState::Complete(CompleteState::Start { n: 0, k: 0 });
|
||||
|
||||
return Permutations {
|
||||
vals,
|
||||
state
|
||||
};
|
||||
}
|
||||
|
||||
let mut enough_vals = true;
|
||||
|
||||
while vals.len() < k {
|
||||
if !vals.get_next() {
|
||||
enough_vals = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let state = if enough_vals {
|
||||
PermutationState::StartUnknownLen { k }
|
||||
} else {
|
||||
PermutationState::Empty
|
||||
};
|
||||
|
||||
Permutations {
|
||||
vals,
|
||||
state
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> Iterator for Permutations<I>
|
||||
where
|
||||
I: Iterator,
|
||||
I::Item: Clone
|
||||
{
|
||||
type Item = Vec<I::Item>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.advance();
|
||||
|
||||
let &mut Permutations { ref vals, ref state } = self;
|
||||
|
||||
match *state {
|
||||
PermutationState::StartUnknownLen { .. } => panic!("unexpected iterator state"),
|
||||
PermutationState::OngoingUnknownLen { k, min_n } => {
|
||||
let latest_idx = min_n - 1;
|
||||
let indices = (0..(k - 1)).chain(once(latest_idx));
|
||||
|
||||
Some(indices.map(|i| vals[i].clone()).collect())
|
||||
}
|
||||
PermutationState::Complete(CompleteState::Start { .. }) => None,
|
||||
PermutationState::Complete(CompleteState::Ongoing { ref indices, ref cycles }) => {
|
||||
let k = cycles.len();
|
||||
|
||||
Some(indices[0..k].iter().map(|&i| vals[i].clone()).collect())
|
||||
},
|
||||
PermutationState::Empty => None
|
||||
}
|
||||
}
|
||||
|
||||
fn count(self) -> usize {
|
||||
let Permutations { vals, state } = self;
|
||||
|
||||
fn from_complete(complete_state: CompleteState) -> usize {
|
||||
match complete_state.remaining() {
|
||||
CompleteStateRemaining::Known(count) => count,
|
||||
CompleteStateRemaining::Overflow => {
|
||||
panic!("Iterator count greater than usize::MAX");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match state {
|
||||
PermutationState::StartUnknownLen { k } => {
|
||||
let n = vals.len() + vals.it.count();
|
||||
let complete_state = CompleteState::Start { n, k };
|
||||
|
||||
from_complete(complete_state)
|
||||
}
|
||||
PermutationState::OngoingUnknownLen { k, min_n } => {
|
||||
let prev_iteration_count = min_n - k + 1;
|
||||
let n = vals.len() + vals.it.count();
|
||||
let complete_state = CompleteState::Start { n, k };
|
||||
|
||||
from_complete(complete_state) - prev_iteration_count
|
||||
},
|
||||
PermutationState::Complete(state) => from_complete(state),
|
||||
PermutationState::Empty => 0
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
match self.state {
|
||||
PermutationState::StartUnknownLen { .. } |
|
||||
PermutationState::OngoingUnknownLen { .. } => (0, None), // TODO can we improve this lower bound?
|
||||
PermutationState::Complete(ref state) => match state.remaining() {
|
||||
CompleteStateRemaining::Known(count) => (count, Some(count)),
|
||||
CompleteStateRemaining::Overflow => (::std::usize::MAX, None)
|
||||
}
|
||||
PermutationState::Empty => (0, Some(0))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> Permutations<I>
|
||||
where
|
||||
I: Iterator,
|
||||
I::Item: Clone
|
||||
{
|
||||
fn advance(&mut self) {
|
||||
let &mut Permutations { ref mut vals, ref mut state } = self;
|
||||
|
||||
*state = match *state {
|
||||
PermutationState::StartUnknownLen { k } => {
|
||||
PermutationState::OngoingUnknownLen { k, min_n: k }
|
||||
}
|
||||
PermutationState::OngoingUnknownLen { k, min_n } => {
|
||||
if vals.get_next() {
|
||||
PermutationState::OngoingUnknownLen { k, min_n: min_n + 1 }
|
||||
} else {
|
||||
let n = min_n;
|
||||
let prev_iteration_count = n - k + 1;
|
||||
let mut complete_state = CompleteState::Start { n, k };
|
||||
|
||||
// Advance the complete-state iterator to the correct point
|
||||
for _ in 0..(prev_iteration_count + 1) {
|
||||
complete_state.advance();
|
||||
}
|
||||
|
||||
PermutationState::Complete(complete_state)
|
||||
}
|
||||
}
|
||||
PermutationState::Complete(ref mut state) => {
|
||||
state.advance();
|
||||
|
||||
return;
|
||||
}
|
||||
PermutationState::Empty => { return; }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl CompleteState {
|
||||
fn advance(&mut self) {
|
||||
*self = match *self {
|
||||
CompleteState::Start { n, k } => {
|
||||
let indices = (0..n).collect();
|
||||
let cycles = ((n - k)..n).rev().collect();
|
||||
|
||||
CompleteState::Ongoing {
|
||||
cycles,
|
||||
indices
|
||||
}
|
||||
},
|
||||
CompleteState::Ongoing { ref mut indices, ref mut cycles } => {
|
||||
let n = indices.len();
|
||||
let k = cycles.len();
|
||||
|
||||
for i in (0..k).rev() {
|
||||
if cycles[i] == 0 {
|
||||
cycles[i] = n - i - 1;
|
||||
|
||||
let to_push = indices.remove(i);
|
||||
indices.push(to_push);
|
||||
} else {
|
||||
let swap_index = n - cycles[i];
|
||||
indices.swap(i, swap_index);
|
||||
|
||||
cycles[i] -= 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CompleteState::Start { n, k }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn remaining(&self) -> CompleteStateRemaining {
|
||||
use self::CompleteStateRemaining::{Known, Overflow};
|
||||
|
||||
match *self {
|
||||
CompleteState::Start { n, k } => {
|
||||
if n < k {
|
||||
return Known(0);
|
||||
}
|
||||
|
||||
let count: Option<usize> = (n - k + 1..n + 1).fold(Some(1), |acc, i| {
|
||||
acc.and_then(|acc| acc.checked_mul(i))
|
||||
});
|
||||
|
||||
match count {
|
||||
Some(count) => Known(count),
|
||||
None => Overflow
|
||||
}
|
||||
}
|
||||
CompleteState::Ongoing { ref indices, ref cycles } => {
|
||||
let mut count: usize = 0;
|
||||
|
||||
for (i, &c) in cycles.iter().enumerate() {
|
||||
let radix = indices.len() - i;
|
||||
let next_count = count.checked_mul(radix)
|
||||
.and_then(|count| count.checked_add(c));
|
||||
|
||||
count = match next_count {
|
||||
Some(count) => count,
|
||||
None => { return Overflow; }
|
||||
};
|
||||
}
|
||||
|
||||
Known(count)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
90
zeroidc/vendor/itertools/src/powerset.rs
vendored
Normal file
90
zeroidc/vendor/itertools/src/powerset.rs
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
use std::fmt;
|
||||
use std::iter::FusedIterator;
|
||||
use std::usize;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use super::combinations::{Combinations, combinations};
|
||||
use super::size_hint;
|
||||
|
||||
/// 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>,
|
||||
// Iterator `position` (equal to count of yielded elements).
|
||||
pos: usize,
|
||||
}
|
||||
|
||||
impl<I> Clone for Powerset<I>
|
||||
where I: Clone + Iterator,
|
||||
I::Item: Clone,
|
||||
{
|
||||
clone_fields!(combs, pos);
|
||||
}
|
||||
|
||||
impl<I> fmt::Debug for Powerset<I>
|
||||
where I: Iterator + fmt::Debug,
|
||||
I::Item: fmt::Debug,
|
||||
{
|
||||
debug_fmt_fields!(Powerset, combs, pos);
|
||||
}
|
||||
|
||||
/// 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),
|
||||
pos: 0,
|
||||
}
|
||||
}
|
||||
|
||||
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() {
|
||||
self.pos = self.pos.saturating_add(1);
|
||||
Some(elt)
|
||||
} else if self.combs.k() < self.combs.n()
|
||||
|| self.combs.k() == 0
|
||||
{
|
||||
self.combs.reset(self.combs.k() + 1);
|
||||
self.combs.next().map(|elt| {
|
||||
self.pos = self.pos.saturating_add(1);
|
||||
elt
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
// Total bounds for source iterator.
|
||||
let src_total = size_hint::add_scalar(self.combs.src().size_hint(), self.combs.n());
|
||||
|
||||
// Total bounds for self ( length(powerset(set) == 2 ^ length(set) )
|
||||
let self_total = size_hint::pow_scalar_base(2, src_total);
|
||||
|
||||
if self.pos < usize::MAX {
|
||||
// Subtract count of elements already yielded from total.
|
||||
size_hint::sub_scalar(self_total, self.pos)
|
||||
} else {
|
||||
// Fallback: self.pos is saturated and no longer reliable.
|
||||
(0, self_total.1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> FusedIterator for Powerset<I>
|
||||
where
|
||||
I: Iterator,
|
||||
I::Item: Clone,
|
||||
{}
|
||||
97
zeroidc/vendor/itertools/src/process_results_impl.rs
vendored
Normal file
97
zeroidc/vendor/itertools/src/process_results_impl.rs
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
|
||||
/// 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, 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> {
|
||||
match self.iter.next() {
|
||||
Some(Ok(x)) => Some(x),
|
||||
Some(Err(e)) => {
|
||||
*self.error = Err(e);
|
||||
None
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
/// “Lift” a function of the values of an iterator so that it can process
|
||||
/// an iterator of `Result` values instead.
|
||||
///
|
||||
/// `iterable` is an iterator or iterable with `Result<T, E>` elements, where
|
||||
/// `T` is the value type and `E` the error type.
|
||||
///
|
||||
/// `processor` is a closure that receives an adapted version of the iterable
|
||||
/// as the only argument — the adapted iterator produces elements of type `T`,
|
||||
/// as long as the original iterator produces `Ok` values.
|
||||
///
|
||||
/// If the original iterable produces an error at any point, the adapted
|
||||
/// iterator ends and the `process_results` function will return the
|
||||
/// error iself.
|
||||
///
|
||||
/// Otherwise, the return value from the closure is returned wrapped
|
||||
/// inside `Ok`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use itertools::process_results;
|
||||
///
|
||||
/// type R = Result<i32, &'static str>;
|
||||
///
|
||||
/// let first_values: Vec<R> = vec![Ok(1), Ok(0), Ok(3)];
|
||||
/// let second_values: Vec<R> = vec![Ok(2), Ok(1), Err("overflow")];
|
||||
///
|
||||
/// // “Lift” the iterator .max() method to work on the values in Results using process_results
|
||||
///
|
||||
/// let first_max = process_results(first_values, |iter| iter.max().unwrap_or(0));
|
||||
/// let second_max = process_results(second_values, |iter| iter.max().unwrap_or(0));
|
||||
///
|
||||
/// assert_eq!(first_max, Ok(3));
|
||||
/// assert!(second_max.is_err());
|
||||
/// ```
|
||||
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)
|
||||
}
|
||||
61
zeroidc/vendor/itertools/src/put_back_n_impl.rs
vendored
Normal file
61
zeroidc/vendor/itertools/src/put_back_n_impl.rs
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
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)]
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
||||
100
zeroidc/vendor/itertools/src/rciter_impl.rs
vendored
Normal file
100
zeroidc/vendor/itertools/src/rciter_impl.rs
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
|
||||
use std::iter::{FusedIterator, IntoIterator};
|
||||
use alloc::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
|
||||
/// A wrapper for `Rc<RefCell<I>>`, that implements the `Iterator` trait.
|
||||
#[derive(Debug)]
|
||||
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> {
|
||||
#[inline]
|
||||
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>
|
||||
{}
|
||||
59
zeroidc/vendor/itertools/src/repeatn.rs
vendored
Normal file
59
zeroidc/vendor/itertools/src/repeatn.rs
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
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> {
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> DoubleEndedIterator for RepeatN<A>
|
||||
where A: Clone
|
||||
{
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
self.next()
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> ExactSizeIterator for RepeatN<A>
|
||||
where A: Clone
|
||||
{}
|
||||
|
||||
impl<A> FusedIterator for RepeatN<A>
|
||||
where A: Clone
|
||||
{}
|
||||
119
zeroidc/vendor/itertools/src/size_hint.rs
vendored
Normal file
119
zeroidc/vendor/itertools/src/size_hint.rs
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
//! Arithmetic on **Iterator** *.size_hint()* values.
|
||||
//!
|
||||
|
||||
use std::usize;
|
||||
use std::cmp;
|
||||
use std::u32;
|
||||
|
||||
/// **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)
|
||||
}
|
||||
|
||||
/// Sbb **x** correctly to a **SizeHint**.
|
||||
#[inline]
|
||||
#[allow(dead_code)]
|
||||
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
|
||||
///
|
||||
/// ```ignore
|
||||
/// use std::usize;
|
||||
/// use itertools::size_hint;
|
||||
///
|
||||
/// assert_eq!(size_hint::mul((3, Some(4)), (3, Some(4))),
|
||||
/// (9, Some(16)));
|
||||
///
|
||||
/// assert_eq!(size_hint::mul((3, Some(4)), (usize::MAX, None)),
|
||||
/// (usize::MAX, None));
|
||||
///
|
||||
/// assert_eq!(size_hint::mul((3, None), (0, Some(0))),
|
||||
/// (0, Some(0)));
|
||||
/// ```
|
||||
#[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)
|
||||
}
|
||||
|
||||
/// Raise `base` correctly by a **`SizeHint`** exponent.
|
||||
#[inline]
|
||||
pub fn pow_scalar_base(base: usize, exp: SizeHint) -> SizeHint {
|
||||
let exp_low = cmp::min(exp.0, u32::MAX as usize) as u32;
|
||||
let low = base.saturating_pow(exp_low);
|
||||
|
||||
let hi = exp.1.and_then(|exp| {
|
||||
let exp_hi = cmp::min(exp, u32::MAX as usize) as u32;
|
||||
base.checked_pow(exp_hi)
|
||||
});
|
||||
|
||||
(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)
|
||||
}
|
||||
183
zeroidc/vendor/itertools/src/sources.rs
vendored
Normal file
183
zeroidc/vendor/itertools/src/sources.rs
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
//! Iterators that are sources (produce elements from parameters,
|
||||
//! not from another iterator).
|
||||
#![allow(deprecated)]
|
||||
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
|
||||
/// See [`repeat_call`](crate::repeat_call) for more information.
|
||||
#[derive(Clone)]
|
||||
#[deprecated(note="Use std repeat_with() instead", since="0.8.0")]
|
||||
pub struct RepeatCall<F> {
|
||||
f: F,
|
||||
}
|
||||
|
||||
impl<F> fmt::Debug for RepeatCall<F>
|
||||
{
|
||||
debug_fmt_fields!(RepeatCall, );
|
||||
}
|
||||
|
||||
/// An iterator source that produces elements indefinitely by calling
|
||||
/// a given closure.
|
||||
///
|
||||
/// Iterator element type is the return type of the closure.
|
||||
///
|
||||
/// ```
|
||||
/// use itertools::repeat_call;
|
||||
/// use itertools::Itertools;
|
||||
/// use std::collections::BinaryHeap;
|
||||
///
|
||||
/// let mut heap = BinaryHeap::from(vec![2, 5, 3, 7, 8]);
|
||||
///
|
||||
/// // extract each element in sorted order
|
||||
/// for element in repeat_call(|| heap.pop()).while_some() {
|
||||
/// print!("{}", element);
|
||||
/// }
|
||||
///
|
||||
/// itertools::assert_equal(
|
||||
/// repeat_call(|| 1).take(5),
|
||||
/// vec![1, 1, 1, 1, 1]
|
||||
/// );
|
||||
/// ```
|
||||
#[deprecated(note="Use std repeat_with() instead", since="0.8.0")]
|
||||
pub fn repeat_call<F, A>(function: F) -> RepeatCall<F>
|
||||
where F: FnMut() -> A
|
||||
{
|
||||
RepeatCall { f: function }
|
||||
}
|
||||
|
||||
impl<A, F> Iterator for RepeatCall<F>
|
||||
where F: FnMut() -> A
|
||||
{
|
||||
type Item = A;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
Some((self.f)())
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(usize::max_value(), None)
|
||||
}
|
||||
}
|
||||
|
||||
/// 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))
|
||||
/// ```
|
||||
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"]
|
||||
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_value(), 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).take(5), vec![1, 3, 9, 27, 81]);
|
||||
/// ```
|
||||
pub fn iterate<St, F>(initial_value: St, f: F) -> Iterate<St, F>
|
||||
where F: FnMut(&St) -> St
|
||||
{
|
||||
Iterate {
|
||||
state: initial_value,
|
||||
f,
|
||||
}
|
||||
}
|
||||
78
zeroidc/vendor/itertools/src/tee.rs
vendored
Normal file
78
zeroidc/vendor/itertools/src/tee.rs
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
use super::size_hint;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use alloc::collections::VecDeque;
|
||||
use alloc::rc::Rc;
|
||||
|
||||
/// 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
|
||||
{}
|
||||
331
zeroidc/vendor/itertools/src/tuple_impl.rs
vendored
Normal file
331
zeroidc/vendor/itertools/src/tuple_impl.rs
vendored
Normal file
@@ -0,0 +1,331 @@
|
||||
//! Some iterator that produces tuples
|
||||
|
||||
use std::iter::Fuse;
|
||||
use std::iter::FusedIterator;
|
||||
use std::iter::Take;
|
||||
use std::iter::Cycle;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
// `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 {
|
||||
TupleBuffer {
|
||||
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_else(|| 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)
|
||||
}
|
||||
}
|
||||
|
||||
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>(mut iter: I) -> TupleWindows<I, T>
|
||||
where I: Iterator<Item = T::Item>,
|
||||
T: HomogeneousTuple,
|
||||
T::Item: Clone
|
||||
{
|
||||
use std::iter::once;
|
||||
|
||||
let mut last = None;
|
||||
if T::num_items() != 1 {
|
||||
// put in a duplicate item in front of the tuple; this simplifies
|
||||
// .next() function.
|
||||
if let Some(item) = iter.next() {
|
||||
let iter = once(item.clone()).chain(once(item)).chain(&mut iter);
|
||||
last = T::collect_from_iter_no_buf(iter);
|
||||
}
|
||||
}
|
||||
|
||||
TupleWindows {
|
||||
last,
|
||||
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(ref mut last) = self.last {
|
||||
if let Some(new) = self.iter.next() {
|
||||
last.left_shift_push(new);
|
||||
return Some(last.clone());
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
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)]
|
||||
pub struct CircularTupleWindows<I, T: Clone>
|
||||
where I: Iterator<Item = T::Item> + Clone,
|
||||
T: TupleCollect + Clone
|
||||
{
|
||||
iter: Take<TupleWindows<Cycle<I>, T>>,
|
||||
phantom_data: PhantomData<T>
|
||||
}
|
||||
|
||||
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()).take(len);
|
||||
|
||||
CircularTupleWindows {
|
||||
iter,
|
||||
phantom_data: PhantomData{}
|
||||
}
|
||||
}
|
||||
|
||||
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> {
|
||||
self.iter.next()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait TupleCollect: Sized {
|
||||
type Item;
|
||||
type Buffer: Default + AsRef<[Option<Self::Item>]> + AsMut<[Option<Self::Item>]>;
|
||||
|
||||
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! count_ident{
|
||||
() => {0};
|
||||
($i0:ident, $($i:ident,)*) => {1 + count_ident!($($i,)*)};
|
||||
}
|
||||
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,);
|
||||
178
zeroidc/vendor/itertools/src/unique_impl.rs
vendored
Normal file
178
zeroidc/vendor/itertools/src/unique_impl.rs
vendored
Normal file
@@ -0,0 +1,178 @@
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::collections::hash_map::{Entry};
|
||||
use std::hash::Hash;
|
||||
use std::fmt;
|
||||
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
|
||||
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> {
|
||||
while let Some(v) = self.iter.next() {
|
||||
let key = (self.f)(&v);
|
||||
if self.used.insert(key, ()).is_none() {
|
||||
return Some(v);
|
||||
}
|
||||
}
|
||||
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> {
|
||||
while let Some(v) = self.iter.next_back() {
|
||||
let key = (self.f)(&v);
|
||||
if self.used.insert(key, ()).is_none() {
|
||||
return Some(v);
|
||||
}
|
||||
}
|
||||
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> {
|
||||
while let Some(v) = self.iter.iter.next() {
|
||||
if let Entry::Vacant(entry) = self.iter.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> {
|
||||
while let Some(v) = self.iter.iter.next_back() {
|
||||
if let Entry::Vacant(entry) = self.iter.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: Iterator> {
|
||||
iter: UniqueBy<I, I::Item, ()>,
|
||||
}
|
||||
|
||||
impl<I> fmt::Debug for Unique<I>
|
||||
where I: Iterator + fmt::Debug,
|
||||
I::Item: Hash + Eq + fmt::Debug,
|
||||
{
|
||||
debug_fmt_fields!(Unique, iter);
|
||||
}
|
||||
|
||||
pub fn unique<I>(iter: I) -> Unique<I>
|
||||
where I: Iterator,
|
||||
I::Item: Eq + Hash,
|
||||
{
|
||||
Unique {
|
||||
iter: UniqueBy {
|
||||
iter,
|
||||
used: HashMap::new(),
|
||||
f: (),
|
||||
}
|
||||
}
|
||||
}
|
||||
80
zeroidc/vendor/itertools/src/unziptuple.rs
vendored
Normal file
80
zeroidc/vendor/itertools/src/unziptuple.rs
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
/// Converts an iterator of tuples into a tuple of containers.
|
||||
///
|
||||
/// `unzip()` 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 as close as possible.
|
||||
// Unfortunately a lot of the used api there is still unstable represented by
|
||||
// the commented out parts that follow.
|
||||
//
|
||||
// https://doc.rust-lang.org/src/core/iter/traits/iterator.rs.html#2816-2844
|
||||
|
||||
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);
|
||||
100
zeroidc/vendor/itertools/src/with_position.rs
vendored
Normal file
100
zeroidc/vendor/itertools/src/with_position.rs
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
use std::iter::{Fuse,Peekable, FusedIterator};
|
||||
|
||||
/// 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> 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(),
|
||||
}
|
||||
}
|
||||
|
||||
/// A value yielded by `WithPosition`.
|
||||
/// Indicates the position of this element in the iterator results.
|
||||
///
|
||||
/// See [`.with_position()`](crate::Itertools::with_position) for more information.
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum Position<T> {
|
||||
/// This is the first element.
|
||||
First(T),
|
||||
/// This is neither the first nor the last element.
|
||||
Middle(T),
|
||||
/// This is the last element.
|
||||
Last(T),
|
||||
/// This is the only element.
|
||||
Only(T),
|
||||
}
|
||||
|
||||
impl<T> Position<T> {
|
||||
/// Return the inner value.
|
||||
pub fn into_inner(self) -> T {
|
||||
match self {
|
||||
Position::First(x) |
|
||||
Position::Middle(x) |
|
||||
Position::Last(x) |
|
||||
Position::Only(x) => x,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> ExactSizeIterator for WithPosition<I>
|
||||
where I: ExactSizeIterator,
|
||||
{ }
|
||||
|
||||
impl<I: Iterator> FusedIterator for WithPosition<I>
|
||||
{}
|
||||
60
zeroidc/vendor/itertools/src/zip_eq_impl.rs
vendored
Normal file
60
zeroidc/vendor/itertools/src/zip_eq_impl.rs
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
use super::size_hint;
|
||||
|
||||
/// An iterator which iterates two other iterators simultaneously
|
||||
///
|
||||
/// 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,
|
||||
}
|
||||
|
||||
/// Iterate `i` and `j` in lock step.
|
||||
///
|
||||
/// **Panics** if the iterators 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
|
||||
{}
|
||||
83
zeroidc/vendor/itertools/src/zip_longest.rs
vendored
Normal file
83
zeroidc/vendor/itertools/src/zip_longest.rs
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
use std::cmp::Ordering::{Equal, Greater, Less};
|
||||
use super::size_hint;
|
||||
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
|
||||
///
|
||||
/// 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())
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
zeroidc/vendor/itertools/src/ziptuple.rs
vendored
Normal file
137
zeroidc/vendor/itertools/src/ziptuple.rs
vendored
Normal 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 macro is a value of a named type (`Zip<(I, J,
|
||||
/// ..)>` of each component iterator `I, J, ...`) if each component iterator is
|
||||
/// nameable.
|
||||
///
|
||||
/// Prefer [`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>,
|
||||
Zip<T>: 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 = (::std::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);
|
||||
Reference in New Issue
Block a user