From 9b01a118919f0d1f7c3327d1a15a5eb660f3912e Mon Sep 17 00:00:00 2001 From: Philippe-Cholet Date: Tue, 7 Nov 2023 15:44:00 +0100 Subject: [PATCH] Make `IntersperseWith` lazy Similar to what is done by `core::iter::Peekable`, a nested option is now used. --- src/intersperse.rs | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/src/intersperse.rs b/src/intersperse.rs index 1b44ed484..9f68a12bf 100644 --- a/src/intersperse.rs +++ b/src/intersperse.rs @@ -54,7 +54,7 @@ where { element: ElemF, iter: Fuse, - peek: Option, + peek: Option>, } /// Create a new `IntersperseWith` iterator @@ -62,10 +62,9 @@ pub fn intersperse_with(iter: I, elt: ElemF) -> IntersperseWith item.take(), - None => match iter.next() { + Some(item @ Some(_)) => item.take(), + Some(None) => match iter.next() { new @ Some(_) => { - *peek = new; + *peek = Some(new); Some(element.generate()) } None => None, }, + None => { + *peek = Some(None); + iter.next() + } } } fn size_hint(&self) -> (usize, Option) { - // 2 * SH + { 1 or 0 } - let has_peek = self.peek.is_some() as usize; - let sh = self.iter.size_hint(); - size_hint::add_scalar(size_hint::add(sh, sh), has_peek) + let mut sh = self.iter.size_hint(); + sh = size_hint::add(sh, sh); + match self.peek { + Some(Some(_)) => size_hint::add_scalar(sh, 1), + Some(None) => sh, + None => size_hint::sub_scalar(sh, 1), + } } - fn fold(mut self, init: B, mut f: F) -> B + fn fold(self, init: B, mut f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, { + let Self { + mut element, + mut iter, + peek, + } = self; let mut accum = init; - if let Some(x) = self.peek.take() { + if let Some(x) = peek.unwrap_or_else(|| iter.next()) { accum = f(accum, x); } - let element = &mut self.element; - - self.iter.fold(accum, |accum, x| { + iter.fold(accum, |accum, x| { let accum = f(accum, element.generate()); f(accum, x) })