use crate::{Error, Result};
pub trait Context<T> {
fn context(self, message: &str) -> Result<T>;
}
impl<T, E: std::error::Error + Send + Sync + 'static> Context<T> for std::result::Result<T, E> {
fn context(self, message: &str) -> Result<T> {
self.map_err(|e| {
Error::new(ContextError {
message: message.into(),
source: Box::new(e),
})
})
}
}
#[derive(Debug)]
struct ContextError {
message: String,
source: Box<dyn std::error::Error + Send + Sync>,
}
impl std::fmt::Display for ContextError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}: {}", self.message, self.source)
}
}
impl std::error::Error for ContextError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
Some(&*self.source)
}
}
impl<T> Context<T> for Option<T> {
fn context(self, message: &str) -> Result<T> {
self.ok_or_else(|| {
Error::new(ContextError {
message: message.into(),
source: Box::new(NoneError),
})
})
}
}
#[derive(Debug)]
struct NoneError;
impl std::fmt::Display for NoneError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "value was None")
}
}
impl std::error::Error for NoneError {}