1 use proc_macro2::TokenStream; 2 use quote::quote; 3 use std::default::Default; 4 use syn::{DeriveInput, Ident, Path, Visibility}; 5 6 use super::case_style::CaseStyle; 7 use super::metadata::{DeriveInputExt, EnumDiscriminantsMeta, EnumMeta}; 8 use super::occurrence_error; 9 10 pub trait HasTypeProperties { get_type_properties(&self) -> syn::Result<StrumTypeProperties>11 fn get_type_properties(&self) -> syn::Result<StrumTypeProperties>; 12 } 13 14 #[derive(Debug, Clone, Default)] 15 pub struct StrumTypeProperties { 16 pub case_style: Option<CaseStyle>, 17 pub ascii_case_insensitive: bool, 18 pub discriminant_derives: Vec<Path>, 19 pub discriminant_name: Option<Ident>, 20 pub discriminant_others: Vec<TokenStream>, 21 pub discriminant_vis: Option<Visibility>, 22 } 23 24 impl HasTypeProperties for DeriveInput { get_type_properties(&self) -> syn::Result<StrumTypeProperties>25 fn get_type_properties(&self) -> syn::Result<StrumTypeProperties> { 26 let mut output = StrumTypeProperties::default(); 27 28 let strum_meta = self.get_metadata()?; 29 let discriminants_meta = self.get_discriminants_metadata()?; 30 31 let mut serialize_all_kw = None; 32 let mut ascii_case_insensitive_kw = None; 33 for meta in strum_meta { 34 match meta { 35 EnumMeta::SerializeAll { case_style, kw } => { 36 if let Some(fst_kw) = serialize_all_kw { 37 return Err(occurrence_error(fst_kw, kw, "serialize_all")); 38 } 39 40 serialize_all_kw = Some(kw); 41 output.case_style = Some(case_style); 42 } 43 EnumMeta::AsciiCaseInsensitive(kw) => { 44 if let Some(fst_kw) = ascii_case_insensitive_kw { 45 return Err(occurrence_error(fst_kw, kw, "ascii_case_insensitive")); 46 } 47 48 ascii_case_insensitive_kw = Some(kw); 49 output.ascii_case_insensitive = true; 50 } 51 } 52 } 53 54 let mut name_kw = None; 55 let mut vis_kw = None; 56 for meta in discriminants_meta { 57 match meta { 58 EnumDiscriminantsMeta::Derive { paths, .. } => { 59 output.discriminant_derives.extend(paths); 60 } 61 EnumDiscriminantsMeta::Name { name, kw } => { 62 if let Some(fst_kw) = name_kw { 63 return Err(occurrence_error(fst_kw, kw, "name")); 64 } 65 66 name_kw = Some(kw); 67 output.discriminant_name = Some(name); 68 } 69 EnumDiscriminantsMeta::Vis { vis, kw } => { 70 if let Some(fst_kw) = vis_kw { 71 return Err(occurrence_error(fst_kw, kw, "vis")); 72 } 73 74 vis_kw = Some(kw); 75 output.discriminant_vis = Some(vis); 76 } 77 EnumDiscriminantsMeta::Other { path, nested } => { 78 output.discriminant_others.push(quote! { #path(#nested) }); 79 } 80 } 81 } 82 83 Ok(output) 84 } 85 } 86