Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

410
vendor/serde_derive/src/bound.rs vendored Normal file
View File

@@ -0,0 +1,410 @@
use crate::internals::ast::{Container, Data};
use crate::internals::{attr, ungroup};
use proc_macro2::Span;
use std::collections::HashSet;
use syn::punctuated::{Pair, Punctuated};
use syn::Token;
// Remove the default from every type parameter because in the generated impls
// they look like associated types: "error: associated type bindings are not
// allowed here".
pub fn without_defaults(generics: &syn::Generics) -> syn::Generics {
syn::Generics {
params: generics
.params
.iter()
.map(|param| match param {
syn::GenericParam::Type(param) => syn::GenericParam::Type(syn::TypeParam {
eq_token: None,
default: None,
..param.clone()
}),
_ => param.clone(),
})
.collect(),
..generics.clone()
}
}
pub fn with_where_predicates(
generics: &syn::Generics,
predicates: &[syn::WherePredicate],
) -> syn::Generics {
let mut generics = generics.clone();
generics
.make_where_clause()
.predicates
.extend(predicates.iter().cloned());
generics
}
pub fn with_where_predicates_from_fields(
cont: &Container,
generics: &syn::Generics,
from_field: fn(&attr::Field) -> Option<&[syn::WherePredicate]>,
) -> syn::Generics {
let predicates = cont
.data
.all_fields()
.filter_map(|field| from_field(&field.attrs))
.flat_map(<[syn::WherePredicate]>::to_vec);
let mut generics = generics.clone();
generics.make_where_clause().predicates.extend(predicates);
generics
}
pub fn with_where_predicates_from_variants(
cont: &Container,
generics: &syn::Generics,
from_variant: fn(&attr::Variant) -> Option<&[syn::WherePredicate]>,
) -> syn::Generics {
let variants = match &cont.data {
Data::Enum(variants) => variants,
Data::Struct(_, _) => {
return generics.clone();
}
};
let predicates = variants
.iter()
.filter_map(|variant| from_variant(&variant.attrs))
.flat_map(<[syn::WherePredicate]>::to_vec);
let mut generics = generics.clone();
generics.make_where_clause().predicates.extend(predicates);
generics
}
// Puts the given bound on any generic type parameters that are used in fields
// for which filter returns true.
//
// For example, the following struct needs the bound `A: Serialize, B:
// Serialize`.
//
// struct S<'b, A, B: 'b, C> {
// a: A,
// b: Option<&'b B>
// #[serde(skip_serializing)]
// c: C,
// }
pub fn with_bound(
cont: &Container,
generics: &syn::Generics,
filter: fn(&attr::Field, Option<&attr::Variant>) -> bool,
bound: &syn::Path,
) -> syn::Generics {
struct FindTyParams<'ast> {
// Set of all generic type parameters on the current struct (A, B, C in
// the example). Initialized up front.
all_type_params: HashSet<syn::Ident>,
// Set of generic type parameters used in fields for which filter
// returns true (A and B in the example). Filled in as the visitor sees
// them.
relevant_type_params: HashSet<syn::Ident>,
// Fields whose type is an associated type of one of the generic type
// parameters.
associated_type_usage: Vec<&'ast syn::TypePath>,
}
impl<'ast> FindTyParams<'ast> {
fn visit_field(&mut self, field: &'ast syn::Field) {
if let syn::Type::Path(ty) = ungroup(&field.ty) {
if let Some(Pair::Punctuated(t, _)) = ty.path.segments.pairs().next() {
if self.all_type_params.contains(&t.ident) {
self.associated_type_usage.push(ty);
}
}
}
self.visit_type(&field.ty);
}
fn visit_path(&mut self, path: &'ast syn::Path) {
if let Some(seg) = path.segments.last() {
if seg.ident == "PhantomData" {
// Hardcoded exception, because PhantomData<T> implements
// Serialize and Deserialize whether or not T implements it.
return;
}
}
if path.leading_colon.is_none() && path.segments.len() == 1 {
let id = &path.segments[0].ident;
if self.all_type_params.contains(id) {
self.relevant_type_params.insert(id.clone());
}
}
for segment in &path.segments {
self.visit_path_segment(segment);
}
}
// Everything below is simply traversing the syntax tree.
fn visit_type(&mut self, ty: &'ast syn::Type) {
match ty {
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
syn::Type::Array(ty) => self.visit_type(&ty.elem),
syn::Type::BareFn(ty) => {
for arg in &ty.inputs {
self.visit_type(&arg.ty);
}
self.visit_return_type(&ty.output);
}
syn::Type::Group(ty) => self.visit_type(&ty.elem),
syn::Type::ImplTrait(ty) => {
for bound in &ty.bounds {
self.visit_type_param_bound(bound);
}
}
syn::Type::Macro(ty) => self.visit_macro(&ty.mac),
syn::Type::Paren(ty) => self.visit_type(&ty.elem),
syn::Type::Path(ty) => {
if let Some(qself) = &ty.qself {
self.visit_type(&qself.ty);
}
self.visit_path(&ty.path);
}
syn::Type::Ptr(ty) => self.visit_type(&ty.elem),
syn::Type::Reference(ty) => self.visit_type(&ty.elem),
syn::Type::Slice(ty) => self.visit_type(&ty.elem),
syn::Type::TraitObject(ty) => {
for bound in &ty.bounds {
self.visit_type_param_bound(bound);
}
}
syn::Type::Tuple(ty) => {
for elem in &ty.elems {
self.visit_type(elem);
}
}
syn::Type::Infer(_) | syn::Type::Never(_) | syn::Type::Verbatim(_) => {}
_ => {}
}
}
fn visit_path_segment(&mut self, segment: &'ast syn::PathSegment) {
self.visit_path_arguments(&segment.arguments);
}
fn visit_path_arguments(&mut self, arguments: &'ast syn::PathArguments) {
match arguments {
syn::PathArguments::None => {}
syn::PathArguments::AngleBracketed(arguments) => {
for arg in &arguments.args {
match arg {
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
syn::GenericArgument::Type(arg) => self.visit_type(arg),
syn::GenericArgument::AssocType(arg) => self.visit_type(&arg.ty),
syn::GenericArgument::Lifetime(_)
| syn::GenericArgument::Const(_)
| syn::GenericArgument::AssocConst(_)
| syn::GenericArgument::Constraint(_) => {}
_ => {}
}
}
}
syn::PathArguments::Parenthesized(arguments) => {
for argument in &arguments.inputs {
self.visit_type(argument);
}
self.visit_return_type(&arguments.output);
}
}
}
fn visit_return_type(&mut self, return_type: &'ast syn::ReturnType) {
match return_type {
syn::ReturnType::Default => {}
syn::ReturnType::Type(_, output) => self.visit_type(output),
}
}
fn visit_type_param_bound(&mut self, bound: &'ast syn::TypeParamBound) {
match bound {
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
syn::TypeParamBound::Trait(bound) => self.visit_path(&bound.path),
syn::TypeParamBound::Lifetime(_)
| syn::TypeParamBound::PreciseCapture(_)
| syn::TypeParamBound::Verbatim(_) => {}
_ => {}
}
}
// Type parameter should not be considered used by a macro path.
//
// struct TypeMacro<T> {
// mac: T!(),
// marker: PhantomData<T>,
// }
fn visit_macro(&mut self, _mac: &'ast syn::Macro) {}
}
let all_type_params = generics
.type_params()
.map(|param| param.ident.clone())
.collect();
let mut visitor = FindTyParams {
all_type_params,
relevant_type_params: HashSet::new(),
associated_type_usage: Vec::new(),
};
match &cont.data {
Data::Enum(variants) => {
for variant in variants {
let relevant_fields = variant
.fields
.iter()
.filter(|field| filter(&field.attrs, Some(&variant.attrs)));
for field in relevant_fields {
visitor.visit_field(field.original);
}
}
}
Data::Struct(_, fields) => {
for field in fields.iter().filter(|field| filter(&field.attrs, None)) {
visitor.visit_field(field.original);
}
}
}
let relevant_type_params = visitor.relevant_type_params;
let associated_type_usage = visitor.associated_type_usage;
let new_predicates = generics
.type_params()
.map(|param| param.ident.clone())
.filter(|id| relevant_type_params.contains(id))
.map(|id| syn::TypePath {
qself: None,
path: id.into(),
})
.chain(associated_type_usage.into_iter().cloned())
.map(|bounded_ty| {
syn::WherePredicate::Type(syn::PredicateType {
lifetimes: None,
// the type parameter that is being bounded e.g. T
bounded_ty: syn::Type::Path(bounded_ty),
colon_token: <Token![:]>::default(),
// the bound e.g. Serialize
bounds: vec![syn::TypeParamBound::Trait(syn::TraitBound {
paren_token: None,
modifier: syn::TraitBoundModifier::None,
lifetimes: None,
path: bound.clone(),
})]
.into_iter()
.collect(),
})
});
let mut generics = generics.clone();
generics
.make_where_clause()
.predicates
.extend(new_predicates);
generics
}
pub fn with_self_bound(
cont: &Container,
generics: &syn::Generics,
bound: &syn::Path,
) -> syn::Generics {
let mut generics = generics.clone();
generics
.make_where_clause()
.predicates
.push(syn::WherePredicate::Type(syn::PredicateType {
lifetimes: None,
// the type that is being bounded e.g. MyStruct<'a, T>
bounded_ty: type_of_item(cont),
colon_token: <Token![:]>::default(),
// the bound e.g. Default
bounds: vec![syn::TypeParamBound::Trait(syn::TraitBound {
paren_token: None,
modifier: syn::TraitBoundModifier::None,
lifetimes: None,
path: bound.clone(),
})]
.into_iter()
.collect(),
}));
generics
}
pub fn with_lifetime_bound(generics: &syn::Generics, lifetime: &str) -> syn::Generics {
let bound = syn::Lifetime::new(lifetime, Span::call_site());
let def = syn::LifetimeParam {
attrs: Vec::new(),
lifetime: bound.clone(),
colon_token: None,
bounds: Punctuated::new(),
};
let params = Some(syn::GenericParam::Lifetime(def))
.into_iter()
.chain(generics.params.iter().cloned().map(|mut param| {
match &mut param {
syn::GenericParam::Lifetime(param) => {
param.bounds.push(bound.clone());
}
syn::GenericParam::Type(param) => {
param
.bounds
.push(syn::TypeParamBound::Lifetime(bound.clone()));
}
syn::GenericParam::Const(_) => {}
}
param
}))
.collect();
syn::Generics {
params,
..generics.clone()
}
}
fn type_of_item(cont: &Container) -> syn::Type {
syn::Type::Path(syn::TypePath {
qself: None,
path: syn::Path {
leading_colon: None,
segments: vec![syn::PathSegment {
ident: cont.ident.clone(),
arguments: syn::PathArguments::AngleBracketed(
syn::AngleBracketedGenericArguments {
colon2_token: None,
lt_token: <Token![<]>::default(),
args: cont
.generics
.params
.iter()
.map(|param| match param {
syn::GenericParam::Type(param) => {
syn::GenericArgument::Type(syn::Type::Path(syn::TypePath {
qself: None,
path: param.ident.clone().into(),
}))
}
syn::GenericParam::Lifetime(param) => {
syn::GenericArgument::Lifetime(param.lifetime.clone())
}
syn::GenericParam::Const(_) => {
panic!("Serde does not support const generics yet");
}
})
.collect(),
gt_token: <Token![>]>::default(),
},
),
}]
.into_iter()
.collect(),
},
})
}

973
vendor/serde_derive/src/de.rs vendored Normal file
View File

