mirror of
https://github.com/serde-rs/serde.git
synced 2025-09-26 20:40:35 +00:00
Move body generator for enums to its own module
Cut-paste
This commit is contained in:
parent
ec13eb4ed6
commit
19956e6b8e
@ -12,6 +12,7 @@ use syn::punctuated::Punctuated;
|
||||
use syn::spanned::Spanned;
|
||||
use syn::{parse_quote, Ident, Index, Member};
|
||||
|
||||
mod enum_;
|
||||
mod enum_adjacently;
|
||||
mod enum_externally;
|
||||
mod enum_internally;
|
||||
@ -307,7 +308,7 @@ fn deserialize_body(cont: &Container, params: &Parameters) -> Fragment {
|
||||
deserialize_try_from(type_try_from)
|
||||
} else if let attr::Identifier::No = cont.attrs.identifier() {
|
||||
match &cont.data {
|
||||
Data::Enum(variants) => deserialize_enum(params, variants, &cont.attrs),
|
||||
Data::Enum(variants) => enum_::deserialize_enum(params, variants, &cont.attrs),
|
||||
Data::Struct(Style::Struct, fields) => {
|
||||
deserialize_struct(params, fields, &cont.attrs, StructForm::Struct)
|
||||
}
|
||||
@ -1231,90 +1232,6 @@ fn deserialize_struct_in_place(
|
||||
})
|
||||
}
|
||||
|
||||
/// Generates `Deserialize::deserialize` body for an `enum Enum {...}`
|
||||
fn deserialize_enum(
|
||||
params: &Parameters,
|
||||
variants: &[Variant],
|
||||
cattrs: &attr::Container,
|
||||
) -> Fragment {
|
||||
// The variants have already been checked (in ast.rs) that all untagged variants appear at the end
|
||||
match variants.iter().position(|var| var.attrs.untagged()) {
|
||||
Some(variant_idx) => {
|
||||
let (tagged, untagged) = variants.split_at(variant_idx);
|
||||
let tagged_frag = Expr(deserialize_homogeneous_enum(params, tagged, cattrs));
|
||||
// Ignore any error associated with non-untagged deserialization so that we
|
||||
// can fall through to the untagged variants. This may be infallible so we
|
||||
// need to provide the error type.
|
||||
let tagged_frag = quote! {
|
||||
if let _serde::#private::Result::<_, __D::Error>::Ok(__ok) = (|| #tagged_frag)() {
|
||||
return _serde::#private::Ok(__ok);
|
||||
}
|
||||
};
|
||||
enum_untagged::deserialize_untagged_enum(params, untagged, cattrs, Some(tagged_frag))
|
||||
}
|
||||
None => deserialize_homogeneous_enum(params, variants, cattrs),
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_homogeneous_enum(
|
||||
params: &Parameters,
|
||||
variants: &[Variant],
|
||||
cattrs: &attr::Container,
|
||||
) -> Fragment {
|
||||
match cattrs.tag() {
|
||||
attr::TagType::External => enum_externally::deserialize_externally_tagged_enum(params, variants, cattrs),
|
||||
attr::TagType::Internal { 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)
|
||||
}
|
||||
attr::TagType::None => enum_untagged::deserialize_untagged_enum(params, variants, cattrs, None),
|
||||
}
|
||||
}
|
||||
|
||||
fn prepare_enum_variant_enum(variants: &[Variant]) -> (TokenStream, Stmts) {
|
||||
let deserialized_variants = variants
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|&(_i, variant)| !variant.attrs.skip_deserializing());
|
||||
|
||||
let fallthrough = deserialized_variants
|
||||
.clone()
|
||||
.find(|(_i, variant)| variant.attrs.other())
|
||||
.map(|(i, _variant)| {
|
||||
let ignore_variant = field_i(i);
|
||||
quote!(_serde::#private::Ok(__Field::#ignore_variant))
|
||||
});
|
||||
|
||||
let variants_stmt = {
|
||||
let variant_names = deserialized_variants
|
||||
.clone()
|
||||
.flat_map(|(_i, variant)| variant.attrs.aliases());
|
||||
quote! {
|
||||
#[doc(hidden)]
|
||||
const VARIANTS: &'static [&'static str] = &[ #(#variant_names),* ];
|
||||
}
|
||||
};
|
||||
|
||||
let deserialized_variants: Vec<_> = deserialized_variants
|
||||
.map(|(i, variant)| FieldWithAliases {
|
||||
ident: field_i(i),
|
||||
aliases: variant.attrs.aliases(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
let variant_visitor = Stmts(deserialize_generated_identifier(
|
||||
&deserialized_variants,
|
||||
false, // variant identifiers do not depend on the presence of flatten fields
|
||||
true,
|
||||
None,
|
||||
fallthrough,
|
||||
));
|
||||
|
||||
(variants_stmt, variant_visitor)
|
||||
}
|
||||
|
||||
struct FieldWithAliases<'a> {
|
||||
ident: Ident,
|
||||
aliases: &'a BTreeSet<Name>,
|
||||
|
95
serde_derive/src/de/enum_.rs
Normal file
95
serde_derive/src/de/enum_.rs
Normal file
@ -0,0 +1,95 @@
|
||||
use crate::de::enum_adjacently;
|
||||
use crate::de::enum_externally;
|
||||
use crate::de::enum_internally;
|
||||
use crate::de::enum_untagged;
|
||||
use crate::de::{deserialize_generated_identifier, field_i, FieldWithAliases, Parameters};
|
||||
use crate::fragment::{Expr, Fragment, Stmts};
|
||||
use crate::internals::ast::Variant;
|
||||
use crate::internals::attr;
|
||||
use crate::private;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
|
||||
/// Generates `Deserialize::deserialize` body for an `enum Enum {...}`
|
||||
pub fn deserialize_enum(
|
||||
params: &Parameters,
|
||||
variants: &[Variant],
|
||||
cattrs: &attr::Container,
|
||||
) -> Fragment {
|
||||
// The variants have already been checked (in ast.rs) that all untagged variants appear at the end
|
||||
match variants.iter().position(|var| var.attrs.untagged()) {
|
||||
Some(variant_idx) => {
|
||||
let (tagged, untagged) = variants.split_at(variant_idx);
|
||||
let tagged_frag = Expr(deserialize_homogeneous_enum(params, tagged, cattrs));
|
||||
// Ignore any error associated with non-untagged deserialization so that we
|
||||
// can fall through to the untagged variants. This may be infallible so we
|
||||
// need to provide the error type.
|
||||
let tagged_frag = quote! {
|
||||
if let _serde::#private::Result::<_, __D::Error>::Ok(__ok) = (|| #tagged_frag)() {
|
||||
return _serde::#private::Ok(__ok);
|
||||
}
|
||||
};
|
||||
enum_untagged::deserialize_untagged_enum(params, untagged, cattrs, Some(tagged_frag))
|
||||
}
|
||||
None => deserialize_homogeneous_enum(params, variants, cattrs),
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_homogeneous_enum(
|
||||
params: &Parameters,
|
||||
variants: &[Variant],
|
||||
cattrs: &attr::Container,
|
||||
) -> Fragment {
|
||||
match cattrs.tag() {
|
||||
attr::TagType::External => enum_externally::deserialize_externally_tagged_enum(params, variants, cattrs),
|
||||
attr::TagType::Internal { 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)
|
||||
}
|
||||
attr::TagType::None => enum_untagged::deserialize_untagged_enum(params, variants, cattrs, None),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn prepare_enum_variant_enum(variants: &[Variant]) -> (TokenStream, Stmts) {
|
||||
let deserialized_variants = variants
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|&(_i, variant)| !variant.attrs.skip_deserializing());
|
||||
|
||||
let fallthrough = deserialized_variants
|
||||
.clone()
|
||||
.find(|(_i, variant)| variant.attrs.other())
|
||||
.map(|(i, _variant)| {
|
||||
let ignore_variant = field_i(i);
|
||||
quote!(_serde::#private::Ok(__Field::#ignore_variant))
|
||||
});
|
||||
|
||||
let variants_stmt = {
|
||||
let variant_names = deserialized_variants
|
||||
.clone()
|
||||
.flat_map(|(_i, variant)| variant.attrs.aliases());
|
||||
quote! {
|
||||
#[doc(hidden)]
|
||||
const VARIANTS: &'static [&'static str] = &[ #(#variant_names),* ];
|
||||
}
|
||||
};
|
||||
|
||||
let deserialized_variants: Vec<_> = deserialized_variants
|
||||
.map(|(i, variant)| FieldWithAliases {
|
||||
ident: field_i(i),
|
||||
aliases: variant.attrs.aliases(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
let variant_visitor = Stmts(deserialize_generated_identifier(
|
||||
&deserialized_variants,
|
||||
false, // variant identifiers do not depend on the presence of flatten fields
|
||||
true,
|
||||
None,
|
||||
fallthrough,
|
||||
));
|
||||
|
||||
(variants_stmt, variant_visitor)
|
||||
}
|
@ -5,8 +5,9 @@
|
||||
//! enum Enum {}
|
||||
//! ```
|
||||
|
||||
use crate::de::enum_;
|
||||
use crate::de::enum_untagged;
|
||||
use crate::de::{field_i, prepare_enum_variant_enum, Parameters};
|
||||
use crate::de::{field_i, Parameters};
|
||||
use crate::fragment::{Fragment, Match};
|
||||
use crate::internals::ast::{Style, Variant};
|
||||
use crate::internals::attr;
|
||||
@ -27,7 +28,7 @@ pub fn deserialize_adjacently_tagged_enum(
|
||||
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = params.generics();
|
||||
let delife = params.borrowed.de_lifetime();
|
||||
|
||||
let (variants_stmt, variant_visitor) = prepare_enum_variant_enum(variants);
|
||||
let (variants_stmt, variant_visitor) = enum_::prepare_enum_variant_enum(variants);
|
||||
|
||||
let variant_arms: &Vec<_> = &variants
|
||||
.iter()
|
||||
|
@ -4,8 +4,9 @@
|
||||
//! enum Enum {}
|
||||
//! ```
|
||||
|
||||
use crate::de::enum_;
|
||||
use crate::de::{
|
||||
deserialize_struct, deserialize_tuple, expr_is_missing, field_i, prepare_enum_variant_enum,
|
||||
deserialize_struct, deserialize_tuple, expr_is_missing, field_i,
|
||||
unwrap_to_variant_closure, wrap_deserialize_field_with, wrap_deserialize_with, Parameters,
|
||||
StructForm, TupleForm,
|
||||
};
|
||||
@ -31,7 +32,7 @@ pub fn deserialize_externally_tagged_enum(
|
||||
let expecting = format!("enum {}", params.type_name());
|
||||
let expecting = cattrs.expecting().unwrap_or(&expecting);
|
||||
|
||||
let (variants_stmt, variant_visitor) = prepare_enum_variant_enum(variants);
|
||||
let (variants_stmt, variant_visitor) = enum_::prepare_enum_variant_enum(variants);
|
||||
|
||||
// Match arms to extract a variant from a string
|
||||
let variant_arms = variants
|
||||
|
@ -5,9 +5,10 @@
|
||||
//! enum Enum {}
|
||||
//! ```
|
||||
|
||||
use crate::de::enum_;
|
||||
use crate::de::enum_untagged;
|
||||
use crate::de::{
|
||||
deserialize_struct, effective_style, expr_is_missing, field_i, prepare_enum_variant_enum,
|
||||
deserialize_struct, effective_style, expr_is_missing, field_i,
|
||||
unwrap_to_variant_closure, Parameters, StructForm,
|
||||
};
|
||||
use crate::fragment::{Expr, Fragment, Match};
|
||||
@ -23,7 +24,7 @@ pub fn deserialize_internally_tagged_enum(
|
||||
cattrs: &attr::Container,
|
||||
tag: &str,
|
||||
) -> Fragment {
|
||||
let (variants_stmt, variant_visitor) = prepare_enum_variant_enum(variants);
|
||||
let (variants_stmt, variant_visitor) = enum_::prepare_enum_variant_enum(variants);
|
||||
|
||||
// Match arms to extract a variant from a string
|
||||
let variant_arms = variants
|
||||
|
Loading…
x
Reference in New Issue
Block a user