usecrate::de::identifier; usecrate::de::{
deserialize_seq, expr_is_missing, field_i, has_flatten, wrap_deserialize_field_with,
FieldWithAliases, Parameters, StructForm,
}; #[cfg(feature = "deserialize_in_place")] usecrate::de::{deserialize_seq_in_place, place_lifetime}; usecrate::fragment::{Expr, Fragment, Match, Stmts}; usecrate::internals::ast::Field; usecrate::internals::attr; usecrate::private; use proc_macro2::TokenStream; use quote::{quote, quote_spanned}; use syn::spanned::Spanned;
/// Generates `Deserialize::deserialize` body for a `struct Struct {...}` pub(super) fn deserialize(
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_with_de_lifetime(); 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 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;
#[automatically_derived] impl#de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics#where_clause { type Value = #this_type#ty_generics;
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! { letmut#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! { letmut __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())?)));
}
})
} elseif 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! { whilelet _serde::#private::Some(__key) = _serde::de::MapAccess::next_key::<__Field>(&pan style='color:red'>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));
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
}
};
letmut 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)
}
}
/// Generates `Deserialize::deserialize_in_place` body for a `struct Struct {...}` #[cfg(feature = "deserialize_in_place")] pub(super) fn deserialize_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_with_de_lifetime(); let delife = params.borrowed.de_lifetime();
let expecting = format!("struct {}", params.type_name()); let expecting = cattrs.expecting().unwrap_or(&expecting);
#[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! { letmut#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;
// 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! { whilelet _serde::#private::Some(__key) = _serde::de::MapAccess::next_key::<__Field>(&pan style='color:red'>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.split_for_impl();
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(())
}
}
/// 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))
} elseif 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))
};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.