let ctxt = Ctxt::new(); let cont = match Container::from_ast(&ctxt, input, Derive::Deserialize, &private.ident()) {
Some(cont) => cont,
None => return Err(ctxt.check().unwrap_err()),
};
precondition(&ctxt, &cont);
ctxt.check()?;
let ident = &cont.ident; let params = Parameters::new(&cont); let (de_impl_generics, _, ty_generics, where_clause) = params.generics_with_de_lifetime(); let body = Stmts(deserialize_body(&cont, ¶ms)); let delife = params.borrowed.de_lifetime(); let allow_deprecated = allow_deprecated(input);
let impl_block = iflet Some(remote) = cont.attrs.remote() { let vis = &input.vis; let used = pretend::pretend_used(&cont, params.is_packed);
quote! { #[automatically_derived] #allow_deprecated impl#de_impl_generics#ident#ty_generics#where_clause { #visfn deserialize<__D>(__deserializer: __D) -> _serde::#private::Result<#remote#ty_generics, __D::Error> where
__D: _serde::Deserializer<#delife>,
{ #used #body
}
}
}
} else { let fn_deserialize_in_place = deserialize_in_place_body(&cont, ¶ms);
fn precondition_no_de_lifetime(cx: &Ctxt, cont: &Container) { iflet BorrowedLifetimes::Borrowed(_) = borrowed_lifetimes(cont) { for param in cont.generics.lifetimes() { if param.lifetime.to_string() == "'de" {
cx.error_spanned_by(
¶m.lifetime, "cannot deserialize when there is a lifetime parameter called 'de",
); return;
}
}
}
}
struct Parameters { /// Name of the type the `derive` is on.
local: syn::Ident,
/// Path to the type the impl is for. Either a single `Ident` for local /// types (does not include generic parameters) or `some::remote::Path` for /// remote types.
this_type: syn::Path,
/// Same as `this_type` but using `::<T>` for generic parameters for use in /// expression position.
this_value: syn::Path,
/// Generics including any explicit and inferred bounds for the impl.
generics: syn::Generics,
/// Lifetimes borrowed from the deserializer. These will become bounds on /// the `'de` lifetime of the deserializer.
borrowed: BorrowedLifetimes,
/// At least one field has a serde(getter) attribute, implying that the /// remote type has a private field.
has_getter: bool,
/// Type has a repr(packed) attribute.
is_packed: bool,
}
impl Parameters { fn new(cont: &Container) -> Self { let local = cont.ident.clone(); let this_type = this::this_type(cont); let this_value = this::this_value(cont); let borrowed = borrowed_lifetimes(cont); let generics = build_generics(cont, &borrowed); let has_getter = cont.data.has_getter(); let is_packed = cont.attrs.is_packed();
/// Type name to use in error messages and `&'static str` arguments to /// various Deserializer methods. fn type_name(&self) -> String { self.this_type.segments.last().unwrap().ident.to_string()
}
/// Split the data structure's generics into the pieces to use for its /// `Deserialize` impl, augmented with an additional `'de` lifetime for use /// as the `Deserialize` trait's lifetime. fn generics_with_de_lifetime(
&self,
) -> (
DeImplGenerics,
DeTypeGenerics,
syn::TypeGenerics,
Option<&syn::WhereClause>,
) { let de_impl_generics = DeImplGenerics(self); let de_ty_generics = DeTypeGenerics(self); let (_, ty_generics, where_clause) = self.generics.split_for_impl();
(de_impl_generics, de_ty_generics, ty_generics, where_clause)
}
}
// All the generics in the input, plus a bound `T: Deserialize` for each generic // field type that will be deserialized by us, plus a bound `T: Default` for // each generic field type that will be set to a default value. fn build_generics(cont: &Container, borrowed: &BorrowedLifetimes) -> syn::Generics { let generics = bound::without_defaults(cont.generics);
let generics = bound::with_where_predicates_from_fields(cont, &generics, attr::Field::de_bound);
let generics =
bound::with_where_predicates_from_variants(cont, &generics, attr::Variant::de_bound);
match cont.attrs.de_bound() {
Some(predicates) => bound::with_where_predicates(&generics, predicates),
None => { let generics = match *cont.attrs.default() {
attr::Default::Default => bound::with_self_bound(
cont,
&generics,
&parse_quote!(_serde::#private::Default),
),
attr::Default::None | attr::Default::Path(_) => generics,
};
let delife = borrowed.de_lifetime(); let generics = bound::with_bound(
cont,
&generics,
needs_deserialize_bound,
&parse_quote!(_serde::Deserialize<#delife>),
);
// Fields with a `skip_deserializing` or `deserialize_with` attribute, or which // belong to a variant with a `skip_deserializing` or `deserialize_with` // attribute, are not deserialized by us so we do not generate a bound. Fields // with a `bound` attribute specify their own bound so we do not generate one. // All other fields may need a `T: Deserialize` bound where T is the type of the // field. fn needs_deserialize_bound(field: &attr::Field, variant: Option<&attr::Variant>) -> bool {
!field.skip_deserializing()
&& field.deserialize_with().is_none()
&& field.de_bound().is_none()
&& variant.map_or(true, |variant| {
!variant.skip_deserializing()
&& variant.deserialize_with().is_none()
&& variant.de_bound().is_none()
})
}
// Fields with a `default` attribute (not `default=...`), and fields with a // `skip_deserializing` attribute that do not also have `default=...`. fn requires_default(field: &attr::Field, _variant: Option<&attr::Variant>) -> bool { iflet attr::Default::Default = *field.default() { true
} else { false
}
}
// The union of lifetimes borrowed by each field of the container. // // These turn into bounds on the `'de` lifetime of the Deserialize impl. If // lifetimes `'a` and `'b` are borrowed but `'c` is not, the impl is: // // impl<'de: 'a + 'b, 'a, 'b, 'c> Deserialize<'de> for S<'a, 'b, 'c> // // If any borrowed lifetime is `'static`, then `'de: 'static` would be redundant // and we use plain `'static` instead of `'de`. fn borrowed_lifetimes(cont: &Container) -> BorrowedLifetimes { letmut lifetimes = BTreeSet::new(); for field in cont.data.all_fields() { if !field.attrs.skip_deserializing() {
lifetimes.extend(field.attrs.borrowed_lifetimes().iter().cloned());
}
} if lifetimes.iter().any(|b| b.to_string() == "'static") {
BorrowedLifetimes::Static
} else {
BorrowedLifetimes::Borrowed(lifetimes)
}
}
#[cfg(feature = "deserialize_in_place")] fn deserialize_in_place_body(cont: &Container, params: &Parameters) -> Option<Stmts> { // Only remote derives have getters, and we do not generate // deserialize_in_place for remote derives.
assert!(!params.has_getter);
/// Generates `Deserialize::deserialize` body for a type with `#[serde(transparent)]` attribute fn deserialize_transparent(cont: &Container, params: &Parameters) -> Fragment { let fields = match &cont.data {
Data::Struct(_, fields) => fields,
Data::Enum(_) => unreachable!(),
};
let this_value = ¶ms.this_value; let transparent_field = fields.iter().find(|f| f.attrs.transparent()).unwrap();
let path = match transparent_field.attrs.deserialize_with() {
Some(path) => quote!(#path),
None => { let span = transparent_field.original.span();
quote_spanned!(span=> _serde::Deserialize::deserialize)
}
};
let assign = fields.iter().map(|field| { let member = &field.member; if ptr::eq(field, transparent_field) {
quote!(#member: __transparent)
} else { let value = match field.attrs.default() {
attr::Default::Default => quote!(_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) => quote_spanned!(path.span()=> #path()),
attr::Default::None => quote!(_serde::#private::PhantomData),
};
quote!(#member: #value)
}
});
/// Generates `Deserialize::deserialize` body for a type with `#[serde(from)]` attribute fn deserialize_from(type_from: &syn::Type) -> Fragment {
quote_block! {
_serde::#private::Result::map(
<#type_fromas _serde::Deserialize>::deserialize(__deserializer),
_serde::#private::From::from)
}
}
/// Generates `Deserialize::deserialize` body for a type with `#[serde(try_from)]` attribute fn deserialize_try_from(type_try_from: &syn::Type) -> Fragment {
quote_block! {
_serde::#private::Result::and_then(
<#type_try_fromas _serde::Deserialize>::deserialize(__deserializer),
|v| _serde::#private::TryFrom::try_from(v).map_err(_serde::de::Error::custom))
}
}
enum TupleForm<'a> {
Tuple, /// Contains a variant name
ExternallyTagged(&'a syn::Ident), /// Contains a variant name
Untagged(&'a syn::Ident),
}
fn deserialize_seq(
type_path: &TokenStream,
params: &Parameters,
fields: &[Field],
is_struct: bool,
cattrs: &attr::Container,
expecting: &str,
) -> Fragment { let vars = (0..fields.len()).map(field_i asfn(_) -> _);
let deserialized_count = fields
.iter()
.filter(|field| !field.attrs.skip_deserializing())
.count(); let expecting = if deserialized_count == 1 {
format!("{} with 1 element", expecting)
} else {
format!("{} with {} elements", expecting, deserialized_count)
}; let expecting = cattrs.expecting().unwrap_or(&expecting);
letmut index_in_seq = 0_usize; let let_values = vars.clone().zip(fields).map(|(var, field)| { if field.attrs.skip_deserializing() { let default = Expr(expr_is_missing(field, cattrs));
quote! { let#var = #default;
}
} else { 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::SeqAccess::next_element::<#field_ty>);
quote!(#func(&mut __seq)?)
}
Some(path) => { let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path);
quote!({ #wrapper
_serde::#private::Option::map(
_serde::de::SeqAccess::next_element::<#wrapper_ty>(&mut __seq)?,
|__wrap| __wrap.value)
})
}
}; let value_if_none = expr_is_missing_seq(None, index_in_seq, field, cattrs, expecting); let assign = quote! { let#var = match#visit {
_serde::#private::Some(__value) => __value,
_serde::#private::None => #value_if_none,
};
};
index_in_seq += 1;
assign
}
});
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)
};
}
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 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
}
};
enum StructForm<'a> { Struct, /// Contains a variant name
ExternallyTagged(&'a syn::Ident), /// Contains a variant name
InternallyTagged(&'a syn::Ident), /// Contains a variant name
Untagged(&'a syn::Ident),
}
/// This function wraps the expression in `#[serde(deserialize_with = "...")]` /// in a trait to prevent it from accessing the internal `Deserialize` state. fn wrap_deserialize_with(
params: &Parameters,
value_ty: &TokenStream,
deserialize_with: &syn::ExprPath,
) -> (TokenStream, TokenStream) { 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 deserializer_var = quote!(__deserializer);
// If #deserialize_with 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(with = "...")] // ^^^^^ let value = quote_spanned! {deserialize_with.span()=> #deserialize_with(#deserializer_var)?
}; let wrapper = quote! { #[doc(hidden)] struct __DeserializeWith #de_impl_generics#where_clause {
value: #value_ty,
phantom: _serde::#private::PhantomData<#this_type#ty_generics>,
lifetime: _serde::#private::PhantomData<&#delife ()>,
}
// Generates closure that converts single input parameter to the final value. fn unwrap_to_variant_closure(
params: &Parameters,
variant: &Variant,
with_wrapper: bool,
) -> TokenStream { let this_value = ¶ms.this_value; let variant_ident = &variant.ident;
fn expr_is_missing(field: &Field, cattrs: &attr::Container) -> Fragment { match field.attrs.default() {
attr::Default::Default => { let span = field.original.span(); let func = quote_spanned!(span=> _serde::#private::Default::default); return quote_expr!(#func());
}
attr::Default::Path(path) => { // 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 = "...")] // ^^^^^ return Fragment::Expr(quote_spanned!(path.span()=> #path()));
}
attr::Default::None => { /* below */ }
}
match *cattrs.default() {
attr::Default::Default | attr::Default::Path(_) => { let member = &field.member; return quote_expr!(__default.#member);
}
attr::Default::None => { /* below */ }
}
let name = field.attrs.name().deserialize_name(); match field.attrs.deserialize_with() {
None => { let span = field.original.span(); let func = quote_spanned!(span=> _serde::#private::de::missing_field);
quote_expr! { #func(#name)?
}
}
Some(_) => {
quote_expr! { return _serde::#private::Err(<__A::Error as _serde::de::Error>::missing_field(#name))
}
}
}
}
fn expr_is_missing_seq(
assign_to: Option<TokenStream>,
index: usize,
field: &Field,
cattrs: &attr::Container,
expecting: &str,
) -> TokenStream { match field.attrs.default() {
attr::Default::Default => { let span = field.original.span(); return quote_spanned!(span=> #assign_to _serde::#private::Default::default());
}
attr::Default::Path(path) => { // 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 = "...")] // ^^^^^ return quote_spanned!(path.span()=> #assign_to#path());
}
attr::Default::None => { /* below */ }
}
match *cattrs.default() {
attr::Default::Default | attr::Default::Path(_) => { let member = &field.member;
quote!(#assign_to __default.#member)
}
attr::Default::None => quote!( return _serde::#private::Err(_serde::de::Error::invalid_length(#index, &'color:turquoise'>#expecting))
),
}
}
fn effective_style(variant: &Variant) -> Style { match variant.style {
Style::Newtype if variant.fields[0].attrs.skip_deserializing() => Style::Unit,
other => other,
}
}
/// True if there is any field with a `#[serde(flatten)]` attribute, other than /// fields which are skipped. fn has_flatten(fields: &[Field]) -> bool {
fields
.iter()
.any(|field| field.attrs.flatten() && !field.attrs.skip_deserializing())
}
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.