Reuse a single ContentRefDeserializer throughout untagged enum deserialization

This commit is contained in:
David Tolnay
2023-06-07 21:33:11 -07:00
parent 361c23a09a
commit f60324e883
2 changed files with 15 additions and 15 deletions
+8
View File
@@ -2193,6 +2193,14 @@ mod content {
} }
} }
impl<'a, 'de: 'a, E> Copy for ContentRefDeserializer<'a, 'de, E> {}
impl<'a, 'de: 'a, E> Clone for ContentRefDeserializer<'a, 'de, E> {
fn clone(&self) -> Self {
*self
}
}
struct EnumRefDeserializer<'a, 'de: 'a, E> struct EnumRefDeserializer<'a, 'de: 'a, E>
where where
E: de::Error, E: de::Error,
+7 -15
View File
@@ -1172,13 +1172,7 @@ fn deserialize_enum(
Some(variant_idx) => { Some(variant_idx) => {
let (tagged, untagged) = variants.split_at(variant_idx); let (tagged, untagged) = variants.split_at(variant_idx);
let tagged_frag = Expr(deserialize_homogeneous_enum(params, tagged, cattrs)); let tagged_frag = Expr(deserialize_homogeneous_enum(params, tagged, cattrs));
let tagged_frag = |deserializer| { deserialize_untagged_enum_after(params, untagged, cattrs, Some(tagged_frag))
Some(Expr(quote_block! {
let __deserializer = #deserializer;
#tagged_frag
}))
};
deserialize_untagged_enum_after(params, untagged, cattrs, tagged_frag)
} }
None => deserialize_homogeneous_enum(params, variants, cattrs), None => deserialize_homogeneous_enum(params, variants, cattrs),
} }
@@ -1689,17 +1683,16 @@ fn deserialize_untagged_enum(
variants: &[Variant], variants: &[Variant],
cattrs: &attr::Container, cattrs: &attr::Container,
) -> Fragment { ) -> Fragment {
deserialize_untagged_enum_after(params, variants, cattrs, |_| None) let first_attempt = None;
deserialize_untagged_enum_after(params, variants, cattrs, first_attempt)
} }
fn deserialize_untagged_enum_after( fn deserialize_untagged_enum_after(
params: &Parameters, params: &Parameters,
variants: &[Variant], variants: &[Variant],
cattrs: &attr::Container, cattrs: &attr::Container,
first_attempt: impl FnOnce(TokenStream) -> Option<Expr>, first_attempt: Option<Expr>,
) -> Fragment { ) -> Fragment {
let deserializer =
quote!(_serde::__private::de::ContentRefDeserializer::<__D::Error>::new(&__content));
let attempts = variants let attempts = variants
.iter() .iter()
.filter(|variant| !variant.attrs.skip_deserializing()) .filter(|variant| !variant.attrs.skip_deserializing())
@@ -1708,12 +1701,10 @@ fn deserialize_untagged_enum_after(
params, params,
variant, variant,
cattrs, cattrs,
deserializer.clone(), quote!(__deserializer),
)) ))
}); });
let attempts = first_attempt(deserializer.clone()) let attempts = first_attempt.into_iter().chain(attempts);
.into_iter()
.chain(attempts);
// TODO this message could be better by saving the errors from the failed // TODO this message could be better by saving the errors from the failed
// attempts. The heuristic used by TOML was to count the number of fields // attempts. The heuristic used by TOML was to count the number of fields
// processed before an error, and use the error that happened after the // processed before an error, and use the error that happened after the
@@ -1728,6 +1719,7 @@ fn deserialize_untagged_enum_after(
quote_block! { quote_block! {
let __content = try!(<_serde::__private::de::Content as _serde::Deserialize>::deserialize(__deserializer)); let __content = try!(<_serde::__private::de::Content as _serde::Deserialize>::deserialize(__deserializer));
let __deserializer = _serde::__private::de::ContentRefDeserializer::<__D::Error>::new(&__content);
#( #(
if let _serde::__private::Ok(__ok) = #attempts { if let _serde::__private::Ok(__ok) = #attempts {