1 use std::default::Default; 2 use syn::{Ident, LitStr, Variant}; 3 4 use super::case_style::{CaseStyle, CaseStyleHelpers}; 5 use super::metadata::{kw, VariantExt, VariantMeta}; 6 use super::occurrence_error; 7 8 pub trait HasStrumVariantProperties { get_variant_properties(&self) -> syn::Result<StrumVariantProperties>9 fn get_variant_properties(&self) -> syn::Result<StrumVariantProperties>; 10 } 11 12 #[derive(Clone, Eq, PartialEq, Debug, Default)] 13 pub struct StrumVariantProperties { 14 pub disabled: Option<kw::disabled>, 15 pub default: Option<kw::default>, 16 pub ascii_case_insensitive: Option<bool>, 17 pub message: Option<LitStr>, 18 pub detailed_message: Option<LitStr>, 19 pub documentation: Vec<LitStr>, 20 pub string_props: Vec<(LitStr, LitStr)>, 21 serialize: Vec<LitStr>, 22 pub to_string: Option<LitStr>, 23 ident: Option<Ident>, 24 } 25 26 impl StrumVariantProperties { ident_as_str(&self, case_style: Option<CaseStyle>) -> LitStr27 fn ident_as_str(&self, case_style: Option<CaseStyle>) -> LitStr { 28 let ident = self.ident.as_ref().expect("identifier"); 29 LitStr::new(&ident.convert_case(case_style), ident.span()) 30 } 31 get_preferred_name(&self, case_style: Option<CaseStyle>) -> LitStr32 pub fn get_preferred_name(&self, case_style: Option<CaseStyle>) -> LitStr { 33 self.to_string.as_ref().cloned().unwrap_or_else(|| { 34 self.serialize 35 .iter() 36 .max_by_key(|s| s.value().len()) 37 .cloned() 38 .unwrap_or_else(|| self.ident_as_str(case_style)) 39 }) 40 } 41 get_serializations(&self, case_style: Option<CaseStyle>) -> Vec<LitStr>42 pub fn get_serializations(&self, case_style: Option<CaseStyle>) -> Vec<LitStr> { 43 let mut attrs = self.serialize.clone(); 44 if let Some(to_string) = &self.to_string { 45 attrs.push(to_string.clone()); 46 } 47 48 if attrs.is_empty() { 49 attrs.push(self.ident_as_str(case_style)); 50 } 51 52 attrs 53 } 54 } 55 56 impl HasStrumVariantProperties for Variant { get_variant_properties(&self) -> syn::Result<StrumVariantProperties>57 fn get_variant_properties(&self) -> syn::Result<StrumVariantProperties> { 58 let mut output = StrumVariantProperties { 59 ident: Some(self.ident.clone()), 60 ..Default::default() 61 }; 62 63 let mut message_kw = None; 64 let mut detailed_message_kw = None; 65 let mut to_string_kw = None; 66 let mut disabled_kw = None; 67 let mut default_kw = None; 68 let mut ascii_case_insensitive_kw = None; 69 for meta in self.get_metadata()? { 70 match meta { 71 VariantMeta::Message { value, kw } => { 72 if let Some(fst_kw) = message_kw { 73 return Err(occurrence_error(fst_kw, kw, "message")); 74 } 75 76 message_kw = Some(kw); 77 output.message = Some(value); 78 } 79 VariantMeta::DetailedMessage { value, kw } => { 80 if let Some(fst_kw) = detailed_message_kw { 81 return Err(occurrence_error(fst_kw, kw, "detailed_message")); 82 } 83 84 detailed_message_kw = Some(kw); 85 output.detailed_message = Some(value); 86 } 87 VariantMeta::Documentation { value } => { 88 output.documentation.push(value); 89 } 90 VariantMeta::Serialize { value, .. } => { 91 output.serialize.push(value); 92 } 93 VariantMeta::ToString { value, kw } => { 94 if let Some(fst_kw) = to_string_kw { 95 return Err(occurrence_error(fst_kw, kw, "to_string")); 96 } 97 98 to_string_kw = Some(kw); 99 output.to_string = Some(value); 100 } 101 VariantMeta::Disabled(kw) => { 102 if let Some(fst_kw) = disabled_kw { 103 return Err(occurrence_error(fst_kw, kw, "disabled")); 104 } 105 106 disabled_kw = Some(kw); 107 output.disabled = Some(kw); 108 } 109 VariantMeta::Default(kw) => { 110 if let Some(fst_kw) = default_kw { 111 return Err(occurrence_error(fst_kw, kw, "default")); 112 } 113 114 default_kw = Some(kw); 115 output.default = Some(kw); 116 } 117 VariantMeta::AsciiCaseInsensitive { kw, value } => { 118 if let Some(fst_kw) = ascii_case_insensitive_kw { 119 return Err(occurrence_error(fst_kw, kw, "ascii_case_insensitive")); 120 } 121 122 ascii_case_insensitive_kw = Some(kw); 123 output.ascii_case_insensitive = Some(value); 124 } 125 VariantMeta::Props { props, .. } => { 126 output.string_props.extend(props); 127 } 128 } 129 } 130 131 Ok(output) 132 } 133 } 134