mm1_common/errors/
chain.rs

1use std::error::Error as StdError;
2use std::fmt;
3
4use crate::types::AnyError;
5
6pub trait ExactTypeDisplayChainExt {
7    fn as_display_chain(&self) -> impl fmt::Display + fmt::Debug;
8}
9
10pub trait StdErrorDisplayChainExt: StdError + Sized {
11    fn as_display_chain(&self) -> impl fmt::Display + fmt::Debug {
12        let e: &dyn StdError = self;
13        D(e)
14    }
15}
16
17impl<E> StdErrorDisplayChainExt for E where E: StdError {}
18
19impl<T> ExactTypeDisplayChainExt for T
20where
21    for<'a> D<&'a T>: fmt::Display + fmt::Debug,
22{
23    fn as_display_chain(&self) -> impl fmt::Display + fmt::Debug {
24        D(self)
25    }
26}
27
28struct D<T>(T);
29
30impl fmt::Display for D<&dyn StdError> {
31    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32        let mut e = self.0;
33        write!(f, "{}", e)?;
34        while let Some(source) = e.source() {
35            write!(f, " << {}", source)?;
36            e = source;
37        }
38        Ok(())
39    }
40}
41impl fmt::Debug for D<&dyn StdError> {
42    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43        fmt::Display::fmt(self, f)
44    }
45}
46
47impl fmt::Display for D<&AnyError> {
48    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49        let mut chain = self.0.chain();
50        if let Some(e) = chain.next() {
51            write!(f, "{}", e)?;
52        }
53        for source in chain {
54            write!(f, "<< {}", source)?;
55        }
56
57        Ok(())
58    }
59}
60
61impl fmt::Debug for D<&AnyError> {
62    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63        fmt::Display::fmt(self, f)
64    }
65}