Skip to content

Commit ccc5081

Browse files
committed
Add more FusedIterator
Some Iterator is fused if the underlying Iterator is fused. (UniqueBy, Unique, InterleaveShortest, Product, MergeBy, FilterOk, FilterMapOk, Positions, Update) Combinations is fused.
1 parent a9e367f commit ccc5081

File tree

4 files changed

+130
-1
lines changed

4 files changed

+130
-1
lines changed

src/adaptors/mod.rs

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub use self::map::MapResults;
1515
pub use self::multi_product::*;
1616

1717
use std::fmt;
18-
use std::iter::{Fuse, Peekable, FromIterator};
18+
use std::iter::{Fuse, Peekable, FromIterator, FusedIterator};
1919
use std::marker::PhantomData;
2020
use crate::size_hint;
2121

@@ -157,6 +157,11 @@ impl<I, J> Iterator for InterleaveShortest<I, J>
157157
}
158158
}
159159

160+
impl<I, J> FusedIterator for InterleaveShortest<I, J>
161+
where I: FusedIterator,
162+
J: FusedIterator<Item = I::Item>
163+
{}
164+
160165
#[derive(Clone, Debug)]
161166
/// An iterator adaptor that allows putting back a single
162167
/// item to the front of the iterator.
@@ -361,6 +366,12 @@ impl<I, J> Iterator for Product<I, J>
361366
}
362367
}
363368

369+
impl<I, J> FusedIterator for Product<I, J>
370+
where I: FusedIterator,
371+
J: Clone + FusedIterator,
372+
I::Item: Clone
373+
{}
374+
364375
/// A “meta iterator adaptor”. Its closure receives a reference to the iterator
365376
/// and may pick off as many elements as it likes, to produce the next iterator element.
366377
///
@@ -588,6 +599,12 @@ impl<I, J, F> Iterator for MergeBy<I, J, F>
588599
}
589600
}
590601

602+
impl<I, J, F> FusedIterator for MergeBy<I, J, F>
603+
where I: FusedIterator,
604+
J: FusedIterator<Item = I::Item>,
605+
F: MergePredicate<I::Item>
606+
{}
607+
591608
/// An iterator adaptor that borrows from a `Clone`-able iterator
592609
/// to only pick off elements while the predicate returns `true`.
593610
///
@@ -876,6 +893,11 @@ impl<I, F, T, E> Iterator for FilterOk<I, F>
876893
}
877894
}
878895

896+
impl<I, F, T, E> FusedIterator for FilterOk<I, F>
897+
where I: FusedIterator<Item = Result<T, E>>,
898+
F: FnMut(&T) -> bool,
899+
{}
900+
879901
/// An iterator adapter to filter and apply a transformation on values within a nested `Result::Ok`.
880902
///
881903
/// See [`.filter_map_ok()`](crate::Itertools::filter_map_ok) for more information.
@@ -947,6 +969,11 @@ impl<I, F, T, U, E> Iterator for FilterMapOk<I, F>
947969
}
948970
}
949971

972+
impl<I, F, T, U, E> FusedIterator for FilterMapOk<I, F>
973+
where I: FusedIterator<Item = Result<T, E>>,
974+
F: FnMut(T) -> Option<U>,
975+
{}
976+
950977
/// An iterator adapter to get the positions of each element that matches a predicate.
951978
///
952979
/// See [`.positions()`](crate::Itertools::positions) for more information.
@@ -1006,6 +1033,11 @@ impl<I, F> DoubleEndedIterator for Positions<I, F>
10061033
}
10071034
}
10081035

1036+
impl<I, F> FusedIterator for Positions<I, F>
1037+
where I: FusedIterator,
1038+
F: FnMut(I::Item) -> bool,
1039+
{}
1040+
10091041
/// An iterator adapter to apply a mutating function to each element before yielding it.
10101042
///
10111043
/// See [`.update()`](crate::Itertools::update) for more information.
@@ -1081,3 +1113,9 @@ where
10811113
}
10821114
}
10831115
}
1116+
1117+
impl<I, F> FusedIterator for Update<I, F>
1118+
where
1119+
I: FusedIterator,
1120+
F: FnMut(&mut I::Item),
1121+
{}

src/combinations.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::fmt;
2+
use std::iter::FusedIterator;
23

