use std::fmt;
pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
#[derive(Debug)]
pub struct Error {
msg: String,
cause: Option<Box<dyn std::error::Error>>
}
impl Error {
pub fn new(msg: &str) -> Error {
Error {
msg: msg.into(),
cause: None
}
}
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.cause.as_ref().map(Box::as_ref)
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(&self.msg)?;
if let Some(cause) = &self.cause {
write!(f, "\n\tcaused by: {}", cause)?;
}
Ok(())
}
}
pub trait ErrorExt {
fn wrap(self, msg: &str) -> Error;
}
impl<T: Into<Box<dyn std::error::Error>>> ErrorExt for T {
fn wrap(self, msg: &str) -> Error {
Error {
msg: msg.into(),
cause: Some(self.into())
}
}
}
pub trait ResultExt<T> {
fn wrap_err(self, msg: &str) -> std::result::Result<T, Error>;
}
impl<T, E: ErrorExt> ResultExt<T> for std::result::Result<T, E> {
fn wrap_err(self, msg: &str) -> std::result::Result<T, Error> {
self.map_err(|err| err.wrap(msg))
}
}