Merge pull request 1992 from Mingun/unnecessary-deserialize-with

This commit is contained in:
David Tolnay 2021-08-21 12:46:13 -07:00
commit c1ce03b3dd
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
2 changed files with 62 additions and 16 deletions

View File

@ -1728,6 +1728,8 @@ fn deserialize_externally_tagged_variant(
} }
} }
// Generates significant part of the visit_seq and visit_map bodies of visitors
// for the variants of internally tagged enum.
fn deserialize_internally_tagged_variant( fn deserialize_internally_tagged_variant(
params: &Parameters, params: &Parameters,
variant: &Variant, variant: &Variant,
@ -1779,11 +1781,9 @@ fn deserialize_untagged_variant(
deserializer: TokenStream, deserializer: TokenStream,
) -> Fragment { ) -> Fragment {
if let Some(path) = variant.attrs.deserialize_with() { if let Some(path) = variant.attrs.deserialize_with() {
let (wrapper, wrapper_ty, unwrap_fn) = wrap_deserialize_variant_with(params, variant, path); let unwrap_fn = unwrap_to_variant_closure(params, variant, false);
return quote_block! { return quote_block! {
#wrapper _serde::__private::Result::map(#path(#deserializer), #unwrap_fn)
_serde::__private::Result::map(
<#wrapper_ty as _serde::Deserialize>::deserialize(#deserializer), #unwrap_fn)
}; };
} }
@ -2883,44 +2883,67 @@ fn wrap_deserialize_variant_with(
variant: &Variant, variant: &Variant,
deserialize_with: &syn::ExprPath, deserialize_with: &syn::ExprPath,
) -> (TokenStream, TokenStream, TokenStream) { ) -> (TokenStream, TokenStream, TokenStream) {
let this = &params.this;
let variant_ident = &variant.ident;
let field_tys = variant.fields.iter().map(|field| field.ty); let field_tys = variant.fields.iter().map(|field| field.ty);
let (wrapper, wrapper_ty) = let (wrapper, wrapper_ty) =
wrap_deserialize_with(params, &quote!((#(#field_tys),*)), deserialize_with); wrap_deserialize_with(params, &quote!((#(#field_tys),*)), deserialize_with);
let unwrap_fn = unwrap_to_variant_closure(params, variant, true);
(wrapper, wrapper_ty, unwrap_fn)
}
// Generates closure that converts single input parameter to the final value.
fn unwrap_to_variant_closure(
params: &Parameters,
variant: &Variant,
with_wrapper: bool,
) -> TokenStream {
let this = &params.this;
let variant_ident = &variant.ident;
let (arg, wrapper) = if with_wrapper {
(
quote!{ __wrap },
quote!{ __wrap.value },
)
} else {
let field_tys = variant.fields.iter().map(|field| field.ty);
(
quote!{ __wrap: (#(#field_tys),*) },
quote!{ __wrap },
)
};
let field_access = (0..variant.fields.len()).map(|n| { let field_access = (0..variant.fields.len()).map(|n| {
Member::Unnamed(Index { Member::Unnamed(Index {
index: n as u32, index: n as u32,
span: Span::call_site(), span: Span::call_site(),
}) })
}); });
let unwrap_fn = match variant.style {
match variant.style {
Style::Struct if variant.fields.len() == 1 => { Style::Struct if variant.fields.len() == 1 => {
let member = &variant.fields[0].member; let member = &variant.fields[0].member;
quote! { quote! {
|__wrap| #this::#variant_ident { #member: __wrap.value } |#arg| #this::#variant_ident { #member: #wrapper }
} }
} }
Style::Struct => { Style::Struct => {
let members = variant.fields.iter().map(|field| &field.member); let members = variant.fields.iter().map(|field| &field.member);
quote! { quote! {
|__wrap| #this::#variant_ident { #(#members: __wrap.value.#field_access),* } |#arg| #this::#variant_ident { #(#members: #wrapper.#field_access),* }
} }
} }
Style::Tuple => quote! { Style::Tuple => quote! {
|__wrap| #this::#variant_ident(#(__wrap.value.#field_access),*) |#arg| #this::#variant_ident(#(#wrapper.#field_access),*)
}, },
Style::Newtype => quote! { Style::Newtype => quote! {
|__wrap| #this::#variant_ident(__wrap.value) |#arg| #this::#variant_ident(#wrapper)
}, },
Style::Unit => quote! { Style::Unit => quote! {
|__wrap| #this::#variant_ident |#arg| #this::#variant_ident
}, },
}; }
(wrapper, wrapper_ty, unwrap_fn)
} }
fn expr_is_missing(field: &Field, cattrs: &attr::Container) -> Fragment { fn expr_is_missing(field: &Field, cattrs: &attr::Container) -> Fragment {

View File

@ -823,3 +823,26 @@ where
{ {
vec.first().serialize(serializer) vec.first().serialize(serializer)
} }
//////////////////////////////////////////////////////////////////////////
#[derive(Debug, PartialEq, Deserialize)]
#[serde(tag = "tag")]
enum InternallyTagged {
#[serde(deserialize_with = "deserialize_generic")]
Unit,
#[serde(deserialize_with = "deserialize_generic")]
Newtype(i32),
#[serde(deserialize_with = "deserialize_generic")]
Struct { f1: String, f2: u8 },
}
fn deserialize_generic<'de, T, D>(deserializer: D) -> StdResult<T, D::Error>
where
T: Deserialize<'de>,
D: Deserializer<'de>,
{
T::deserialize(deserializer)
}