1use crate::de::enum_adjacently;
2use crate::de::enum_externally;
3use crate::de::enum_internally;
4use crate::de::enum_untagged;
5use crate::de::identifier;
6use crate::de::{field_i, FieldWithAliases, Parameters};
7use crate::fragment::{Expr, Fragment, Stmts};
8use crate::internals::ast::Variant;
9use crate::internals::attr;
10use crate::private;
11use proc_macro2::TokenStream;
12use quote::quote;
13
14pub(super) fn deserialize(
16 params: &Parameters,
17 variants: &[Variant],
18 cattrs: &attr::Container,
19) -> Fragment {
20 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 let first_attempt = {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "if");
::quote::__private::push_ident(&mut _s, "let");
::quote::__private::push_ident(&mut _s, "_serde");
::quote::__private::push_colon2(&mut _s);
::quote::ToTokens::to_tokens(&private, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Result");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_lt(&mut _s);
::quote::__private::push_underscore(&mut _s);
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "__D");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Error");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Ok");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "__ok");
_s
});
::quote::__private::push_eq(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_or_or(&mut _s);
::quote::ToTokens::to_tokens(&tagged_frag, &mut _s);
_s
});
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "return");
::quote::__private::push_ident(&mut _s, "_serde");
::quote::__private::push_colon2(&mut _s);
::quote::ToTokens::to_tokens(&private, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Ok");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "__ok");
_s
});
::quote::__private::push_semi(&mut _s);
_s
});
_s
}quote! {
29 if let _serde::#private::Result::<_, __D::Error>::Ok(__ok) = (|| #tagged_frag)() {
30 return _serde::#private::Ok(__ok);
31 }
32 };
33 enum_untagged::deserialize(params, untagged, cattrs, Some(first_attempt))
34 }
35 None => deserialize_homogeneous_enum(params, variants, cattrs),
36 }
37}
38
39fn 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::deserialize(params, variants, cattrs),
46 attr::TagType::Internal { tag } => {
47 enum_internally::deserialize(params, variants, cattrs, tag)
48 }
49 attr::TagType::Adjacent { tag, content } => {
50 enum_adjacently::deserialize(params, variants, cattrs, tag, content)
51 }
52 attr::TagType::None => enum_untagged::deserialize(params, variants, cattrs, None),
53 }
54}
55
56pub 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 {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "_serde");
::quote::__private::push_colon2(&mut _s);
::quote::ToTokens::to_tokens(&private, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Ok");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "__Field");
::quote::__private::push_colon2(&mut _s);
::quote::ToTokens::to_tokens(&ignore_variant, &mut _s);
_s
});
_s
}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 {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "hidden");
_s
});
_s
});
::quote::__private::push_ident(&mut _s, "const");
::quote::__private::push_ident(&mut _s, "VARIANTS");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_and(&mut _s);
::quote::__private::push_lifetime(&mut _s, "\'static");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_and(&mut _s);
::quote::__private::push_lifetime(&mut _s, "\'static");
::quote::__private::push_ident(&mut _s, "str");
_s
});
::quote::__private::push_eq(&mut _s);
::quote::__private::push_and(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let mut _i = 0usize;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut variant_names, i) = variant_names.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let variant_names =
match variant_names.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
if _i > 0 { ::quote::__private::push_comma(&mut _s); }
_i += 1;
::quote::ToTokens::to_tokens(&variant_names, &mut _s);
}
}
_s
});
::quote::__private::push_semi(&mut _s);
_s
}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::deserialize_generated(
88 &deserialized_variants,
89 false, true,
91 None,
92 fallthrough,
93 ));
94
95 (variants_stmt, variant_visitor)
96}