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