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, ¶ms));
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 self_var: Ident,
82
83 this_type: syn::Path,
87
88 this_value: syn::Path,
91
92 generics: syn::Generics,
94
95 is_remote: bool,
97
98 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 fn type_name(&self) -> String {
129 self.this_type.segments.last().unwrap().ident.to_string()
130 }
131}
132
133fn 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
155fn 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 = ¶ms.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 = ¶ms.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 = ¶ms.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 = ¶ms.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 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 = ¶ms.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(¶ms.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 #[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 = ¶ms.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(¶ms.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 = ¶ms.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(¶ms.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 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
1265fn 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 = ¶ms.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}