Skip to content

Commit 502a065

Browse files
authored
Merge pull request #2987 from Mingun/split-de-generator
Refactor: split de generator over multiple files
2 parents 1799547 + 027112e commit 502a065

10 files changed

Lines changed: 2487 additions & 2395 deletions

File tree

serde_derive/src/de.rs

Lines changed: 115 additions & 2395 deletions
Large diffs are not rendered by default.

serde_derive/src/de/enum_.rs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
use crate::de::enum_adjacently;
2+
use crate::de::enum_externally;
3+
use crate::de::enum_internally;
4+
use crate::de::enum_untagged;
5+
use crate::de::identifier;
6+
use crate::de::{field_i, FieldWithAliases, Parameters};
7+
use crate::fragment::{Expr, Fragment, Stmts};
8+
use crate::internals::ast::Variant;
9+
use crate::internals::attr;
10+
use crate::private;
11+
use proc_macro2::TokenStream;
12+
use quote::quote;
13+
14+
/// Generates `Deserialize::deserialize` body for an `enum Enum {...}`
15+
pub(super) fn generate_body(
16+
params: &Parameters,
17+
variants: &[Variant],
18+
cattrs: &attr::Container,
19+
) -> Fragment {
20+
// The variants have already been checked (in ast.rs) that all untagged variants appear at the end
21+
match variants.iter().position(|var| var.attrs.untagged()) {
22+
Some(variant_idx) => {
23+
let (tagged, untagged) = variants.split_at(variant_idx);
24+
let tagged_frag = Expr(deserialize_homogeneous_enum(params, tagged, cattrs));
25+
// Ignore any error associated with non-untagged deserialization so that we
26+
// can fall through to the untagged variants. This may be infallible so we
27+
// need to provide the error type.
28+
let tagged_frag = quote! {
29+
if let _serde::#private::Result::<_, __D::Error>::Ok(__ok) = (|| #tagged_frag)() {
30+
return _serde::#private::Ok(__ok);
31+
}
32+
};
33+
enum_untagged::generate_body(params, untagged, cattrs, Some(tagged_frag))
34+
}
35+
None => deserialize_homogeneous_enum(params, variants, cattrs),
36+
}
37+
}
38+
39+
fn deserialize_homogeneous_enum(
40+
params: &Parameters,
41+
variants: &[Variant],
42+
cattrs: &attr::Container,
43+
) -> Fragment {
44+
match cattrs.tag() {
45+
attr::TagType::External => enum_externally::generate_body(params, variants, cattrs),
46+
attr::TagType::Internal { tag } => {
47+
enum_internally::generate_body(params, variants, cattrs, tag)
48+
}
49+
attr::TagType::Adjacent { tag, content } => {
50+
enum_adjacently::generate_body(params, variants, cattrs, tag, content)
51+
}
52+
attr::TagType::None => enum_untagged::generate_body(params, variants, cattrs, None),
53+
}
54+
}
55+
56+
pub fn prepare_enum_variant_enum(variants: &[Variant]) -> (TokenStream, Stmts) {
57+
let deserialized_variants = variants
58+
.iter()
59+
.enumerate()
60+
.filter(|&(_i, variant)| !variant.attrs.skip_deserializing());
61+
62+
let fallthrough = deserialized_variants
63+
.clone()
64+
.find(|(_i, variant)| variant.attrs.other())
65+
.map(|(i, _variant)| {
66+
let ignore_variant = field_i(i);
67+
quote!(_serde::#private::Ok(__Field::#ignore_variant))
68+
});
69+
70+
let variants_stmt = {
71+
let variant_names = deserialized_variants
72+
.clone()
73+
.flat_map(|(_i, variant)| variant.attrs.aliases());
74+
quote! {
75+
#[doc(hidden)]
76+
const VARIANTS: &'static [&'static str] = &[ #(#variant_names),* ];
77+
}
78+
};
79+
80+
let deserialized_variants: Vec<_> = deserialized_variants
81+
.map(|(i, variant)| FieldWithAliases {
82+
ident: field_i(i),
83+
aliases: variant.attrs.aliases(),
84+
})
85+
.collect();
86+
87+
let variant_visitor = Stmts(identifier::generate_identifier(
88+
&deserialized_variants,
89+
false, // variant identifiers do not depend on the presence of flatten fields
90+
true,
91+
None,
92+
fallthrough,
93+
));
94+
95+
(variants_stmt, variant_visitor)
96+
}

0 commit comments

Comments
 (0)