Expand description
This crate is intended to provide some convenience enums for mapping enums from one type to
another. This is intended as an expansion of thiserror
that has more compile time mapping
between sets of enums as well as shortcutting From
implementations.
This is how to use wrapped the crate:
#![feature(more_qualified_paths)]
treeerror::treeerror! {
#[derive(PartialEq, Debug)]
Root {
#[derive(PartialEq, Debug)]
Child0 {
#[derive(PartialEq, Debug)]
Child0_0 {
#[derive(PartialEq, Debug)]
Child0_0_0(&'static str),
},
#[derive(PartialEq, Debug)]
Child0_1 @unit,
Child0_2 @flatunit,
},
#[derive(PartialEq, Debug)]
Child1 {
#[derive(PartialEq, Debug)]
Child1_0 @unit,
#[derive(PartialEq, Debug)]
Child1_1 @unit,
Child1_2(u64),
Child1_3 @skipfrom (&'static str)
},
},
#[derive(PartialEq, Debug)]
SiblingRoot {
SiblingChild0(String),
SiblingChild1(&'static str)
}
}
const MSG: &'static str = "hello from below";
fn root_error() -> Result<(), Root> {
Err(MSG)?;
unreachable!("error should have returned earlier");
}
assert_eq!(
Err(Root::Child0(Child0::Child0_0(RenamedChild0_0::Child0_0_0(MSG)))),
root_error()
);
We also provide some utilities for generating simple From
implementations.
#![feature(more_qualified_paths)]
use treeerror::{from_many, from};
#[derive(PartialEq, Debug)]
enum Root {
A(A),
}
#[derive(PartialEq, Debug)]
enum A {
Alpha(Alpha),
}
#[derive(PartialEq, Debug)]
enum Alpha {
One(One),
}
#[derive(PartialEq, Debug)]
enum One {
Child(Child),
}
#[derive(PartialEq, Debug)]
struct Child;
from_many!(Root: A, A, Alpha, One, Child);
from_many!(A: Alpha, Alpha, One, Child);
from_many!(Alpha: One, One, Child);
from!(One = Child(Child));
const MSG: &'static str = "hello from below";
fn root_error() -> Result<(), Root> {
Err(Child)?;
unreachable!("error should have returned earlier");
}
assert_eq!(
Err(Root::A(A::Alpha(Alpha::One(One::Child(Child))))),
root_error()
);
You’ll notice that there are many from_many
call here – automatically generating this
tree is not yet complete and in progress.
We can also handle “flatter” error structures where, instead of nesting these enums by wrapping them, we destructure the internal values instead.
There are several ways to use this as well, but here’s the most basic use case.
#![feature(more_qualified_paths)]
use treeerror::map_enum;
#[derive(PartialEq, Eq, Debug)]
pub enum ParentError {
Child(&'static str),
}
#[derive(PartialEq, Eq, Debug)]
pub enum ChildError {
SomeError(&'static str),
}
map_enum!(ChildError > ParentError {
SomeError > Child
});
const MSG: &'static str = "hello there";
fn parent_error() -> Result<(), ParentError> {
Err(ChildError::SomeError(MSG))?;
unreachable!("error should have returned earlier");
}
assert_eq!(
Err(ParentError::Child(MSG)),
parent_error(),
);
Some things that remain: combining all of this in a nice interface to autogenerate the error chains, as well as packaging all of this stuff in a way to enable better error messages during compilation. This potentially includes a proc macro rewrite to enable better error messages and configurability.
Macros§
- as_pat
- from
- Generates simple
From
implemeentations between various types. - from_
chain - Takes multiple enums that wrap child enums (that can be constructed like
A::BVariant(B::CVariant(C))
) and implementsFrom
for all types involved so that the lowest type can be converted into a higher type. - from_
many - Implements
From
multiple times. - map_
enum - Shorthand for mapping one error enum on top of another one.
- treeerror
- Generates the tree of errors.