From 02274578c23fdac5ec1ca74e62cab506ed043650 Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Tue, 2 Apr 2024 21:19:09 -0400 Subject: [PATCH] Implement DoubleEndedIterator for ProcessResults --- src/process_results_impl.rs | 51 +++++++++++++++++++++++++++++++------ tests/specializations.rs | 15 ++++++++++- 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/src/process_results_impl.rs b/src/process_results_impl.rs index 7b40cc015..ad6c60d3c 100644 --- a/src/process_results_impl.rs +++ b/src/process_results_impl.rs @@ -13,14 +13,10 @@ pub struct ProcessResults<'a, I, E: 'a> { iter: I, } -impl<'a, I, T, E> Iterator for ProcessResults<'a, I, E> -where - I: Iterator>, -{ - type Item = T; - - fn next(&mut self) -> Option { - match self.iter.next() { +impl<'a, I, E> ProcessResults<'a, I, E> { + #[inline(always)] + fn next_body(&mut self, item: Option>) -> Option { + match item { Some(Ok(x)) => Some(x), Some(Err(e)) => { *self.error = Err(e); @@ -29,6 +25,18 @@ where None => None, } } +} + +impl<'a, I, T, E> Iterator for ProcessResults<'a, I, E> +where + I: Iterator>, +{ + type Item = T; + + fn next(&mut self) -> Option { + let item = self.iter.next(); + self.next_body(item) + } fn size_hint(&self) -> (usize, Option) { (0, self.iter.size_hint().1) @@ -52,6 +60,33 @@ where } } +impl<'a, I, T, E> DoubleEndedIterator for ProcessResults<'a, I, E> +where + I: Iterator>, + I: DoubleEndedIterator, +{ + fn next_back(&mut self) -> Option { + let item = self.iter.next_back(); + self.next_body(item) + } + + fn rfold(mut self, init: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + let error = self.error; + self.iter + .try_rfold(init, |acc, opt| match opt { + Ok(x) => Ok(f(acc, x)), + Err(e) => { + *error = Err(e); + Err(acc) + } + }) + .unwrap_or_else(|e| e) + } +} + /// “Lift” a function of the values of an iterator so that it can process /// an iterator of `Result` values instead. /// diff --git a/tests/specializations.rs b/tests/specializations.rs index fd8801e4e..949b2a7de 100644 --- a/tests/specializations.rs +++ b/tests/specializations.rs @@ -466,7 +466,7 @@ quickcheck! { helper(v.iter().copied()); helper(v.iter().copied().filter(Result::is_ok)); - fn helper(it: impl Iterator> + Clone) { + fn helper(it: impl Iterator> + DoubleEndedIterator + Clone) { macro_rules! check_results_specialized { ($src:expr, |$it:pat| $closure:expr) => { assert_eq!( @@ -482,6 +482,7 @@ quickcheck! { check_results_specialized!(it, |i| i.count()); check_results_specialized!(it, |i| i.last()); check_results_specialized!(it, |i| i.collect::>()); + check_results_specialized!(it, |i| i.rev().collect::>()); check_results_specialized!(it, |i| { let mut parameters_from_fold = vec![]; let fold_result = i.fold(vec![], |mut acc, v| { @@ -491,6 +492,15 @@ quickcheck! { }); (parameters_from_fold, fold_result) }); + check_results_specialized!(it, |i| { + let mut parameters_from_rfold = vec![]; + let rfold_result = i.rfold(vec![], |mut acc, v| { + parameters_from_rfold.push((acc.clone(), v)); + acc.push(v); + acc + }); + (parameters_from_rfold, rfold_result) + }); check_results_specialized!(it, |mut i| { let mut parameters_from_all = vec![]; let first = i.next(); @@ -504,6 +514,9 @@ quickcheck! { for n in 0..size + 2 { check_results_specialized!(it, |mut i| i.nth(n)); } + for n in 0..size + 2 { + check_results_specialized!(it, |mut i| i.nth_back(n)); + } } } }