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}