use ControlFlow::*;
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum ControlFlow {
Break,
Continue,
}
pub trait ErrorCollector<E> {
type Collection;
fn empty() -> Self;
fn push_err(&mut self, err: E) -> ControlFlow;
fn with_value<T>(self, val: T) -> Result<T, Self::Collection>;
}
#[derive(Debug, Copy, Clone)]
pub struct Ignore;
impl<E> ErrorCollector<E> for Ignore {
type Collection = Infallible;
#[inline]
fn empty() -> Self {
Self
}
#[inline]
fn push_err(&mut self, _err: E) -> ControlFlow {
Continue
}
#[inline]
fn with_value<T>(self, val: T) -> Result<T, Self::Collection> {
Ok(val)
}
}
impl<E, F: From<E>> ErrorCollector<E> for Option<F> {
type Collection = F;
#[inline]
fn empty() -> Self {
None
}
#[inline]
fn push_err(&mut self, err: E) -> ControlFlow {
*self = Some(err.into());
Break
}
#[inline]
fn with_value<T>(self, val: T) -> Result<T, Self::Collection> {
if let Some(err) = self {
Err(err)
} else {
Ok(val)
}
}
}
impl<E, F: From<E>> ErrorCollector<E> for Vec<F> {
type Collection = Self;
#[inline]
fn empty() -> Self {
Self::new()
}
#[inline]
fn push_err(&mut self, err: E) -> ControlFlow {
self.push(err.into());
Continue
}
#[inline]
fn with_value<T>(self, val: T) -> Result<T, Self::Collection> {
if self.is_empty() {
Ok(val)
} else {
Err(self)
}
}
}
#[cfg(feature = "arrayvec")]
use arrayvec::ArrayVec;
use std::convert::Infallible;
#[cfg(feature = "arrayvec")]
impl<E, F: From<E>, const CAP: usize> ErrorCollector<E> for ArrayVec<F, CAP> {
type Collection = Self;
#[inline]
fn empty() -> Self {
Self::new()
}
#[inline]
fn push_err(&mut self, err: E) -> ControlFlow {
match self.try_push(err.into()) {
Ok(_) => Continue,
Err(_) => Break,
}
}
#[inline]
fn with_value<T>(self, val: T) -> Result<T, Self::Collection> {
if self.is_empty() {
Ok(val)
} else {
Err(self)
}
}
}