1 use proc_macro2::{Span, TokenStream};
2 use syn::spanned::Spanned;
3 use syn::{self, Ident, Index, Member};
4 
5 use bound;
6 use dummy;
7 use fragment::{Fragment, Match, Stmts};
8 use internals::ast::{Container, Data, Field, Style, Variant};
9 use internals::{attr, Ctxt, Derive};
10 use pretend;
11 
expand_derive_serialize(input: &syn::DeriveInput) -> Result<TokenStream, Vec<syn::Error>>12 pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<TokenStream, Vec<syn::Error>> {
13     let ctxt = Ctxt::new();
14     let cont = match Container::from_ast(&ctxt, input, Derive::Serialize) {
15         Some(cont) => cont,
16         None => return Err(ctxt.check().unwrap_err()),
17     };
18     precondition(&ctxt, &cont);
19     ctxt.check()?;
20 
21     let ident = &cont.ident;
22     let params = Parameters::new(&cont);
23     let (impl_generics, ty_generics, where_clause) = params.generics.split_for_impl();
24     let body = Stmts(serialize_body(&cont, &params));
25     let serde = cont.attrs.serde_path();
26 
27     let impl_block = if let Some(remote) = cont.attrs.remote() {
28         let vis = &input.vis;
29         let used = pretend::pretend_used(&cont);
30         quote! {
31             impl #impl_generics #ident #ty_generics #where_clause {
32                 #vis fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> #serde::export::Result<__S::Ok, __S::Error>
33                 where
34                     __S: #serde::Serializer,
35                 {
36                     #used
37                     #body
38                 }
39             }
40         }
41     } else {
42         quote! {
43             #[automatically_derived]
44             impl #impl_generics #serde::Serialize for #ident #ty_generics #where_clause {
45                 fn serialize<__S>(&self, __serializer: __S) -> #serde::export::Result<__S::Ok, __S::Error>
46                 where
47                     __S: #serde::Serializer,
48                 {
49                     #body
50                 }
51             }
52         }
53     };
54 
55     Ok(dummy::wrap_in_const(
56         cont.attrs.custom_serde_path(),
57         "SERIALIZE",
58         ident,
59         impl_block,
60     ))
61 }
62 
precondition(cx: &Ctxt, cont: &Container)63 fn precondition(cx: &Ctxt, cont: &Container) {
64     match cont.attrs.identifier() {
65         attr::Identifier::No => {}
66         attr::Identifier::Field => {
67             cx.error_spanned_by(cont.original, "field identifiers cannot be serialized");
68         }
69         attr::Identifier::Variant => {
70             cx.error_spanned_by(cont.original, "variant identifiers cannot be serialized");
71         }
72     }
73 }
74 
75 struct Parameters {
76     /// Variable holding the value being serialized. Either `self` for local
77     /// types or `__self` for remote types.
78     self_var: Ident,
79 
80     /// Path to the type the impl is for. Either a single `Ident` for local
81     /// types or `some::remote::Ident` for remote types. Does not include
82     /// generic parameters.
83     this: syn::Path,
84 
85     /// Generics including any explicit and inferred bounds for the impl.
86     generics: syn::Generics,
87 
88     /// Type has a `serde(remote = "...")` attribute.
89     is_remote: bool,
90 }
91 
92 impl Parameters {
new(cont: &Container) -> Self93     fn new(cont: &Container) -> Self {
94         let is_remote = cont.attrs.remote().is_some();
95         let self_var = if is_remote {
96             Ident::new("__self", Span::call_site())
97         } else {
98             Ident::new("self", Span::call_site())
99         };
100 
101         let this = match cont.attrs.remote() {
102             Some(remote) => remote.clone(),
103             None => cont.ident.clone().into(),
104         };
105 
106         let generics = build_generics(cont);
107 
108         Parameters {
109             self_var: self_var,
110             this: this,
111             generics: generics,
112             is_remote: is_remote,
113         }
114     }
115 
116     /// Type name to use in error messages and `&'static str` arguments to
117     /// various Serializer methods.
type_name(&self) -> String118     fn type_name(&self) -> String {
119         self.this.segments.last().unwrap().ident.to_string()
120     }
121 }
122 
123 // All the generics in the input, plus a bound `T: Serialize` for each generic
124 // field type that will be serialized by us.
build_generics(cont: &Container) -> syn::Generics125 fn build_generics(cont: &Container) -> syn::Generics {
126     let generics = bound::without_defaults(cont.generics);
127 
128     let generics =
129         bound::with_where_predicates_from_fields(cont, &generics, attr::Field::ser_bound);
130 
131     let generics =
132         bound::with_where_predicates_from_variants(cont, &generics, attr::Variant::ser_bound);
133 
134     match cont.attrs.ser_bound() {
135         Some(predicates) => bound::with_where_predicates(&generics, predicates),
136         None => bound::with_bound(
137             cont,
138             &generics,
139             needs_serialize_bound,
140             &parse_quote!(_serde::Serialize),
141         ),
142     }
143 }
144 
145 // Fields with a `skip_serializing` or `serialize_with` attribute, or which
146 // belong to a variant with a 'skip_serializing` or `serialize_with` attribute,
147 // are not serialized by us so we do not generate a bound. Fields with a `bound`
148 // attribute specify their own bound so we do not generate one. All other fields
149 // may need a `T: Serialize` bound where T is the type of the field.
needs_serialize_bound(field: &attr::Field, variant: Option<&attr::Variant>) -> bool150 fn needs_serialize_bound(field: &attr::Field, variant: Option<&attr::Variant>) -> bool {
151     !field.skip_serializing()
152         && field.serialize_with().is_none()
153         && field.ser_bound().is_none()
154         && variant.map_or(true, |variant| {
155             !variant.skip_serializing()
156                 && variant.serialize_with().is_none()
157                 && variant.ser_bound().is_none()
158         })
159 }
160 
serialize_body(cont: &Container, params: &Parameters) -> Fragment161 fn serialize_body(cont: &Container, params: &Parameters) -> Fragment {
162     if cont.attrs.transparent() {
163         serialize_transparent(cont, params)
164     } else if let Some(type_into) = cont.attrs.type_into() {
165         serialize_into(params, type_into)
166     } else {
167         match &cont.data {
168             Data::Enum(variants) => serialize_enum(params, variants, &cont.attrs),
169             Data::Struct(Style::Struct, fields) => serialize_struct(params, fields, &cont.attrs),
170             Data::Struct(Style::Tuple, fields) => {
171                 serialize_tuple_struct(params, fields, &cont.attrs)
172             }
173             Data::Struct(Style::Newtype, fields) => {
174                 serialize_newtype_struct(params, &fields[0], &cont.attrs)
175             }
176             Data::Struct(Style::Unit, _) => serialize_unit_struct(&cont.attrs),
177         }
178     }
179 }
180 
serialize_transparent(cont: &Container, params: &Parameters) -> Fragment181 fn serialize_transparent(cont: &Container, params: &Parameters) -> Fragment {
182     let fields = match &cont.data {
183         Data::Struct(_, fields) => fields,
184         Data::Enum(_) => unreachable!(),
185     };
186 
187     let self_var = &params.self_var;
188     let transparent_field = fields.iter().find(|f| f.attrs.transparent()).unwrap();
189     let member = &transparent_field.member;
190 
191     let path = match transparent_field.attrs.serialize_with() {
192         Some(path) => quote!(#path),
193         None => {
194             let span = transparent_field.original.span();
195             quote_spanned!(span=> _serde::Serialize::serialize)
196         }
197     };
198 
199     quote_block! {
200         #path(&#self_var.#member, __serializer)
201     }
202 }
203 
serialize_into(params: &Parameters, type_into: &syn::Type) -> Fragment204 fn serialize_into(params: &Parameters, type_into: &syn::Type) -> Fragment {
205     let self_var = &params.self_var;
206     quote_block! {
207         _serde::Serialize::serialize(
208             &_serde::export::Into::<#type_into>::into(_serde::export::Clone::clone(#self_var)),
209             __serializer)
210     }
211 }
212 
serialize_unit_struct(cattrs: &attr::Container) -> Fragment213 fn serialize_unit_struct(cattrs: &attr::Container) -> Fragment {
214     let type_name = cattrs.name().serialize_name();
215 
216     quote_expr! {
217         _serde::Serializer::serialize_unit_struct(__serializer, #type_name)
218     }
219 }
220 
serialize_newtype_struct( params: &Parameters, field: &Field, cattrs: &attr::Container, ) -> Fragment221 fn serialize_newtype_struct(
222     params: &Parameters,
223     field: &Field,
224     cattrs: &attr::Container,
225 ) -> Fragment {
226     let type_name = cattrs.name().serialize_name();
227 
228     let mut field_expr = get_member(
229         params,
230         field,
231         &Member::Unnamed(Index {
232             index: 0,
233             span: Span::call_site(),
234         }),
235     );
236     if let Some(path) = field.attrs.serialize_with() {
237         field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
238     }
239 
240     let span = field.original.span();
241     let func = quote_spanned!(span=> _serde::Serializer::serialize_newtype_struct);
242     quote_expr! {
243         #func(__serializer, #type_name, #field_expr)
244     }
245 }
246 
serialize_tuple_struct( params: &Parameters, fields: &[Field], cattrs: &attr::Container, ) -> Fragment247 fn serialize_tuple_struct(
248     params: &Parameters,
249     fields: &[Field],
250     cattrs: &attr::Container,
251 ) -> Fragment {
252     let serialize_stmts =
253         serialize_tuple_struct_visitor(fields, params, false, &TupleTrait::SerializeTupleStruct);
254 
255     let type_name = cattrs.name().serialize_name();
256 
257     let mut serialized_fields = fields
258         .iter()
259         .enumerate()
260         .filter(|(_, field)| !field.attrs.skip_serializing())
261         .peekable();
262 
263     let let_mut = mut_if(serialized_fields.peek().is_some());
264 
265     let len = serialized_fields
266         .map(|(i, field)| match field.attrs.skip_serializing_if() {
267             None => quote!(1),
268             Some(path) => {
269                 let index = syn::Index {
270                     index: i as u32,
271                     span: Span::call_site(),
272                 };
273                 let field_expr = get_member(params, field, &Member::Unnamed(index));
274                 quote!(if #path(#field_expr) { 0 } else { 1 })
275             }
276         })
277         .fold(quote!(0), |sum, expr| quote!(#sum + #expr));
278 
279     quote_block! {
280         let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_struct(__serializer, #type_name, #len));
281         #(#serialize_stmts)*
282         _serde::ser::SerializeTupleStruct::end(__serde_state)
283     }
284 }
285 
serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Container) -> Fragment286 fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Container) -> Fragment {
287     assert!(fields.len() as u64 <= u64::from(u32::max_value()));
288 
289     if cattrs.has_flatten() {
290         serialize_struct_as_map(params, fields, cattrs)
291     } else {
292         serialize_struct_as_struct(params, fields, cattrs)
293     }
294 }
295 
serialize_struct_tag_field(cattrs: &attr::Container, struct_trait: &StructTrait) -> TokenStream296 fn serialize_struct_tag_field(cattrs: &attr::Container, struct_trait: &StructTrait) -> TokenStream {
297     match cattrs.tag() {
298         attr::TagType::Internal { tag } => {
299             let type_name = cattrs.name().serialize_name();
300             let func = struct_trait.serialize_field(Span::call_site());
301             quote! {
302                 try!(#func(&mut __serde_state, #tag, #type_name));
303             }
304         }
305         _ => quote! {},
306     }
307 }
308 
serialize_struct_as_struct( params: &Parameters, fields: &[Field], cattrs: &attr::Container, ) -> Fragment309 fn serialize_struct_as_struct(
310     params: &Parameters,
311     fields: &[Field],
312     cattrs: &attr::Container,
313 ) -> Fragment {
314     let serialize_fields =
315         serialize_struct_visitor(fields, params, false, &StructTrait::SerializeStruct);
316 
317     let type_name = cattrs.name().serialize_name();
318 
319     let tag_field = serialize_struct_tag_field(cattrs, &StructTrait::SerializeStruct);
320     let tag_field_exists = !tag_field.is_empty();
321 
322     let mut serialized_fields = fields
323         .iter()
324         .filter(|&field| !field.attrs.skip_serializing())
325         .peekable();
326 
327     let let_mut = mut_if(serialized_fields.peek().is_some() || tag_field_exists);
328 
329     let len = serialized_fields
330         .map(|field| match field.attrs.skip_serializing_if() {
331             None => quote!(1),
332             Some(path) => {
333                 let field_expr = get_member(params, field, &field.member);
334                 quote!(if #path(#field_expr) { 0 } else { 1 })
335             }
336         })
337         .fold(
338             quote!(#tag_field_exists as usize),
339             |sum, expr| quote!(#sum + #expr),
340         );
341 
342     quote_block! {
343         let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct(__serializer, #type_name, #len));
344         #tag_field
345         #(#serialize_fields)*
346         _serde::ser::SerializeStruct::end(__serde_state)
347     }
348 }
349 
serialize_struct_as_map( params: &Parameters, fields: &[Field], cattrs: &attr::Container, ) -> Fragment350 fn serialize_struct_as_map(
351     params: &Parameters,
352     fields: &[Field],
353     cattrs: &attr::Container,
354 ) -> Fragment {
355     let serialize_fields =
356         serialize_struct_visitor(fields, params, false, &StructTrait::SerializeMap);
357 
358     let tag_field = serialize_struct_tag_field(cattrs, &StructTrait::SerializeMap);
359     let tag_field_exists = !tag_field.is_empty();
360 
361     let mut serialized_fields = fields
362         .iter()
363         .filter(|&field| !field.attrs.skip_serializing())
364         .peekable();
365 
366     let let_mut = mut_if(serialized_fields.peek().is_some() || tag_field_exists);
367 
368     let len = if cattrs.has_flatten() {
369         quote!(_serde::export::None)
370     } else {
371         let len = serialized_fields
372             .map(|field| match field.attrs.skip_serializing_if() {
373                 None => quote!(1),
374                 Some(path) => {
375                     let field_expr = get_member(params, field, &field.member);
376                     quote!(if #path(#field_expr) { 0 } else { 1 })
377                 }
378             })
379             .fold(
380                 quote!(#tag_field_exists as usize),
381                 |sum, expr| quote!(#sum + #expr),
382             );
383         quote!(_serde::export::Some(#len))
384     };
385 
386     quote_block! {
387         let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(__serializer, #len));
388         #tag_field
389         #(#serialize_fields)*
390         _serde::ser::SerializeMap::end(__serde_state)
391     }
392 }
393 
serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Container) -> Fragment394 fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Container) -> Fragment {
395     assert!(variants.len() as u64 <= u64::from(u32::max_value()));
396 
397     let self_var = &params.self_var;
398 
399     let arms: Vec<_> = variants
400         .iter()
401         .enumerate()
402         .map(|(variant_index, variant)| {
403             serialize_variant(params, variant, variant_index as u32, cattrs)
404         })
405         .collect();
406 
407     quote_expr! {
408         match *#self_var {
409             #(#arms)*
410         }
411     }
412 }
413 
serialize_variant( params: &Parameters, variant: &Variant, variant_index: u32, cattrs: &attr::Container, ) -> TokenStream414 fn serialize_variant(
415     params: &Parameters,
416     variant: &Variant,
417     variant_index: u32,
418     cattrs: &attr::Container,
419 ) -> TokenStream {
420     let this = &params.this;
421     let variant_ident = &variant.ident;
422 
423     if variant.attrs.skip_serializing() {
424         let skipped_msg = format!(
425             "the enum variant {}::{} cannot be serialized",
426             params.type_name(),
427             variant_ident
428         );
429         let skipped_err = quote! {
430             _serde::export::Err(_serde::ser::Error::custom(#skipped_msg))
431         };
432         let fields_pat = match variant.style {
433             Style::Unit => quote!(),
434             Style::Newtype | Style::Tuple => quote!((..)),
435             Style::Struct => quote!({ .. }),
436         };
437         quote! {
438             #this::#variant_ident #fields_pat => #skipped_err,
439         }
440     } else {
441         // variant wasn't skipped
442         let case = match variant.style {
443             Style::Unit => {
444                 quote! {
445                     #this::#variant_ident
446                 }
447             }
448             Style::Newtype => {
449                 quote! {
450                     #this::#variant_ident(ref __field0)
451                 }
452             }
453             Style::Tuple => {
454                 let field_names = (0..variant.fields.len())
455                     .map(|i| Ident::new(&format!("__field{}", i), Span::call_site()));
456                 quote! {
457                     #this::#variant_ident(#(ref #field_names),*)
458                 }
459             }
460             Style::Struct => {
461                 let members = variant.fields.iter().map(|f| &f.member);
462                 quote! {
463                     #this::#variant_ident { #(ref #members),* }
464                 }
465             }
466         };
467 
468         let body = Match(match cattrs.tag() {
469             attr::TagType::External => {
470                 serialize_externally_tagged_variant(params, variant, variant_index, cattrs)
471             }
472             attr::TagType::Internal { tag } => {
473                 serialize_internally_tagged_variant(params, variant, cattrs, tag)
474             }
475             attr::TagType::Adjacent { tag, content } => {
476                 serialize_adjacently_tagged_variant(params, variant, cattrs, tag, content)
477             }
478             attr::TagType::None => serialize_untagged_variant(params, variant, cattrs),
479         });
480 
481         quote! {
482             #case => #body
483         }
484     }
485 }
486 
serialize_externally_tagged_variant( params: &Parameters, variant: &Variant, variant_index: u32, cattrs: &attr::Container, ) -> Fragment487 fn serialize_externally_tagged_variant(
488     params: &Parameters,
489     variant: &Variant,
490     variant_index: u32,
491     cattrs: &attr::Container,
492 ) -> Fragment {
493     let type_name = cattrs.name().serialize_name();
494     let variant_name = variant.attrs.name().serialize_name();
495 
496     if let Some(path) = variant.attrs.serialize_with() {
497         let ser = wrap_serialize_variant_with(params, path, variant);
498         return quote_expr! {
499             _serde::Serializer::serialize_newtype_variant(
500                 __serializer,
501                 #type_name,
502                 #variant_index,
503                 #variant_name,
504                 #ser,
505             )
506         };
507     }
508 
509     match effective_style(variant) {
510         Style::Unit => {
511             quote_expr! {
512                 _serde::Serializer::serialize_unit_variant(
513                     __serializer,
514                     #type_name,
515                     #variant_index,
516                     #variant_name,
517                 )
518             }
519         }
520         Style::Newtype => {
521             let field = &variant.fields[0];
522             let mut field_expr = quote!(__field0);
523             if let Some(path) = field.attrs.serialize_with() {
524                 field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
525             }
526 
527             let span = field.original.span();
528             let func = quote_spanned!(span=> _serde::Serializer::serialize_newtype_variant);
529             quote_expr! {
530                 #func(
531                     __serializer,
532                     #type_name,
533                     #variant_index,
534                     #variant_name,
535                     #field_expr,
536                 )
537             }
538         }
539         Style::Tuple => serialize_tuple_variant(
540             TupleVariant::ExternallyTagged {
541                 type_name: type_name,
542                 variant_index: variant_index,
543                 variant_name: variant_name,
544             },
545             params,
546             &variant.fields,
547         ),
548         Style::Struct => serialize_struct_variant(
549             StructVariant::ExternallyTagged {
550                 variant_index: variant_index,
551                 variant_name: variant_name,
552             },
553             params,
554             &variant.fields,
555             &type_name,
556         ),
557     }
558 }
559 
serialize_internally_tagged_variant( params: &Parameters, variant: &Variant, cattrs: &attr::Container, tag: &str, ) -> Fragment560 fn serialize_internally_tagged_variant(
561     params: &Parameters,
562     variant: &Variant,
563     cattrs: &attr::Container,
564     tag: &str,
565 ) -> Fragment {
566     let type_name = cattrs.name().serialize_name();
567     let variant_name = variant.attrs.name().serialize_name();
568 
569     let enum_ident_str = params.type_name();
570     let variant_ident_str = variant.ident.to_string();
571 
572     if let Some(path) = variant.attrs.serialize_with() {
573         let ser = wrap_serialize_variant_with(params, path, variant);
574         return quote_expr! {
575             _serde::private::ser::serialize_tagged_newtype(
576                 __serializer,
577                 #enum_ident_str,
578                 #variant_ident_str,
579                 #tag,
580                 #variant_name,
581                 #ser,
582             )
583         };
584     }
585 
586     match effective_style(variant) {
587         Style::Unit => {
588             quote_block! {
589                 let mut __struct = try!(_serde::Serializer::serialize_struct(
590                     __serializer, #type_name, 1));
591                 try!(_serde::ser::SerializeStruct::serialize_field(
592                     &mut __struct, #tag, #variant_name));
593                 _serde::ser::SerializeStruct::end(__struct)
594             }
595         }
596         Style::Newtype => {
597             let field = &variant.fields[0];
598             let mut field_expr = quote!(__field0);
599             if let Some(path) = field.attrs.serialize_with() {
600                 field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
601             }
602 
603             let span = field.original.span();
604             let func = quote_spanned!(span=> _serde::private::ser::serialize_tagged_newtype);
605             quote_expr! {
606                 #func(
607                     __serializer,
608                     #enum_ident_str,
609                     #variant_ident_str,
610                     #tag,
611                     #variant_name,
612                     #field_expr,
613                 )
614             }
615         }
616         Style::Struct => serialize_struct_variant(
617             StructVariant::InternallyTagged {
618                 tag: tag,
619                 variant_name: variant_name,
620             },
621             params,
622             &variant.fields,
623             &type_name,
624         ),
625         Style::Tuple => unreachable!("checked in serde_derive_internals"),
626     }
627 }
628 
serialize_adjacently_tagged_variant( params: &Parameters, variant: &Variant, cattrs: &attr::Container, tag: &str, content: &str, ) -> Fragment629 fn serialize_adjacently_tagged_variant(
630     params: &Parameters,
631     variant: &Variant,
632     cattrs: &attr::Container,
633     tag: &str,
634     content: &str,
635 ) -> Fragment {
636     let this = &params.this;
637     let type_name = cattrs.name().serialize_name();
638     let variant_name = variant.attrs.name().serialize_name();
639 
640     let inner = Stmts(if let Some(path) = variant.attrs.serialize_with() {
641         let ser = wrap_serialize_variant_with(params, path, variant);
642         quote_expr! {
643             _serde::Serialize::serialize(#ser, __serializer)
644         }
645     } else {
646         match effective_style(variant) {
647             Style::Unit => {
648                 return quote_block! {
649                     let mut __struct = try!(_serde::Serializer::serialize_struct(
650                         __serializer, #type_name, 1));
651                     try!(_serde::ser::SerializeStruct::serialize_field(
652                         &mut __struct, #tag, #variant_name));
653                     _serde::ser::SerializeStruct::end(__struct)
654                 };
655             }
656             Style::Newtype => {
657                 let field = &variant.fields[0];
658                 let mut field_expr = quote!(__field0);
659                 if let Some(path) = field.attrs.serialize_with() {
660                     field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
661                 }
662 
663                 let span = field.original.span();
664                 let func = quote_spanned!(span=> _serde::ser::SerializeStruct::serialize_field);
665                 return quote_block! {
666                     let mut __struct = try!(_serde::Serializer::serialize_struct(
667                         __serializer, #type_name, 2));
668                     try!(_serde::ser::SerializeStruct::serialize_field(
669                         &mut __struct, #tag, #variant_name));
670                     try!(#func(
671                         &mut __struct, #content, #field_expr));
672                     _serde::ser::SerializeStruct::end(__struct)
673                 };
674             }
675             Style::Tuple => {
676                 serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields)
677             }
678             Style::Struct => serialize_struct_variant(
679                 StructVariant::Untagged,
680                 params,
681                 &variant.fields,
682                 &variant_name,
683             ),
684         }
685     });
686 
687     let fields_ty = variant.fields.iter().map(|f| &f.ty);
688     let fields_ident: &Vec<_> = &match variant.style {
689         Style::Unit => {
690             if variant.attrs.serialize_with().is_some() {
691                 vec![]
692             } else {
693                 unreachable!()
694             }
695         }
696         Style::Newtype => vec![Member::Named(Ident::new("__field0", Span::call_site()))],
697         Style::Tuple => (0..variant.fields.len())
698             .map(|i| Member::Named(Ident::new(&format!("__field{}", i), Span::call_site())))
699             .collect(),
700         Style::Struct => variant.fields.iter().map(|f| f.member.clone()).collect(),
701     };
702 
703     let (_, ty_generics, where_clause) = params.generics.split_for_impl();
704 
705     let wrapper_generics = if fields_ident.is_empty() {
706         params.generics.clone()
707     } else {
708         bound::with_lifetime_bound(&params.generics, "'__a")
709     };
710     let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
711 
712     quote_block! {
713         struct __AdjacentlyTagged #wrapper_generics #where_clause {
714             data: (#(&'__a #fields_ty,)*),
715             phantom: _serde::export::PhantomData<#this #ty_generics>,
716         }
717 
718         impl #wrapper_impl_generics _serde::Serialize for __AdjacentlyTagged #wrapper_ty_generics #where_clause {
719             fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
720             where
721                 __S: _serde::Serializer,
722             {
723                 // Elements that have skip_serializing will be unused.
724                 #[allow(unused_variables)]
725                 let (#(#fields_ident,)*) = self.data;
726                 #inner
727             }
728         }
729 
730         let mut __struct = try!(_serde::Serializer::serialize_struct(
731             __serializer, #type_name, 2));
732         try!(_serde::ser::SerializeStruct::serialize_field(
733             &mut __struct, #tag, #variant_name));
734         try!(_serde::ser::SerializeStruct::serialize_field(
735             &mut __struct, #content, &__AdjacentlyTagged {
736                 data: (#(#fields_ident,)*),
737                 phantom: _serde::export::PhantomData::<#this #ty_generics>,
738             }));
739         _serde::ser::SerializeStruct::end(__struct)
740     }
741 }
742 
serialize_untagged_variant( params: &Parameters, variant: &Variant, cattrs: &attr::Container, ) -> Fragment743 fn serialize_untagged_variant(
744     params: &Parameters,
745     variant: &Variant,
746     cattrs: &attr::Container,
747 ) -> Fragment {
748     if let Some(path) = variant.attrs.serialize_with() {
749         let ser = wrap_serialize_variant_with(params, path, variant);
750         return quote_expr! {
751             _serde::Serialize::serialize(#ser, __serializer)
752         };
753     }
754 
755     match effective_style(variant) {
756         Style::Unit => {
757             quote_expr! {
758                 _serde::Serializer::serialize_unit(__serializer)
759             }
760         }
761         Style::Newtype => {
762             let field = &variant.fields[0];
763             let mut field_expr = quote!(__field0);
764             if let Some(path) = field.attrs.serialize_with() {
765                 field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
766             }
767 
768             let span = field.original.span();
769             let func = quote_spanned!(span=> _serde::Serialize::serialize);
770             quote_expr! {
771                 #func(#field_expr, __serializer)
772             }
773         }
774         Style::Tuple => serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields),
775         Style::Struct => {
776             let type_name = cattrs.name().serialize_name();
777             serialize_struct_variant(StructVariant::Untagged, params, &variant.fields, &type_name)
778         }
779     }
780 }
781 
782 enum TupleVariant {
783     ExternallyTagged {
784         type_name: String,
785         variant_index: u32,
786         variant_name: String,
787     },
788     Untagged,
789 }
790 
serialize_tuple_variant( context: TupleVariant, params: &Parameters, fields: &[Field], ) -> Fragment791 fn serialize_tuple_variant(
792     context: TupleVariant,
793     params: &Parameters,
794     fields: &[Field],
795 ) -> Fragment {
796     let tuple_trait = match context {
797         TupleVariant::ExternallyTagged { .. } => TupleTrait::SerializeTupleVariant,
798         TupleVariant::Untagged => TupleTrait::SerializeTuple,
799     };
800 
801     let serialize_stmts = serialize_tuple_struct_visitor(fields, params, true, &tuple_trait);
802 
803     let mut serialized_fields = fields
804         .iter()
805         .enumerate()
806         .filter(|(_, field)| !field.attrs.skip_serializing())
807         .peekable();
808 
809     let let_mut = mut_if(serialized_fields.peek().is_some());
810 
811     let len = serialized_fields
812         .map(|(i, field)| match field.attrs.skip_serializing_if() {
813             None => quote!(1),
814             Some(path) => {
815                 let field_expr = Ident::new(&format!("__field{}", i), Span::call_site());
816                 quote!(if #path(#field_expr) { 0 } else { 1 })
817             }
818         })
819         .fold(quote!(0), |sum, expr| quote!(#sum + #expr));
820 
821     match context {
822         TupleVariant::ExternallyTagged {
823             type_name,
824             variant_index,
825             variant_name,
826         } => {
827             quote_block! {
828                 let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_variant(
829                     __serializer,
830                     #type_name,
831                     #variant_index,
832                     #variant_name,
833                     #len));
834                 #(#serialize_stmts)*
835                 _serde::ser::SerializeTupleVariant::end(__serde_state)
836             }
837         }
838         TupleVariant::Untagged => {
839             quote_block! {
840                 let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple(
841                     __serializer,
842                     #len));
843                 #(#serialize_stmts)*
844                 _serde::ser::SerializeTuple::end(__serde_state)
845             }
846         }
847     }
848 }
849 
850 enum StructVariant<'a> {
851     ExternallyTagged {
852         variant_index: u32,
853         variant_name: String,
854     },
855     InternallyTagged {
856         tag: &'a str,
857         variant_name: String,
858     },
859     Untagged,
860 }
861 
serialize_struct_variant<'a>( context: StructVariant<'a>, params: &Parameters, fields: &[Field], name: &str, ) -> Fragment862 fn serialize_struct_variant<'a>(
863     context: StructVariant<'a>,
864     params: &Parameters,
865     fields: &[Field],
866     name: &str,
867 ) -> Fragment {
868     if fields.iter().any(|field| field.attrs.flatten()) {
869         return serialize_struct_variant_with_flatten(context, params, fields, name);
870     }
871 
872     let struct_trait = match context {
873         StructVariant::ExternallyTagged { .. } => StructTrait::SerializeStructVariant,
874         StructVariant::InternallyTagged { .. } | StructVariant::Untagged => {
875             StructTrait::SerializeStruct
876         }
877     };
878 
879     let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait);
880 
881     let mut serialized_fields = fields
882         .iter()
883         .filter(|&field| !field.attrs.skip_serializing())
884         .peekable();
885 
886     let let_mut = mut_if(serialized_fields.peek().is_some());
887 
888     let len = serialized_fields
889         .map(|field| {
890             let member = &field.member;
891 
892             match field.attrs.skip_serializing_if() {
893                 Some(path) => quote!(if #path(#member) { 0 } else { 1 }),
894                 None => quote!(1),
895             }
896         })
897         .fold(quote!(0), |sum, expr| quote!(#sum + #expr));
898 
899     match context {
900         StructVariant::ExternallyTagged {
901             variant_index,
902             variant_name,
903         } => {
904             quote_block! {
905                 let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct_variant(
906                     __serializer,
907                     #name,
908                     #variant_index,
909                     #variant_name,
910                     #len,
911                 ));
912                 #(#serialize_fields)*
913                 _serde::ser::SerializeStructVariant::end(__serde_state)
914             }
915         }
916         StructVariant::InternallyTagged { tag, variant_name } => {
917             quote_block! {
918                 let mut __serde_state = try!(_serde::Serializer::serialize_struct(
919                     __serializer,
920                     #name,
921                     #len + 1,
922                 ));
923                 try!(_serde::ser::SerializeStruct::serialize_field(
924                     &mut __serde_state,
925                     #tag,
926                     #variant_name,
927                 ));
928                 #(#serialize_fields)*
929                 _serde::ser::SerializeStruct::end(__serde_state)
930             }
931         }
932         StructVariant::Untagged => {
933             quote_block! {
934                 let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct(
935                     __serializer,
936                     #name,
937                     #len,
938                 ));
939                 #(#serialize_fields)*
940                 _serde::ser::SerializeStruct::end(__serde_state)
941             }
942         }
943     }
944 }
945 
serialize_struct_variant_with_flatten<'a>( context: StructVariant<'a>, params: &Parameters, fields: &[Field], name: &str, ) -> Fragment946 fn serialize_struct_variant_with_flatten<'a>(
947     context: StructVariant<'a>,
948     params: &Parameters,
949     fields: &[Field],
950     name: &str,
951 ) -> Fragment {
952     let struct_trait = StructTrait::SerializeMap;
953     let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait);
954 
955     let mut serialized_fields = fields
956         .iter()
957         .filter(|&field| !field.attrs.skip_serializing())
958         .peekable();
959 
960     let let_mut = mut_if(serialized_fields.peek().is_some());
961 
962     match context {
963         StructVariant::ExternallyTagged {
964             variant_index,
965             variant_name,
966         } => {
967             let this = &params.this;
968             let fields_ty = fields.iter().map(|f| &f.ty);
969             let members = &fields.iter().map(|f| &f.member).collect::<Vec<_>>();
970 
971             let (_, ty_generics, where_clause) = params.generics.split_for_impl();
972             let wrapper_generics = bound::with_lifetime_bound(&params.generics, "'__a");
973             let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
974 
975             quote_block! {
976                 struct __EnumFlatten #wrapper_generics #where_clause {
977                     data: (#(&'__a #fields_ty,)*),
978                     phantom: _serde::export::PhantomData<#this #ty_generics>,
979                 }
980 
981                 impl #wrapper_impl_generics _serde::Serialize for __EnumFlatten #wrapper_ty_generics #where_clause {
982                     fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
983                     where
984                         __S: _serde::Serializer,
985                     {
986                         let (#(#members,)*) = self.data;
987                         let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
988                             __serializer,
989                             _serde::export::None));
990                         #(#serialize_fields)*
991                         _serde::ser::SerializeMap::end(__serde_state)
992                     }
993                 }
994 
995                 _serde::Serializer::serialize_newtype_variant(
996                     __serializer,
997                     #name,
998                     #variant_index,
999                     #variant_name,
1000                     &__EnumFlatten {
1001                         data: (#(#members,)*),
1002                         phantom: _serde::export::PhantomData::<#this #ty_generics>,
1003                     })
1004             }
1005         }
1006         StructVariant::InternallyTagged { tag, variant_name } => {
1007             quote_block! {
1008                 let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
1009                     __serializer,
1010                     _serde::export::None));
1011                 try!(_serde::ser::SerializeMap::serialize_entry(
1012                     &mut __serde_state,
1013                     #tag,
1014                     #variant_name,
1015                 ));
1016                 #(#serialize_fields)*
1017                 _serde::ser::SerializeMap::end(__serde_state)
1018             }
1019         }
1020         StructVariant::Untagged => {
1021             quote_block! {
1022                 let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
1023                     __serializer,
1024                     _serde::export::None));
1025                 #(#serialize_fields)*
1026                 _serde::ser::SerializeMap::end(__serde_state)
1027             }
1028         }
1029     }
1030 }
1031 
serialize_tuple_struct_visitor( fields: &[Field], params: &Parameters, is_enum: bool, tuple_trait: &TupleTrait, ) -> Vec<TokenStream>1032 fn serialize_tuple_struct_visitor(
1033     fields: &[Field],
1034     params: &Parameters,
1035     is_enum: bool,
1036     tuple_trait: &TupleTrait,
1037 ) -> Vec<TokenStream> {
1038     fields
1039         .iter()
1040         .enumerate()
1041         .filter(|(_, field)| !field.attrs.skip_serializing())
1042         .map(|(i, field)| {
1043             let mut field_expr = if is_enum {
1044                 let id = Ident::new(&format!("__field{}", i), Span::call_site());
1045                 quote!(#id)
1046             } else {
1047                 get_member(
1048                     params,
1049                     field,
1050                     &Member::Unnamed(Index {
1051                         index: i as u32,
1052                         span: Span::call_site(),
1053                     }),
1054                 )
1055             };
1056 
1057             let skip = field
1058                 .attrs
1059                 .skip_serializing_if()
1060                 .map(|path| quote!(#path(#field_expr)));
1061 
1062             if let Some(path) = field.attrs.serialize_with() {
1063                 field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
1064             }
1065 
1066             let span = field.original.span();
1067             let func = tuple_trait.serialize_element(span);
1068             let ser = quote! {
1069                 try!(#func(&mut __serde_state, #field_expr));
1070             };
1071 
1072             match skip {
1073                 None => ser,
1074                 Some(skip) => quote!(if !#skip { #ser }),
1075             }
1076         })
1077         .collect()
1078 }
1079 
serialize_struct_visitor( fields: &[Field], params: &Parameters, is_enum: bool, struct_trait: &StructTrait, ) -> Vec<TokenStream>1080 fn serialize_struct_visitor(
1081     fields: &[Field],
1082     params: &Parameters,
1083     is_enum: bool,
1084     struct_trait: &StructTrait,
1085 ) -> Vec<TokenStream> {
1086     fields
1087         .iter()
1088         .filter(|&field| !field.attrs.skip_serializing())
1089         .map(|field| {
1090             let member = &field.member;
1091 
1092             let mut field_expr = if is_enum {
1093                 quote!(#member)
1094             } else {
1095                 get_member(params, field, &member)
1096             };
1097 
1098             let key_expr = field.attrs.name().serialize_name();
1099 
1100             let skip = field
1101                 .attrs
1102                 .skip_serializing_if()
1103                 .map(|path| quote!(#path(#field_expr)));
1104 
1105             if let Some(path) = field.attrs.serialize_with() {
1106                 field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
1107             }
1108 
1109             let span = field.original.span();
1110             let ser = if field.attrs.flatten() {
1111                 let func = quote_spanned!(span=> _serde::Serialize::serialize);
1112                 quote! {
1113                     try!(#func(&#field_expr, _serde::private::ser::FlatMapSerializer(&mut __serde_state)));
1114                 }
1115             } else {
1116                 let func = struct_trait.serialize_field(span);
1117                 quote! {
1118                     try!(#func(&mut __serde_state, #key_expr, #field_expr));
1119                 }
1120             };
1121 
1122             match skip {
1123                 None => ser,
1124                 Some(skip) => {
1125                     if let Some(skip_func) = struct_trait.skip_field(span) {
1126                         quote! {
1127                             if !#skip {
1128                                 #ser
1129                             } else {
1130                                 try!(#skip_func(&mut __serde_state, #key_expr));
1131                             }
1132                         }
1133                     } else {
1134                         quote! {
1135                             if !#skip {
1136                                 #ser
1137                             }
1138                         }
1139                     }
1140                 }
1141             }
1142         })
1143         .collect()
1144 }
1145 
wrap_serialize_field_with( params: &Parameters, field_ty: &syn::Type, serialize_with: &syn::ExprPath, field_expr: &TokenStream, ) -> TokenStream1146 fn wrap_serialize_field_with(
1147     params: &Parameters,
1148     field_ty: &syn::Type,
1149     serialize_with: &syn::ExprPath,
1150     field_expr: &TokenStream,
1151 ) -> TokenStream {
1152     wrap_serialize_with(params, serialize_with, &[field_ty], &[quote!(#field_expr)])
1153 }
1154 
wrap_serialize_variant_with( params: &Parameters, serialize_with: &syn::ExprPath, variant: &Variant, ) -> TokenStream1155 fn wrap_serialize_variant_with(
1156     params: &Parameters,
1157     serialize_with: &syn::ExprPath,
1158     variant: &Variant,
1159 ) -> TokenStream {
1160     let field_tys: Vec<_> = variant.fields.iter().map(|field| field.ty).collect();
1161     let field_exprs: Vec<_> = variant
1162         .fields
1163         .iter()
1164         .map(|field| {
1165             let id = match &field.member {
1166                 Member::Named(ident) => ident.clone(),
1167                 Member::Unnamed(member) => {
1168                     Ident::new(&format!("__field{}", member.index), Span::call_site())
1169                 }
1170             };
1171             quote!(#id)
1172         })
1173         .collect();
1174     wrap_serialize_with(
1175         params,
1176         serialize_with,
1177         field_tys.as_slice(),
1178         field_exprs.as_slice(),
1179     )
1180 }
1181 
wrap_serialize_with( params: &Parameters, serialize_with: &syn::ExprPath, field_tys: &[&syn::Type], field_exprs: &[TokenStream], ) -> TokenStream1182 fn wrap_serialize_with(
1183     params: &Parameters,
1184     serialize_with: &syn::ExprPath,
1185     field_tys: &[&syn::Type],
1186     field_exprs: &[TokenStream],
1187 ) -> TokenStream {
1188     let this = &params.this;
1189     let (_, ty_generics, where_clause) = params.generics.split_for_impl();
1190 
1191     let wrapper_generics = if field_exprs.is_empty() {
1192         params.generics.clone()
1193     } else {
1194         bound::with_lifetime_bound(&params.generics, "'__a")
1195     };
1196     let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
1197 
1198     let field_access = (0..field_exprs.len()).map(|n| {
1199         Member::Unnamed(Index {
1200             index: n as u32,
1201             span: Span::call_site(),
1202         })
1203     });
1204 
1205     quote!({
1206         struct __SerializeWith #wrapper_impl_generics #where_clause {
1207             values: (#(&'__a #field_tys, )*),
1208             phantom: _serde::export::PhantomData<#this #ty_generics>,
1209         }
1210 
1211         impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause {
1212             fn serialize<__S>(&self, __s: __S) -> _serde::export::Result<__S::Ok, __S::Error>
1213             where
1214                 __S: _serde::Serializer,
1215             {
1216                 #serialize_with(#(self.values.#field_access, )* __s)
1217             }
1218         }
1219 
1220         &__SerializeWith {
1221             values: (#(#field_exprs, )*),
1222             phantom: _serde::export::PhantomData::<#this #ty_generics>,
1223         }
1224     })
1225 }
1226 
1227 // Serialization of an empty struct results in code like:
1228 //
1229 //     let mut __serde_state = try!(serializer.serialize_struct("S", 0));
1230 //     _serde::ser::SerializeStruct::end(__serde_state)
1231 //
1232 // where we want to omit the `mut` to avoid a warning.
mut_if(is_mut: bool) -> Option<TokenStream>1233 fn mut_if(is_mut: bool) -> Option<TokenStream> {
1234     if is_mut {
1235         Some(quote!(mut))
1236     } else {
1237         None
1238     }
1239 }
1240 
get_member(params: &Parameters, field: &Field, member: &Member) -> TokenStream1241 fn get_member(params: &Parameters, field: &Field, member: &Member) -> TokenStream {
1242     let self_var = &params.self_var;
1243     match (params.is_remote, field.attrs.getter()) {
1244         (false, None) => quote!(&#self_var.#member),
1245         (true, None) => {
1246             let inner = quote!(&#self_var.#member);
1247             let ty = field.ty;
1248             quote!(_serde::private::ser::constrain::<#ty>(#inner))
1249         }
1250         (true, Some(getter)) => {
1251             let ty = field.ty;
1252             quote!(_serde::private::ser::constrain::<#ty>(&#getter(#self_var)))
1253         }
1254         (false, Some(_)) => {
1255             unreachable!("getter is only allowed for remote impls");
1256         }
1257     }
1258 }
1259 
effective_style(variant: &Variant) -> Style1260 fn effective_style(variant: &Variant) -> Style {
1261     match variant.style {
1262         Style::Newtype if variant.fields[0].attrs.skip_serializing() => Style::Unit,
1263         other => other,
1264     }
1265 }
1266 
1267 enum StructTrait {
1268     SerializeMap,
1269     SerializeStruct,
1270     SerializeStructVariant,
1271 }
1272 
1273 impl StructTrait {
serialize_field(&self, span: Span) -> TokenStream1274     fn serialize_field(&self, span: Span) -> TokenStream {
1275         match *self {
1276             StructTrait::SerializeMap => {
1277                 quote_spanned!(span=> _serde::ser::SerializeMap::serialize_entry)
1278             }
1279             StructTrait::SerializeStruct => {
1280                 quote_spanned!(span=> _serde::ser::SerializeStruct::serialize_field)
1281             }
1282             StructTrait::SerializeStructVariant => {
1283                 quote_spanned!(span=> _serde::ser::SerializeStructVariant::serialize_field)
1284             }
1285         }
1286     }
1287 
skip_field(&self, span: Span) -> Option<TokenStream>1288     fn skip_field(&self, span: Span) -> Option<TokenStream> {
1289         match *self {
1290             StructTrait::SerializeMap => None,
1291             StructTrait::SerializeStruct => {
1292                 Some(quote_spanned!(span=> _serde::ser::SerializeStruct::skip_field))
1293             }
1294             StructTrait::SerializeStructVariant => {
1295                 Some(quote_spanned!(span=> _serde::ser::SerializeStructVariant::skip_field))
1296             }
1297         }
1298     }
1299 }
1300 
1301 enum TupleTrait {
1302     SerializeTuple,
1303     SerializeTupleStruct,
1304     SerializeTupleVariant,
1305 }
1306 
1307 impl TupleTrait {
serialize_element(&self, span: Span) -> TokenStream1308     fn serialize_element(&self, span: Span) -> TokenStream {
1309         match *self {
1310             TupleTrait::SerializeTuple => {
1311                 quote_spanned!(span=> _serde::ser::SerializeTuple::serialize_element)
1312             }
1313             TupleTrait::SerializeTupleStruct => {
1314                 quote_spanned!(span=> _serde::ser::SerializeTupleStruct::serialize_field)
1315             }
1316             TupleTrait::SerializeTupleVariant => {
1317                 quote_spanned!(span=> _serde::ser::SerializeTupleVariant::serialize_field)
1318             }
1319         }
1320     }
1321 }
1322