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