Skip to content

Commit eedea19

Browse files
bors[bot]aobatact
andauthored
Merge #550
550: Add More FusedIterator r=jswrenn a=aobatact These Iterator is fused if the underlying Iterator is fused. - `FilterOk` - `FilterMapOk` - `InterleaveShortest` - `KMergeBy` - `MergeBy` - `PadUsing` - `Positions` - `Product` - `RcIter` - `TupleWindows` - `Unique` - `UniqueBy` - `Update` - `WhileSome` These is fused even though the underlying Iterator is not fused. - `Combinations` - `CombinationsWithReplacement` - `Powerset` - `RepeatN` - `WithPosition` `FusedIterator` can be added to these structs. Related #55, #152, #531, #533 I separate the pull request with #548 because these Iterator are sure to be fused because it was documented, but I'm not 100% sure that the structs in this PR is actually fused. (Though I believe it is.) Co-authored-by: aobatact <[email protected]>
2 parents a9e367f + f9ccc34 commit eedea19

12 files changed

+206
-4
lines changed

src/adaptors/mod.rs

Lines changed: 44 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
///
@@ -711,6 +728,11 @@ impl<I, T> Iterator for TupleCombinations<I, T>
711728
}
712729
}
713730

731+
impl<I, T> FusedIterator for TupleCombinations<I, T>
732+
where I: FusedIterator,
733+
T: HasCombination<I>,
734+
{}
735+
714736
#[derive(Clone, Debug)]
715737
pub struct Tuple1Combination<I> {
716738
iter: I,
@@ -876,6 +898,11 @@ impl<I, F, T, E> Iterator for FilterOk<I, F>
876898
}
877899
}
878900

901+
impl<I, F, T, E> FusedIterator for FilterOk<I, F>
902+
where I: FusedIterator<Item = Result<T, E>>,
903+
F: FnMut(&T) -> bool,
904+
{}
905+
879906
/// An iterator adapter to filter and apply a transformation on values within a nested `Result::Ok`.
880907
///
881908
/// See [`.filter_map_ok()`](crate::Itertools::filter_map_ok) for more information.
@@ -947,6 +974,11 @@ impl<I, F, T, U, E> Iterator for FilterMapOk<I, F>
947974
}
948975
}
949976

977+
impl<I, F, T, U, E> FusedIterator for FilterMapOk<I, F>
978+
where I: FusedIterator<Item = Result<T, E>>,
979+
F: FnMut(T) -> Option<U>,
980+
{}
981+
950982
/// An iterator adapter to get the positions of each element that matches a predicate.
951983
///
952984
/// See [`.positions()`](crate::Itertools::positions) for more information.
@@ -1006,6 +1038,11 @@ impl<I, F> DoubleEndedIterator for Positions<I, F>
10061038
}
10071039
}
10081040

1041+
impl<I, F> FusedIterator for Positions<I, F>
1042+
where I: FusedIterator,
1043+
F: FnMut(I::Item) -> bool,
1044+
{}
1045+
10091046
/// An iterator adapter to apply a mutating function to each element before yielding it.
10101047
///
10111048
/// See [`.update()`](crate::Itertools::update) for more information.
@@ -1081,3 +1118,9 @@ where
10811118
}
10821119
}
10831120
}
1121+
1122+
impl<I, F> FusedIterator for Update<I, F>
1123+
where
1124+
I: FusedIterator,
1125+
F: FnMut(&mut I::Item),
1126+
{}

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/combinations_with_replacement.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use alloc::vec::Vec;
22
use std::fmt;
3+
use std::iter::FusedIterator;
34

45
use super::lazy_buffer::LazyBuffer;
56

@@ -100,3 +101,9 @@ where
100101
}
101102
}
102103
}
104+
105+
impl<I> FusedIterator for CombinationsWithReplacement<I>
106+
where
107+
I: Iterator,
108+
I::Item: Clone,
109+
{}

src/kmerge_impl.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::size_hint;
22
use crate::Itertools;
33

44
use alloc::vec::Vec;
5+
use std::iter::FusedIterator;
56
use std::mem::replace;
67
use std::fmt;
78

@@ -219,3 +220,8 @@ impl<I, F> Iterator for KMergeBy<I, F>
219220
.unwrap_or((0, Some(0)))
220221
}
221222
}
223+
224+
impl<I, F> FusedIterator for KMergeBy<I, F>
225+
where I: Iterator,
226+
F: KMergePredicate<I::Item>
227+
{}

src/pad_tail.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::iter::Fuse;
1+
use std::iter::{Fuse, FusedIterator};
22
use crate::size_hint;
33

44
/// An iterator adaptor that pads a sequence to a minimum length by filling
@@ -81,3 +81,9 @@ impl<I, F> ExactSizeIterator for PadUsing<I, F>
8181
where I: ExactSizeIterator,
8282
F: FnMut(usize) -> I::Item
8383
{}
84+
85+
86+
impl<I, F> FusedIterator for PadUsing<I, F>
87+
where I: FusedIterator,
88+
F: FnMut(usize) -> I::Item
89+
{}

src/powerset.rs

Lines changed: 7 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
use std::usize;
34
use alloc::vec::Vec;
45

@@ -81,3 +82,9 @@ impl<I> Iterator for Powerset<I>
8182
}
8283
}
8384
}
85+
86+
impl<I> FusedIterator for Powerset<I>
87+
where
88+
I: Iterator,
89+
I::Item: Clone,
90+
{}

