Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add More FusedIterator #550

Merged
merged 2 commits into from Jun 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
45 changes: 44 additions & 1 deletion src/adaptors/mod.rs
Expand Up @@ -15,7 +15,7 @@ pub use self::map::MapResults;
pub use self::multi_product::*;

use std::fmt;
use std::iter::{Fuse, Peekable, FromIterator};
use std::iter::{Fuse, Peekable, FromIterator, FusedIterator};
use std::marker::PhantomData;
use crate::size_hint;

Expand Down Expand Up @@ -157,6 +157,11 @@ impl<I, J> Iterator for InterleaveShortest<I, J>
}
}

impl<I, J> FusedIterator for InterleaveShortest<I, J>
where I: FusedIterator,
J: FusedIterator<Item = I::Item>
{}

#[derive(Clone, Debug)]
/// An iterator adaptor that allows putting back a single
/// item to the front of the iterator.
Expand Down Expand Up @@ -361,6 +366,12 @@ impl<I, J> Iterator for Product<I, J>
}
}

impl<I, J> FusedIterator for Product<I, J>
where I: FusedIterator,
J: Clone + FusedIterator,
I::Item: Clone
{}

/// A “meta iterator adaptor”. Its closure receives a reference to the iterator
/// and may pick off as many elements as it likes, to produce the next iterator element.
///
Expand Down Expand Up @@ -588,6 +599,12 @@ impl<I, J, F> Iterator for MergeBy<I, J, F>
}
}

impl<I, J, F> FusedIterator for MergeBy<I, J, F>
where I: FusedIterator,
J: FusedIterator<Item = I::Item>,
F: MergePredicate<I::Item>
{}

/// An iterator adaptor that borrows from a `Clone`-able iterator
/// to only pick off elements while the predicate returns `true`.
///
Expand Down Expand Up @@ -711,6 +728,11 @@ impl<I, T> Iterator for TupleCombinations<I, T>
}
}

impl<I, T> FusedIterator for TupleCombinations<I, T>
where I: FusedIterator,
T: HasCombination<I>,
{}

#[derive(Clone, Debug)]
pub struct Tuple1Combination<I> {
iter: I,
Expand Down Expand Up @@ -876,6 +898,11 @@ impl<I, F, T, E> Iterator for FilterOk<I, F>
}
}

impl<I, F, T, E> FusedIterator for FilterOk<I, F>
where I: FusedIterator<Item = Result<T, E>>,
F: FnMut(&T) -> bool,
{}

/// An iterator adapter to filter and apply a transformation on values within a nested `Result::Ok`.
///
/// See [`.filter_map_ok()`](crate::Itertools::filter_map_ok) for more information.
Expand Down Expand Up @@ -947,6 +974,11 @@ impl<I, F, T, U, E> Iterator for FilterMapOk<I, F>
}
}

impl<I, F, T, U, E> FusedIterator for FilterMapOk<I, F>
where I: FusedIterator<Item = Result<T, E>>,
F: FnMut(T) -> Option<U>,
{}

/// An iterator adapter to get the positions of each element that matches a predicate.
///
/// See [`.positions()`](crate::Itertools::positions) for more information.
Expand Down Expand Up @@ -1006,6 +1038,11 @@ impl<I, F> DoubleEndedIterator for Positions<I, F>
}
}

impl<I, F> FusedIterator for Positions<I, F>
where I: FusedIterator,
F: FnMut(I::Item) -> bool,
{}

/// An iterator adapter to apply a mutating function to each element before yielding it.
///
/// See [`.update()`](crate::Itertools::update) for more information.
Expand Down Expand Up @@ -1081,3 +1118,9 @@ where
}
}
}

impl<I, F> FusedIterator for Update<I, F>
where
I: FusedIterator,
F: FnMut(&mut I::Item),
{}
6 changes: 6 additions & 0 deletions src/combinations.rs
@@ -1,4 +1,5 @@
use std::fmt;
use std::iter::FusedIterator;

use super::lazy_buffer::LazyBuffer;
use alloc::vec::Vec;
Expand Down Expand Up @@ -122,3 +123,8 @@ impl<I> Iterator for Combinations<I>
Some(self.indices.iter().map(|i| self.pool[*i].clone()).collect())
}
}

impl<I> FusedIterator for Combinations<I>
where I: Iterator,
I::Item: Clone
{}
7 changes: 7 additions & 0 deletions src/combinations_with_replacement.rs
@@ -1,5 +1,6 @@
use alloc::vec::Vec;
use std::fmt;
use std::iter::FusedIterator;

use super::lazy_buffer::LazyBuffer;

Expand Down Expand Up @@ -100,3 +101,9 @@ where
}
}
}

impl<I> FusedIterator for CombinationsWithReplacement<I>
where
I: Iterator,
I::Item: Clone,
{}
6 changes: 6 additions & 0 deletions src/kmerge_impl.rs
Expand Up @@ -2,6 +2,7 @@ use crate::size_hint;
use crate::Itertools;

use alloc::vec::Vec;
use std::iter::FusedIterator;
use std::mem::replace;
use std::fmt;

Expand Down Expand Up @@ -219,3 +220,8 @@ impl<I, F> Iterator for KMergeBy<I, F>
.unwrap_or((0, Some(0)))
}
}

impl<I, F> FusedIterator for KMergeBy<I, F>
where I: Iterator,
F: KMergePredicate<I::Item>
{}
8 changes: 7 additions & 1 deletion src/pad_tail.rs
@@ -1,4 +1,4 @@
use std::iter::Fuse;
use std::iter::{Fuse, FusedIterator};
use crate::size_hint;

