Skip to content

Commit

Permalink
корректно обрабатываем skip в variant-with
Browse files Browse the repository at this point in the history
  • Loading branch information
Mingun committed Jul 31, 2023
1 parent 0c8fa03 commit 77b3293
Showing 1 changed file with 48 additions and 18 deletions.
66 changes: 48 additions & 18 deletions serde_derive/src/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::ptr;
use std::sync::atomic::Ordering;
use syn::punctuated::Punctuated;
use syn::spanned::Spanned;
use syn::{parse_quote, Ident, Index, Member};
use syn::{parse_quote, Ident, Index};

pub fn expand_derive_deserialize(input: &mut syn::DeriveInput) -> syn::Result<TokenStream> {
replace_receiver(input);
Expand Down Expand Up @@ -1859,10 +1859,16 @@ fn deserialize_externally_tagged_variant(
) -> Fragment {
// Feature https://github.com/serde-rs/serde/issues/1013
if let Some(path) = variant.attrs.deserialize_with() {
let field_tys = variant.fields.iter().map(|field| field.ty);
let field_tys = variant.fields.iter().filter_map(|field| {
if field.attrs.skip_deserializing() {
None
} else {
Some(field.ty)
}
});
let (wrapper, wrapper_ty) = wrap_deserialize_with(params, &quote!((#(#field_tys),*)), path);

let unwrap_fn = unwrap_to_variant_closure(params, variant, true);
let unwrap_fn = unwrap_to_variant_closure(params, variant, cattrs, true);

return quote_block! {
#wrapper
Expand Down Expand Up @@ -1949,7 +1955,7 @@ fn deserialize_untagged_variant(
) -> Fragment {
// Feature https://github.com/serde-rs/serde/issues/1013
if let Some(path) = variant.attrs.deserialize_with() {
let unwrap_fn = unwrap_to_variant_closure(params, variant, false);
let unwrap_fn = unwrap_to_variant_closure(params, variant, cattrs, false);
return quote_block! {
_serde::__private::Result::map(#path(#deserializer), #unwrap_fn)
};
Expand Down Expand Up @@ -3013,41 +3019,65 @@ fn wrap_deserialize_field_with(
fn unwrap_to_variant_closure(
params: &Parameters,
variant: &Variant,
cattrs: &attr::Container,
with_wrapper: bool,
) -> TokenStream {
let this_value = &params.this_value;
let variant_ident = &variant.ident;

let fields = variant
.fields
.iter()
.filter(|field| !field.attrs.skip_deserializing());
let (arg, wrapper) = if with_wrapper {
(quote! { __wrap }, quote! { __wrap.value })
} else {
let field_tys = variant.fields.iter().map(|field| field.ty);
let field_tys = fields.clone().map(|field| field.ty);
(quote! { __wrap: (#(#field_tys),*) }, quote! { __wrap })
};

let field_access = (0..variant.fields.len()).map(|n| {
Member::Unnamed(Index {
index: n as u32,
span: Span::call_site(),
})
});

match variant.style {
match variant.de_style() {
Style::Struct if variant.fields.len() == 1 => {
let member = &variant.fields[0].member;
quote! {
|#arg| #this_value::#variant_ident { #member: #wrapper }
}
}
Style::Struct => {
let members = variant.fields.iter().map(|field| &field.member);
let mut i = 0;
let members = variant.fields.iter().map(|field| {
let name = &field.member;
let index = Index::from(i);
i += 1;

if field.attrs.skip_deserializing() {
let expr = Expr(expr_is_missing(&field, cattrs));
quote!(#name: #expr)
} else {
quote!(#name: #wrapper.#index)
}
});
quote! {
|#arg| #this_value::#variant_ident { #(#members: #wrapper.#field_access),* }
|#arg| #this_value::#variant_ident { #(#members),* }
}
}
Style::Tuple => {
let mut i = 0;
let members = variant.fields.iter().map(|field| {
let index = Index::from(i);
i += 1;

if field.attrs.skip_deserializing() {
let expr = Expr(expr_is_missing(&field, cattrs));
quote!(#expr)
} else {
quote!(#wrapper.#index)
}
});
quote! {
|#arg| #this_value::#variant_ident(#(#members),*)
}
}
Style::Tuple => quote! {
|#arg| #this_value::#variant_ident(#(#wrapper.#field_access),*)
},
Style::Newtype => quote! {
|#arg| #this_value::#variant_ident(#wrapper)
},
Expand Down

0 comments on commit 77b3293

Please sign in to comment.