bind-conf/bind_conf_derive/src/gen_enum.rs

68 lines
1.8 KiB
Rust

use quote::quote;
use syn;
use proc_macro2;
use super::attr::{self, NamedIdent};
pub fn gen_parse_enum(data: &syn::DataEnum, gattr: &attr::Global) -> proc_macro2::TokenStream {
let (pattern, parse_variant) = get_variant_list(&data);
let fallback = gattr.gen_enum_fallback();
quote! {
match pa.read_word()? {
#( #pattern => #parse_variant , )*
_ => #fallback
}
}
}
fn get_variant_list(data: &syn::DataEnum) -> (Vec<proc_macro2::TokenStream>, Vec<proc_macro2::TokenStream>) {
let mut patterns = Vec::new();
let mut parse_variants = Vec::new();
for variant in &data.variants {
patterns.push(gen_variant_pattern(&variant));
parse_variants.push(gen_variant_parse(&variant));
}
(patterns, parse_variants)
}
fn gen_variant_pattern(variant: &syn::Variant) -> proc_macro2::TokenStream {
let variant_attr = attr::VariantAttr::from_ast(&variant);
let names = variant_attr.names(&variant.ident);
quote! {
#(#names)|*
}
}
fn gen_variant_parse(variant: &syn::Variant) -> proc_macro2::TokenStream {
match &variant.fields {
syn::Fields::Unit => {
gen_unit_variant_parse(&variant.ident)
},
syn::Fields::Unnamed(ref fields) => {
gen_unnamed_variant_parse(&variant.ident, &fields)
},
_ => panic!("Only Unit and Unnamed variants are supported.")
}
}
fn gen_unit_variant_parse(name: &syn::Ident) -> proc_macro2::TokenStream {
quote!{ Ok( Self::#name ) }
}
fn gen_unnamed_variant_parse(
name: &syn::Ident,
fields: &syn::FieldsUnnamed
) -> proc_macro2::TokenStream
{
match fields.unnamed.len() {
0 => quote! { Ok( Self::#name() ) },
1 => quote! { Ok( Self::#name(pa.read()?) ) },
_ => panic!("Unnamed variants are supported only with 0 or 1 element.")
}
}