mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-06-14 04:41:01 +00:00
Move body generator for structs to its own module
Cut-paste
This commit is contained in:
+4
-684
@@ -1,5 +1,5 @@
|
|||||||
use crate::deprecated::allow_deprecated;
|
use crate::deprecated::allow_deprecated;
|
||||||
use crate::fragment::{Expr, Fragment, Match, Stmts};
|
use crate::fragment::{Expr, Fragment, Stmts};
|
||||||
use crate::internals::ast::{Container, Data, Field, Style, Variant};
|
use crate::internals::ast::{Container, Data, Field, Style, Variant};
|
||||||
use crate::internals::name::Name;
|
use crate::internals::name::Name;
|
||||||
use crate::internals::{attr, replace_receiver, ungroup, Ctxt, Derive};
|
use crate::internals::{attr, replace_receiver, ungroup, Ctxt, Derive};
|
||||||
@@ -17,6 +17,7 @@ mod enum_adjacently;
|
|||||||
mod enum_externally;
|
mod enum_externally;
|
||||||
mod enum_internally;
|
mod enum_internally;
|
||||||
mod enum_untagged;
|
mod enum_untagged;
|
||||||
|
mod struct_;
|
||||||
|
|
||||||
pub fn expand_derive_deserialize(input: &mut syn::DeriveInput) -> syn::Result<TokenStream> {
|
pub fn expand_derive_deserialize(input: &mut syn::DeriveInput) -> syn::Result<TokenStream> {
|
||||||
replace_receiver(input);
|
replace_receiver(input);
|
||||||
@@ -310,7 +311,7 @@ fn deserialize_body(cont: &Container, params: &Parameters) -> Fragment {
|
|||||||
match &cont.data {
|
match &cont.data {
|
||||||
Data::Enum(variants) => enum_::deserialize_enum(params, variants, &cont.attrs),
|
Data::Enum(variants) => enum_::deserialize_enum(params, variants, &cont.attrs),
|
||||||
Data::Struct(Style::Struct, fields) => {
|
Data::Struct(Style::Struct, fields) => {
|
||||||
deserialize_struct(params, fields, &cont.attrs, StructForm::Struct)
|
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(params, fields, &cont.attrs, TupleForm::Tuple)
|
deserialize_tuple(params, fields, &cont.attrs, TupleForm::Tuple)
|
||||||
@@ -345,7 +346,7 @@ fn deserialize_in_place_body(cont: &Container, params: &Parameters) -> Option<St
|
|||||||
|
|
||||||
let code = match &cont.data {
|
let code = match &cont.data {
|
||||||
Data::Struct(Style::Struct, fields) => {
|
Data::Struct(Style::Struct, fields) => {
|
||||||
deserialize_struct_in_place(params, fields, &cont.attrs)?
|
struct_::deserialize_struct_in_place(params, fields, &cont.attrs)?
|
||||||
}
|
}
|
||||||
Data::Struct(Style::Tuple, fields) | Data::Struct(Style::Newtype, fields) => {
|
Data::Struct(Style::Tuple, fields) | Data::Struct(Style::Newtype, fields) => {
|
||||||
deserialize_tuple_in_place(params, fields, &cont.attrs)
|
deserialize_tuple_in_place(params, fields, &cont.attrs)
|
||||||
@@ -960,278 +961,6 @@ enum StructForm<'a> {
|
|||||||
Untagged(&'a syn::Ident),
|
Untagged(&'a syn::Ident),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates `Deserialize::deserialize` body for a `struct Struct {...}`
|
|
||||||
fn deserialize_struct(
|
|
||||||
params: &Parameters,
|
|
||||||
fields: &[Field],
|
|
||||||
cattrs: &attr::Container,
|
|
||||||
form: StructForm,
|
|
||||||
) -> Fragment {
|
|
||||||
let this_type = ¶ms.this_type;
|
|
||||||
let this_value = ¶ms.this_value;
|
|
||||||
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = params.generics();
|
|
||||||
let delife = params.borrowed.de_lifetime();
|
|
||||||
|
|
||||||
// If there are getters (implying private fields), construct the local type
|
|
||||||
// and use an `Into` conversion to get the remote type. If there are no
|
|
||||||
// getters then construct the target type directly.
|
|
||||||
let construct = if params.has_getter {
|
|
||||||
let local = ¶ms.local;
|
|
||||||
quote!(#local)
|
|
||||||
} else {
|
|
||||||
quote!(#this_value)
|
|
||||||
};
|
|
||||||
|
|
||||||
let type_path = match form {
|
|
||||||
StructForm::Struct => construct,
|
|
||||||
StructForm::ExternallyTagged(variant_ident)
|
|
||||||
| StructForm::InternallyTagged(variant_ident)
|
|
||||||
| StructForm::Untagged(variant_ident) => quote!(#construct::#variant_ident),
|
|
||||||
};
|
|
||||||
let expecting = match form {
|
|
||||||
StructForm::Struct => format!("struct {}", params.type_name()),
|
|
||||||
StructForm::ExternallyTagged(variant_ident)
|
|
||||||
| StructForm::InternallyTagged(variant_ident)
|
|
||||||
| StructForm::Untagged(variant_ident) => {
|
|
||||||
format!("struct variant {}::{}", params.type_name(), variant_ident)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let expecting = cattrs.expecting().unwrap_or(&expecting);
|
|
||||||
|
|
||||||
let deserialized_fields: Vec<_> = fields
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
// Skip fields that shouldn't be deserialized or that were flattened,
|
|
||||||
// so they don't appear in the storage in their literal form
|
|
||||||
.filter(|&(_, field)| !field.attrs.skip_deserializing() && !field.attrs.flatten())
|
|
||||||
.map(|(i, field)| FieldWithAliases {
|
|
||||||
ident: field_i(i),
|
|
||||||
aliases: field.attrs.aliases(),
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let has_flatten = has_flatten(fields);
|
|
||||||
let field_visitor = deserialize_field_identifier(&deserialized_fields, cattrs, has_flatten);
|
|
||||||
|
|
||||||
// untagged struct variants do not get a visit_seq method. The same applies to
|
|
||||||
// structs that only have a map representation.
|
|
||||||
let visit_seq = match form {
|
|
||||||
StructForm::Untagged(_) => None,
|
|
||||||
_ if has_flatten => None,
|
|
||||||
_ => {
|
|
||||||
let mut_seq = if deserialized_fields.is_empty() {
|
|
||||||
quote!(_)
|
|
||||||
} else {
|
|
||||||
quote!(mut __seq)
|
|
||||||
};
|
|
||||||
|
|
||||||
let visit_seq = Stmts(deserialize_seq(
|
|
||||||
&type_path, params, fields, true, cattrs, expecting,
|
|
||||||
));
|
|
||||||
|
|
||||||
Some(quote! {
|
|
||||||
#[inline]
|
|
||||||
fn visit_seq<__A>(self, #mut_seq: __A) -> _serde::#private::Result<Self::Value, __A::Error>
|
|
||||||
where
|
|
||||||
__A: _serde::de::SeqAccess<#delife>,
|
|
||||||
{
|
|
||||||
#visit_seq
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let visit_map = Stmts(deserialize_map(
|
|
||||||
&type_path,
|
|
||||||
params,
|
|
||||||
fields,
|
|
||||||
cattrs,
|
|
||||||
has_flatten,
|
|
||||||
));
|
|
||||||
|
|
||||||
let visitor_seed = match form {
|
|
||||||
StructForm::ExternallyTagged(..) if has_flatten => Some(quote! {
|
|
||||||
#[automatically_derived]
|
|
||||||
impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Visitor #de_ty_generics #where_clause {
|
|
||||||
type Value = #this_type #ty_generics;
|
|
||||||
|
|
||||||
fn deserialize<__D>(self, __deserializer: __D) -> _serde::#private::Result<Self::Value, __D::Error>
|
|
||||||
where
|
|
||||||
__D: _serde::Deserializer<#delife>,
|
|
||||||
{
|
|
||||||
_serde::Deserializer::deserialize_map(__deserializer, self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let fields_stmt = if has_flatten {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
let field_names = deserialized_fields.iter().flat_map(|field| field.aliases);
|
|
||||||
|
|
||||||
Some(quote! {
|
|
||||||
#[doc(hidden)]
|
|
||||||
const FIELDS: &'static [&'static str] = &[ #(#field_names),* ];
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
let visitor_expr = quote! {
|
|
||||||
__Visitor {
|
|
||||||
marker: _serde::#private::PhantomData::<#this_type #ty_generics>,
|
|
||||||
lifetime: _serde::#private::PhantomData,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let dispatch = match form {
|
|
||||||
StructForm::Struct if has_flatten => quote! {
|
|
||||||
_serde::Deserializer::deserialize_map(__deserializer, #visitor_expr)
|
|
||||||
},
|
|
||||||
StructForm::Struct => {
|
|
||||||
let type_name = cattrs.name().deserialize_name();
|
|
||||||
quote! {
|
|
||||||
_serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, #visitor_expr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
StructForm::ExternallyTagged(_) if has_flatten => quote! {
|
|
||||||
_serde::de::VariantAccess::newtype_variant_seed(__variant, #visitor_expr)
|
|
||||||
},
|
|
||||||
StructForm::ExternallyTagged(_) => quote! {
|
|
||||||
_serde::de::VariantAccess::struct_variant(__variant, FIELDS, #visitor_expr)
|
|
||||||
},
|
|
||||||
StructForm::InternallyTagged(_) => quote! {
|
|
||||||
_serde::Deserializer::deserialize_any(__deserializer, #visitor_expr)
|
|
||||||
},
|
|
||||||
StructForm::Untagged(_) => quote! {
|
|
||||||
_serde::Deserializer::deserialize_any(__deserializer, #visitor_expr)
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
quote_block! {
|
|
||||||
#field_visitor
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
struct __Visitor #de_impl_generics #where_clause {
|
|
||||||
marker: _serde::#private::PhantomData<#this_type #ty_generics>,
|
|
||||||
lifetime: _serde::#private::PhantomData<&#delife ()>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[automatically_derived]
|
|
||||||
impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause {
|
|
||||||
type Value = #this_type #ty_generics;
|
|
||||||
|
|
||||||
fn expecting(&self, __formatter: &mut _serde::#private::Formatter) -> _serde::#private::fmt::Result {
|
|
||||||
_serde::#private::Formatter::write_str(__formatter, #expecting)
|
|
||||||
}
|
|
||||||
|
|
||||||
#visit_seq
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn visit_map<__A>(self, mut __map: __A) -> _serde::#private::Result<Self::Value, __A::Error>
|
|
||||||
where
|
|
||||||
__A: _serde::de::MapAccess<#delife>,
|
|
||||||
{
|
|
||||||
#visit_map
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#visitor_seed
|
|
||||||
|
|
||||||
#fields_stmt
|
|
||||||
|
|
||||||
#dispatch
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generates `Deserialize::deserialize_in_place` body for a `struct Struct {...}`
|
|
||||||
#[cfg(feature = "deserialize_in_place")]
|
|
||||||
fn deserialize_struct_in_place(
|
|
||||||
params: &Parameters,
|
|
||||||
fields: &[Field],
|
|
||||||
cattrs: &attr::Container,
|
|
||||||
) -> Option<Fragment> {
|
|
||||||
// for now we do not support in_place deserialization for structs that
|
|
||||||
// are represented as map.
|
|
||||||
if has_flatten(fields) {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let this_type = ¶ms.this_type;
|
|
||||||
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = params.generics();
|
|
||||||
let delife = params.borrowed.de_lifetime();
|
|
||||||
|
|
||||||
let expecting = format!("struct {}", params.type_name());
|
|
||||||
let expecting = cattrs.expecting().unwrap_or(&expecting);
|
|
||||||
|
|
||||||
let deserialized_fields: Vec<_> = fields
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.filter(|&(_, field)| !field.attrs.skip_deserializing())
|
|
||||||
.map(|(i, field)| FieldWithAliases {
|
|
||||||
ident: field_i(i),
|
|
||||||
aliases: field.attrs.aliases(),
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let field_visitor = deserialize_field_identifier(&deserialized_fields, cattrs, false);
|
|
||||||
|
|
||||||
let mut_seq = if deserialized_fields.is_empty() {
|
|
||||||
quote!(_)
|
|
||||||
} else {
|
|
||||||
quote!(mut __seq)
|
|
||||||
};
|
|
||||||
let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, expecting));
|
|
||||||
let visit_map = Stmts(deserialize_map_in_place(params, fields, cattrs));
|
|
||||||
let field_names = deserialized_fields.iter().flat_map(|field| field.aliases);
|
|
||||||
let type_name = cattrs.name().deserialize_name();
|
|
||||||
|
|
||||||
let in_place_impl_generics = de_impl_generics.in_place();
|
|
||||||
let in_place_ty_generics = de_ty_generics.in_place();
|
|
||||||
let place_life = place_lifetime();
|
|
||||||
|
|
||||||
Some(quote_block! {
|
|
||||||
#field_visitor
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
struct __Visitor #in_place_impl_generics #where_clause {
|
|
||||||
place: &#place_life mut #this_type #ty_generics,
|
|
||||||
lifetime: _serde::#private::PhantomData<&#delife ()>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[automatically_derived]
|
|
||||||
impl #in_place_impl_generics _serde::de::Visitor<#delife> for __Visitor #in_place_ty_generics #where_clause {
|
|
||||||
type Value = ();
|
|
||||||
|
|
||||||
fn expecting(&self, __formatter: &mut _serde::#private::Formatter) -> _serde::#private::fmt::Result {
|
|
||||||
_serde::#private::Formatter::write_str(__formatter, #expecting)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn visit_seq<__A>(self, #mut_seq: __A) -> _serde::#private::Result<Self::Value, __A::Error>
|
|
||||||
where
|
|
||||||
__A: _serde::de::SeqAccess<#delife>,
|
|
||||||
{
|
|
||||||
#visit_seq
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn visit_map<__A>(self, mut __map: __A) -> _serde::#private::Result<Self::Value, __A::Error>
|
|
||||||
where
|
|
||||||
__A: _serde::de::MapAccess<#delife>,
|
|
||||||
{
|
|
||||||
#visit_map
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
const FIELDS: &'static [&'static str] = &[ #(#field_names),* ];
|
|
||||||
|
|
||||||
_serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, __Visitor {
|
|
||||||
place: __place,
|
|
||||||
lifetime: _serde::#private::PhantomData,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
struct FieldWithAliases<'a> {
|
struct FieldWithAliases<'a> {
|
||||||
ident: Ident,
|
ident: Ident,
|
||||||
aliases: &'a BTreeSet<Name>,
|
aliases: &'a BTreeSet<Name>,
|
||||||
@@ -1297,34 +1026,6 @@ fn deserialize_generated_identifier(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates enum and its `Deserialize` implementation that represents each
|
|
||||||
/// non-skipped field of the struct
|
|
||||||
fn deserialize_field_identifier(
|
|
||||||
deserialized_fields: &[FieldWithAliases],
|
|
||||||
cattrs: &attr::Container,
|
|
||||||
has_flatten: bool,
|
|
||||||
) -> Stmts {
|
|
||||||
let (ignore_variant, fallthrough) = if has_flatten {
|
|
||||||
let ignore_variant = quote!(__other(_serde::#private::de::Content<'de>),);
|
|
||||||
let fallthrough = quote!(_serde::#private::Ok(__Field::__other(__value)));
|
|
||||||
(Some(ignore_variant), Some(fallthrough))
|
|
||||||
} else if cattrs.deny_unknown_fields() {
|
|
||||||
(None, None)
|
|
||||||
} else {
|
|
||||||
let ignore_variant = quote!(__ignore,);
|
|
||||||
let fallthrough = quote!(_serde::#private::Ok(__Field::__ignore));
|
|
||||||
(Some(ignore_variant), Some(fallthrough))
|
|
||||||
};
|
|
||||||
|
|
||||||
Stmts(deserialize_generated_identifier(
|
|
||||||
deserialized_fields,
|
|
||||||
has_flatten,
|
|
||||||
false,
|
|
||||||
ignore_variant,
|
|
||||||
fallthrough,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generates `Deserialize::deserialize` body for an enum with
|
// Generates `Deserialize::deserialize` body for an enum with
|
||||||
// `serde(field_identifier)` or `serde(variant_identifier)` attribute.
|
// `serde(field_identifier)` or `serde(variant_identifier)` attribute.
|
||||||
fn deserialize_custom_identifier(
|
fn deserialize_custom_identifier(
|
||||||
@@ -1731,387 +1432,6 @@ fn deserialize_identifier(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_map(
|
|
||||||
struct_path: &TokenStream,
|
|
||||||
params: &Parameters,
|
|
||||||
fields: &[Field],
|
|
||||||
cattrs: &attr::Container,
|
|
||||||
has_flatten: bool,
|
|
||||||
) -> Fragment {
|
|
||||||
// Create the field names for the fields.
|
|
||||||
let fields_names: Vec<_> = fields
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.map(|(i, field)| (field, field_i(i)))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
// Declare each field that will be deserialized.
|
|
||||||
let let_values = fields_names
|
|
||||||
.iter()
|
|
||||||
.filter(|&&(field, _)| !field.attrs.skip_deserializing() && !field.attrs.flatten())
|
|
||||||
.map(|(field, name)| {
|
|
||||||
let field_ty = field.ty;
|
|
||||||
quote! {
|
|
||||||
let mut #name: _serde::#private::Option<#field_ty> = _serde::#private::None;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Collect contents for flatten fields into a buffer
|
|
||||||
let let_collect = if has_flatten {
|
|
||||||
Some(quote! {
|
|
||||||
let mut __collect = _serde::#private::Vec::<_serde::#private::Option<(
|
|
||||||
_serde::#private::de::Content,
|
|
||||||
_serde::#private::de::Content
|
|
||||||
)>>::new();
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
// Match arms to extract a value for a field.
|
|
||||||
let value_arms = fields_names
|
|
||||||
.iter()
|
|
||||||
.filter(|&&(field, _)| !field.attrs.skip_deserializing() && !field.attrs.flatten())
|
|
||||||
.map(|(field, name)| {
|
|
||||||
let deser_name = field.attrs.name().deserialize_name();
|
|
||||||
|
|
||||||
let visit = match field.attrs.deserialize_with() {
|
|
||||||
None => {
|
|
||||||
let field_ty = field.ty;
|
|
||||||
let span = field.original.span();
|
|
||||||
let func =
|
|
||||||
quote_spanned!(span=> _serde::de::MapAccess::next_value::<#field_ty>);
|
|
||||||
quote! {
|
|
||||||
#func(&mut __map)?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(path) => {
|
|
||||||
let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path);
|
|
||||||
quote!({
|
|
||||||
#wrapper
|
|
||||||
match _serde::de::MapAccess::next_value::<#wrapper_ty>(&mut __map) {
|
|
||||||
_serde::#private::Ok(__wrapper) => __wrapper.value,
|
|
||||||
_serde::#private::Err(__err) => {
|
|
||||||
return _serde::#private::Err(__err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
||||||
quote! {
|
|
||||||
__Field::#name => {
|
|
||||||
if _serde::#private::Option::is_some(&#name) {
|
|
||||||
return _serde::#private::Err(<__A::Error as _serde::de::Error>::duplicate_field(#deser_name));
|
|
||||||
}
|
|
||||||
#name = _serde::#private::Some(#visit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Visit ignored values to consume them
|
|
||||||
let ignored_arm = if has_flatten {
|
|
||||||
Some(quote! {
|
|
||||||
__Field::__other(__name) => {
|
|
||||||
__collect.push(_serde::#private::Some((
|
|
||||||
__name,
|
|
||||||
_serde::de::MapAccess::next_value_seed(&mut __map, _serde::#private::de::ContentVisitor::new())?)));
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else if cattrs.deny_unknown_fields() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(quote! {
|
|
||||||
_ => { let _ = _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?; }
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing());
|
|
||||||
let match_keys = if cattrs.deny_unknown_fields() && all_skipped {
|
|
||||||
quote! {
|
|
||||||
// FIXME: Once feature(exhaustive_patterns) is stable:
|
|
||||||
// let _serde::#private::None::<__Field> = _serde::de::MapAccess::next_key(&mut __map)?;
|
|
||||||
_serde::#private::Option::map(
|
|
||||||
_serde::de::MapAccess::next_key::<__Field>(&mut __map)?,
|
|
||||||
|__impossible| match __impossible {});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
quote! {
|
|
||||||
while let _serde::#private::Some(__key) = _serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
|
|
||||||
match __key {
|
|
||||||
#(#value_arms)*
|
|
||||||
#ignored_arm
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let extract_values = fields_names
|
|
||||||
.iter()
|
|
||||||
.filter(|&&(field, _)| !field.attrs.skip_deserializing() && !field.attrs.flatten())
|
|
||||||
.map(|(field, name)| {
|
|
||||||
let missing_expr = Match(expr_is_missing(field, cattrs));
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
let #name = match #name {
|
|
||||||
_serde::#private::Some(#name) => #name,
|
|
||||||
_serde::#private::None => #missing_expr
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let extract_collected = fields_names
|
|
||||||
.iter()
|
|
||||||
.filter(|&&(field, _)| field.attrs.flatten() && !field.attrs.skip_deserializing())
|
|
||||||
.map(|(field, name)| {
|
|
||||||
let field_ty = field.ty;
|
|
||||||
let func = match field.attrs.deserialize_with() {
|
|
||||||
None => {
|
|
||||||
let span = field.original.span();
|
|
||||||
quote_spanned!(span=> _serde::de::Deserialize::deserialize)
|
|
||||||
}
|
|
||||||
Some(path) => quote!(#path),
|
|
||||||
};
|
|
||||||
quote! {
|
|
||||||
let #name: #field_ty = #func(
|
|
||||||
_serde::#private::de::FlatMapDeserializer(
|
|
||||||
&mut __collect,
|
|
||||||
_serde::#private::PhantomData))?;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let collected_deny_unknown_fields = if has_flatten && cattrs.deny_unknown_fields() {
|
|
||||||
Some(quote! {
|
|
||||||
if let _serde::#private::Some(_serde::#private::Some((__key, _))) =
|
|
||||||
__collect.into_iter().filter(_serde::#private::Option::is_some).next()
|
|
||||||
{
|
|
||||||
if let _serde::#private::Some(__key) = _serde::#private::de::content_as_str(&__key) {
|
|
||||||
return _serde::#private::Err(
|
|
||||||
_serde::de::Error::custom(format_args!("unknown field `{}`", &__key)));
|
|
||||||
} else {
|
|
||||||
return _serde::#private::Err(
|
|
||||||
_serde::de::Error::custom(format_args!("unexpected map key")));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let result = fields_names.iter().map(|(field, name)| {
|
|
||||||
let member = &field.member;
|
|
||||||
if field.attrs.skip_deserializing() {
|
|
||||||
let value = Expr(expr_is_missing(field, cattrs));
|
|
||||||
quote!(#member: #value)
|
|
||||||
} else {
|
|
||||||
quote!(#member: #name)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let let_default = match cattrs.default() {
|
|
||||||
attr::Default::Default => Some(quote!(
|
|
||||||
let __default: Self::Value = _serde::#private::Default::default();
|
|
||||||
)),
|
|
||||||
// If #path returns wrong type, error will be reported here (^^^^^).
|
|
||||||
// We attach span of the path to the function so it will be reported
|
|
||||||
// on the #[serde(default = "...")]
|
|
||||||
// ^^^^^
|
|
||||||
attr::Default::Path(path) => Some(quote_spanned!(path.span()=>
|
|
||||||
let __default: Self::Value = #path();
|
|
||||||
)),
|
|
||||||
attr::Default::None => {
|
|
||||||
// We don't need the default value, to prevent an unused variable warning
|
|
||||||
// we'll leave the line empty.
|
|
||||||
None
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut result = quote!(#struct_path { #(#result),* });
|
|
||||||
if params.has_getter {
|
|
||||||
let this_type = ¶ms.this_type;
|
|
||||||
let (_, ty_generics, _) = params.generics.split_for_impl();
|
|
||||||
result = quote! {
|
|
||||||
_serde::#private::Into::<#this_type #ty_generics>::into(#result)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
quote_block! {
|
|
||||||
#(#let_values)*
|
|
||||||
|
|
||||||
#let_collect
|
|
||||||
|
|
||||||
#match_keys
|
|
||||||
|
|
||||||
#let_default
|
|
||||||
|
|
||||||
#(#extract_values)*
|
|
||||||
|
|
||||||
#(#extract_collected)*
|
|
||||||
|
|
||||||
#collected_deny_unknown_fields
|
|
||||||
|
|
||||||
_serde::#private::Ok(#result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "deserialize_in_place")]
|
|
||||||
fn deserialize_map_in_place(
|
|
||||||
params: &Parameters,
|
|
||||||
fields: &[Field],
|
|
||||||
cattrs: &attr::Container,
|
|
||||||
) -> Fragment {
|
|
||||||
assert!(
|
|
||||||
!has_flatten(fields),
|
|
||||||
"inplace deserialization of maps does not support flatten fields"
|
|
||||||
);
|
|
||||||
|
|
||||||
// Create the field names for the fields.
|
|
||||||
let fields_names: Vec<_> = fields
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.map(|(i, field)| (field, field_i(i)))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
// For deserialize_in_place, declare booleans for each field that will be
|
|
||||||
// deserialized.
|
|
||||||
let let_flags = fields_names
|
|
||||||
.iter()
|
|
||||||
.filter(|&&(field, _)| !field.attrs.skip_deserializing())
|
|
||||||
.map(|(_, name)| {
|
|
||||||
quote! {
|
|
||||||
let mut #name: bool = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Match arms to extract a value for a field.
|
|
||||||
let value_arms_from = fields_names
|
|
||||||
.iter()
|
|
||||||
.filter(|&&(field, _)| !field.attrs.skip_deserializing())
|
|
||||||
.map(|(field, name)| {
|
|
||||||
let deser_name = field.attrs.name().deserialize_name();
|
|
||||||
let member = &field.member;
|
|
||||||
|
|
||||||
let visit = match field.attrs.deserialize_with() {
|
|
||||||
None => {
|
|
||||||
quote! {
|
|
||||||
_serde::de::MapAccess::next_value_seed(&mut __map, _serde::#private::de::InPlaceSeed(&mut self.place.#member))?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(path) => {
|
|
||||||
let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path);
|
|
||||||
quote!({
|
|
||||||
#wrapper
|
|
||||||
self.place.#member = match _serde::de::MapAccess::next_value::<#wrapper_ty>(&mut __map) {
|
|
||||||
_serde::#private::Ok(__wrapper) => __wrapper.value,
|
|
||||||
_serde::#private::Err(__err) => {
|
|
||||||
return _serde::#private::Err(__err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
||||||
quote! {
|
|
||||||
__Field::#name => {
|
|
||||||
if #name {
|
|
||||||
return _serde::#private::Err(<__A::Error as _serde::de::Error>::duplicate_field(#deser_name));
|
|
||||||
}
|
|
||||||
#visit;
|
|
||||||
#name = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Visit ignored values to consume them
|
|
||||||
let ignored_arm = if cattrs.deny_unknown_fields() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(quote! {
|
|
||||||
_ => { let _ = _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?; }
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing());
|
|
||||||
|
|
||||||
let match_keys = if cattrs.deny_unknown_fields() && all_skipped {
|
|
||||||
quote! {
|
|
||||||
// FIXME: Once feature(exhaustive_patterns) is stable:
|
|
||||||
// let _serde::#private::None::<__Field> = _serde::de::MapAccess::next_key(&mut __map)?;
|
|
||||||
_serde::#private::Option::map(
|
|
||||||
_serde::de::MapAccess::next_key::<__Field>(&mut __map)?,
|
|
||||||
|__impossible| match __impossible {});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
quote! {
|
|
||||||
while let _serde::#private::Some(__key) = _serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
|
|
||||||
match __key {
|
|
||||||
#(#value_arms_from)*
|
|
||||||
#ignored_arm
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let check_flags = fields_names
|
|
||||||
.iter()
|
|
||||||
.filter(|&&(field, _)| !field.attrs.skip_deserializing())
|
|
||||||
.map(|(field, name)| {
|
|
||||||
let missing_expr = expr_is_missing(field, cattrs);
|
|
||||||
// If missing_expr unconditionally returns an error, don't try
|
|
||||||
// to assign its value to self.place.
|
|
||||||
if field.attrs.default().is_none()
|
|
||||||
&& cattrs.default().is_none()
|
|
||||||
&& field.attrs.deserialize_with().is_some()
|
|
||||||
{
|
|
||||||
let missing_expr = Stmts(missing_expr);
|
|
||||||
quote! {
|
|
||||||
if !#name {
|
|
||||||
#missing_expr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let member = &field.member;
|
|
||||||
let missing_expr = Expr(missing_expr);
|
|
||||||
quote! {
|
|
||||||
if !#name {
|
|
||||||
self.place.#member = #missing_expr;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let this_type = ¶ms.this_type;
|
|
||||||
let (_, _, ty_generics, _) = params.generics();
|
|
||||||
|
|
||||||
let let_default = match cattrs.default() {
|
|
||||||
attr::Default::Default => Some(quote!(
|
|
||||||
let __default: #this_type #ty_generics = _serde::#private::Default::default();
|
|
||||||
)),
|
|
||||||
// If #path returns wrong type, error will be reported here (^^^^^).
|
|
||||||
// We attach span of the path to the function so it will be reported
|
|
||||||
// on the #[serde(default = "...")]
|
|
||||||
// ^^^^^
|
|
||||||
attr::Default::Path(path) => Some(quote_spanned!(path.span()=>
|
|
||||||
let __default: #this_type #ty_generics = #path();
|
|
||||||
)),
|
|
||||||
attr::Default::None => {
|
|
||||||
// We don't need the default value, to prevent an unused variable warning
|
|
||||||
// we'll leave the line empty.
|
|
||||||
None
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
quote_block! {
|
|
||||||
#(#let_flags)*
|
|
||||||
|
|
||||||
#match_keys
|
|
||||||
|
|
||||||
#let_default
|
|
||||||
|
|
||||||
#(#check_flags)*
|
|
||||||
|
|
||||||
_serde::#private::Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn field_i(i: usize) -> Ident {
|
fn field_i(i: usize) -> Ident {
|
||||||
Ident::new(&format!("__field{}", i), Span::call_site())
|
Ident::new(&format!("__field{}", i), Span::call_site())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,9 @@
|
|||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use crate::de::enum_;
|
use crate::de::enum_;
|
||||||
|
use crate::de::struct_;
|
||||||
use crate::de::{
|
use crate::de::{
|
||||||
deserialize_struct, deserialize_tuple, expr_is_missing, field_i,
|
deserialize_tuple, expr_is_missing, field_i,
|
||||||
unwrap_to_variant_closure, wrap_deserialize_field_with, wrap_deserialize_with, Parameters,
|
unwrap_to_variant_closure, wrap_deserialize_field_with, wrap_deserialize_with, Parameters,
|
||||||
StructForm, TupleForm,
|
StructForm, TupleForm,
|
||||||
};
|
};
|
||||||
@@ -148,7 +149,7 @@ fn deserialize_externally_tagged_variant(
|
|||||||
cattrs,
|
cattrs,
|
||||||
TupleForm::ExternallyTagged(variant_ident),
|
TupleForm::ExternallyTagged(variant_ident),
|
||||||
),
|
),
|
||||||
Style::Struct => deserialize_struct(
|
Style::Struct => struct_::deserialize_struct(
|
||||||
params,
|
params,
|
||||||
&variant.fields,
|
&variant.fields,
|
||||||
cattrs,
|
cattrs,
|
||||||
|
|||||||
@@ -7,8 +7,9 @@
|
|||||||
|
|
||||||
use crate::de::enum_;
|
use crate::de::enum_;
|
||||||
use crate::de::enum_untagged;
|
use crate::de::enum_untagged;
|
||||||
|
use crate::de::struct_;
|
||||||
use crate::de::{
|
use crate::de::{
|
||||||
deserialize_struct, effective_style, expr_is_missing, field_i,
|
effective_style, expr_is_missing, field_i,
|
||||||
unwrap_to_variant_closure, Parameters, StructForm,
|
unwrap_to_variant_closure, Parameters, StructForm,
|
||||||
};
|
};
|
||||||
use crate::fragment::{Expr, Fragment, Match};
|
use crate::fragment::{Expr, Fragment, Match};
|
||||||
@@ -95,7 +96,7 @@ fn deserialize_internally_tagged_variant(
|
|||||||
Style::Newtype => {
|
Style::Newtype => {
|
||||||
enum_untagged::deserialize_untagged_newtype_variant(variant_ident, params, &variant.fields[0])
|
enum_untagged::deserialize_untagged_newtype_variant(variant_ident, params, &variant.fields[0])
|
||||||
}
|
}
|
||||||
Style::Struct => deserialize_struct(
|
Style::Struct => struct_::deserialize_struct(
|
||||||
params,
|
params,
|
||||||
&variant.fields,
|
&variant.fields,
|
||||||
cattrs,
|
cattrs,
|
||||||
|
|||||||
@@ -5,8 +5,9 @@
|
|||||||
//! enum Enum {}
|
//! enum Enum {}
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
|
use crate::de::struct_;
|
||||||
use crate::de::{
|
use crate::de::{
|
||||||
deserialize_struct, deserialize_tuple, effective_style, expr_is_missing,
|
deserialize_tuple, effective_style, expr_is_missing,
|
||||||
unwrap_to_variant_closure, Parameters, StructForm, TupleForm,
|
unwrap_to_variant_closure, Parameters, StructForm, TupleForm,
|
||||||
};
|
};
|
||||||
use crate::fragment::{Expr, Fragment};
|
use crate::fragment::{Expr, Fragment};
|
||||||
@@ -99,7 +100,7 @@ pub fn deserialize_untagged_variant(
|
|||||||
cattrs,
|
cattrs,
|
||||||
TupleForm::Untagged(variant_ident),
|
TupleForm::Untagged(variant_ident),
|
||||||
),
|
),
|
||||||
Style::Struct => deserialize_struct(
|
Style::Struct => struct_::deserialize_struct(
|
||||||
params,
|
params,
|
||||||
&variant.fields,
|
&variant.fields,
|
||||||
cattrs,
|
cattrs,
|
||||||
|
|||||||
@@ -0,0 +1,694 @@
|
|||||||
|
use crate::de::{
|
||||||
|
deserialize_generated_identifier, deserialize_seq, expr_is_missing, field_i, has_flatten,
|
||||||
|
wrap_deserialize_field_with, FieldWithAliases, Parameters, StructForm,
|
||||||
|
};
|
||||||
|
#[cfg(feature = "deserialize_in_place")]
|
||||||
|
use crate::de::{deserialize_seq_in_place, place_lifetime};
|
||||||
|
use crate::fragment::{Expr, Fragment, Match, Stmts};
|
||||||
|
use crate::internals::ast::Field;
|
||||||
|
use crate::internals::attr;
|
||||||
|
use crate::private;
|
||||||
|
use proc_macro2::TokenStream;
|
||||||
|
use quote::{quote, quote_spanned};
|
||||||
|
use syn::spanned::Spanned;
|
||||||
|
|
||||||
|
/// Generates `Deserialize::deserialize` body for a `struct Struct {...}`
|
||||||
|
pub fn deserialize_struct(
|
||||||
|
params: &Parameters,
|
||||||
|
fields: &[Field],
|
||||||
|
cattrs: &attr::Container,
|
||||||
|
form: StructForm,
|
||||||
|
) -> Fragment {
|
||||||
|
let this_type = ¶ms.this_type;
|
||||||
|
let this_value = ¶ms.this_value;
|
||||||
|
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = params.generics();
|
||||||
|
let delife = params.borrowed.de_lifetime();
|
||||||
|
|
||||||
|
// If there are getters (implying private fields), construct the local type
|
||||||
|
// and use an `Into` conversion to get the remote type. If there are no
|
||||||
|
// getters then construct the target type directly.
|
||||||
|
let construct = if params.has_getter {
|
||||||
|
let local = ¶ms.local;
|
||||||
|
quote!(#local)
|
||||||
|
} else {
|
||||||
|
quote!(#this_value)
|
||||||
|
};
|
||||||
|
|
||||||
|
let type_path = match form {
|
||||||
|
StructForm::Struct => construct,
|
||||||
|
StructForm::ExternallyTagged(variant_ident)
|
||||||
|
| StructForm::InternallyTagged(variant_ident)
|
||||||
|
| StructForm::Untagged(variant_ident) => quote!(#construct::#variant_ident),
|
||||||
|
};
|
||||||
|
let expecting = match form {
|
||||||
|
StructForm::Struct => format!("struct {}", params.type_name()),
|
||||||
|
StructForm::ExternallyTagged(variant_ident)
|
||||||
|
| StructForm::InternallyTagged(variant_ident)
|
||||||
|
| StructForm::Untagged(variant_ident) => {
|
||||||
|
format!("struct variant {}::{}", params.type_name(), variant_ident)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let expecting = cattrs.expecting().unwrap_or(&expecting);
|
||||||
|
|
||||||
|
let deserialized_fields: Vec<_> = fields
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
// Skip fields that shouldn't be deserialized or that were flattened,
|
||||||
|
// so they don't appear in the storage in their literal form
|
||||||
|
.filter(|&(_, field)| !field.attrs.skip_deserializing() && !field.attrs.flatten())
|
||||||
|
.map(|(i, field)| FieldWithAliases {
|
||||||
|
ident: field_i(i),
|
||||||
|
aliases: field.attrs.aliases(),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let has_flatten = has_flatten(fields);
|
||||||
|
let field_visitor = deserialize_field_identifier(&deserialized_fields, cattrs, has_flatten);
|
||||||
|
|
||||||
|
// untagged struct variants do not get a visit_seq method. The same applies to
|
||||||
|
// structs that only have a map representation.
|
||||||
|
let visit_seq = match form {
|
||||||
|
StructForm::Untagged(_) => None,
|
||||||
|
_ if has_flatten => None,
|
||||||
|
_ => {
|
||||||
|
let mut_seq = if deserialized_fields.is_empty() {
|
||||||
|
quote!(_)
|
||||||
|
} else {
|
||||||
|
quote!(mut __seq)
|
||||||
|
};
|
||||||
|
|
||||||
|
let visit_seq = Stmts(deserialize_seq(
|
||||||
|
&type_path, params, fields, true, cattrs, expecting,
|
||||||
|
));
|
||||||
|
|
||||||
|
Some(quote! {
|
||||||
|
#[inline]
|
||||||
|
fn visit_seq<__A>(self, #mut_seq: __A) -> _serde::#private::Result<Self::Value, __A::Error>
|
||||||
|
where
|
||||||
|
__A: _serde::de::SeqAccess<#delife>,
|
||||||
|
{
|
||||||
|
#visit_seq
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let visit_map = Stmts(deserialize_map(
|
||||||
|
&type_path,
|
||||||
|
params,
|
||||||
|
fields,
|
||||||
|
cattrs,
|
||||||
|
has_flatten,
|
||||||
|
));
|
||||||
|
|
||||||
|
let visitor_seed = match form {
|
||||||
|
StructForm::ExternallyTagged(..) if has_flatten => Some(quote! {
|
||||||
|
#[automatically_derived]
|
||||||
|
impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Visitor #de_ty_generics #where_clause {
|
||||||
|
type Value = #this_type #ty_generics;
|
||||||
|
|
||||||
|
fn deserialize<__D>(self, __deserializer: __D) -> _serde::#private::Result<Self::Value, __D::Error>
|
||||||
|
where
|
||||||
|
__D: _serde::Deserializer<#delife>,
|
||||||
|
{
|
||||||
|
_serde::Deserializer::deserialize_map(__deserializer, self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let fields_stmt = if has_flatten {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let field_names = deserialized_fields.iter().flat_map(|field| field.aliases);
|
||||||
|
|
||||||
|
Some(quote! {
|
||||||
|
#[doc(hidden)]
|
||||||
|
const FIELDS: &'static [&'static str] = &[ #(#field_names),* ];
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
let visitor_expr = quote! {
|
||||||
|
__Visitor {
|
||||||
|
marker: _serde::#private::PhantomData::<#this_type #ty_generics>,
|
||||||
|
lifetime: _serde::#private::PhantomData,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let dispatch = match form {
|
||||||
|
StructForm::Struct if has_flatten => quote! {
|
||||||
|
_serde::Deserializer::deserialize_map(__deserializer, #visitor_expr)
|
||||||
|
},
|
||||||
|
StructForm::Struct => {
|
||||||
|
let type_name = cattrs.name().deserialize_name();
|
||||||
|
quote! {
|
||||||
|
_serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, #visitor_expr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StructForm::ExternallyTagged(_) if has_flatten => quote! {
|
||||||
|
_serde::de::VariantAccess::newtype_variant_seed(__variant, #visitor_expr)
|
||||||
|
},
|
||||||
|
StructForm::ExternallyTagged(_) => quote! {
|
||||||
|
_serde::de::VariantAccess::struct_variant(__variant, FIELDS, #visitor_expr)
|
||||||
|
},
|
||||||
|
StructForm::InternallyTagged(_) => quote! {
|
||||||
|
_serde::Deserializer::deserialize_any(__deserializer, #visitor_expr)
|
||||||
|
},
|
||||||
|
StructForm::Untagged(_) => quote! {
|
||||||
|
_serde::Deserializer::deserialize_any(__deserializer, #visitor_expr)
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
quote_block! {
|
||||||
|
#field_visitor
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
struct __Visitor #de_impl_generics #where_clause {
|
||||||
|
marker: _serde::#private::PhantomData<#this_type #ty_generics>,
|
||||||
|
lifetime: _serde::#private::PhantomData<&#delife ()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[automatically_derived]
|
||||||
|
impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause {
|
||||||
|
type Value = #this_type #ty_generics;
|
||||||
|
|
||||||
|
fn expecting(&self, __formatter: &mut _serde::#private::Formatter) -> _serde::#private::fmt::Result {
|
||||||
|
_serde::#private::Formatter::write_str(__formatter, #expecting)
|
||||||
|
}
|
||||||
|
|
||||||
|
#visit_seq
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_map<__A>(self, mut __map: __A) -> _serde::#private::Result<Self::Value, __A::Error>
|
||||||
|
where
|
||||||
|
__A: _serde::de::MapAccess<#delife>,
|
||||||
|
{
|
||||||
|
#visit_map
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#visitor_seed
|
||||||
|
|
||||||
|
#fields_stmt
|
||||||
|
|
||||||
|
#dispatch
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates `Deserialize::deserialize_in_place` body for a `struct Struct {...}`
|
||||||
|
#[cfg(feature = "deserialize_in_place")]
|
||||||
|
pub fn deserialize_struct_in_place(
|
||||||
|
params: &Parameters,
|
||||||
|
fields: &[Field],
|
||||||
|
cattrs: &attr::Container,
|
||||||
|
) -> Option<Fragment> {
|
||||||
|
// for now we do not support in_place deserialization for structs that
|
||||||
|
// are represented as map.
|
||||||
|
if has_flatten(fields) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let this_type = ¶ms.this_type;
|
||||||
|
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = params.generics();
|
||||||
|
let delife = params.borrowed.de_lifetime();
|
||||||
|
|
||||||
|
let expecting = format!("struct {}", params.type_name());
|
||||||
|
let expecting = cattrs.expecting().unwrap_or(&expecting);
|
||||||
|
|
||||||
|
let deserialized_fields: Vec<_> = fields
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter(|&(_, field)| !field.attrs.skip_deserializing())
|
||||||
|
.map(|(i, field)| FieldWithAliases {
|
||||||
|
ident: field_i(i),
|
||||||
|
aliases: field.attrs.aliases(),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let field_visitor = deserialize_field_identifier(&deserialized_fields, cattrs, false);
|
||||||
|
|
||||||
|
let mut_seq = if deserialized_fields.is_empty() {
|
||||||
|
quote!(_)
|
||||||
|
} else {
|
||||||
|
quote!(mut __seq)
|
||||||
|
};
|
||||||
|
let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, expecting));
|
||||||
|
let visit_map = Stmts(deserialize_map_in_place(params, fields, cattrs));
|
||||||
|
let field_names = deserialized_fields.iter().flat_map(|field| field.aliases);
|
||||||
|
let type_name = cattrs.name().deserialize_name();
|
||||||
|
|
||||||
|
let in_place_impl_generics = de_impl_generics.in_place();
|
||||||
|
let in_place_ty_generics = de_ty_generics.in_place();
|
||||||
|
let place_life = place_lifetime();
|
||||||
|
|
||||||
|
Some(quote_block! {
|
||||||
|
#field_visitor
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
struct __Visitor #in_place_impl_generics #where_clause {
|
||||||
|
place: &#place_life mut #this_type #ty_generics,
|
||||||
|
lifetime: _serde::#private::PhantomData<&#delife ()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[automatically_derived]
|
||||||
|
impl #in_place_impl_generics _serde::de::Visitor<#delife> for __Visitor #in_place_ty_generics #where_clause {
|
||||||
|
type Value = ();
|
||||||
|
|
||||||
|
fn expecting(&self, __formatter: &mut _serde::#private::Formatter) -> _serde::#private::fmt::Result {
|
||||||
|
_serde::#private::Formatter::write_str(__formatter, #expecting)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_seq<__A>(self, #mut_seq: __A) -> _serde::#private::Result<Self::Value, __A::Error>
|
||||||
|
where
|
||||||
|
__A: _serde::de::SeqAccess<#delife>,
|
||||||
|
{
|
||||||
|
#visit_seq
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_map<__A>(self, mut __map: __A) -> _serde::#private::Result<Self::Value, __A::Error>
|
||||||
|
where
|
||||||
|
__A: _serde::de::MapAccess<#delife>,
|
||||||
|
{
|
||||||
|
#visit_map
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
const FIELDS: &'static [&'static str] = &[ #(#field_names),* ];
|
||||||
|
|
||||||
|
_serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, __Visitor {
|
||||||
|
place: __place,
|
||||||
|
lifetime: _serde::#private::PhantomData,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates enum and its `Deserialize` implementation that represents each
|
||||||
|
/// non-skipped field of the struct
|
||||||
|
fn deserialize_field_identifier(
|
||||||
|
deserialized_fields: &[FieldWithAliases],
|
||||||
|
cattrs: &attr::Container,
|
||||||
|
has_flatten: bool,
|
||||||
|
) -> Stmts {
|
||||||
|
let (ignore_variant, fallthrough) = if has_flatten {
|
||||||
|
let ignore_variant = quote!(__other(_serde::#private::de::Content<'de>),);
|
||||||
|
let fallthrough = quote!(_serde::#private::Ok(__Field::__other(__value)));
|
||||||
|
(Some(ignore_variant), Some(fallthrough))
|
||||||
|
} else if cattrs.deny_unknown_fields() {
|
||||||
|
(None, None)
|
||||||
|
} else {
|
||||||
|
let ignore_variant = quote!(__ignore,);
|
||||||
|
let fallthrough = quote!(_serde::#private::Ok(__Field::__ignore));
|
||||||
|
(Some(ignore_variant), Some(fallthrough))
|
||||||
|
};
|
||||||
|
|
||||||
|
Stmts(deserialize_generated_identifier(
|
||||||
|
deserialized_fields,
|
||||||
|
has_flatten,
|
||||||
|
false,
|
||||||
|
ignore_variant,
|
||||||
|
fallthrough,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_map(
|
||||||
|
struct_path: &TokenStream,
|
||||||
|
params: &Parameters,
|
||||||
|
fields: &[Field],
|
||||||
|
cattrs: &attr::Container,
|
||||||
|
has_flatten: bool,
|
||||||
|
) -> Fragment {
|
||||||
|
// Create the field names for the fields.
|
||||||
|
let fields_names: Vec<_> = fields
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, field)| (field, field_i(i)))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// Declare each field that will be deserialized.
|
||||||
|
let let_values = fields_names
|
||||||
|
.iter()
|
||||||
|
.filter(|&&(field, _)| !field.attrs.skip_deserializing() && !field.attrs.flatten())
|
||||||
|
.map(|(field, name)| {
|
||||||
|
let field_ty = field.ty;
|
||||||
|
quote! {
|
||||||
|
let mut #name: _serde::#private::Option<#field_ty> = _serde::#private::None;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Collect contents for flatten fields into a buffer
|
||||||
|
let let_collect = if has_flatten {
|
||||||
|
Some(quote! {
|
||||||
|
let mut __collect = _serde::#private::Vec::<_serde::#private::Option<(
|
||||||
|
_serde::#private::de::Content,
|
||||||
|
_serde::#private::de::Content
|
||||||
|
)>>::new();
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
// Match arms to extract a value for a field.
|
||||||
|
let value_arms = fields_names
|
||||||
|
.iter()
|
||||||
|
.filter(|&&(field, _)| !field.attrs.skip_deserializing() && !field.attrs.flatten())
|
||||||
|
.map(|(field, name)| {
|
||||||
|
let deser_name = field.attrs.name().deserialize_name();
|
||||||
|
|
||||||
|
let visit = match field.attrs.deserialize_with() {
|
||||||
|
None => {
|
||||||
|
let field_ty = field.ty;
|
||||||
|
let span = field.original.span();
|
||||||
|
let func =
|
||||||
|
quote_spanned!(span=> _serde::de::MapAccess::next_value::<#field_ty>);
|
||||||
|
quote! {
|
||||||
|
#func(&mut __map)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(path) => {
|
||||||
|
let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path);
|
||||||
|
quote!({
|
||||||
|
#wrapper
|
||||||
|
match _serde::de::MapAccess::next_value::<#wrapper_ty>(&mut __map) {
|
||||||
|
_serde::#private::Ok(__wrapper) => __wrapper.value,
|
||||||
|
_serde::#private::Err(__err) => {
|
||||||
|
return _serde::#private::Err(__err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
quote! {
|
||||||
|
__Field::#name => {
|
||||||
|
if _serde::#private::Option::is_some(&#name) {
|
||||||
|
return _serde::#private::Err(<__A::Error as _serde::de::Error>::duplicate_field(#deser_name));
|
||||||
|
}
|
||||||
|
#name = _serde::#private::Some(#visit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Visit ignored values to consume them
|
||||||
|
let ignored_arm = if has_flatten {
|
||||||
|
Some(quote! {
|
||||||
|
__Field::__other(__name) => {
|
||||||
|
__collect.push(_serde::#private::Some((
|
||||||
|
__name,
|
||||||
|
_serde::de::MapAccess::next_value_seed(&mut __map, _serde::#private::de::ContentVisitor::new())?)));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else if cattrs.deny_unknown_fields() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(quote! {
|
||||||
|
_ => { let _ = _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?; }
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing());
|
||||||
|
let match_keys = if cattrs.deny_unknown_fields() && all_skipped {
|
||||||
|
quote! {
|
||||||
|
// FIXME: Once feature(exhaustive_patterns) is stable:
|
||||||
|
// let _serde::#private::None::<__Field> = _serde::de::MapAccess::next_key(&mut __map)?;
|
||||||
|
_serde::#private::Option::map(
|
||||||
|
_serde::de::MapAccess::next_key::<__Field>(&mut __map)?,
|
||||||
|
|__impossible| match __impossible {});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
while let _serde::#private::Some(__key) = _serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
|
||||||
|
match __key {
|
||||||
|
#(#value_arms)*
|
||||||
|
#ignored_arm
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let extract_values = fields_names
|
||||||
|
.iter()
|
||||||
|
.filter(|&&(field, _)| !field.attrs.skip_deserializing() && !field.attrs.flatten())
|
||||||
|
.map(|(field, name)| {
|
||||||
|
let missing_expr = Match(expr_is_missing(field, cattrs));
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
let #name = match #name {
|
||||||
|
_serde::#private::Some(#name) => #name,
|
||||||
|
_serde::#private::None => #missing_expr
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let extract_collected = fields_names
|
||||||
|
.iter()
|
||||||
|
.filter(|&&(field, _)| field.attrs.flatten() && !field.attrs.skip_deserializing())
|
||||||
|
.map(|(field, name)| {
|
||||||
|
let field_ty = field.ty;
|
||||||
|
let func = match field.attrs.deserialize_with() {
|
||||||
|
None => {
|
||||||
|
let span = field.original.span();
|
||||||
|
quote_spanned!(span=> _serde::de::Deserialize::deserialize)
|
||||||
|
}
|
||||||
|
Some(path) => quote!(#path),
|
||||||
|
};
|
||||||
|
quote! {
|
||||||
|
let #name: #field_ty = #func(
|
||||||
|
_serde::#private::de::FlatMapDeserializer(
|
||||||
|
&mut __collect,
|
||||||
|
_serde::#private::PhantomData))?;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let collected_deny_unknown_fields = if has_flatten && cattrs.deny_unknown_fields() {
|
||||||
|
Some(quote! {
|
||||||
|
if let _serde::#private::Some(_serde::#private::Some((__key, _))) =
|
||||||
|
__collect.into_iter().filter(_serde::#private::Option::is_some).next()
|
||||||
|
{
|
||||||
|
if let _serde::#private::Some(__key) = _serde::#private::de::content_as_str(&__key) {
|
||||||
|
return _serde::#private::Err(
|
||||||
|
_serde::de::Error::custom(format_args!("unknown field `{}`", &__key)));
|
||||||
|
} else {
|
||||||
|
return _serde::#private::Err(
|
||||||
|
_serde::de::Error::custom(format_args!("unexpected map key")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = fields_names.iter().map(|(field, name)| {
|
||||||
|
let member = &field.member;
|
||||||
|
if field.attrs.skip_deserializing() {
|
||||||
|
let value = Expr(expr_is_missing(field, cattrs));
|
||||||
|
quote!(#member: #value)
|
||||||
|
} else {
|
||||||
|
quote!(#member: #name)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let let_default = match cattrs.default() {
|
||||||
|
attr::Default::Default => Some(quote!(
|
||||||
|
let __default: Self::Value = _serde::#private::Default::default();
|
||||||
|
)),
|
||||||
|
// If #path returns wrong type, error will be reported here (^^^^^).
|
||||||
|
// We attach span of the path to the function so it will be reported
|
||||||
|
// on the #[serde(default = "...")]
|
||||||
|
// ^^^^^
|
||||||
|
attr::Default::Path(path) => Some(quote_spanned!(path.span()=>
|
||||||
|
let __default: Self::Value = #path();
|
||||||
|
)),
|
||||||
|
attr::Default::None => {
|
||||||
|
// We don't need the default value, to prevent an unused variable warning
|
||||||
|
// we'll leave the line empty.
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut result = quote!(#struct_path { #(#result),* });
|
||||||
|
if params.has_getter {
|
||||||
|
let this_type = ¶ms.this_type;
|
||||||
|
let (_, ty_generics, _) = params.generics.split_for_impl();
|
||||||
|
result = quote! {
|
||||||
|
_serde::#private::Into::<#this_type #ty_generics>::into(#result)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
quote_block! {
|
||||||
|
#(#let_values)*
|
||||||
|
|
||||||
|
#let_collect
|
||||||
|
|
||||||
|
#match_keys
|
||||||
|
|
||||||
|
#let_default
|
||||||
|
|
||||||
|
#(#extract_values)*
|
||||||
|
|
||||||
|
#(#extract_collected)*
|
||||||
|
|
||||||
|
#collected_deny_unknown_fields
|
||||||
|
|
||||||
|
_serde::#private::Ok(#result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "deserialize_in_place")]
|
||||||
|
fn deserialize_map_in_place(
|
||||||
|
params: &Parameters,
|
||||||
|
fields: &[Field],
|
||||||
|
cattrs: &attr::Container,
|
||||||
|
) -> Fragment {
|
||||||
|
assert!(
|
||||||
|
!has_flatten(fields),
|
||||||
|
"inplace deserialization of maps does not support flatten fields"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create the field names for the fields.
|
||||||
|
let fields_names: Vec<_> = fields
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, field)| (field, field_i(i)))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// For deserialize_in_place, declare booleans for each field that will be
|
||||||
|
// deserialized.
|
||||||
|
let let_flags = fields_names
|
||||||
|
.iter()
|
||||||
|
.filter(|&&(field, _)| !field.attrs.skip_deserializing())
|
||||||
|
.map(|(_, name)| {
|
||||||
|
quote! {
|
||||||
|
let mut #name: bool = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Match arms to extract a value for a field.
|
||||||
|
let value_arms_from = fields_names
|
||||||
|
.iter()
|
||||||
|
.filter(|&&(field, _)| !field.attrs.skip_deserializing())
|
||||||
|
.map(|(field, name)| {
|
||||||
|
let deser_name = field.attrs.name().deserialize_name();
|
||||||
|
let member = &field.member;
|
||||||
|
|
||||||
|
let visit = match field.attrs.deserialize_with() {
|
||||||
|
None => {
|
||||||
|
quote! {
|
||||||
|
_serde::de::MapAccess::next_value_seed(&mut __map, _serde::#private::de::InPlaceSeed(&mut self.place.#member))?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(path) => {
|
||||||
|
let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path);
|
||||||
|
quote!({
|
||||||
|
#wrapper
|
||||||
|
self.place.#member = match _serde::de::MapAccess::next_value::<#wrapper_ty>(&mut __map) {
|
||||||
|
_serde::#private::Ok(__wrapper) => __wrapper.value,
|
||||||
|
_serde::#private::Err(__err) => {
|
||||||
|
return _serde::#private::Err(__err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
quote! {
|
||||||
|
__Field::#name => {
|
||||||
|
if #name {
|
||||||
|
return _serde::#private::Err(<__A::Error as _serde::de::Error>::duplicate_field(#deser_name));
|
||||||
|
}
|
||||||
|
#visit;
|
||||||
|
#name = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Visit ignored values to consume them
|
||||||
|
let ignored_arm = if cattrs.deny_unknown_fields() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(quote! {
|
||||||
|
_ => { let _ = _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?; }
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing());
|
||||||
|
|
||||||
|
let match_keys = if cattrs.deny_unknown_fields() && all_skipped {
|
||||||
|
quote! {
|
||||||
|
// FIXME: Once feature(exhaustive_patterns) is stable:
|
||||||
|
// let _serde::#private::None::<__Field> = _serde::de::MapAccess::next_key(&mut __map)?;
|
||||||
|
_serde::#private::Option::map(
|
||||||
|
_serde::de::MapAccess::next_key::<__Field>(&mut __map)?,
|
||||||
|
|__impossible| match __impossible {});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
while let _serde::#private::Some(__key) = _serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
|
||||||
|
match __key {
|
||||||
|
#(#value_arms_from)*
|
||||||
|
#ignored_arm
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let check_flags = fields_names
|
||||||
|
.iter()
|
||||||
|
.filter(|&&(field, _)| !field.attrs.skip_deserializing())
|
||||||
|
.map(|(field, name)| {
|
||||||
|
let missing_expr = expr_is_missing(field, cattrs);
|
||||||
|
// If missing_expr unconditionally returns an error, don't try
|
||||||
|
// to assign its value to self.place.
|
||||||
|
if field.attrs.default().is_none()
|
||||||
|
&& cattrs.default().is_none()
|
||||||
|
&& field.attrs.deserialize_with().is_some()
|
||||||
|
{
|
||||||
|
let missing_expr = Stmts(missing_expr);
|
||||||
|
quote! {
|
||||||
|
if !#name {
|
||||||
|
#missing_expr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let member = &field.member;
|
||||||
|
let missing_expr = Expr(missing_expr);
|
||||||
|
quote! {
|
||||||
|
if !#name {
|
||||||
|
self.place.#member = #missing_expr;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let this_type = ¶ms.this_type;
|
||||||
|
let (_, _, ty_generics, _) = params.generics();
|
||||||
|
|
||||||
|
let let_default = match cattrs.default() {
|
||||||
|
attr::Default::Default => Some(quote!(
|
||||||
|
let __default: #this_type #ty_generics = _serde::#private::Default::default();
|
||||||
|
)),
|
||||||
|
// If #path returns wrong type, error will be reported here (^^^^^).
|
||||||
|
// We attach span of the path to the function so it will be reported
|
||||||
|
// on the #[serde(default = "...")]
|
||||||
|
// ^^^^^
|
||||||
|
attr::Default::Path(path) => Some(quote_spanned!(path.span()=>
|
||||||
|
let __default: #this_type #ty_generics = #path();
|
||||||
|
)),
|
||||||
|
attr::Default::None => {
|
||||||
|
// We don't need the default value, to prevent an unused variable warning
|
||||||
|
// we'll leave the line empty.
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
quote_block! {
|
||||||
|
#(#let_flags)*
|
||||||
|
|
||||||
|
#match_keys
|
||||||
|
|
||||||
|
#let_default
|
||||||
|
|
||||||
|
#(#check_flags)*
|
||||||
|
|
||||||
|
_serde::#private::Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user