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