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 | |