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
// ERRORS.rs
// by Lut99
//
// Created:
// 10 May 2023, 16:35:29
// Last edited:
// 10 May 2023, 16:45:29
// Auto updated?
// Yes
//
// Description:
//! Defines commonly used functions and structs relating to error
//! handling.
//
use std::error::Error;
use std::fmt::{Display, Formatter, Result as FResult};
/***** AUXILLARY *****/
/// Defines the formatter used in the [`ErrorTrace`] trait.
#[derive(Debug)]
pub struct ErrorTraceFormatter<'e> {
/// The error to format.
err: &'e dyn Error,
}
impl<'e> Display for ErrorTraceFormatter<'e> {
fn fmt(&self, f: &mut Formatter<'_>) -> FResult {
// We can always serialize the error itself
write!(f, "{}", self.err)?;
// If it has a source, recurse to print them all
if let Some(source) = self.err.source() {
write!(f, "\n\nCaused by:")?;
// Write them all
let mut i: usize = 1;
let mut source: Option<&dyn Error> = Some(source);
while let Some(err) = source {
write!(f, "\n {i}) {err}")?;
source = err.source();
i += 1;
}
}
// Done!
Ok(())
}
}
/***** LIBRARY *****/
/// Implements a function over a normal [`Error`] that prints it and any [`Error::source()`] it has.
pub trait ErrorTrace: Error {
/// Returns a formatter that writes the error to the given formatter, with any sources it has.
///
/// # Returns
/// A new [`ErrorTraceFormatter`] that can write this error and its sources.
fn trace(&self) -> ErrorTraceFormatter;
}
// We auto-implement [`ErrorTrace`] for everything [`Error`]
impl<T: Error> ErrorTrace for T {
#[inline]
fn trace(&self) -> ErrorTraceFormatter { ErrorTraceFormatter { err: self } }
}