Skip to content

Commit 78908f2

Browse files
committed
Override StepBy::{try_fold, try_rfold}
1 parent d760df5 commit 78908f2

File tree

2 files changed

+78
-1
lines changed

2 files changed

+78
-1
lines changed

src/libcore/iter/adapters/mod.rs

+43-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::usize;
55
use crate::intrinsics;
66

77
use super::{Iterator, DoubleEndedIterator, ExactSizeIterator, FusedIterator, TrustedLen};
8-
use super::LoopState;
8+
use super::{LoopState, from_fn};
99

1010
mod chain;
1111
mod flatten;
@@ -541,6 +541,26 @@ impl<I> Iterator for StepBy<I> where I: Iterator {
541541
self.iter.nth(nth - 1);
542542
}
543543
}
544+
545+
fn try_fold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R
546+
where
547+
F: FnMut(Acc, Self::Item) -> R,
548+
R: Try<Ok = Acc>,
549+
{
550+
#[inline]
551+
fn nth<I: Iterator>(iter: &mut I, step: usize) -> impl FnMut() -> Option<I::Item> + '_ {
552+
move || iter.nth(step)
553+
}
554+
555+
if self.first_take {
556+
self.first_take = false;
557+
match self.iter.next() {
558+
None => return Try::from_ok(acc),
559+
Some(x) => acc = f(acc, x)?,
560+
}
561+
}
562+
from_fn(nth(&mut self.iter, self.step)).try_fold(acc, f)
563+
}
544564
}
545565

546566
impl<I> StepBy<I> where I: ExactSizeIterator {
@@ -574,6 +594,28 @@ impl<I> DoubleEndedIterator for StepBy<I> where I: DoubleEndedIterator + ExactSi
574594
.saturating_add(self.next_back_index());
575595
self.iter.nth_back(n)
576596
}
597+
598+
fn try_rfold<Acc, F, R>(&mut self, init: Acc, mut f: F) -> R
599+
where
600+
F: FnMut(Acc, Self::Item) -> R,
601+
R: Try<Ok = Acc>,
602+
{
603+
#[inline]
604+
fn nth_back<I: DoubleEndedIterator>(
605+
iter: &mut I,
606+
step: usize,
607+
) -> impl FnMut() -> Option<I::Item> + '_ {
608+
move || iter.nth_back(step)
609+
}
610+
611+
match self.next_back() {
612+
None => Try::from_ok(init),
613+
Some(x) => {
614+
let acc = f(init, x)?;
615+
from_fn(nth_back(&mut self.iter, self.step)).try_fold(acc, f)
616+
}
617+
}
618+
}
577619
}
578620

579621
// StepBy can only make the iterator shorter, so the len will still fit.

src/libcore/tests/iter.rs

+35
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,23 @@ fn test_iterator_step_by_nth_overflow() {
329329
assert_eq!(it.0, (usize::MAX as Bigger) * 1);
330330
}
331331

332+
#[test]
333+
fn test_iterator_step_by_nth_try_fold() {
334+
let mut it = (0..).step_by(10);
335+
assert_eq!(it.try_fold(0, i8::checked_add), None);
336+
assert_eq!(it.next(), Some(60));
337+
assert_eq!(it.try_fold(0, i8::checked_add), None);
338+
assert_eq!(it.next(), Some(90));
339+
340+
let mut it = (100..).step_by(10);
341+
assert_eq!(it.try_fold(50, i8::checked_add), None);
342+
assert_eq!(it.next(), Some(110));
343+
344+
let mut it = (100..=100).step_by(10);
345+
assert_eq!(it.next(), Some(100));
346+
assert_eq!(it.try_fold(0, i8::checked_add), Some(0));
347+
}
348+
332349
#[test]
333350
fn test_iterator_step_by_nth_back() {
334351
let mut it = (0..16).step_by(5);
@@ -354,6 +371,24 @@ fn test_iterator_step_by_nth_back() {
354371
assert_eq!(it().nth_back(42), None);
355372
}
356373

374+
#[test]
375+
fn test_iterator_step_by_nth_try_rfold() {
376+
let mut it = (0..100).step_by(10);
377+
assert_eq!(it.try_rfold(0, i8::checked_add), None);
378+
assert_eq!(it.next_back(), Some(70));
379+
assert_eq!(it.next(), Some(0));
380+
assert_eq!(it.try_rfold(0, i8::checked_add), None);
381+
assert_eq!(it.next_back(), Some(30));
382+
383+
let mut it = (0..100).step_by(10);
384+
assert_eq!(it.try_rfold(50, i8::checked_add), None);
385+
assert_eq!(it.next_back(), Some(80));
386+
387+
let mut it = (100..=100).step_by(10);
388+
assert_eq!(it.next_back(), Some(100));
389+
assert_eq!(it.try_fold(0, i8::checked_add), Some(0));
390+
}
391+
357392
#[test]
358393
#[should_panic]
359394
fn test_iterator_step_by_zero() {

0 commit comments

Comments
 (0)