@@ -0,0 +1,973 @@
use crate::deprecated::allow_deprecated;
use crate::fragment::{Expr, Fragment, Stmts};
use crate::internals::ast::{Container, Data, Field, Style, Variant};
use crate::internals::name::Name;
use crate::internals::{attr, replace_receiver, ungroup, Ctxt, Derive};
use crate::{bound, dummy, pretend, private, this};
use proc_macro2::{Span, TokenStream};
use quote::{quote, quote_spanned, ToTokens};
use std::collections::BTreeSet;
use std::ptr;
use syn::punctuated::Punctuated;
use syn::spanned::Spanned;
use syn::{parse_quote, Ident, Index, Member};
mod enum_;
mod enum_adjacently;
mod enum_externally;
mod enum_internally;
mod enum_untagged;
mod identifier;
mod struct_;
mod tuple;
mod unit;
pub fn expand_derive_deserialize(input: &mut syn::DeriveInput) -> syn::Result<TokenStream> {
replace_receiver(input);
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, &params));
let delife = params.borrowed.de_lifetime();
let allow_deprecated = allow_deprecated(input);
let impl_block = if let 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 {
#vis fn 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, &params);
quote! {
#[automatically_derived]
#allow_deprecated
impl #de_impl_generics _serde::Deserialize<#delife> for #ident #ty_generics #where_clause {
fn deserialize<__D>(__deserializer: __D) -> _serde::#private::Result<Self, __D::Error>
where
__D: _serde::Deserializer<#delife>,
{
#body
}
#fn_deserialize_in_place
}
}
};
Ok(dummy::wrap_in_const(
cont.attrs.custom_serde_path(),
impl_block,
))
}
fn precondition(cx: &Ctxt, cont: &Container) {
precondition_sized(cx, cont);
precondition_no_de_lifetime(cx, cont);
}
fn precondition_sized(cx: &Ctxt, cont: &Container) {
if let Data::Struct(_, fields) = &cont.data {
if let Some(last) = fields.last() {
if let syn::Type::Slice(_) = ungroup(last.ty) {
cx.error_spanned_by(
cont.original,
"cannot deserialize a dynamically sized struct",
);
}
}
}
}
fn precondition_no_de_lifetime(cx: &Ctxt, cont: &Container) {
if let BorrowedLifetimes::Borrowed(_) = borrowed_lifetimes(cont) {
for param in cont.generics.lifetimes() {
if param.lifetime.to_string() == "'de" {
cx.error_spanned_by(
&param.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();
Parameters {
local,
this_type,
this_value,
generics,
borrowed,
has_getter,
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>),
);
bound::with_bound(
cont,
&generics,
requires_default,
&parse_quote!(_serde::#private::Default),
)
}
}
}
// 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 {
if let attr::Default::Default = *field.default() {
true
} else {
false
}
}
enum BorrowedLifetimes {
Borrowed(BTreeSet<syn::Lifetime>),
Static,
}
impl BorrowedLifetimes {
fn de_lifetime(&self) -> syn::Lifetime {
match *self {
BorrowedLifetimes::Borrowed(_) => syn::Lifetime::new("'de", Span::call_site()),
BorrowedLifetimes::Static => syn::Lifetime::new("'static", Span::call_site()),
}
}
fn de_lifetime_param(&self) -> Option<syn::LifetimeParam> {
match self {
BorrowedLifetimes::Borrowed(bounds) => Some(syn::LifetimeParam {
attrs: Vec::new(),
lifetime: syn::Lifetime::new("'de", Span::call_site()),
colon_token: None,
bounds: bounds.iter().cloned().collect(),
}),
BorrowedLifetimes::Static => None,
}
}
}
// 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 {
let mut 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)
}
}
fn deserialize_body(cont: &Container, params: &Parameters) -> Fragment {
if cont.attrs.transparent() {
deserialize_transparent(cont, params)
} else if let Some(type_from) = cont.attrs.type_from() {
deserialize_from(type_from)
} else if let Some(type_try_from) = cont.attrs.type_try_from() {
deserialize_try_from(type_try_from)
} else if let attr::Identifier::No = cont.attrs.identifier() {
match &cont.data {
Data::Enum(variants) => enum_::deserialize(params, variants, &cont.attrs),
Data::Struct(Style::Struct, fields) => {
struct_::deserialize(params, fields, &cont.attrs, StructForm::Struct)
}
Data::Struct(Style::Tuple, fields) | Data::Struct(Style::Newtype, fields) => {
tuple::deserialize(params, fields, &cont.attrs, TupleForm::Tuple)
}
Data::Struct(Style::Unit, _) => unit::deserialize(params, &cont.attrs),
}
} else {
match &cont.data {
Data::Enum(variants) => identifier::deserialize_custom(params, variants, &cont.attrs),
Data::Struct(_, _) => unreachable!("checked in serde_derive_internals"),
}
}
}
#[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);
if cont.attrs.transparent()
|| cont.attrs.type_from().is_some()
|| cont.attrs.type_try_from().is_some()
|| cont.attrs.identifier().is_some()
|| cont
.data
.all_fields()
.all(|f| f.attrs.deserialize_with().is_some())
{
return None;
}
let code = match &cont.data {
Data::Struct(Style::Struct, fields) => {
struct_::deserialize_in_place(params, fields, &cont.attrs)?
}
Data::Struct(Style::Tuple, fields) | Data::Struct(Style::Newtype, fields) => {
tuple::deserialize_in_place(params, fields, &cont.attrs)
}
Data::Enum(_) | Data::Struct(Style::Unit, _) => {
return None;
}
};
let delife = params.borrowed.de_lifetime();
let stmts = Stmts(code);
let fn_deserialize_in_place = quote_block! {
fn deserialize_in_place<__D>(__deserializer: __D, __place: &mut Self) -> _serde::#private::Result<(), __D::Error>
where
__D: _serde::Deserializer<#delife>,
{
#stmts
}
};
Some(Stmts(fn_deserialize_in_place))
}
#[cfg(not(feature = "deserialize_in_place"))]
fn deserialize_in_place_body(_cont: &Container, _params: &Parameters) -> Option<Stmts> {
None
}
/// 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 = &params.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)
}
});
quote_block! {
_serde::#private::Result::map(
#path(__deserializer),
|__transparent| #this_value { #(#assign),* })
}
}
/// 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_from as _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_from as _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 as fn(_) -> _);
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);
let mut 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
}
});
let mut result = if is_struct {
let names = fields.iter().map(|f| &f.member);
quote! {
#type_path { #( #names: #vars ),* }
}
} else {
quote! {
#type_path ( #(#vars),* )
}
};
if params.has_getter {
let this_type = &params.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
}
};
quote_block! {
#let_default
#(#let_values)*
_serde::#private::Ok(#result)
}
}
#[cfg(feature = "deserialize_in_place")]
fn deserialize_seq_in_place(
params: &Parameters,
fields: &[Field],
cattrs: &attr::Container,
expecting: &str,
) -> Fragment {
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);
let mut index_in_seq = 0usize;
let write_values = fields.iter().map(|field| {
let member = &field.member;
if field.attrs.skip_deserializing() {
let default = Expr(expr_is_missing(field, cattrs));
quote! {
self.place.#member = #default;
}
} else {
let value_if_none = expr_is_missing_seq(Some(quote!(self.place.#member = )), index_in_seq, field, cattrs, expecting);
let write = match field.attrs.deserialize_with() {
None => {
quote! {
if let _serde::#private::None = _serde::de::SeqAccess::next_element_seed(&mut __seq,
_serde::#private::de::InPlaceSeed(&mut self.place.#member))?
{
#value_if_none;
}
}
}
Some(path) => {
let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path);
quote!({
#wrapper
match _serde::de::SeqAccess::next_element::<#wrapper_ty>(&mut __seq)? {
_serde::#private::Some(__wrap) => {
self.place.#member = __wrap.value;
}
_serde::#private::None => {
#value_if_none;
}
}
})
}
};
index_in_seq += 1;
write
}
});
let this_type = &params.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_default
#(#write_values)*
_serde::#private::Ok(())
}
}
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),
}
struct FieldWithAliases<'a> {
ident: Ident,
aliases: &'a BTreeSet<Name>,
}
fn field_i(i: usize) -> Ident {
Ident::new(&format!("__field{}", i), Span::call_site())
}
/// 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 = &params.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 ()>,
}
#[automatically_derived]
impl #de_impl_generics _serde::Deserialize<#delife> for __DeserializeWith #de_ty_generics #where_clause {
fn deserialize<__D>(#deserializer_var: __D) -> _serde::#private::Result<Self, __D::Error>
where
__D: _serde::Deserializer<#delife>,
{
_serde::#private::Ok(__DeserializeWith {
value: #value,
phantom: _serde::#private::PhantomData,
lifetime: _serde::#private::PhantomData,
})
}
}
};
let wrapper_ty = quote!(__DeserializeWith #de_ty_generics);
(wrapper, wrapper_ty)
}
fn wrap_deserialize_field_with(
params: &Parameters,
field_ty: &syn::Type,
deserialize_with: &syn::ExprPath,
) -> (TokenStream, TokenStream) {
wrap_deserialize_with(params, &quote!(#field_ty), deserialize_with)
}
// 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 = &params.this_value;
let variant_ident = &variant.ident;
let (arg, wrapper) = if with_wrapper {
(quote! { __wrap }, quote! { __wrap.value })
} else {
let field_tys = variant.fields.iter().map(|field| field.ty);
(quote! { __wrap: (#(#field_tys),*) }, quote! { __wrap })
};
let field_access = (0..variant.fields.len()).map(|n| {
Member::Unnamed(Index {
index: n as u32,
span: Span::call_site(),
})
});
match variant.style {
Style::Struct if variant.fields.len() == 1 => {
let member = &variant.fields[0].member;
quote! {
|#arg| #this_value::#variant_ident { #member: #wrapper }
}
}
Style::Struct => {
let members = variant.fields.iter().map(|field| &field.member);
quote! {
|#arg| #this_value::#variant_ident { #(#members: #wrapper.#field_access),* }
}
}
Style::Tuple => quote! {
|#arg| #this_value::#variant_ident(#(#wrapper.#field_access),*)
},
Style::Newtype => quote! {
|#arg| #this_value::#variant_ident(#wrapper)
},
Style::Unit => quote! {
|#arg| #this_value::#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, &#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())
}
struct DeImplGenerics<'a>(&'a Parameters);
#[cfg(feature = "deserialize_in_place")]
struct InPlaceImplGenerics<'a>(&'a Parameters);
impl<'a> ToTokens for DeImplGenerics<'a> {
fn to_tokens(&self, tokens: &mut TokenStream) {
let mut generics = self.0.generics.clone();
if let Some(de_lifetime) = self.0.borrowed.de_lifetime_param() {
generics.params = Some(syn::GenericParam::Lifetime(de_lifetime))
.into_iter()
.chain(generics.params)
.collect();
}
let (impl_generics, _, _) = generics.split_for_impl();
impl_generics.to_tokens(tokens);
}
}
#[cfg(feature = "deserialize_in_place")]
impl<'a> ToTokens for InPlaceImplGenerics<'a> {
fn to_tokens(&self, tokens: &mut TokenStream) {
let place_lifetime = place_lifetime();
let mut generics = self.0.generics.clone();
// Add lifetime for `&'place mut Self, and `'a: 'place`
for param in &mut generics.params {
match param {
syn::GenericParam::Lifetime(param) => {
param.bounds.push(place_lifetime.lifetime.clone());
}
syn::GenericParam::Type(param) => {
param.bounds.push(syn::TypeParamBound::Lifetime(
place_lifetime.lifetime.clone(),
));
}
syn::GenericParam::Const(_) => {}
}
}
generics.params = Some(syn::GenericParam::Lifetime(place_lifetime))
.into_iter()
.chain(generics.params)
.collect();
if let Some(de_lifetime) = self.0.borrowed.de_lifetime_param() {
generics.params = Some(syn::GenericParam::Lifetime(de_lifetime))
.into_iter()
.chain(generics.params)
.collect();
}
let (impl_generics, _, _) = generics.split_for_impl();
impl_generics.to_tokens(tokens);
}
}
#[cfg(feature = "deserialize_in_place")]
impl<'a> DeImplGenerics<'a> {
fn in_place(self) -> InPlaceImplGenerics<'a> {
InPlaceImplGenerics(self.0)
}
}
struct DeTypeGenerics<'a>(&'a Parameters);
#[cfg(feature = "deserialize_in_place")]
struct InPlaceTypeGenerics<'a>(&'a Parameters);
fn de_type_generics_to_tokens(
mut generics: syn::Generics,
borrowed: &BorrowedLifetimes,
tokens: &mut TokenStream,
) {
if borrowed.de_lifetime_param().is_some() {
let def = syn::LifetimeParam {
attrs: Vec::new(),
lifetime: syn::Lifetime::new("'de", Span::call_site()),
colon_token: None,
bounds: Punctuated::new(),
};
// Prepend 'de lifetime to list of generics
generics.params = Some(syn::GenericParam::Lifetime(def))
.into_iter()
.chain(generics.params)
.collect();
}
let (_, ty_generics, _) = generics.split_for_impl();
ty_generics.to_tokens(tokens);
}
impl<'a> ToTokens for DeTypeGenerics<'a> {
fn to_tokens(&self, tokens: &mut TokenStream) {
de_type_generics_to_tokens(self.0.generics.clone(), &self.0.borrowed, tokens);
}
}
#[cfg(feature = "deserialize_in_place")]
impl<'a> ToTokens for InPlaceTypeGenerics<'a> {
fn to_tokens(&self, tokens: &mut TokenStream) {
let mut generics = self.0.generics.clone();
generics.params = Some(syn::GenericParam::Lifetime(place_lifetime()))
.into_iter()
.chain(generics.params)
.collect();
de_type_generics_to_tokens(generics, &self.0.borrowed, tokens);
}
}
#[cfg(feature = "deserialize_in_place")]
impl<'a> DeTypeGenerics<'a> {
fn in_place(self) -> InPlaceTypeGenerics<'a> {
InPlaceTypeGenerics(self.0)
}
}
#[cfg(feature = "deserialize_in_place")]
fn place_lifetime() -> syn::LifetimeParam {
syn::LifetimeParam {
attrs: Vec::new(),
lifetime: syn::Lifetime::new("'place", Span::call_site()),
colon_token: None,
bounds: Punctuated::new(),
}
}

96
vendor/serde_derive/src/de/enum_.rs vendored Normal file
View File

