use crate::{accumulator::Accumulator, IntoResultParts};
use std::iter::FusedIterator;
pub struct Accumulate<'a, I, E> {
iter: I,
acc: &'a mut Accumulator<E>,
}
impl<'a, I, E> Accumulate<'a, I, E> {
fn new(iter: I, acc: &'a mut Accumulator<E>) -> Self {
Accumulate { iter, acc }
}
}
impl<'a, I, E> Iterator for Accumulate<'a, I, E>
where
I: Iterator,
I::Item: IntoResultParts,
<I::Item as IntoResultParts>::Err: Into<E>,
{
type Item = <I::Item as IntoResultParts>::Ok;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter.find_map(|res| self.acc.handle(res))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a, I, E> ExactSizeIterator for Accumulate<'a, I, E>
where
Self: Iterator,
I: ExactSizeIterator,
{
#[inline]
fn len(&self) -> usize {
self.iter.len()
}
}
impl<'a, I, E> FusedIterator for Accumulate<'a, I, E>
where
Self: Iterator,
I: FusedIterator,
{
}
pub trait IteratorExt: Iterator {
#[inline]
fn accumulate<E>(self, acc: &mut Accumulator<E>) -> Accumulate<Self, E>
where
Self: Sized,
Self::Item: IntoResultParts,
<Self::Item as IntoResultParts>::Err: Into<E>,
{
Accumulate::new(self, acc)
}
#[inline]
fn collect_errors<E>(self, acc: &mut Accumulator<E>)
where
Self: Sized,
Self::Item: IntoResultParts,
<Self::Item as IntoResultParts>::Err: Into<E>,
{
self.for_each(|res| {
let (_, err) = res.into_result_parts();
acc.extend(err);
});
}
fn partition_results<C>(self) -> (C, Accumulator<<Self::Item as IntoResultParts>::Err>)
where
Self: Sized,
Self::Item: IntoResultParts,
C: FromIterator<<Self::Item as IntoResultParts>::Ok>,
{
let mut acc = Accumulator::new();
let c: C = self.accumulate(&mut acc).collect::<C>();
(c, acc)
}
}
impl<I> IteratorExt for I where I: Iterator {}