Skip to content

Commit 8ff8d05

Browse files
committed
Move shared logic of try_fold and advance_by into iter_try_fold
1 parent e141246 commit 8ff8d05

File tree

1 file changed

+66
-52
lines changed

1 file changed

+66
-52
lines changed

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

+66-52
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::fmt;
22
use crate::iter::{DoubleEndedIterator, Fuse, FusedIterator, Iterator, Map, TrustedLen};
3-
use crate::ops::Try;
3+
use crate::ops::{ControlFlow, Try};
44

55
/// An iterator that maps each element to an iterator, and yields the elements
66
/// of the produced iterators.
@@ -73,6 +73,11 @@ where
7373
{
7474
self.inner.fold(init, fold)
7575
}
76+
77+
#[inline]
78+
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
79+
self.inner.advance_by(n)
80+
}
7681
}
7782

7883
#[stable(feature = "rust1", since = "1.0.0")]
@@ -214,6 +219,11 @@ where
214219
{
215220
self.inner.fold(init, fold)
216221
}
222+
223+
#[inline]
224+
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
225+
self.inner.advance_by(n)
226+
}
217227
}
218228

219229
#[stable(feature = "iterator_flatten", since = "1.29.0")]
@@ -280,6 +290,46 @@ where
280290
}
281291
}
282292

293+
impl<I, U> FlattenCompat<I, U>
294+
where
295+
I: Iterator<Item: IntoIterator<IntoIter = U>>,
296+
{
297+
/// Folds over the inner iterators as long as the given function returns successfully,
298+
/// always storing the most recent inner iterator in `self.frontiter`.
299+
///
300+
/// Folds over the inner iterators, not over their elements. Is used by the `try_fold` and
301+
/// `advance_by` methods.
302+
#[inline]
303+
fn iter_try_fold<Acc, Fold, R>(&mut self, mut acc: Acc, mut fold: Fold) -> R
304+
where
305+
Fold: FnMut(Acc, &mut U) -> R,
306+
R: Try<Output = Acc>,
307+
{
308+
#[inline]
309+
fn flatten<'a, T: IntoIterator, Acc, R: Try<Output = Acc>>(
310+
frontiter: &'a mut Option<T::IntoIter>,
311+
fold: &'a mut impl FnMut(Acc, &mut T::IntoIter) -> R,
312+
) -> impl FnMut(Acc, T) -> R + 'a {
313+
move |acc, iter| fold(acc, frontiter.insert(iter.into_iter()))
314+
}
315+
316+
if let Some(iter) = &mut self.frontiter {
317+
acc = fold(acc, iter)?;
318+
}
319+
self.frontiter = None;
320+
321+
acc = self.iter.try_fold(acc, flatten(&mut self.frontiter, &mut fold))?;
322+
self.frontiter = None;
323+
324+
if let Some(iter) = &mut self.backiter {
325+
acc = fold(acc, iter)?;
326+
}
327+
self.backiter = None;
328+
329+
try { acc }
330+
}
331+
}
332+
283333
impl<I, U> Iterator for FlattenCompat<I, U>
284334
where
285335
I: Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
@@ -323,39 +373,20 @@ where
323373
}
324374

325375
#[inline]
326-
fn try_fold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R
376+
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
327377
where
328378
Self: Sized,
329379
Fold: FnMut(Acc, Self::Item) -> R,
330380
R: Try<Output = Acc>,
331381
{
332382
#[inline]
333-
fn flatten<'a, T: IntoIterator, Acc, R: Try<Output = Acc>>(
334-
frontiter: &'a mut Option<T::IntoIter>,
335-
fold: &'a mut impl FnMut(Acc, T::Item) -> R,
336-
) -> impl FnMut(Acc, T) -> R + 'a {
337-
move |acc, x| {
338-
let mut mid = x.into_iter();
339-
let r = mid.try_fold(acc, &mut *fold);
340-
*frontiter = Some(mid);
341-
r
342-
}
343-
}
344-
345-
if let Some(ref mut front) = self.frontiter {
346-
init = front.try_fold(init, &mut fold)?;
383+
fn flatten<U: Iterator, Acc, R: Try<Output = Acc>>(
384+
mut fold: impl FnMut(Acc, U::Item) -> R,
385+
) -> impl FnMut(Acc, &mut U) -> R {
386+
move |acc, iter| iter.try_fold(acc, &mut fold)
347387
}
348-
self.frontiter = None;
349-
350-
init = self.iter.try_fold(init, flatten(&mut self.frontiter, &mut fold))?;
351-
self.frontiter = None;
352388

353-
if let Some(ref mut back) = self.backiter {
354-
init = back.try_fold(init, &mut fold)?;
355-
}
356-
self.backiter = None;
357-
358-
try { init }
389+
self.iter_try_fold(init, flatten(fold))
359390
}
360391

361392
#[inline]
@@ -386,36 +417,19 @@ where
386417
#[inline]
387418
#[rustc_inherit_overflow_checks]
388419
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
389-
let mut rem = n;
390-
loop {
391-
if let Some(ref mut front) = self.frontiter {
392-
match front.advance_by(rem) {
393-
ret @ Ok(_) => return ret,
394-
Err(advanced) => rem -= advanced,
395-
}
396-
}
397-
self.frontiter = match self.iter.next() {
398-
Some(iterable) => Some(iterable.into_iter()),
399-
_ => break,
400-
}
401-
}
402-
403-
self.frontiter = None;
404-
405-
if let Some(ref mut back) = self.backiter {
406-
match back.advance_by(rem) {
407-
ret @ Ok(_) => return ret,
408-
Err(advanced) => rem -= advanced,
420+
#[inline]
421+
#[rustc_inherit_overflow_checks]
422+
fn advance<U: Iterator>(n: usize, iter: &mut U) -> ControlFlow<(), usize> {
423+
match iter.advance_by(n) {
424+
Ok(()) => ControlFlow::BREAK,
425+
Err(advanced) => ControlFlow::Continue(n - advanced),
409426
}
410427
}
411428

412-
if rem > 0 {
413-
return Err(n - rem);
429+
match self.iter_try_fold(n, advance) {
430+
ControlFlow::Continue(remaining) if remaining > 0 => Err(n - remaining),
431+
_ => Ok(()),
414432
}
415-
416-
self.backiter = None;
417-
418-
Ok(())
419433
}
420434
}
421435

0 commit comments

Comments
 (0)