1 stable release
1.0.0 | Feb 1, 2025 |
---|
#675 in Rust patterns
127 downloads per month
7KB
59 lines
simplerror
A zero-dependency Rust macro to declaratively define your error enums with automatic From
, Display
, and Error
trait implementations. Declare error types which automatically wrap an inner error type while also providing detailed formatted error messages.
simplerror::declare! {
pub enum MyError {
SimpleMember => "something went wrong",
SomeMember(e1: String) => "1234 {e1}",
AnotherMember(e1: String, e2: String) => "1234 {e1} {e2}",
BasicMember, // Display::fmt writes "MyError::BasicMember"
}
pub enum AnotherError {
Variant1,
Variant2 => "message",
ComposedVariant(e: MyError) => "an inner error: {e}",
}
}
assert_eq!(MyError::SimpleMember.to_string(), "something went wrong");
assert_eq!(
MyError::SomeMember("5678".to_string()).to_string(),
"1234 5678"
);
assert_eq!(
AnotherError::ComposedVariant(MyError::SimpleMember).to_string(),
"an inner error: something went wrong"
);
From
implementations are handled automatically for any enum members which wrap a single value.
#[derive(Debug)]
struct Foo;
simplerror::declare! {
pub(crate) enum CustomError {
Failure => "We failed...",
}
// This enum automatically implements From<CustomError> by returning `Self::Wrapped(CustomError)`
pub(crate) enum WrappingError {
Wrapped(e: CustomError) => "wrapped: {e}",
}
}
fn fail_inner() -> Result<(), CustomError> {
Err(CustomError::Failure)
}
fn fail_outer() -> Result<(), WrappingError> {
fail_inner()?;
Ok(())
}
assert!(matches!(
fail_outer(),
Err(WrappingError::Wrapped(CustomError::Failure))
));
To derive extra traits on your error enum, or run other procedural macros, you can add them like so above each enum declaration or enum variant like so.
simplerror::declare! {
#[derive(PartialEq)]
#[cfg_attr(test, derive(serde::Serialize))]
enum MyError {
#[cfg_attr(test, serde(rename_all = "ERR_NOT_FOUND"))]
ErrorCode404 => "didn't find it",
}
}
impl MyError {
fn is_404(&self) -> bool {
self == &Self::ErrorCode404
}
}
[!WARNING] To conditionally compile a certain enum, you can wrap the entire
declare!
invocation in your compilation flag.If you conditionally compile enum members, or configure-out the enum type itself, you'll encounter compilation errors due to missing references on the automatic trait implementations which
declare!
generates.