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