@@ -0,0 +1,96 @@
use crate::de::enum_adjacently;
use crate::de::enum_externally;
use crate::de::enum_internally;
use crate::de::enum_untagged;
use crate::de::identifier;
use crate::de::{field_i, FieldWithAliases, Parameters};
use crate::fragment::{Expr, Fragment, Stmts};
use crate::internals::ast::Variant;
use crate::internals::attr;
use crate::private;
use proc_macro2::TokenStream;
use quote::quote;
/// Generates `Deserialize::deserialize` body for an `enum Enum {...}`
pub(super) fn deserialize(
params: &Parameters,
variants: &[Variant],
cattrs: &attr::Container,
) -> Fragment {
// The variants have already been checked (in ast.rs) that all untagged variants appear at the end
match variants.iter().position(|var| var.attrs.untagged()) {
Some(variant_idx) => {
let (tagged, untagged) = variants.split_at(variant_idx);
let tagged_frag = Expr(deserialize_homogeneous_enum(params, tagged, cattrs));
// Ignore any error associated with non-untagged deserialization so that we
// can fall through to the untagged variants. This may be infallible so we
// need to provide the error type.
let first_attempt = quote! {
if let _serde::#private::Result::<_, __D::Error>::Ok(__ok) = (|| #tagged_frag)() {
return _serde::#private::Ok(__ok);
}
};
enum_untagged::deserialize(params, untagged, cattrs, Some(first_attempt))
}
None => deserialize_homogeneous_enum(params, variants, cattrs),
}
}
fn deserialize_homogeneous_enum(
params: &Parameters,
variants: &[Variant],
cattrs: &attr::Container,
) -> Fragment {
match cattrs.tag() {
attr::TagType::External => enum_externally::deserialize(params, variants, cattrs),
attr::TagType::Internal { tag } => {
enum_internally::deserialize(params, variants, cattrs, tag)
}
attr::TagType::Adjacent { tag, content } => {
enum_adjacently::deserialize(params, variants, cattrs, tag, content)
}
attr::TagType::None => enum_untagged::deserialize(params, variants, cattrs, None),
}
}
pub fn prepare_enum_variant_enum(variants: &[Variant]) -> (TokenStream, Stmts) {
let deserialized_variants = variants
.iter()
.enumerate()
.filter(|&(_i, variant)| !variant.attrs.skip_deserializing());
let fallthrough = deserialized_variants
.clone()
.find(|(_i, variant)| variant.attrs.other())
.map(|(i, _variant)| {
let ignore_variant = field_i(i);
quote!(_serde::#private::Ok(__Field::#ignore_variant))
});
let variants_stmt = {
let variant_names = deserialized_variants
.clone()
.flat_map(|(_i, variant)| variant.attrs.aliases());
quote! {
#[doc(hidden)]
const VARIANTS: &'static [&'static str] = &[ #(#variant_names),* ];
}
};
let deserialized_variants: Vec<_> = deserialized_variants
.map(|(i, variant)| FieldWithAliases {
ident: field_i(i),
aliases: variant.attrs.aliases(),
})
.collect();
let variant_visitor = Stmts(identifier::deserialize_generated(
&deserialized_variants,
false, // variant identifiers do not depend on the presence of flatten fields
true,
None,
fallthrough,
));
(variants_stmt, variant_visitor)
}

View File

@@ -0,0 +1,323 @@
//! Deserialization for adjacently tagged enums:
//!
//! ```ignore
//! #[serde(tag = "...", content = "...")]
//! enum Enum {}
//! ```
use crate::de::enum_;
use crate::de::enum_untagged;
use crate::de::{field_i, Parameters};
use crate::fragment::{Fragment, Match};
use crate::internals::ast::{Style, Variant};
use crate::internals::attr;
use crate::private;
use quote::{quote, quote_spanned};
use syn::spanned::Spanned;
/// Generates `Deserialize::deserialize` body for an `enum Enum {...}` with `#[serde(tag, content)]` attributes
pub(super) fn deserialize(
params: &Parameters,
variants: &[Variant],
cattrs: &attr::Container,
tag: &str,
content: &str,
) -> Fragment {
let this_type = &params.this_type;
let this_value = &params.this_value;
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
params.generics_with_de_lifetime();
let delife = params.borrowed.de_lifetime();
let (variants_stmt, variant_visitor) = enum_::prepare_enum_variant_enum(variants);
let variant_arms: &Vec<_> = &variants
.iter()
.enumerate()
.filter(|&(_, variant)| !variant.attrs.skip_deserializing())
.map(|(i, variant)| {
let variant_index = field_i(i);
let block = Match(enum_untagged::deserialize_variant(params, variant, cattrs));
quote! {
__Field::#variant_index => #block
}
})
.collect();
let rust_name = params.type_name();
let expecting = format!("adjacently tagged enum {}", rust_name);
let expecting = cattrs.expecting().unwrap_or(&expecting);
let type_name = cattrs.name().deserialize_name();
let deny_unknown_fields = cattrs.deny_unknown_fields();
// If unknown fields are allowed, we pick the visitor that can step over
// those. Otherwise we pick the visitor that fails on unknown keys.
let field_visitor_ty = if deny_unknown_fields {
quote! { _serde::#private::de::TagOrContentFieldVisitor }
} else {
quote! { _serde::#private::de::TagContentOtherFieldVisitor }
};
let mut missing_content = quote! {
_serde::#private::Err(<__A::Error as _serde::de::Error>::missing_field(#content))
};
let mut missing_content_fallthrough = quote!();
let missing_content_arms = variants
.iter()
.enumerate()
.filter(|&(_, variant)| !variant.attrs.skip_deserializing())
.filter_map(|(i, variant)| {
let variant_index = field_i(i);
let variant_ident = &variant.ident;
let arm = match variant.style {
Style::Unit => quote! {
_serde::#private::Ok(#this_value::#variant_ident)
},
Style::Newtype if variant.attrs.deserialize_with().is_none() => {
let span = variant.original.span();
let func = quote_spanned!(span=> _serde::#private::de::missing_field);
quote! {
#func(#content).map(#this_value::#variant_ident)
}
}
_ => {
missing_content_fallthrough = quote!(_ => #missing_content);
return None;
}
};
Some(quote! {
__Field::#variant_index => #arm,
})
})
.collect::<Vec<_>>();
if !missing_content_arms.is_empty() {
missing_content = quote! {
match __field {
#(#missing_content_arms)*
#missing_content_fallthrough
}
};
}
// Advance the map by one key, returning early in case of error.
let next_key = quote! {
_serde::de::MapAccess::next_key_seed(&mut __map, #field_visitor_ty {
tag: #tag,
content: #content,
})?
};
let variant_from_map = quote! {
_serde::de::MapAccess::next_value_seed(&mut __map, _serde::#private::de::AdjacentlyTaggedEnumVariantSeed::<__Field> {
enum_name: #rust_name,
variants: VARIANTS,
fields_enum: _serde::#private::PhantomData
})?
};
// When allowing unknown fields, we want to transparently step through keys
// we don't care about until we find `tag`, `content`, or run out of keys.
let next_relevant_key = if deny_unknown_fields {
next_key
} else {
quote!({
let mut __rk : _serde::#private::Option<_serde::#private::de::TagOrContentField> = _serde::#private::None;
while let _serde::#private::Some(__k) = #next_key {
match __k {
_serde::#private::de::TagContentOtherField::Other => {
let _ = _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
continue;
},
_serde::#private::de::TagContentOtherField::Tag => {
__rk = _serde::#private::Some(_serde::#private::de::TagOrContentField::Tag);
break;
}
_serde::#private::de::TagContentOtherField::Content => {
__rk = _serde::#private::Some(_serde::#private::de::TagOrContentField::Content);
break;
}
}
}
__rk
})
};
// Step through remaining keys, looking for duplicates of previously-seen
// keys. When unknown fields are denied, any key that isn't a duplicate will
// at this point immediately produce an error.
let visit_remaining_keys = quote! {
match #next_relevant_key {
_serde::#private::Some(_serde::#private::de::TagOrContentField::Tag) => {
_serde::#private::Err(<__A::Error as _serde::de::Error>::duplicate_field(#tag))
}
_serde::#private::Some(_serde::#private::de::TagOrContentField::Content) => {
_serde::#private::Err(<__A::Error as _serde::de::Error>::duplicate_field(#content))
}
_serde::#private::None => _serde::#private::Ok(__ret),
}
};
let finish_content_then_tag = if variant_arms.is_empty() {
quote! {
match #variant_from_map {}
}
} else {
quote! {
let __seed = __Seed {
variant: #variant_from_map,
marker: _serde::#private::PhantomData,
lifetime: _serde::#private::PhantomData,
};
let __deserializer = _serde::#private::de::ContentDeserializer::<__A::Error>::new(__content);
let __ret = _serde::de::DeserializeSeed::deserialize(__seed, __deserializer)?;
// Visit remaining keys, looking for duplicates.
#visit_remaining_keys
}
};
quote_block! {
#variant_visitor
#variants_stmt
#[doc(hidden)]
struct __Seed #de_impl_generics #where_clause {
variant: __Field,
marker: _serde::#private::PhantomData<#this_type #ty_generics>,
lifetime: _serde::#private::PhantomData<&#delife ()>,
}
#[automatically_derived]
impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Seed #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>,
{
match self.variant {
#(#variant_arms)*
}
}
}
#[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)
}
fn visit_map<__A>(self, mut __map: __A) -> _serde::#private::Result<Self::Value, __A::Error>
where
__A: _serde::de::MapAccess<#delife>,
{
// Visit the first relevant key.
match #next_relevant_key {
// First key is the tag.
_serde::#private::Some(_serde::#private::de::TagOrContentField::Tag) => {
// Parse the tag.
let __field = #variant_from_map;
// Visit the second key.
match #next_relevant_key {
// Second key is a duplicate of the tag.
_serde::#private::Some(_serde::#private::de::TagOrContentField::Tag) => {
_serde::#private::Err(<__A::Error as _serde::de::Error>::duplicate_field(#tag))
}
// Second key is the content.
_serde::#private::Some(_serde::#private::de::TagOrContentField::Content) => {
let __ret = _serde::de::MapAccess::next_value_seed(&mut __map,
__Seed {
variant: __field,
marker: _serde::#private::PhantomData,
lifetime: _serde::#private::PhantomData,
})?;
// Visit remaining keys, looking for duplicates.
#visit_remaining_keys
}
// There is no second key; might be okay if the we have a unit variant.
_serde::#private::None => #missing_content
}
}
// First key is the content.
_serde::#private::Some(_serde::#private::de::TagOrContentField::Content) => {
// Buffer up the content.
let __content = _serde::de::MapAccess::next_value_seed(&mut __map, _serde::#private::de::ContentVisitor::new())?;
// Visit the second key.
match #next_relevant_key {
// Second key is the tag.
_serde::#private::Some(_serde::#private::de::TagOrContentField::Tag) => {
#finish_content_then_tag
}
// Second key is a duplicate of the content.
_serde::#private::Some(_serde::#private::de::TagOrContentField::Content) => {
_serde::#private::Err(<__A::Error as _serde::de::Error>::duplicate_field(#content))
}
// There is no second key.
_serde::#private::None => {
_serde::#private::Err(<__A::Error as _serde::de::Error>::missing_field(#tag))
}
}
}
// There is no first key.
_serde::#private::None => {
_serde::#private::Err(<__A::Error as _serde::de::Error>::missing_field(#tag))
}
}
}
fn visit_seq<__A>(self, mut __seq: __A) -> _serde::#private::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<#delife>,
{
// Visit the first element - the tag.
match _serde::de::SeqAccess::next_element(&mut __seq)? {
_serde::#private::Some(__variant) => {
// Visit the second element - the content.
match _serde::de::SeqAccess::next_element_seed(
&mut __seq,
__Seed {
variant: __variant,
marker: _serde::#private::PhantomData,
lifetime: _serde::#private::PhantomData,
},
)? {
_serde::#private::Some(__ret) => _serde::#private::Ok(__ret),
// There is no second element.
_serde::#private::None => {
_serde::#private::Err(_serde::de::Error::invalid_length(1, &self))
}
}
}
// There is no first element.
_serde::#private::None => {
_serde::#private::Err(_serde::de::Error::invalid_length(0, &self))
}
}
}
}
#[doc(hidden)]
const FIELDS: &'static [&'static str] = &[#tag, #content];
_serde::Deserializer::deserialize_struct(
__deserializer,
#type_name,
FIELDS,
__Visitor {
marker: _serde::#private::PhantomData::<#this_type #ty_generics>,
lifetime: _serde::#private::PhantomData,
},
)
}
}

View File

