use std::{iter::FusedIterator, ops::ControlFlow};
#[cfg(feature = "rand")]
pub mod sampling;
#[cfg(not(feature = "fuzzing"))]
#[doc(auto_cfg(hide(feature = "fuzzing")))]
mod stepped_windows;
#[cfg(not(feature = "fuzzing"))]
#[doc(auto_cfg(hide(feature = "fuzzing")))]
pub(crate) use stepped_windows::*;
#[cfg(feature = "fuzzing")]
mod stepped_windows;
#[cfg(feature = "fuzzing")]
pub use stepped_windows::*;
#[derive(Debug)]
pub struct ProcessResults<'a, I, E: 'a> {
error: &'a mut Result<(), E>,
iter: Option<I>,
}
impl<I, T, E> Iterator for ProcessResults<'_, I, E>
where
I: Iterator<Item = Result<T, E>>,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
match self.iter.as_mut()?.next() {
Some(Ok(val)) => Some(val),
Some(Err(e)) => {
self.iter = None;
*self.error = Err(e);
None
}
None => {
self.iter = None;
None
}
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
match &self.iter {
Some(iter) => (0, iter.size_hint().1),
None => (0, Some(0)),
}
}
fn fold<B, F>(mut self, init: B, mut f: F) -> B
where
Self: Sized,
F: FnMut(B, Self::Item) -> B, {
let Some(iter) = &mut self.iter else {
return init;
};
let res = iter.try_fold(init, |acc, res| match res {
Ok(val) => ControlFlow::Continue(f(acc, val)),
Err(e) => {
*self.error = Err(e);
ControlFlow::Break(acc)
}
});
match res {
ControlFlow::Continue(acc) => acc,
ControlFlow::Break(acc) => {
self.iter = None;
acc
}
}
}
fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
where
Self: Sized,
F: FnMut(B, Self::Item) -> R,
R: std::ops::Try<Output = B>, {
let Some(iter) = &mut self.iter else {
return R::from_output(init);
};
let res = iter.try_fold(init, |acc, res| match res {
Ok(val) => f(acc, val).branch().map_break(Err),
Err(e) => {
*self.error = Err(e);
ControlFlow::Break(Ok(acc))
}
});
match res {
ControlFlow::Continue(val) => R::from_output(val),
ControlFlow::Break(Ok(acc)) => {
self.iter = None;
R::from_output(acc)
}
ControlFlow::Break(Err(err)) => R::from_residual(err),
}
}
}
impl<I, T, E> DoubleEndedIterator for ProcessResults<'_, I, E>
where
I: DoubleEndedIterator<Item = Result<T, E>>,
{
fn next_back(&mut self) -> Option<Self::Item> {
match self.iter.as_mut()?.next_back() {
Some(Ok(val)) => Some(val),
Some(Err(e)) => {
self.iter = None;
*self.error = Err(e);
None
}
None => {
self.iter = None;
None
}
}
}
fn rfold<B, F>(mut self, init: B, mut f: F) -> B
where
F: FnMut(B, Self::Item) -> B, {
let Some(iter) = &mut self.iter else {
return init;
};
let res = iter.try_rfold(init, |acc, res| match res {
Ok(val) => ControlFlow::Continue(f(acc, val)),
Err(e) => {
*self.error = Err(e);
ControlFlow::Break(acc)
}
});
match res {
ControlFlow::Continue(acc) => acc,
ControlFlow::Break(acc) => {
self.iter = None;
acc
}
}
}
fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
where
Self: Sized,
F: FnMut(B, Self::Item) -> R,
R: std::ops::Try<Output = B>, {
let Some(iter) = &mut self.iter else {
return R::from_output(init);
};
let res = iter.try_rfold(init, |acc, res| match res {
Ok(val) => f(acc, val).branch().map_break(Err),
Err(e) => {
*self.error = Err(e);
ControlFlow::Break(Ok(acc))
}
});
match res {
ControlFlow::Continue(val) => R::from_output(val),
ControlFlow::Break(Ok(acc)) => {
self.iter = None;
R::from_output(acc)
}
ControlFlow::Break(Err(err)) => R::from_residual(err),
}
}
}
impl<T, I, E> FusedIterator for ProcessResults<'_, I, E> where I: Iterator<Item = Result<T, E>> {}
pub trait ProcessResultsExt<T, E>: Iterator<Item = Result<T, E>> + Sized {
fn process_results<F, R>(self, f: F) -> Result<R, E>
where
F: FnOnce(ProcessResults<Self, E>) -> R, {
let mut error = Ok(());
let result = f(ProcessResults {
error: &mut error,
iter: Some(self),
});
error.map(|()| result)
}
}
impl<T, E, I: Iterator<Item = Result<T, E>>> ProcessResultsExt<T, E> for I {}