diff options
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/iter/adapters/mod.rs | 44 | ||||
| -rw-r--r-- | src/libcore/tests/iter.rs | 35 |
2 files changed, 78 insertions, 1 deletions
diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index 8e1ac6082c8..3b8edc2ad61 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -5,7 +5,7 @@ use crate::usize; use crate::intrinsics; use super::{Iterator, DoubleEndedIterator, ExactSizeIterator, FusedIterator, TrustedLen}; -use super::LoopState; +use super::{LoopState, from_fn}; mod chain; mod flatten; @@ -534,6 +534,26 @@ impl<I> Iterator for StepBy<I> where I: Iterator { self.iter.nth(nth - 1); } } + + fn try_fold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R + where + F: FnMut(Acc, Self::Item) -> R, + R: Try<Ok = Acc>, + { + #[inline] + fn nth<I: Iterator>(iter: &mut I, step: usize) -> impl FnMut() -> Option<I::Item> + '_ { + move || iter.nth(step) + } + + if self.first_take { + self.first_take = false; + match self.iter.next() { + None => return Try::from_ok(acc), + Some(x) => acc = f(acc, x)?, + } + } + from_fn(nth(&mut self.iter, self.step)).try_fold(acc, f) + } } impl<I> StepBy<I> where I: ExactSizeIterator { @@ -567,6 +587,28 @@ impl<I> DoubleEndedIterator for StepBy<I> where I: DoubleEndedIterator + ExactSi .saturating_add(self.next_back_index()); self.iter.nth_back(n) } + + fn try_rfold<Acc, F, R>(&mut self, init: Acc, mut f: F) -> R + where + F: FnMut(Acc, Self::Item) -> R, + R: Try<Ok = Acc>, + { + #[inline] + fn nth_back<I: DoubleEndedIterator>( + iter: &mut I, + step: usize, + ) -> impl FnMut() -> Option<I::Item> + '_ { + move || iter.nth_back(step) + } + + match self.next_back() { + None => Try::from_ok(init), + Some(x) => { + let acc = f(init, x)?; + from_fn(nth_back(&mut self.iter, self.step)).try_fold(acc, f) + } + } + } } // StepBy can only make the iterator shorter, so the len will still fit. diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index d7088cf891f..c9096b713f2 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -386,6 +386,23 @@ fn test_iterator_step_by_nth_overflow() { } #[test] +fn test_iterator_step_by_nth_try_fold() { + let mut it = (0..).step_by(10); + assert_eq!(it.try_fold(0, i8::checked_add), None); + assert_eq!(it.next(), Some(60)); + assert_eq!(it.try_fold(0, i8::checked_add), None); + assert_eq!(it.next(), Some(90)); + + let mut it = (100..).step_by(10); + assert_eq!(it.try_fold(50, i8::checked_add), None); + assert_eq!(it.next(), Some(110)); + + let mut it = (100..=100).step_by(10); + assert_eq!(it.next(), Some(100)); + assert_eq!(it.try_fold(0, i8::checked_add), Some(0)); +} + +#[test] fn test_iterator_step_by_nth_back() { let mut it = (0..16).step_by(5); assert_eq!(it.nth_back(0), Some(15)); @@ -411,6 +428,24 @@ fn test_iterator_step_by_nth_back() { } #[test] +fn test_iterator_step_by_nth_try_rfold() { + let mut it = (0..100).step_by(10); + assert_eq!(it.try_rfold(0, i8::checked_add), None); + assert_eq!(it.next_back(), Some(70)); + assert_eq!(it.next(), Some(0)); + assert_eq!(it.try_rfold(0, i8::checked_add), None); + assert_eq!(it.next_back(), Some(30)); + + let mut it = (0..100).step_by(10); + assert_eq!(it.try_rfold(50, i8::checked_add), None); + assert_eq!(it.next_back(), Some(80)); + + let mut it = (100..=100).step_by(10); + assert_eq!(it.next_back(), Some(100)); + assert_eq!(it.try_fold(0, i8::checked_add), Some(0)); +} + +#[test] #[should_panic] fn test_iterator_step_by_zero() { let mut it = (0..).step_by(0); |
