Skip to content

Commit af4c388

Browse files
authored
Merge pull request #2843 from dtolnay/fieldwithaliases
Collect field ident and aliases into a struct
2 parents 1f9eb83 + 09f6d93 commit af4c388

File tree

1 file changed

+52
-37
lines changed

1 file changed

+52
-37
lines changed

serde_derive/src/de.rs

+52-37
Original file line numberDiff line numberDiff line change
@@ -966,25 +966,28 @@ fn deserialize_struct(
966966
};
967967
let expecting = cattrs.expecting().unwrap_or(&expecting);
968968

969-
let field_idents_aliases: Vec<_> = fields
969+
let deserialized_fields: Vec<_> = fields
970970
.iter()
971971
.enumerate()
972972
// Skip fields that shouldn't be deserialized or that were flattened,
973973
// so they don't appear in the storage in their literal form
974974
.filter(|&(_, field)| !field.attrs.skip_deserializing() && !field.attrs.flatten())
975-
.map(|(i, field)| (field_i(i), field.attrs.aliases()))
975+
.map(|(i, field)| FieldWithAliases {
976+
ident: field_i(i),
977+
aliases: field.attrs.aliases(),
978+
})
976979
.collect();
977980

978981
let has_flatten = has_flatten(fields);
979-
let field_visitor = deserialize_field_identifier(&field_idents_aliases, cattrs, has_flatten);
982+
let field_visitor = deserialize_field_identifier(&deserialized_fields, cattrs, has_flatten);
980983