@@ -0,0 +1,212 @@
//! Deserialization for externally tagged enums:
//!
//! ```ignore
//! enum Enum {}
//! ```
use crate::de::enum_;
use crate::de::struct_;
use crate::de::tuple;
use crate::de::{
expr_is_missing, field_i, unwrap_to_variant_closure, wrap_deserialize_field_with,
wrap_deserialize_with, Parameters, StructForm, TupleForm,
};
use crate::fragment::{Expr, Fragment, Match};
use crate::internals::ast::{Field, Style, Variant};
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 an `enum Enum {...}` without additional attributes
pub(super) fn deserialize(
params: &Parameters,
variants: &[Variant],
cattrs: &attr::Container,
) -> Fragment {
let this_type = &params.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 type_name = cattrs.name().deserialize_name();
let expecting = format!("enum {}", params.type_name());
let expecting = cattrs.expecting().unwrap_or(&expecting);
let (variants_stmt, variant_visitor) = enum_::prepare_enum_variant_enum(variants);
// Match arms to extract a variant from a string
let variant_arms = variants
.iter()
.enumerate()
.filter(|&(_, variant)| !variant.attrs.skip_deserializing())
.map(|(i, variant)| {
let variant_name = field_i(i);
let block = Match(deserialize_externally_tagged_variant(
params, variant, cattrs,
));
quote! {
(__Field::#variant_name, __variant) => #block
}
});
let all_skipped = variants
.iter()
.all(|variant| variant.attrs.skip_deserializing());
let match_variant = if all_skipped {
// This is an empty enum like `enum Impossible {}` or an enum in which
// all variants have `#[serde(skip_deserializing)]`.
quote! {
// FIXME: Once feature(exhaustive_patterns) is stable:
// let _serde::#private::Err(__err) = _serde::de::EnumAccess::variant::<__Field>(__data);
// _serde::#private::Err(__err)
_serde::#private::Result::map(
_serde::de::EnumAccess::variant::<__Field>(__data),
|(__impossible, _)| match __impossible {})
}
} else {
quote! {
match _serde::de::EnumAccess::variant(__data)? {
#(#variant_arms)*
}
}
};
quote_block! {
#variant_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)
}
fn visit_enum<__A>(self, __data: __A) -> _serde::#private::Result<Self::Value, __A::Error>
where
__A: _serde::de::EnumAccess<#delife>,
{
#match_variant
}
}
#variants_stmt
_serde::Deserializer::deserialize_enum(
__deserializer,
#type_name,
VARIANTS,
__Visitor {
marker: _serde::#private::PhantomData::<#this_type #ty_generics>,
lifetime: _serde::#private::PhantomData,
},
)
}
}
fn deserialize_externally_tagged_variant(
params: &Parameters,
variant: &Variant,
cattrs: &attr::Container,
) -> Fragment {
if let Some(path) = variant.attrs.deserialize_with() {
let (wrapper, wrapper_ty, unwrap_fn) = wrap_deserialize_variant_with(params, variant, path);
return quote_block! {
#wrapper
_serde::#private::Result::map(
_serde::de::VariantAccess::newtype_variant::<#wrapper_ty>(__variant), #unwrap_fn)
};
}
let variant_ident = &variant.ident;
match variant.style {
Style::Unit => {
let this_value = &params.this_value;
quote_block! {
_serde::de::VariantAccess::unit_variant(__variant)?;
_serde::#private::Ok(#this_value::#variant_ident)
}
}
Style::Newtype => deserialize_externally_tagged_newtype_variant(
variant_ident,
params,
&variant.fields[0],
cattrs,
),
Style::Tuple => tuple::deserialize(
params,
&variant.fields,
cattrs,
TupleForm::ExternallyTagged(variant_ident),
),
Style::Struct => struct_::deserialize(
params,
&variant.fields,
cattrs,
StructForm::ExternallyTagged(variant_ident),
),
}
}
fn wrap_deserialize_variant_with(
params: &Parameters,
variant: &Variant,
deserialize_with: &syn::ExprPath,
) -> (TokenStream, TokenStream, TokenStream) {
let field_tys = variant.fields.iter().map(|field| field.ty);
let (wrapper, wrapper_ty) =
wrap_deserialize_with(params, &quote!((#(#field_tys),*)), deserialize_with);
let unwrap_fn = unwrap_to_variant_closure(params, variant, true);
(wrapper, wrapper_ty, unwrap_fn)
}
fn deserialize_externally_tagged_newtype_variant(
variant_ident: &syn::Ident,
params: &Parameters,
field: &Field,
cattrs: &attr::Container,
) -> Fragment {
let this_value = &params.this_value;
if field.attrs.skip_deserializing() {
let default = Expr(expr_is_missing(field, cattrs));
return quote_block! {
_serde::de::VariantAccess::unit_variant(__variant)?;
_serde::#private::Ok(#this_value::#variant_ident(#default))
};
}
match field.attrs.deserialize_with() {
None => {
let field_ty = field.ty;
let span = field.original.span();
let func =
quote_spanned!(span=> _serde::de::VariantAccess::newtype_variant::<#field_ty>);
quote_expr! {
_serde::#private::Result::map(#func(__variant), #this_value::#variant_ident)
}
}
Some(path) => {
let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path);
quote_block! {
#wrapper
_serde::#private::Result::map(
_serde::de::VariantAccess::newtype_variant::<#wrapper_ty>(__variant),
|__wrapper| #this_value::#variant_ident(__wrapper.value))
}
}
}
}

View File

@@ -0,0 +1,106 @@
//! Deserialization for internally tagged enums:
//!
//! ```ignore
//! #[serde(tag = "...")]
//! enum Enum {}
//! ```
use crate::de::enum_;
use crate::de::enum_untagged;
use crate::de::struct_;
use crate::de::{
effective_style, expr_is_missing, field_i, unwrap_to_variant_closure, Parameters, StructForm,
};
use crate::fragment::{Expr, Fragment, Match};
use crate::internals::ast::{Style, Variant};
use crate::internals::attr;
use crate::private;
use quote::quote;
/// Generates `Deserialize::deserialize` body for an `enum Enum {...}` with `#[serde(tag)]` attribute
pub(super) fn deserialize(
params: &Parameters,
variants: &[Variant],
cattrs: &attr::Container,
tag: &str,
) -> Fragment {
let (variants_stmt, variant_visitor) = enum_::prepare_enum_variant_enum(variants);
// Match arms to extract a variant from a string
let variant_arms = variants
.iter()
.enumerate()
.filter(|&(_, variant)| !variant.attrs.skip_deserializing())
.map(|(i, variant)| {
let variant_name = field_i(i);
let block = Match(deserialize_internally_tagged_variant(
params, variant, cattrs,
));
quote! {
__Field::#variant_name => #block
}
});
let expecting = format!("internally tagged enum {}", params.type_name());
let expecting = cattrs.expecting().unwrap_or(&expecting);
quote_block! {
#variant_visitor
#variants_stmt
let (__tag, __content) = _serde::Deserializer::deserialize_any(
__deserializer,
_serde::#private::de::TaggedContentVisitor::<__Field>::new(#tag, #expecting))?;
let __deserializer = _serde::#private::de::ContentDeserializer::<__D::Error>::new(__content);
match __tag {
#(#variant_arms)*
}
}
}
// Generates significant part of the visit_seq and visit_map bodies of visitors
// for the variants of internally tagged enum.
fn deserialize_internally_tagged_variant(
params: &Parameters,
variant: &Variant,
cattrs: &attr::Container,
) -> Fragment {
if let Some(path) = variant.attrs.deserialize_with() {
let unwrap_fn = unwrap_to_variant_closure(params, variant, false);
return quote_block! {
_serde::#private::Result::map(#path(__deserializer), #unwrap_fn)
};
}
let variant_ident = &variant.ident;
match effective_style(variant) {
Style::Unit => {
let this_value = &params.this_value;
let type_name = params.type_name();
let variant_name = variant.ident.to_string();
let default = variant.fields.first().map(|field| {
let default = Expr(expr_is_missing(field, cattrs));
quote!((#default))
});
quote_block! {
_serde::Deserializer::deserialize_any(__deserializer, _serde::#private::de::InternallyTaggedUnitVisitor::new(#type_name, #variant_name))?;
_serde::#private::Ok(#this_value::#variant_ident #default)
}
}
Style::Newtype => {
enum_untagged::deserialize_newtype_variant(variant_ident, params, &variant.fields[0])
}
Style::Struct => struct_::deserialize(
params,
&variant.fields,
cattrs,
StructForm::InternallyTagged(variant_ident),
),
Style::Tuple => unreachable!("checked in serde_derive_internals"),
}
}

View File

@@ -0,0 +1,135 @@
//! Deserialization for untagged enums:
//!
//! ```ignore
//! #[serde(untagged)]
//! enum Enum {}
//! ```
use crate::de::struct_;
use crate::de::tuple;
use crate::de::{
effective_style, expr_is_missing, unwrap_to_variant_closure, Parameters, StructForm, TupleForm,
};
use crate::fragment::{Expr, Fragment};
use crate::internals::ast::{Field, Style, Variant};
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 an `enum Enum {...}` with `#[serde(untagged)]` attribute
pub(super) fn deserialize(
params: &Parameters,
variants: &[Variant],
cattrs: &attr::Container,
first_attempt: Option<TokenStream>,
) -> Fragment {
let attempts = variants
.iter()
.filter(|variant| !variant.attrs.skip_deserializing())
.map(|variant| Expr(deserialize_variant(params, variant, cattrs)));
// TODO this message could be better by saving the errors from the failed
// attempts. The heuristic used by TOML was to count the number of fields
// processed before an error, and use the error that happened after the
// largest number of fields. I'm not sure I like that. Maybe it would be
// better to save all the errors and combine them into one message that
// explains why none of the variants matched.
let fallthrough_msg = format!(
"data did not match any variant of untagged enum {}",
params.type_name()
);
let fallthrough_msg = cattrs.expecting().unwrap_or(&fallthrough_msg);
let private2 = private;
quote_block! {
let __content = _serde::de::DeserializeSeed::deserialize(_serde::#private::de::ContentVisitor::new(), __deserializer)?;
let __deserializer = _serde::#private::de::ContentRefDeserializer::<__D::Error>::new(&__content);
#first_attempt
#(
if let _serde::#private2::Ok(__ok) = #attempts {
return _serde::#private2::Ok(__ok);
}
)*
_serde::#private::Err(_serde::de::Error::custom(#fallthrough_msg))
}
}
// Also used by adjacently tagged enums
pub(super) fn deserialize_variant(
params: &Parameters,
variant: &Variant,
cattrs: &attr::Container,
) -> Fragment {
if let Some(path) = variant.attrs.deserialize_with() {
let unwrap_fn = unwrap_to_variant_closure(params, variant, false);
return quote_block! {
_serde::#private::Result::map(#path(__deserializer), #unwrap_fn)
};
}
let variant_ident = &variant.ident;
match effective_style(variant) {
Style::Unit => {
let this_value = &params.this_value;
let type_name = params.type_name();
let variant_name = variant.ident.to_string();
let default = variant.fields.first().map(|field| {
let default = Expr(expr_is_missing(field, cattrs));
quote!((#default))
});
quote_expr! {
match _serde::Deserializer::deserialize_any(
__deserializer,
_serde::#private::de::UntaggedUnitVisitor::new(#type_name, #variant_name)
) {
_serde::#private::Ok(()) => _serde::#private::Ok(#this_value::#variant_ident #default),
_serde::#private::Err(__err) => _serde::#private::Err(__err),
}
}
}
Style::Newtype => deserialize_newtype_variant(variant_ident, params, &variant.fields[0]),
Style::Tuple => tuple::deserialize(
params,
&variant.fields,
cattrs,
TupleForm::Untagged(variant_ident),
),
Style::Struct => struct_::deserialize(
params,
&variant.fields,
cattrs,
StructForm::Untagged(variant_ident),
),
}
}
// Also used by internally tagged enums
// Implicitly (via `generate_variant`) used by adjacently tagged enums
pub(super) fn deserialize_newtype_variant(
variant_ident: &syn::Ident,
params: &Parameters,
field: &Field,
) -> Fragment {
let this_value = &params.this_value;
let field_ty = field.ty;
match field.attrs.deserialize_with() {
None => {
let span = field.original.span();
let func = quote_spanned!(span=> <#field_ty as _serde::Deserialize>::deserialize);
quote_expr! {
_serde::#private::Result::map(#func(__deserializer), #this_value::#variant_ident)
}
}
Some(path) => {
quote_block! {
let __value: _serde::#private::Result<#field_ty, _> = #path(__deserializer);
_serde::#private::Result::map(__value, #this_value::#variant_ident)
}
}
}
}

477
vendor/serde_derive/src/de/identifier.rs vendored Normal file
View File

@@ -0,0 +1,477 @@
//! Deserialization of struct field identifiers and enum variant identifiers by
//! way of a Rust enum.
use crate::de::{FieldWithAliases, Parameters};
use crate::fragment::{Fragment, Stmts};
use crate::internals::ast::{Style, Variant};
use crate::internals::attr;
use crate::private;
use proc_macro2::{Literal, TokenStream};
use quote::{quote, ToTokens};
// Generates `Deserialize::deserialize` body for an enum with
// `serde(field_identifier)` or `serde(variant_identifier)` attribute.
pub(super) fn deserialize_custom(
params: &Parameters,
variants: &[Variant],
cattrs: &attr::Container,
) -> Fragment {
let is_variant = match cattrs.identifier() {
attr::Identifier::Variant => true,
attr::Identifier::Field => false,
attr::Identifier::No => unreachable!(),
};
let this_type = params.this_type.to_token_stream();
let this_value = params.this_value.to_token_stream();
let (ordinary, fallthrough, fallthrough_borrowed) = if let Some(last) = variants.last() {
let last_ident = &last.ident;
if last.attrs.other() {
// Process `serde(other)` attribute. It would always be found on the
// last variant (checked in `check_identifier`), so all preceding
// are ordinary variants.
let ordinary = &variants[..variants.len() - 1];
let fallthrough = quote!(_serde::#private::Ok(#this_value::#last_ident));
(ordinary, Some(fallthrough), None)
} else if let Style::Newtype = last.style {
let ordinary = &variants[..variants.len() - 1];
let fallthrough = |value| {
quote! {
_serde::#private::Result::map(
_serde::Deserialize::deserialize(
_serde::#private::de::IdentifierDeserializer::from(#value)
),
#this_value::#last_ident)
}
};
(
ordinary,
Some(fallthrough(quote!(__value))),
Some(fallthrough(quote!(_serde::#private::de::Borrowed(
__value
)))),
)
} else {
(variants, None, None)
}
} else {
(variants, None, None)
};
let idents_aliases: Vec<_> = ordinary
.iter()
.map(|variant| FieldWithAliases {
ident: variant.ident.clone(),
aliases: variant.attrs.aliases(),
})
.collect();
let names = idents_aliases.iter().flat_map(|variant| variant.aliases);
let names_const = if fallthrough.is_some() {
None
} else if is_variant {
let variants = quote! {
#[doc(hidden)]
const VARIANTS: &'static [&'static str] = &[ #(#names),* ];
};
Some(variants)
} else {
let fields = quote! {
#[doc(hidden)]
const FIELDS: &'static [&'static str] = &[ #(#names),* ];
};
Some(fields)
};
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
params.generics_with_de_lifetime();
let delife = params.borrowed.de_lifetime();
let visitor_impl = Stmts(deserialize_identifier(
&this_value,
&idents_aliases,
is_variant,
fallthrough,
fallthrough_borrowed,
false,
cattrs.expecting(),
));
quote_block! {
#names_const
#[doc(hidden)]
struct __FieldVisitor #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 __FieldVisitor #de_ty_generics #where_clause {
type Value = #this_type #ty_generics;
#visitor_impl
}
let __visitor = __FieldVisitor {
marker: _serde::#private::PhantomData::<#this_type #ty_generics>,
lifetime: _serde::#private::PhantomData,
};
_serde::Deserializer::deserialize_identifier(__deserializer, __visitor)
}
}
pub(super) fn deserialize_generated(
deserialized_fields: &[FieldWithAliases],
has_flatten: bool,
is_variant: bool,
ignore_variant: Option<TokenStream>,
fallthrough: Option<TokenStream>,
) -> Fragment {
let this_value = quote!(__Field);
let field_idents: &Vec<_> = &deserialized_fields
.iter()
.map(|field| &field.ident)
.collect();
let visitor_impl = Stmts(deserialize_identifier(
&this_value,
deserialized_fields,
is_variant,
fallthrough,
None,
!is_variant && has_flatten,
None,
));
let lifetime = if !is_variant && has_flatten {
Some(quote!(<'de>))
} else {
None
};
quote_block! {
#[allow(non_camel_case_types)]
#[doc(hidden)]
enum __Field #lifetime {
#(#field_idents,)*
#ignore_variant
}
#[doc(hidden)]
struct __FieldVisitor;
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field #lifetime;
#visitor_impl
}
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for __Field #lifetime {
#[inline]
fn deserialize<__D>(__deserializer: __D) -> _serde::#private::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor)
}
}
}
}
fn deserialize_identifier(
this_value: &TokenStream,
deserialized_fields: &[FieldWithAliases],
is_variant: bool,
fallthrough: Option<TokenStream>,
fallthrough_borrowed: Option<TokenStream>,
collect_other_fields: bool,
expecting: Option<&str>,
) -> Fragment {
let str_mapping = deserialized_fields.iter().map(|field| {
let ident = &field.ident;
let aliases = field.aliases;
let private2 = private;
// `aliases` also contains a main name
quote! {
#(
#aliases => _serde::#private2::Ok(#this_value::#ident),
)*
}
});
let bytes_mapping = deserialized_fields.iter().map(|field| {
let ident = &field.ident;
// `aliases` also contains a main name
let aliases = field
.aliases
.iter()
.map(|alias| Literal::byte_string(alias.value.as_bytes()));
let private2 = private;
quote! {
#(
#aliases => _serde::#private2::Ok(#this_value::#ident),
)*
}
});
let expecting = expecting.unwrap_or(if is_variant {
"variant identifier"
} else {
"field identifier"
});
let bytes_to_str = if fallthrough.is_some() || collect_other_fields {
None
} else {
Some(quote! {
let __value = &_serde::#private::from_utf8_lossy(__value);
})
};
let (
value_as_str_content,
value_as_borrowed_str_content,
value_as_bytes_content,
value_as_borrowed_bytes_content,
) = if collect_other_fields {
(
Some(quote! {
let __value = _serde::#private::de::Content::String(_serde::#private::ToString::to_string(__value));
}),
Some(quote! {
let __value = _serde::#private::de::Content::Str(__value);
}),
Some(quote! {
let __value = _serde::#private::de::Content::ByteBuf(__value.to_vec());
}),
Some(quote! {
let __value = _serde::#private::de::Content::Bytes(__value);
}),
)
} else {
(None, None, None, None)
};
let fallthrough_arm_tokens;
let fallthrough_arm = if let Some(fallthrough) = &fallthrough {
fallthrough
} else if is_variant {
fallthrough_arm_tokens = quote! {
_serde::#private::Err(_serde::de::Error::unknown_variant(__value, VARIANTS))
};
&fallthrough_arm_tokens
} else {
fallthrough_arm_tokens = quote! {
_serde::#private::Err(_serde::de::Error::unknown_field(__value, FIELDS))
};
&fallthrough_arm_tokens
};
let visit_other = if collect_other_fields {
quote! {
fn visit_bool<__E>(self, __value: bool) -> _serde::#private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::Bool(__value)))
}
fn visit_i8<__E>(self, __value: i8) -> _serde::#private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::I8(__value)))
}
fn visit_i16<__E>(self, __value: i16) -> _serde::#private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::I16(__value)))
}
fn visit_i32<__E>(self, __value: i32) -> _serde::#private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::I32(__value)))
}
fn visit_i64<__E>(self, __value: i64) -> _serde::#private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::I64(__value)))
}
fn visit_u8<__E>(self, __value: u8) -> _serde::#private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::U8(__value)))
}
fn visit_u16<__E>(self, __value: u16) -> _serde::#private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::U16(__value)))
}
fn visit_u32<__E>(self, __value: u32) -> _serde::#private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::U32(__value)))
}
fn visit_u64<__E>(self, __value: u64) -> _serde::#private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::U64(__value)))
}
fn visit_f32<__E>(self, __value: f32) -> _serde::#private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::F32(__value)))
}
fn visit_f64<__E>(self, __value: f64) -> _serde::#private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::F64(__value)))
}
fn visit_char<__E>(self, __value: char) -> _serde::#private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::Char(__value)))
}
fn visit_unit<__E>(self) -> _serde::#private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::Unit))
}
}
} else {
let u64_mapping = deserialized_fields.iter().enumerate().map(|(i, field)| {
let i = i as u64;
let ident = &field.ident;
quote!(#i => _serde::#private::Ok(#this_value::#ident))
});
let u64_fallthrough_arm_tokens;
let u64_fallthrough_arm = if let Some(fallthrough) = &fallthrough {
fallthrough
} else {
let index_expecting = if is_variant { "variant" } else { "field" };
let fallthrough_msg = format!(
"{} index 0 <= i < {}",
index_expecting,
deserialized_fields.len(),
);
u64_fallthrough_arm_tokens = quote! {
_serde::#private::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&#fallthrough_msg,
))
};
&u64_fallthrough_arm_tokens
};
quote! {
fn visit_u64<__E>(self, __value: u64) -> _serde::#private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
#(#u64_mapping,)*
_ => #u64_fallthrough_arm,
}
}
}
};
let visit_borrowed = if fallthrough_borrowed.is_some() || collect_other_fields {
let str_mapping = str_mapping.clone();
let bytes_mapping = bytes_mapping.clone();
let fallthrough_borrowed_arm = fallthrough_borrowed.as_ref().unwrap_or(fallthrough_arm);
Some(quote! {
fn visit_borrowed_str<__E>(self, __value: &'de str) -> _serde::#private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
#(#str_mapping)*
_ => {
#value_as_borrowed_str_content
#fallthrough_borrowed_arm
}
}
}
fn visit_borrowed_bytes<__E>(self, __value: &'de [u8]) -> _serde::#private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
#(#bytes_mapping)*
_ => {
#bytes_to_str
#value_as_borrowed_bytes_content
#fallthrough_borrowed_arm
}
}
}
})
} else {
None
};
quote_block! {
fn expecting(&self, __formatter: &mut _serde::#private::Formatter) -> _serde::#private::fmt::Result {
_serde::#private::Formatter::write_str(__formatter, #expecting)
}
#visit_other
fn visit_str<__E>(self, __value: &str) -> _serde::#private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
#(#str_mapping)*
_ => {
#value_as_str_content
#fallthrough_arm
}
}
}
fn visit_bytes<__E>(self, __value: &[u8]) -> _serde::#private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
#(#bytes_mapping)*
_ => {
#bytes_to_str
#value_as_bytes_content
#fallthrough_arm
}
}
}
#visit_borrowed
}
}

697
vendor/serde_derive/src/de/struct_.rs vendored Normal file
View File

@@ -0,0 +1,697 @@
use crate::de::identifier;
use crate::de::{
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(super) fn deserialize(
params: &Parameters,
fields: &[Field],
cattrs: &attr::Container,
form: StructForm,
) -> Fragment {
let this_type = &params.this_type;
let this_value = &params.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 = &params.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
}
}
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 = &params.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 = &params.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);
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,
})
})
}
#[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 = &params.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))
} 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(identifier::deserialize_generated(
deserialized_fields,
has_flatten,
false,
ignore_variant,
fallthrough,
))
}

283
vendor/serde_derive/src/de/tuple.rs vendored Normal file
View File

