serde_derive/
ser.rs

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