Crate treeerror

Crate treeerror 

Source
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 implements From 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.