@@ -0,0 +1,283 @@
use crate::de::{deserialize_seq, has_flatten, Parameters, TupleForm};
#[cfg(feature = "deserialize_in_place")]
use crate::de::{deserialize_seq_in_place, place_lifetime};
use crate::fragment::{Fragment, 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 Tuple(...);` including `struct Newtype(T);`
pub(super) fn deserialize(
params: &Parameters,
fields: &[Field],
cattrs: &attr::Container,
form: TupleForm,
) -> Fragment {
assert!(
!has_flatten(fields),
"tuples and tuple variants cannot have flatten fields"
);
let field_count = fields
.iter()
.filter(|field| !field.attrs.skip_deserializing())
.count();
let this_type = &params.this_type;
let this_value = &params.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 = &params.local;
quote!(#local)
} else {
quote!(#this_value)
};
let type_path = match form {
TupleForm::Tuple => construct,
TupleForm::ExternallyTagged(variant_ident) | TupleForm::Untagged(variant_ident) => {
quote!(#construct::#variant_ident)
}
};
let expecting = match form {
TupleForm::Tuple => 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 nfields = fields.len();
let visit_newtype_struct = match form {
TupleForm::Tuple if nfields == 1 => {
Some(deserialize_newtype_struct(&type_path, params, &fields[0]))
}
_ => None,
};
let visit_seq = Stmts(deserialize_seq(
&type_path, params, fields, false, cattrs, expecting,
));
let visitor_expr = quote! {
__Visitor {
marker: _serde::#private::PhantomData::<#this_type #ty_generics>,
lifetime: _serde::#private::PhantomData,
}
};
let dispatch = match form {
TupleForm::Tuple if nfields == 1 => {
let type_name = cattrs.name().deserialize_name();
quote! {
_serde::Deserializer::deserialize_newtype_struct(__deserializer, #type_name, #visitor_expr)
}
}
TupleForm::Tuple => {
let type_name = cattrs.name().deserialize_name();
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(_) => quote! {
_serde::Deserializer::deserialize_tuple(__deserializer, #field_count, #visitor_expr)
},
};
let visitor_var = if field_count == 0 {
quote!(_)
} else {
quote!(mut __seq)
};
quote_block! {
#[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_newtype_struct
#[inline]
fn visit_seq<__A>(self, #visitor_var: __A) -> _serde::#private::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<#delife>,
{
#visit_seq
}
}
#dispatch
}
}
fn deserialize_newtype_struct(
type_path: &TokenStream,
params: &Parameters,
field: &Field,
) -> TokenStream {
let delife = params.borrowed.de_lifetime();
let field_ty = field.ty;
let deserializer_var = quote!(__e);
let value = match field.attrs.deserialize_with() {
None => {
let span = field.original.span();
let func = quote_spanned!(span=> <#field_ty as _serde::Deserialize>::deserialize);
quote! {
#func(#deserializer_var)?
}
}
Some(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(with = "...")]
// ^^^^^
quote_spanned! {path.span()=>
#path(#deserializer_var)?
}
}
};
let mut result = quote!(#type_path(__field0));
if params.has_getter {
let this_type = &params.this_type;
let (_, ty_generics, _) = params.generics.split_for_impl();
result = quote! {
_serde::#private::Into::<#this_type #ty_generics>::into(#result)
};
}
quote! {
#[inline]
fn visit_newtype_struct<__E>(self, #deserializer_var: __E) -> _serde::#private::Result<Self::Value, __E::Error>
where
__E: _serde::Deserializer<#delife>,
{
let __field0: #field_ty = #value;
_serde::#private::Ok(#result)
}
}
}
/// Generates `Deserialize::deserialize_in_place` body for a `struct Tuple(...);` including `struct Newtype(T);`
#[cfg(feature = "deserialize_in_place")]
pub(super) fn deserialize_in_place(
params: &Parameters,
fields: &[Field],
cattrs: &attr::Container,
) -> Fragment {
assert!(
!has_flatten(fields),
"tuples and tuple variants cannot have flatten fields"
);
let field_count = fields
.iter()
.filter(|field| !field.attrs.skip_deserializing())
.count();
let this_type = &params.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!("tuple struct {}", params.type_name());
let expecting = cattrs.expecting().unwrap_or(&expecting);
let nfields = fields.len();
let visit_newtype_struct = if nfields == 1 {
// We do not generate deserialize_in_place if every field has a
// deserialize_with.
assert!(fields[0].attrs.deserialize_with().is_none());
Some(quote! {
#[inline]
fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::#private::Result<Self::Value, __E::Error>
where
__E: _serde::Deserializer<#delife>,
{
_serde::Deserialize::deserialize_in_place(__e, &mut self.place.0)
}
})
} else {
None
};
let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, expecting));
let visitor_expr = quote! {
__Visitor {
place: __place,
lifetime: _serde::#private::PhantomData,
}
};
let type_name = cattrs.name().deserialize_name();
let dispatch = if nfields == 1 {
quote!(_serde::Deserializer::deserialize_newtype_struct(__deserializer, #type_name, #visitor_expr))
} else {
quote!(_serde::Deserializer::deserialize_tuple_struct(__deserializer, #type_name, #field_count, #visitor_expr))
};
let visitor_var = if field_count == 0 {
quote!(_)
} else {
quote!(mut __seq)
};
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();
quote_block! {
#[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)
}
#visit_newtype_struct
#[inline]
fn visit_seq<__A>(self, #visitor_var: __A) -> _serde::#private::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<#delife>,
{
#visit_seq
}
}
#dispatch
}
}

52
vendor/serde_derive/src/de/unit.rs vendored Normal file
View File

@@ -0,0 +1,52 @@
use crate::de::Parameters;
use crate::fragment::Fragment;
use crate::internals::attr;
use crate::private;
use quote::quote;
/// Generates `Deserialize::deserialize` body for a `struct Unit;`
pub(super) fn deserialize(params: &Parameters, cattrs: &attr::Container) -> Fragment {
let this_type = &params.this_type;
let this_value = &params.this_value;
let type_name = cattrs.name().deserialize_name();
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!("unit struct {}", params.type_name());
let expecting = cattrs.expecting().unwrap_or(&expecting);
quote_block! {
#[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)
}
#[inline]
fn visit_unit<__E>(self) -> _serde::#private::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
_serde::#private::Ok(#this_value)
}
}
_serde::Deserializer::deserialize_unit_struct(
__deserializer,
#type_name,
__Visitor {
marker: _serde::#private::PhantomData::<#this_type #ty_generics>,
lifetime: _serde::#private::PhantomData,
},
)
}
}

56
vendor/serde_derive/src/deprecated.rs vendored Normal file
View File

@@ -0,0 +1,56 @@
use proc_macro2::TokenStream;
use quote::quote;
pub fn allow_deprecated(input: &syn::DeriveInput) -> Option<TokenStream> {
if should_allow_deprecated(input) {
Some(quote! { #[allow(deprecated)] })
} else {
None
}
}
/// Determine if an `#[allow(deprecated)]` should be added to the derived impl.
///
/// This should happen if the derive input or an enum variant it contains has
/// one of:
/// - `#[deprecated]`
/// - `#[allow(deprecated)]`
fn should_allow_deprecated(input: &syn::DeriveInput) -> bool {
if contains_deprecated(&input.attrs) {
return true;
}
if let syn::Data::Enum(data_enum) = &input.data {
for variant in &data_enum.variants {
if contains_deprecated(&variant.attrs) {
return true;
}
}
}
false
}
/// Check whether the given attributes contains one of:
/// - `#[deprecated]`
/// - `#[allow(deprecated)]`
fn contains_deprecated(attrs: &[syn::Attribute]) -> bool {
for attr in attrs {
if attr.path().is_ident("deprecated") {
return true;
}
if let syn::Meta::List(meta_list) = &attr.meta {
if meta_list.path.is_ident("allow") {
let mut allow_deprecated = false;
let _ = meta_list.parse_nested_meta(|meta| {
if meta.path.is_ident("deprecated") {
allow_deprecated = true;
}
Ok(())
});
if allow_deprecated {
return true;
}
}
}
}
false
}

31
vendor/serde_derive/src/dummy.rs vendored Normal file
View File

@@ -0,0 +1,31 @@
use proc_macro2::TokenStream;
use quote::quote;
pub fn wrap_in_const(serde_path: Option<&syn::Path>, code: TokenStream) -> TokenStream {
let use_serde = match serde_path {
Some(path) => quote! {
use #path as _serde;
},
None => quote! {
#[allow(unused_extern_crates, clippy::useless_attribute)]
extern crate serde as _serde;
},
};
quote! {
#[doc(hidden)]
#[allow(
non_upper_case_globals,
unused_attributes,
unused_qualifications,
clippy::absolute_paths,
)]
const _: () = {
#use_serde
_serde::__require_serde_not_serde_core!();
#code
};
}
}

74
vendor/serde_derive/src/fragment.rs vendored Normal file
View File

@@ -0,0 +1,74 @@
use proc_macro2::TokenStream;
use quote::ToTokens;
use syn::{token, Token};
pub enum Fragment {
/// Tokens that can be used as an expression.
Expr(TokenStream),
/// Tokens that can be used inside a block. The surrounding curly braces are
/// not part of these tokens.
Block(TokenStream),
}
macro_rules! quote_expr {
($($tt:tt)*) => {
$crate::fragment::Fragment::Expr(quote!($($tt)*))
}
}
macro_rules! quote_block {
($($tt:tt)*) => {
$crate::fragment::Fragment::Block(quote!($($tt)*))
}
}
/// Interpolate a fragment in place of an expression. This involves surrounding
/// Block fragments in curly braces.
pub struct Expr(pub Fragment);
impl ToTokens for Expr {
fn to_tokens(&self, out: &mut TokenStream) {
match &self.0 {
Fragment::Expr(expr) => expr.to_tokens(out),
Fragment::Block(block) => {
token::Brace::default().surround(out, |out| block.to_tokens(out));
}
}
}
}
/// Interpolate a fragment as the statements of a block.
pub struct Stmts(pub Fragment);
impl ToTokens for Stmts {
fn to_tokens(&self, out: &mut TokenStream) {
match &self.0 {
Fragment::Expr(expr) => expr.to_tokens(out),
Fragment::Block(block) => block.to_tokens(out),
}
}
}
/// Interpolate a fragment as the value part of a `match` expression. This
/// involves putting a comma after expressions and curly braces around blocks.
pub struct Match(pub Fragment);
impl ToTokens for Match {
fn to_tokens(&self, out: &mut TokenStream) {
match &self.0 {
Fragment::Expr(expr) => {
expr.to_tokens(out);
<Token![,]>::default().to_tokens(out);
}
Fragment::Block(block) => {
token::Brace::default().surround(out, |out| block.to_tokens(out));
}
}
}
}
impl AsRef<TokenStream> for Fragment {
fn as_ref(&self) -> &TokenStream {
match self {
Fragment::Expr(expr) => expr,
Fragment::Block(block) => block,
}
}
}

218
vendor/serde_derive/src/internals/ast.rs vendored Normal file
View File

@@ -0,0 +1,218 @@
//! A Serde ast, parsed from the Syn ast and ready to generate Rust code.
use crate::internals::{attr, check, Ctxt, Derive};
use proc_macro2::Ident;
use syn::punctuated::Punctuated;
use syn::Token;
/// A source data structure annotated with `#[derive(Serialize)]` and/or `#[derive(Deserialize)]`,
/// parsed into an internal representation.
pub struct Container<'a> {
/// The struct or enum name (without generics).
pub ident: syn::Ident,
/// Attributes on the structure, parsed for Serde.
pub attrs: attr::Container,
/// The contents of the struct or enum.
pub data: Data<'a>,
/// Any generics on the struct or enum.
pub generics: &'a syn::Generics,
/// Original input.
pub original: &'a syn::DeriveInput,
}
/// The fields of a struct or enum.
///
/// Analogous to `syn::Data`.
pub enum Data<'a> {
Enum(Vec<Variant<'a>>),
Struct(Style, Vec<Field<'a>>),
}
/// A variant of an enum.
pub struct Variant<'a> {
pub ident: syn::Ident,
pub attrs: attr::Variant,
pub style: Style,
pub fields: Vec<Field<'a>>,
pub original: &'a syn::Variant,
}
/// A field of a struct.
pub struct Field<'a> {
pub member: syn::Member,
pub attrs: attr::Field,
pub ty: &'a syn::Type,
pub original: &'a syn::Field,
}
#[derive(Copy, Clone)]
pub enum Style {
/// Named fields.
Struct,
/// Many unnamed fields.
Tuple,
/// One unnamed field.
Newtype,
/// No fields.
Unit,
}
impl<'a> Container<'a> {
/// Convert the raw Syn ast into a parsed container object, collecting errors in `cx`.
pub fn from_ast(
cx: &Ctxt,
item: &'a syn::DeriveInput,
derive: Derive,
private: &Ident,
) -> Option<Container<'a>> {
let attrs = attr::Container::from_ast(cx, item);
let mut data = match &item.data {
syn::Data::Enum(data) => {
Data::Enum(enum_from_ast(cx, &data.variants, attrs.default(), private))
}
syn::Data::Struct(data) => {
let (style, fields) =
struct_from_ast(cx, &data.fields, None, attrs.default(), private);
Data::Struct(style, fields)
}
syn::Data::Union(_) => {
cx.error_spanned_by(item, "Serde does not support derive for unions");
return None;
}
};
match &mut data {
Data::Enum(variants) => {
for variant in variants {
variant.attrs.rename_by_rules(attrs.rename_all_rules());
for field in &mut variant.fields {
field.attrs.rename_by_rules(
variant
.attrs
.rename_all_rules()
.or(attrs.rename_all_fields_rules()),
);
}
}
}
Data::Struct(_, fields) => {
for field in fields {
field.attrs.rename_by_rules(attrs.rename_all_rules());
}
}
}
let mut item = Container {
ident: item.ident.clone(),
attrs,
data,
generics: &item.generics,
original: item,
};
check::check(cx, &mut item, derive);
Some(item)
}
}
impl<'a> Data<'a> {
pub fn all_fields(&'a self) -> Box<dyn Iterator<Item = &'a Field<'a>> + 'a> {
match self {
Data::Enum(variants) => {
Box::new(variants.iter().flat_map(|variant| variant.fields.iter()))
}
Data::Struct(_, fields) => Box::new(fields.iter()),
}
}
pub fn has_getter(&self) -> bool {
self.all_fields().any(|f| f.attrs.getter().is_some())
}
}
fn enum_from_ast<'a>(
cx: &Ctxt,
variants: &'a Punctuated<syn::Variant, Token![,]>,
container_default: &attr::Default,
private: &Ident,
) -> Vec<Variant<'a>> {
let variants: Vec<Variant> = variants
.iter()
.map(|variant| {
let attrs = attr::Variant::from_ast(cx, variant);
let (style, fields) = struct_from_ast(
cx,
&variant.fields,
Some(&attrs),
container_default,
private,
);
Variant {
ident: variant.ident.clone(),
attrs,
style,
fields,
original: variant,
}
})
.collect();
let index_of_last_tagged_variant = variants
.iter()
.rposition(|variant| !variant.attrs.untagged());
if let Some(index_of_last_tagged_variant) = index_of_last_tagged_variant {
for variant in &variants[..index_of_last_tagged_variant] {
if variant.attrs.untagged() {
cx.error_spanned_by(&variant.ident, "all variants with the #[serde(untagged)] attribute must be placed at the end of the enum");
}
}
}
variants
}
fn struct_from_ast<'a>(
cx: &Ctxt,
fields: &'a syn::Fields,
attrs: Option<&attr::Variant>,
container_default: &attr::Default,
private: &Ident,
) -> (Style, Vec<Field<'a>>) {
match fields {
syn::Fields::Named(fields) => (
Style::Struct,
fields_from_ast(cx, &fields.named, attrs, container_default, private),
),
syn::Fields::Unnamed(fields) if fields.unnamed.len() == 1 => (
Style::Newtype,
fields_from_ast(cx, &fields.unnamed, attrs, container_default, private),
),
syn::Fields::Unnamed(fields) => (
Style::Tuple,
fields_from_ast(cx, &fields.unnamed, attrs, container_default, private),
),
syn::Fields::Unit => (Style::Unit, Vec::new()),
}
}
fn fields_from_ast<'a>(
cx: &Ctxt,
fields: &'a Punctuated<syn::Field, Token![,]>,
attrs: Option<&attr::Variant>,
container_default: &attr::Default,
private: &Ident,
) -> Vec<Field<'a>> {
fields
.iter()
.enumerate()
.map(|(i, field)| Field {
member: match &field.ident {
Some(ident) => syn::Member::Named(ident.clone()),
None => syn::Member::Unnamed(i.into()),
},
attrs: attr::Field::from_ast(cx, i, field, attrs, container_default, private),
ty: &field.ty,
original: field,
})
.collect()
}

