68 lines
1.8 KiB
Rust
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.")
|
|
}
|
|
}
|