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