use std::{ error::Error, fmt::{Debug, Display, Formatter}, ops::Deref, }; use errify::WrapErr; #[derive(Debug)] pub struct ContextExpr(i32); impl ContextExpr { pub fn new(i: i32) -> Self { Self(i) } } impl Display for ContextExpr { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.write_fmt(format_args!("ContextExpr({})", self.0)) } } impl Error for ContextExpr {} #[derive(Debug)] pub struct StringError(pub String); impl Display for StringError { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0) } } impl Error for StringError {} impl Deref for StringError { type Target = String; fn deref(&self) -> &Self::Target { &self.0 } } impl From for StringError { fn from(value: String) -> Self { Self(value) } } #[derive(Debug)] pub struct ErrorWithContext { pub msg: StringError, pub cx: Option, } impl ErrorWithContext { pub fn new(msg: impl Display) -> Self { Self { msg: format!("{msg}").into(), cx: None, } } } impl Display for ErrorWithContext { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match &self.cx { None => write!(f, "{}", self.msg), Some(cx) => write!(f, "{cx}"), } } } impl Error for ErrorWithContext { fn source(&self) -> Option<&(dyn Error + 'static)> { Some(&self.msg) } } impl WrapErr for ErrorWithContext { fn wrap_err(self, context: C) -> Self where C: Display + Send + Sync + 'static, { Self { msg: self.msg, cx: Some(context.to_string()), } } }