Skip to content

AlterionX/treeerror

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

treeerror

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.

Some old notes

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));

About

thiserror expansion for deriving useful error conversion methods

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages