Skip to content

Commit b8d245e

Browse files
committed
Postpone .next() call until iteration
1 parent f9259d1 commit b8d245e

File tree

1 file changed

+49
-29
lines changed

1 file changed

+49
-29
lines changed

library/core/src/iter/adapters/intersperse.rs

+49-29
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ pub struct Intersperse<I: Iterator>
1111
where
1212
I::Item: Clone,
1313
{
14+
started: bool,
1415
separator: I::Item,
1516
next_item: Option<I::Item>,
1617
iter: Fuse<I>,
@@ -29,8 +30,7 @@ where
2930
I::Item: Clone,
3031
{
3132
pub(in crate::iter) fn new(iter: I, separator: I::Item) -> Self {
32-
let mut iter = iter.fuse();
33-
Self { separator, next_item: iter.next(), iter }
33+
Self { started: false, separator, next_item: None, iter: iter.fuse() }
3434
}
3535
}
3636

@@ -44,21 +44,26 @@ where
4444

4545
#[inline]
4646
fn next(&mut self) -> Option<Self::Item> {
47-
if let Some(v) = self.next_item.take() {
48-
Some(v)
49-
} else {
50-
let next_item = self.iter.next();
51-
if next_item.is_some() {
52-
self.next_item = next_item;
53-
Some(self.separator.clone())
47+
if self.started {
48+
if let Some(v) = self.next_item.take() {
49+
Some(v)
5450
} else {
55-
None
51+
let next_item = self.iter.next();
52+
if next_item.is_some() {
53+
self.next_item = next_item;
54+
Some(self.separator.clone())
55+
} else {
56+
None
57+
}
5658
}
59+
} else {
60+
self.started = true;
61+
self.iter.next()
5762
}
5863
}
5964

6065
fn size_hint(&self) -> (usize, Option<usize>) {
61-
intersperse_size_hint(&self.iter, self.next_item.is_some())
66+
intersperse_size_hint(&self.iter, self.started, self.next_item.is_some())
6267
}
6368

6469
fn fold<B, F>(self, init: B, f: F) -> B
@@ -67,7 +72,7 @@ where
6772
F: FnMut(B, Self::Item) -> B,
6873
{
6974
let separator = self.separator;
70-
intersperse_fold(self.iter, init, f, move || separator.clone(), self.next_item)
75+
intersperse_fold(self.iter, init, f, move || separator.clone(), self.started,self.next_item)
7176
}
7277
}
7378

@@ -80,6 +85,7 @@ pub struct IntersperseWith<I, G>
8085
where
8186
I: Iterator,
8287
{
88+
started: bool,
8389
separator: G,
8490
next_item: Option<I::Item>,
8591
iter: Fuse<I>,
@@ -102,6 +108,7 @@ where
102108
{
103109
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104110
f.debug_struct("IntersperseWith")
111+
.field("started", &self.started)
105112
.field("separator", &self.separator)
106113
.field("iter", &self.iter)
107114
.field("next_item", &self.next_item)
@@ -118,6 +125,7 @@ where
118125
{
119126
fn clone(&self) -> Self {
120127
Self {
128+
started: self.started,
121129
separator: self.separator.clone(),
122130
iter: self.iter.clone(),
123131
next_item: self.next_item.clone(),
@@ -131,8 +139,7 @@ where
131139
G: FnMut() -> I::Item,
132140
{
133141
pub(in crate::iter) fn new(iter: I, separator: G) -> Self {
134-
let mut iter = iter.fuse();
135-
Self { separator, next_item: iter.next(), iter }
142+
Self { started: false, separator, next_item: None, iter: iter.fuse() }
136143
}
137144
}
138145

@@ -146,48 +153,60 @@ where
146153

147154
#[inline]
148155
fn next(&mut self) -> Option<Self::Item> {
149-
if let Some(v) = self.next_item.take() {
150-
Some(v)
151-
} else {
152-
let next_item = self.iter.next();
153-
if next_item.is_some() {
154-
self.next_item = next_item;
155-
Some((self.separator)())
156+
if self.started {
157+
if let Some(v) = self.next_item.take() {
158+
Some(v)
156159
} else {
157-
None
160+
let next_item = self.iter.next();
161+
if next_item.is_some() {
162+
self.next_item = next_item;
163+
Some((self.separator)())
164+
} else {
165+
None
166+
}
158167
}
168+
} else {
169+
self.started = true;
170+
self.iter.next()
159171
}
160172
}
161173

162174
fn size_hint(&self) -> (usize, Option<usize>) {
163-
intersperse_size_hint(&self.iter, self.next_item.is_some())
175+
intersperse_size_hint(&self.iter, self.started, self.next_item.is_some())
164176
}
165177

166178
fn fold<B, F>(self, init: B, f: F) -> B
167179
where
168180
Self: Sized,
169181
F: FnMut(B, Self::Item) -> B,
170182
{
171-
intersperse_fold(self.iter, init, f, self.separator, self.next_item)
183+
intersperse_fold(self.iter, init, f, self.separator, self.started, self.next_item)
172184
}
173185
}
174186

175-
fn intersperse_size_hint<I>(iter: &I, next_is_elem: bool) -> (usize, Option<usize>)
187+
fn intersperse_size_hint<I>(iter: &I, started: bool, next_is_some: bool) -> (usize, Option<usize>)
176188
where
177189
I: Iterator,
178190
{
179191
let (lo, hi) = iter.size_hint();
180192
(
181-
lo.saturating_add(next_is_elem as usize).saturating_add(lo),
182-
hi.map(|hi| hi.saturating_add(next_is_elem as usize).saturating_add(hi)),
193+
lo.saturating_sub(!started as usize)
194+
.saturating_add(next_is_some as usize)
195+
.saturating_add(lo),
196+
hi.map(|hi| {
197+
hi.saturating_sub(!started as usize)
198+
.saturating_add(next_is_some as usize)
199+
.saturating_add(hi)
200+
}),
183201
)
184202
}
185203

186204
fn intersperse_fold<I, B, F, G>(
187-
iter: I,
205+
mut iter: I,
188206
init: B,
189207
mut f: F,
190208
mut separator: G,
209+
started: bool,
191210
mut next_item: Option<I::Item>,
192211
) -> B
193212
where
@@ -197,7 +216,8 @@ where
197216
{
198217
let mut accum = init;
199218

200-
if let Some(x) = next_item.take() {
219+
let first = if started { next_item.take() } else { iter.next() };
220+
if let Some(x) = first {
201221
accum = f(accum, x);
202222
}
203223

0 commit comments

Comments
 (0)