serde_derive/de/
enum_internally.rs1use crate::de::enum_;
9use crate::de::enum_untagged;
10use crate::de::struct_;
11use crate::de::{
12 effective_style, expr_is_missing, field_i, unwrap_to_variant_closure, Parameters, StructForm,
13};
14use crate::fragment::{Expr, Fragment, Match};
15use crate::internals::ast::{Style, Variant};
16use crate::internals::attr;
17use crate::private;
18use quote::quote;
19
20pub(super) fn deserialize(
22 params: &Parameters,
23 variants: &[Variant],
24 cattrs: &attr::Container,
25 tag: &str,
26) -> Fragment {
27 let (variants_stmt, variant_visitor) = enum_::prepare_enum_variant_enum(variants);
28
29 let variant_arms = variants
31 .iter()
32 .enumerate()
33 .filter(|&(_, variant)| !variant.attrs.skip_deserializing())
34 .map(|(i, variant)| {
35 let variant_name = field_i(i);
36
37 let block = Match(deserialize_internally_tagged_variant(
38 params, variant, cattrs,
39 ));
40
41 quote! {
42 __Field::#variant_name => #block
43 }
44 });
45
46 let expecting = format!("internally tagged enum {}", params.type_name());
47 let expecting = cattrs.expecting().unwrap_or(&expecting);
48
49 quote_block! {
50 #variant_visitor
51
52 #variants_stmt
53
54 let (__tag, __content) = _serde::Deserializer::deserialize_any(
55 __deserializer,
56 _serde::#private::de::TaggedContentVisitor::<__Field>::new(#tag, #expecting))?;
57 let __deserializer = _serde::#private::de::ContentDeserializer::<__D::Error>::new(__content);
58
59 match __tag {
60 #(#variant_arms)*
61 }
62 }
63}
64
65fn deserialize_internally_tagged_variant(
68 params: &Parameters,
69 variant: &Variant,
70 cattrs: &attr::Container,
71) -> Fragment {
72 if let Some(path) = variant.attrs.deserialize_with() {
73 let unwrap_fn = unwrap_to_variant_closure(params, variant, false);
74 return quote_block! {
75 _serde::#private::Result::map(#path(__deserializer), #unwrap_fn)
76 };
77 }
78
79 let variant_ident = &variant.ident;
80
81 match effective_style(variant) {
82 Style::Unit => {
83 let this_value = ¶ms.this_value;
84 let type_name = params.type_name();
85 let variant_name = variant.ident.to_string();
86 let default = variant.fields.first().map(|field| {
87 let default = Expr(expr_is_missing(field, cattrs));
88 quote!((#default))
89 });
90 quote_block! {
91 _serde::Deserializer::deserialize_any(__deserializer, _serde::#private::de::InternallyTaggedUnitVisitor::new(#type_name, #variant_name))?;
92 _serde::#private::Ok(#this_value::#variant_ident #default)
93 }
94 }
95 Style::Newtype => {
96 enum_untagged::deserialize_newtype_variant(variant_ident, params, &variant.fields[0])
97 }
98 Style::Struct => struct_::deserialize(
99 params,
100 &variant.fields,
101 cattrs,
102 StructForm::InternallyTagged(variant_ident),
103 ),
104 Style::Tuple => unreachable!("checked in serde_derive_internals"),
105 }
106}