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