/// An iterator adaptor that pads a sequence to a minimum length by filling
Expand Down Expand Up @@ -81,3 +81,9 @@ 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
{}
7 changes: 7 additions & 0 deletions src/powerset.rs
@@ -1,4 +1,5 @@
use std::fmt;
use std::iter::FusedIterator;
use std::usize;
use alloc::vec::Vec;

Expand Down Expand Up @@ -81,3 +82,9 @@ impl<I> Iterator for Powerset<I>
}
}
}

impl<I> FusedIterator for Powerset<I>
where
I: Iterator,
I::Item: Clone,
{}
7 changes: 6 additions & 1 deletion src/rciter_impl.rs
@@ -1,5 +1,5 @@

use std::iter::IntoIterator;
use std::iter::{FusedIterator, IntoIterator};
use alloc::rc::Rc;
use std::cell::RefCell;

Expand Down Expand Up @@ -93,3 +93,8 @@ impl<'a, I> IntoIterator for &'a RcIter<I>
self.clone()
}
}


impl<A, I> FusedIterator for RcIter<I>
where I: FusedIterator<Item = A>
{}
5 changes: 5 additions & 0 deletions src/repeatn.rs
@@ -1,3 +1,4 @@
use std::iter::FusedIterator;

/// An iterator that produces *n* repetitions of an element.
///
Expand Down Expand Up @@ -52,3 +53,7 @@ impl<A> DoubleEndedIterator for RepeatN<A>
impl<A> ExactSizeIterator for RepeatN<A>
where A: Clone
{}

impl<A> FusedIterator for RepeatN<A>
where A: Clone
{}
7 changes: 7 additions & 0 deletions src/tuple_impl.rs
@@ -1,6 +1,7 @@
//! 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;
Expand Down Expand Up @@ -187,6 +188,12 @@ impl<I, T> Iterator for TupleWindows<I, T>
}
}

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.
Expand Down
12 changes: 12 additions & 0 deletions src/unique_impl.rs
Expand Up @@ -3,6 +3,7 @@ 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.
///
Expand Down Expand Up @@ -92,6 +93,12 @@ impl<I, V, F> DoubleEndedIterator for UniqueBy<I, V, F>
}
}

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
Expand Down Expand Up @@ -136,6 +143,11 @@ impl<I> DoubleEndedIterator for Unique<I>
}
}

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.
Expand Down
5 changes: 4 additions & 1 deletion src/with_position.rs
@@ -1,4 +1,4 @@
use std::iter::{Fuse,Peekable};
use std::iter::{Fuse,Peekable, FusedIterator};

/// An iterator adaptor that wraps each element in an [`Position`].
///
Expand Down Expand Up @@ -95,3 +95,6 @@ impl<I: Iterator> Iterator for WithPosition<I> {
impl<I> ExactSizeIterator for WithPosition<I>
where I: ExactSizeIterator,
{ }

impl<I: Iterator> FusedIterator for WithPosition<I>
{}
95 changes: 95 additions & 0 deletions tests/quick.rs
Expand Up @@ -1598,3 +1598,98 @@ quickcheck! {
TestResult::from_bool(itertools::equal(x, y))
}
}


fn is_fused<I: Iterator>(mut it: I) -> bool
{
while let Some(_) = it.next() {}
for _ in 0..10{
if it.next().is_some(){
return false;
}
}
true
}

quickcheck! {
fn fused_combination(a: Iter<i16>) -> bool
{
is_fused(a.clone().combinations(1)) &&
is_fused(a.combinations(3))
}

fn fused_combination_with_replacement(a: Iter<i16>) -> bool
{
is_fused(a.clone().combinations_with_replacement(1)) &&
is_fused(a.combinations_with_replacement(3))
}

fn fused_tuple_combination(a: Iter<i16>) -> bool
{
is_fused(a.clone().fuse().tuple_combinations::<(_,)>()) &&
is_fused(a.fuse().tuple_combinations::<(_,_,_)>())
}

fn fused_unique(a: Iter<i16>) -> bool
{
is_fused(a.fuse().unique())
}

fn fused_unique_by(a: Iter<i16>) -> bool
{
is_fused(a.fuse().unique_by(|x| x % 100))
}

fn fused_interleave_shortest(a: Iter<i16>, b: Iter<i16>) -> bool
{
!is_fused(a.clone().interleave_shortest(b.clone())) &&
is_fused(a.fuse().interleave_shortest(b.fuse()))
}

fn fused_product(a: Iter<i16>, b: Iter<i16>) -> bool
{
is_fused(a.fuse().cartesian_product(b.fuse()))
}

fn fused_merge(a: Iter<i16>, b: Iter<i16>) -> bool
{
is_fused(a.fuse().merge(b.fuse()))
}

fn fused_filter_ok(a: Iter<i16>) -> bool
{
is_fused(a.map(|x| if x % 2 == 0 {Ok(x)} else {Err(x)} )
.filter_ok(|x| x % 3 == 0)
.fuse())
}

fn fused_filter_map_ok(a: Iter<i16>) -> bool
{
is_fused(a.map(|x| if x % 2 == 0 {Ok(x)} else {Err(x)} )
.filter_map_ok(|x| if x % 3 == 0 {Some(x / 3)} else {None})
.fuse())
}

fn fused_positions(a: Iter<i16>) -> bool
{
!is_fused(a.clone().positions(|x|x%2==0)) &&
is_fused(a.fuse().positions(|x|x%2==0))
}

fn fused_update(a: Iter<i16>) -> bool
{
!is_fused(a.clone().update(|x|*x+=1)) &&
is_fused(a.fuse().update(|x|*x+=1))
}

fn fused_tuple_windows(a: Iter<i16>) -> bool
{
is_fused(a.fuse().tuple_windows::<(_,_)>())
}

fn fused_pad_using(a: Iter<i16>) -> bool
{
is_fused(a.fuse().pad_using(100,|_|0))
}
}