denumic 0.1.0

Creating enum-based runtime dispatched traits
Documentation

# denumic

`denumic` macro is to create enum-based runtime dispatched traits.

When applied to a `trait`, it exports the definition of the trait that would be passed to other `denumic` attributes on `enum`s.

When applied to an `enum`, it generates a macro that can be used to dispatch to the appropriate implementation of the trait for each variant of the `enum`.

`From` and `TryFrom` are also automatically implemented for the `enum`, as long as it does not break coherence rules, so that it can be converted to and from the variants.

# Example

```rust
use denumic::denumic;

// Generic parameters of the trait and the enum could be finly merged matching by names.
#[denumic]
pub trait Trait {
    const MY_CONST: i32;
    type MyType;
    fn foo(self) -> i32;
}

// Note that the identifiers `used` before the trait definition also have to be `use`d before the enum definition.
#[denumic(Trait)]
// Associated types and consts can be specified using attributes:
#[MY_CONST = 1]
// As for types that are not a valid `expr`, quote them instead of raw types:
#[MyType = "&'static str"]
pub enum Impl<Other = ()>
where
    Other: Trait,
{
    // `From` and `TryFrom` are only generated if the enum has only a single field.
    A(A),
    // If multiple fields are found, the one with `#[denumic]` otherwise the first one is dispatched.
    Other(Other, String),
}

pub struct A;

impl Trait for A {
    const MY_CONST: i32 = 2;

    type MyType = ();

    fn foo(self) -> i32 {
        10
    }
}

impl Trait for () {
    const MY_CONST: i32 = 0;

    type MyType = String;

    fn foo(self) -> i32 {
        20
    }
}

fn call_foo(v: A) -> i32 {
    let v: Impl = v.into();
    v.foo()
}

```