Merge pull request #2555 from Mingun/field

Refactor code that generates `__Field` enums
This commit is contained in:
David Tolnay
2023-08-06 18:23:52 -07:00
committed by GitHub
+39 -31
View File
@@ -965,12 +965,7 @@ fn deserialize_struct(
) )
}) })
.collect(); .collect();
let field_visitor = Stmts(deserialize_generated_identifier( let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs);
&field_names_idents,
cattrs,
false,
None,
));
// untagged struct variants do not get a visit_seq method. The same applies to // untagged struct variants do not get a visit_seq method. The same applies to
// structs that only have a map representation. // structs that only have a map representation.
@@ -1128,12 +1123,7 @@ fn deserialize_struct_in_place(
}) })
.collect(); .collect();
let field_visitor = Stmts(deserialize_generated_identifier( let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs);
&field_names_idents,
cattrs,
false,
None,
));
let mut_seq = if field_names_idents.is_empty() { let mut_seq = if field_names_idents.is_empty() {
quote!(_) quote!(_)
@@ -1247,7 +1237,12 @@ fn prepare_enum_variant_enum(
}) })
.collect(); .collect();
let other_idx = deserialized_variants.position(|(_, variant)| variant.attrs.other()); let fallthrough = deserialized_variants
.position(|(_, variant)| variant.attrs.other())
.map(|other_idx| {
let ignore_variant = variant_names_idents[other_idx].1.clone();
quote!(_serde::__private::Ok(__Field::#ignore_variant))
});
let variants_stmt = { let variants_stmt = {
let variant_names = variant_names_idents.iter().map(|(name, _, _)| name); let variant_names = variant_names_idents.iter().map(|(name, _, _)| name);
@@ -1261,7 +1256,8 @@ fn prepare_enum_variant_enum(
&variant_names_idents, &variant_names_idents,
cattrs, cattrs,
true, true,
other_idx, None,
fallthrough,
)); ));
(variants_stmt, variant_visitor) (variants_stmt, variant_visitor)
@@ -1986,27 +1982,12 @@ fn deserialize_generated_identifier(
fields: &[(&str, Ident, &BTreeSet<String>)], fields: &[(&str, Ident, &BTreeSet<String>)],
cattrs: &attr::Container, cattrs: &attr::Container,
is_variant: bool, is_variant: bool,
other_idx: Option<usize>, ignore_variant: Option<TokenStream>,
fallthrough: Option<TokenStream>,
) -> Fragment { ) -> Fragment {
let this_value = quote!(__Field); let this_value = quote!(__Field);
let field_idents: &Vec<_> = &fields.iter().map(|(_, ident, _)| ident).collect(); let field_idents: &Vec<_> = &fields.iter().map(|(_, ident, _)| ident).collect();
let (ignore_variant, fallthrough) = if !is_variant && cattrs.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 let Some(other_idx) = other_idx {
let ignore_variant = fields[other_idx].1.clone();
let fallthrough = quote!(_serde::__private::Ok(__Field::#ignore_variant));
(None, Some(fallthrough))
} else if is_variant || 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))
};
let visitor_impl = Stmts(deserialize_identifier( let visitor_impl = Stmts(deserialize_identifier(
&this_value, &this_value,
fields, fields,
@@ -2052,6 +2033,33 @@ fn deserialize_generated_identifier(
} }
} }
/// Generates enum and its `Deserialize` implementation that represents each
/// non-skipped field of the struct
fn deserialize_field_identifier(
fields: &[(&str, Ident, &BTreeSet<String>)],
cattrs: &attr::Container,
) -> Stmts {
let (ignore_variant, fallthrough) = if cattrs.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(deserialize_generated_identifier(
fields,
cattrs,
false,
ignore_variant,
fallthrough,
))
}
// Generates `Deserialize::deserialize` body for an enum with // Generates `Deserialize::deserialize` body for an enum with
// `serde(field_identifier)` or `serde(variant_identifier)` attribute. // `serde(field_identifier)` or `serde(variant_identifier)` attribute.
fn deserialize_custom_identifier( fn deserialize_custom_identifier(