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