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
use core::fmt::{Display, Formatter, Debug};
use super::source::ErrorSource;
use super::tracer::ErrorMessageTracer;

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>
  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()
  }
}