This crate is intended to provide some convenience enums for mapping enums from one type to
another. This is intended to work with 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(),
);
Future work potentially includes a proc macro rewrite to enable better error messages and configurability.
One Ring to rule them all
treeerror! {
Mordor {
Hobbit {
Peregrin @unit,
Meriadoc @unit,
Samwise @unit,
Frodo @unit,
Bilbo @unit,
Gollum @unit,
},
Elf {
Galadriel @unit,
Elrond @unit,
Legolas @unit,
Celebrimbor @unit,
Arwen @unit,
},
Wizard {
Saruman @unit,
Gandalf @unit,
Radagast @unit,
},
Ents {
@unit SorryIDoNotRememberYourName,
},
Man {
Theoden @unit,
Denethor @unit,
Eowyn @unit,
Faramir @unit,
Isildur @unit,
Elendil @unit,
Aragorn @unit,
},
Orc @unit,
Shelob @unit,
GenericPerson @unit,
Gollum @unit,
}
}
One Ring to find them
// This and the rest do work though!
map_enum! {
MiddleEarth > Mordor {
Shire = Hobbit,
Lothlorien = Elf,
Rohan = Man,
Gondor = Man,
Wizard = Wizard,
Gollum = Gollum,
} @catchrest |_ignored| {
Mordor::GenericPerson
}
}
One Ring to bring them all
from_chain!(Mordor::Hobbit < Hobbit < (Peregrin, Meriadoc, Samwise, Frodo, Bilbo));
// And so on.
and in the darkness bind them.
// Muhahahaha!
from!(Mordor = Hobbit(Hobbit));
from!(Mordor = Hobbit(Peregrin));
from!(Mordor = Hobbit(Meriadoc));
from!(Mordor = Hobbit(Samwise));
from!(Mordor = Hobbit(Frodo));
from!(Mordor = Hobbit(Bilbo));
from!(Hobbit = Peregrin(Peregrin));