use std::{error::Error, fmt::Display};
use vec1::Vec1;
#[derive(Debug)]
pub struct ErrorList<E: Error> {
errors: Vec1<E>,
}
impl<E: Error> ErrorList<E> {
pub fn into_errors(self) -> Vec1<E> {
self.errors
}
pub(crate) fn single(error: E) -> Self {
ErrorList {
errors: Vec1::new(error),
}
}
pub(crate) fn iter_to_result(iter: impl IntoIterator<Item = E>) -> Result<(), Self> {
let mut iter = iter.into_iter();
let Some(first_error) = iter.next() else {
return Ok(());
};
let mut errors = Vec1::new(first_error);
errors.extend(iter);
Err(Self { errors })
}
pub(crate) fn combine<T, U>(a: Result<T, Self>, b: Result<U, Self>) -> Result<(T, U), Self> {
match (a, b) {
(Ok(a), Ok(b)) => Ok((a, b)),
(Err(a), Ok(_)) => Err(a),
(Ok(_), Err(b)) => Err(b),
(Err(mut a), Err(b)) => {
a.extend(b);
Err(a)
}
}
}
pub(crate) fn combine_and_vec<T, U>(
a: Result<T, Self>,
b: Result<U, Self>,
errors: Vec<E>,
) -> Result<(T, U), Self> {
let (a, b) = match Self::combine(a, b) {
Ok(ok) => ok,
Err(mut err) => {
err.extend(errors);
return Err(err);
}
};
Self::iter_to_result(errors)?;
Ok((a, b))
}
pub(crate) fn errors_vec_to_result(errors: Vec<Self>) -> Result<(), Self> {
if errors.is_empty() {
return Ok(());
}
let mut errors_iter = errors.into_iter();
let Some(first_errors) = errors_iter.next() else {
return Ok(());
};
let mut result = first_errors;
for errors in errors_iter {
result.extend(errors);
}
Err(result)
}
pub(crate) fn vec_result<T>(vec: Vec<Result<T, E>>) -> Result<Vec<T>, Self> {
let mut ok_result = Vec::new();
let mut err_result = Vec::new();
for element in vec {
match element {
Ok(ok) => ok_result.push(ok),
Err(err) => err_result.push(err),
}
}
Self::iter_to_result(err_result).map(|_| ok_result)
}
pub(crate) fn flat_single_result<T>(vec: Vec<Result<T, E>>) -> Result<Vec<T>, Self> {
let vec = vec
.into_iter()
.map(|element| element.map_err(|err| Self::single(err)))
.collect();
Self::flat_result(vec)
}
pub(crate) fn flat_result<T>(vec: Vec<Result<T, Self>>) -> Result<Vec<T>, Self> {
let mut ok_result = Vec::new();
let mut err_result = Vec::new();
for element in vec {
match element {
Ok(ok) => ok_result.push(ok),
Err(err) => err_result.extend(err.into_iter()),
}
}
Self::iter_to_result(err_result).map(|_| ok_result)
}
pub(crate) fn convert_inner<F: Error>(self) -> ErrorList<F>
where
E: std::convert::Into<F>,
{
ErrorList::<F> {
errors: self.errors.mapped(Into::into),
}
}
}
impl<E: Error> From<E> for ErrorList<E> {
fn from(error: E) -> Self {
ErrorList::single(error)
}
}
impl<E: Error> IntoIterator for ErrorList<E> {
type Item = E;
type IntoIter = <Vec1<E> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.errors.into_iter()
}
}
impl<E: Error> Extend<E> for ErrorList<E> {
fn extend<T: IntoIterator<Item = E>>(&mut self, iter: T) {
self.errors.extend(iter);
}
}
impl<E: Error> Extend<ErrorList<E>> for ErrorList<E> {
fn extend<T: IntoIterator<Item = ErrorList<E>>>(&mut self, iter: T) {
for errors in iter {
self.errors.extend(errors);
}
}
}
impl<E: Error> Display for ErrorList<E> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for error in &self.errors {
writeln!(f, "{}", error)?;
}
Ok(())
}
}