1831
vendor/serde_derive/src/internals/attr.rs vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,200 @@
//! Code to convert the Rust-styled field/variant (e.g. `my_field`, `MyType`) to the
//! case of the source (e.g. `my-field`, `MY_FIELD`).
use self::RenameRule::*;
use std::fmt::{self, Debug, Display};
/// The different possible ways to change case of fields in a struct, or variants in an enum.
#[derive(Copy, Clone, PartialEq)]
pub enum RenameRule {
/// Don't apply a default rename rule.
None,
/// Rename direct children to "lowercase" style.
LowerCase,
/// Rename direct children to "UPPERCASE" style.
UpperCase,
/// Rename direct children to "PascalCase" style, as typically used for
/// enum variants.
PascalCase,
/// Rename direct children to "camelCase" style.
CamelCase,
/// Rename direct children to "snake_case" style, as commonly used for
/// fields.
SnakeCase,
/// Rename direct children to "SCREAMING_SNAKE_CASE" style, as commonly
/// used for constants.
ScreamingSnakeCase,
/// Rename direct children to "kebab-case" style.
KebabCase,
/// Rename direct children to "SCREAMING-KEBAB-CASE" style.
ScreamingKebabCase,
}
static RENAME_RULES: &[(&str, RenameRule)] = &[
("lowercase", LowerCase),
("UPPERCASE", UpperCase),
("PascalCase", PascalCase),
("camelCase", CamelCase),
("snake_case", SnakeCase),
("SCREAMING_SNAKE_CASE", ScreamingSnakeCase),
("kebab-case", KebabCase),
("SCREAMING-KEBAB-CASE", ScreamingKebabCase),
];
impl RenameRule {
pub fn from_str(rename_all_str: &str) -> Result<Self, ParseError> {
for (name, rule) in RENAME_RULES {
if rename_all_str == *name {
return Ok(*rule);
}
}
Err(ParseError {
unknown: rename_all_str,
})
}
/// Apply a renaming rule to an enum variant, returning the version expected in the source.
pub fn apply_to_variant(self, variant: &str) -> String {
match self {
None | PascalCase => variant.to_owned(),
LowerCase => variant.to_ascii_lowercase(),
UpperCase => variant.to_ascii_uppercase(),
CamelCase => variant[..1].to_ascii_lowercase() + &variant[1..],
SnakeCase => {
let mut snake = String::new();
for (i, ch) in variant.char_indices() {
if i > 0 && ch.is_uppercase() {
snake.push('_');
}
snake.push(ch.to_ascii_lowercase());
}
snake
}
ScreamingSnakeCase => SnakeCase.apply_to_variant(variant).to_ascii_uppercase(),
KebabCase => SnakeCase.apply_to_variant(variant).replace('_', "-"),
ScreamingKebabCase => ScreamingSnakeCase
.apply_to_variant(variant)
.replace('_', "-"),
}
}
/// Apply a renaming rule to a struct field, returning the version expected in the source.
pub fn apply_to_field(self, field: &str) -> String {
match self {
None | LowerCase | SnakeCase => field.to_owned(),
UpperCase => field.to_ascii_uppercase(),
PascalCase => {
let mut pascal = String::new();
let mut capitalize = true;
for ch in field.chars() {
if ch == '_' {
capitalize = true;
} else if capitalize {
pascal.push(ch.to_ascii_uppercase());
capitalize = false;
} else {
pascal.push(ch);
}
}
pascal
}
CamelCase => {
let pascal = PascalCase.apply_to_field(field);
pascal[..1].to_ascii_lowercase() + &pascal[1..]
}
ScreamingSnakeCase => field.to_ascii_uppercase(),
KebabCase => field.replace('_', "-"),
ScreamingKebabCase => ScreamingSnakeCase.apply_to_field(field).replace('_', "-"),
}
}
/// Returns the `RenameRule` if it is not `None`, `rule_b` otherwise.
pub fn or(self, rule_b: Self) -> Self {
match self {
None => rule_b,
_ => self,
}
}
}
pub struct ParseError<'a> {
unknown: &'a str,
}
impl<'a> Display for ParseError<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("unknown rename rule `rename_all = ")?;
Debug::fmt(self.unknown, f)?;
f.write_str("`, expected one of ")?;
for (i, (name, _rule)) in RENAME_RULES.iter().enumerate() {
if i > 0 {
f.write_str(", ")?;
}
Debug::fmt(name, f)?;
}
Ok(())
}
}
#[test]
fn rename_variants() {
for &(original, lower, upper, camel, snake, screaming, kebab, screaming_kebab) in &[
(
"Outcome", "outcome", "OUTCOME", "outcome", "outcome", "OUTCOME", "outcome", "OUTCOME",
),
(
"VeryTasty",
"verytasty",
"VERYTASTY",
"veryTasty",
"very_tasty",
"VERY_TASTY",
"very-tasty",
"VERY-TASTY",
),
("A", "a", "A", "a", "a", "A", "a", "A"),
("Z42", "z42", "Z42", "z42", "z42", "Z42", "z42", "Z42"),
] {
assert_eq!(None.apply_to_variant(original), original);
assert_eq!(LowerCase.apply_to_variant(original), lower);
assert_eq!(UpperCase.apply_to_variant(original), upper);
assert_eq!(PascalCase.apply_to_variant(original), original);
assert_eq!(CamelCase.apply_to_variant(original), camel);
assert_eq!(SnakeCase.apply_to_variant(original), snake);
assert_eq!(ScreamingSnakeCase.apply_to_variant(original), screaming);
assert_eq!(KebabCase.apply_to_variant(original), kebab);
assert_eq!(
ScreamingKebabCase.apply_to_variant(original),
screaming_kebab
);
}
}
#[test]
fn rename_fields() {
for &(original, upper, pascal, camel, screaming, kebab, screaming_kebab) in &[
(
"outcome", "OUTCOME", "Outcome", "outcome", "OUTCOME", "outcome", "OUTCOME",
),
(
"very_tasty",
"VERY_TASTY",
"VeryTasty",
"veryTasty",
"VERY_TASTY",
"very-tasty",
"VERY-TASTY",
),
("a", "A", "A", "a", "A", "a", "A"),
("z42", "Z42", "Z42", "z42", "Z42", "z42", "Z42"),
] {
assert_eq!(None.apply_to_field(original), original);
assert_eq!(UpperCase.apply_to_field(original), upper);
assert_eq!(PascalCase.apply_to_field(original), pascal);
assert_eq!(CamelCase.apply_to_field(original), camel);
assert_eq!(SnakeCase.apply_to_field(original), original);
assert_eq!(ScreamingSnakeCase.apply_to_field(original), screaming);
assert_eq!(KebabCase.apply_to_field(original), kebab);
assert_eq!(ScreamingKebabCase.apply_to_field(original), screaming_kebab);
}
}

View File

@@ -0,0 +1,477 @@
use crate::internals::ast::{Container, Data, Field, Style};
use crate::internals::attr::{Default, Identifier, TagType};
use crate::internals::{ungroup, Ctxt, Derive};
use syn::{Member, Type};
// Cross-cutting checks that require looking at more than a single attrs object.
// Simpler checks should happen when parsing and building the attrs.
pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) {
check_default_on_tuple(cx, cont);
check_remote_generic(cx, cont);
check_getter(cx, cont);
check_flatten(cx, cont);
check_identifier(cx, cont);
check_variant_skip_attrs(cx, cont);
check_internal_tag_field_name_conflict(cx, cont);
check_adjacent_tag_conflict(cx, cont);
check_transparent(cx, cont, derive);
check_from_and_try_from(cx, cont);
}
// If some field of a tuple struct is marked #[serde(default)] then all fields
// after it must also be marked with that attribute, or the struct must have a
// container-level serde(default) attribute. A field's default value is only
// used for tuple fields if the sequence is exhausted at that point; that means
// all subsequent fields will fail to deserialize if they don't have their own
// default.
fn check_default_on_tuple(cx: &Ctxt, cont: &Container) {
if let Default::None = cont.attrs.default() {
if let Data::Struct(Style::Tuple, fields) = &cont.data {
let mut first_default_index = None;
for (i, field) in fields.iter().enumerate() {
// Skipped fields automatically get the #[serde(default)]
// attribute. We are interested only on non-skipped fields here.
if field.attrs.skip_deserializing() {
continue;
}
if let Default::None = field.attrs.default() {
if let Some(first) = first_default_index {
cx.error_spanned_by(
field.ty,
format!("field must have #[serde(default)] because previous field {} has #[serde(default)]", first),
);
}
continue;
}
if first_default_index.is_none() {
first_default_index = Some(i);
}
}
}
}
}
// Remote derive definition type must have either all of the generics of the
// remote type:
//
// #[serde(remote = "Generic")]
// struct Generic<T> {…}
//
// or none of them, i.e. defining impls for one concrete instantiation of the
// remote type only:
//
// #[serde(remote = "Generic<T>")]
// struct ConcreteDef {…}
//
fn check_remote_generic(cx: &Ctxt, cont: &Container) {
if let Some(remote) = cont.attrs.remote() {
let local_has_generic = !cont.generics.params.is_empty();
let remote_has_generic = !remote.segments.last().unwrap().arguments.is_none();
if local_has_generic && remote_has_generic {
cx.error_spanned_by(remote, "remove generic parameters from this path");
}
}
}
// Getters are only allowed inside structs (not enums) with the `remote`
// attribute.
fn check_getter(cx: &Ctxt, cont: &Container) {
match cont.data {
Data::Enum(_) => {
if cont.data.has_getter() {
cx.error_spanned_by(
cont.original,
"#[serde(getter = \"...\")] is not allowed in an enum",
);
}
}
Data::Struct(_, _) => {
if cont.data.has_getter() && cont.attrs.remote().is_none() {
cx.error_spanned_by(
cont.original,
"#[serde(getter = \"...\")] can only be used in structs that have #[serde(remote = \"...\")]",
);
}
}
}
}
// Flattening has some restrictions we can test.
fn check_flatten(cx: &Ctxt, cont: &Container) {
match &cont.data {
Data::Enum(variants) => {
for variant in variants {
for field in &variant.fields {
check_flatten_field(cx, variant.style, field);
}
}
}
Data::Struct(style, fields) => {
for field in fields {
check_flatten_field(cx, *style, field);
}
}
}
}
fn check_flatten_field(cx: &Ctxt, style: Style, field: &Field) {
if !field.attrs.flatten() {
return;
}
match style {
Style::Tuple => {
cx.error_spanned_by(
field.original,
"#[serde(flatten)] cannot be used on tuple structs",
);
}
Style::Newtype => {
cx.error_spanned_by(
field.original,
"#[serde(flatten)] cannot be used on newtype structs",
);
}
_ => {}
}
}
// The `other` attribute must be used at most once and it must be the last
// variant of an enum.
//
// Inside a `variant_identifier` all variants must be unit variants. Inside a
// `field_identifier` all but possibly one variant must be unit variants. The
// last variant may be a newtype variant which is an implicit "other" case.
fn check_identifier(cx: &Ctxt, cont: &Container) {
let variants = match &cont.data {
Data::Enum(variants) => variants,
Data::Struct(_, _) => return,
};
for (i, variant) in variants.iter().enumerate() {
match (
variant.style,
cont.attrs.identifier(),
variant.attrs.other(),
cont.attrs.tag(),
) {
// The `other` attribute may not be used in a variant_identifier.
(_, Identifier::Variant, true, _) => {
cx.error_spanned_by(
variant.original,
"#[serde(other)] may not be used on a variant identifier",
);
}
// Variant with `other` attribute cannot appear in untagged enum
(_, Identifier::No, true, &TagType::None) => {
cx.error_spanned_by(
variant.original,
"#[serde(other)] cannot appear on untagged enum",
);
}
// Variant with `other` attribute must be the last one.
(Style::Unit, Identifier::Field, true, _) | (Style::Unit, Identifier::No, true, _) => {
if i < variants.len() - 1 {
cx.error_spanned_by(
variant.original,
"#[serde(other)] must be on the last variant",
);
}
}
// Variant with `other` attribute must be a unit variant.
(_, Identifier::Field, true, _) | (_, Identifier::No, true, _) => {
cx.error_spanned_by(
variant.original,
"#[serde(other)] must be on a unit variant",
);
}
// Any sort of variant is allowed if this is not an identifier.
(_, Identifier::No, false, _) => {}
// Unit variant without `other` attribute is always fine.
(Style::Unit, _, false, _) => {}
// The last field is allowed to be a newtype catch-all.
(Style::Newtype, Identifier::Field, false, _) => {
if i < variants.len() - 1 {
cx.error_spanned_by(
variant.original,
format!("`{}` must be the last variant", variant.ident),
);
}
}
(_, Identifier::Field, false, _) => {
cx.error_spanned_by(
variant.original,
"#[serde(field_identifier)] may only contain unit variants",
);
}
(_, Identifier::Variant, false, _) => {
cx.error_spanned_by(
variant.original,
"#[serde(variant_identifier)] may only contain unit variants",
);
}
}
}
}
// Skip-(de)serializing attributes are not allowed on variants marked
// (de)serialize_with.
fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
let variants = match &cont.data {
Data::Enum(variants) => variants,
Data::Struct(_, _) => return,
};
for variant in variants {
if variant.attrs.serialize_with().is_some() {
if variant.attrs.skip_serializing() {
cx.error_spanned_by(
variant.original,
format!(
"variant `{}` cannot have both #[serde(serialize_with)] and #[serde(skip_serializing)]",
variant.ident
),
);
}
for field in &variant.fields {
let member = member_message(&field.member);
if field.attrs.skip_serializing() {
cx.error_spanned_by(
variant.original,
format!(
"variant `{}` cannot have both #[serde(serialize_with)] and a field {} marked with #[serde(skip_serializing)]",
variant.ident, member
),
);
}
if field.attrs.skip_serializing_if().is_some() {
cx.error_spanned_by(
variant.original,
format!(
"variant `{}` cannot have both #[serde(serialize_with)] and a field {} marked with #[serde(skip_serializing_if)]",
variant.ident, member
),
);
}
}
}
if variant.attrs.deserialize_with().is_some() {
if variant.attrs.skip_deserializing() {
cx.error_spanned_by(
variant.original,
format!(
"variant `{}` cannot have both #[serde(deserialize_with)] and #[serde(skip_deserializing)]",
variant.ident
),
);
}
for field in &variant.fields {
if field.attrs.skip_deserializing() {
let member = member_message(&field.member);
cx.error_spanned_by(
variant.original,
format!(
"variant `{}` cannot have both #[serde(deserialize_with)] and a field {} marked with #[serde(skip_deserializing)]",
variant.ident, member
),
);
}
}
}
}
}
// The tag of an internally-tagged struct variant must not be the same as either
// one of its fields, as this would result in duplicate keys in the serialized
// output and/or ambiguity in the to-be-deserialized input.
fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) {
let variants = match &cont.data {
Data::Enum(variants) => variants,
Data::Struct(_, _) => return,
};
let tag = match cont.attrs.tag() {
TagType::Internal { tag } => tag.as_str(),
TagType::External | TagType::Adjacent { .. } | TagType::None => return,
};
let diagnose_conflict = || {
cx.error_spanned_by(
cont.original,
format!("variant field name `{}` conflicts with internal tag", tag),
);
};
for variant in variants {
match variant.style {
Style::Struct => {
if variant.attrs.untagged() {
continue;
}
for field in &variant.fields {
let check_ser =
!(field.attrs.skip_serializing() || variant.attrs.skip_serializing());
let check_de =
!(field.attrs.skip_deserializing() || variant.attrs.skip_deserializing());
let name = field.attrs.name();
let ser_name = name.serialize_name();
if check_ser && ser_name.value == tag {
diagnose_conflict();
return;
}
for de_name in field.attrs.aliases() {
if check_de && de_name.value == tag {
diagnose_conflict();
return;
}
}
}
}
Style::Unit | Style::Newtype | Style::Tuple => {}
}
}
}
// In the case of adjacently-tagged enums, the type and the contents tag must
// differ, for the same reason.
fn check_adjacent_tag_conflict(cx: &Ctxt, cont: &Container) {
let (type_tag, content_tag) = match cont.attrs.tag() {
TagType::Adjacent { tag, content } => (tag, content),
TagType::Internal { .. } | TagType::External | TagType::None => return,
};
if type_tag == content_tag {
cx.error_spanned_by(
cont.original,
format!(
"enum tags `{}` for type and content conflict with each other",
type_tag
),
);
}
}
// Enums and unit structs cannot be transparent.
fn check_transparent(cx: &Ctxt, cont: &mut Container, derive: Derive) {
if !cont.attrs.transparent() {
return;
}
if cont.attrs.type_from().is_some() {
cx.error_spanned_by(
cont.original,
"#[serde(transparent)] is not allowed with #[serde(from = \"...\")]",
);
}
if cont.attrs.type_try_from().is_some() {
cx.error_spanned_by(
cont.original,
"#[serde(transparent)] is not allowed with #[serde(try_from = \"...\")]",
);
}
if cont.attrs.type_into().is_some() {
cx.error_spanned_by(
cont.original,
"#[serde(transparent)] is not allowed with #[serde(into = \"...\")]",
);
}
let fields = match &mut cont.data {
Data::Enum(_) => {
cx.error_spanned_by(
cont.original,
"#[serde(transparent)] is not allowed on an enum",
);
return;
}
Data::Struct(Style::Unit, _) => {
cx.error_spanned_by(
cont.original,
"#[serde(transparent)] is not allowed on a unit struct",
);
return;
}
Data::Struct(_, fields) => fields,
};
let mut transparent_field = None;
for field in fields {
if allow_transparent(field, derive) {
if transparent_field.is_some() {
cx.error_spanned_by(
cont.original,
"#[serde(transparent)] requires struct to have at most one transparent field",
);
return;
}
transparent_field = Some(field);
}
}
match transparent_field {
Some(transparent_field) => transparent_field.attrs.mark_transparent(),
None => match derive {
Derive::Serialize => {
cx.error_spanned_by(
cont.original,
"#[serde(transparent)] requires at least one field that is not skipped",
);
}
Derive::Deserialize => {
cx.error_spanned_by(
cont.original,
"#[serde(transparent)] requires at least one field that is neither skipped nor has a default",
);
}
},
}
}
fn member_message(member: &Member) -> String {
match member {
Member::Named(ident) => format!("`{}`", ident),
Member::Unnamed(i) => format!("#{}", i.index),
}
}
fn allow_transparent(field: &Field, derive: Derive) -> bool {
if let Type::Path(ty) = ungroup(field.ty) {
if let Some(seg) = ty.path.segments.last() {
if seg.ident == "PhantomData" {
return false;
}
}
}
match derive {
Derive::Serialize => !field.attrs.skip_serializing(),
Derive::Deserialize => !field.attrs.skip_deserializing() && field.attrs.default().is_none(),
}
}
fn check_from_and_try_from(cx: &Ctxt, cont: &mut Container) {
if cont.attrs.type_from().is_some() && cont.attrs.type_try_from().is_some() {
cx.error_spanned_by(
cont.original,
"#[serde(from = \"...\")] and #[serde(try_from = \"...\")] conflict with each other",
);
}
}

