diff --git a/library/core/src/iter/adapters/intersperse.rs b/library/core/src/iter/adapters/intersperse.rs index 654e3077771..2ff24cd7792 100644 --- a/library/core/src/iter/adapters/intersperse.rs +++ b/library/core/src/iter/adapters/intersperse.rs @@ -11,6 +11,7 @@ pub struct Intersperse where I::Item: Clone, { + started: bool, separator: I::Item, next_item: Option, iter: Fuse, @@ -29,8 +30,7 @@ where I::Item: Clone, { pub(in crate::iter) fn new(iter: I, separator: I::Item) -> Self { - let mut iter = iter.fuse(); - Self { separator, next_item: iter.next(), iter } + Self { started: false, separator, next_item: None, iter: iter.fuse() } } } @@ -44,21 +44,26 @@ where #[inline] fn next(&mut self) -> Option { - if let Some(v) = self.next_item.take() { - Some(v) - } else { - let next_item = self.iter.next(); - if next_item.is_some() { - self.next_item = next_item; - Some(self.separator.clone()) + if self.started { + if let Some(v) = self.next_item.take() { + Some(v) } else { - None + let next_item = self.iter.next(); + if next_item.is_some() { + self.next_item = next_item; + Some(self.separator.clone()) + } else { + None + } } + } else { + self.started = true; + self.iter.next() } } fn size_hint(&self) -> (usize, Option) { - intersperse_size_hint(&self.iter, self.next_item.is_some()) + intersperse_size_hint(&self.iter, self.started, self.next_item.is_some()) } fn fold(self, init: B, f: F) -> B @@ -67,7 +72,7 @@ where F: FnMut(B, Self::Item) -> B, { let separator = self.separator; - intersperse_fold(self.iter, init, f, move || separator.clone(), self.next_item) + intersperse_fold(self.iter, init, f, move || separator.clone(), self.started,self.next_item) } } @@ -80,6 +85,7 @@ pub struct IntersperseWith where I: Iterator, { + started: bool, separator: G, next_item: Option, iter: Fuse, @@ -102,6 +108,7 @@ where { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("IntersperseWith") + .field("started", &self.started) .field("separator", &self.separator) .field("iter", &self.iter) .field("next_item", &self.next_item) @@ -118,6 +125,7 @@ where { fn clone(&self) -> Self { Self { + started: self.started, separator: self.separator.clone(), iter: self.iter.clone(), next_item: self.next_item.clone(), @@ -131,8 +139,7 @@ where G: FnMut() -> I::Item, { pub(in crate::iter) fn new(iter: I, separator: G) -> Self { - let mut iter = iter.fuse(); - Self { separator, next_item: iter.next(), iter } + Self { started: false, separator, next_item: None, iter: iter.fuse() } } } @@ -146,21 +153,26 @@ where #[inline] fn next(&mut self) -> Option { - if let Some(v) = self.next_item.take() { - Some(v) - } else { - let next_item = self.iter.next(); - if next_item.is_some() { - self.next_item = next_item; - Some((self.separator)()) + if self.started { + if let Some(v) = self.next_item.take() { + Some(v) } else { - None + let next_item = self.iter.next(); + if next_item.is_some() { + self.next_item = next_item; + Some((self.separator)()) + } else { + None + } } + } else { + self.started = true; + self.iter.next() } } fn size_hint(&self) -> (usize, Option) { - intersperse_size_hint(&self.iter, self.next_item.is_some()) + intersperse_size_hint(&self.iter, self.started, self.next_item.is_some()) } fn fold(self, init: B, f: F) -> B @@ -168,26 +180,33 @@ where Self: Sized, F: FnMut(B, Self::Item) -> B, { - intersperse_fold(self.iter, init, f, self.separator, self.next_item) + intersperse_fold(self.iter, init, f, self.separator, self.started, self.next_item) } } -fn intersperse_size_hint(iter: &I, next_is_elem: bool) -> (usize, Option) +fn intersperse_size_hint(iter: &I, started: bool, next_is_some: bool) -> (usize, Option) where I: Iterator, { let (lo, hi) = iter.size_hint(); ( - lo.saturating_add(next_is_elem as usize).saturating_add(lo), - hi.map(|hi| hi.saturating_add(next_is_elem as usize).saturating_add(hi)), + lo.saturating_sub(!started as usize) + .saturating_add(next_is_some as usize) + .saturating_add(lo), + hi.map(|hi| { + hi.saturating_sub(!started as usize) + .saturating_add(next_is_some as usize) + .saturating_add(hi) + }), ) } fn intersperse_fold( - iter: I, + mut iter: I, init: B, mut f: F, mut separator: G, + started: bool, mut next_item: Option, ) -> B where @@ -197,7 +216,8 @@ where { let mut accum = init; - if let Some(x) = next_item.take() { + let first = if started { next_item.take() } else { iter.next() }; + if let Some(x) = first { accum = f(accum, x); }