miette/
diagnostic_chain.rs1use crate::protocol::Diagnostic;
6
7#[derive(Clone, Default)]
9#[allow(missing_debug_implementations)]
10pub(crate) struct DiagnosticChain<'a> {
11 state: Option<ErrorKind<'a>>,
12}
13
14impl<'a> DiagnosticChain<'a> {
15 pub(crate) fn from_diagnostic(head: &'a dyn Diagnostic) -> Self {
16 DiagnosticChain {
17 state: Some(ErrorKind::Diagnostic(head)),
18 }
19 }
20
21 pub(crate) fn from_stderror(head: &'a (dyn std::error::Error + 'static)) -> Self {
22 DiagnosticChain {
23 state: Some(ErrorKind::StdError(head)),
24 }
25 }
26}
27
28impl<'a> Iterator for DiagnosticChain<'a> {
29 type Item = ErrorKind<'a>;
30
31 fn next(&mut self) -> Option<Self::Item> {
32 if let Some(err) = self.state.take() {
33 self.state = err.get_nested();
34 Some(err)
35 } else {
36 None
37 }
38 }
39
40 fn size_hint(&self) -> (usize, Option<usize>) {
41 let len = self.len();
42 (len, Some(len))
43 }
44}
45
46impl ExactSizeIterator for DiagnosticChain<'_> {
47 fn len(&self) -> usize {
48 fn depth(d: Option<&ErrorKind<'_>>) -> usize {
49 match d {
50 Some(d) => 1 + depth(d.get_nested().as_ref()),
51 None => 0,
52 }
53 }
54
55 depth(self.state.as_ref())
56 }
57}
58
59#[derive(Clone)]
60pub(crate) enum ErrorKind<'a> {
61 Diagnostic(&'a dyn Diagnostic),
62 StdError(&'a (dyn std::error::Error + 'static)),
63}
64
65impl<'a> ErrorKind<'a> {
66 fn get_nested(&self) -> Option<ErrorKind<'a>> {
67 match self {
68 ErrorKind::Diagnostic(d) => d
69 .diagnostic_source()
70 .map(ErrorKind::Diagnostic)
71 .or_else(|| d.source().map(ErrorKind::StdError)),
72 ErrorKind::StdError(e) => e.source().map(ErrorKind::StdError),
73 }
74 }
75}
76
77impl<'a> std::fmt::Debug for ErrorKind<'a> {
78 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79 match self {
80 ErrorKind::Diagnostic(d) => d.fmt(f),
81 ErrorKind::StdError(e) => e.fmt(f),
82 }
83 }
84}
85
86impl<'a> std::fmt::Display for ErrorKind<'a> {
87 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
88 match self {
89 ErrorKind::Diagnostic(d) => d.fmt(f),
90 ErrorKind::StdError(e) => e.fmt(f),
91 }
92 }
93}