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