tailcall_valid/
cause.rs

1use std::{collections::VecDeque, fmt::Display};
2
3use derive_setters::Setters;
4use thiserror::Error;
5
6#[derive(Clone, PartialEq, Debug, Setters, Error)]
7pub struct Cause<E, T> {
8    pub error: E,
9    #[setters(skip)]
10    pub trace: VecDeque<T>,
11}
12
13impl<E: Display, T: Display> Display for Cause<E, T> {
14    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
15        write!(f, "[")?;
16        for (i, entry) in self.trace.iter().enumerate() {
17            if i > 0 {
18                write!(f, ", ")?;
19            }
20            write!(f, "{}", entry)?;
21        }
22        write!(f, "] {}", self.error)?;
23        Ok(())
24    }
25}
26
27impl<E, T> Cause<E, T> {
28    pub fn new(e: E) -> Self {
29        Cause {
30            error: e,
31            trace: Default::default(),
32        }
33    }
34
35    pub fn trace(mut self, t: T) -> Self {
36        self.trace.push_front(t);
37        self
38    }
39
40    pub fn transform<E1>(self, e: impl Fn(E) -> E1) -> Cause<E1, T> {
41        Cause {
42            error: e(self.error),
43            trace: self.trace,
44        }
45    }
46}
47
48#[cfg(test)]
49mod tests {
50    use pretty_assertions::assert_eq;
51
52    #[test]
53    fn test_display() {
54        use super::Cause;
55        let cause = Cause::new("error").trace("trace0").trace("trace1");
56        assert_eq!(cause.to_string(), "[trace1, trace0] error");
57    }
58}