View File

@@ -0,0 +1,68 @@
use quote::ToTokens;
use std::cell::RefCell;
use std::fmt::Display;
use std::thread;
/// A type to collect errors together and format them.
///
/// Dropping this object will cause a panic. It must be consumed using `check`.
///
/// References can be shared since this type uses run-time exclusive mut checking.
#[derive(Default)]
pub struct Ctxt {
// The contents will be set to `None` during checking. This is so that checking can be
// enforced.
errors: RefCell<Option<Vec<syn::Error>>>,
}
impl Ctxt {
/// Create a new context object.
///
/// This object contains no errors, but will still trigger a panic if it is not `check`ed.
pub fn new() -> Self {
Ctxt {
errors: RefCell::new(Some(Vec::new())),
}
}
/// Add an error to the context object with a tokenenizable object.
///
/// The object is used for spanning in error messages.
pub fn error_spanned_by<A: ToTokens, T: Display>(&self, obj: A, msg: T) {
self.errors
.borrow_mut()
.as_mut()
.unwrap()
// Curb monomorphization from generating too many identical methods.
.push(syn::Error::new_spanned(obj.into_token_stream(), msg));
}
/// Add one of Syn's parse errors.
pub fn syn_error(&self, err: syn::Error) {
self.errors.borrow_mut().as_mut().unwrap().push(err);
}
/// Consume this object, producing a formatted error string if there are errors.
pub fn check(self) -> syn::Result<()> {
let mut errors = self.errors.borrow_mut().take().unwrap().into_iter();
let mut combined = match errors.next() {
Some(first) => first,
None => return Ok(()),
};
for rest in errors {
combined.combine(rest);
}
Err(combined)
}
}
impl Drop for Ctxt {
fn drop(&mut self) {
if !thread::panicking() && self.errors.borrow().is_some() {
panic!("forgot to check for errors");
}
}
}

View File

@@ -0,0 +1,28 @@
pub mod ast;
pub mod attr;
pub mod name;
mod case;
mod check;
mod ctxt;
mod receiver;
mod respan;
mod symbol;
use syn::Type;
pub use self::ctxt::Ctxt;
pub use self::receiver::replace_receiver;
#[derive(Copy, Clone)]
pub enum Derive {
Serialize,
Deserialize,
}
pub fn ungroup(mut ty: &Type) -> &Type {
while let Type::Group(group) = ty {
ty = &group.elem;
}
ty
}

View File

@@ -0,0 +1,113 @@
use crate::internals::attr::{Attr, VecAttr};
use proc_macro2::{Ident, Span, TokenStream};
use quote::ToTokens;
use std::cmp::Ordering;
use std::collections::BTreeSet;
use std::fmt::{self, Display};
use syn::LitStr;
pub struct MultiName {
pub(crate) serialize: Name,
pub(crate) serialize_renamed: bool,
pub(crate) deserialize: Name,
pub(crate) deserialize_renamed: bool,
pub(crate) deserialize_aliases: BTreeSet<Name>,
}
impl MultiName {
pub(crate) fn from_attrs(
source_name: Name,
ser_name: Attr<Name>,
de_name: Attr<Name>,
de_aliases: Option<VecAttr<Name>>,
) -> Self {
let mut alias_set = BTreeSet::new();
if let Some(de_aliases) = de_aliases {
for alias_name in de_aliases.get() {
alias_set.insert(alias_name);
}
}
let ser_name = ser_name.get();
let ser_renamed = ser_name.is_some();
let de_name = de_name.get();
let de_renamed = de_name.is_some();
MultiName {
serialize: ser_name.unwrap_or_else(|| source_name.clone()),
serialize_renamed: ser_renamed,
deserialize: de_name.unwrap_or(source_name),
deserialize_renamed: de_renamed,
deserialize_aliases: alias_set,
}
}
/// Return the container name for the container when serializing.
pub fn serialize_name(&self) -> &Name {
&self.serialize
}
/// Return the container name for the container when deserializing.
pub fn deserialize_name(&self) -> &Name {
&self.deserialize
}
pub(crate) fn deserialize_aliases(&self) -> &BTreeSet<Name> {
&self.deserialize_aliases
}
}
#[derive(Clone)]
pub struct Name {
pub value: String,
pub span: Span,
}
impl ToTokens for Name {
fn to_tokens(&self, tokens: &mut TokenStream) {
LitStr::new(&self.value, self.span).to_tokens(tokens);
}
}
impl Ord for Name {
fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(&self.value, &other.value)
}
}
impl PartialOrd for Name {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(Ord::cmp(self, other))
}
}
impl Eq for Name {}
impl PartialEq for Name {
fn eq(&self, other: &Self) -> bool {
self.value == other.value
}
}
impl From<&Ident> for Name {
fn from(ident: &Ident) -> Self {
Name {
value: ident.to_string(),
span: ident.span(),
}
}
}
impl From<&LitStr> for Name {
fn from(lit: &LitStr) -> Self {
Name {
value: lit.value(),
span: lit.span(),
}
}
}
impl Display for Name {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(&self.value, formatter)
}
}

View File

@@ -0,0 +1,293 @@
use crate::internals::respan::respan;
use proc_macro2::Span;
use quote::ToTokens;
use std::mem;
use syn::{
parse_quote, Data, DeriveInput, Expr, ExprPath, GenericArgument, GenericParam, Generics, Macro,
Path, PathArguments, QSelf, ReturnType, Token, Type, TypeParamBound, TypePath, WherePredicate,
};
pub fn replace_receiver(input: &mut DeriveInput) {
let self_ty = {
let ident = &input.ident;
let ty_generics = input.generics.split_for_impl().1;
parse_quote!(#ident #ty_generics)
};
let mut visitor = ReplaceReceiver(&self_ty);
visitor.visit_generics_mut(&mut input.generics);
visitor.visit_data_mut(&mut input.data);
}
struct ReplaceReceiver<'a>(&'a TypePath);
impl ReplaceReceiver<'_> {
fn self_ty(&self, span: Span) -> TypePath {
let tokens = self.0.to_token_stream();
let respanned = respan(tokens, span);
syn::parse2(respanned).unwrap()
}
fn self_to_qself(&self, qself: &mut Option<QSelf>, path: &mut Path) {
if path.leading_colon.is_some() || path.segments[0].ident != "Self" {
return;
}
if path.segments.len() == 1 {
self.self_to_expr_path(path);
return;
}
let span = path.segments[0].ident.span();
*qself = Some(QSelf {
lt_token: Token![<](span),
ty: Box::new(Type::Path(self.self_ty(span))),
position: 0,
as_token: None,
gt_token: Token![>](span),
});
path.leading_colon = Some(**path.segments.pairs().next().unwrap().punct().unwrap());
let segments = mem::take(&mut path.segments);
path.segments = segments.into_pairs().skip(1).collect();
}
fn self_to_expr_path(&self, path: &mut Path) {
let self_ty = self.self_ty(path.segments[0].ident.span());
let variant = mem::replace(path, self_ty.path);
for segment in &mut path.segments {
if let PathArguments::AngleBracketed(bracketed) = &mut segment.arguments {
if bracketed.colon2_token.is_none() && !bracketed.args.is_empty() {
bracketed.colon2_token = Some(<Token![::]>::default());
}
}
}
if variant.segments.len() > 1 {
path.segments.push_punct(<Token![::]>::default());
path.segments.extend(variant.segments.into_pairs().skip(1));
}
}
}
impl ReplaceReceiver<'_> {
// `Self` -> `Receiver`
fn visit_type_mut(&mut self, ty: &mut Type) {
let span = if let Type::Path(node) = ty {
if node.qself.is_none() && node.path.is_ident("Self") {
node.path.segments[0].ident.span()
} else {
self.visit_type_path_mut(node);
return;
}
} else {
self.visit_type_mut_impl(ty);
return;
};
*ty = Type::Path(self.self_ty(span));
}
// `Self::Assoc` -> `<Receiver>::Assoc`
fn visit_type_path_mut(&mut self, ty: &mut TypePath) {
if ty.qself.is_none() {
self.self_to_qself(&mut ty.qself, &mut ty.path);
}
self.visit_type_path_mut_impl(ty);
}
// `Self::method` -> `<Receiver>::method`
fn visit_expr_path_mut(&mut self, expr: &mut ExprPath) {
if expr.qself.is_none() {
self.self_to_qself(&mut expr.qself, &mut expr.path);
}
self.visit_expr_path_mut_impl(expr);
}
// Everything below is simply traversing the syntax tree.
fn visit_type_mut_impl(&mut self, ty: &mut Type) {
match ty {
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
Type::Array(ty) => {
self.visit_type_mut(&mut ty.elem);
self.visit_expr_mut(&mut ty.len);
}
Type::BareFn(ty) => {
for arg in &mut ty.inputs {
self.visit_type_mut(&mut arg.ty);
}
self.visit_return_type_mut(&mut ty.output);
}
Type::Group(ty) => self.visit_type_mut(&mut ty.elem),
Type::ImplTrait(ty) => {
for bound in &mut ty.bounds {
self.visit_type_param_bound_mut(bound);
}
}
Type::Macro(ty) => self.visit_macro_mut(&mut ty.mac),
Type::Paren(ty) => self.visit_type_mut(&mut ty.elem),
Type::Path(ty) => {
if let Some(qself) = &mut ty.qself {
self.visit_type_mut(&mut qself.ty);
}
self.visit_path_mut(&mut ty.path);
}
Type::Ptr(ty) => self.visit_type_mut(&mut ty.elem),
Type::Reference(ty) => self.visit_type_mut(&mut ty.elem),
Type::Slice(ty) => self.visit_type_mut(&mut ty.elem),
Type::TraitObject(ty) => {
for bound in &mut ty.bounds {
self.visit_type_param_bound_mut(bound);
}
}
Type::Tuple(ty) => {
for elem in &mut ty.elems {
self.visit_type_mut(elem);
}
}
Type::Infer(_) | Type::Never(_) | Type::Verbatim(_) => {}
_ => {}
}
}
fn visit_type_path_mut_impl(&mut self, ty: &mut TypePath) {
if let Some(qself) = &mut ty.qself {
self.visit_type_mut(&mut qself.ty);
}
self.visit_path_mut(&mut ty.path);
}
fn visit_expr_path_mut_impl(&mut self, expr: &mut ExprPath) {
if let Some(qself) = &mut expr.qself {
self.visit_type_mut(&mut qself.ty);
}
self.visit_path_mut(&mut expr.path);
}
fn visit_path_mut(&mut self, path: &mut Path) {
for segment in &mut path.segments {
self.visit_path_arguments_mut(&mut segment.arguments);
}
}
fn visit_path_arguments_mut(&mut self, arguments: &mut PathArguments) {
match arguments {
PathArguments::None => {}
PathArguments::AngleBracketed(arguments) => {
for arg in &mut arguments.args {
match arg {
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
GenericArgument::Type(arg) => self.visit_type_mut(arg),
GenericArgument::AssocType(arg) => self.visit_type_mut(&mut arg.ty),
GenericArgument::Lifetime(_)
| GenericArgument::Const(_)
| GenericArgument::AssocConst(_)
| GenericArgument::Constraint(_) => {}
_ => {}
}
}
}
PathArguments::Parenthesized(arguments) => {
for argument in &mut arguments.inputs {
self.visit_type_mut(argument);
}
self.visit_return_type_mut(&mut arguments.output);
}
}
}
fn visit_return_type_mut(&mut self, return_type: &mut ReturnType) {
match return_type {
ReturnType::Default => {}
ReturnType::Type(_, output) => self.visit_type_mut(output),
}
}
fn visit_type_param_bound_mut(&mut self, bound: &mut TypeParamBound) {
match bound {
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
TypeParamBound::Trait(bound) => self.visit_path_mut(&mut bound.path),
TypeParamBound::Lifetime(_)
| TypeParamBound::PreciseCapture(_)
| TypeParamBound::Verbatim(_) => {}
_ => {}
}
}
fn visit_generics_mut(&mut self, generics: &mut Generics) {
for param in &mut generics.params {
match param {
GenericParam::Type(param) => {
for bound in &mut param.bounds {
self.visit_type_param_bound_mut(bound);
}
}
GenericParam::Lifetime(_) | GenericParam::Const(_) => {}
}
}
if let Some(where_clause) = &mut generics.where_clause {
for predicate in &mut where_clause.predicates {
match predicate {
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
WherePredicate::Type(predicate) => {
self.visit_type_mut(&mut predicate.bounded_ty);
for bound in &mut predicate.bounds {
self.visit_type_param_bound_mut(bound);
}
}
WherePredicate::Lifetime(_) => {}
_ => {}
}
}
}
}
fn visit_data_mut(&mut self, data: &mut Data) {
match data {
Data::Struct(data) => {
for field in &mut data.fields {
self.visit_type_mut(&mut field.ty);
}
}
Data::Enum(data) => {
for variant in &mut data.variants {
for field in &mut variant.fields {
self.visit_type_mut(&mut field.ty);
}
}
}
Data::Union(_) => {}
}
}
fn visit_expr_mut(&mut self, expr: &mut Expr) {
match expr {
Expr::Binary(expr) => {
self.visit_expr_mut(&mut expr.left);
self.visit_expr_mut(&mut expr.right);
}
Expr::Call(expr) => {
self.visit_expr_mut(&mut expr.func);
for arg in &mut expr.args {
self.visit_expr_mut(arg);
}
}
Expr::Cast(expr) => {
self.visit_expr_mut(&mut expr.expr);
self.visit_type_mut(&mut expr.ty);
}
Expr::Field(expr) => self.visit_expr_mut(&mut expr.base),
Expr::Index(expr) => {
self.visit_expr_mut(&mut expr.expr);
self.visit_expr_mut(&mut expr.index);
}
Expr::Paren(expr) => self.visit_expr_mut(&mut expr.expr),
Expr::Path(expr) => self.visit_expr_path_mut(expr),
Expr::Unary(expr) => self.visit_expr_mut(&mut expr.expr),
_ => {}
}
}
fn visit_macro_mut(&mut self, _mac: &mut Macro) {}
}

