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, ¶ms));
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 self_var: Ident,
77
78 this_type: syn::Path,
82
83 this_value: syn::Path,
86
87 generics: syn::Generics,
89
90 is_remote: bool,
92
93 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 fn type_name(&self) -> String {
124 self.this_type.segments.last().unwrap().ident.to_string()
125 }
126}
127
128fn 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
150fn 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 = ¶ms.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 = ¶ms.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!(
293 fields.len() as u64 <= u64::from(u32::MAX),
294 "too many fields in {}: {}, maximum supported count is {}",
295 cattrs.name().serialize_name(),
296 fields.len(),
297 u32::MAX,
298 );
299
300 let has_non_skipped_flatten = fields
301 .iter()
302 .any(|field| field.attrs.flatten() && !field.attrs.skip_serializing());
303 if has_non_skipped_flatten {
304 serialize_struct_as_map(params, fields, cattrs)
305 } else {
306 serialize_struct_as_struct(params, fields, cattrs)
307 }
308}
309
310fn serialize_struct_tag_field(cattrs: &attr::Container, struct_trait: &StructTrait) -> TokenStream {
311 match cattrs.tag() {
312 attr::TagType::Internal { tag } => {
313 let type_name = cattrs.name().serialize_name();
314 let func = struct_trait.serialize_field(Span::call_site());
315 quote! {
316 #func(&mut __serde_state, #tag, #type_name)?;
317 }
318 }
319 _ => quote! {},
320 }
321}
322
323fn serialize_struct_as_struct(
324 params: &Parameters,
325 fields: &[Field],
326 cattrs: &attr::Container,
327) -> Fragment {
328 let serialize_fields =
329 serialize_struct_visitor(fields, params, false, &StructTrait::SerializeStruct);
330
331 let type_name = cattrs.name().serialize_name();
332
333 let tag_field = serialize_struct_tag_field(cattrs, &StructTrait::SerializeStruct);
334 let tag_field_exists = !tag_field.is_empty();
335
336 let mut serialized_fields = fields
337 .iter()
338 .filter(|&field| !field.attrs.skip_serializing())
339 .peekable();
340
341 let let_mut = mut_if(serialized_fields.peek().is_some() || tag_field_exists);
342
343 let len = serialized_fields
344 .map(|field| match field.attrs.skip_serializing_if() {
345 None => quote!(1),
346 Some(path) => {
347 let field_expr = get_member(params, field, &field.member);
348 quote!(if #path(#field_expr) { 0 } else { 1 })
349 }
350 })
351 .fold(
352 quote!(#tag_field_exists as usize),
353 |sum, expr| quote!(#sum + #expr),
354 );
355
356 quote_block! {
357 let #let_mut __serde_state = _serde::Serializer::serialize_struct(__serializer, #type_name, #len)?;
358 #tag_field
359 #(#serialize_fields)*
360 _serde::ser::SerializeStruct::end(__serde_state)
361 }
362}
363
364fn serialize_struct_as_map(
365 params: &Parameters,
366 fields: &[Field],
367 cattrs: &attr::Container,
368) -> Fragment {
369 let serialize_fields =
370 serialize_struct_visitor(fields, params, false, &StructTrait::SerializeMap);
371
372 let tag_field = serialize_struct_tag_field(cattrs, &StructTrait::SerializeMap);
373 let tag_field_exists = !tag_field.is_empty();
374
375 let mut serialized_fields = fields
376 .iter()
377 .filter(|&field| !field.attrs.skip_serializing())
378 .peekable();
379
380 let let_mut = mut_if(serialized_fields.peek().is_some() || tag_field_exists);
381
382 quote_block! {
383 let #let_mut __serde_state = _serde::Serializer::serialize_map(__serializer, _serde::__private::None)?;
384 #tag_field
385 #(#serialize_fields)*
386 _serde::ser::SerializeMap::end(__serde_state)
387 }
388}
389
390fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Container) -> Fragment {
391 assert!(variants.len() as u64 <= u64::from(u32::MAX));
392
393 let self_var = ¶ms.self_var;
394
395 let mut arms: Vec<_> = variants
396 .iter()
397 .enumerate()
398 .map(|(variant_index, variant)| {
399 serialize_variant(params, variant, variant_index as u32, cattrs)
400 })
401 .collect();
402
403 if cattrs.remote().is_some() && cattrs.non_exhaustive() {
404 arms.push(quote! {
405 ref unrecognized => _serde::__private::Err(_serde::ser::Error::custom(_serde::__private::ser::CannotSerializeVariant(unrecognized))),
406 });
407 }
408
409 quote_expr! {
410 match *#self_var {
411 #(#arms)*
412 }
413 }
414}
415
416fn serialize_variant(
417 params: &Parameters,
418 variant: &Variant,
419 variant_index: u32,
420 cattrs: &attr::Container,
421) -> TokenStream {
422 let this_value = ¶ms.this_value;
423 let variant_ident = &variant.ident;
424
425 if variant.attrs.skip_serializing() {
426 let skipped_msg = format!(
427 "the enum variant {}::{} cannot be serialized",
428 params.type_name(),
429 variant_ident
430 );
431 let skipped_err = quote! {
432 _serde::__private::Err(_serde::ser::Error::custom(#skipped_msg))
433 };
434 let fields_pat = match variant.style {
435 Style::Unit => quote!(),
436 Style::Newtype | Style::Tuple => quote!((..)),
437 Style::Struct => quote!({ .. }),
438 };
439 quote! {
440 #this_value::#variant_ident #fields_pat => #skipped_err,
441 }
442 } else {
443 let case = match variant.style {
445 Style::Unit => {
446 quote! {
447 #this_value::#variant_ident
448 }
449 }
450 Style::Newtype => {
451 quote! {
452 #this_value::#variant_ident(ref __field0)
453 }
454 }
455 Style::Tuple => {
456 let field_names = (0..variant.fields.len())
457 .map(|i| Ident::new(&format!("__field{}", i), Span::call_site()));
458 quote! {
459 #this_value::#variant_ident(#(ref #field_names),*)
460 }
461 }
462 Style::Struct => {
463 let members = variant.fields.iter().map(|f| &f.member);
464 quote! {
465 #this_value::#variant_ident { #(ref #members),* }
466 }
467 }
468 };
469
470 let body = Match(match (cattrs.tag(), variant.attrs.untagged()) {
471 (attr::TagType::External, false) => {
472 serialize_externally_tagged_variant(params, variant, variant_index, cattrs)
473 }
474 (attr::TagType::Internal { tag }, false) => {
475 serialize_internally_tagged_variant(params, variant, cattrs, tag)
476 }
477 (attr::TagType::Adjacent { tag, content }, false) => {
478 serialize_adjacently_tagged_variant(
479 params,
480 variant,
481 cattrs,
482 variant_index,
483 tag,
484 content,
485 )
486 }
487 (attr::TagType::None, _) | (_, true) => {
488 serialize_untagged_variant(params, variant, cattrs)
489 }
490 });
491
492 quote! {
493 #case => #body
494 }
495 }
496}
497
498fn serialize_externally_tagged_variant(
499 params: &Parameters,
500 variant: &Variant,
501 variant_index: u32,
502 cattrs: &attr::Container,
503) -> Fragment {
504 let type_name = cattrs.name().serialize_name();
505 let variant_name = variant.attrs.name().serialize_name();
506
507 if let Some(path) = variant.attrs.serialize_with() {
508 let ser = wrap_serialize_variant_with(params, path, variant);
509 return quote_expr! {
510 _serde::Serializer::serialize_newtype_variant(
511 __serializer,
512 #type_name,
513 #variant_index,
514 #variant_name,
515 #ser,
516 )
517 };
518 }
519
520 match effective_style(variant) {
521 Style::Unit => {
522 quote_expr! {
523 _serde::Serializer::serialize_unit_variant(
524 __serializer,
525 #type_name,
526 #variant_index,
527 #variant_name,
528 )
529 }
530 }
531 Style::Newtype => {
532 let field = &variant.fields[0];
533 let mut field_expr = quote!(__field0);
534 if let Some(path) = field.attrs.serialize_with() {
535 field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
536 }
537
538 let span = field.original.span();
539 let func = quote_spanned!(span=> _serde::Serializer::serialize_newtype_variant);
540 quote_expr! {
541 #func(
542 __serializer,
543 #type_name,
544 #variant_index,
545 #variant_name,
546 #field_expr,
547 )
548 }
549 }
550 Style::Tuple => serialize_tuple_variant(
551 TupleVariant::ExternallyTagged {
552 type_name,
553 variant_index,
554 variant_name,
555 },
556 params,
557 &variant.fields,
558 ),
559 Style::Struct => serialize_struct_variant(
560 StructVariant::ExternallyTagged {
561 variant_index,
562 variant_name,
563 },
564 params,
565 &variant.fields,
566 type_name,
567 ),
568 }
569}
570
571fn serialize_internally_tagged_variant(
572 params: &Parameters,
573 variant: &Variant,
574 cattrs: &attr::Container,
575 tag: &str,
576) -> Fragment {
577 let type_name = cattrs.name().serialize_name();
578 let variant_name = variant.attrs.name().serialize_name();
579
580 let enum_ident_str = params.type_name();
581 let variant_ident_str = variant.ident.to_string();
582
583 if let Some(path) = variant.attrs.serialize_with() {
584 let ser = wrap_serialize_variant_with(params, path, variant);
585 return quote_expr! {
586 _serde::__private::ser::serialize_tagged_newtype(
587 __serializer,
588 #enum_ident_str,
589 #variant_ident_str,
590 #tag,
591 #variant_name,
592 #ser,
593 )
594 };
595 }
596
597 match effective_style(variant) {
598 Style::Unit => {
599 quote_block! {
600 let mut __struct = _serde::Serializer::serialize_struct(
601 __serializer, #type_name, 1)?;
602 _serde::ser::SerializeStruct::serialize_field(
603 &mut __struct, #tag, #variant_name)?;
604 _serde::ser::SerializeStruct::end(__struct)
605 }
606 }
607 Style::Newtype => {
608 let field = &variant.fields[0];
609 let mut field_expr = quote!(__field0);
610 if let Some(path) = field.attrs.serialize_with() {
611 field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
612 }
613
614 let span = field.original.span();
615 let func = quote_spanned!(span=> _serde::__private::ser::serialize_tagged_newtype);
616 quote_expr! {
617 #func(
618 __serializer,
619 #enum_ident_str,
620 #variant_ident_str,
621 #tag,
622 #variant_name,
623 #field_expr,
624 )
625 }
626 }
627 Style::Struct => serialize_struct_variant(
628 StructVariant::InternallyTagged { tag, variant_name },
629 params,
630 &variant.fields,
631 type_name,
632 ),
633 Style::Tuple => unreachable!("checked in serde_derive_internals"),
634 }
635}
636
637fn serialize_adjacently_tagged_variant(
638 params: &Parameters,
639 variant: &Variant,
640 cattrs: &attr::Container,
641 variant_index: u32,
642 tag: &str,
643 content: &str,
644) -> Fragment {
645 let this_type = ¶ms.this_type;
646 let type_name = cattrs.name().serialize_name();
647 let variant_name = variant.attrs.name().serialize_name();
648 let serialize_variant = quote! {
649 &_serde::__private::ser::AdjacentlyTaggedEnumVariant {
650 enum_name: #type_name,
651 variant_index: #variant_index,
652 variant_name: #variant_name,
653 }
654 };
655
656 let inner = Stmts(if let Some(path) = variant.attrs.serialize_with() {
657 let ser = wrap_serialize_variant_with(params, path, variant);
658 quote_expr! {
659 _serde::Serialize::serialize(#ser, __serializer)
660 }
661 } else {
662 match effective_style(variant) {
663 Style::Unit => {
664 return quote_block! {
665 let mut __struct = _serde::Serializer::serialize_struct(
666 __serializer, #type_name, 1)?;
667 _serde::ser::SerializeStruct::serialize_field(
668 &mut __struct, #tag, #serialize_variant)?;
669 _serde::ser::SerializeStruct::end(__struct)
670 };
671 }
672 Style::Newtype => {
673 let field = &variant.fields[0];
674 let mut field_expr = quote!(__field0);
675 if let Some(path) = field.attrs.serialize_with() {
676 field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
677 }
678
679 let span = field.original.span();
680 let func = quote_spanned!(span=> _serde::ser::SerializeStruct::serialize_field);
681 return quote_block! {
682 let mut __struct = _serde::Serializer::serialize_struct(
683 __serializer, #type_name, 2)?;
684 _serde::ser::SerializeStruct::serialize_field(
685 &mut __struct, #tag, #serialize_variant)?;
686 #func(
687 &mut __struct, #content, #field_expr)?;
688 _serde::ser::SerializeStruct::end(__struct)
689 };
690 }
691 Style::Tuple => {
692 serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields)
693 }
694 Style::Struct => serialize_struct_variant(
695 StructVariant::Untagged,
696 params,
697 &variant.fields,
698 variant_name,
699 ),
700 }
701 });
702
703 let fields_ty = variant.fields.iter().map(|f| &f.ty);
704 let fields_ident: &[_] = &match variant.style {
705 Style::Unit => {
706 if variant.attrs.serialize_with().is_some() {
707 vec![]
708 } else {
709 unreachable!()
710 }
711 }
712 Style::Newtype => vec![Member::Named(Ident::new("__field0", Span::call_site()))],
713 Style::Tuple => (0..variant.fields.len())
714 .map(|i| Member::Named(Ident::new(&format!("__field{}", i), Span::call_site())))
715 .collect(),
716 Style::Struct => variant.fields.iter().map(|f| f.member.clone()).collect(),
717 };
718
719 let (_, ty_generics, where_clause) = params.generics.split_for_impl();
720
721 let wrapper_generics = if fields_ident.is_empty() {
722 params.generics.clone()
723 } else {
724 bound::with_lifetime_bound(¶ms.generics, "'__a")
725 };
726 let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
727
728 quote_block! {
729 #[doc(hidden)]
730 struct __AdjacentlyTagged #wrapper_generics #where_clause {
731 data: (#(&'__a #fields_ty,)*),
732 phantom: _serde::__private::PhantomData<#this_type #ty_generics>,
733 }
734
735 impl #wrapper_impl_generics _serde::Serialize for __AdjacentlyTagged #wrapper_ty_generics #where_clause {
736 fn serialize<__S>(&self, __serializer: __S) -> _serde::__private::Result<__S::Ok, __S::Error>
737 where
738 __S: _serde::Serializer,
739 {
740 #[allow(unused_variables)]
742 let (#(#fields_ident,)*) = self.data;
743 #inner
744 }
745 }
746
747 let mut __struct = _serde::Serializer::serialize_struct(
748 __serializer, #type_name, 2)?;
749 _serde::ser::SerializeStruct::serialize_field(
750 &mut __struct, #tag, #serialize_variant)?;
751 _serde::ser::SerializeStruct::serialize_field(
752 &mut __struct, #content, &__AdjacentlyTagged {
753 data: (#(#fields_ident,)*),
754 phantom: _serde::__private::PhantomData::<#this_type #ty_generics>,
755 })?;
756 _serde::ser::SerializeStruct::end(__struct)
757 }
758}
759
760fn serialize_untagged_variant(
761 params: &Parameters,
762 variant: &Variant,
763 cattrs: &attr::Container,
764) -> Fragment {
765 if let Some(path) = variant.attrs.serialize_with() {
766 let ser = wrap_serialize_variant_with(params, path, variant);
767 return quote_expr! {
768 _serde::Serialize::serialize(#ser, __serializer)
769 };
770 }
771
772 match effective_style(variant) {
773 Style::Unit => {
774 quote_expr! {
775 _serde::Serializer::serialize_unit(__serializer)
776 }
777 }
778 Style::Newtype => {
779 let field = &variant.fields[0];
780 let mut field_expr = quote!(__field0);
781 if let Some(path) = field.attrs.serialize_with() {
782 field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
783 }
784
785 let span = field.original.span();
786 let func = quote_spanned!(span=> _serde::Serialize::serialize);
787 quote_expr! {
788 #func(#field_expr, __serializer)
789 }
790 }
791 Style::Tuple => serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields),
792 Style::Struct => {
793 let type_name = cattrs.name().serialize_name();
794 serialize_struct_variant(StructVariant::Untagged, params, &variant.fields, type_name)
795 }
796 }
797}
798
799enum TupleVariant<'a> {
800 ExternallyTagged {
801 type_name: &'a str,
802 variant_index: u32,
803 variant_name: &'a str,
804 },
805 Untagged,
806}
807
808fn serialize_tuple_variant(
809 context: TupleVariant,
810 params: &Parameters,
811 fields: &[Field],
812) -> Fragment {
813 let tuple_trait = match context {
814 TupleVariant::ExternallyTagged { .. } => TupleTrait::SerializeTupleVariant,
815 TupleVariant::Untagged => TupleTrait::SerializeTuple,
816 };
817
818 let serialize_stmts = serialize_tuple_struct_visitor(fields, params, true, &tuple_trait);
819
820 let mut serialized_fields = fields
821 .iter()
822 .enumerate()
823 .filter(|(_, field)| !field.attrs.skip_serializing())
824 .peekable();
825
826 let let_mut = mut_if(serialized_fields.peek().is_some());
827
828 let len = serialized_fields
829 .map(|(i, field)| match field.attrs.skip_serializing_if() {
830 None => quote!(1),
831 Some(path) => {
832 let field_expr = Ident::new(&format!("__field{}", i), Span::call_site());
833 quote!(if #path(#field_expr) { 0 } else { 1 })
834 }
835 })
836 .fold(quote!(0), |sum, expr| quote!(#sum + #expr));
837
838 match context {
839 TupleVariant::ExternallyTagged {
840 type_name,
841 variant_index,
842 variant_name,
843 } => {
844 quote_block! {
845 let #let_mut __serde_state = _serde::Serializer::serialize_tuple_variant(
846 __serializer,
847 #type_name,
848 #variant_index,
849 #variant_name,
850 #len)?;
851 #(#serialize_stmts)*
852 _serde::ser::SerializeTupleVariant::end(__serde_state)
853 }
854 }
855 TupleVariant::Untagged => {
856 quote_block! {
857 let #let_mut __serde_state = _serde::Serializer::serialize_tuple(
858 __serializer,
859 #len)?;
860 #(#serialize_stmts)*
861 _serde::ser::SerializeTuple::end(__serde_state)
862 }
863 }
864 }
865}
866
867enum StructVariant<'a> {
868 ExternallyTagged {
869 variant_index: u32,
870 variant_name: &'a str,
871 },
872 InternallyTagged {
873 tag: &'a str,
874 variant_name: &'a str,
875 },
876 Untagged,
877}
878
879fn serialize_struct_variant(
880 context: StructVariant,
881 params: &Parameters,
882 fields: &[Field],
883 name: &str,
884) -> Fragment {
885 if fields.iter().any(|field| field.attrs.flatten()) {
886 return serialize_struct_variant_with_flatten(context, params, fields, name);
887 }
888
889 let struct_trait = match context {
890 StructVariant::ExternallyTagged { .. } => StructTrait::SerializeStructVariant,
891 StructVariant::InternallyTagged { .. } | StructVariant::Untagged => {
892 StructTrait::SerializeStruct
893 }
894 };
895
896 let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait);
897
898 let mut serialized_fields = fields
899 .iter()
900 .filter(|&field| !field.attrs.skip_serializing())
901 .peekable();
902
903 let let_mut = mut_if(serialized_fields.peek().is_some());
904
905 let len = serialized_fields
906 .map(|field| {
907 let member = &field.member;
908
909 match field.attrs.skip_serializing_if() {
910 Some(path) => quote!(if #path(#member) { 0 } else { 1 }),
911 None => quote!(1),
912 }
913 })
914 .fold(quote!(0), |sum, expr| quote!(#sum + #expr));
915
916 match context {
917 StructVariant::ExternallyTagged {
918 variant_index,
919 variant_name,
920 } => {
921 quote_block! {
922 let #let_mut __serde_state = _serde::Serializer::serialize_struct_variant(
923 __serializer,
924 #name,
925 #variant_index,
926 #variant_name,
927 #len,
928 )?;
929 #(#serialize_fields)*
930 _serde::ser::SerializeStructVariant::end(__serde_state)
931 }
932 }
933 StructVariant::InternallyTagged { tag, variant_name } => {
934 quote_block! {
935 let mut __serde_state = _serde::Serializer::serialize_struct(
936 __serializer,
937 #name,
938 #len + 1,
939 )?;
940 _serde::ser::SerializeStruct::serialize_field(
941 &mut __serde_state,
942 #tag,
943 #variant_name,
944 )?;
945 #(#serialize_fields)*
946 _serde::ser::SerializeStruct::end(__serde_state)
947 }
948 }
949 StructVariant::Untagged => {
950 quote_block! {
951 let #let_mut __serde_state = _serde::Serializer::serialize_struct(
952 __serializer,
953 #name,
954 #len,
955 )?;
956 #(#serialize_fields)*
957 _serde::ser::SerializeStruct::end(__serde_state)
958 }
959 }
960 }
961}
962
963fn serialize_struct_variant_with_flatten(
964 context: StructVariant,
965 params: &Parameters,
966 fields: &[Field],
967 name: &str,
968) -> Fragment {
969 let struct_trait = StructTrait::SerializeMap;
970 let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait);
971
972 let mut serialized_fields = fields
973 .iter()
974 .filter(|&field| !field.attrs.skip_serializing())
975 .peekable();
976
977 let let_mut = mut_if(serialized_fields.peek().is_some());
978
979 match context {
980 StructVariant::ExternallyTagged {
981 variant_index,
982 variant_name,
983 } => {
984 let this_type = ¶ms.this_type;
985 let fields_ty = fields.iter().map(|f| &f.ty);
986 let members = &fields.iter().map(|f| &f.member).collect::<Vec<_>>();
987
988 let (_, ty_generics, where_clause) = params.generics.split_for_impl();
989 let wrapper_generics = bound::with_lifetime_bound(¶ms.generics, "'__a");
990 let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
991
992 quote_block! {
993 #[doc(hidden)]
994 struct __EnumFlatten #wrapper_generics #where_clause {
995 data: (#(&'__a #fields_ty,)*),
996 phantom: _serde::__private::PhantomData<#this_type #ty_generics>,
997 }
998
999 impl #wrapper_impl_generics _serde::Serialize for __EnumFlatten #wrapper_ty_generics #where_clause {
1000 fn serialize<__S>(&self, __serializer: __S) -> _serde::__private::Result<__S::Ok, __S::Error>
1001 where
1002 __S: _serde::Serializer,
1003 {
1004 let (#(#members,)*) = self.data;
1005 let #let_mut __serde_state = _serde::Serializer::serialize_map(
1006 __serializer,
1007 _serde::__private::None)?;
1008 #(#serialize_fields)*
1009 _serde::ser::SerializeMap::end(__serde_state)
1010 }
1011 }
1012
1013 _serde::Serializer::serialize_newtype_variant(
1014 __serializer,
1015 #name,
1016 #variant_index,
1017 #variant_name,
1018 &__EnumFlatten {
1019 data: (#(#members,)*),
1020 phantom: _serde::__private::PhantomData::<#this_type #ty_generics>,
1021 })
1022 }
1023 }
1024 StructVariant::InternallyTagged { tag, variant_name } => {
1025 quote_block! {
1026 let #let_mut __serde_state = _serde::Serializer::serialize_map(
1027 __serializer,
1028 _serde::__private::None)?;
1029 _serde::ser::SerializeMap::serialize_entry(
1030 &mut __serde_state,
1031 #tag,
1032 #variant_name,
1033 )?;
1034 #(#serialize_fields)*
1035 _serde::ser::SerializeMap::end(__serde_state)
1036 }
1037 }
1038 StructVariant::Untagged => {
1039 quote_block! {
1040 let #let_mut __serde_state = _serde::Serializer::serialize_map(
1041 __serializer,
1042 _serde::__private::None)?;
1043 #(#serialize_fields)*
1044 _serde::ser::SerializeMap::end(__serde_state)
1045 }
1046 }
1047 }
1048}
1049
1050fn serialize_tuple_struct_visitor(
1051 fields: &[Field],
1052 params: &Parameters,
1053 is_enum: bool,
1054 tuple_trait: &TupleTrait,
1055) -> Vec<TokenStream> {
1056 fields
1057 .iter()
1058 .enumerate()
1059 .filter(|(_, field)| !field.attrs.skip_serializing())
1060 .map(|(i, field)| {
1061 let mut field_expr = if is_enum {
1062 let id = Ident::new(&format!("__field{}", i), Span::call_site());
1063 quote!(#id)
1064 } else {
1065 get_member(
1066 params,
1067 field,
1068 &Member::Unnamed(Index {
1069 index: i as u32,
1070 span: Span::call_site(),
1071 }),
1072 )
1073 };
1074
1075 let skip = field
1076 .attrs
1077 .skip_serializing_if()
1078 .map(|path| quote!(#path(#field_expr)));
1079
1080 if let Some(path) = field.attrs.serialize_with() {
1081 field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
1082 }
1083
1084 let span = field.original.span();
1085 let func = tuple_trait.serialize_element(span);
1086 let ser = quote! {
1087 #func(&mut __serde_state, #field_expr)?;
1088 };
1089
1090 match skip {
1091 None => ser,
1092 Some(skip) => quote!(if !#skip { #ser }),
1093 }
1094 })
1095 .collect()
1096}
1097
1098fn serialize_struct_visitor(
1099 fields: &[Field],
1100 params: &Parameters,
1101 is_enum: bool,
1102 struct_trait: &StructTrait,
1103) -> Vec<TokenStream> {
1104 fields
1105 .iter()
1106 .filter(|&field| !field.attrs.skip_serializing())
1107 .map(|field| {
1108 let member = &field.member;
1109
1110 let mut field_expr = if is_enum {
1111 quote!(#member)
1112 } else {
1113 get_member(params, field, member)
1114 };
1115
1116 let key_expr = field.attrs.name().serialize_name();
1117
1118 let skip = field
1119 .attrs
1120 .skip_serializing_if()
1121 .map(|path| quote!(#path(#field_expr)));
1122
1123 if let Some(path) = field.attrs.serialize_with() {
1124 field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
1125 }
1126
1127 let span = field.original.span();
1128 let ser = if field.attrs.flatten() {
1129 let func = quote_spanned!(span=> _serde::Serialize::serialize);
1130 quote! {
1131 #func(&#field_expr, _serde::__private::ser::FlatMapSerializer(&mut __serde_state))?;
1132 }
1133 } else {
1134 let func = struct_trait.serialize_field(span);
1135 quote! {
1136 #func(&mut __serde_state, #key_expr, #field_expr)?;
1137 }
1138 };
1139
1140 match skip {
1141 None => ser,
1142 Some(skip) => {
1143 if let Some(skip_func) = struct_trait.skip_field(span) {
1144 quote! {
1145 if !#skip {
1146 #ser
1147 } else {
1148 #skip_func(&mut __serde_state, #key_expr)?;
1149 }
1150 }
1151 } else {
1152 quote! {
1153 if !#skip {
1154 #ser
1155 }
1156 }
1157 }
1158 }
1159 }
1160 })
1161 .collect()
1162}
1163
1164fn wrap_serialize_field_with(
1165 params: &Parameters,
1166 field_ty: &syn::Type,
1167 serialize_with: &syn::ExprPath,
1168 field_expr: &TokenStream,
1169) -> TokenStream {
1170 wrap_serialize_with(params, serialize_with, &[field_ty], &[quote!(#field_expr)])
1171}
1172
1173fn wrap_serialize_variant_with(
1174 params: &Parameters,
1175 serialize_with: &syn::ExprPath,
1176 variant: &Variant,
1177) -> TokenStream {
1178 let field_tys: Vec<_> = variant.fields.iter().map(|field| field.ty).collect();
1179 let field_exprs: Vec<_> = variant
1180 .fields
1181 .iter()
1182 .map(|field| {
1183 let id = match &field.member {
1184 Member::Named(ident) => ident.clone(),
1185 Member::Unnamed(member) => {
1186 Ident::new(&format!("__field{}", member.index), Span::call_site())
1187 }
1188 };
1189 quote!(#id)
1190 })
1191 .collect();
1192 wrap_serialize_with(
1193 params,
1194 serialize_with,
1195 field_tys.as_slice(),
1196 field_exprs.as_slice(),
1197 )
1198}
1199
1200fn wrap_serialize_with(
1201 params: &Parameters,
1202 serialize_with: &syn::ExprPath,
1203 field_tys: &[&syn::Type],
1204 field_exprs: &[TokenStream],
1205) -> TokenStream {
1206 let this_type = ¶ms.this_type;
1207 let (_, ty_generics, where_clause) = params.generics.split_for_impl();
1208
1209 let wrapper_generics = if field_exprs.is_empty() {
1210 params.generics.clone()
1211 } else {
1212 bound::with_lifetime_bound(¶ms.generics, "'__a")
1213 };
1214 let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
1215
1216 let field_access = (0..field_exprs.len()).map(|n| {
1217 Member::Unnamed(Index {
1218 index: n as u32,
1219 span: Span::call_site(),
1220 })
1221 });
1222
1223 quote!({
1224 #[doc(hidden)]
1225 struct __SerializeWith #wrapper_impl_generics #where_clause {
1226 values: (#(&'__a #field_tys, )*),
1227 phantom: _serde::__private::PhantomData<#this_type #ty_generics>,
1228 }
1229
1230 impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause {
1231 fn serialize<__S>(&self, __s: __S) -> _serde::__private::Result<__S::Ok, __S::Error>
1232 where
1233 __S: _serde::Serializer,
1234 {
1235 #serialize_with(#(self.values.#field_access, )* __s)
1236 }
1237 }
1238
1239 &__SerializeWith {
1240 values: (#(#field_exprs, )*),
1241 phantom: _serde::__private::PhantomData::<#this_type #ty_generics>,
1242 }
1243 })
1244}
1245
1246fn mut_if(is_mut: bool) -> Option<TokenStream> {
1253 if is_mut {
1254 Some(quote!(mut))
1255 } else {
1256 None
1257 }
1258}
1259
1260fn get_member(params: &Parameters, field: &Field, member: &Member) -> TokenStream {
1261 let self_var = ¶ms.self_var;
1262 match (params.is_remote, field.attrs.getter()) {
1263 (false, None) => {
1264 if params.is_packed {
1265 quote!(&{#self_var.#member})
1266 } else {
1267 quote!(&#self_var.#member)
1268 }
1269 }
1270 (true, None) => {
1271 let inner = if params.is_packed {
1272 quote!(&{#self_var.#member})
1273 } else {
1274 quote!(&#self_var.#member)
1275 };
1276 let ty = field.ty;
1277 quote!(_serde::__private::ser::constrain::<#ty>(#inner))
1278 }
1279 (true, Some(getter)) => {
1280 let ty = field.ty;
1281 quote!(_serde::__private::ser::constrain::<#ty>(&#getter(#self_var)))
1282 }
1283 (false, Some(_)) => {
1284 unreachable!("getter is only allowed for remote impls");
1285 }
1286 }
1287}
1288
1289fn effective_style(variant: &Variant) -> Style {
1290 match variant.style {
1291 Style::Newtype if variant.fields[0].attrs.skip_serializing() => Style::Unit,
1292 other => other,
1293 }
1294}
1295
1296enum StructTrait {
1297 SerializeMap,
1298 SerializeStruct,
1299 SerializeStructVariant,
1300}
1301
1302impl StructTrait {
1303 fn serialize_field(&self, span: Span) -> TokenStream {
1304 match *self {
1305 StructTrait::SerializeMap => {
1306 quote_spanned!(span=> _serde::ser::SerializeMap::serialize_entry)
1307 }
1308 StructTrait::SerializeStruct => {
1309 quote_spanned!(span=> _serde::ser::SerializeStruct::serialize_field)
1310 }
1311 StructTrait::SerializeStructVariant => {
1312 quote_spanned!(span=> _serde::ser::SerializeStructVariant::serialize_field)
1313 }
1314 }
1315 }
1316
1317 fn skip_field(&self, span: Span) -> Option<TokenStream> {
1318 match *self {
1319 StructTrait::SerializeMap => None,
1320 StructTrait::SerializeStruct => {
1321 Some(quote_spanned!(span=> _serde::ser::SerializeStruct::skip_field))
1322 }
1323 StructTrait::SerializeStructVariant => {
1324 Some(quote_spanned!(span=> _serde::ser::SerializeStructVariant::skip_field))
1325 }
1326 }
1327 }
1328}
1329
1330enum TupleTrait {
1331 SerializeTuple,
1332 SerializeTupleStruct,
1333 SerializeTupleVariant,
1334}
1335
1336impl TupleTrait {
1337 fn serialize_element(&self, span: Span) -> TokenStream {
1338 match *self {
1339 TupleTrait::SerializeTuple => {
1340 quote_spanned!(span=> _serde::ser::SerializeTuple::serialize_element)
1341 }
1342 TupleTrait::SerializeTupleStruct => {
1343 quote_spanned!(span=> _serde::ser::SerializeTupleStruct::serialize_field)
1344 }
1345 TupleTrait::SerializeTupleVariant => {
1346 quote_spanned!(span=> _serde::ser::SerializeTupleVariant::serialize_field)
1347 }
1348 }
1349 }
1350}