about summary refs log tree commit diff
diff options
context:
space:
mode:
authorYuri Astrakhan <YuriAstrakhan@gmail.com>2023-05-09 18:31:56 -0400
committerYuri Astrakhan <YuriAstrakhan@gmail.com>2024-01-25 15:56:57 -0500
commitb8d245e7490be49fedf0609bd9763adc1116b725 (patch)
tree88e27dd280d4a5098de55e1e56853fadec67636c
parentf9259d1b73f01c4c690dfd7429bb3ce25a34874f (diff)
downloadrust-b8d245e7490be49fedf0609bd9763adc1116b725.tar.gz
rust-b8d245e7490be49fedf0609bd9763adc1116b725.zip
Postpone .next() call until iteration
-rw-r--r--library/core/src/iter/adapters/intersperse.rs78
1 files changed, 49 insertions, 29 deletions
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<I: Iterator>
 where
     I::Item: Clone,
 {
+    started: bool,
     separator: I::Item,
     next_item: Option<I::Item>,
     iter: Fuse<I>,
@@ -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<Self::Item> {
-        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<usize>) {
-        intersperse_size_hint(&self.iter, self.next_item.is_some())
+        intersperse_size_hint(&self.iter, self.started, self.next_item.is_some())
     }
 
     fn fold<B, F>(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<I, G>
 where
     I: Iterator,
 {
+    started: bool,
     separator: G,
     next_item: Option<I::Item>,
     iter: Fuse<I>,
@@ -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<Self::Item> {
-        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<usize>) {
-        intersperse_size_hint(&self.iter, self.next_item.is_some())
+        intersperse_size_hint(&self.iter, self.started, self.next_item.is_some())
     }
 
     fn fold<B, F>(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<I>(iter: &I, next_is_elem: bool) -> (usize, Option<usize>)
+fn intersperse_size_hint<I>(iter: &I, started: bool, next_is_some: bool) -> (usize, Option<usize>)
 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<I, B, F, G>(
-    iter: I,
+    mut iter: I,
     init: B,
     mut f: F,
     mut separator: G,
+    started: bool,
     mut next_item: Option<I::Item>,
 ) -> 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);
     }