1use crate::de::enum_;
8use crate::de::struct_;
9use crate::de::tuple;
10use crate::de::{
11 expr_is_missing, field_i, unwrap_to_variant_closure, wrap_deserialize_field_with,
12 wrap_deserialize_with, Parameters, StructForm, TupleForm,
13};
14use crate::fragment::{Expr, Fragment, Match};
15use crate::internals::ast::{Field, Style, Variant};
16use crate::internals::attr;
17use crate::private;
18use proc_macro2::TokenStream;
19use quote::{quote, quote_spanned};
20use syn::spanned::Spanned;
21
22pub(super) fn deserialize(
24 params: &Parameters,
25 variants: &[Variant],
26 cattrs: &attr::Container,
27) -> Fragment {
28 let this_type = ¶ms.this_type;
29 let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
30 params.generics_with_de_lifetime();
31 let delife = params.borrowed.de_lifetime();
32
33 let type_name = cattrs.name().deserialize_name();
34 let expecting = format!("enum {}", params.type_name());
35 let expecting = cattrs.expecting().unwrap_or(&expecting);
36
37 let (variants_stmt, variant_visitor) = enum_::prepare_enum_variant_enum(variants);
38
39 let variant_arms = variants
41 .iter()
42 .enumerate()
43 .filter(|&(_, variant)| !variant.attrs.skip_deserializing())
44 .map(|(i, variant)| {
45 let variant_name = field_i(i);
46
47 let block = Match(deserialize_externally_tagged_variant(
48 params, variant, cattrs,
49 ));
50
51 quote! {
52 (__Field::#variant_name, __variant) => #block
53 }
54 });
55
56 let all_skipped = variants
57 .iter()
58 .all(|variant| variant.attrs.skip_deserializing());
59 let match_variant = if all_skipped {
60 quote! {
63 _serde::#private::Result::map(
67 _serde::de::EnumAccess::variant::<__Field>(__data),
68 |(__impossible, _)| match __impossible {})
69 }
70 } else {
71 quote! {
72 match _serde::de::EnumAccess::variant(__data)? {
73 #(#variant_arms)*
74 }
75 }
76 };
77
78 quote_block! {
79 #variant_visitor
80
81 #[doc(hidden)]
82 struct __Visitor #de_impl_generics #where_clause {
83 marker: _serde::#private::PhantomData<#this_type #ty_generics>,
84 lifetime: _serde::#private::PhantomData<&#delife ()>,
85 }
86
87 #[automatically_derived]
88 impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause {
89 type Value = #this_type #ty_generics;
90
91 fn expecting(&self, __formatter: &mut _serde::#private::Formatter) -> _serde::#private::fmt::Result {
92 _serde::#private::Formatter::write_str(__formatter, #expecting)
93 }
94
95 fn visit_enum<__A>(self, __data: __A) -> _serde::#private::Result<Self::Value, __A::Error>
96 where
97 __A: _serde::de::EnumAccess<#delife>,
98 {
99 #match_variant
100 }
101 }
102
103 #variants_stmt
104
105 _serde::Deserializer::deserialize_enum(
106 __deserializer,
107 #type_name,
108 VARIANTS,
109 __Visitor {
110 marker: _serde::#private::PhantomData::<#this_type #ty_generics>,
111 lifetime: _serde::#private::PhantomData,
112 },
113 )
114 }
115}
116
117fn deserialize_externally_tagged_variant(
118 params: &Parameters,
119 variant: &Variant,
120 cattrs: &attr::Container,
121) -> Fragment {
122 if let Some(path) = variant.attrs.deserialize_with() {
123 let (wrapper, wrapper_ty, unwrap_fn) = wrap_deserialize_variant_with(params, variant, path);
124 return quote_block! {
125 #wrapper
126 _serde::#private::Result::map(
127 _serde::de::VariantAccess::newtype_variant::<#wrapper_ty>(__variant), #unwrap_fn)
128 };
129 }
130
131 let variant_ident = &variant.ident;
132
133 match variant.style {
134 Style::Unit => {
135 let this_value = ¶ms.this_value;
136 quote_block! {
137 _serde::de::VariantAccess::unit_variant(__variant)?;
138 _serde::#private::Ok(#this_value::#variant_ident)
139 }
140 }
141 Style::Newtype => deserialize_externally_tagged_newtype_variant(
142 variant_ident,
143 params,
144 &variant.fields[0],
145 cattrs,
146 ),
147 Style::Tuple => tuple::deserialize(
148 params,
149 &variant.fields,
150 cattrs,
151 TupleForm::ExternallyTagged(variant_ident),
152 ),
153 Style::Struct => struct_::deserialize(
154 params,
155 &variant.fields,
156 cattrs,
157 StructForm::ExternallyTagged(variant_ident),
158 ),
159 }
160}
161
162fn wrap_deserialize_variant_with(
163 params: &Parameters,
164 variant: &Variant,
165 deserialize_with: &syn::ExprPath,
166) -> (TokenStream, TokenStream, TokenStream) {
167 let field_tys = variant.fields.iter().map(|field| field.ty);
168 let (wrapper, wrapper_ty) =
169 wrap_deserialize_with(params, "e!((#(#field_tys),*)), deserialize_with);
170
171 let unwrap_fn = unwrap_to_variant_closure(params, variant, true);
172
173 (wrapper, wrapper_ty, unwrap_fn)
174}
175
176fn deserialize_externally_tagged_newtype_variant(
177 variant_ident: &syn::Ident,
178 params: &Parameters,
179 field: &Field,
180 cattrs: &attr::Container,
181) -> Fragment {
182 let this_value = ¶ms.this_value;
183
184 if field.attrs.skip_deserializing() {
185 let default = Expr(expr_is_missing(field, cattrs));
186 return quote_block! {
187 _serde::de::VariantAccess::unit_variant(__variant)?;
188 _serde::#private::Ok(#this_value::#variant_ident(#default))
189 };
190 }
191
192 match field.attrs.deserialize_with() {
193 None => {
194 let field_ty = field.ty;
195 let span = field.original.span();
196 let func =
197 quote_spanned!(span=> _serde::de::VariantAccess::newtype_variant::<#field_ty>);
198 quote_expr! {
199 _serde::#private::Result::map(#func(__variant), #this_value::#variant_ident)
200 }
201 }
202 Some(path) => {
203 let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path);
204 quote_block! {
205 #wrapper
206 _serde::#private::Result::map(
207 _serde::de::VariantAccess::newtype_variant::<#wrapper_ty>(__variant),
208 |__wrapper| #this_value::#variant_ident(__wrapper.value))
209 }
210 }
211 }
212}