serde_derive/
ser.rs

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