1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
use alloc::boxed::Box;
use super::source::{ErrorSource, BoxDetail};
use super::tracer::ErrorMessageTracer;
use core::fmt::{Debug, Display, Formatter};
pub struct ErrorReport<Detail, Trace> {
pub detail: Detail,
pub trace: Trace,
}
impl<Detail, Trace> ErrorSource<Trace> for ErrorReport<Detail, Trace> {
type Source = Self;
type Detail = Detail;
fn error_details(source: Self::Source) -> (Self::Detail, Option<Trace>) {
(source.detail, Some(source.trace))
}
}
impl <Detail, Trace> ErrorSource<Trace>
for BoxDetail<Detail>
{
type Source = ErrorReport<Detail, Trace>;
type Detail = Box<Detail>;
fn error_details(source: Self::Source) -> (Self::Detail, Option<Trace>) {
(Box::new(source.detail), Some(source.trace))
}
}
impl<Detail, Trace> ErrorReport<Detail, Trace> {
pub fn trace_from<E, Cont>(source: E::Source, cont: Cont) -> Self
where
Detail: Display,
E: ErrorSource<Trace>,
Trace: ErrorMessageTracer,
Cont: FnOnce(E::Detail) -> Detail,
{
let (detail1, m_trace1) = E::error_details(source);
let detail2 = cont(detail1);
match m_trace1 {
Some(trace1) => {
let trace2 = trace1.add_message(&detail2);
ErrorReport {
detail: detail2,
trace: trace2,
}
}
None => {
let trace2 = Trace::new_message(&detail2);
ErrorReport {
detail: detail2,
trace: trace2,
}
}
}
}
}
impl<Detail, Trace> Debug for ErrorReport<Detail, Trace>
where
Trace: Debug,
{
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
self.trace.fmt(f)
}
}
impl<Detail, Trace> Display for ErrorReport<Detail, Trace>
where
Trace: Display,
{
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
self.trace.fmt(f)
}
}
#[cfg(feature = "std")]
impl<Detail, Trace> std::error::Error for ErrorReport<Detail, Trace>
where
Detail: Display,
Trace: Debug + Display,
Trace: ErrorMessageTracer,
{
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.trace.as_error()
}
}