Skip to content

Commit cbc5f62

Browse files
committed
Move shared logic of try_rfold and advance_back_by into iter_try_rfold
1 parent 8ff8d05 commit cbc5f62

File tree

1 file changed

+65
-54
lines changed

1 file changed

+65
-54
lines changed

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

+65-54
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,11 @@ where
108108
{
109109
self.inner.rfold(init, fold)
110110
}
111+
112+
#[inline]
113+
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
114+
self.inner.advance_back_by(n)
115+
}
111116
}
112117

113118
#[stable(feature = "fused", since = "1.26.0")]
@@ -254,6 +259,11 @@ where
254259
{
255260
self.inner.rfold(init, fold)
256261
}
262+
263+
#[inline]
264+
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
265+
self.inner.advance_back_by(n)
266+
}
257267
}
258268

259269
#[stable(feature = "iterator_flatten", since = "1.29.0")]
@@ -330,6 +340,46 @@ where
330340
}
331341
}
332342

343+
impl<I, U> FlattenCompat<I, U>
344+
where
345+
I: DoubleEndedIterator<Item: IntoIterator<IntoIter = U>>,
346+
{
347+
/// Folds over the inner iterators in reverse order as long as the given function returns
348+
/// successfully, always storing the most recent inner iterator in `self.backiter`.
349+
///
350+
/// Folds over the inner iterators, not over their elements. Is used by the `try_rfold` and
351+
/// `advance_back_by` methods.
352+
#[inline]
353+
fn iter_try_rfold<Acc, Fold, R>(&mut self, mut acc: Acc, mut fold: Fold) -> R
354+
where
355+
Fold: FnMut(Acc, &mut U) -> R,
356+
R: Try<Output = Acc>,
357+
{
358+
#[inline]
359+
fn flatten<'a, T: IntoIterator, Acc, R: Try>(
360+
backiter: &'a mut Option<T::IntoIter>,
361+
fold: &'a mut impl FnMut(Acc, &mut T::IntoIter) -> R,
362+
) -> impl FnMut(Acc, T) -> R + 'a {
363+
move |acc, iter| fold(acc, backiter.insert(iter.into_iter()))
364+
}
365+
366+
if let Some(iter) = &mut self.backiter {
367+
acc = fold(acc, iter)?;
368+
}
369+
self.backiter = None;
370+
371+
acc = self.iter.try_rfold(acc, flatten(&mut self.backiter, &mut fold))?;
372+
self.backiter = None;
373+
374+
if let Some(iter) = &mut self.frontiter {
375+
acc = fold(acc, iter)?;
376+
}
377+
self.frontiter = None;
378+
379+
try { acc }
380+
}
381+
}
382+
333383
impl<I, U> Iterator for FlattenCompat<I, U>
334384
where
335385
I: Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
@@ -452,42 +502,20 @@ where
452502
}
453503

454504
#[inline]
455-
fn try_rfold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R
505+
fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
456506
where
457507
Self: Sized,
458508
Fold: FnMut(Acc, Self::Item) -> R,
459509
R: Try<Output = Acc>,
460510
{
461511
#[inline]
462-
fn flatten<'a, T: IntoIterator, Acc, R: Try<Output = Acc>>(
463-
backiter: &'a mut Option<T::IntoIter>,
464-
fold: &'a mut impl FnMut(Acc, T::Item) -> R,
465-
) -> impl FnMut(Acc, T) -> R + 'a
466-
where
467-
T::IntoIter: DoubleEndedIterator,
468-
{
469-
move |acc, x| {
470-
let mut mid = x.into_iter();
471-
let r = mid.try_rfold(acc, &mut *fold);
472-
*backiter = Some(mid);
473-
r
474-
}
475-
}
476-
477-
if let Some(ref mut back) = self.backiter {
478-
init = back.try_rfold(init, &mut fold)?;
479-
}
480-
self.backiter = None;
481-
482-
init = self.iter.try_rfold(init, flatten(&mut self.backiter, &mut fold))?;
483-
self.backiter = None;
484-
485-
if let Some(ref mut front) = self.frontiter {
486-
init = front.try_rfold(init, &mut fold)?;
512+
fn flatten<U: DoubleEndedIterator, Acc, R: Try<Output = Acc>>(
513+
mut fold: impl FnMut(Acc, U::Item) -> R,
514+
) -> impl FnMut(Acc, &mut U) -> R {
515+
move |acc, iter| iter.try_rfold(acc, &mut fold)
487516
}
488-
self.frontiter = None;
489517

490-
try { init }
518+
self.iter_try_rfold(init, flatten(fold))
491519
}
492520

493521
#[inline]
@@ -521,36 +549,19 @@ where
521549
#[inline]
522550
#[rustc_inherit_overflow_checks]
523551
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
524-
let mut rem = n;
525-
loop {
526-
if let Some(ref mut back) = self.backiter {
527-
match back.advance_back_by(rem) {
528-
ret @ Ok(_) => return ret,
529-
Err(advanced) => rem -= advanced,
530-
}
531-
}
532-
match self.iter.next_back() {
533-
Some(iterable) => self.backiter = Some(iterable.into_iter()),
534-
_ => break,
535-
}
536-
}
537-
538-
self.backiter = None;
539-
540-
if let Some(ref mut front) = self.frontiter {
541-
match front.advance_back_by(rem) {
542-
ret @ Ok(_) => return ret,
543-
Err(advanced) => rem -= advanced,
552+
#[inline]
553+
#[rustc_inherit_overflow_checks]
554+
fn advance<U: DoubleEndedIterator>(n: usize, iter: &mut U) -> ControlFlow<(), usize> {
555+
match iter.advance_back_by(n) {
556+
Ok(()) => ControlFlow::BREAK,
557+
Err(advanced) => ControlFlow::Continue(n - advanced),
544558
}
545559
}
546560

547-
if rem > 0 {
548-
return Err(n - rem);
561+
match self.iter_try_rfold(n, advance) {
562+
ControlFlow::Continue(remaining) if remaining > 0 => Err(n - remaining),
563+
_ => Ok(()),
549564
}
550-
551-
self.frontiter = None;
552-
553-
Ok(())
554565
}
555566
}
556567

0 commit comments

Comments
 (0)