cascade_error/
lib.rs

1use opt_struct::vec::OptVec;
2
3#[derive(Debug)]
4pub struct CascadeError<E: Cascadable> {
5    error: E,
6    code_trace: OptVec<CodeTrace>,
7}
8impl<E: Cascadable> CascadeError<E> {
9    pub fn inner(&self) -> &E {
10        &self.error
11    }
12    pub fn get_trace(&self) -> &OptVec<CodeTrace> {
13        &self.code_trace
14    }
15    pub fn into_inner(self) -> E {
16        self.error
17    }
18    pub fn map<F, Q: Cascadable>(self, func: F, trace: CodeTrace) -> CascadeError<Q>
19    where
20        F: Fn(E) -> Q,
21    {
22        let mut code_trace = self.code_trace;
23        code_trace.push(trace);
24        CascadeError {
25            error: func(self.error),
26            code_trace,
27        }
28    }
29    pub fn trace(&mut self, trace: CodeTrace) {
30        self.code_trace.push(trace);
31    }
32}
33
34pub trait Cascadable: Sized {
35    fn into_cascade(self, trace: CodeTrace) -> CascadeError<Self> {
36        CascadeError {
37            error: self,
38            code_trace: OptVec::from(trace),
39        }
40    }
41}
42
43#[macro_export]
44macro_rules! cascade_new {
45    ( ) => {
46        |e| e.into_cascade(code_trace!())
47    };
48    ( $err:expr ) => {{
49        let tmp = $err;
50        tmp.into_cascade(code_trace!())
51    }};
52}
53
54#[macro_export]
55macro_rules! cascade_trace {
56    ( ) => {
57        |mut e: CascadeError<_>| {
58            e.trace(code_trace!());
59            e
60        }
61    };
62}
63
64#[macro_export]
65macro_rules! cascade {
66    ( ) => {
67        |mut e: CascadeError<_>| {
68            e.trace(code_trace!());
69            e
70        }
71    };
72    ( $map:expr ) => {
73        |e: CascadeError<_>| e.map($map, code_trace!())
74    };
75}
76
77#[macro_export]
78macro_rules! code_trace {
79    () => {
80        CodeTrace::new(file!(), line!())
81    };
82}
83
84#[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd, Hash)]
85pub struct CodeTrace {
86    file: &'static str,
87    line: u32,
88}
89impl CodeTrace {
90    pub fn new(file: &'static str, line: u32) -> CodeTrace {
91        CodeTrace { file, line }
92    }
93}
94impl std::fmt::Debug for CodeTrace {
95    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
96        write!(f, "{}:{}", self.file, self.line)
97    }
98}
99impl std::fmt::Display for CodeTrace {
100    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
101        write!(f, "{}:{}", self.file, self.line)
102    }
103}