| 1 | use proc_macro2::TokenStream; |
| 2 | use quote::quote; |
| 3 | use syn::{Fields, Ident, Variant}; |
| 4 | |
| 5 | pub mod as_ref_str; |
| 6 | pub mod display; |
| 7 | pub mod from_string; |
| 8 | pub mod to_string; |
| 9 | |
| 10 | struct NonSingleFieldEnum; |
| 11 | |
| 12 | fn extract_single_field_variant_and_then<F>( |
| 13 | name: &Ident, |
| 14 | variant: &Variant, |
| 15 | return_val_fn: F, |
| 16 | ) -> Result<TokenStream, NonSingleFieldEnum> |
| 17 | where |
| 18 | F: Fn(&TokenStream) -> TokenStream, |
| 19 | { |
| 20 | let variant_ident = &variant.ident; |
| 21 | |
| 22 | let pattern_and_return = match &variant.fields { |
| 23 | Fields::Unnamed(f) if f.unnamed.len() == 1 => { |
| 24 | let ident = "e! { field0 }; |
| 25 | let ref_kw = match f.unnamed.last().unwrap().ty { |
| 26 | syn::Type::Reference(..) => quote! { }, |
| 27 | _ => quote! { ref }, |
| 28 | }; |
| 29 | |
| 30 | let ret_val = return_val_fn(ident); |
| 31 | quote! { (#ref_kw #ident) => #ret_val } |
| 32 | } |
| 33 | Fields::Named(f) if f.named.len() == 1 => { |
| 34 | let field = f.named.last().unwrap(); |
| 35 | let ref_kw = match field.ty { |
| 36 | syn::Type::Reference(..) => quote! { }, |
| 37 | _ => quote! { ref }, |
| 38 | }; |
| 39 | |
| 40 | let ident = field.ident.as_ref().unwrap(); |
| 41 | let ident = "e! { #ident }; |
| 42 | let ret_val = return_val_fn(ident); |
| 43 | quote! { { #ref_kw #ident} => #ret_val } |
| 44 | } |
| 45 | _ => return Err(NonSingleFieldEnum), |
| 46 | }; |
| 47 | |
| 48 | Ok(quote! { #name::#variant_ident #pattern_and_return }) |
| 49 | } |
| 50 | |