err-derive
A failure-like derive macro for the std Error
.
The source code is mostly copied from failure-derive
.
Motivation
Why yet another error handling library? There already are dozen others, the most popular being:
The former provides a nice #[derive(Fail)]
macro, but it uses its own error type (Fail
) and its usage is rather discouraged since std::error::Error
is getting fixed to provide the same benefits as Fail
.
error-chain
does support std::error::Error
, but it uses a declarative for generating the error implementation which makes the syntax too obscure in my opinion.
This crate tries to combine both advantages:
- work with
std::error::Error
- provide a custom
#[derive(Error)]
that works just likefailure-derive
err-derive
is compatible with std
, including the recent change to deprecate Error::cause
in favour of Error::source
, and provides an easy syntax for generating the Display
and Error
boilerplate (the latter being 99% copied from failure-derive
).
Features
err-derive
can be applied to your error struct / enum and does the following for you:
- Derive
Display
implementation - Derive
Error
implementation (implementingsource
to return the cause of the error)
Planned features
- Derive
From<OtherError>
implementations
Usage
Cargo.toml:
[dependencies]
err-derive = "0.1"
Rust code:
#[macro_use]
extern crate err_derive;
use std::error::Error;
use std::path::PathBuf;
#[derive(Debug, Error)]
pub enum FormatError {
#[error(display = "invalid header (expected: {}, got: {})", expected, found)]
InvalidHeader {
expected: String,
found: String,
},
#[error(display = "missing attribute: {:?}", _0)]
MissingAttribute(String),
}
#[derive(Debug, Error)]
pub enum LoadingError {
#[error(display = "could not decode file")]
FormatError(#[error(cause)] FormatError),
#[error(display = "could not find file: {:?}", path)]
NotFound { path: PathBuf },
}
impl From<FormatError> for LoadingError {
fn from(f: FormatError) -> Self {
LoadingError::FormatError(f)
}
}
fn main() {
let my_error: LoadingError =
FormatError::MissingAttribute("some_attr".to_owned()).into();
print_error(&my_error);
}
fn print_error(e: &dyn Error) {
eprintln!("error: {}", e);
let mut cause = e.source();
while let Some(e) = cause {
eprintln!("caused by: {}", e);
cause = e.source();
}
}
Credit
Credit goes to @withoutboats and other contributors of failure
.