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