serde_derive/
ser.rs

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!(
293        fields.len() as u64 <= u64::from(u32::MAX),
294        "too many fields in {}: {}, maximum supported count is {}",
295        cattrs.name().serialize_name(),
296        fields.len(),
297        u32::MAX,
298    );
299
300    let has_non_skipped_flatten = fields
301        .iter()
302        .any(|field| field.attrs.flatten() && !field.attrs.skip_serializing());
303    if has_non_skipped_flatten {
304        serialize_struct_as_map(params, fields, cattrs)
305    } else {
306        serialize_struct_as_struct(params, fields, cattrs)
307    }
308}
309
310fn serialize_struct_tag_field(cattrs: &attr::Container, struct_trait: &StructTrait) -> TokenStream {
311    match cattrs.tag() {
312        attr::TagType::Internal { tag } => {
313            let type_name = cattrs.name().serialize_name();
314            let func = struct_trait.serialize_field(Span::call_site());
315            quote! {
316                #func(&mut __serde_state, #tag, #type_name)?;
317            }
318        }
319        _ => quote! {},
320    }
321}
322
323fn serialize_struct_as_struct(
324    params: &Parameters,
325    fields: &[Field],
326    cattrs: &attr::Container,
327) -> Fragment {
328    let serialize_fields =
329        serialize_struct_visitor(fields, params, false, &StructTrait::SerializeStruct);
330
331    let type_name = cattrs.name().serialize_name();
332
333    let tag_field = serialize_struct_tag_field(cattrs, &StructTrait::SerializeStruct);
334    let tag_field_exists = !tag_field.is_empty();
335
336    let mut serialized_fields = fields
337        .iter()
338        .filter(|&field| !field.attrs.skip_serializing())
339        .peekable();
340
341    let let_mut = mut_if(serialized_fields.peek().is_some() || tag_field_exists);
342
343    let len = serialized_fields
344        .map(|field| match field.attrs.skip_serializing_if() {
345            None => quote!(1),
346            Some(path) => {
347                let field_expr = get_member(params, field, &field.member);
348                quote!(if #path(#field_expr) { 0 } else { 1 })
349            }
350        })
351        .fold(
352            quote!(#tag_field_exists as usize),
353            |sum, expr| quote!(#sum + #expr),
354        );
355
356    quote_block! {
357        let #let_mut __serde_state = _serde::Serializer::serialize_struct(__serializer, #type_name, #len)?;
358        #tag_field
359        #(#serialize_fields)*
360        _serde::ser::SerializeStruct::end(__serde_state)
361    }
362}
363
364fn serialize_struct_as_map(
365    params: &Parameters,
366    fields: &[Field],
367    cattrs: &attr::Container,
368) -> Fragment {
369    let serialize_fields =
370        serialize_struct_visitor(fields, params, false, &StructTrait::SerializeMap);
371
372    let tag_field = serialize_struct_tag_field(cattrs, &StructTrait::SerializeMap);
373    let tag_field_exists = !tag_field.is_empty();
374
375    let mut serialized_fields = fields
376        .iter()
377        .filter(|&field| !field.attrs.skip_serializing())
378        .peekable();
379
380    let let_mut = mut_if(serialized_fields.peek().is_some() || tag_field_exists);
381
382    quote_block! {
383        let #let_mut __serde_state = _serde::Serializer::serialize_map(__serializer, _serde::__private::None)?;
384        #tag_field
385        #(#serialize_fields)*
386        _serde::ser::SerializeMap::end(__serde_state)
387    }
388}
389
390fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Container) -> Fragment {
391    assert!(variants.len() as u64 <= u64::from(u32::MAX));
392
393    let self_var = &params.self_var;
394
395    let mut arms: Vec<_> = variants
396        .iter()
397        .enumerate()
398        .map(|(variant_index, variant)| {
399            serialize_variant(params, variant, variant_index as u32, cattrs)
400        })
401        .collect();
402
403    if cattrs.remote().is_some() && cattrs.non_exhaustive() {
404        arms.push(quote! {
405            ref unrecognized => _serde::__private::Err(_serde::ser::Error::custom(_serde::__private::ser::CannotSerializeVariant(unrecognized))),
406        });
407    }
408
409    quote_expr! {
410        match *#self_var {
411            #(#arms)*
412        }
413    }
414}
415
416fn serialize_variant(
417    params: &Parameters,
418    variant: &Variant,
419    variant_index: u32,
420    cattrs: &attr::Container,
421) -> TokenStream {
422    let this_value = &params.this_value;
423    let variant_ident = &variant.ident;
424
425    if variant.attrs.skip_serializing() {
426        let skipped_msg = format!(
427            "the enum variant {}::{} cannot be serialized",
428            params.type_name(),
429            variant_ident
430        );
431        let skipped_err = quote! {
432            _serde::__private::Err(_serde::ser::Error::custom(#skipped_msg))
433        };
434        let fields_pat = match variant.style {
435            Style::Unit => quote!(),
436            Style::Newtype | Style::Tuple => quote!((..)),
437            Style::Struct => quote!({ .. }),
438        };
439        quote! {
440            #this_value::#variant_ident #fields_pat => #skipped_err,
441        }
442    } else {
443        // variant wasn't skipped
444        let case = match variant.style {
445            Style::Unit => {
446                quote! {
447                    #this_value::#variant_ident
448                }
449            }
450            Style::Newtype => {
451                quote! {
452                    #this_value::#variant_ident(ref __field0)
453                }
454            }
455            Style::Tuple => {
456                let field_names = (0..variant.fields.len())
457                    .map(|i| Ident::new(&format!("__field{}", i), Span::call_site()));
458                quote! {
459                    #this_value::#variant_ident(#(ref #field_names),*)
460                }
461            }
462            Style::Struct => {
463                let members = variant.fields.iter().map(|f| &f.member);
464                quote! {
465                    #this_value::#variant_ident { #(ref #members),* }
466                }
467            }
468        };
469
470        let body = Match(match (cattrs.tag(), variant.attrs.untagged()) {
471            (attr::TagType::External, false) => {
472                serialize_externally_tagged_variant(params, variant, variant_index, cattrs)
473            }
474            (attr::TagType::Internal { tag }, false) => {
475                serialize_internally_tagged_variant(params, variant, cattrs, tag)
476            }
477            (attr::TagType::Adjacent { tag, content }, false) => {
478                serialize_adjacently_tagged_variant(
479                    params,
480                    variant,
481                    cattrs,
482                    variant_index,
483                    tag,
484                    content,
485                )
486            }
487            (attr::TagType::None, _) | (_, true) => {
488                serialize_untagged_variant(params, variant, cattrs)
489            }
490        });
491
492        quote! {
493            #case => #body
494        }
495    }
496}
497
498fn serialize_externally_tagged_variant(
499    params: &Parameters,
500    variant: &Variant,
501    variant_index: u32,
502    cattrs: &attr::Container,
503) -> Fragment {
504    let type_name = cattrs.name().serialize_name();
505    let variant_name = variant.attrs.name().serialize_name();
506
507    if let Some(path) = variant.attrs.serialize_with() {
508        let ser = wrap_serialize_variant_with(params, path, variant);
509        return quote_expr! {
510            _serde::Serializer::serialize_newtype_variant(
511                __serializer,
512                #type_name,
513                #variant_index,
514                #variant_name,
515                #ser,
516            )
517        };
518    }
519
520    match effective_style(variant) {
521        Style::Unit => {
522            quote_expr! {
523                _serde::Serializer::serialize_unit_variant(
524                    __serializer,
525                    #type_name,
526                    #variant_index,
527                    #variant_name,
528                )
529            }
530        }
531        Style::Newtype => {
532            let field = &variant.fields[0];
533            let mut field_expr = quote!(__field0);
534            if let Some(path) = field.attrs.serialize_with() {
535                field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
536            }
537
538            let span = field.original.span();
539            let func = quote_spanned!(span=> _serde::Serializer::serialize_newtype_variant);
540            quote_expr! {
541                #func(
542                    __serializer,
543                    #type_name,
544                    #variant_index,
545                    #variant_name,
546                    #field_expr,
547                )
548            }
549        }
550        Style::Tuple => serialize_tuple_variant(
551            TupleVariant::ExternallyTagged {
552                type_name,
553                variant_index,
554                variant_name,
555            },
556            params,
557            &variant.fields,
558        ),
559        Style::Struct => serialize_struct_variant(
560            StructVariant::ExternallyTagged {
561                variant_index,
562                variant_name,
563            },
564            params,
565            &variant.fields,
566            type_name,
567        ),
568    }
569}
570
571fn serialize_internally_tagged_variant(
572    params: &Parameters,
573    variant: &Variant,
574    cattrs: &attr::Container,
575    tag: &str,
576) -> Fragment {
577    let type_name = cattrs.name().serialize_name();
578    let variant_name = variant.attrs.name().serialize_name();
579
580    let enum_ident_str = params.type_name();
581    let variant_ident_str = variant.ident.to_string();
582
583    if let Some(path) = variant.attrs.serialize_with() {
584        let ser = wrap_serialize_variant_with(params, path, variant);
585        return quote_expr! {
586            _serde::__private::ser::serialize_tagged_newtype(
587                __serializer,
588                #enum_ident_str,
589                #variant_ident_str,
590                #tag,
591                #variant_name,
592                #ser,
593            )
594        };
595    }
596
597    match effective_style(variant) {
598        Style::Unit => {
599            quote_block! {
600                let mut __struct = _serde::Serializer::serialize_struct(
601                    __serializer, #type_name, 1)?;
602                _serde::ser::SerializeStruct::serialize_field(
603                    &mut __struct, #tag, #variant_name)?;
604                _serde::ser::SerializeStruct::end(__struct)
605            }
606        }
607        Style::Newtype => {
608            let field = &variant.fields[0];
609            let mut field_expr = quote!(__field0);
610            if let Some(path) = field.attrs.serialize_with() {
611                field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
612            }
613
614            let span = field.original.span();
615            let func = quote_spanned!(span=> _serde::__private::ser::serialize_tagged_newtype);
616            quote_expr! {
617                #func(
618                    __serializer,
619                    #enum_ident_str,
620                    #variant_ident_str,
621                    #tag,
622                    #variant_name,
623                    #field_expr,
624                )
625            }
626        }
627        Style::Struct => serialize_struct_variant(
628            StructVariant::InternallyTagged { tag, variant_name },
629            params,
630            &variant.fields,
631            type_name,
632        ),
633        Style::Tuple => unreachable!("checked in serde_derive_internals"),
634    }
635}
636
637fn serialize_adjacently_tagged_variant(
638    params: &Parameters,
639    variant: &Variant,
640    cattrs: &attr::Container,
641    variant_index: u32,
642    tag: &str,
643    content: &str,
644) -> Fragment {
645    let this_type = &params.this_type;
646    let type_name = cattrs.name().serialize_name();
647    let variant_name = variant.attrs.name().serialize_name();
648    let serialize_variant = quote! {
649        &_serde::__private::ser::AdjacentlyTaggedEnumVariant {
650            enum_name: #type_name,
651            variant_index: #variant_index,
652            variant_name: #variant_name,
653        }
654    };
655
656    let inner = Stmts(if let Some(path) = variant.attrs.serialize_with() {
657        let ser = wrap_serialize_variant_with(params, path, variant);
658        quote_expr! {
659            _serde::Serialize::serialize(#ser, __serializer)
660        }
661    } else {
662        match effective_style(variant) {
663            Style::Unit => {
664                return quote_block! {
665                    let mut __struct = _serde::Serializer::serialize_struct(
666                        __serializer, #type_name, 1)?;
667                    _serde::ser::SerializeStruct::serialize_field(
668                        &mut __struct, #tag, #serialize_variant)?;
669                    _serde::ser::SerializeStruct::end(__struct)
670                };
671            }
672            Style::Newtype => {
673                let field = &variant.fields[0];
674                let mut field_expr = quote!(__field0);
675                if let Some(path) = field.attrs.serialize_with() {
676                    field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
677                }
678
679                let span = field.original.span();
680                let func = quote_spanned!(span=> _serde::ser::SerializeStruct::serialize_field);
681                return quote_block! {
682                    let mut __struct = _serde::Serializer::serialize_struct(
683                        __serializer, #type_name, 2)?;
684                    _serde::ser::SerializeStruct::serialize_field(
685                        &mut __struct, #tag, #serialize_variant)?;
686                    #func(
687                        &mut __struct, #content, #field_expr)?;
688                    _serde::ser::SerializeStruct::end(__struct)
689                };
690            }
691            Style::Tuple => {
692                serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields)
693            }
694            Style::Struct => serialize_struct_variant(
695                StructVariant::Untagged,
696                params,
697                &variant.fields,
698                variant_name,
699            ),
700        }
701    });
702
703    let fields_ty = variant.fields.iter().map(|f| &f.ty);
704    let fields_ident: &[_] = &match variant.style {
705        Style::Unit => {
706            if variant.attrs.serialize_with().is_some() {
707                vec![]
708            } else {
709                unreachable!()
710            }
711        }
712        Style::Newtype => vec![Member::Named(Ident::new("__field0", Span::call_site()))],
713        Style::Tuple => (0..variant.fields.len())
714            .map(|i| Member::Named(Ident::new(&format!("__field{}", i), Span::call_site())))
715            .collect(),
716        Style::Struct => variant.fields.iter().map(|f| f.member.clone()).collect(),
717    };
718
719    let (_, ty_generics, where_clause) = params.generics.split_for_impl();
720
721    let wrapper_generics = if fields_ident.is_empty() {
722        params.generics.clone()
723    } else {
724        bound::with_lifetime_bound(&params.generics, "'__a")
725    };
726    let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
727
728    quote_block! {
729        #[doc(hidden)]
730        struct __AdjacentlyTagged #wrapper_generics #where_clause {
731            data: (#(&'__a #fields_ty,)*),
732            phantom: _serde::__private::PhantomData<#this_type #ty_generics>,
733        }
734
735        impl #wrapper_impl_generics _serde::Serialize for __AdjacentlyTagged #wrapper_ty_generics #where_clause {
736            fn serialize<__S>(&self, __serializer: __S) -> _serde::__private::Result<__S::Ok, __S::Error>
737            where
738                __S: _serde::Serializer,
739            {
740                // Elements that have skip_serializing will be unused.
741                #[allow(unused_variables)]
742                let (#(#fields_ident,)*) = self.data;
743                #inner
744            }
745        }
746
747        let mut __struct = _serde::Serializer::serialize_struct(
748            __serializer, #type_name, 2)?;
749        _serde::ser::SerializeStruct::serialize_field(
750            &mut __struct, #tag, #serialize_variant)?;
751        _serde::ser::SerializeStruct::serialize_field(
752            &mut __struct, #content, &__AdjacentlyTagged {
753                data: (#(#fields_ident,)*),
754                phantom: _serde::__private::PhantomData::<#this_type #ty_generics>,
755            })?;
756        _serde::ser::SerializeStruct::end(__struct)
757    }
758}
759
760fn serialize_untagged_variant(
761    params: &Parameters,
762    variant: &Variant,
763    cattrs: &attr::Container,
764) -> Fragment {
765    if let Some(path) = variant.attrs.serialize_with() {
766        let ser = wrap_serialize_variant_with(params, path, variant);
767        return quote_expr! {
768            _serde::Serialize::serialize(#ser, __serializer)
769        };
770    }
771
772    match effective_style(variant) {
773        Style::Unit => {
774            quote_expr! {
775                _serde::Serializer::serialize_unit(__serializer)
776            }
777        }
778        Style::Newtype => {
779            let field = &variant.fields[0];
780            let mut field_expr = quote!(__field0);
781            if let Some(path) = field.attrs.serialize_with() {
782                field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
783            }
784
785            let span = field.original.span();
786            let func = quote_spanned!(span=> _serde::Serialize::serialize);
787            quote_expr! {
788                #func(#field_expr, __serializer)
789            }
790        }
791        Style::Tuple => serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields),
792        Style::Struct => {
793            let type_name = cattrs.name().serialize_name();
794            serialize_struct_variant(StructVariant::Untagged, params, &variant.fields, type_name)
795        }
796    }
797}
798
799enum TupleVariant<'a> {
800    ExternallyTagged {
801        type_name: &'a str,
802        variant_index: u32,
803        variant_name: &'a str,
804    },
805    Untagged,
806}
807
808fn serialize_tuple_variant(
809    context: TupleVariant,
810    params: &Parameters,
811    fields: &[Field],
812) -> Fragment {
813    let tuple_trait = match context {
814        TupleVariant::ExternallyTagged { .. } => TupleTrait::SerializeTupleVariant,
815        TupleVariant::Untagged => TupleTrait::SerializeTuple,
816    };
817
818    let serialize_stmts = serialize_tuple_struct_visitor(fields, params, true, &tuple_trait);
819
820    let mut serialized_fields = fields
821        .iter()
822        .enumerate()
823        .filter(|(_, field)| !field.attrs.skip_serializing())
824        .peekable();
825
826    let let_mut = mut_if(serialized_fields.peek().is_some());
827
828    let len = serialized_fields
829        .map(|(i, field)| match field.attrs.skip_serializing_if() {
830            None => quote!(1),
831            Some(path) => {
832                let field_expr = Ident::new(&format!("__field{}", i), Span::call_site());
833                quote!(if #path(#field_expr) { 0 } else { 1 })
834            }
835        })
836        .fold(quote!(0), |sum, expr| quote!(#sum + #expr));
837
838    match context {
839        TupleVariant::ExternallyTagged {
840            type_name,
841            variant_index,
842            variant_name,
843        } => {
844            quote_block! {
845                let #let_mut __serde_state = _serde::Serializer::serialize_tuple_variant(
846                    __serializer,
847                    #type_name,
848                    #variant_index,
849                    #variant_name,
850                    #len)?;
851                #(#serialize_stmts)*
852                _serde::ser::SerializeTupleVariant::end(__serde_state)
853            }
854        }
855        TupleVariant::Untagged => {
856            quote_block! {
857                let #let_mut __serde_state = _serde::Serializer::serialize_tuple(
858                    __serializer,
859                    #len)?;
860                #(#serialize_stmts)*
861                _serde::ser::SerializeTuple::end(__serde_state)
862            }
863        }
864    }
865}
866
867enum StructVariant<'a> {
868    ExternallyTagged {
869        variant_index: u32,
870        variant_name: &'a str,
871    },
872    InternallyTagged {
873        tag: &'a str,
874        variant_name: &'a str,
875    },
876    Untagged,
877}
878
879fn serialize_struct_variant(
880    context: StructVariant,
881    params: &Parameters,
882    fields: &[Field],
883    name: &str,
884) -> Fragment {
885    if fields.iter().any(|field| field.attrs.flatten()) {
886        return serialize_struct_variant_with_flatten(context, params, fields, name);
887    }
888
889    let struct_trait = match context {
890        StructVariant::ExternallyTagged { .. } => StructTrait::SerializeStructVariant,
891        StructVariant::InternallyTagged { .. } | StructVariant::Untagged => {
892            StructTrait::SerializeStruct
893        }
894    };
895
896    let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait);
897
898    let mut serialized_fields = fields
899        .iter()
900        .filter(|&field| !field.attrs.skip_serializing())
901        .peekable();
902
903    let let_mut = mut_if(serialized_fields.peek().is_some());
904
905    let len = serialized_fields
906        .map(|field| {
907            let member = &field.member;
908
909            match field.attrs.skip_serializing_if() {
910                Some(path) => quote!(if #path(#member) { 0 } else { 1 }),
911                None => quote!(1),
912            }
913        })
914        .fold(quote!(0), |sum, expr| quote!(#sum + #expr));
915
916    match context {
917        StructVariant::ExternallyTagged {
918            variant_index,
919            variant_name,
920        } => {
921            quote_block! {
922                let #let_mut __serde_state = _serde::Serializer::serialize_struct_variant(
923                    __serializer,
924                    #name,
925                    #variant_index,
926                    #variant_name,
927                    #len,
928                )?;
929                #(#serialize_fields)*
930                _serde::ser::SerializeStructVariant::end(__serde_state)
931            }
932        }
933        StructVariant::InternallyTagged { tag, variant_name } => {
934            quote_block! {
935                let mut __serde_state = _serde::Serializer::serialize_struct(
936                    __serializer,
937                    #name,
938                    #len + 1,
939                )?;
940                _serde::ser::SerializeStruct::serialize_field(
941                    &mut __serde_state,
942                    #tag,
943                    #variant_name,
944                )?;
945                #(#serialize_fields)*
946                _serde::ser::SerializeStruct::end(__serde_state)
947            }
948        }
949        StructVariant::Untagged => {
950            quote_block! {
951                let #let_mut __serde_state = _serde::Serializer::serialize_struct(
952                    __serializer,
953                    #name,
954                    #len,
955                )?;
956                #(#serialize_fields)*
957                _serde::ser::SerializeStruct::end(__serde_state)
958            }
959        }
960    }
961}
962
963fn serialize_struct_variant_with_flatten(
964    context: StructVariant,
965    params: &Parameters,
966    fields: &[Field],
967    name: &str,
968) -> Fragment {
969    let struct_trait = StructTrait::SerializeMap;
970    let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait);
971
972    let mut serialized_fields = fields
973        .iter()
974        .filter(|&field| !field.attrs.skip_serializing())
975        .peekable();
976
977    let let_mut = mut_if(serialized_fields.peek().is_some());
978
979    match context {
980        StructVariant::ExternallyTagged {
981            variant_index,
982            variant_name,
983        } => {
984            let this_type = &params.this_type;
985            let fields_ty = fields.iter().map(|f| &f.ty);
986            let members = &fields.iter().map(|f| &f.member).collect::<Vec<_>>();
987
988            let (_, ty_generics, where_clause) = params.generics.split_for_impl();
989            let wrapper_generics = bound::with_lifetime_bound(&params.generics, "'__a");
990            let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
991
992            quote_block! {
993                #[doc(hidden)]
994                struct __EnumFlatten #wrapper_generics #where_clause {
995                    data: (#(&'__a #fields_ty,)*),
996                    phantom: _serde::__private::PhantomData<#this_type #ty_generics>,
997                }
998
999                impl #wrapper_impl_generics _serde::Serialize for __EnumFlatten #wrapper_ty_generics #where_clause {
1000                    fn serialize<__S>(&self, __serializer: __S) -> _serde::__private::Result<__S::Ok, __S::Error>
1001                    where
1002                        __S: _serde::Serializer,
1003                    {
1004                        let (#(#members,)*) = self.data;
1005                        let #let_mut __serde_state = _serde::Serializer::serialize_map(
1006                            __serializer,
1007                            _serde::__private::None)?;
1008                        #(#serialize_fields)*
1009                        _serde::ser::SerializeMap::end(__serde_state)
1010                    }
1011                }
1012
1013                _serde::Serializer::serialize_newtype_variant(
1014                    __serializer,
1015                    #name,
1016                    #variant_index,
1017                    #variant_name,
1018                    &__EnumFlatten {
1019                        data: (#(#members,)*),
1020                        phantom: _serde::__private::PhantomData::<#this_type #ty_generics>,
1021                    })
1022            }
1023        }
1024        StructVariant::InternallyTagged { tag, variant_name } => {
1025            quote_block! {
1026                let #let_mut __serde_state = _serde::Serializer::serialize_map(
1027                    __serializer,
1028                    _serde::__private::None)?;
1029                _serde::ser::SerializeMap::serialize_entry(
1030                    &mut __serde_state,
1031                    #tag,
1032                    #variant_name,
1033                )?;
1034                #(#serialize_fields)*
1035                _serde::ser::SerializeMap::end(__serde_state)
1036            }
1037        }
1038        StructVariant::Untagged => {
1039            quote_block! {
1040                let #let_mut __serde_state = _serde::Serializer::serialize_map(
1041                    __serializer,
1042                    _serde::__private::None)?;
1043                #(#serialize_fields)*
1044                _serde::ser::SerializeMap::end(__serde_state)
1045            }
1046        }
1047    }
1048}
1049
1050fn serialize_tuple_struct_visitor(
1051    fields: &[Field],
1052    params: &Parameters,
1053    is_enum: bool,
1054    tuple_trait: &TupleTrait,
1055) -> Vec<TokenStream> {
1056    fields
1057        .iter()
1058        .enumerate()
1059        .filter(|(_, field)| !field.attrs.skip_serializing())
1060        .map(|(i, field)| {
1061            let mut field_expr = if is_enum {
1062                let id = Ident::new(&format!("__field{}", i), Span::call_site());
1063                quote!(#id)
1064            } else {
1065                get_member(
1066                    params,
1067                    field,
1068                    &Member::Unnamed(Index {
1069                        index: i as u32,
1070                        span: Span::call_site(),
1071                    }),
1072                )
1073            };
1074
1075            let skip = field
1076                .attrs
1077                .skip_serializing_if()
1078                .map(|path| quote!(#path(#field_expr)));
1079
1080            if let Some(path) = field.attrs.serialize_with() {
1081                field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
1082            }
1083
1084            let span = field.original.span();
1085            let func = tuple_trait.serialize_element(span);
1086            let ser = quote! {
1087                #func(&mut __serde_state, #field_expr)?;
1088            };
1089
1090            match skip {
1091                None => ser,
1092                Some(skip) => quote!(if !#skip { #ser }),
1093            }
1094        })
1095        .collect()
1096}
1097
1098fn serialize_struct_visitor(
1099    fields: &[Field],
1100    params: &Parameters,
1101    is_enum: bool,
1102    struct_trait: &StructTrait,
1103) -> Vec<TokenStream> {
1104    fields
1105        .iter()
1106        .filter(|&field| !field.attrs.skip_serializing())
1107        .map(|field| {
1108            let member = &field.member;
1109
1110            let mut field_expr = if is_enum {
1111                quote!(#member)
1112            } else {
1113                get_member(params, field, member)
1114            };
1115
1116            let key_expr = field.attrs.name().serialize_name();
1117
1118            let skip = field
1119                .attrs
1120                .skip_serializing_if()
1121                .map(|path| quote!(#path(#field_expr)));
1122
1123            if let Some(path) = field.attrs.serialize_with() {
1124                field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
1125            }
1126
1127            let span = field.original.span();
1128            let ser = if field.attrs.flatten() {
1129                let func = quote_spanned!(span=> _serde::Serialize::serialize);
1130                quote! {
1131                    #func(&#field_expr, _serde::__private::ser::FlatMapSerializer(&mut __serde_state))?;
1132                }
1133            } else {
1134                let func = struct_trait.serialize_field(span);
1135                quote! {
1136                    #func(&mut __serde_state, #key_expr, #field_expr)?;
1137                }
1138            };
1139
1140            match skip {
1141                None => ser,
1142                Some(skip) => {
1143                    if let Some(skip_func) = struct_trait.skip_field(span) {
1144                        quote! {
1145                            if !#skip {
1146                                #ser
1147                            } else {
1148                                #skip_func(&mut __serde_state, #key_expr)?;
1149                            }
1150                        }
1151                    } else {
1152                        quote! {
1153                            if !#skip {
1154                                #ser
1155                            }
1156                        }
1157                    }
1158                }
1159            }
1160        })
1161        .collect()
1162}
1163
1164fn wrap_serialize_field_with(
1165    params: &Parameters,
1166    field_ty: &syn::Type,
1167    serialize_with: &syn::ExprPath,
1168    field_expr: &TokenStream,
1169) -> TokenStream {
1170    wrap_serialize_with(params, serialize_with, &[field_ty], &[quote!(#field_expr)])
1171}
1172
1173fn wrap_serialize_variant_with(
1174    params: &Parameters,
1175    serialize_with: &syn::ExprPath,
1176    variant: &Variant,
1177) -> TokenStream {
1178    let field_tys: Vec<_> = variant.fields.iter().map(|field| field.ty).collect();
1179    let field_exprs: Vec<_> = variant
1180        .fields
1181        .iter()
1182        .map(|field| {
1183            let id = match &field.member {
1184                Member::Named(ident) => ident.clone(),
1185                Member::Unnamed(member) => {
1186                    Ident::new(&format!("__field{}", member.index), Span::call_site())
1187                }
1188            };
1189            quote!(#id)
1190        })
1191        .collect();
1192    wrap_serialize_with(
1193        params,
1194        serialize_with,
1195        field_tys.as_slice(),
1196        field_exprs.as_slice(),
1197    )
1198}
1199
1200fn wrap_serialize_with(
1201    params: &Parameters,
1202    serialize_with: &syn::ExprPath,
1203    field_tys: &[&syn::Type],
1204    field_exprs: &[TokenStream],
1205) -> TokenStream {
1206    let this_type = &params.this_type;
1207    let (_, ty_generics, where_clause) = params.generics.split_for_impl();
1208
1209    let wrapper_generics = if field_exprs.is_empty() {
1210        params.generics.clone()
1211    } else {
1212        bound::with_lifetime_bound(&params.generics, "'__a")
1213    };
1214    let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
1215
1216    let field_access = (0..field_exprs.len()).map(|n| {
1217        Member::Unnamed(Index {
1218            index: n as u32,
1219            span: Span::call_site(),
1220        })
1221    });
1222
1223    quote!({
1224        #[doc(hidden)]
1225        struct __SerializeWith #wrapper_impl_generics #where_clause {
1226            values: (#(&'__a #field_tys, )*),
1227            phantom: _serde::__private::PhantomData<#this_type #ty_generics>,
1228        }
1229
1230        impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause {
1231            fn serialize<__S>(&self, __s: __S) -> _serde::__private::Result<__S::Ok, __S::Error>
1232            where
1233                __S: _serde::Serializer,
1234            {
1235                #serialize_with(#(self.values.#field_access, )* __s)
1236            }
1237        }
1238
1239        &__SerializeWith {
1240            values: (#(#field_exprs, )*),
1241            phantom: _serde::__private::PhantomData::<#this_type #ty_generics>,
1242        }
1243    })
1244}
1245
1246// Serialization of an empty struct results in code like:
1247//
1248//     let mut __serde_state = serializer.serialize_struct("S", 0)?;
1249//     _serde::ser::SerializeStruct::end(__serde_state)
1250//
1251// where we want to omit the `mut` to avoid a warning.
1252fn mut_if(is_mut: bool) -> Option<TokenStream> {
1253    if is_mut {
1254        Some(quote!(mut))
1255    } else {
1256        None
1257    }
1258}
1259
1260fn get_member(params: &Parameters, field: &Field, member: &Member) -> TokenStream {
1261    let self_var = &params.self_var;
1262    match (params.is_remote, field.attrs.getter()) {
1263        (false, None) => {
1264            if params.is_packed {
1265                quote!(&{#self_var.#member})
1266            } else {
1267                quote!(&#self_var.#member)
1268            }
1269        }
1270        (true, None) => {
1271            let inner = if params.is_packed {
1272                quote!(&{#self_var.#member})
1273            } else {
1274                quote!(&#self_var.#member)
1275            };
1276            let ty = field.ty;
1277            quote!(_serde::__private::ser::constrain::<#ty>(#inner))
1278        }
1279        (true, Some(getter)) => {
1280            let ty = field.ty;
1281            quote!(_serde::__private::ser::constrain::<#ty>(&#getter(#self_var)))
1282        }
1283        (false, Some(_)) => {
1284            unreachable!("getter is only allowed for remote impls");
1285        }
1286    }
1287}
1288
1289fn effective_style(variant: &Variant) -> Style {
1290    match variant.style {
1291        Style::Newtype if variant.fields[0].attrs.skip_serializing() => Style::Unit,
1292        other => other,
1293    }
1294}
1295
1296enum StructTrait {
1297    SerializeMap,
1298    SerializeStruct,
1299    SerializeStructVariant,
1300}
1301
1302impl StructTrait {
1303    fn serialize_field(&self, span: Span) -> TokenStream {
1304        match *self {
1305            StructTrait::SerializeMap => {
1306                quote_spanned!(span=> _serde::ser::SerializeMap::serialize_entry)
1307            }
1308            StructTrait::SerializeStruct => {
1309                quote_spanned!(span=> _serde::ser::SerializeStruct::serialize_field)
1310            }
1311            StructTrait::SerializeStructVariant => {
1312                quote_spanned!(span=> _serde::ser::SerializeStructVariant::serialize_field)
1313            }
1314        }
1315    }
1316
1317    fn skip_field(&self, span: Span) -> Option<TokenStream> {
1318        match *self {
1319            StructTrait::SerializeMap => None,
1320            StructTrait::SerializeStruct => {
1321                Some(quote_spanned!(span=> _serde::ser::SerializeStruct::skip_field))
1322            }
1323            StructTrait::SerializeStructVariant => {
1324                Some(quote_spanned!(span=> _serde::ser::SerializeStructVariant::skip_field))
1325            }
1326        }
1327    }
1328}
1329
1330enum TupleTrait {
1331    SerializeTuple,
1332    SerializeTupleStruct,
1333    SerializeTupleVariant,
1334}
1335
1336impl TupleTrait {
1337    fn serialize_element(&self, span: Span) -> TokenStream {
1338        match *self {
1339            TupleTrait::SerializeTuple => {
1340                quote_spanned!(span=> _serde::ser::SerializeTuple::serialize_element)
1341            }
1342            TupleTrait::SerializeTupleStruct => {
1343                quote_spanned!(span=> _serde::ser::SerializeTupleStruct::serialize_field)
1344            }
1345            TupleTrait::SerializeTupleVariant => {
1346                quote_spanned!(span=> _serde::ser::SerializeTupleVariant::serialize_field)
1347            }
1348        }
1349    }
1350}