err-gen 0.1.0

Error-generation macro for hierarchical actor design
Documentation
extern crate proc_macro;

use proc_macro::{
    TokenStream,
};
use quote::quote;
use syn::{self, DeriveInput, TypeTuple};

#[proc_macro_attribute]
pub fn err_gen(attr: TokenStream, input: TokenStream) -> TokenStream {
    use syn::Data::*;

    let attr_ast: TypeTuple = syn::parse(attr).unwrap();
    let input_ast: DeriveInput = syn::parse(input).unwrap();

    let raw_enum = match input_ast.data {
        Enum(data_enum) => data_enum,
        _ => panic!("input must be an enum"),
    };

    let name = &input_ast.ident;

    let mut nested_variants = quote! {};

    for variant in raw_enum.variants.iter() {
        let ident = &variant.ident;

        nested_variants = match variant.attrs.get(0usize) {
            Some(attr) => quote! {
                #attr
                #ident,
                #nested_variants
            },
            None => quote! {
                #ident,
                #nested_variants
            },
        };
    };

    let enum_declaration = quote! {
        #[derive(Display, Debug)]
        pub enum #name {
            #nested_variants
            ErrorNode(Box<dyn std::error::Error>),
        }
    };

    let mut impl_clauses = quote! {};

    for element in attr_ast.elems.iter() {
        impl_clauses = quote! {
            impl From<#element> for #name {
                fn from(e: #element) -> Self { Self::ErrorNode(Box::new(e)) }
            }
            #impl_clauses
        };
    };

    let result = quote! {
        #enum_declaration
        #impl_clauses
    };

    result.into()
}