Skip to content

Commit

Permalink
Implement DoubleEndedIterator for ProcessResults
Browse files Browse the repository at this point in the history
  • Loading branch information
shepmaster authored and Philippe-Cholet committed Apr 9, 2024
1 parent 1ef5453 commit 1c5d5cd
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 9 deletions.
51 changes: 43 additions & 8 deletions src/process_results_impl.rs
Expand Up @@ -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<Item = Result<T, E>>,
{
type Item = T;

fn next(&mut self) -> Option<Self::Item> {
match self.iter.next() {
impl<'a, I, E> ProcessResults<'a, I, E> {
#[inline(always)]
fn next_body<T>(&mut self, item: Option<Result<T, E>>) -> Option<T> {
match item {
Some(Ok(x)) => Some(x),
Some(Err(e)) => {
*self.error = Err(e);
Expand All @@ -29,6 +25,18 @@ where
None => None,
}
}
}

impl<'a, I, T, E> Iterator for ProcessResults<'a, I, E>
where
I: Iterator<Item = Result<T, E>>,
{
type Item = T;

fn next(&mut self) -> Option<Self::Item> {
let item = self.iter.next();
self.next_body(item)
}

fn size_hint(&self) -> (usize, Option<usize>) {
(0, self.iter.size_hint().1)
Expand All @@ -52,6 +60,33 @@ where
}
}

impl<'a, I, T, E> DoubleEndedIterator for ProcessResults<'a, I, E>
where
I: Iterator<Item = Result<T, E>>,
I: DoubleEndedIterator,
{
fn next_back(&mut self) -> Option<Self::Item> {
let item = self.iter.next_back();
self.next_body(item)
}

fn rfold<B, F>(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.
///
Expand Down
15 changes: 14 additions & 1 deletion tests/specializations.rs
Expand Up @@ -466,7 +466,7 @@ quickcheck! {
helper(v.iter().copied());
helper(v.iter().copied().filter(Result::is_ok));

fn helper(it: impl Iterator<Item = Result<u8, u8>> + Clone) {
fn helper(it: impl Iterator<Item = Result<u8, u8>> + DoubleEndedIterator + Clone) {
macro_rules! check_results_specialized {
($src:expr, |$it:pat| $closure:expr) => {
assert_eq!(
Expand All @@ -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::<Vec<_>>());
check_results_specialized!(it, |i| i.rev().collect::<Vec<_>>());
check_results_specialized!(it, |i| {
let mut parameters_from_fold = vec![];
let fold_result = i.fold(vec![], |mut acc, v| {
Expand All @@ -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();
Expand All @@ -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));
}
}
}
}

0 comments on commit 1c5d5cd

Please sign in to comment.