agner_utils/
std_error_pp.rs

1use std::error::Error as StdError;
2use std::fmt;
3
4const DEFAULT_DEPTH_LIMIT: usize = 10;
5
6pub trait StdErrorPP: StdError + Sized {
7    fn pp<'a>(&'a self) -> ErrorPP<'a> {
8        let err: &'a dyn StdError = self;
9        ErrorPP { err, depth_limit: DEFAULT_DEPTH_LIMIT }
10    }
11}
12impl<E> StdErrorPP for E where E: StdError + Sized {}
13
14#[derive(Debug, Clone, Copy)]
15pub struct ErrorPP<'a> {
16    err: &'a dyn StdError,
17    depth_limit: usize,
18}
19
20impl ErrorPP<'_> {
21    pub fn depth_limit(self, depth_limit: usize) -> Self {
22        Self { depth_limit, ..self }
23    }
24}
25
26impl<'a> fmt::Display for ErrorPP<'a> {
27    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28        let mut depth_left = self.depth_limit;
29        let mut err = self.err;
30        write!(f, "{}", err)?;
31
32        while let Some(next) = err.source() {
33            if depth_left == 0 {
34                write!(f, " << ...")?;
35            } else {
36                depth_left -= 1;
37                err = next;
38                write!(f, " << {}", err)?;
39            }
40        }
41        Ok(())
42    }
43}