1 //! A Serde ast, parsed from the Syn ast and ready to generate Rust code.
2 
3 use internals::attr;
4 use internals::check;
5 use internals::{Ctxt, Derive};
6 use syn;
7 use syn::punctuated::Punctuated;
8 
9 /// A source data structure annotated with `#[derive(Serialize)]` and/or `#[derive(Deserialize)]`,
10 /// parsed into an internal representation.
11 pub struct Container<'a> {
12     /// The struct or enum name (without generics).
13     pub ident: syn::Ident,
14     /// Attributes on the structure, parsed for Serde.
15     pub attrs: attr::Container,
16     /// The contents of the struct or enum.
17     pub data: Data<'a>,
18     /// Any generics on the struct or enum.
19     pub generics: &'a syn::Generics,
20     /// Original input.
21     pub original: &'a syn::DeriveInput,
22 }
23 
24 /// The fields of a struct or enum.
25 ///
26 /// Analagous to `syn::Data`.
27 pub enum Data<'a> {
28     Enum(Vec<Variant<'a>>),
29     Struct(Style, Vec<Field<'a>>),
30 }
31 
32 /// A variant of an enum.
33 pub struct Variant<'a> {
34     pub ident: syn::Ident,
35     pub attrs: attr::Variant,
36     pub style: Style,
37     pub fields: Vec<Field<'a>>,
38     pub original: &'a syn::Variant,
39 }
40 
41 /// A field of a struct.
42 pub struct Field<'a> {
43     pub member: syn::Member,
44     pub attrs: attr::Field,
45     pub ty: &'a syn::Type,
46     pub original: &'a syn::Field,
47 }
48 
49 #[derive(Copy, Clone)]
50 pub enum Style {
51     /// Named fields.
52     Struct,
53     /// Many unnamed fields.
54     Tuple,
55     /// One unnamed field.
56     Newtype,
57     /// No fields.
58     Unit,
59 }
60 
61 impl<'a> Container<'a> {
62     /// Convert the raw Syn ast into a parsed container object, collecting errors in `cx`.
from_ast( cx: &Ctxt, item: &'a syn::DeriveInput, derive: Derive, ) -> Option<Container<'a>>63     pub fn from_ast(
64         cx: &Ctxt,
65         item: &'a syn::DeriveInput,
66         derive: Derive,
67     ) -> Option<Container<'a>> {
68         let mut attrs = attr::Container::from_ast(cx, item);
69 
70         let mut data = match item.data {
71             syn::Data::Enum(ref data) => {
72                 Data::Enum(enum_from_ast(cx, &data.variants, attrs.default()))
73             }
74             syn::Data::Struct(ref data) => {
75                 let (style, fields) = struct_from_ast(cx, &data.fields, None, attrs.default());
76                 Data::Struct(style, fields)
77             }
78             syn::Data::Union(_) => {
79                 cx.error_spanned_by(item, "Serde does not support derive for unions");
80                 return None;
81             }
82         };
83 
84         let mut has_flatten = false;
85         match data {
86             Data::Enum(ref mut variants) => {
87                 for variant in variants {
88                     variant.attrs.rename_by_rules(attrs.rename_all_rules());
89                     for field in &mut variant.fields {
90                         if field.attrs.flatten() {
91                             has_flatten = true;
92                         }
93                         field
94                             .attrs
95                             .rename_by_rules(variant.attrs.rename_all_rules());
96                     }
97                 }
98             }
99             Data::Struct(_, ref mut fields) => {
100                 for field in fields {
101                     if field.attrs.flatten() {
102                         has_flatten = true;
103                     }
104                     field.attrs.rename_by_rules(attrs.rename_all_rules());
105                 }
106             }
107         }
108 
109         if has_flatten {
110             attrs.mark_has_flatten();
111         }
112 
113         let mut item = Container {
114             ident: item.ident.clone(),
115             attrs: attrs,
116             data: data,
117             generics: &item.generics,
118             original: item,
119         };
120         check::check(cx, &mut item, derive);
121         Some(item)
122     }
123 }
124 
125 impl<'a> Data<'a> {
all_fields(&'a self) -> Box<Iterator<Item = &'a Field<'a>> + 'a>126     pub fn all_fields(&'a self) -> Box<Iterator<Item = &'a Field<'a>> + 'a> {
127         match *self {
128             Data::Enum(ref variants) => {
129                 Box::new(variants.iter().flat_map(|variant| variant.fields.iter()))
130             }
131             Data::Struct(_, ref fields) => Box::new(fields.iter()),
132         }
133     }
134 
has_getter(&self) -> bool135     pub fn has_getter(&self) -> bool {
136         self.all_fields().any(|f| f.attrs.getter().is_some())
137     }
138 }
139 
enum_from_ast<'a>( cx: &Ctxt, variants: &'a Punctuated<syn::Variant, Token![,]>, container_default: &attr::Default, ) -> Vec<Variant<'a>>140 fn enum_from_ast<'a>(
141     cx: &Ctxt,
142     variants: &'a Punctuated<syn::Variant, Token![,]>,
143     container_default: &attr::Default,
144 ) -> Vec<Variant<'a>> {
145     variants
146         .iter()
147         .map(|variant| {
148             let attrs = attr::Variant::from_ast(cx, variant);
149             let (style, fields) =
150                 struct_from_ast(cx, &variant.fields, Some(&attrs), container_default);
151             Variant {
152                 ident: variant.ident.clone(),
153                 attrs: attrs,
154                 style: style,
155                 fields: fields,
156                 original: variant,
157             }
158         })
159         .collect()
160 }
161 
struct_from_ast<'a>( cx: &Ctxt, fields: &'a syn::Fields, attrs: Option<&attr::Variant>, container_default: &attr::Default, ) -> (Style, Vec<Field<'a>>)162 fn struct_from_ast<'a>(
163     cx: &Ctxt,
164     fields: &'a syn::Fields,
165     attrs: Option<&attr::Variant>,
166     container_default: &attr::Default,
167 ) -> (Style, Vec<Field<'a>>) {
168     match *fields {
169         syn::Fields::Named(ref fields) => (
170             Style::Struct,
171             fields_from_ast(cx, &fields.named, attrs, container_default),
172         ),
173         syn::Fields::Unnamed(ref fields) if fields.unnamed.len() == 1 => (
174             Style::Newtype,
175             fields_from_ast(cx, &fields.unnamed, attrs, container_default),
176         ),
177         syn::Fields::Unnamed(ref fields) => (
178             Style::Tuple,
179             fields_from_ast(cx, &fields.unnamed, attrs, container_default),
180         ),
181         syn::Fields::Unit => (Style::Unit, Vec::new()),
182     }
183 }
184 
fields_from_ast<'a>( cx: &Ctxt, fields: &'a Punctuated<syn::Field, Token![,]>, attrs: Option<&attr::Variant>, container_default: &attr::Default, ) -> Vec<Field<'a>>185 fn fields_from_ast<'a>(
186     cx: &Ctxt,
187     fields: &'a Punctuated<syn::Field, Token![,]>,
188     attrs: Option<&attr::Variant>,
189     container_default: &attr::Default,
190 ) -> Vec<Field<'a>> {
191     fields
192         .iter()
193         .enumerate()
194         .map(|(i, field)| Field {
195             member: match field.ident {
196                 Some(ref ident) => syn::Member::Named(ident.clone()),
197                 None => syn::Member::Unnamed(i.into()),
198             },
199             attrs: attr::Field::from_ast(cx, i, field, attrs, container_default),
200             ty: &field.ty,
201             original: field,
202         })
203         .collect()
204 }
205