diff options
Diffstat (limited to 'vendor/serde_derive/src/ser.rs')
-rw-r--r-- | vendor/serde_derive/src/ser.rs | 1359 |
1 files changed, 0 insertions, 1359 deletions
diff --git a/vendor/serde_derive/src/ser.rs b/vendor/serde_derive/src/ser.rs deleted file mode 100644 index 3be51ee..0000000 --- a/vendor/serde_derive/src/ser.rs +++ /dev/null @@ -1,1359 +0,0 @@ -use crate::fragment::{Fragment, Match, Stmts}; -use crate::internals::ast::{Container, Data, Field, Style, Variant}; -use crate::internals::{attr, replace_receiver, Ctxt, Derive}; -use crate::{bound, dummy, pretend, this}; -use proc_macro2::{Span, TokenStream}; -use quote::{quote, quote_spanned}; -use syn::spanned::Spanned; -use syn::{parse_quote, Ident, Index, Member}; - -pub fn expand_derive_serialize(input: &mut syn::DeriveInput) -> syn::Result<TokenStream> { - replace_receiver(input); - - let ctxt = Ctxt::new(); - let cont = match Container::from_ast(&ctxt, input, Derive::Serialize) { - Some(cont) => cont, - None => return Err(ctxt.check().unwrap_err()), - }; - precondition(&ctxt, &cont); - ctxt.check()?; - - let ident = &cont.ident; - let params = Parameters::new(&cont); - let (impl_generics, ty_generics, where_clause) = params.generics.split_for_impl(); - let body = Stmts(serialize_body(&cont, ¶ms)); - let serde = cont.attrs.serde_path(); - - let impl_block = if let Some(remote) = cont.attrs.remote() { - let vis = &input.vis; - let used = pretend::pretend_used(&cont, params.is_packed); - quote! { - impl #impl_generics #ident #ty_generics #where_clause { - #vis fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> #serde::__private::Result<__S::Ok, __S::Error> - where - __S: #serde::Serializer, - { - #used - #body - } - } - } - } else { - quote! { - #[automatically_derived] - impl #impl_generics #serde::Serialize for #ident #ty_generics #where_clause { - fn serialize<__S>(&self, __serializer: __S) -> #serde::__private::Result<__S::Ok, __S::Error> - where - __S: #serde::Serializer, - { - #body - } - } - } - }; - - Ok(dummy::wrap_in_const( - cont.attrs.custom_serde_path(), - impl_block, - )) -} - -fn precondition(cx: &Ctxt, cont: &Container) { - match cont.attrs.identifier() { - attr::Identifier::No => {} - attr::Identifier::Field => { - cx.error_spanned_by(cont.original, "field identifiers cannot be serialized"); - } - attr::Identifier::Variant => { - cx.error_spanned_by(cont.original, "variant identifiers cannot be serialized"); - } - } -} - -struct Parameters { - /// Variable holding the value being serialized. Either `self` for local - /// types or `__self` for remote types. - self_var: Ident, - - /// Path to the type the impl is for. Either a single `Ident` for local - /// types (does not include generic parameters) or `some::remote::Path` for - /// remote types. - this_type: syn::Path, - - /// Same as `this_type` but using `::<T>` for generic parameters for use in - /// expression position. - this_value: syn::Path, - - /// Generics including any explicit and inferred bounds for the impl. - generics: syn::Generics, - - /// Type has a `serde(remote = "...")` attribute. - is_remote: bool, - - /// Type has a repr(packed) attribute. - is_packed: bool, -} - -impl Parameters { - fn new(cont: &Container) -> Self { - let is_remote = cont.attrs.remote().is_some(); - let self_var = if is_remote { - Ident::new("__self", Span::call_site()) - } else { - Ident::new("self", Span::call_site()) - }; - - let this_type = this::this_type(cont); - let this_value = this::this_value(cont); - let is_packed = cont.attrs.is_packed(); - let generics = build_generics(cont); - - Parameters { - self_var, - this_type, - this_value, - generics, - is_remote, - is_packed, - } - } - - /// Type name to use in error messages and `&'static str` arguments to - /// various Serializer methods. - fn type_name(&self) -> String { - self.this_type.segments.last().unwrap().ident.to_string() - } -} - -// All the generics in the input, plus a bound `T: Serialize` for each generic -// field type that will be serialized by us. -fn build_generics(cont: &Container) -> syn::Generics { - let generics = bound::without_defaults(cont.generics); - - let generics = - bound::with_where_predicates_from_fields(cont, &generics, attr::Field::ser_bound); - - let generics = - bound::with_where_predicates_from_variants(cont, &generics, attr::Variant::ser_bound); - - match cont.attrs.ser_bound() { - Some(predicates) => bound::with_where_predicates(&generics, predicates), - None => bound::with_bound( - cont, - &generics, - needs_serialize_bound, - &parse_quote!(_serde::Serialize), - ), - } -} - -// Fields with a `skip_serializing` or `serialize_with` attribute, or which -// belong to a variant with a 'skip_serializing` or `serialize_with` attribute, -// are not serialized by us so we do not generate a bound. Fields with a `bound` -// attribute specify their own bound so we do not generate one. All other fields -// may need a `T: Serialize` bound where T is the type of the field. -fn needs_serialize_bound(field: &attr::Field, variant: Option<&attr::Variant>) -> bool { - !field.skip_serializing() - && field.serialize_with().is_none() - && field.ser_bound().is_none() - && variant.map_or(true, |variant| { - !variant.skip_serializing() - && variant.serialize_with().is_none() - && variant.ser_bound().is_none() - }) -} - -fn serialize_body(cont: &Container, params: &Parameters) -> Fragment { - if cont.attrs.transparent() { - serialize_transparent(cont, params) - } else if let Some(type_into) = cont.attrs.type_into() { - serialize_into(params, type_into) - } else { - match &cont.data { - Data::Enum(variants) => serialize_enum(params, variants, &cont.attrs), - Data::Struct(Style::Struct, fields) => serialize_struct(params, fields, &cont.attrs), - Data::Struct(Style::Tuple, fields) => { - serialize_tuple_struct(params, fields, &cont.attrs) - } - Data::Struct(Style::Newtype, fields) => { - serialize_newtype_struct(params, &fields[0], &cont.attrs) - } - Data::Struct(Style::Unit, _) => serialize_unit_struct(&cont.attrs), - } - } -} - -fn serialize_transparent(cont: &Container, params: &Parameters) -> Fragment { - let fields = match &cont.data { - Data::Struct(_, fields) => fields, - Data::Enum(_) => unreachable!(), - }; - - let self_var = ¶ms.self_var; - let transparent_field = fields.iter().find(|f| f.attrs.transparent()).unwrap(); - let member = &transparent_field.member; - - let path = match transparent_field.attrs.serialize_with() { - Some(path) => quote!(#path), - None => { - let span = transparent_field.original.span(); - quote_spanned!(span=> _serde::Serialize::serialize) - } - }; - - quote_block! { - #path(&#self_var.#member, __serializer) - } -} - -fn serialize_into(params: &Parameters, type_into: &syn::Type) -> Fragment { - let self_var = ¶ms.self_var; - quote_block! { - _serde::Serialize::serialize( - &_serde::__private::Into::<#type_into>::into(_serde::__private::Clone::clone(#self_var)), - __serializer) - } -} - -fn serialize_unit_struct(cattrs: &attr::Container) -> Fragment { - let type_name = cattrs.name().serialize_name(); - - quote_expr! { - _serde::Serializer::serialize_unit_struct(__serializer, #type_name) - } -} - -fn serialize_newtype_struct( - params: &Parameters, - field: &Field, - cattrs: &attr::Container, -) -> Fragment { - let type_name = cattrs.name().serialize_name(); - - let mut field_expr = get_member( - params, - field, - &Member::Unnamed(Index { - index: 0, - span: Span::call_site(), - }), - ); - if let Some(path) = field.attrs.serialize_with() { - field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); - } - - let span = field.original.span(); - let func = quote_spanned!(span=> _serde::Serializer::serialize_newtype_struct); - quote_expr! { - #func(__serializer, #type_name, #field_expr) - } -} - -fn serialize_tuple_struct( - params: &Parameters, - fields: &[Field], - cattrs: &attr::Container, -) -> Fragment { - let serialize_stmts = - serialize_tuple_struct_visitor(fields, params, false, &TupleTrait::SerializeTupleStruct); - - let type_name = cattrs.name().serialize_name(); - - let mut serialized_fields = fields - .iter() - .enumerate() - .filter(|(_, field)| !field.attrs.skip_serializing()) - .peekable(); - - let let_mut = mut_if(serialized_fields.peek().is_some()); - - let len = serialized_fields - .map(|(i, field)| match field.attrs.skip_serializing_if() { - None => quote!(1), - Some(path) => { - let index = syn::Index { - index: i as u32, - span: Span::call_site(), - }; - let field_expr = get_member(params, field, &Member::Unnamed(index)); - quote!(if #path(#field_expr) { 0 } else { 1 }) - } - }) - .fold(quote!(0), |sum, expr| quote!(#sum + #expr)); - - quote_block! { - let #let_mut __serde_state = _serde::Serializer::serialize_tuple_struct(__serializer, #type_name, #len)?; - #(#serialize_stmts)* - _serde::ser::SerializeTupleStruct::end(__serde_state) - } -} - -fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Container) -> Fragment { - assert!(fields.len() as u64 <= u64::from(u32::max_value())); - - if cattrs.has_flatten() { - serialize_struct_as_map(params, fields, cattrs) - } else { - serialize_struct_as_struct(params, fields, cattrs) - } -} - -fn serialize_struct_tag_field(cattrs: &attr::Container, struct_trait: &StructTrait) -> TokenStream { - match cattrs.tag() { - attr::TagType::Internal { tag } => { - let type_name = cattrs.name().serialize_name(); - let func = struct_trait.serialize_field(Span::call_site()); - quote! { - #func(&mut __serde_state, #tag, #type_name)?; - } - } - _ => quote! {}, - } -} - -fn serialize_struct_as_struct( - params: &Parameters, - fields: &[Field], - cattrs: &attr::Container, -) -> Fragment { - let serialize_fields = - serialize_struct_visitor(fields, params, false, &StructTrait::SerializeStruct); - - let type_name = cattrs.name().serialize_name(); - - let tag_field = serialize_struct_tag_field(cattrs, &StructTrait::SerializeStruct); - let tag_field_exists = !tag_field.is_empty(); - - let mut serialized_fields = fields - .iter() - .filter(|&field| !field.attrs.skip_serializing()) - .peekable(); - - let let_mut = mut_if(serialized_fields.peek().is_some() || tag_field_exists); - - let len = serialized_fields - .map(|field| match field.attrs.skip_serializing_if() { - None => quote!(1), - Some(path) => { - let field_expr = get_member(params, field, &field.member); - quote!(if #path(#field_expr) { 0 } else { 1 }) - } - }) - .fold( - quote!(#tag_field_exists as usize), - |sum, expr| quote!(#sum + #expr), - ); - - quote_block! { - let #let_mut __serde_state = _serde::Serializer::serialize_struct(__serializer, #type_name, #len)?; - #tag_field - #(#serialize_fields)* - _serde::ser::SerializeStruct::end(__serde_state) - } -} - -fn serialize_struct_as_map( - params: &Parameters, - fields: &[Field], - cattrs: &attr::Container, -) -> Fragment { - let serialize_fields = - serialize_struct_visitor(fields, params, false, &StructTrait::SerializeMap); - - let tag_field = serialize_struct_tag_field(cattrs, &StructTrait::SerializeMap); - let tag_field_exists = !tag_field.is_empty(); - - let mut serialized_fields = fields - .iter() - .filter(|&field| !field.attrs.skip_serializing()) - .peekable(); - - let let_mut = mut_if(serialized_fields.peek().is_some() || tag_field_exists); - - let len = if cattrs.has_flatten() { - quote!(_serde::__private::None) - } else { - let len = serialized_fields - .map(|field| match field.attrs.skip_serializing_if() { - None => quote!(1), - Some(path) => { - let field_expr = get_member(params, field, &field.member); - quote!(if #path(#field_expr) { 0 } else { 1 }) - } - }) - .fold( - quote!(#tag_field_exists as usize), - |sum, expr| quote!(#sum + #expr), - ); - quote!(_serde::__private::Some(#len)) - }; - - quote_block! { - let #let_mut __serde_state = _serde::Serializer::serialize_map(__serializer, #len)?; - #tag_field - #(#serialize_fields)* - _serde::ser::SerializeMap::end(__serde_state) - } -} - -fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Container) -> Fragment { - assert!(variants.len() as u64 <= u64::from(u32::max_value())); - - let self_var = ¶ms.self_var; - - let mut arms: Vec<_> = variants - .iter() - .enumerate() - .map(|(variant_index, variant)| { - serialize_variant(params, variant, variant_index as u32, cattrs) - }) - .collect(); - - if cattrs.remote().is_some() && cattrs.non_exhaustive() { - arms.push(quote! { - ref unrecognized => _serde::__private::Err(_serde::ser::Error::custom(_serde::__private::ser::CannotSerializeVariant(unrecognized))), - }); - } - - quote_expr! { - match *#self_var { - #(#arms)* - } - } -} - -fn serialize_variant( - params: &Parameters, - variant: &Variant, - variant_index: u32, - cattrs: &attr::Container, -) -> TokenStream { - let this_value = ¶ms.this_value; - let variant_ident = &variant.ident; - - if variant.attrs.skip_serializing() { - let skipped_msg = format!( - "the enum variant {}::{} cannot be serialized", - params.type_name(), - variant_ident - ); - let skipped_err = quote! { - _serde::__private::Err(_serde::ser::Error::custom(#skipped_msg)) - }; - let fields_pat = match variant.style { - Style::Unit => quote!(), - Style::Newtype | Style::Tuple => quote!((..)), - Style::Struct => quote!({ .. }), - }; - quote! { - #this_value::#variant_ident #fields_pat => #skipped_err, - } - } else { - // variant wasn't skipped - let case = match variant.style { - Style::Unit => { - quote! { - #this_value::#variant_ident - } - } - Style::Newtype => { - quote! { - #this_value::#variant_ident(ref __field0) - } - } - Style::Tuple => { - let field_names = (0..variant.fields.len()) - .map(|i| Ident::new(&format!("__field{}", i), Span::call_site())); - quote! { - #this_value::#variant_ident(#(ref #field_names),*) - } - } - Style::Struct => { - let members = variant.fields.iter().map(|f| &f.member); - quote! { - #this_value::#variant_ident { #(ref #members),* } - } - } - }; - - let body = Match(match (cattrs.tag(), variant.attrs.untagged()) { - (attr::TagType::External, false) => { - serialize_externally_tagged_variant(params, variant, variant_index, cattrs) - } - (attr::TagType::Internal { tag }, false) => { - serialize_internally_tagged_variant(params, variant, cattrs, tag) - } - (attr::TagType::Adjacent { tag, content }, false) => { - serialize_adjacently_tagged_variant( - params, - variant, - cattrs, - variant_index, - tag, - content, - ) - } - (attr::TagType::None, _) | (_, true) => { - serialize_untagged_variant(params, variant, cattrs) - } - }); - - quote! { - #case => #body - } - } -} - -fn serialize_externally_tagged_variant( - params: &Parameters, - variant: &Variant, - variant_index: u32, - cattrs: &attr::Container, -) -> Fragment { - let type_name = cattrs.name().serialize_name(); - let variant_name = variant.attrs.name().serialize_name(); - - if let Some(path) = variant.attrs.serialize_with() { - let ser = wrap_serialize_variant_with(params, path, variant); - return quote_expr! { - _serde::Serializer::serialize_newtype_variant( - __serializer, - #type_name, - #variant_index, - #variant_name, - #ser, - ) - }; - } - - match effective_style(variant) { - Style::Unit => { - quote_expr! { - _serde::Serializer::serialize_unit_variant( - __serializer, - #type_name, - #variant_index, - #variant_name, - ) - } - } - Style::Newtype => { - let field = &variant.fields[0]; - let mut field_expr = quote!(__field0); - if let Some(path) = field.attrs.serialize_with() { - field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); - } - - let span = field.original.span(); - let func = quote_spanned!(span=> _serde::Serializer::serialize_newtype_variant); - quote_expr! { - #func( - __serializer, - #type_name, - #variant_index, - #variant_name, - #field_expr, - ) - } - } - Style::Tuple => serialize_tuple_variant( - TupleVariant::ExternallyTagged { - type_name, - variant_index, - variant_name, - }, - params, - &variant.fields, - ), - Style::Struct => serialize_struct_variant( - StructVariant::ExternallyTagged { - variant_index, - variant_name, - }, - params, - &variant.fields, - type_name, - ), - } -} - -fn serialize_internally_tagged_variant( - params: &Parameters, - variant: &Variant, - cattrs: &attr::Container, - tag: &str, -) -> Fragment { - let type_name = cattrs.name().serialize_name(); - let variant_name = variant.attrs.name().serialize_name(); - - let enum_ident_str = params.type_name(); - let variant_ident_str = variant.ident.to_string(); - - if let Some(path) = variant.attrs.serialize_with() { - let ser = wrap_serialize_variant_with(params, path, variant); - return quote_expr! { - _serde::__private::ser::serialize_tagged_newtype( - __serializer, - #enum_ident_str, - #variant_ident_str, - #tag, - #variant_name, - #ser, - ) - }; - } - - match effective_style(variant) { - Style::Unit => { - quote_block! { - let mut __struct = _serde::Serializer::serialize_struct( - __serializer, #type_name, 1)?; - _serde::ser::SerializeStruct::serialize_field( - &mut __struct, #tag, #variant_name)?; - _serde::ser::SerializeStruct::end(__struct) - } - } - Style::Newtype => { - let field = &variant.fields[0]; - let mut field_expr = quote!(__field0); - if let Some(path) = field.attrs.serialize_with() { - field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); - } - - let span = field.original.span(); - let func = quote_spanned!(span=> _serde::__private::ser::serialize_tagged_newtype); - quote_expr! { - #func( - __serializer, - #enum_ident_str, - #variant_ident_str, - #tag, - #variant_name, - #field_expr, - ) - } - } - Style::Struct => serialize_struct_variant( - StructVariant::InternallyTagged { tag, variant_name }, - params, - &variant.fields, - type_name, - ), - Style::Tuple => unreachable!("checked in serde_derive_internals"), - } -} - -fn serialize_adjacently_tagged_variant( - params: &Parameters, - variant: &Variant, - cattrs: &attr::Container, - variant_index: u32, - tag: &str, - content: &str, -) -> Fragment { - let this_type = ¶ms.this_type; - let type_name = cattrs.name().serialize_name(); - let variant_name = variant.attrs.name().serialize_name(); - let serialize_variant = quote! { - &_serde::__private::ser::AdjacentlyTaggedEnumVariant { - enum_name: #type_name, - variant_index: #variant_index, - variant_name: #variant_name, - } - }; - - let inner = Stmts(if let Some(path) = variant.attrs.serialize_with() { - let ser = wrap_serialize_variant_with(params, path, variant); - quote_expr! { - _serde::Serialize::serialize(#ser, __serializer) - } - } else { - match effective_style(variant) { - Style::Unit => { - return quote_block! { - let mut __struct = _serde::Serializer::serialize_struct( - __serializer, #type_name, 1)?; - _serde::ser::SerializeStruct::serialize_field( - &mut __struct, #tag, #serialize_variant)?; - _serde::ser::SerializeStruct::end(__struct) - }; - } - Style::Newtype => { - let field = &variant.fields[0]; - let mut field_expr = quote!(__field0); - if let Some(path) = field.attrs.serialize_with() { - field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); - } - - let span = field.original.span(); - let func = quote_spanned!(span=> _serde::ser::SerializeStruct::serialize_field); - return quote_block! { - let mut __struct = _serde::Serializer::serialize_struct( - __serializer, #type_name, 2)?; - _serde::ser::SerializeStruct::serialize_field( - &mut __struct, #tag, #serialize_variant)?; - #func( - &mut __struct, #content, #field_expr)?; - _serde::ser::SerializeStruct::end(__struct) - }; - } - Style::Tuple => { - serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields) - } - Style::Struct => serialize_struct_variant( - StructVariant::Untagged, - params, - &variant.fields, - variant_name, - ), - } - }); - - let fields_ty = variant.fields.iter().map(|f| &f.ty); - let fields_ident: &[_] = &match variant.style { - Style::Unit => { - if variant.attrs.serialize_with().is_some() { - vec![] - } else { - unreachable!() - } - } - Style::Newtype => vec![Member::Named(Ident::new("__field0", Span::call_site()))], - Style::Tuple => (0..variant.fields.len()) - .map(|i| Member::Named(Ident::new(&format!("__field{}", i), Span::call_site()))) - .collect(), - Style::Struct => variant.fields.iter().map(|f| f.member.clone()).collect(), - }; - - let (_, ty_generics, where_clause) = params.generics.split_for_impl(); - - let wrapper_generics = if fields_ident.is_empty() { - params.generics.clone() - } else { - bound::with_lifetime_bound(¶ms.generics, "'__a") - }; - let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl(); - - quote_block! { - #[doc(hidden)] - struct __AdjacentlyTagged #wrapper_generics #where_clause { - data: (#(&'__a #fields_ty,)*), - phantom: _serde::__private::PhantomData<#this_type #ty_generics>, - } - - impl #wrapper_impl_generics _serde::Serialize for __AdjacentlyTagged #wrapper_ty_generics #where_clause { - fn serialize<__S>(&self, __serializer: __S) -> _serde::__private::Result<__S::Ok, __S::Error> - where - __S: _serde::Serializer, - { - // Elements that have skip_serializing will be unused. - #[allow(unused_variables)] - let (#(#fields_ident,)*) = self.data; - #inner - } - } - - let mut __struct = _serde::Serializer::serialize_struct( - __serializer, #type_name, 2)?; - _serde::ser::SerializeStruct::serialize_field( - &mut __struct, #tag, #serialize_variant)?; - _serde::ser::SerializeStruct::serialize_field( - &mut __struct, #content, &__AdjacentlyTagged { - data: (#(#fields_ident,)*), - phantom: _serde::__private::PhantomData::<#this_type #ty_generics>, - })?; - _serde::ser::SerializeStruct::end(__struct) - } -} - -fn serialize_untagged_variant( - params: &Parameters, - variant: &Variant, - cattrs: &attr::Container, -) -> Fragment { - if let Some(path) = variant.attrs.serialize_with() { - let ser = wrap_serialize_variant_with(params, path, variant); - return quote_expr! { - _serde::Serialize::serialize(#ser, __serializer) - }; - } - - match effective_style(variant) { - Style::Unit => { - quote_expr! { - _serde::Serializer::serialize_unit(__serializer) - } - } - Style::Newtype => { - let field = &variant.fields[0]; - let mut field_expr = quote!(__field0); - if let Some(path) = field.attrs.serialize_with() { - field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); - } - - let span = field.original.span(); - let func = quote_spanned!(span=> _serde::Serialize::serialize); - quote_expr! { - #func(#field_expr, __serializer) - } - } - Style::Tuple => serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields), - Style::Struct => { - let type_name = cattrs.name().serialize_name(); - serialize_struct_variant(StructVariant::Untagged, params, &variant.fields, type_name) - } - } -} - -enum TupleVariant<'a> { - ExternallyTagged { - type_name: &'a str, - variant_index: u32, - variant_name: &'a str, - }, - Untagged, -} - -fn serialize_tuple_variant( - context: TupleVariant, - params: &Parameters, - fields: &[Field], -) -> Fragment { - let tuple_trait = match context { - TupleVariant::ExternallyTagged { .. } => TupleTrait::SerializeTupleVariant, - TupleVariant::Untagged => TupleTrait::SerializeTuple, - }; - - let serialize_stmts = serialize_tuple_struct_visitor(fields, params, true, &tuple_trait); - - let mut serialized_fields = fields - .iter() - .enumerate() - .filter(|(_, field)| !field.attrs.skip_serializing()) - .peekable(); - - let let_mut = mut_if(serialized_fields.peek().is_some()); - - let len = serialized_fields - .map(|(i, field)| match field.attrs.skip_serializing_if() { - None => quote!(1), - Some(path) => { - let field_expr = Ident::new(&format!("__field{}", i), Span::call_site()); - quote!(if #path(#field_expr) { 0 } else { 1 }) - } - }) - .fold(quote!(0), |sum, expr| quote!(#sum + #expr)); - - match context { - TupleVariant::ExternallyTagged { - type_name, - variant_index, - variant_name, - } => { - quote_block! { - let #let_mut __serde_state = _serde::Serializer::serialize_tuple_variant( - __serializer, - #type_name, - #variant_index, - #variant_name, - #len)?; - #(#serialize_stmts)* - _serde::ser::SerializeTupleVariant::end(__serde_state) - } - } - TupleVariant::Untagged => { - quote_block! { - let #let_mut __serde_state = _serde::Serializer::serialize_tuple( - __serializer, - #len)?; - #(#serialize_stmts)* - _serde::ser::SerializeTuple::end(__serde_state) - } - } - } -} - -enum StructVariant<'a> { - ExternallyTagged { - variant_index: u32, - variant_name: &'a str, - }, - InternallyTagged { - tag: &'a str, - variant_name: &'a str, - }, - Untagged, -} - -fn serialize_struct_variant( - context: StructVariant, - params: &Parameters, - fields: &[Field], - name: &str, -) -> Fragment { - if fields.iter().any(|field| field.attrs.flatten()) { - return serialize_struct_variant_with_flatten(context, params, fields, name); - } - - let struct_trait = match context { - StructVariant::ExternallyTagged { .. } => StructTrait::SerializeStructVariant, - StructVariant::InternallyTagged { .. } | StructVariant::Untagged => { - StructTrait::SerializeStruct - } - }; - - let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait); - - let mut serialized_fields = fields - .iter() - .filter(|&field| !field.attrs.skip_serializing()) - .peekable(); - - let let_mut = mut_if(serialized_fields.peek().is_some()); - - let len = serialized_fields - .map(|field| { - let member = &field.member; - - match field.attrs.skip_serializing_if() { - Some(path) => quote!(if #path(#member) { 0 } else { 1 }), - None => quote!(1), - } - }) - .fold(quote!(0), |sum, expr| quote!(#sum + #expr)); - - match context { - StructVariant::ExternallyTagged { - variant_index, - variant_name, - } => { - quote_block! { - let #let_mut __serde_state = _serde::Serializer::serialize_struct_variant( - __serializer, - #name, - #variant_index, - #variant_name, - #len, - )?; - #(#serialize_fields)* - _serde::ser::SerializeStructVariant::end(__serde_state) - } - } - StructVariant::InternallyTagged { tag, variant_name } => { - quote_block! { - let mut __serde_state = _serde::Serializer::serialize_struct( - __serializer, - #name, - #len + 1, - )?; - _serde::ser::SerializeStruct::serialize_field( - &mut __serde_state, - #tag, - #variant_name, - )?; - #(#serialize_fields)* - _serde::ser::SerializeStruct::end(__serde_state) - } - } - StructVariant::Untagged => { - quote_block! { - let #let_mut __serde_state = _serde::Serializer::serialize_struct( - __serializer, - #name, - #len, - )?; - #(#serialize_fields)* - _serde::ser::SerializeStruct::end(__serde_state) - } - } - } -} - -fn serialize_struct_variant_with_flatten( - context: StructVariant, - params: &Parameters, - fields: &[Field], - name: &str, -) -> Fragment { - let struct_trait = StructTrait::SerializeMap; - let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait); - - let mut serialized_fields = fields - .iter() - .filter(|&field| !field.attrs.skip_serializing()) - .peekable(); - - let let_mut = mut_if(serialized_fields.peek().is_some()); - - match context { - StructVariant::ExternallyTagged { - variant_index, - variant_name, - } => { - let this_type = ¶ms.this_type; - let fields_ty = fields.iter().map(|f| &f.ty); - let members = &fields.iter().map(|f| &f.member).collect::<Vec<_>>(); - - let (_, ty_generics, where_clause) = params.generics.split_for_impl(); - let wrapper_generics = bound::with_lifetime_bound(¶ms.generics, "'__a"); - let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl(); - - quote_block! { - #[doc(hidden)] - struct __EnumFlatten #wrapper_generics #where_clause { - data: (#(&'__a #fields_ty,)*), - phantom: _serde::__private::PhantomData<#this_type #ty_generics>, - } - - impl #wrapper_impl_generics _serde::Serialize for __EnumFlatten #wrapper_ty_generics #where_clause { - fn serialize<__S>(&self, __serializer: __S) -> _serde::__private::Result<__S::Ok, __S::Error> - where - __S: _serde::Serializer, - { - let (#(#members,)*) = self.data; - let #let_mut __serde_state = _serde::Serializer::serialize_map( - __serializer, - _serde::__private::None)?; - #(#serialize_fields)* - _serde::ser::SerializeMap::end(__serde_state) - } - } - - _serde::Serializer::serialize_newtype_variant( - __serializer, - #name, - #variant_index, - #variant_name, - &__EnumFlatten { - data: (#(#members,)*), - phantom: _serde::__private::PhantomData::<#this_type #ty_generics>, - }) - } - } - StructVariant::InternallyTagged { tag, variant_name } => { - quote_block! { - let #let_mut __serde_state = _serde::Serializer::serialize_map( - __serializer, - _serde::__private::None)?; - _serde::ser::SerializeMap::serialize_entry( - &mut __serde_state, - #tag, - #variant_name, - )?; - #(#serialize_fields)* - _serde::ser::SerializeMap::end(__serde_state) - } - } - StructVariant::Untagged => { - quote_block! { - let #let_mut __serde_state = _serde::Serializer::serialize_map( - __serializer, - _serde::__private::None)?; - #(#serialize_fields)* - _serde::ser::SerializeMap::end(__serde_state) - } - } - } -} - -fn serialize_tuple_struct_visitor( - fields: &[Field], - params: &Parameters, - is_enum: bool, - tuple_trait: &TupleTrait, -) -> Vec<TokenStream> { - fields - .iter() - .enumerate() - .filter(|(_, field)| !field.attrs.skip_serializing()) - .map(|(i, field)| { - let mut field_expr = if is_enum { - let id = Ident::new(&format!("__field{}", i), Span::call_site()); - quote!(#id) - } else { - get_member( - params, - field, - &Member::Unnamed(Index { - index: i as u32, - span: Span::call_site(), - }), - ) - }; - - let skip = field - .attrs - .skip_serializing_if() - .map(|path| quote!(#path(#field_expr))); - - if let Some(path) = field.attrs.serialize_with() { - field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); - } - - let span = field.original.span(); - let func = tuple_trait.serialize_element(span); - let ser = quote! { - #func(&mut __serde_state, #field_expr)?; - }; - - match skip { - None => ser, - Some(skip) => quote!(if !#skip { #ser }), - } - }) - .collect() -} - -fn serialize_struct_visitor( - fields: &[Field], - params: &Parameters, - is_enum: bool, - struct_trait: &StructTrait, -) -> Vec<TokenStream> { - fields - .iter() - .filter(|&field| !field.attrs.skip_serializing()) - .map(|field| { - let member = &field.member; - - let mut field_expr = if is_enum { - quote!(#member) - } else { - get_member(params, field, member) - }; - - let key_expr = field.attrs.name().serialize_name(); - - let skip = field - .attrs - .skip_serializing_if() - .map(|path| quote!(#path(#field_expr))); - - if let Some(path) = field.attrs.serialize_with() { - field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); - } - - let span = field.original.span(); - let ser = if field.attrs.flatten() { - let func = quote_spanned!(span=> _serde::Serialize::serialize); - quote! { - #func(&#field_expr, _serde::__private::ser::FlatMapSerializer(&mut __serde_state))?; - } - } else { - let func = struct_trait.serialize_field(span); - quote! { - #func(&mut __serde_state, #key_expr, #field_expr)?; - } - }; - - match skip { - None => ser, - Some(skip) => { - if let Some(skip_func) = struct_trait.skip_field(span) { - quote! { - if !#skip { - #ser - } else { - #skip_func(&mut __serde_state, #key_expr)?; - } - } - } else { - quote! { - if !#skip { - #ser - } - } - } - } - } - }) - .collect() -} - -fn wrap_serialize_field_with( - params: &Parameters, - field_ty: &syn::Type, - serialize_with: &syn::ExprPath, - field_expr: &TokenStream, -) -> TokenStream { - wrap_serialize_with(params, serialize_with, &[field_ty], &[quote!(#field_expr)]) -} - -fn wrap_serialize_variant_with( - params: &Parameters, - serialize_with: &syn::ExprPath, - variant: &Variant, -) -> TokenStream { - let field_tys: Vec<_> = variant.fields.iter().map(|field| field.ty).collect(); - let field_exprs: Vec<_> = variant - .fields - .iter() - .map(|field| { - let id = match &field.member { - Member::Named(ident) => ident.clone(), - Member::Unnamed(member) => { - Ident::new(&format!("__field{}", member.index), Span::call_site()) - } - }; - quote!(#id) - }) - .collect(); - wrap_serialize_with( - params, - serialize_with, - field_tys.as_slice(), - field_exprs.as_slice(), - ) -} - -fn wrap_serialize_with( - params: &Parameters, - serialize_with: &syn::ExprPath, - field_tys: &[&syn::Type], - field_exprs: &[TokenStream], -) -> TokenStream { - let this_type = ¶ms.this_type; - let (_, ty_generics, where_clause) = params.generics.split_for_impl(); - - let wrapper_generics = if field_exprs.is_empty() { - params.generics.clone() - } else { - bound::with_lifetime_bound(¶ms.generics, "'__a") - }; - let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl(); - - let field_access = (0..field_exprs.len()).map(|n| { - Member::Unnamed(Index { - index: n as u32, - span: Span::call_site(), - }) - }); - - quote!({ - #[doc(hidden)] - struct __SerializeWith #wrapper_impl_generics #where_clause { - values: (#(&'__a #field_tys, )*), - phantom: _serde::__private::PhantomData<#this_type #ty_generics>, - } - - impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause { - fn serialize<__S>(&self, __s: __S) -> _serde::__private::Result<__S::Ok, __S::Error> - where - __S: _serde::Serializer, - { - #serialize_with(#(self.values.#field_access, )* __s) - } - } - - &__SerializeWith { - values: (#(#field_exprs, )*), - phantom: _serde::__private::PhantomData::<#this_type #ty_generics>, - } - }) -} - -// Serialization of an empty struct results in code like: -// -// let mut __serde_state = serializer.serialize_struct("S", 0)?; -// _serde::ser::SerializeStruct::end(__serde_state) -// -// where we want to omit the `mut` to avoid a warning. -fn mut_if(is_mut: bool) -> Option<TokenStream> { - if is_mut { - Some(quote!(mut)) - } else { - None - } -} - -fn get_member(params: &Parameters, field: &Field, member: &Member) -> TokenStream { - let self_var = ¶ms.self_var; - match (params.is_remote, field.attrs.getter()) { - (false, None) => { - if params.is_packed { - quote!(&{#self_var.#member}) - } else { - quote!(&#self_var.#member) - } - } - (true, None) => { - let inner = if params.is_packed { - quote!(&{#self_var.#member}) - } else { - quote!(&#self_var.#member) - }; - let ty = field.ty; - quote!(_serde::__private::ser::constrain::<#ty>(#inner)) - } - (true, Some(getter)) => { - let ty = field.ty; - quote!(_serde::__private::ser::constrain::<#ty>(&#getter(#self_var))) - } - (false, Some(_)) => { - unreachable!("getter is only allowed for remote impls"); - } - } -} - -fn effective_style(variant: &Variant) -> Style { - match variant.style { - Style::Newtype if variant.fields[0].attrs.skip_serializing() => Style::Unit, - other => other, - } -} - -enum StructTrait { - SerializeMap, - SerializeStruct, - SerializeStructVariant, -} - -impl StructTrait { - fn serialize_field(&self, span: Span) -> TokenStream { - match *self { - StructTrait::SerializeMap => { - quote_spanned!(span=> _serde::ser::SerializeMap::serialize_entry) - } - StructTrait::SerializeStruct => { - quote_spanned!(span=> _serde::ser::SerializeStruct::serialize_field) - } - StructTrait::SerializeStructVariant => { - quote_spanned!(span=> _serde::ser::SerializeStructVariant::serialize_field) - } - } - } - - fn skip_field(&self, span: Span) -> Option<TokenStream> { - match *self { - StructTrait::SerializeMap => None, - StructTrait::SerializeStruct => { - Some(quote_spanned!(span=> _serde::ser::SerializeStruct::skip_field)) - } - StructTrait::SerializeStructVariant => { - Some(quote_spanned!(span=> _serde::ser::SerializeStructVariant::skip_field)) - } - } - } -} - -enum TupleTrait { - SerializeTuple, - SerializeTupleStruct, - SerializeTupleVariant, -} - -impl TupleTrait { - fn serialize_element(&self, span: Span) -> TokenStream { - match *self { - TupleTrait::SerializeTuple => { - quote_spanned!(span=> _serde::ser::SerializeTuple::serialize_element) - } - TupleTrait::SerializeTupleStruct => { - quote_spanned!(span=> _serde::ser::SerializeTupleStruct::serialize_field) - } - TupleTrait::SerializeTupleVariant => { - quote_spanned!(span=> _serde::ser::SerializeTupleVariant::serialize_field) - } - } - } -} |