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 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 word: *self.word.unwrap_or_default(),
34 allow_unknown_fields: self.allow_unknown_fields.unwrap_or_default(),
35 }
36 }
37
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
76 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
89impl ParseAttribute for InputVariant {
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}