981984
// untagged struct variants do not get a visit_seq method. The same applies to
982985
// structs that only have a map representation.
983986
let visit_seq = match form {
984987
StructForm::Untagged(..) => None,
985988
_ if has_flatten => None,
986989
_ => {
987-
let mut_seq = if field_idents_aliases.is_empty() {
990+
let mut_seq = if deserialized_fields.is_empty() {
988991
quote!(_)
989992
} else {
990993
quote!(mut __seq)
@@ -1032,9 +1035,7 @@ fn deserialize_struct(
10321035
let fields_stmt = if has_flatten {
10331036
None
10341037
} else {
1035-
let field_names = field_idents_aliases
1036-
.iter()
1037-
.flat_map(|&(_, aliases)| aliases);
1038+
let field_names = deserialized_fields.iter().flat_map(|field| field.aliases);
10381039

10391040
Some(quote! {
10401041
#[doc(hidden)]
@@ -1127,25 +1128,26 @@ fn deserialize_struct_in_place(
11271128
let expecting = format!("struct {}", params.type_name());
11281129
let expecting = cattrs.expecting().unwrap_or(&expecting);
11291130

1130-
let field_idents_aliases: Vec<_> = fields
1131+
let deserialized_fields: Vec<_> = fields
11311132
.iter()
11321133
.enumerate()
11331134
.filter(|&(_, field)| !field.attrs.skip_deserializing())
1134-
.map(|(i, field)| (field_i(i), field.attrs.aliases()))
1135+
.map(|(i, field)| FieldWithAliases {
1136+
ident: field_i(i),
1137+
aliases: field.attrs.aliases(),
1138+
})
11351139
.collect();
11361140

1137-
let field_visitor = deserialize_field_identifier(&field_idents_aliases, cattrs, false);
1141+
let field_visitor = deserialize_field_identifier(&deserialized_fields, cattrs, false);
11381142

1139-
let mut_seq = if field_idents_aliases.is_empty() {
1143+
let mut_seq = if deserialized_fields.is_empty() {
11401144
quote!(_)
11411145
} else {
11421146
quote!(mut __seq)
11431147
};
11441148
let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, expecting));
11451149
let visit_map = Stmts(deserialize_map_in_place(params, fields, cattrs));
1146-
let field_names = field_idents_aliases
1147-
.iter()
1148-
.flat_map(|&(_, aliases)| aliases);
1150+
let field_names = deserialized_fields.iter().flat_map(|field| field.aliases);
11491151
let type_name = cattrs.name().deserialize_name();
11501152

11511153
let in_place_impl_generics = de_impl_generics.in_place();
@@ -1252,12 +1254,15 @@ fn prepare_enum_variant_enum(variants: &[Variant]) -> (TokenStream, Stmts) {
12521254
}
12531255
};
12541256

1255-
let variant_idents_aliases: Vec<_> = deserialized_variants
1256-
.map(|(i, variant)| (field_i(i), variant.attrs.aliases()))
1257+
let deserialized_variants: Vec<_> = deserialized_variants
1258+
.map(|(i, variant)| FieldWithAliases {
1259+
ident: field_i(i),
1260+
aliases: variant.attrs.aliases(),
1261+
})
12571262
.collect();
12581263

12591264
let variant_visitor = Stmts(deserialize_generated_identifier(
1260-
&variant_idents_aliases,
1265+
&deserialized_variants,
12611266
false, // variant identifiers do not depend on the presence of flatten fields
12621267
true,
12631268
None,
@@ -1994,22 +1999,27 @@ fn deserialize_untagged_newtype_variant(
19941999
}
19952000
}
19962001

2002+
struct FieldWithAliases<'a> {
2003+
ident: Ident,
2004+
aliases: &'a BTreeSet<String>,
2005+
}
2006+
19972007
fn deserialize_generated_identifier(
1998-
field_idents_aliases: &[(Ident, &BTreeSet<String>)],
2008+
deserialized_fields: &[FieldWithAliases],
19992009
has_flatten: bool,
20002010
is_variant: bool,
20012011
ignore_variant: Option<TokenStream>,
20022012
fallthrough: Option<TokenStream>,
20032013
) -> Fragment {
20042014
let this_value = quote!(__Field);
2005-
let field_idents: &Vec<_> = &field_idents_aliases
2015+
let field_idents: &Vec<_> = &deserialized_fields
20062016
.iter()
2007-
.map(|(ident, _)| ident)
2017+
.map(|field| &field.ident)
20082018
.collect();
20092019

20102020
let visitor_impl = Stmts(deserialize_identifier(
20112021
&this_value,
2012-
field_idents_aliases,
2022+
deserialized_fields,
20132023
is_variant,
20142024
fallthrough,
20152025
None,
@@ -2055,7 +2065,7 @@ fn deserialize_generated_identifier(
20552065
/// Generates enum and its `Deserialize` implementation that represents each
20562066
/// non-skipped field of the struct
20572067
fn deserialize_field_identifier(
2058-
field_idents_aliases: &[(Ident, &BTreeSet<String>)],
2068+
deserialized_fields: &[FieldWithAliases],
20592069
cattrs: &attr::Container,
20602070
has_flatten: bool,
20612071
) -> Stmts {
@@ -2072,7 +2082,7 @@ fn deserialize_field_identifier(
20722082
};
20732083

20742084
Stmts(deserialize_generated_identifier(
2075-
field_idents_aliases,
2085+
deserialized_fields,
20762086
has_flatten,
20772087
false,
20782088
ignore_variant,
@@ -2132,10 +2142,13 @@ fn deserialize_custom_identifier(
21322142

21332143
let idents_aliases: Vec<_> = ordinary
21342144
.iter()
2135-
.map(|variant| (variant.ident.clone(), variant.attrs.aliases()))
2145+
.map(|variant| FieldWithAliases {
2146+
ident: variant.ident.clone(),
2147+
aliases: variant.attrs.aliases(),
2148+
})
21362149
.collect();
21372150

2138-
let names = idents_aliases.iter().flat_map(|&(_, aliases)| aliases);
2151+
let names = idents_aliases.iter().flat_map(|variant| variant.aliases);
21392152

21402153
let names_const = if fallthrough.is_some() {
21412154
None
@@ -2191,20 +2204,24 @@ fn deserialize_custom_identifier(
21912204

21922205
fn deserialize_identifier(
21932206
this_value: &TokenStream,
2194-
field_idents_aliases: &[(Ident, &BTreeSet<String>)],
2207+
deserialized_fields: &[FieldWithAliases],
21952208
is_variant: bool,
21962209
fallthrough: Option<TokenStream>,
21972210
fallthrough_borrowed: Option<TokenStream>,
21982211
collect_other_fields: bool,
21992212
expecting: Option<&str>,
22002213
) -> Fragment {
2201-
let str_mapping = field_idents_aliases.iter().map(|(ident, aliases)| {
2214+
let str_mapping = deserialized_fields.iter().map(|field| {
2215+
let ident = &field.ident;
2216+
let aliases = field.aliases;
22022217
// `aliases` also contains a main name
22032218
quote!(#(#aliases)|* => _serde::__private::Ok(#this_value::#ident))
22042219
});
2205-
let bytes_mapping = field_idents_aliases.iter().map(|(ident, aliases)| {
2220+
let bytes_mapping = deserialized_fields.iter().map(|field| {
2221+
let ident = &field.ident;
22062222
// `aliases` also contains a main name
2207-
let aliases = aliases
2223+
let aliases = field
2224+
.aliases
22082225
.iter()
22092226
.map(|alias| Literal::byte_string(alias.as_bytes()));
22102227
quote!(#(#aliases)|* => _serde::__private::Ok(#this_value::#ident))
@@ -2357,13 +2374,11 @@ fn deserialize_identifier(
23572374
}
23582375
}
23592376
} else {
2360-
let u64_mapping = field_idents_aliases
2361-
.iter()
2362-
.enumerate()
2363-
.map(|(i, (ident, _))| {
2364-
let i = i as u64;
2365-
quote!(#i => _serde::__private::Ok(#this_value::#ident))
2366-
});
2377+
let u64_mapping = deserialized_fields.iter().enumerate().map(|(i, field)| {
2378+
let i = i as u64;
2379+
let ident = &field.ident;
2380+
quote!(#i => _serde::__private::Ok(#this_value::#ident))
2381+
});
23672382

23682383
let u64_fallthrough_arm_tokens;
23692384
let u64_fallthrough_arm = if let Some(fallthrough) = &fallthrough {
@@ -2373,7 +2388,7 @@ fn deserialize_identifier(
23732388
let fallthrough_msg = format!(
23742389
"{} index 0 <= i < {}",
23752390
index_expecting,
2376-
field_idents_aliases.len(),
2391+
deserialized_fields.len(),
23772392
);
23782393
u64_fallthrough_arm_tokens = quote! {
23792394
_serde::__private::Err(_serde::de::Error::invalid_value(

0 commit comments

Comments
 (0)