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