Skip to content

Commit

Permalink
Add more FusedIterator
Browse files Browse the repository at this point in the history
Some Iterator is fused if the underlying Iterator is fused.
(UniqueBy, Unique, InterleaveShortest, Product, MergeBy, FilterOk,
FilterMapOk, Positions, Update)
Combinations is fused.
  • Loading branch information
aobatact committed May 26, 2021
1 parent a9e367f commit ccc5081
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 1 deletion.
40 changes: 39 additions & 1 deletion src/adaptors/mod.rs
Original file line number Diff line number Diff line change
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 @@ -876,6 +893,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 +969,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 +1033,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 +1113,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
Original file line number Diff line number Diff line change
@@ -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
{}
12 changes: 12 additions & 0 deletions src/unique_impl.rs
Original file line number Diff line number Diff line change
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
73 changes: 73 additions & 0 deletions tests/quick.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1598,3 +1598,76 @@ 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_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))
}
}

0 comments on commit ccc5081

Please sign in to comment.