34
use super::lazy_buffer::LazyBuffer;
45
use alloc::vec::Vec;
@@ -122,3 +123,8 @@ impl<I> Iterator for Combinations<I>
122123
Some(self.indices.iter().map(|i| self.pool[*i].clone()).collect())
123124
}
124125
}
126+
127+
impl<I> FusedIterator for Combinations<I>
128+
where I: Iterator,
129+
I::Item: Clone
130+
{}

src/unique_impl.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::collections::HashMap;
33
use std::collections::hash_map::{Entry};
44
use std::hash::Hash;
55
use std::fmt;
6+
use std::iter::FusedIterator;
67

78
/// An iterator adapter to filter out duplicate elements.
89
///
@@ -92,6 +93,12 @@ impl<I, V, F> DoubleEndedIterator for UniqueBy<I, V, F>
9293
}
9394
}
9495

96+
impl<I, V, F> FusedIterator for UniqueBy<I, V, F>
97+
where I: FusedIterator,
98+
V: Eq + Hash,
99+
F: FnMut(&I::Item) -> V
100+
{}
101+
95102
impl<I> Iterator for Unique<I>
96103
where I: Iterator,
97104
I::Item: Eq + Hash + Clone
@@ -136,6 +143,11 @@ impl<I> DoubleEndedIterator for Unique<I>
136143
}
137144
}
138145

146+
impl<I> FusedIterator for Unique<I>
147+
where I: FusedIterator,
148+
I::Item: Eq + Hash + Clone
149+
{}
150+
139151
/// An iterator adapter to filter out duplicate elements.
140152
///
141153
/// See [`.unique()`](crate::Itertools::unique) for more information.

tests/quick.rs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1598,3 +1598,76 @@ quickcheck! {
15981598
TestResult::from_bool(itertools::equal(x, y))
15991599
}
16001600
}
1601+
1602+
1603+
fn is_fused<I: Iterator>(mut it: I) -> bool
1604+
{
1605+
while let Some(_) = it.next() {}
1606+
for _ in 0..10{
1607+
if it.next().is_some(){
1608+
return false;
1609+
}
1610+
}
1611+
true
1612+
}
1613+
1614+
quickcheck! {
1615+
fn fused_combination(a: Iter<i16>) -> bool
1616+
{
1617+
is_fused(a.clone().combinations(1)) &&
1618+
is_fused(a.combinations(3))
1619+
}
1620+
1621+
fn fused_unique(a: Iter<i16>) -> bool
1622+
{
1623+
is_fused(a.fuse().unique())
1624+
}
1625+
1626+
fn fused_unique_by(a: Iter<i16>) -> bool
1627+
{
1628+
is_fused(a.fuse().unique_by(|x| x % 100))
1629+
}
1630+
1631+
fn fused_interleave_shortest(a: Iter<i16>, b: Iter<i16>) -> bool
1632+
{
1633+
!is_fused(a.clone().interleave_shortest(b.clone())) &&
1634+
is_fused(a.fuse().interleave_shortest(b.fuse()))
1635+
}
1636+
1637+
fn fused_product(a: Iter<i16>, b: Iter<i16>) -> bool
1638+
{
1639+
is_fused(a.fuse().cartesian_product(b.fuse()))
1640+
}
1641+
1642+
fn fused_merge(a: Iter<i16>, b: Iter<i16>) -> bool
1643+
{
1644+
is_fused(a.fuse().merge(b.fuse()))
1645+
}
1646+
1647+
fn fused_filter_ok(a: Iter<i16>) -> bool
1648+
{
1649+
is_fused(a.map(|x| if x % 2 == 0 {Ok(x)} else {Err(x)} )
1650+
.filter_ok(|x| x % 3 == 0)
1651+
.fuse())
1652+
}
1653+
1654+
fn fused_filter_map_ok(a: Iter<i16>) -> bool
1655+
{
1656+
is_fused(a.map(|x| if x % 2 == 0 {Ok(x)} else {Err(x)} )
1657+
.filter_map_ok(|x| if x % 3 == 0 {Some(x / 3)} else {None})
1658+
.fuse())
1659+
}
1660+
1661+
fn fused_positions(a: Iter<i16>) -> bool
1662+
{
1663+
!is_fused(a.clone().positions(|x|x%2==0)) &&
1664+
is_fused(a.fuse().positions(|x|x%2==0))
1665+
}
1666+
1667+
fn fused_update(a: Iter<i16>) -> bool
1668+
{
1669+
!is_fused(a.clone().update(|x|*x+=1)) &&
1670+
is_fused(a.fuse().update(|x|*x+=1))
1671+
}
1672+
}
1673+

0 commit comments

Comments
 (0)