From 8c3445efe4b81d31fd87ea0d4069de266795314e Mon Sep 17 00:00:00 2001 From: Mingun Date: Fri, 19 Sep 2025 21:39:47 +0500 Subject: [PATCH] Group some functions that used together --- serde_derive/src/de/enum_externally.rs | 28 +-- serde_derive/src/de/identifier.rs | 120 ++++++------- serde_derive/src/de/struct_.rs | 236 ++++++++++++------------- serde_derive/src/de/tuple.rs | 98 +++++----- 4 files changed, 241 insertions(+), 241 deletions(-) diff --git a/serde_derive/src/de/enum_externally.rs b/serde_derive/src/de/enum_externally.rs index b777571c..41c3aeaf 100644 --- a/serde_derive/src/de/enum_externally.rs +++ b/serde_derive/src/de/enum_externally.rs @@ -158,6 +158,20 @@ fn deserialize_externally_tagged_variant( } } +fn wrap_deserialize_variant_with( + params: &Parameters, + variant: &Variant, + deserialize_with: &syn::ExprPath, +) -> (TokenStream, TokenStream, TokenStream) { + let field_tys = variant.fields.iter().map(|field| field.ty); + let (wrapper, wrapper_ty) = + wrap_deserialize_with(params, "e!((#(#field_tys),*)), deserialize_with); + + let unwrap_fn = unwrap_to_variant_closure(params, variant, true); + + (wrapper, wrapper_ty, unwrap_fn) +} + fn deserialize_externally_tagged_newtype_variant( variant_ident: &syn::Ident, params: &Parameters, @@ -195,17 +209,3 @@ fn deserialize_externally_tagged_newtype_variant( } } } - -fn wrap_deserialize_variant_with( - params: &Parameters, - variant: &Variant, - deserialize_with: &syn::ExprPath, -) -> (TokenStream, TokenStream, TokenStream) { - let field_tys = variant.fields.iter().map(|field| field.ty); - let (wrapper, wrapper_ty) = - wrap_deserialize_with(params, "e!((#(#field_tys),*)), deserialize_with); - - let unwrap_fn = unwrap_to_variant_closure(params, variant, true); - - (wrapper, wrapper_ty, unwrap_fn) -} diff --git a/serde_derive/src/de/identifier.rs b/serde_derive/src/de/identifier.rs index 19c52e13..1b347b35 100644 --- a/serde_derive/src/de/identifier.rs +++ b/serde_derive/src/de/identifier.rs @@ -8,66 +8,6 @@ use crate::private; use proc_macro2::{Literal, TokenStream}; use quote::{quote, ToTokens}; -pub fn generate_identifier( - deserialized_fields: &[FieldWithAliases], - has_flatten: bool, - is_variant: bool, - ignore_variant: Option, - fallthrough: Option, -) -> Fragment { - let this_value = quote!(__Field); - let field_idents: &Vec<_> = &deserialized_fields - .iter() - .map(|field| &field.ident) - .collect(); - - let visitor_impl = Stmts(deserialize_identifier( - &this_value, - deserialized_fields, - is_variant, - fallthrough, - None, - !is_variant && has_flatten, - None, - )); - - let lifetime = if !is_variant && has_flatten { - Some(quote!(<'de>)) - } else { - None - }; - - quote_block! { - #[allow(non_camel_case_types)] - #[doc(hidden)] - enum __Field #lifetime { - #(#field_idents,)* - #ignore_variant - } - - #[doc(hidden)] - struct __FieldVisitor; - - #[automatically_derived] - impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { - type Value = __Field #lifetime; - - #visitor_impl - } - - #[automatically_derived] - impl<'de> _serde::Deserialize<'de> for __Field #lifetime { - #[inline] - fn deserialize<__D>(__deserializer: __D) -> _serde::#private::Result - where - __D: _serde::Deserializer<'de>, - { - _serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor) - } - } - } -} - // Generates `Deserialize::deserialize` body for an enum with // `serde(field_identifier)` or `serde(variant_identifier)` attribute. pub fn generate_body( @@ -180,6 +120,66 @@ pub fn generate_body( } } +pub fn generate_identifier( + deserialized_fields: &[FieldWithAliases], + has_flatten: bool, + is_variant: bool, + ignore_variant: Option, + fallthrough: Option, +) -> Fragment { + let this_value = quote!(__Field); + let field_idents: &Vec<_> = &deserialized_fields + .iter() + .map(|field| &field.ident) + .collect(); + + let visitor_impl = Stmts(deserialize_identifier( + &this_value, + deserialized_fields, + is_variant, + fallthrough, + None, + !is_variant && has_flatten, + None, + )); + + let lifetime = if !is_variant && has_flatten { + Some(quote!(<'de>)) + } else { + None + }; + + quote_block! { + #[allow(non_camel_case_types)] + #[doc(hidden)] + enum __Field #lifetime { + #(#field_idents,)* + #ignore_variant + } + + #[doc(hidden)] + struct __FieldVisitor; + + #[automatically_derived] + impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { + type Value = __Field #lifetime; + + #visitor_impl + } + + #[automatically_derived] + impl<'de> _serde::Deserialize<'de> for __Field #lifetime { + #[inline] + fn deserialize<__D>(__deserializer: __D) -> _serde::#private::Result + where + __D: _serde::Deserializer<'de>, + { + _serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor) + } + } + } +} + fn deserialize_identifier( this_value: &TokenStream, deserialized_fields: &[FieldWithAliases], diff --git a/serde_derive/src/de/struct_.rs b/serde_derive/src/de/struct_.rs index bef1c500..4d80e08f 100644 --- a/serde_derive/src/de/struct_.rs +++ b/serde_derive/src/de/struct_.rs @@ -195,124 +195,6 @@ pub fn generate_body( } } -/// Generates `Deserialize::deserialize_in_place` body for a `struct Struct {...}` -#[cfg(feature = "deserialize_in_place")] -pub fn generate_body_in_place( - params: &Parameters, - fields: &[Field], - cattrs: &attr::Container, -) -> Option { - // for now we do not support in_place deserialization for structs that - // are represented as map. - if has_flatten(fields) { - return None; - } - - let this_type = ¶ms.this_type; - let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = params.generics(); - let delife = params.borrowed.de_lifetime(); - - let expecting = format!("struct {}", params.type_name()); - let expecting = cattrs.expecting().unwrap_or(&expecting); - - let deserialized_fields: Vec<_> = fields - .iter() - .enumerate() - .filter(|&(_, field)| !field.attrs.skip_deserializing()) - .map(|(i, field)| FieldWithAliases { - ident: field_i(i), - aliases: field.attrs.aliases(), - }) - .collect(); - - let field_visitor = deserialize_field_identifier(&deserialized_fields, cattrs, false); - - let mut_seq = if deserialized_fields.is_empty() { - quote!(_) - } else { - quote!(mut __seq) - }; - let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, expecting)); - let visit_map = Stmts(deserialize_map_in_place(params, fields, cattrs)); - let field_names = deserialized_fields.iter().flat_map(|field| field.aliases); - let type_name = cattrs.name().deserialize_name(); - - let in_place_impl_generics = de_impl_generics.in_place(); - let in_place_ty_generics = de_ty_generics.in_place(); - let place_life = place_lifetime(); - - Some(quote_block! { - #field_visitor - - #[doc(hidden)] - struct __Visitor #in_place_impl_generics #where_clause { - place: &#place_life mut #this_type #ty_generics, - lifetime: _serde::#private::PhantomData<&#delife ()>, - } - - #[automatically_derived] - impl #in_place_impl_generics _serde::de::Visitor<#delife> for __Visitor #in_place_ty_generics #where_clause { - type Value = (); - - fn expecting(&self, __formatter: &mut _serde::#private::Formatter) -> _serde::#private::fmt::Result { - _serde::#private::Formatter::write_str(__formatter, #expecting) - } - - #[inline] - fn visit_seq<__A>(self, #mut_seq: __A) -> _serde::#private::Result - where - __A: _serde::de::SeqAccess<#delife>, - { - #visit_seq - } - - #[inline] - fn visit_map<__A>(self, mut __map: __A) -> _serde::#private::Result - where - __A: _serde::de::MapAccess<#delife>, - { - #visit_map - } - } - - #[doc(hidden)] - const FIELDS: &'static [&'static str] = &[ #(#field_names),* ]; - - _serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, __Visitor { - place: __place, - lifetime: _serde::#private::PhantomData, - }) - }) -} - -/// Generates enum and its `Deserialize` implementation that represents each -/// non-skipped field of the struct -fn deserialize_field_identifier( - deserialized_fields: &[FieldWithAliases], - cattrs: &attr::Container, - has_flatten: bool, -) -> Stmts { - let (ignore_variant, fallthrough) = if has_flatten { - let ignore_variant = quote!(__other(_serde::#private::de::Content<'de>),); - let fallthrough = quote!(_serde::#private::Ok(__Field::__other(__value))); - (Some(ignore_variant), Some(fallthrough)) - } else if cattrs.deny_unknown_fields() { - (None, None) - } else { - let ignore_variant = quote!(__ignore,); - let fallthrough = quote!(_serde::#private::Ok(__Field::__ignore)); - (Some(ignore_variant), Some(fallthrough)) - }; - - Stmts(identifier::generate_identifier( - deserialized_fields, - has_flatten, - false, - ignore_variant, - fallthrough, - )) -} - fn deserialize_map( struct_path: &TokenStream, params: &Parameters, @@ -535,6 +417,96 @@ fn deserialize_map( } } +/// Generates `Deserialize::deserialize_in_place` body for a `struct Struct {...}` +#[cfg(feature = "deserialize_in_place")] +pub fn generate_body_in_place( + params: &Parameters, + fields: &[Field], + cattrs: &attr::Container, +) -> Option { + // for now we do not support in_place deserialization for structs that + // are represented as map. + if has_flatten(fields) { + return None; + } + + let this_type = ¶ms.this_type; + let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = params.generics(); + let delife = params.borrowed.de_lifetime(); + + let expecting = format!("struct {}", params.type_name()); + let expecting = cattrs.expecting().unwrap_or(&expecting); + + let deserialized_fields: Vec<_> = fields + .iter() + .enumerate() + .filter(|&(_, field)| !field.attrs.skip_deserializing()) + .map(|(i, field)| FieldWithAliases { + ident: field_i(i), + aliases: field.attrs.aliases(), + }) + .collect(); + + let field_visitor = deserialize_field_identifier(&deserialized_fields, cattrs, false); + + let mut_seq = if deserialized_fields.is_empty() { + quote!(_) + } else { + quote!(mut __seq) + }; + let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, expecting)); + let visit_map = Stmts(deserialize_map_in_place(params, fields, cattrs)); + let field_names = deserialized_fields.iter().flat_map(|field| field.aliases); + let type_name = cattrs.name().deserialize_name(); + + let in_place_impl_generics = de_impl_generics.in_place(); + let in_place_ty_generics = de_ty_generics.in_place(); + let place_life = place_lifetime(); + + Some(quote_block! { + #field_visitor + + #[doc(hidden)] + struct __Visitor #in_place_impl_generics #where_clause { + place: &#place_life mut #this_type #ty_generics, + lifetime: _serde::#private::PhantomData<&#delife ()>, + } + + #[automatically_derived] + impl #in_place_impl_generics _serde::de::Visitor<#delife> for __Visitor #in_place_ty_generics #where_clause { + type Value = (); + + fn expecting(&self, __formatter: &mut _serde::#private::Formatter) -> _serde::#private::fmt::Result { + _serde::#private::Formatter::write_str(__formatter, #expecting) + } + + #[inline] + fn visit_seq<__A>(self, #mut_seq: __A) -> _serde::#private::Result + where + __A: _serde::de::SeqAccess<#delife>, + { + #visit_seq + } + + #[inline] + fn visit_map<__A>(self, mut __map: __A) -> _serde::#private::Result + where + __A: _serde::de::MapAccess<#delife>, + { + #visit_map + } + } + + #[doc(hidden)] + const FIELDS: &'static [&'static str] = &[ #(#field_names),* ]; + + _serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, __Visitor { + place: __place, + lifetime: _serde::#private::PhantomData, + }) + }) +} + #[cfg(feature = "deserialize_in_place")] fn deserialize_map_in_place( params: &Parameters, @@ -693,3 +665,31 @@ fn deserialize_map_in_place( _serde::#private::Ok(()) } } + +/// Generates enum and its `Deserialize` implementation that represents each +/// non-skipped field of the struct +fn deserialize_field_identifier( + deserialized_fields: &[FieldWithAliases], + cattrs: &attr::Container, + has_flatten: bool, +) -> Stmts { + let (ignore_variant, fallthrough) = if has_flatten { + let ignore_variant = quote!(__other(_serde::#private::de::Content<'de>),); + let fallthrough = quote!(_serde::#private::Ok(__Field::__other(__value))); + (Some(ignore_variant), Some(fallthrough)) + } else if cattrs.deny_unknown_fields() { + (None, None) + } else { + let ignore_variant = quote!(__ignore,); + let fallthrough = quote!(_serde::#private::Ok(__Field::__ignore)); + (Some(ignore_variant), Some(fallthrough)) + }; + + Stmts(identifier::generate_identifier( + deserialized_fields, + has_flatten, + false, + ignore_variant, + fallthrough, + )) +} diff --git a/serde_derive/src/de/tuple.rs b/serde_derive/src/de/tuple.rs index da3b286c..2a2d9f97 100644 --- a/serde_derive/src/de/tuple.rs +++ b/serde_derive/src/de/tuple.rs @@ -131,6 +131,55 @@ pub fn generate_body( } } +fn deserialize_newtype_struct( + type_path: &TokenStream, + params: &Parameters, + field: &Field, +) -> TokenStream { + let delife = params.borrowed.de_lifetime(); + let field_ty = field.ty; + let deserializer_var = quote!(__e); + + let value = match field.attrs.deserialize_with() { + None => { + let span = field.original.span(); + let func = quote_spanned!(span=> <#field_ty as _serde::Deserialize>::deserialize); + quote! { + #func(#deserializer_var)? + } + } + Some(path) => { + // If #path returns wrong type, error will be reported here (^^^^^). + // We attach span of the path to the function so it will be reported + // on the #[serde(with = "...")] + // ^^^^^ + quote_spanned! {path.span()=> + #path(#deserializer_var)? + } + } + }; + + let mut result = quote!(#type_path(__field0)); + if params.has_getter { + let this_type = ¶ms.this_type; + let (_, ty_generics, _) = params.generics.split_for_impl(); + result = quote! { + _serde::#private::Into::<#this_type #ty_generics>::into(#result) + }; + } + + quote! { + #[inline] + fn visit_newtype_struct<__E>(self, #deserializer_var: __E) -> _serde::#private::Result + where + __E: _serde::Deserializer<#delife>, + { + let __field0: #field_ty = #value; + _serde::#private::Ok(#result) + } + } +} + /// Generates `Deserialize::deserialize_in_place` body for a `struct Tuple(...);` including `struct Newtype(T);` #[cfg(feature = "deserialize_in_place")] pub fn generate_body_in_place( @@ -230,52 +279,3 @@ pub fn generate_body_in_place( #dispatch } } - -fn deserialize_newtype_struct( - type_path: &TokenStream, - params: &Parameters, - field: &Field, -) -> TokenStream { - let delife = params.borrowed.de_lifetime(); - let field_ty = field.ty; - let deserializer_var = quote!(__e); - - let value = match field.attrs.deserialize_with() { - None => { - let span = field.original.span(); - let func = quote_spanned!(span=> <#field_ty as _serde::Deserialize>::deserialize); - quote! { - #func(#deserializer_var)? - } - } - Some(path) => { - // If #path returns wrong type, error will be reported here (^^^^^). - // We attach span of the path to the function so it will be reported - // on the #[serde(with = "...")] - // ^^^^^ - quote_spanned! {path.span()=> - #path(#deserializer_var)? - } - } - }; - - let mut result = quote!(#type_path(__field0)); - if params.has_getter { - let this_type = ¶ms.this_type; - let (_, ty_generics, _) = params.generics.split_for_impl(); - result = quote! { - _serde::#private::Into::<#this_type #ty_generics>::into(#result) - }; - } - - quote! { - #[inline] - fn visit_newtype_struct<__E>(self, #deserializer_var: __E) -> _serde::#private::Result - where - __E: _serde::Deserializer<#delife>, - { - let __field0: #field_ty = #value; - _serde::#private::Ok(#result) - } - } -}