use std::fmt::Display;
pub type Error = Box<dyn std::error::Error + Send + Sync>;
pub type Result<T, E = Error> = std::result::Result<T, E>;
#[macro_export]
macro_rules! err {
($($arg:tt)*) => {
$crate::error::Error::from(format!($($arg)*))
};
}
#[macro_export]
macro_rules! bail {
($($arg:tt)*) => {
return Err($crate::err!($($arg)*))
};
}
pub trait Context<T> {
fn context(self, msg: impl Display) -> Result<T>;
fn with_context<F, D>(self, f: F) -> Result<T>
where
F: FnOnce() -> D,
D: Display;
}
impl<T, E> Context<T> for std::result::Result<T, E>
where
E: Into<Error>,
{
fn context(self, msg: impl Display) -> Result<T> {
self.map_err(|e| Error::from(format!("{msg}: {}", e.into())))
}
fn with_context<F, D>(self, f: F) -> Result<T>
where
F: FnOnce() -> D,
D: Display,
{
self.map_err(|e| Error::from(format!("{}: {}", f(), e.into())))
}
}
impl<T> Context<T> for Option<T> {
fn context(self, msg: impl Display) -> Result<T> {
self.ok_or_else(|| Error::from(msg.to_string()))
}
fn with_context<F, D>(self, f: F) -> Result<T>
where
F: FnOnce() -> D,
D: Display,
{
self.ok_or_else(|| Error::from(f().to_string()))
}
}