diff --git a/src/size_hint.rs b/src/size_hint.rs index d592ca925..857e0c4c6 100644 --- a/src/size_hint.rs +++ b/src/size_hint.rs @@ -29,7 +29,6 @@ pub fn add_scalar(sh: SizeHint, x: usize) -> SizeHint { } /// Subtract `x` correctly from a `SizeHint`. -#[cfg(feature = "use_alloc")] #[inline] pub fn sub_scalar(sh: SizeHint, x: usize) -> SizeHint { let (mut low, mut hi) = sh; diff --git a/src/tuple_impl.rs b/src/tuple_impl.rs index c0b39d79d..688df448e 100644 --- a/src/tuple_impl.rs +++ b/src/tuple_impl.rs @@ -5,6 +5,8 @@ use std::iter::Fuse; use std::iter::FusedIterator; use std::marker::PhantomData; +use crate::size_hint; + // `HomogeneousTuple` is a public facade for `TupleCollect`, allowing // tuple-related methods to be used by clients in generic contexts, while // hiding the implementation details of `TupleCollect`. @@ -172,25 +174,13 @@ where } /// Create a new tuple windows iterator. -pub fn tuple_windows(mut iter: I) -> TupleWindows +pub fn tuple_windows(iter: I) -> TupleWindows where I: Iterator, T: HomogeneousTuple, T::Item: Clone, { - use std::iter::once; - - let mut last = None; - if T::num_items() != 1 { - // put in a duplicate item in front of the tuple; this simplifies - // .next() function. - if let Some(item) = iter.next() { - let iter = once(item.clone()).chain(once(item)).chain(&mut iter); - last = T::collect_from_iter_no_buf(iter); - } - } - - TupleWindows { iter, last } + TupleWindows { last: None, iter } } impl Iterator for TupleWindows @@ -205,19 +195,29 @@ where if T::num_items() == 1 { return T::collect_from_iter_no_buf(&mut self.iter); } - if let Some(ref mut last) = self.last { - if let Some(new) = self.iter.next() { + if let Some(new) = self.iter.next() { + if let Some(ref mut last) = self.last { last.left_shift_push(new); - return Some(last.clone()); + Some(last.clone()) + } else { + use std::iter::once; + let iter = once(new).chain(&mut self.iter); + self.last = T::collect_from_iter_no_buf(iter); + self.last.clone() } + } else { + None } - 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() + let mut sh = self.iter.size_hint(); + // Adjust the size hint at the beginning + // OR when `num_items == 1` (but it does not change the size hint). + if self.last.is_none() { + sh = size_hint::sub_scalar(sh, T::num_items() - 1); + } + sh } }