Replace several linked variables with enumeration for tuples

This commit is contained in:
Mingun
2023-05-07 01:28:47 +05:00
committed by Mingun
parent ee7d77defa
commit 4cf1fec575
+52 -29
View File
@@ -290,7 +290,7 @@ fn deserialize_body(cont: &Container, params: &Parameters) -> Fragment {
deserialize_struct(params, fields, &cont.attrs, StructForm::Struct) deserialize_struct(params, fields, &cont.attrs, StructForm::Struct)
} }
Data::Struct(Style::Tuple, fields) | Data::Struct(Style::Newtype, fields) => { Data::Struct(Style::Tuple, fields) | Data::Struct(Style::Newtype, fields) => {
deserialize_tuple(None, params, fields, &cont.attrs, None) deserialize_tuple(params, fields, &cont.attrs, TupleForm::Tuple)
} }
Data::Struct(Style::Unit, _) => deserialize_unit_struct(params, &cont.attrs), Data::Struct(Style::Unit, _) => deserialize_unit_struct(params, &cont.attrs),
} }
@@ -438,12 +438,20 @@ fn deserialize_unit_struct(params: &Parameters, cattrs: &attr::Container) -> Fra
} }
} }
enum TupleForm<'a> {
Tuple,
/// Contains a variant name
ExternallyTagged(&'a syn::Ident),
/// Contains a variant name and an intermediate deserializer from which actual
/// deserialization will be performed
Untagged(&'a syn::Ident, TokenStream),
}
fn deserialize_tuple( fn deserialize_tuple(
variant_ident: Option<&syn::Ident>,
params: &Parameters, params: &Parameters,
fields: &[Field], fields: &[Field],
cattrs: &attr::Container, cattrs: &attr::Container,
deserializer: Option<TokenStream>, form: TupleForm,
) -> Fragment { ) -> Fragment {
assert!(!cattrs.has_flatten()); assert!(!cattrs.has_flatten());
@@ -468,23 +476,27 @@ fn deserialize_tuple(
quote!(#this_value) quote!(#this_value)
}; };
let is_enum = variant_ident.is_some(); let type_path = match form {
let type_path = match variant_ident { TupleForm::Tuple => construct,
Some(variant_ident) => quote!(#construct::#variant_ident), TupleForm::ExternallyTagged(variant_ident) | TupleForm::Untagged(variant_ident, _) => {
None => construct, quote!(#construct::#variant_ident)
}
}; };
let expecting = match variant_ident { let expecting = match form {
Some(variant_ident) => format!("tuple variant {}::{}", params.type_name(), variant_ident), TupleForm::Tuple => format!("tuple struct {}", params.type_name()),
None => format!("tuple struct {}", params.type_name()), TupleForm::ExternallyTagged(variant_ident) | TupleForm::Untagged(variant_ident, _) => {
format!("tuple variant {}::{}", params.type_name(), variant_ident)
}
}; };
let expecting = cattrs.expecting().unwrap_or(&expecting); let expecting = cattrs.expecting().unwrap_or(&expecting);
let nfields = fields.len(); let nfields = fields.len();
let visit_newtype_struct = if !is_enum && nfields == 1 { let visit_newtype_struct = match form {
Some(deserialize_newtype_struct(&type_path, params, &fields[0])) TupleForm::Tuple if nfields == 1 => {
} else { Some(deserialize_newtype_struct(&type_path, params, &fields[0]))
None }
_ => None,
}; };
let visit_seq = Stmts(deserialize_seq( let visit_seq = Stmts(deserialize_seq(
@@ -497,16 +509,25 @@ fn deserialize_tuple(
lifetime: _serde::__private::PhantomData, lifetime: _serde::__private::PhantomData,
} }
}; };
let dispatch = if let Some(deserializer) = deserializer { let dispatch = match form {
quote!(_serde::Deserializer::deserialize_tuple(#deserializer, #field_count, #visitor_expr)) TupleForm::Tuple if nfields == 1 => {
} else if is_enum { let type_name = cattrs.name().deserialize_name();
quote!(_serde::de::VariantAccess::tuple_variant(__variant, #field_count, #visitor_expr)) quote! {
} else if nfields == 1 { _serde::Deserializer::deserialize_newtype_struct(__deserializer, #type_name, #visitor_expr)
let type_name = cattrs.name().deserialize_name(); }
quote!(_serde::Deserializer::deserialize_newtype_struct(__deserializer, #type_name, #visitor_expr)) }
} else { TupleForm::Tuple => {
let type_name = cattrs.name().deserialize_name(); let type_name = cattrs.name().deserialize_name();
quote!(_serde::Deserializer::deserialize_tuple_struct(__deserializer, #type_name, #field_count, #visitor_expr)) quote! {
_serde::Deserializer::deserialize_tuple_struct(__deserializer, #type_name, #field_count, #visitor_expr)
}
}
TupleForm::ExternallyTagged(_) => quote! {
_serde::de::VariantAccess::tuple_variant(__variant, #field_count, #visitor_expr)
},
TupleForm::Untagged(_, deserializer) => quote! {
_serde::Deserializer::deserialize_tuple(#deserializer, #field_count, #visitor_expr)
},
}; };
let visitor_var = if field_count == 0 { let visitor_var = if field_count == 0 {
@@ -1805,9 +1826,12 @@ fn deserialize_externally_tagged_variant(
&variant.fields[0], &variant.fields[0],
cattrs, cattrs,
), ),
Style::Tuple => { Style::Tuple => deserialize_tuple(
deserialize_tuple(Some(variant_ident), params, &variant.fields, cattrs, None) params,
} &variant.fields,
cattrs,
TupleForm::ExternallyTagged(variant_ident),
),
Style::Struct => deserialize_struct( Style::Struct => deserialize_struct(
params, params,
&variant.fields, &variant.fields,
@@ -1902,11 +1926,10 @@ fn deserialize_untagged_variant(
&deserializer, &deserializer,
), ),
Style::Tuple => deserialize_tuple( Style::Tuple => deserialize_tuple(
Some(variant_ident),
params, params,
&variant.fields, &variant.fields,
cattrs, cattrs,
Some(deserializer), TupleForm::Untagged(variant_ident, deserializer),
), ),
Style::Struct => deserialize_struct( Style::Struct => deserialize_struct(
params, params,