src/rciter_impl.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
use std::iter::IntoIterator;
2+
use std::iter::{FusedIterator, IntoIterator};
33
use alloc::rc::Rc;
44
use std::cell::RefCell;
55

@@ -93,3 +93,8 @@ impl<'a, I> IntoIterator for &'a RcIter<I>
9393
self.clone()
9494
}
9595
}
96+
97+
98+
impl<A, I> FusedIterator for RcIter<I>
99+
where I: FusedIterator<Item = A>
100+
{}

src/repeatn.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::iter::FusedIterator;
12

23
/// An iterator that produces *n* repetitions of an element.
34
///
@@ -52,3 +53,7 @@ impl<A> DoubleEndedIterator for RepeatN<A>
5253
impl<A> ExactSizeIterator for RepeatN<A>
5354
where A: Clone
5455
{}
56+
57+
impl<A> FusedIterator for RepeatN<A>
58+
where A: Clone
59+
{}

src/tuple_impl.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Some iterator that produces tuples
22
33
use std::iter::Fuse;
4+
use std::iter::FusedIterator;
45
use std::iter::Take;
56
use std::iter::Cycle;
67
use std::marker::PhantomData;
@@ -187,6 +188,12 @@ impl<I, T> Iterator for TupleWindows<I, T>
187188
}
188189
}
189190

191+
impl<I, T> FusedIterator for TupleWindows<I, T>
192+
where I: FusedIterator<Item = T::Item>,
193+
T: HomogeneousTuple + Clone,
194+
T::Item: Clone
195+
{}
196+
190197
/// An iterator over all windows,wrapping back to the first elements when the
191198
/// window would otherwise exceed the length of the iterator, producing tuples
192199
/// of a specific size.

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.

src/with_position.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::iter::{Fuse,Peekable};
1+
use std::iter::{Fuse,Peekable, FusedIterator};
22

33
/// An iterator adaptor that wraps each element in an [`Position`].
44
///
@@ -95,3 +95,6 @@ impl<I: Iterator> Iterator for WithPosition<I> {
9595
impl<I> ExactSizeIterator for WithPosition<I>
9696
where I: ExactSizeIterator,
9797
{ }
98+
99+
impl<I: Iterator> FusedIterator for WithPosition<I>
100+
{}

tests/quick.rs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1598,3 +1598,98 @@ 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_combination_with_replacement(a: Iter<i16>) -> bool
1622+
{
1623+
is_fused(a.clone().combinations_with_replacement(1)) &&
1624+
is_fused(a.combinations_with_replacement(3))
1625+
}
1626+
1627+
fn fused_tuple_combination(a: Iter<i16>) -> bool
1628+
{
1629+
is_fused(a.clone().fuse().tuple_combinations::<(_,)>()) &&
1630+
is_fused(a.fuse().tuple_combinations::<(_,_,_)>())
1631+
}
1632+
1633+
fn fused_unique(a: Iter<i16>) -> bool
1634+
{
1635+
is_fused(a.fuse().unique())
1636+
}
1637+
1638+
fn fused_unique_by(a: Iter<i16>) -> bool
1639+
{
1640+
is_fused(a.fuse().unique_by(|x| x % 100))
1641+
}
1642+
1643+
fn fused_interleave_shortest(a: Iter<i16>, b: Iter<i16>) -> bool
1644+
{
1645+
!is_fused(a.clone().interleave_shortest(b.clone())) &&
1646+
is_fused(a.fuse().interleave_shortest(b.fuse()))
1647+
}
1648+
1649+
fn fused_product(a: Iter<i16>, b: Iter<i16>) -> bool
1650+
{
1651+
is_fused(a.fuse().cartesian_product(b.fuse()))
1652+
}
1653+
1654+
fn fused_merge(a: Iter<i16>, b: Iter<i16>) -> bool
1655+
{
1656+
is_fused(a.fuse().merge(b.fuse()))
1657+
}
1658+
1659+
fn fused_filter_ok(a: Iter<i16>) -> bool
1660+
{
1661+
is_fused(a.map(|x| if x % 2 == 0 {Ok(x)} else {Err(x)} )
1662+
.filter_ok(|x| x % 3 == 0)
1663+
.fuse())
1664+
}
1665+
1666+
fn fused_filter_map_ok(a: Iter<i16>) -> bool
1667+
{
1668+
is_fused(a.map(|x| if x % 2 == 0 {Ok(x)} else {Err(x)} )
1669+
.filter_map_ok(|x| if x % 3 == 0 {Some(x / 3)} else {None})
1670+
.fuse())
1671+
}
1672+
1673+
fn fused_positions(a: Iter<i16>) -> bool
1674+
{
1675+
!is_fused(a.clone().positions(|x|x%2==0)) &&
1676+
is_fused(a.fuse().positions(|x|x%2==0))
1677+
}
1678+
1679+
fn fused_update(a: Iter<i16>) -> bool
1680+
{
1681+
!is_fused(a.clone().update(|x|*x+=1)) &&
1682+
is_fused(a.fuse().update(|x|*x+=1))
1683+
}
1684+
1685+
fn fused_tuple_windows(a: Iter<i16>) -> bool
1686+
{
1687+
is_fused(a.fuse().tuple_windows::<(_,_)>())
1688+
}
1689+
1690+
fn fused_pad_using(a: Iter<i16>) -> bool
1691+
{
1692+
is_fused(a.fuse().pad_using(100,|_|0))
1693+
}
1694+
}
1695+

0 commit comments

Comments
 (0)