1 use std::default::Default; 2 use syn::{Ident, Lit, 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, Default)] 13 pub struct StrumVariantProperties { 14 pub transparent: Option<kw::transparent>, 15 pub disabled: Option<kw::disabled>, 16 pub default: Option<kw::default>, 17 pub default_with: Option<LitStr>, 18 pub ascii_case_insensitive: Option<bool>, 19 pub message: Option<LitStr>, 20 pub detailed_message: Option<LitStr>, 21 pub documentation: Vec<LitStr>, 22 pub props: Vec<(LitStr, Lit)>, 23 serialize: Vec<LitStr>, 24 pub to_string: Option<LitStr>, 25 ident: Option<Ident>, 26 } 27 28 impl StrumVariantProperties { ident_as_str(&self, case_style: Option<CaseStyle>) -> LitStr29 fn ident_as_str(&self, case_style: Option<CaseStyle>) -> LitStr { 30 let ident = self.ident.as_ref().expect("identifier"); 31 LitStr::new(&ident.convert_case(case_style), ident.span()) 32 } 33 get_preferred_name( &self, case_style: Option<CaseStyle>, prefix: Option<&LitStr>, ) -> LitStr34 pub fn get_preferred_name( 35 &self, 36 case_style: Option<CaseStyle>, 37 prefix: Option<&LitStr>, 38 ) -> LitStr { 39 let mut output = self.to_string.as_ref().cloned().unwrap_or_else(|| { 40 self.serialize 41 .iter() 42 .max_by_key(|s| s.value().len()) 43 .cloned() 44 .unwrap_or_else(|| self.ident_as_str(case_style)) 45 }); 46 47 if let Some(prefix) = prefix { 48 output = LitStr::new(&(prefix.value() + &output.value()), output.span()); 49 } 50 51 output 52 } 53 get_serializations(&self, case_style: Option<CaseStyle>) -> Vec<LitStr>54 pub fn get_serializations(&self, case_style: Option<CaseStyle>) -> Vec<LitStr> { 55 let mut attrs = self.serialize.clone(); 56 if let Some(to_string) = &self.to_string { 57 attrs.push(to_string.clone()); 58 } 59 60 if attrs.is_empty() { 61 attrs.push(self.ident_as_str(case_style)); 62 } 63 64 attrs 65 } 66 } 67 68 impl HasStrumVariantProperties for Variant { get_variant_properties(&self) -> syn::Result<StrumVariantProperties>69 fn get_variant_properties(&self) -> syn::Result<StrumVariantProperties> { 70 let mut output = StrumVariantProperties { 71 ident: Some(self.ident.clone()), 72 ..Default::default() 73 }; 74 75 let mut message_kw = None; 76 let mut detailed_message_kw = None; 77 let mut transparent_kw = None; 78 let mut disabled_kw = None; 79 let mut default_kw = None; 80 let mut default_with_kw = None; 81 let mut to_string_kw = None; 82 let mut ascii_case_insensitive_kw = None; 83 for meta in self.get_metadata()? { 84 match meta { 85 VariantMeta::Message { value, kw } => { 86 if let Some(fst_kw) = message_kw { 87 return Err(occurrence_error(fst_kw, kw, "message")); 88 } 89 90 message_kw = Some(kw); 91 output.message = Some(value); 92 } 93 VariantMeta::DetailedMessage { value, kw } => { 94 if let Some(fst_kw) = detailed_message_kw { 95 return Err(occurrence_error(fst_kw, kw, "detailed_message")); 96 } 97 98 detailed_message_kw = Some(kw); 99 output.detailed_message = Some(value); 100 } 101 VariantMeta::Documentation { value } => { 102 output.documentation.push(value); 103 } 104 VariantMeta::Serialize { value, .. } => { 105 output.serialize.push(value); 106 } 107 VariantMeta::ToString { value, kw } => { 108 if let Some(fst_kw) = to_string_kw { 109 return Err(occurrence_error(fst_kw, kw, "to_string")); 110 } 111 112 to_string_kw = Some(kw); 113 output.to_string = Some(value); 114 } 115 VariantMeta::Transparent(kw) => { 116 if let Some(fst_kw) = transparent_kw { 117 return Err(occurrence_error(fst_kw, kw, "transparent")); 118 } 119 120 transparent_kw = Some(kw); 121 output.transparent = Some(kw); 122 } 123 VariantMeta::Disabled(kw) => { 124 if let Some(fst_kw) = disabled_kw { 125 return Err(occurrence_error(fst_kw, kw, "disabled")); 126 } 127 128 disabled_kw = Some(kw); 129 output.disabled = Some(kw); 130 } 131 VariantMeta::Default(kw) => { 132 if let Some(fst_kw) = default_kw { 133 return Err(occurrence_error(fst_kw, kw, "default")); 134 } 135 136 default_kw = Some(kw); 137 output.default = Some(kw); 138 } 139 VariantMeta::DefaultWith { kw, value } => { 140 if let Some(fst_kw) = default_with_kw { 141 return Err(occurrence_error(fst_kw, kw, "default_with")); 142 } 143 144 default_with_kw = Some(kw); 145 output.default_with = Some(value); 146 } 147 VariantMeta::AsciiCaseInsensitive { kw, value } => { 148 if let Some(fst_kw) = ascii_case_insensitive_kw { 149 return Err(occurrence_error(fst_kw, kw, "ascii_case_insensitive")); 150 } 151 152 ascii_case_insensitive_kw = Some(kw); 153 output.ascii_case_insensitive = Some(value); 154 } 155 VariantMeta::Props { props, .. } => { 156 output.props.extend(props); 157 } 158 } 159 } 160 161 Ok(output) 162 } 163 } 164