Skip to content

Commit

Permalink
Merge pull request #2555 from Mingun/field
Browse files Browse the repository at this point in the history
Refactor code that generates `__Field` enums
  • Loading branch information
dtolnay committed Aug 7, 2023
2 parents aaadd93 + 070cce0 commit 3bff326
Showing 1 changed file with 39 additions and 31 deletions.
70 changes: 39 additions & 31 deletions serde_derive/src/de.rs
Expand Up @@ -965,12 +965,7 @@ fn deserialize_struct(
)
})
.collect();
let field_visitor = Stmts(deserialize_generated_identifier(
&field_names_idents,
cattrs,
false,
None,
));
let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs);

// untagged struct variants do not get a visit_seq method. The same applies to
// structs that only have a map representation.
Expand Down Expand Up @@ -1128,12 +1123,7 @@ fn deserialize_struct_in_place(
})
.collect();

let field_visitor = Stmts(deserialize_generated_identifier(
&field_names_idents,
cattrs,
false,
None,
));
let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs);

let mut_seq = if field_names_idents.is_empty() {
quote!(_)
Expand Down Expand Up @@ -1247,7 +1237,12 @@ fn prepare_enum_variant_enum(
})
.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 variant_names = variant_names_idents.iter().map(|(name, _, _)| name);
Expand All @@ -1261,7 +1256,8 @@ fn prepare_enum_variant_enum(
&variant_names_idents,
cattrs,
true,
other_idx,
None,
fallthrough,
));

(variants_stmt, variant_visitor)
Expand Down Expand Up @@ -1986,27 +1982,12 @@ fn deserialize_generated_identifier(
fields: &[(&str, Ident, &BTreeSet<String>)],
cattrs: &attr::Container,
is_variant: bool,
other_idx: Option<usize>,
ignore_variant: Option<TokenStream>,
fallthrough: Option<TokenStream>,
) -> Fragment {
let this_value = quote!(__Field);
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(
&this_value,
fields,
Expand Down Expand Up @@ -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
// `serde(field_identifier)` or `serde(variant_identifier)` attribute.
fn deserialize_custom_identifier(
Expand Down

0 comments on commit 3bff326

Please sign in to comment.