tailcall-valid 0.1.4

A Rust library for validating multiple inputs, collecting all possible errors instead of failing at the first error. Useful for scenarios where comprehensive feedback is required for user inputs or configuration settings.
Documentation
use std::{collections::VecDeque, fmt::Display};

use derive_setters::Setters;
use thiserror::Error;

#[derive(Clone, PartialEq, Debug, Setters, Error)]
pub struct Cause<E, T> {
    pub error: E,
    #[setters(skip)]
    pub trace: VecDeque<T>,
}

impl<E: Display, T: Display> Display for Cause<E, T> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "[")?;
        for (i, entry) in self.trace.iter().enumerate() {
            if i > 0 {
                write!(f, ", ")?;
            }
            write!(f, "{}", entry)?;
        }
        write!(f, "] {}", self.error)?;
        Ok(())
    }
}

impl<E, T> Cause<E, T> {
    pub fn new(e: E) -> Self {
        Cause {
            error: e,
            trace: Default::default(),
        }
    }

    pub fn trace(mut self, t: T) -> Self {
        self.trace.push_front(t);
        self
    }

    pub fn transform<E1>(self, e: impl Fn(E) -> E1) -> Cause<E1, T> {
        Cause {
            error: e(self.error),
            trace: self.trace,
        }
    }
}

#[cfg(test)]
mod tests {
    use pretty_assertions::assert_eq;

    #[test]
    fn test_display() {
        use super::Cause;
        let cause = Cause::new("error").trace("trace0").trace("trace1");
        assert_eq!(cause.to_string(), "[trace1, trace0] error");
    }
}