use std::{ error, fmt, }; #[derive(Debug)] pub struct PrefixedError where T: error::Error + 'static { prefix: String, internal: T, } impl std::error::Error for PrefixedError where T: error::Error + 'static { fn source(&self) -> Option<&(dyn error::Error + 'static)> { Some(&self.internal) } } impl std::fmt::Display for PrefixedError where T: error::Error + 'static { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}: {}", self.prefix, self.internal) } } impl PrefixedError where T: error::Error + 'static { #[inline] pub fn into_inner(self) -> T { self.internal } } pub trait ErrorExt: Sized + error::Error { fn with_prefix(self, msg: impl ToString) -> PrefixedError; } pub trait ResultExt: Sized where E: error::Error + 'static { fn with_prefix(self, msg: impl ToString) -> Result>; } impl ErrorExt for T where T: error::Error + 'static { #[inline] fn with_prefix(self, msg: impl ToString) -> PrefixedError { PrefixedError { prefix: msg.to_string(), internal: self } } } impl ResultExt for Result where E: error::Error + 'static { #[inline] fn with_prefix(self, msg: impl ToString) -> Result> { self.map_err(|e| e.with_prefix(msg)) } }