View File

@@ -0,0 +1,16 @@
use proc_macro2::{Group, Span, TokenStream, TokenTree};
pub(crate) fn respan(stream: TokenStream, span: Span) -> TokenStream {
stream
.into_iter()
.map(|token| respan_token(token, span))
.collect()
}
fn respan_token(mut token: TokenTree, span: Span) -> TokenTree {
if let TokenTree::Group(g) = &mut token {
*g = Group::new(g.delimiter(), respan(g.stream(), span));
}
token.set_span(span);
token
}

View File

@@ -0,0 +1,71 @@
use std::fmt::{self, Display};
use syn::{Ident, Path};
#[derive(Copy, Clone)]
pub struct Symbol(&'static str);
pub const ALIAS: Symbol = Symbol("alias");
pub const BORROW: Symbol = Symbol("borrow");
pub const BOUND: Symbol = Symbol("bound");
pub const CONTENT: Symbol = Symbol("content");
pub const CRATE: Symbol = Symbol("crate");
pub const DEFAULT: Symbol = Symbol("default");
pub const DENY_UNKNOWN_FIELDS: Symbol = Symbol("deny_unknown_fields");
pub const DESERIALIZE: Symbol = Symbol("deserialize");
pub const DESERIALIZE_WITH: Symbol = Symbol("deserialize_with");
pub const EXPECTING: Symbol = Symbol("expecting");
pub const FIELD_IDENTIFIER: Symbol = Symbol("field_identifier");
pub const FLATTEN: Symbol = Symbol("flatten");
pub const FROM: Symbol = Symbol("from");
pub const GETTER: Symbol = Symbol("getter");
pub const INTO: Symbol = Symbol("into");
pub const NON_EXHAUSTIVE: Symbol = Symbol("non_exhaustive");
pub const OTHER: Symbol = Symbol("other");
pub const REMOTE: Symbol = Symbol("remote");
pub const RENAME: Symbol = Symbol("rename");
pub const RENAME_ALL: Symbol = Symbol("rename_all");
pub const RENAME_ALL_FIELDS: Symbol = Symbol("rename_all_fields");
pub const REPR: Symbol = Symbol("repr");
pub const SERDE: Symbol = Symbol("serde");
pub const SERIALIZE: Symbol = Symbol("serialize");
pub const SERIALIZE_WITH: Symbol = Symbol("serialize_with");
pub const SKIP: Symbol = Symbol("skip");
pub const SKIP_DESERIALIZING: Symbol = Symbol("skip_deserializing");
pub const SKIP_SERIALIZING: Symbol = Symbol("skip_serializing");
pub const SKIP_SERIALIZING_IF: Symbol = Symbol("skip_serializing_if");
pub const TAG: Symbol = Symbol("tag");
pub const TRANSPARENT: Symbol = Symbol("transparent");
pub const TRY_FROM: Symbol = Symbol("try_from");
pub const UNTAGGED: Symbol = Symbol("untagged");
pub const VARIANT_IDENTIFIER: Symbol = Symbol("variant_identifier");
pub const WITH: Symbol = Symbol("with");
impl PartialEq<Symbol> for Ident {
fn eq(&self, word: &Symbol) -> bool {
self == word.0
}
}
impl PartialEq<Symbol> for &Ident {
fn eq(&self, word: &Symbol) -> bool {
*self == word.0
}
}
impl PartialEq<Symbol> for Path {
fn eq(&self, word: &Symbol) -> bool {
self.is_ident(word.0)
}
}
impl PartialEq<Symbol> for &Path {
fn eq(&self, word: &Symbol) -> bool {
self.is_ident(word.0)
}
}
impl Display for Symbol {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(self.0)
}
}

127
vendor/serde_derive/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,127 @@
//! This crate provides Serde's two derive macros.
//!
//! ```edition2021
//! # use serde_derive::{Deserialize, Serialize};
//! #
//! #[derive(Serialize, Deserialize)]
//! # struct S;
//! #
//! # fn main() {}
//! ```
//!
//! Please refer to [https://serde.rs/derive.html] for how to set this up.
//!
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.227")]
#![cfg_attr(not(check_cfg), allow(unexpected_cfgs))]
// Ignored clippy lints
#![allow(
// clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054
clippy::branches_sharing_code,
clippy::cognitive_complexity,
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/7575
clippy::collapsible_match,
clippy::derive_partial_eq_without_eq,
clippy::enum_variant_names,
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/6797
clippy::manual_map,
clippy::match_like_matches_macro,
clippy::needless_lifetimes,
clippy::needless_pass_by_value,
clippy::too_many_arguments,
clippy::trivially_copy_pass_by_ref,
clippy::used_underscore_binding,
clippy::wildcard_in_or_patterns,
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704
clippy::unnested_or_patterns,
)]
// Ignored clippy_pedantic lints
#![allow(
clippy::cast_possible_truncation,
clippy::checked_conversions,
clippy::doc_markdown,
clippy::elidable_lifetime_names,
clippy::enum_glob_use,
clippy::indexing_slicing,
clippy::items_after_statements,
clippy::let_underscore_untyped,
clippy::manual_assert,
clippy::map_err_ignore,
clippy::match_same_arms,
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/6984
clippy::match_wildcard_for_single_variants,
clippy::module_name_repetitions,
clippy::must_use_candidate,
clippy::similar_names,
clippy::single_match_else,
clippy::struct_excessive_bools,
clippy::too_many_lines,
clippy::uninlined_format_args,
clippy::unseparated_literal_suffix,
clippy::unused_self,
clippy::use_self,
clippy::wildcard_imports
)]
#![cfg_attr(all(test, exhaustive), feature(non_exhaustive_omitted_patterns_lint))]
#![allow(unknown_lints, mismatched_lifetime_syntaxes)]
extern crate proc_macro2;
extern crate quote;
extern crate syn;
extern crate proc_macro;
mod internals;
use proc_macro::TokenStream;
use proc_macro2::{Ident, Span};
use quote::{ToTokens, TokenStreamExt as _};
use syn::parse_macro_input;
use syn::DeriveInput;
#[macro_use]
mod bound;
#[macro_use]
mod fragment;
mod de;
mod deprecated;
mod dummy;
mod pretend;
mod ser;
mod this;
#[allow(non_camel_case_types)]
struct private;
impl private {
fn ident(&self) -> Ident {
Ident::new(
concat!("__private", env!("CARGO_PKG_VERSION_PATCH")),
Span::call_site(),
)
}
}
impl ToTokens for private {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
tokens.append(self.ident());
}
}
#[proc_macro_derive(Serialize, attributes(serde))]
pub fn derive_serialize(input: TokenStream) -> TokenStream {
let mut input = parse_macro_input!(input as DeriveInput);
ser::expand_derive_serialize(&mut input)
.unwrap_or_else(syn::Error::into_compile_error)
.into()
}
#[proc_macro_derive(Deserialize, attributes(serde))]
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
let mut input = parse_macro_input!(input as DeriveInput);
de::expand_derive_deserialize(&mut input)
.unwrap_or_else(syn::Error::into_compile_error)
.into()
}

188
vendor/serde_derive/src/pretend.rs vendored Normal file
View File

@@ -0,0 +1,188 @@
use crate::internals::ast::{Container, Data, Field, Style, Variant};
use crate::private;
use proc_macro2::TokenStream;
use quote::{format_ident, quote};
// Suppress dead_code warnings that would otherwise appear when using a remote
// derive. Other than this pretend code, a struct annotated with remote derive
// never has its fields referenced and an enum annotated with remote derive
// never has its variants constructed.
//
// warning: field is never used: `i`
// --> src/main.rs:4:20
// |
// 4 | struct StructDef { i: i32 }
// | ^^^^^^
//
// warning: variant is never constructed: `V`
// --> src/main.rs:8:16
// |
// 8 | enum EnumDef { V }
// | ^
//
pub fn pretend_used(cont: &Container, is_packed: bool) -> TokenStream {
let pretend_fields = pretend_fields_used(cont, is_packed);
let pretend_variants = pretend_variants_used(cont);
quote! {
#pretend_fields
#pretend_variants
}
}
// For structs with named fields, expands to:
//
// match None::<&T> {
// Some(T { a: __v0, b: __v1 }) => {}
// _ => {}
// }
//
// For packed structs on sufficiently new rustc, expands to:
//
// match None::<&T> {
// Some(__v @ T { a: _, b: _ }) => {
// let _ = addr_of!(__v.a);
// let _ = addr_of!(__v.b);
// }
// _ => {}
// }
//
// For packed structs on older rustc, we assume Sized and !Drop, and expand to:
//
// match None::<T> {
// Some(T { a: __v0, b: __v1 }) => {}
// _ => {}
// }
//
// For enums, expands to the following but only including struct variants:
//
// match None::<&T> {
// Some(T::A { a: __v0 }) => {}
// Some(T::B { b: __v0 }) => {}
// _ => {}
// }
//
fn pretend_fields_used(cont: &Container, is_packed: bool) -> TokenStream {
match &cont.data {
Data::Enum(variants) => pretend_fields_used_enum(cont, variants),
Data::Struct(Style::Struct | Style::Tuple | Style::Newtype, fields) => {
if is_packed {
pretend_fields_used_struct_packed(cont, fields)
} else {
pretend_fields_used_struct(cont, fields)
}
}
Data::Struct(Style::Unit, _) => quote!(),
}
}
fn pretend_fields_used_struct(cont: &Container, fields: &[Field]) -> TokenStream {
let type_ident = &cont.ident;
let (_, ty_generics, _) = cont.generics.split_for_impl();
let members = fields.iter().map(|field| &field.member);
let placeholders = (0usize..).map(|i| format_ident!("__v{}", i));
quote! {
match _serde::#private::None::<&#type_ident #ty_generics> {
_serde::#private::Some(#type_ident { #(#members: #placeholders),* }) => {}
_ => {}
}
}
}
fn pretend_fields_used_struct_packed(cont: &Container, fields: &[Field]) -> TokenStream {
let type_ident = &cont.ident;
let (_, ty_generics, _) = cont.generics.split_for_impl();
let members = fields.iter().map(|field| &field.member).collect::<Vec<_>>();
let private2 = private;
quote! {
match _serde::#private::None::<&#type_ident #ty_generics> {
_serde::#private::Some(__v @ #type_ident { #(#members: _),* }) => {
#(
let _ = _serde::#private2::ptr::addr_of!(__v.#members);
)*
}
_ => {}
}
}
}
fn pretend_fields_used_enum(cont: &Container, variants: &[Variant]) -> TokenStream {
let type_ident = &cont.ident;
let (_, ty_generics, _) = cont.generics.split_for_impl();
let patterns = variants
.iter()
.filter_map(|variant| match variant.style {
Style::Struct | Style::Tuple | Style::Newtype => {
let variant_ident = &variant.ident;
let members = variant.fields.iter().map(|field| &field.member);
let placeholders = (0usize..).map(|i| format_ident!("__v{}", i));
Some(quote!(#type_ident::#variant_ident { #(#members: #placeholders),* }))
}
Style::Unit => None,
})
.collect::<Vec<_>>();
let private2 = private;
quote! {
match _serde::#private::None::<&#type_ident #ty_generics> {
#(
_serde::#private2::Some(#patterns) => {}
)*
_ => {}
}
}
}
// Expands to one of these per enum variant:
//
// match None {
// Some((__v0, __v1,)) => {
// let _ = E::V { a: __v0, b: __v1 };
// }
// _ => {}
// }
//
fn pretend_variants_used(cont: &Container) -> TokenStream {
let variants = match &cont.data {
Data::Enum(variants) => variants,
Data::Struct(_, _) => {
return quote!();
}
};
let type_ident = &cont.ident;
let (_, ty_generics, _) = cont.generics.split_for_impl();
let turbofish = ty_generics.as_turbofish();
let cases = variants.iter().map(|variant| {
let variant_ident = &variant.ident;
let placeholders = &(0..variant.fields.len())
.map(|i| format_ident!("__v{}", i))
.collect::<Vec<_>>();
let pat = match variant.style {
Style::Struct => {
let members = variant.fields.iter().map(|field| &field.member);
quote!({ #(#members: #placeholders),* })
}
Style::Tuple | Style::Newtype => quote!(( #(#placeholders),* )),
Style::Unit => quote!(),
};
quote! {
match _serde::#private::None {
_serde::#private::Some((#(#placeholders,)*)) => {
let _ = #type_ident::#variant_ident #turbofish #pat;
}
_ => {}
}
}
});
quote!(#(#cases)*)
}

1369
vendor/serde_derive/src/ser.rs vendored Normal file

File diff suppressed because it is too large Load Diff

32
vendor/serde_derive/src/this.rs vendored Normal file
View File

@@ -0,0 +1,32 @@
use crate::internals::ast::Container;
use syn::{Path, PathArguments, Token};
pub fn this_type(cont: &Container) -> Path {
if let Some(remote) = cont.attrs.remote() {
let mut this = remote.clone();
for segment in &mut this.segments {
if let PathArguments::AngleBracketed(arguments) = &mut segment.arguments {
arguments.colon2_token = None;
}
}
this
} else {
Path::from(cont.ident.clone())
}
}
pub fn this_value(cont: &Container) -> Path {
if let Some(remote) = cont.attrs.remote() {
let mut this = remote.clone();
for segment in &mut this.segments {
if let PathArguments::AngleBracketed(arguments) = &mut segment.arguments {
if arguments.colon2_token.is_none() {
arguments.colon2_token = Some(Token![::](arguments.lt_token.span));
}
}
}
this
} else {
Path::from(cont.ident.clone())
}
}