diff --git a/src/tuple_impl.rs b/src/tuple_impl.rs index 0aea97716..ba1c69df6 100644 --- a/src/tuple_impl.rs +++ b/src/tuple_impl.rs @@ -3,7 +3,6 @@ use std::iter::Cycle; use std::iter::Fuse; use std::iter::FusedIterator; -use std::iter::Take; use std::marker::PhantomData; // `HomogeneousTuple` is a public facade for `TupleCollect`, allowing @@ -185,6 +184,20 @@ where } None } + + fn size_hint(&self) -> (usize, Option) { + // At definition, `T::num_items() - 1` are collected + // so each remaining item in `iter` will lead to an item. + self.iter.size_hint() + } +} + +impl ExactSizeIterator for TupleWindows +where + I: ExactSizeIterator, + T: HomogeneousTuple + Clone, + T::Item: Clone, +{ } impl FusedIterator for TupleWindows @@ -208,7 +221,8 @@ where I: Iterator + Clone, T: TupleCollect + Clone, { - iter: Take, T>>, + iter: TupleWindows, T>, + len: usize, phantom_data: PhantomData, } @@ -219,10 +233,11 @@ where T::Item: Clone, { let len = iter.len(); - let iter = tuple_windows(iter.cycle()).take(len); + let iter = tuple_windows(iter.cycle()); CircularTupleWindows { iter, + len, phantom_data: PhantomData {}, } } @@ -236,10 +251,35 @@ where type Item = T; fn next(&mut self) -> Option { - self.iter.next() + if self.len != 0 { + self.len -= 1; + self.iter.next() + } else { + None + } + } + + fn size_hint(&self) -> (usize, Option) { + (self.len, Some(self.len)) } } +impl ExactSizeIterator for CircularTupleWindows +where + I: Iterator + Clone, + T: TupleCollect + Clone, + T::Item: Clone, +{ +} + +impl FusedIterator for CircularTupleWindows +where + I: Iterator + Clone, + T: TupleCollect + Clone, + T::Item: Clone, +{ +} + pub trait TupleCollect: Sized { type Item; type Buffer: Default + AsRef<[Option]> + AsMut<[Option]>; diff --git a/tests/quick.rs b/tests/quick.rs index 1a19d60e8..3dc23d704 100644 --- a/tests/quick.rs +++ b/tests/quick.rs @@ -1117,6 +1117,10 @@ quickcheck! { true } + fn circular_tuple_windows_exact_size(a: Vec) -> bool { + exact_size(a.iter().circular_tuple_windows::<(_, _, _, _)>()) + } + fn equal_tuple_windows_1(a: Vec) -> bool { let x = a.windows(1).map(|s| (&s[0], )); let y = a.iter().tuple_windows::<(_,)>(); @@ -1141,6 +1145,14 @@ quickcheck! { itertools::equal(x, y) } + fn tuple_windows_exact_size_1(a: Vec) -> bool { + exact_size(a.iter().tuple_windows::<(_,)>()) + } + + fn tuple_windows_exact_size_4(a: Vec) -> bool { + exact_size(a.iter().tuple_windows::<(_, _, _, _)>()) + } + fn equal_tuples_1(a: Vec) -> bool { let x = a.chunks(1).map(|s| (&s[0], )); let y = a.iter().tuples::<(_,)>();