Move body generator for internally tagged enums to its own module

Cut-paste
This commit is contained in:
Mingun
2025-06-14 16:30:43 +05:00
parent 85d0b9ccd8
commit ae00c4acb7
2 changed files with 106 additions and 89 deletions
+2 -89
View File
@@ -14,6 +14,7 @@ use syn::{parse_quote, Ident, Index, Member};
mod enum_adjacently;
mod enum_externally;
mod enum_internally;
pub fn expand_derive_deserialize(input: &mut syn::DeriveInput) -> syn::Result<TokenStream> {
replace_receiver(input);
@@ -1262,7 +1263,7 @@ fn deserialize_homogeneous_enum(
match cattrs.tag() {
attr::TagType::External => enum_externally::deserialize_externally_tagged_enum(params, variants, cattrs),
attr::TagType::Internal { tag } => {
deserialize_internally_tagged_enum(params, variants, cattrs, tag)
enum_internally::deserialize_internally_tagged_enum(params, variants, cattrs, tag)
}
attr::TagType::Adjacent { tag, content } => {
enum_adjacently::deserialize_adjacently_tagged_enum(params, variants, cattrs, tag, content)
@@ -1313,51 +1314,6 @@ fn prepare_enum_variant_enum(variants: &[Variant]) -> (TokenStream, Stmts) {
(variants_stmt, variant_visitor)
}
/// Generates `Deserialize::deserialize` body for an `enum Enum {...}` with `#[serde(tag)]` attribute
fn deserialize_internally_tagged_enum(
params: &Parameters,
variants: &[Variant],
cattrs: &attr::Container,
tag: &str,
) -> Fragment {
let (variants_stmt, variant_visitor) = prepare_enum_variant_enum(variants);
// Match arms to extract a variant from a string
let variant_arms = variants
.iter()
.enumerate()
.filter(|&(_, variant)| !variant.attrs.skip_deserializing())
.map(|(i, variant)| {
let variant_name = field_i(i);
let block = Match(deserialize_internally_tagged_variant(
params, variant, cattrs,
));
quote! {
__Field::#variant_name => #block
}
});
let expecting = format!("internally tagged enum {}", params.type_name());
let expecting = cattrs.expecting().unwrap_or(&expecting);
quote_block! {
#variant_visitor
#variants_stmt
let (__tag, __content) = _serde::Deserializer::deserialize_any(
__deserializer,
_serde::#private::de::TaggedContentVisitor::<__Field>::new(#tag, #expecting))?;
let __deserializer = _serde::#private::de::ContentDeserializer::<__D::Error>::new(__content);
match __tag {
#(#variant_arms)*
}
}
}
/// Generates `Deserialize::deserialize` body for an `enum Enum {...}` with `#[serde(untagged)]` attribute
fn deserialize_untagged_enum(
params: &Parameters,
@@ -1398,49 +1354,6 @@ fn deserialize_untagged_enum(
}
}
// Generates significant part of the visit_seq and visit_map bodies of visitors
// for the variants of internally tagged enum.
fn deserialize_internally_tagged_variant(
params: &Parameters,
variant: &Variant,
cattrs: &attr::Container,
) -> Fragment {
if let Some(path) = variant.attrs.deserialize_with() {
let unwrap_fn = unwrap_to_variant_closure(params, variant, false);
return quote_block! {
_serde::#private::Result::map(#path(__deserializer), #unwrap_fn)
};
}
let variant_ident = &variant.ident;
match effective_style(variant) {
Style::Unit => {
let this_value = &params.this_value;
let type_name = params.type_name();
let variant_name = variant.ident.to_string();
let default = variant.fields.first().map(|field| {
let default = Expr(expr_is_missing(field, cattrs));
quote!((#default))
});
quote_block! {
_serde::Deserializer::deserialize_any(__deserializer, _serde::#private::de::InternallyTaggedUnitVisitor::new(#type_name, #variant_name))?;
_serde::#private::Ok(#this_value::#variant_ident #default)
}
}
Style::Newtype => {
deserialize_untagged_newtype_variant(variant_ident, params, &variant.fields[0])
}
Style::Struct => deserialize_struct(
params,
&variant.fields,
cattrs,
StructForm::InternallyTagged(variant_ident),
),
Style::Tuple => unreachable!("checked in serde_derive_internals"),
}
}
fn deserialize_untagged_variant(
params: &Parameters,
variant: &Variant,