nit/crates/nit/src/result.rs

53 lines
1.3 KiB
Rust

//! Error handling niceties.
// Because who needs anyhow anyways.
/// Provide context for an existing error.
pub trait Context<T> {
fn context(self, fmt: std::fmt::Arguments<'_>) -> Result<T, CtxError>;
}
impl<T, E> Context<T> for std::result::Result<T, E>
where
E: std::error::Error + 'static,
{
fn context(self, fmt: std::fmt::Arguments<'_>) -> Result<T, CtxError> {
match self {
Ok(o) => Ok(o),
Err(e) => Err(CtxError {
context: fmt.to_string(),
inner: Box::new(e),
}),
}
}
}
/// An error with context attached.
///
/// The context is provided as format arguments, but will be constructed into a string if the value
/// is an error.
#[derive(Debug)]
pub struct CtxError {
context: String,
inner: Box<dyn std::error::Error>,
}
impl std::fmt::Display for CtxError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.context.as_str())
}
}
impl std::error::Error for CtxError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
Some(self.inner.as_ref())
}
}
pub type Result<T, E = CtxError> = std::result::Result<T, E>;
pub fn ctx_os_error(args: std::fmt::Arguments<'_>) -> Result<(), CtxError> {
Err(std::io::Error::last_os_error()).context(args)
}