1use crate::fragment::{Fragment, Match, Stmts};
2use crate::internals::ast::{Container, Data, Field, Style, Variant};
3use crate::internals::{attr, replace_receiver, Ctxt, Derive};
4use crate::{bound, dummy, pretend, this};
5use proc_macro2::{Span, TokenStream};
6use quote::{quote, quote_spanned};
7use syn::spanned::Spanned;
8use syn::{parse_quote, Ident, Index, Member};
9
10pub 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
61fn 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
73struct 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
97impl Parameters {
98    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.
123    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.
130fn 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.
155fn 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
166fn 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
186fn 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
209fn 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
218fn 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
226fn 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
252fn 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
291fn 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
301fn 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
314fn 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
355fn 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
399fn 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
425fn 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
507fn 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
580fn 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
646fn 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
769fn 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
808enum TupleVariant<'a> {
809    ExternallyTagged {
810        type_name: &'a str,
811        variant_index: u32,
812        variant_name: &'a str,
813    },
814    Untagged,
815}
816
817fn 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
876enum 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
888fn 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
972fn 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
1059fn 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
1107fn 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
1173fn 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
1182fn 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
1209fn 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.
1261fn mut_if(is_mut: bool) -> Option<TokenStream> {
1262    if is_mut {
1263        Some(quote!(mut))
1264    } else {
1265        None
1266    }
1267}
1268
1269fn 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
1298fn 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
1305enum StructTrait {
1306    SerializeMap,
1307    SerializeStruct,
1308    SerializeStructVariant,
1309}
1310
1311impl StructTrait {
1312    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
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
1339enum TupleTrait {
1340    SerializeTuple,
1341    SerializeTupleStruct,
1342    SerializeTupleVariant,
1343}
1344
1345impl TupleTrait {
1346    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