rpa_enum 0.1.1

RPA Enum extension.
Documentation
use crate::proc_macro::TokenStream;
use std::collections::HashMap;
use syn::{Lit, Meta, MetaNameValue, MetaList};

// Generic derive macro fn
pub fn derive_macro<F>(tokens: TokenStream, gen_impl: F) -> TokenStream
    where F: Fn(&syn::Ident, Vec<String>, HashMap<String, Vec<String>>) -> TokenStream {
    // Parse TokenStream into AST
    let ast: syn::ItemEnum = syn::parse(tokens).unwrap();
    let mut attributes: HashMap<String, Vec<String>> = HashMap::new();
    // Iterate over the struct's #[...] attributes

    let mut variants: Vec<String> = Vec::new();

    for variant in ast.variants.iter() {
        let variant = variant.ident.to_string();
        variants.push(variant);
    }

    for attr in ast.attrs.into_iter() {
        let option = attr.parse_meta().unwrap();
        match option {
            Meta::List(MetaList{ref path, ref nested, ..}) => {
                let segment = path.segments.first().unwrap();
                let ident = segment.ident.clone();
                let mut values: Vec<String> = Vec::new();
                if attributes.get(ident.to_string().as_str()).is_some() {
                    values.extend(attributes.get(ident.to_string().as_str()).unwrap().iter().cloned());
                }
                for nested_meta in nested.iter() {
                    match nested_meta {
                        syn::NestedMeta::Meta(meta) => {
                            match meta {
                                Meta::Path(path) => {
                                    let segment = path.segments.first().unwrap();
                                    let ident = segment.ident.clone();
                                    values.push(ident.to_string());
                                    ()
                                },
                                _=> ()
                            }
                        },
                        _ => ()
                    }
                }
                attributes.insert(ident.to_string(), values);
                ()
            },
            Meta::NameValue(MetaNameValue{ref path, ref lit, ..}) => {
                let segment = path.segments.first().unwrap();
                let ident = segment.ident.clone();
                if let Lit::Str(lit) = lit {
                    let mut values: Vec<String> = Vec::new();
                    if attributes.get(ident.to_string().as_str()).is_some() {
                        values.extend(attributes.get(ident.to_string().as_str()).unwrap().iter().cloned());
                    }
                    values.push(lit.value());
                    attributes.insert(ident.to_string(), values);
                }
            },
            _=> ()
        }
    }

    // Build the trait implementation
    gen_impl(&ast.ident, variants, attributes)
}