Skip to content

Commit

Permalink
Reuse a single ContentRefDeserializer throughout untagged enum deseri…
Browse files Browse the repository at this point in the history
…alization
  • Loading branch information
dtolnay committed Jun 8, 2023
1 parent 361c23a commit f60324e
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 15 deletions.
8 changes: 8 additions & 0 deletions serde/src/private/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>
where
E: de::Error,
Expand Down
22 changes: 7 additions & 15 deletions serde_derive/src/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1172,13 +1172,7 @@ fn deserialize_enum(
Some(variant_idx) => {
let (tagged, untagged) = variants.split_at(variant_idx);
let tagged_frag = Expr(deserialize_homogeneous_enum(params, tagged, cattrs));
let tagged_frag = |deserializer| {
Some(Expr(quote_block! {
let __deserializer = #deserializer;
#tagged_frag
}))
};
deserialize_untagged_enum_after(params, untagged, cattrs, tagged_frag)
deserialize_untagged_enum_after(params, untagged, cattrs, Some(tagged_frag))
}
None => deserialize_homogeneous_enum(params, variants, cattrs),
}
Expand Down Expand Up @@ -1689,17 +1683,16 @@ fn deserialize_untagged_enum(
variants: &[Variant],
cattrs: &attr::Container,
) -> 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(
params: &Parameters,
variants: &[Variant],
cattrs: &attr::Container,
first_attempt: impl FnOnce(TokenStream) -> Option<Expr>,
first_attempt: Option<Expr>,
) -> Fragment {
let deserializer =
quote!(_serde::__private::de::ContentRefDeserializer::<__D::Error>::new(&__content));
let attempts = variants
.iter()
.filter(|variant| !variant.attrs.skip_deserializing())
Expand All @@ -1708,12 +1701,10 @@ fn deserialize_untagged_enum_after(
params,
variant,
cattrs,
deserializer.clone(),
quote!(__deserializer),
))
});
let attempts = first_attempt(deserializer.clone())
.into_iter()
.chain(attempts);
let attempts = first_attempt.into_iter().chain(attempts);
// 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
// processed before an error, and use the error that happened after the
Expand All @@ -1728,6 +1719,7 @@ fn deserialize_untagged_enum_after(

quote_block! {
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 {
Expand Down

0 comments on commit f60324e

Please sign in to comment.