1use std::borrow::Cow;
2
3use syn::{parse_quote_spanned, spanned::Spanned};
4
5use crate::codegen;
6use crate::options::{Core, DefaultExpression, ParseAttribute};
7use crate::util::SpannedValue;
8use crate::{Error, FromMeta, Result};
9
10#[derive(Debug, Clone)]
11pub struct InputField {
12 pub ident: syn::Ident,
13 pub attr_name: Option<String>,
14 pub ty: syn::Type,
15 pub default: Option<DefaultExpression>,
16 pub with: Option<syn::Path>,
17
18 /// If `true`, generated code will not look for this field in the input meta item,
19 /// instead always falling back to either `InputField::default` or `Default::default`.
20 pub skip: Option<SpannedValue<bool>>,
21 pub post_transform: Option<codegen::PostfixTransform>,
22 pub multiple: Option<bool>,
23}
24
25impl InputField {
26 /// Generate a view into this field that can be used for code generation.
27 pub fn as_codegen_field(&self) -> codegen::Field<'_> {
28 codegen::Field {
29 ident: &self.ident,
30 name_in_attr: self
31 .attr_name
32 .as_ref()
33 .map_or_else(|| Cow::Owned(self.ident.to_string()), Cow::Borrowed),
34 ty: &self.ty,
35 default_expression: self.as_codegen_default(),
36 with_path: self.with.as_ref().map_or_else(
37 || {
38 Cow::Owned(
39 parse_quote_spanned!(self.ty.span()=> ::darling::FromMeta::from_meta),
40 )
41 },
42 Cow::Borrowed,
43 ),
44 skip: *self.skip.unwrap_or_default(),
45 post_transform: self.post_transform.as_ref(),
46 multiple: self.multiple.unwrap_or_default(),
47 }
48 }
49
50 /// Generate a codegen::DefaultExpression for this field. This requires the field name
51 /// in the `Inherit` case.
52 fn as_codegen_default(&self) -> Option<codegen::DefaultExpression<'_>> {
53 self.default.as_ref().map(|expr| match *expr {
54 DefaultExpression::Explicit(ref path) => codegen::DefaultExpression::Explicit(path),
55 DefaultExpression::Inherit => codegen::DefaultExpression::Inherit(&self.ident),
56 DefaultExpression::Trait { span } => codegen::DefaultExpression::Trait { span },
57 })
58 }
59
60 fn new(ident: syn::Ident, ty: syn::Type) -> Self {
61 InputField {
62 ident,
63 ty,
64 attr_name: None,
65 default: None,
66 with: None,
67 skip: None,
68 post_transform: Default::default(),
69 multiple: None,
70 }
71 }
72
73 pub fn from_field(f: &syn::Field, parent: Option<&Core>) -> Result<Self> {
74 let ident = f
75 .ident
76 .clone()
77 .unwrap_or_else(|| syn::Ident::new("__unnamed", ::proc_macro2::Span::call_site()));
78 let ty = f.ty.clone();
79 let base = Self::new(ident, ty).parse_attributes(&f.attrs)?;
80
81 Ok(if let Some(container) = parent {
82 base.with_inherited(container)
83 } else {
84 base
85 })
86 }
87
88 /// Apply inherited settings from the container. This is done _after_ parsing
89 /// to ensure deference to explicit field-level settings.
90 fn with_inherited(mut self, parent: &Core) -> Self {
91 // explicit renamings take precedence over rename rules on the container,
92 // but in the absence of an explicit name we apply the rule.
93 if self.attr_name.is_none() {
94 self.attr_name = Some(parent.rename_rule.apply_to_field(self.ident.to_string()));
95 }
96
97 // Determine the default expression for this field, based on three pieces of information:
98 // 1. Will we look for this field in the attribute?
99 // 1. Is there a locally-defined default?
100 // 1. Did the parent define a default?
101 self.default = match (&self.skip, self.default.is_some(), parent.default.is_some()) {
102 // If we have a default, use it.
103 (_, true, _) => self.default,
104
105 // If there isn't an explicit default but the struct sets a default, we'll
106 // inherit from that.
107 (_, false, true) => Some(DefaultExpression::Inherit),
108
109 // If we're skipping the field and no defaults have been expressed then we should
110 // use the ::darling::export::Default trait, and set the span to the skip keyword
111 // so that an error caused by the skipped field's type not implementing `Default`
112 // will correctly identify why darling is trying to use `Default`.
113 (Some(v), false, false) if **v => Some(DefaultExpression::Trait { span: v.span() }),
114
115 // If we don't have or need a default, then leave it blank.
116 (_, false, false) => None,
117 };
118
119 self
120 }
121}
122
123impl ParseAttribute for InputField {
124 fn parse_nested(&mut self, mi: &syn::Meta) -> Result<()> {
125 let path = mi.path();
126
127 if path.is_ident("rename") {
128 if self.attr_name.is_some() {
129 return Err(Error::duplicate_field_path(path).with_span(mi));
130 }
131
132 self.attr_name = FromMeta::from_meta(mi)?;
133 } else if path.is_ident("default") {
134 if self.default.is_some() {
135 return Err(Error::duplicate_field_path(path).with_span(mi));
136 }
137 self.default = FromMeta::from_meta(mi)?;
138 } else if path.is_ident("with") {
139 if self.with.is_some() {
140 return Err(Error::duplicate_field_path(path).with_span(mi));
141 }
142
143 self.with = Some(FromMeta::from_meta(mi)?);
144 } else if path.is_ident("skip") {
145 if self.skip.is_some() {
146 return Err(Error::duplicate_field_path(path).with_span(mi));
147 }
148
149 self.skip = FromMeta::from_meta(mi)?;
150 } else if path.is_ident("map") || path.is_ident("and_then") {
151 let transformer = path.get_ident().unwrap().clone();
152 if let Some(post_transform) = &self.post_transform {
153 if transformer == post_transform.transformer {
154 return Err(Error::duplicate_field_path(path).with_span(mi));
155 } else {
156 return Err(Error::custom(format!(
157 "Options `{}` and `{}` are mutually exclusive",
158 transformer, post_transform.transformer
159 ))
160 .with_span(mi));
161 }
162 }
163
164 self.post_transform = Some(codegen::PostfixTransform::new(
165 transformer,
166 FromMeta::from_meta(mi)?,
167 ));
168 } else if path.is_ident("multiple") {
169 if self.multiple.is_some() {
170 return Err(Error::duplicate_field_path(path).with_span(mi));
171 }
172
173 self.multiple = FromMeta::from_meta(mi)?;
174 } else {
175 return Err(Error::unknown_field_path(path).with_span(mi));
176 }
177
178 Ok(())
179 }
180}
181