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