Skip to main content

fedimint_util_error/
lib.rs

1use std::fmt::Formatter;
2use std::{error, fmt};
3
4/// A wrapper with `fmt::Display` for any `E : Error`, unsized ones such as
5/// `dyn Error` included, that prints the error and its chain of causes,
6/// joined with `": "`.
7pub struct FmtErrorCompact<'e, E>(pub &'e E)
8where
9    E: ?Sized;
10
11impl<E> fmt::Display for FmtErrorCompact<'_, E>
12where
13    E: error::Error + ?Sized,
14{
15    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
16        write!(f, "{}", self.0)?;
17
18        let mut source = self.0.source();
19        while let Some(error) = source {
20            write!(f, ": {error}")?;
21            source = error.source();
22        }
23        Ok(())
24    }
25}
26
27/// Simple utility trait to print error chains
28///
29/// Implemented for a reference to any error, `dyn Error` included, so method
30/// calls also reach the error behind a `Box<dyn Error>` or any other pointer
31/// that derefs to one.
32pub trait FmtCompact<'a> {
33    type Report: fmt::Display + 'a;
34    fn fmt_compact(self) -> Self::Report;
35}
36
37impl<'e, E> FmtCompact<'e> for &'e E
38where
39    E: error::Error + ?Sized,
40{
41    type Report = FmtErrorCompact<'e, E>;
42
43    fn fmt_compact(self) -> Self::Report {
44        FmtErrorCompact(self)
45    }
46}
47
48/// A wrapper with `fmt::Display` for `Result<T, E>` where `E: Error` that
49/// prints the error chain on `Err` or `-` on `Ok`
50pub struct FmtCompactResultDisplay<'a, T, E>(pub &'a Result<T, E>);
51
52impl<T, E: error::Error> fmt::Display for FmtCompactResultDisplay<'_, T, E> {
53    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
54        match self.0 {
55            Ok(_) => f.write_str("-"),
56            Err(e) => FmtErrorCompact(e).fmt(f),
57        }
58    }
59}
60
61/// Extension trait to format `Result<T, E>` compactly (for `E: Error`)
62pub trait FmtCompactResult<'a> {
63    type Report: fmt::Display + 'a;
64    fn fmt_compact_result(&'a self) -> Self::Report;
65}
66
67impl<'a, T, E> FmtCompactResult<'a> for Result<T, E>
68where
69    E: error::Error + 'a,
70    T: 'a,
71{
72    type Report = FmtCompactResultDisplay<'a, T, E>;
73
74    fn fmt_compact_result(&'a self) -> Self::Report {
75        FmtCompactResultDisplay(self)
76    }
77}
78
79#[cfg(test)]
80mod test;