serde_derive/
ser.rs

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