1 use std::borrow::Cow; 2 3 use crate::ast::Fields; 4 use crate::codegen; 5 use crate::options::{Core, InputField, ParseAttribute}; 6 use crate::util::SpannedValue; 7 use crate::{Error, FromMeta, Result}; 8 9 #[derive(Debug, Clone)] 10 pub struct InputVariant { 11 ident: syn::Ident, 12 attr_name: Option<String>, 13 data: Fields<InputField>, 14 skip: Option<bool>, 15 /// Whether or not the variant should be used to create an instance for 16 /// `FromMeta::from_word`. 17 pub word: Option<SpannedValue<bool>>, 18 /// Whether or not unknown fields are acceptable in this 19 allow_unknown_fields: Option<bool>, 20 } 21 22 impl InputVariant { as_codegen_variant<'a>(&'a self, ty_ident: &'a syn::Ident) -> codegen::Variant<'a>23 pub fn as_codegen_variant<'a>(&'a self, ty_ident: &'a syn::Ident) -> codegen::Variant<'a> { 24 codegen::Variant { 25 ty_ident, 26 variant_ident: &self.ident, 27 name_in_attr: self 28 .attr_name 29 .as_ref() 30 .map_or_else(|| Cow::Owned(self.ident.to_string()), Cow::Borrowed), 31 data: self.data.as_ref().map(InputField::as_codegen_field), 32 skip: self.skip.unwrap_or_default(), 33 word: *self.word.unwrap_or_default(), 34 allow_unknown_fields: self.allow_unknown_fields.unwrap_or_default(), 35 } 36 } 37 from_variant(v: &syn::Variant, parent: Option<&Core>) -> Result<Self>38 pub fn from_variant(v: &syn::Variant, parent: Option<&Core>) -> Result<Self> { 39 let mut starter = (InputVariant { 40 ident: v.ident.clone(), 41 attr_name: Default::default(), 42 data: Fields::empty_from(&v.fields), 43 skip: Default::default(), 44 word: Default::default(), 45 allow_unknown_fields: None, 46 }) 47 .parse_attributes(&v.attrs)?; 48 49 starter.data.fields = match v.fields { 50 syn::Fields::Unit => vec![], 51 syn::Fields::Unnamed(ref fields) => { 52 let mut items = Vec::with_capacity(fields.unnamed.len()); 53 for item in &fields.unnamed { 54 items.push(InputField::from_field(item, parent)?); 55 } 56 57 items 58 } 59 syn::Fields::Named(ref fields) => { 60 let mut items = Vec::with_capacity(fields.named.len()); 61 for item in &fields.named { 62 items.push(InputField::from_field(item, parent)?); 63 } 64 65 items 66 } 67 }; 68 69 Ok(if let Some(p) = parent { 70 starter.with_inherited(p) 71 } else { 72 starter 73 }) 74 } 75 with_inherited(mut self, parent: &Core) -> Self76 fn with_inherited(mut self, parent: &Core) -> Self { 77 if self.attr_name.is_none() { 78 self.attr_name = Some(parent.rename_rule.apply_to_variant(self.ident.to_string())); 79 } 80 81 if self.allow_unknown_fields.is_none() { 82 self.allow_unknown_fields = Some(parent.allow_unknown_fields.unwrap_or_default()); 83 } 84 85 self 86 } 87 } 88 89 impl ParseAttribute for InputVariant { parse_nested(&mut self, mi: &syn::Meta) -> Result<()>90 fn parse_nested(&mut self, mi: &syn::Meta) -> Result<()> { 91 let path = mi.path(); 92 if path.is_ident("rename") { 93 if self.attr_name.is_some() { 94 return Err(Error::duplicate_field_path(path).with_span(mi)); 95 } 96 97 self.attr_name = FromMeta::from_meta(mi)?; 98 } else if path.is_ident("skip") { 99 if self.skip.is_some() { 100 return Err(Error::duplicate_field_path(path).with_span(mi)); 101 } 102 103 self.skip = FromMeta::from_meta(mi)?; 104 } else if path.is_ident("word") { 105 if self.word.is_some() { 106 return Err(Error::duplicate_field_path(path).with_span(mi)); 107 } 108 109 if !self.data.is_unit() { 110 let note = "`#[darling(word)]` can only be applied to a unit variant"; 111 #[cfg(feature = "diagnostics")] 112 let error = Error::unknown_field_path(path).note(note); 113 #[cfg(not(feature = "diagnostics"))] 114 let error = Error::custom(format!("Unexpected field: `word`. {}", note)); 115 116 return Err(error.with_span(mi)); 117 } 118 119 self.word = FromMeta::from_meta(mi)?; 120 } else { 121 return Err(Error::unknown_field_path(path).with_span(mi)); 122 } 123 124 Ok(()) 125 } 126 } 127