summaryrefslogtreecommitdiffstats
path: root/third_party/rust/serde_derive/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /third_party/rust/serde_derive/src
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/serde_derive/src')
-rw-r--r--third_party/rust/serde_derive/src/bound.rs408
-rw-r--r--third_party/rust/serde_derive/src/de.rs3148
-rw-r--r--third_party/rust/serde_derive/src/dummy.rs23
-rw-r--r--third_party/rust/serde_derive/src/fragment.rs74
-rw-r--r--third_party/rust/serde_derive/src/internals/ast.rs216
-rw-r--r--third_party/rust/serde_derive/src/internals/attr.rs1881
-rw-r--r--third_party/rust/serde_derive/src/internals/case.rs200
-rw-r--r--third_party/rust/serde_derive/src/internals/check.rs477
-rw-r--r--third_party/rust/serde_derive/src/internals/ctxt.rs68
-rw-r--r--third_party/rust/serde_derive/src/internals/mod.rs27
-rw-r--r--third_party/rust/serde_derive/src/internals/receiver.rs292
-rw-r--r--third_party/rust/serde_derive/src/internals/respan.rs16
-rw-r--r--third_party/rust/serde_derive/src/internals/symbol.rs71
-rw-r--r--third_party/rust/serde_derive/src/lib.rs101
-rw-r--r--third_party/rust/serde_derive/src/pretend.rs185
-rw-r--r--third_party/rust/serde_derive/src/ser.rs1359
-rw-r--r--third_party/rust/serde_derive/src/this.rs32
17 files changed, 8578 insertions, 0 deletions
diff --git a/third_party/rust/serde_derive/src/bound.rs b/third_party/rust/serde_derive/src/bound.rs
new file mode 100644
index 0000000000..fe8ccfff5b
--- /dev/null
+++ b/third_party/rust/serde_derive/src/bound.rs
@@ -0,0 +1,408 @@
+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::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(),
+ },
+ })
+}
diff --git a/third_party/rust/serde_derive/src/de.rs b/third_party/rust/serde_derive/src/de.rs
new file mode 100644
index 0000000000..e3b737c61c
--- /dev/null
+++ b/third_party/rust/serde_derive/src/de.rs
@@ -0,0 +1,3148 @@
+use crate::fragment::{Expr, Fragment, Match, Stmts};
+use crate::internals::ast::{Container, Data, Field, Style, Variant};
+use crate::internals::{attr, replace_receiver, ungroup, Ctxt, Derive};
+use crate::{bound, dummy, pretend, this};
+use proc_macro2::{Literal, 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};
+
+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) {
+ 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) = split_with_de_lifetime(&params);
+ let body = Stmts(deserialize_body(&cont, &params));
+ let delife = params.borrowed.de_lifetime();
+ let serde = cont.attrs.serde_path();
+
+ let impl_block = if let Some(remote) = cont.attrs.remote() {
+ let vis = &input.vis;
+ let used = pretend::pretend_used(&cont, params.is_packed);
+ quote! {
+ 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]
+ 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()
+ }
+}
+
+// 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) => deserialize_enum(params, variants, &cont.attrs),
+ Data::Struct(Style::Struct, fields) => {
+ deserialize_struct(params, fields, &cont.attrs, StructForm::Struct)
+ }
+ Data::Struct(Style::Tuple, fields) | Data::Struct(Style::Newtype, fields) => {
+ deserialize_tuple(params, fields, &cont.attrs, TupleForm::Tuple)
+ }
+ Data::Struct(Style::Unit, _) => deserialize_unit_struct(params, &cont.attrs),
+ }
+ } else {
+ match &cont.data {
+ Data::Enum(variants) => deserialize_custom_identifier(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) => {
+ deserialize_struct_in_place(params, fields, &cont.attrs)?
+ }
+ Data::Struct(Style::Tuple, fields) | Data::Struct(Style::Newtype, fields) => {
+ deserialize_tuple_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
+}
+
+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()),
+ attr::Default::Path(path) => quote!(#path()),
+ attr::Default::None => quote!(_serde::__private::PhantomData),
+ };
+ quote!(#member: #value)
+ }
+ });
+
+ quote_block! {
+ _serde::__private::Result::map(
+ #path(__deserializer),
+ |__transparent| #this_value { #(#assign),* })
+ }
+}
+
+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)
+ }
+}
+
+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))
+ }
+}
+
+fn deserialize_unit_struct(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) =
+ split_with_de_lifetime(params);
+ 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 ()>,
+ }
+
+ 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,
+ },
+ )
+ }
+}
+
+enum TupleForm<'a> {
+ Tuple,
+ /// Contains a variant name
+ ExternallyTagged(&'a syn::Ident),
+ /// Contains a variant name and an intermediate deserializer from which actual
+ /// deserialization will be performed
+ Untagged(&'a syn::Ident, TokenStream),
+}
+
+fn deserialize_tuple(
+ params: &Parameters,
+ fields: &[Field],
+ cattrs: &attr::Container,
+ form: TupleForm,
+) -> Fragment {
+ assert!(!cattrs.has_flatten());
+
+ 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) =
+ split_with_de_lifetime(params);
+ 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(_, deserializer) => 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 ()>,
+ }
+
+ 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
+ }
+}
+
+#[cfg(feature = "deserialize_in_place")]
+fn deserialize_tuple_in_place(
+ params: &Parameters,
+ fields: &[Field],
+ cattrs: &attr::Container,
+) -> Fragment {
+ assert!(!cattrs.has_flatten());
+
+ 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) =
+ split_with_de_lifetime(params);
+ 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 ()>,
+ }
+
+ 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
+ }
+}
+
+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();
+ )),
+ attr::Default::Path(path) => Some(quote!(
+ 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();
+ )),
+ attr::Default::Path(path) => Some(quote!(
+ 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(())
+ }
+}
+
+fn deserialize_newtype_struct(
+ type_path: &TokenStream,
+ params: &Parameters,
+ field: &Field,
+) -> TokenStream {
+ let delife = params.borrowed.de_lifetime();
+ let field_ty = field.ty;
+
+ 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(__e)?
+ }
+ }
+ Some(path) => {
+ quote! {
+ #path(__e)?
+ }
+ }
+ };
+
+ 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, __e: __E) -> _serde::__private::Result<Self::Value, __E::Error>
+ where
+ __E: _serde::Deserializer<#delife>,
+ {
+ let __field0: #field_ty = #value;
+ _serde::__private::Ok(#result)
+ }
+ }
+}
+
+enum StructForm<'a> {
+ Struct,
+ /// Contains a variant name
+ ExternallyTagged(&'a syn::Ident),
+ /// Contains a variant name and an intermediate deserializer from which actual
+ /// deserialization will be performed
+ InternallyTagged(&'a syn::Ident, TokenStream),
+ /// Contains a variant name and an intermediate deserializer from which actual
+ /// deserialization will be performed
+ Untagged(&'a syn::Ident, TokenStream),
+}
+
+fn deserialize_struct(
+ 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) =
+ split_with_de_lifetime(params);
+ 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 field_names_idents: 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)| {
+ (
+ field.attrs.name().deserialize_name(),
+ field_i(i),
+ field.attrs.aliases(),
+ )
+ })
+ .collect();
+ let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs);
+
+ // 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 cattrs.has_flatten() => None,
+ _ => {
+ let mut_seq = if field_names_idents.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));
+
+ let visitor_seed = match form {
+ StructForm::ExternallyTagged(..) if cattrs.has_flatten() => Some(quote! {
+ 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 cattrs.has_flatten() {
+ None
+ } else {
+ let field_names = field_names_idents
+ .iter()
+ .flat_map(|&(_, _, aliases)| 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 cattrs.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 cattrs.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(_, deserializer) => quote! {
+ _serde::Deserializer::deserialize_any(#deserializer, #visitor_expr)
+ },
+ StructForm::Untagged(_, deserializer) => 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 ()>,
+ }
+
+ 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
+ }
+}
+
+#[cfg(feature = "deserialize_in_place")]
+fn deserialize_struct_in_place(
+ params: &Parameters,
+ fields: &[Field],
+ cattrs: &attr::Container,
+) -> Option<Fragment> {
+ // for now we do not support in_place deserialization for structs that
+ // are represented as map.
+ if cattrs.has_flatten() {
+ return None;
+ }
+
+ let this_type = &params.this_type;
+ let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
+ split_with_de_lifetime(params);
+ let delife = params.borrowed.de_lifetime();
+
+ let expecting = format!("struct {}", params.type_name());
+ let expecting = cattrs.expecting().unwrap_or(&expecting);
+
+ let field_names_idents: Vec<_> = fields
+ .iter()
+ .enumerate()
+ .filter(|&(_, field)| !field.attrs.skip_deserializing())
+ .map(|(i, field)| {
+ (
+ field.attrs.name().deserialize_name(),
+ field_i(i),
+ field.attrs.aliases(),
+ )
+ })
+ .collect();
+
+ let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs);
+
+ let mut_seq = if field_names_idents.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 = field_names_idents
+ .iter()
+ .flat_map(|&(_, _, aliases)| 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 ()>,
+ }
+
+ 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,
+ })
+ })
+}
+
+fn deserialize_enum(
+ 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));
+ deserialize_untagged_enum_after(params, untagged, cattrs, Some(tagged_frag))
+ }
+ 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 => deserialize_externally_tagged_enum(params, variants, cattrs),
+ attr::TagType::Internal { tag } => {
+ deserialize_internally_tagged_enum(params, variants, cattrs, tag)
+ }
+ attr::TagType::Adjacent { tag, content } => {
+ deserialize_adjacently_tagged_enum(params, variants, cattrs, tag, content)
+ }
+ attr::TagType::None => deserialize_untagged_enum(params, variants, cattrs),
+ }
+}
+
+fn prepare_enum_variant_enum(
+ variants: &[Variant],
+ cattrs: &attr::Container,
+) -> (TokenStream, Stmts) {
+ let mut deserialized_variants = variants
+ .iter()
+ .enumerate()
+ .filter(|&(_, variant)| !variant.attrs.skip_deserializing());
+
+ let variant_names_idents: Vec<_> = deserialized_variants
+ .clone()
+ .map(|(i, variant)| {
+ (
+ variant.attrs.name().deserialize_name(),
+ field_i(i),
+ variant.attrs.aliases(),
+ )
+ })
+ .collect();
+
+ let fallthrough = deserialized_variants
+ .position(|(_, variant)| variant.attrs.other())
+ .map(|other_idx| {
+ let ignore_variant = variant_names_idents[other_idx].1.clone();
+ quote!(_serde::__private::Ok(__Field::#ignore_variant))
+ });
+
+ let variants_stmt = {
+ let variant_names = variant_names_idents.iter().map(|(name, _, _)| name);
+ quote! {
+ #[doc(hidden)]
+ const VARIANTS: &'static [&'static str] = &[ #(#variant_names),* ];
+ }
+ };
+
+ let variant_visitor = Stmts(deserialize_generated_identifier(
+ &variant_names_idents,
+ cattrs,
+ true,
+ None,
+ fallthrough,
+ ));
+
+ (variants_stmt, variant_visitor)
+}
+
+fn deserialize_externally_tagged_enum(
+ 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) =
+ split_with_de_lifetime(params);
+ 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) = prepare_enum_variant_enum(variants, cattrs);
+
+ // 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 ()>,
+ }
+
+ 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_internally_tagged_enum(
+ params: &Parameters,
+ variants: &[Variant],
+ cattrs: &attr::Container,
+ tag: &str,
+) -> Fragment {
+ let (variants_stmt, variant_visitor) = prepare_enum_variant_enum(variants, cattrs);
+
+ // 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!(__deserializer),
+ ));
+
+ 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)*
+ }
+ }
+}
+
+fn deserialize_adjacently_tagged_enum(
+ 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) =
+ split_with_de_lifetime(params);
+ let delife = params.borrowed.de_lifetime();
+
+ let (variants_stmt, variant_visitor) = prepare_enum_variant_enum(variants, cattrs);
+
+ 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(deserialize_untagged_variant(
+ params,
+ variant,
+ cattrs,
+ quote!(__deserializer),
+ ));
+
+ 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 tag_or_content = quote! {
+ #field_visitor_ty {
+ tag: #tag,
+ content: #content,
+ }
+ };
+
+ let variant_seed = quote! {
+ _serde::__private::de::AdjacentlyTaggedEnumVariantSeed::<__Field> {
+ enum_name: #rust_name,
+ variants: VARIANTS,
+ fields_enum: _serde::__private::PhantomData
+ }
+ };
+
+ 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, #tag_or_content)?
+ };
+
+ let variant_from_map = quote! {
+ _serde::de::MapAccess::next_value_seed(&mut __map, #variant_seed)?
+ };
+
+ // 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 __ret = match #variant_from_map {
+ // Deserialize the buffered content now that we know the variant.
+ #(#variant_arms)*
+ }?;
+ // Visit remaining keys, looking for duplicates.
+ #visit_remaining_keys
+ }
+ };
+
+ quote_block! {
+ #variant_visitor
+
+ #variants_stmt
+
+ #[doc(hidden)]
+ struct __Seed #de_impl_generics #where_clause {
+ field: __Field,
+ marker: _serde::__private::PhantomData<#this_type #ty_generics>,
+ lifetime: _serde::__private::PhantomData<&#delife ()>,
+ }
+
+ 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.field {
+ #(#variant_arms)*
+ }
+ }
+ }
+
+ #[doc(hidden)]
+ struct __Visitor #de_impl_generics #where_clause {
+ marker: _serde::__private::PhantomData<#this_type #ty_generics>,
+ lifetime: _serde::__private::PhantomData<&#delife ()>,
+ }
+
+ 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 {
+ field: __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::<_serde::__private::de::Content>(&mut __map)?;
+ // Visit the second key.
+ match #next_relevant_key {
+ // Second key is the tag.
+ _serde::__private::Some(_serde::__private::de::TagOrContentField::Tag) => {
+ let __deserializer = _serde::__private::de::ContentDeserializer::<__A::Error>::new(__content);
+ #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(__field) => {
+ // Visit the second element - the content.
+ match _serde::de::SeqAccess::next_element_seed(
+ &mut __seq,
+ __Seed {
+ field: __field,
+ 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,
+ },
+ )
+ }
+}
+
+fn deserialize_untagged_enum(
+ params: &Parameters,
+ variants: &[Variant],
+ cattrs: &attr::Container,
+) -> Fragment {
+ let first_attempt = None;
+ deserialize_untagged_enum_after(params, variants, cattrs, first_attempt)
+}
+
+fn deserialize_untagged_enum_after(
+ params: &Parameters,
+ variants: &[Variant],
+ cattrs: &attr::Container,
+ first_attempt: Option<Expr>,
+) -> Fragment {
+ let attempts = variants
+ .iter()
+ .filter(|variant| !variant.attrs.skip_deserializing())
+ .map(|variant| {
+ Expr(deserialize_untagged_variant(
+ params,
+ variant,
+ cattrs,
+ quote!(__deserializer),
+ ))
+ });
+ // 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);
+
+ // 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 = first_attempt.map(|expr| {
+ quote! {
+ if let _serde::__private::Result::<_, __D::Error>::Ok(__ok) = (|| #expr)() {
+ return _serde::__private::Ok(__ok);
+ }
+ }
+ });
+
+ quote_block! {
+ let __content = <_serde::__private::de::Content as _serde::Deserialize>::deserialize(__deserializer)?;
+ let __deserializer = _serde::__private::de::ContentRefDeserializer::<__D::Error>::new(&__content);
+
+ #first_attempt
+
+ #(
+ if let _serde::__private::Ok(__ok) = #attempts {
+ return _serde::__private::Ok(__ok);
+ }
+ )*
+
+ _serde::__private::Err(_serde::de::Error::custom(#fallthrough_msg))
+ }
+}
+
+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 => deserialize_tuple(
+ params,
+ &variant.fields,
+ cattrs,
+ TupleForm::ExternallyTagged(variant_ident),
+ ),
+ Style::Struct => deserialize_struct(
+ params,
+ &variant.fields,
+ cattrs,
+ StructForm::ExternallyTagged(variant_ident),
+ ),
+ }
+}
+
+// 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,
+ deserializer: TokenStream,
+) -> Fragment {
+ if variant.attrs.deserialize_with().is_some() {
+ return deserialize_untagged_variant(params, variant, cattrs, deserializer);
+ }
+
+ 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 => deserialize_untagged_newtype_variant(
+ variant_ident,
+ params,
+ &variant.fields[0],
+ &deserializer,
+ ),
+ Style::Struct => deserialize_struct(
+ params,
+ &variant.fields,
+ cattrs,
+ StructForm::InternallyTagged(variant_ident, deserializer),
+ ),
+ Style::Tuple => unreachable!("checked in serde_derive_internals"),
+ }
+}
+
+fn deserialize_untagged_variant(
+ params: &Parameters,
+ variant: &Variant,
+ cattrs: &attr::Container,
+ deserializer: TokenStream,
+) -> 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_untagged_newtype_variant(
+ variant_ident,
+ params,
+ &variant.fields[0],
+ &deserializer,
+ ),
+ Style::Tuple => deserialize_tuple(
+ params,
+ &variant.fields,
+ cattrs,
+ TupleForm::Untagged(variant_ident, deserializer),
+ ),
+ Style::Struct => deserialize_struct(
+ params,
+ &variant.fields,
+ cattrs,
+ StructForm::Untagged(variant_ident, deserializer),
+ ),
+ }
+}
+
+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))
+ }
+ }
+ }
+}
+
+fn deserialize_untagged_newtype_variant(
+ variant_ident: &syn::Ident,
+ params: &Parameters,
+ field: &Field,
+ deserializer: &TokenStream,
+) -> 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)
+ }
+ }
+ }
+}
+
+fn deserialize_generated_identifier(
+ fields: &[(&str, Ident, &BTreeSet<String>)],
+ cattrs: &attr::Container,
+ is_variant: bool,
+ ignore_variant: Option<TokenStream>,
+ fallthrough: Option<TokenStream>,
+) -> Fragment {
+ let this_value = quote!(__Field);
+ let field_idents: &Vec<_> = &fields.iter().map(|(_, ident, _)| ident).collect();
+
+ let visitor_impl = Stmts(deserialize_identifier(
+ &this_value,
+ fields,
+ is_variant,
+ fallthrough,
+ None,
+ !is_variant && cattrs.has_flatten(),
+ None,
+ ));
+
+ let lifetime = if !is_variant && cattrs.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;
+
+ impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
+ type Value = __Field #lifetime;
+
+ #visitor_impl
+ }
+
+ 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)
+ }
+ }
+ }
+}
+
+/// Generates enum and its `Deserialize` implementation that represents each
+/// non-skipped field of the struct
+fn deserialize_field_identifier(
+ fields: &[(&str, Ident, &BTreeSet<String>)],
+ cattrs: &attr::Container,
+) -> Stmts {
+ let (ignore_variant, fallthrough) = if cattrs.has_flatten() {
+ let ignore_variant = quote!(__other(_serde::__private::de::Content<'de>),);
+ let fallthrough = quote!(_serde::__private::Ok(__Field::__other(__value)));
+ (Some(ignore_variant), Some(fallthrough))
+ } else if cattrs.deny_unknown_fields() {
+ (None, None)
+ } else {
+ let ignore_variant = quote!(__ignore,);
+ let fallthrough = quote!(_serde::__private::Ok(__Field::__ignore));
+ (Some(ignore_variant), Some(fallthrough))
+ };
+
+ Stmts(deserialize_generated_identifier(
+ fields,
+ cattrs,
+ false,
+ ignore_variant,
+ fallthrough,
+ ))
+}
+
+// Generates `Deserialize::deserialize` body for an enum with
+// `serde(field_identifier)` or `serde(variant_identifier)` attribute.
+fn deserialize_custom_identifier(
+ 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 names_idents: Vec<_> = ordinary
+ .iter()
+ .map(|variant| {
+ (
+ variant.attrs.name().deserialize_name(),
+ variant.ident.clone(),
+ variant.attrs.aliases(),
+ )
+ })
+ .collect();
+
+ let names = names_idents.iter().flat_map(|&(_, _, aliases)| 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) =
+ split_with_de_lifetime(params);
+ let delife = params.borrowed.de_lifetime();
+ let visitor_impl = Stmts(deserialize_identifier(
+ &this_value,
+ &names_idents,
+ 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 ()>,
+ }
+
+ 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)
+ }
+}
+
+fn deserialize_identifier(
+ this_value: &TokenStream,
+ fields: &[(&str, Ident, &BTreeSet<String>)],
+ is_variant: bool,
+ fallthrough: Option<TokenStream>,
+ fallthrough_borrowed: Option<TokenStream>,
+ collect_other_fields: bool,
+ expecting: Option<&str>,
+) -> Fragment {
+ let str_mapping = fields.iter().map(|(_, ident, aliases)| {
+ // `aliases` also contains a main name
+ quote!(#(#aliases)|* => _serde::__private::Ok(#this_value::#ident))
+ });
+ let bytes_mapping = fields.iter().map(|(_, ident, aliases)| {
+ // `aliases` also contains a main name
+ let aliases = aliases
+ .iter()
+ .map(|alias| Literal::byte_string(alias.as_bytes()));
+ quote!(#(#aliases)|* => _serde::__private::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 = fields.iter().enumerate().map(|(i, (_, ident, _))| {
+ let i = i as u64;
+ 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, 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
+ }
+}
+
+fn deserialize_map(
+ struct_path: &TokenStream,
+ params: &Parameters,
+ fields: &[Field],
+ cattrs: &attr::Container,
+) -> 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 cattrs.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 cattrs.has_flatten() {
+ Some(quote! {
+ __Field::__other(__name) => {
+ __collect.push(_serde::__private::Some((
+ __name,
+ _serde::de::MapAccess::next_value(&mut __map)?)));
+ }
+ })
+ } 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 cattrs.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) = __key.as_str() {
+ 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();
+ )),
+ attr::Default::Path(path) => Some(quote!(
+ 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)
+ }
+}
+
+#[cfg(feature = "deserialize_in_place")]
+fn deserialize_map_in_place(
+ params: &Parameters,
+ fields: &[Field],
+ cattrs: &attr::Container,
+) -> Fragment {
+ assert!(!cattrs.has_flatten());
+
+ // 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, _) = split_with_de_lifetime(params);
+
+ let let_default = match cattrs.default() {
+ attr::Default::Default => Some(quote!(
+ let __default: #this_type #ty_generics = _serde::__private::Default::default();
+ )),
+ attr::Default::Path(path) => Some(quote!(
+ let __default: #this_type #ty_generics = #path();
+ )),
+ attr::Default::None => {
+ // We don't need the default value, to prevent an unused variable warning
+ // we'll leave the line empty.
+ None
+ }
+ };
+
+ quote_block! {
+ #(#let_flags)*
+
+ #match_keys
+
+ #let_default
+
+ #(#check_flags)*
+
+ _serde::__private::Ok(())
+ }
+}
+
+fn field_i(i: usize) -> Ident {
+ 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) =
+ split_with_de_lifetime(params);
+ let delife = params.borrowed.de_lifetime();
+
+ 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 ()>,
+ }
+
+ impl #de_impl_generics _serde::Deserialize<#delife> for __DeserializeWith #de_ty_generics #where_clause {
+ fn deserialize<__D>(__deserializer: __D) -> _serde::__private::Result<Self, __D::Error>
+ where
+ __D: _serde::Deserializer<#delife>,
+ {
+ _serde::__private::Ok(__DeserializeWith {
+ value: #deserialize_with(__deserializer)?,
+ 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)
+}
+
+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)
+}
+
+// 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) => {
+ return quote_expr!(#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) => {
+ 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,
+ }
+}
+
+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(),
+ }
+}
+
+fn split_with_de_lifetime(
+ params: &Parameters,
+) -> (
+ DeImplGenerics,
+ DeTypeGenerics,
+ syn::TypeGenerics,
+ Option<&syn::WhereClause>,
+) {
+ let de_impl_generics = DeImplGenerics(params);
+ let de_ty_generics = DeTypeGenerics(params);
+ let (_, ty_generics, where_clause) = params.generics.split_for_impl();
+ (de_impl_generics, de_ty_generics, ty_generics, where_clause)
+}
diff --git a/third_party/rust/serde_derive/src/dummy.rs b/third_party/rust/serde_derive/src/dummy.rs
new file mode 100644
index 0000000000..095f950f3e
--- /dev/null
+++ b/third_party/rust/serde_derive/src/dummy.rs
@@ -0,0 +1,23 @@
+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)]
+ const _: () = {
+ #use_serde
+ #code
+ };
+ }
+}
diff --git a/third_party/rust/serde_derive/src/fragment.rs b/third_party/rust/serde_derive/src/fragment.rs
new file mode 100644
index 0000000000..6627c26699
--- /dev/null
+++ b/third_party/rust/serde_derive/src/fragment.rs
@@ -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,
+ }
+ }
+}
diff --git a/third_party/rust/serde_derive/src/internals/ast.rs b/third_party/rust/serde_derive/src/internals/ast.rs
new file mode 100644
index 0000000000..a28d3ae7e9
--- /dev/null
+++ b/third_party/rust/serde_derive/src/internals/ast.rs
@@ -0,0 +1,216 @@
+//! A Serde ast, parsed from the Syn ast and ready to generate Rust code.
+
+use crate::internals::{attr, check, Ctxt, Derive};
+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,
+ ) -> Option<Container<'a>> {
+ let mut 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())),
+ syn::Data::Struct(data) => {
+ let (style, fields) = struct_from_ast(cx, &data.fields, None, attrs.default());
+ Data::Struct(style, fields)
+ }
+ syn::Data::Union(_) => {
+ cx.error_spanned_by(item, "Serde does not support derive for unions");
+ return None;
+ }
+ };
+
+ let mut has_flatten = false;
+ 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 {
+ if field.attrs.flatten() {
+ has_flatten = true;
+ }
+ field.attrs.rename_by_rules(
+ variant
+ .attrs
+ .rename_all_rules()
+ .or(attrs.rename_all_fields_rules()),
+ );
+ }
+ }
+ }
+ Data::Struct(_, fields) => {
+ for field in fields {
+ if field.attrs.flatten() {
+ has_flatten = true;
+ }
+ field.attrs.rename_by_rules(attrs.rename_all_rules());
+ }
+ }
+ }
+
+ if has_flatten {
+ attrs.mark_has_flatten();
+ }
+
+ 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,
+) -> 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);
+ 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,
+) -> (Style, Vec<Field<'a>>) {
+ match fields {
+ syn::Fields::Named(fields) => (
+ Style::Struct,
+ fields_from_ast(cx, &fields.named, attrs, container_default),
+ ),
+ syn::Fields::Unnamed(fields) if fields.unnamed.len() == 1 => (
+ Style::Newtype,
+ fields_from_ast(cx, &fields.unnamed, attrs, container_default),
+ ),
+ syn::Fields::Unnamed(fields) => (
+ Style::Tuple,
+ fields_from_ast(cx, &fields.unnamed, attrs, container_default),
+ ),
+ 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,
+) -> 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),
+ ty: &field.ty,
+ original: field,
+ })
+ .collect()
+}
diff --git a/third_party/rust/serde_derive/src/internals/attr.rs b/third_party/rust/serde_derive/src/internals/attr.rs
new file mode 100644
index 0000000000..bb9de328a6
--- /dev/null
+++ b/third_party/rust/serde_derive/src/internals/attr.rs
@@ -0,0 +1,1881 @@
+use crate::internals::symbol::*;
+use crate::internals::{ungroup, Ctxt};
+use proc_macro2::{Spacing, Span, TokenStream, TokenTree};
+use quote::ToTokens;
+use std::borrow::Cow;
+use std::collections::BTreeSet;
+use std::iter::FromIterator;
+use syn::meta::ParseNestedMeta;
+use syn::parse::ParseStream;
+use syn::punctuated::Punctuated;
+use syn::{parse_quote, token, Ident, Lifetime, Token};
+
+// This module handles parsing of `#[serde(...)]` attributes. The entrypoints
+// are `attr::Container::from_ast`, `attr::Variant::from_ast`, and
+// `attr::Field::from_ast`. Each returns an instance of the corresponding
+// struct. Note that none of them return a Result. Unrecognized, malformed, or
+// duplicated attributes result in a span_err but otherwise are ignored. The
+// user will see errors simultaneously for all bad attributes in the crate
+// rather than just the first.
+
+pub use crate::internals::case::RenameRule;
+
+struct Attr<'c, T> {
+ cx: &'c Ctxt,
+ name: Symbol,
+ tokens: TokenStream,
+ value: Option<T>,
+}
+
+impl<'c, T> Attr<'c, T> {
+ fn none(cx: &'c Ctxt, name: Symbol) -> Self {
+ Attr {
+ cx,
+ name,
+ tokens: TokenStream::new(),
+ value: None,
+ }
+ }
+
+ fn set<A: ToTokens>(&mut self, obj: A, value: T) {
+ let tokens = obj.into_token_stream();
+
+ if self.value.is_some() {
+ let msg = format!("duplicate serde attribute `{}`", self.name);
+ self.cx.error_spanned_by(tokens, msg);
+ } else {
+ self.tokens = tokens;
+ self.value = Some(value);
+ }
+ }
+
+ fn set_opt<A: ToTokens>(&mut self, obj: A, value: Option<T>) {
+ if let Some(value) = value {
+ self.set(obj, value);
+ }
+ }
+
+ fn set_if_none(&mut self, value: T) {
+ if self.value.is_none() {
+ self.value = Some(value);
+ }
+ }
+
+ fn get(self) -> Option<T> {
+ self.value
+ }
+
+ fn get_with_tokens(self) -> Option<(TokenStream, T)> {
+ match self.value {
+ Some(v) => Some((self.tokens, v)),
+ None => None,
+ }
+ }
+}
+
+struct BoolAttr<'c>(Attr<'c, ()>);
+
+impl<'c> BoolAttr<'c> {
+ fn none(cx: &'c Ctxt, name: Symbol) -> Self {
+ BoolAttr(Attr::none(cx, name))
+ }
+
+ fn set_true<A: ToTokens>(&mut self, obj: A) {
+ self.0.set(obj, ());
+ }
+
+ fn get(&self) -> bool {
+ self.0.value.is_some()
+ }
+}
+
+struct VecAttr<'c, T> {
+ cx: &'c Ctxt,
+ name: Symbol,
+ first_dup_tokens: TokenStream,
+ values: Vec<T>,
+}
+
+impl<'c, T> VecAttr<'c, T> {
+ fn none(cx: &'c Ctxt, name: Symbol) -> Self {
+ VecAttr {
+ cx,
+ name,
+ first_dup_tokens: TokenStream::new(),
+ values: Vec::new(),
+ }
+ }
+
+ fn insert<A: ToTokens>(&mut self, obj: A, value: T) {
+ if self.values.len() == 1 {
+ self.first_dup_tokens = obj.into_token_stream();
+ }
+ self.values.push(value);
+ }
+
+ fn at_most_one(mut self) -> Option<T> {
+ if self.values.len() > 1 {
+ let dup_token = self.first_dup_tokens;
+ let msg = format!("duplicate serde attribute `{}`", self.name);
+ self.cx.error_spanned_by(dup_token, msg);
+ None
+ } else {
+ self.values.pop()
+ }
+ }
+
+ fn get(self) -> Vec<T> {
+ self.values
+ }
+}
+
+pub struct Name {
+ serialize: String,
+ serialize_renamed: bool,
+ deserialize: String,
+ deserialize_renamed: bool,
+ deserialize_aliases: BTreeSet<String>,
+}
+
+fn unraw(ident: &Ident) -> String {
+ ident.to_string().trim_start_matches("r#").to_owned()
+}
+
+impl Name {
+ fn from_attrs(
+ source_name: String,
+ ser_name: Attr<String>,
+ de_name: Attr<String>,
+ de_aliases: Option<VecAttr<String>>,
+ ) -> Name {
+ 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();
+ Name {
+ 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) -> &str {
+ &self.serialize
+ }
+
+ /// Return the container name for the container when deserializing.
+ pub fn deserialize_name(&self) -> &str {
+ &self.deserialize
+ }
+
+ fn deserialize_aliases(&self) -> &BTreeSet<String> {
+ &self.deserialize_aliases
+ }
+}
+
+#[derive(Copy, Clone)]
+pub struct RenameAllRules {
+ serialize: RenameRule,
+ deserialize: RenameRule,
+}
+
+impl RenameAllRules {
+ /// Returns a new `RenameAllRules` with the individual rules of `self` and
+ /// `other_rules` joined by `RenameRules::or`.
+ pub fn or(self, other_rules: Self) -> Self {
+ Self {
+ serialize: self.serialize.or(other_rules.serialize),
+ deserialize: self.deserialize.or(other_rules.deserialize),
+ }
+ }
+}
+
+/// Represents struct or enum attribute information.
+pub struct Container {
+ name: Name,
+ transparent: bool,
+ deny_unknown_fields: bool,
+ default: Default,
+ rename_all_rules: RenameAllRules,
+ rename_all_fields_rules: RenameAllRules,
+ ser_bound: Option<Vec<syn::WherePredicate>>,
+ de_bound: Option<Vec<syn::WherePredicate>>,
+ tag: TagType,
+ type_from: Option<syn::Type>,
+ type_try_from: Option<syn::Type>,
+ type_into: Option<syn::Type>,
+ remote: Option<syn::Path>,
+ identifier: Identifier,
+ has_flatten: bool,
+ serde_path: Option<syn::Path>,
+ is_packed: bool,
+ /// Error message generated when type can't be deserialized
+ expecting: Option<String>,
+ non_exhaustive: bool,
+}
+
+/// Styles of representing an enum.
+pub enum TagType {
+ /// The default.
+ ///
+ /// ```json
+ /// {"variant1": {"key1": "value1", "key2": "value2"}}
+ /// ```
+ External,
+
+ /// `#[serde(tag = "type")]`
+ ///
+ /// ```json
+ /// {"type": "variant1", "key1": "value1", "key2": "value2"}
+ /// ```
+ Internal { tag: String },
+
+ /// `#[serde(tag = "t", content = "c")]`
+ ///
+ /// ```json
+ /// {"t": "variant1", "c": {"key1": "value1", "key2": "value2"}}
+ /// ```
+ Adjacent { tag: String, content: String },
+
+ /// `#[serde(untagged)]`
+ ///
+ /// ```json
+ /// {"key1": "value1", "key2": "value2"}
+ /// ```
+ None,
+}
+
+/// Whether this enum represents the fields of a struct or the variants of an
+/// enum.
+#[derive(Copy, Clone)]
+pub enum Identifier {
+ /// It does not.
+ No,
+
+ /// This enum represents the fields of a struct. All of the variants must be
+ /// unit variants, except possibly one which is annotated with
+ /// `#[serde(other)]` and is a newtype variant.
+ Field,
+
+ /// This enum represents the variants of an enum. All of the variants must
+ /// be unit variants.
+ Variant,
+}
+
+impl Identifier {
+ #[cfg(feature = "deserialize_in_place")]
+ pub fn is_some(self) -> bool {
+ match self {
+ Identifier::No => false,
+ Identifier::Field | Identifier::Variant => true,
+ }
+ }
+}
+
+impl Container {
+ /// Extract out the `#[serde(...)]` attributes from an item.
+ pub fn from_ast(cx: &Ctxt, item: &syn::DeriveInput) -> Self {
+ let mut ser_name = Attr::none(cx, RENAME);
+ let mut de_name = Attr::none(cx, RENAME);
+ let mut transparent = BoolAttr::none(cx, TRANSPARENT);
+ let mut deny_unknown_fields = BoolAttr::none(cx, DENY_UNKNOWN_FIELDS);
+ let mut default = Attr::none(cx, DEFAULT);
+ let mut rename_all_ser_rule = Attr::none(cx, RENAME_ALL);
+ let mut rename_all_de_rule = Attr::none(cx, RENAME_ALL);
+ let mut rename_all_fields_ser_rule = Attr::none(cx, RENAME_ALL_FIELDS);
+ let mut rename_all_fields_de_rule = Attr::none(cx, RENAME_ALL_FIELDS);
+ let mut ser_bound = Attr::none(cx, BOUND);
+ let mut de_bound = Attr::none(cx, BOUND);
+ let mut untagged = BoolAttr::none(cx, UNTAGGED);
+ let mut internal_tag = Attr::none(cx, TAG);
+ let mut content = Attr::none(cx, CONTENT);
+ let mut type_from = Attr::none(cx, FROM);
+ let mut type_try_from = Attr::none(cx, TRY_FROM);
+ let mut type_into = Attr::none(cx, INTO);
+ let mut remote = Attr::none(cx, REMOTE);
+ let mut field_identifier = BoolAttr::none(cx, FIELD_IDENTIFIER);
+ let mut variant_identifier = BoolAttr::none(cx, VARIANT_IDENTIFIER);
+ let mut serde_path = Attr::none(cx, CRATE);
+ let mut expecting = Attr::none(cx, EXPECTING);
+ let mut non_exhaustive = false;
+
+ for attr in &item.attrs {
+ if attr.path() != SERDE {
+ non_exhaustive |=
+ matches!(&attr.meta, syn::Meta::Path(path) if path == NON_EXHAUSTIVE);
+ continue;
+ }
+
+ if let syn::Meta::List(meta) = &attr.meta {
+ if meta.tokens.is_empty() {
+ continue;
+ }
+ }
+
+ if let Err(err) = attr.parse_nested_meta(|meta| {
+ if meta.path == RENAME {
+ // #[serde(rename = "foo")]
+ // #[serde(rename(serialize = "foo", deserialize = "bar"))]
+ let (ser, de) = get_renames(cx, RENAME, &meta)?;
+ ser_name.set_opt(&meta.path, ser.as_ref().map(syn::LitStr::value));
+ de_name.set_opt(&meta.path, de.as_ref().map(syn::LitStr::value));
+ } else if meta.path == RENAME_ALL {
+ // #[serde(rename_all = "foo")]
+ // #[serde(rename_all(serialize = "foo", deserialize = "bar"))]
+ let one_name = meta.input.peek(Token![=]);
+ let (ser, de) = get_renames(cx, RENAME_ALL, &meta)?;
+ if let Some(ser) = ser {
+ match RenameRule::from_str(&ser.value()) {
+ Ok(rename_rule) => rename_all_ser_rule.set(&meta.path, rename_rule),
+ Err(err) => cx.error_spanned_by(ser, err),
+ }
+ }
+ if let Some(de) = de {
+ match RenameRule::from_str(&de.value()) {
+ Ok(rename_rule) => rename_all_de_rule.set(&meta.path, rename_rule),
+ Err(err) => {
+ if !one_name {
+ cx.error_spanned_by(de, err);
+ }
+ }
+ }
+ }
+ } else if meta.path == RENAME_ALL_FIELDS {
+ // #[serde(rename_all_fields = "foo")]
+ // #[serde(rename_all_fields(serialize = "foo", deserialize = "bar"))]
+ let one_name = meta.input.peek(Token![=]);
+ let (ser, de) = get_renames(cx, RENAME_ALL_FIELDS, &meta)?;
+
+ match item.data {
+ syn::Data::Enum(_) => {
+ if let Some(ser) = ser {
+ match RenameRule::from_str(&ser.value()) {
+ Ok(rename_rule) => {
+ rename_all_fields_ser_rule.set(&meta.path, rename_rule);
+ }
+ Err(err) => cx.error_spanned_by(ser, err),
+ }
+ }
+ if let Some(de) = de {
+ match RenameRule::from_str(&de.value()) {
+ Ok(rename_rule) => {
+ rename_all_fields_de_rule.set(&meta.path, rename_rule);
+ }
+ Err(err) => {
+ if !one_name {
+ cx.error_spanned_by(de, err);
+ }
+ }
+ }
+ }
+ }
+ syn::Data::Struct(_) => {
+ let msg = "#[serde(rename_all_fields)] can only be used on enums";
+ cx.syn_error(meta.error(msg));
+ }
+ syn::Data::Union(_) => {
+ let msg = "#[serde(rename_all_fields)] can only be used on enums";
+ cx.syn_error(meta.error(msg));
+ }
+ }
+ } else if meta.path == TRANSPARENT {
+ // #[serde(transparent)]
+ transparent.set_true(meta.path);
+ } else if meta.path == DENY_UNKNOWN_FIELDS {
+ // #[serde(deny_unknown_fields)]
+ deny_unknown_fields.set_true(meta.path);
+ } else if meta.path == DEFAULT {
+ if meta.input.peek(Token![=]) {
+ // #[serde(default = "...")]
+ if let Some(path) = parse_lit_into_expr_path(cx, DEFAULT, &meta)? {
+ match &item.data {
+ syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields {
+ syn::Fields::Named(_) | syn::Fields::Unnamed(_) => {
+ default.set(&meta.path, Default::Path(path));
+ }
+ syn::Fields::Unit => {
+ let msg = "#[serde(default = \"...\")] can only be used on structs that have fields";
+ cx.syn_error(meta.error(msg));
+ }
+ },
+ syn::Data::Enum(_) => {
+ let msg = "#[serde(default = \"...\")] can only be used on structs";
+ cx.syn_error(meta.error(msg));
+ }
+ syn::Data::Union(_) => {
+ let msg = "#[serde(default = \"...\")] can only be used on structs";
+ cx.syn_error(meta.error(msg));
+ }
+ }
+ }
+ } else {
+ // #[serde(default)]
+ match &item.data {
+ syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields {
+ syn::Fields::Named(_) | syn::Fields::Unnamed(_) => {
+ default.set(meta.path, Default::Default);
+ }
+ syn::Fields::Unit => {
+ let msg = "#[serde(default)] can only be used on structs that have fields";
+ cx.error_spanned_by(fields, msg);
+ }
+ },
+ syn::Data::Enum(_) => {
+ let msg = "#[serde(default)] can only be used on structs";
+ cx.syn_error(meta.error(msg));
+ }
+ syn::Data::Union(_) => {
+ let msg = "#[serde(default)] can only be used on structs";
+ cx.syn_error(meta.error(msg));
+ }
+ }
+ }
+ } else if meta.path == BOUND {
+ // #[serde(bound = "T: SomeBound")]
+ // #[serde(bound(serialize = "...", deserialize = "..."))]
+ let (ser, de) = get_where_predicates(cx, &meta)?;
+ ser_bound.set_opt(&meta.path, ser);
+ de_bound.set_opt(&meta.path, de);
+ } else if meta.path == UNTAGGED {
+ // #[serde(untagged)]
+ match item.data {
+ syn::Data::Enum(_) => {
+ untagged.set_true(&meta.path);
+ }
+ syn::Data::Struct(_) => {
+ let msg = "#[serde(untagged)] can only be used on enums";
+ cx.syn_error(meta.error(msg));
+ }
+ syn::Data::Union(_) => {
+ let msg = "#[serde(untagged)] can only be used on enums";
+ cx.syn_error(meta.error(msg));
+ }
+ }
+ } else if meta.path == TAG {
+ // #[serde(tag = "type")]
+ if let Some(s) = get_lit_str(cx, TAG, &meta)? {
+ match &item.data {
+ syn::Data::Enum(_) => {
+ internal_tag.set(&meta.path, s.value());
+ }
+ syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields {
+ syn::Fields::Named(_) => {
+ internal_tag.set(&meta.path, s.value());
+ }
+ syn::Fields::Unnamed(_) | syn::Fields::Unit => {
+ let msg = "#[serde(tag = \"...\")] can only be used on enums and structs with named fields";
+ cx.syn_error(meta.error(msg));
+ }
+ },
+ syn::Data::Union(_) => {
+ let msg = "#[serde(tag = \"...\")] can only be used on enums and structs with named fields";
+ cx.syn_error(meta.error(msg));
+ }
+ }
+ }
+ } else if meta.path == CONTENT {
+ // #[serde(content = "c")]
+ if let Some(s) = get_lit_str(cx, CONTENT, &meta)? {
+ match &item.data {
+ syn::Data::Enum(_) => {
+ content.set(&meta.path, s.value());
+ }
+ syn::Data::Struct(_) => {
+ let msg = "#[serde(content = \"...\")] can only be used on enums";
+ cx.syn_error(meta.error(msg));
+ }
+ syn::Data::Union(_) => {
+ let msg = "#[serde(content = \"...\")] can only be used on enums";
+ cx.syn_error(meta.error(msg));
+ }
+ }
+ }
+ } else if meta.path == FROM {
+ // #[serde(from = "Type")]
+ if let Some(from_ty) = parse_lit_into_ty(cx, FROM, &meta)? {
+ type_from.set_opt(&meta.path, Some(from_ty));
+ }
+ } else if meta.path == TRY_FROM {
+ // #[serde(try_from = "Type")]
+ if let Some(try_from_ty) = parse_lit_into_ty(cx, TRY_FROM, &meta)? {
+ type_try_from.set_opt(&meta.path, Some(try_from_ty));
+ }
+ } else if meta.path == INTO {
+ // #[serde(into = "Type")]
+ if let Some(into_ty) = parse_lit_into_ty(cx, INTO, &meta)? {
+ type_into.set_opt(&meta.path, Some(into_ty));
+ }
+ } else if meta.path == REMOTE {
+ // #[serde(remote = "...")]
+ if let Some(path) = parse_lit_into_path(cx, REMOTE, &meta)? {
+ if is_primitive_path(&path, "Self") {
+ remote.set(&meta.path, item.ident.clone().into());
+ } else {
+ remote.set(&meta.path, path);
+ }
+ }
+ } else if meta.path == FIELD_IDENTIFIER {
+ // #[serde(field_identifier)]
+ field_identifier.set_true(&meta.path);
+ } else if meta.path == VARIANT_IDENTIFIER {
+ // #[serde(variant_identifier)]
+ variant_identifier.set_true(&meta.path);
+ } else if meta.path == CRATE {
+ // #[serde(crate = "foo")]
+ if let Some(path) = parse_lit_into_path(cx, CRATE, &meta)? {
+ serde_path.set(&meta.path, path);
+ }
+ } else if meta.path == EXPECTING {
+ // #[serde(expecting = "a message")]
+ if let Some(s) = get_lit_str(cx, EXPECTING, &meta)? {
+ expecting.set(&meta.path, s.value());
+ }
+ } else {
+ let path = meta.path.to_token_stream().to_string().replace(' ', "");
+ return Err(
+ meta.error(format_args!("unknown serde container attribute `{}`", path))
+ );
+ }
+ Ok(())
+ }) {
+ cx.syn_error(err);
+ }
+ }
+
+ let mut is_packed = false;
+ for attr in &item.attrs {
+ if attr.path() == REPR {
+ let _ = attr.parse_args_with(|input: ParseStream| {
+ while let Some(token) = input.parse()? {
+ if let TokenTree::Ident(ident) = token {
+ is_packed |= ident == "packed";
+ }
+ }
+ Ok(())
+ });
+ }
+ }
+
+ Container {
+ name: Name::from_attrs(unraw(&item.ident), ser_name, de_name, None),
+ transparent: transparent.get(),
+ deny_unknown_fields: deny_unknown_fields.get(),
+ default: default.get().unwrap_or(Default::None),
+ rename_all_rules: RenameAllRules {
+ serialize: rename_all_ser_rule.get().unwrap_or(RenameRule::None),
+ deserialize: rename_all_de_rule.get().unwrap_or(RenameRule::None),
+ },
+ rename_all_fields_rules: RenameAllRules {
+ serialize: rename_all_fields_ser_rule.get().unwrap_or(RenameRule::None),
+ deserialize: rename_all_fields_de_rule.get().unwrap_or(RenameRule::None),
+ },
+ ser_bound: ser_bound.get(),
+ de_bound: de_bound.get(),
+ tag: decide_tag(cx, item, untagged, internal_tag, content),
+ type_from: type_from.get(),
+ type_try_from: type_try_from.get(),
+ type_into: type_into.get(),
+ remote: remote.get(),
+ identifier: decide_identifier(cx, item, field_identifier, variant_identifier),
+ has_flatten: false,
+ serde_path: serde_path.get(),
+ is_packed,
+ expecting: expecting.get(),
+ non_exhaustive,
+ }
+ }
+
+ pub fn name(&self) -> &Name {
+ &self.name
+ }
+
+ pub fn rename_all_rules(&self) -> RenameAllRules {
+ self.rename_all_rules
+ }
+
+ pub fn rename_all_fields_rules(&self) -> RenameAllRules {
+ self.rename_all_fields_rules
+ }
+
+ pub fn transparent(&self) -> bool {
+ self.transparent
+ }
+
+ pub fn deny_unknown_fields(&self) -> bool {
+ self.deny_unknown_fields
+ }
+
+ pub fn default(&self) -> &Default {
+ &self.default
+ }
+
+ pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> {
+ self.ser_bound.as_ref().map(|vec| &vec[..])
+ }
+
+ pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> {
+ self.de_bound.as_ref().map(|vec| &vec[..])
+ }
+
+ pub fn tag(&self) -> &TagType {
+ &self.tag
+ }
+
+ pub fn type_from(&self) -> Option<&syn::Type> {
+ self.type_from.as_ref()
+ }
+
+ pub fn type_try_from(&self) -> Option<&syn::Type> {
+ self.type_try_from.as_ref()
+ }
+
+ pub fn type_into(&self) -> Option<&syn::Type> {
+ self.type_into.as_ref()
+ }
+
+ pub fn remote(&self) -> Option<&syn::Path> {
+ self.remote.as_ref()
+ }
+
+ pub fn is_packed(&self) -> bool {
+ self.is_packed
+ }
+
+ pub fn identifier(&self) -> Identifier {
+ self.identifier
+ }
+
+ pub fn has_flatten(&self) -> bool {
+ self.has_flatten
+ }
+
+ pub fn mark_has_flatten(&mut self) {
+ self.has_flatten = true;
+ }
+
+ pub fn custom_serde_path(&self) -> Option<&syn::Path> {
+ self.serde_path.as_ref()
+ }
+
+ pub fn serde_path(&self) -> Cow<syn::Path> {
+ self.custom_serde_path()
+ .map_or_else(|| Cow::Owned(parse_quote!(_serde)), Cow::Borrowed)
+ }
+
+ /// Error message generated when type can't be deserialized.
+ /// If `None`, default message will be used
+ pub fn expecting(&self) -> Option<&str> {
+ self.expecting.as_ref().map(String::as_ref)
+ }
+
+ pub fn non_exhaustive(&self) -> bool {
+ self.non_exhaustive
+ }
+}
+
+fn decide_tag(
+ cx: &Ctxt,
+ item: &syn::DeriveInput,
+ untagged: BoolAttr,
+ internal_tag: Attr<String>,
+ content: Attr<String>,
+) -> TagType {
+ match (
+ untagged.0.get_with_tokens(),
+ internal_tag.get_with_tokens(),
+ content.get_with_tokens(),
+ ) {
+ (None, None, None) => TagType::External,
+ (Some(_), None, None) => TagType::None,
+ (None, Some((_, tag)), None) => {
+ // Check that there are no tuple variants.
+ if let syn::Data::Enum(data) = &item.data {
+ for variant in &data.variants {
+ match &variant.fields {
+ syn::Fields::Named(_) | syn::Fields::Unit => {}
+ syn::Fields::Unnamed(fields) => {
+ if fields.unnamed.len() != 1 {
+ let msg =
+ "#[serde(tag = \"...\")] cannot be used with tuple variants";
+ cx.error_spanned_by(variant, msg);
+ break;
+ }
+ }
+ }
+ }
+ }
+ TagType::Internal { tag }
+ }
+ (Some((untagged_tokens, ())), Some((tag_tokens, _)), None) => {
+ let msg = "enum cannot be both untagged and internally tagged";
+ cx.error_spanned_by(untagged_tokens, msg);
+ cx.error_spanned_by(tag_tokens, msg);
+ TagType::External // doesn't matter, will error
+ }
+ (None, None, Some((content_tokens, _))) => {
+ let msg = "#[serde(tag = \"...\", content = \"...\")] must be used together";
+ cx.error_spanned_by(content_tokens, msg);
+ TagType::External
+ }
+ (Some((untagged_tokens, ())), None, Some((content_tokens, _))) => {
+ let msg = "untagged enum cannot have #[serde(content = \"...\")]";
+ cx.error_spanned_by(untagged_tokens, msg);
+ cx.error_spanned_by(content_tokens, msg);
+ TagType::External
+ }
+ (None, Some((_, tag)), Some((_, content))) => TagType::Adjacent { tag, content },
+ (Some((untagged_tokens, ())), Some((tag_tokens, _)), Some((content_tokens, _))) => {
+ let msg = "untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]";
+ cx.error_spanned_by(untagged_tokens, msg);
+ cx.error_spanned_by(tag_tokens, msg);
+ cx.error_spanned_by(content_tokens, msg);
+ TagType::External
+ }
+ }
+}
+
+fn decide_identifier(
+ cx: &Ctxt,
+ item: &syn::DeriveInput,
+ field_identifier: BoolAttr,
+ variant_identifier: BoolAttr,
+) -> Identifier {
+ match (
+ &item.data,
+ field_identifier.0.get_with_tokens(),
+ variant_identifier.0.get_with_tokens(),
+ ) {
+ (_, None, None) => Identifier::No,
+ (_, Some((field_identifier_tokens, ())), Some((variant_identifier_tokens, ()))) => {
+ let msg =
+ "#[serde(field_identifier)] and #[serde(variant_identifier)] cannot both be set";
+ cx.error_spanned_by(field_identifier_tokens, msg);
+ cx.error_spanned_by(variant_identifier_tokens, msg);
+ Identifier::No
+ }
+ (syn::Data::Enum(_), Some(_), None) => Identifier::Field,
+ (syn::Data::Enum(_), None, Some(_)) => Identifier::Variant,
+ (syn::Data::Struct(syn::DataStruct { struct_token, .. }), Some(_), None) => {
+ let msg = "#[serde(field_identifier)] can only be used on an enum";
+ cx.error_spanned_by(struct_token, msg);
+ Identifier::No
+ }
+ (syn::Data::Union(syn::DataUnion { union_token, .. }), Some(_), None) => {
+ let msg = "#[serde(field_identifier)] can only be used on an enum";
+ cx.error_spanned_by(union_token, msg);
+ Identifier::No
+ }
+ (syn::Data::Struct(syn::DataStruct { struct_token, .. }), None, Some(_)) => {
+ let msg = "#[serde(variant_identifier)] can only be used on an enum";
+ cx.error_spanned_by(struct_token, msg);
+ Identifier::No
+ }
+ (syn::Data::Union(syn::DataUnion { union_token, .. }), None, Some(_)) => {
+ let msg = "#[serde(variant_identifier)] can only be used on an enum";
+ cx.error_spanned_by(union_token, msg);
+ Identifier::No
+ }
+ }
+}
+
+/// Represents variant attribute information
+pub struct Variant {
+ name: Name,
+ rename_all_rules: RenameAllRules,
+ ser_bound: Option<Vec<syn::WherePredicate>>,
+ de_bound: Option<Vec<syn::WherePredicate>>,
+ skip_deserializing: bool,
+ skip_serializing: bool,
+ other: bool,
+ serialize_with: Option<syn::ExprPath>,
+ deserialize_with: Option<syn::ExprPath>,
+ borrow: Option<BorrowAttribute>,
+ untagged: bool,
+}
+
+struct BorrowAttribute {
+ path: syn::Path,
+ lifetimes: Option<BTreeSet<syn::Lifetime>>,
+}
+
+impl Variant {
+ pub fn from_ast(cx: &Ctxt, variant: &syn::Variant) -> Self {
+ let mut ser_name = Attr::none(cx, RENAME);
+ let mut de_name = Attr::none(cx, RENAME);
+ let mut de_aliases = VecAttr::none(cx, RENAME);
+ let mut skip_deserializing = BoolAttr::none(cx, SKIP_DESERIALIZING);
+ let mut skip_serializing = BoolAttr::none(cx, SKIP_SERIALIZING);
+ let mut rename_all_ser_rule = Attr::none(cx, RENAME_ALL);
+ let mut rename_all_de_rule = Attr::none(cx, RENAME_ALL);
+ let mut ser_bound = Attr::none(cx, BOUND);
+ let mut de_bound = Attr::none(cx, BOUND);
+ let mut other = BoolAttr::none(cx, OTHER);
+ let mut serialize_with = Attr::none(cx, SERIALIZE_WITH);
+ let mut deserialize_with = Attr::none(cx, DESERIALIZE_WITH);
+ let mut borrow = Attr::none(cx, BORROW);
+ let mut untagged = BoolAttr::none(cx, UNTAGGED);
+
+ for attr in &variant.attrs {
+ if attr.path() != SERDE {
+ continue;
+ }
+
+ if let syn::Meta::List(meta) = &attr.meta {
+ if meta.tokens.is_empty() {
+ continue;
+ }
+ }
+
+ if let Err(err) = attr.parse_nested_meta(|meta| {
+ if meta.path == RENAME {
+ // #[serde(rename = "foo")]
+ // #[serde(rename(serialize = "foo", deserialize = "bar"))]
+ let (ser, de) = get_multiple_renames(cx, &meta)?;
+ ser_name.set_opt(&meta.path, ser.as_ref().map(syn::LitStr::value));
+ for de_value in de {
+ de_name.set_if_none(de_value.value());
+ de_aliases.insert(&meta.path, de_value.value());
+ }
+ } else if meta.path == ALIAS {
+ // #[serde(alias = "foo")]
+ if let Some(s) = get_lit_str(cx, ALIAS, &meta)? {
+ de_aliases.insert(&meta.path, s.value());
+ }
+ } else if meta.path == RENAME_ALL {
+ // #[serde(rename_all = "foo")]
+ // #[serde(rename_all(serialize = "foo", deserialize = "bar"))]
+ let one_name = meta.input.peek(Token![=]);
+ let (ser, de) = get_renames(cx, RENAME_ALL, &meta)?;
+ if let Some(ser) = ser {
+ match RenameRule::from_str(&ser.value()) {
+ Ok(rename_rule) => rename_all_ser_rule.set(&meta.path, rename_rule),
+ Err(err) => cx.error_spanned_by(ser, err),
+ }
+ }
+ if let Some(de) = de {
+ match RenameRule::from_str(&de.value()) {
+ Ok(rename_rule) => rename_all_de_rule.set(&meta.path, rename_rule),
+ Err(err) => {
+ if !one_name {
+ cx.error_spanned_by(de, err);
+ }
+ }
+ }
+ }
+ } else if meta.path == SKIP {
+ // #[serde(skip)]
+ skip_serializing.set_true(&meta.path);
+ skip_deserializing.set_true(&meta.path);
+ } else if meta.path == SKIP_DESERIALIZING {
+ // #[serde(skip_deserializing)]
+ skip_deserializing.set_true(&meta.path);
+ } else if meta.path == SKIP_SERIALIZING {
+ // #[serde(skip_serializing)]
+ skip_serializing.set_true(&meta.path);
+ } else if meta.path == OTHER {
+ // #[serde(other)]
+ other.set_true(&meta.path);
+ } else if meta.path == BOUND {
+ // #[serde(bound = "T: SomeBound")]
+ // #[serde(bound(serialize = "...", deserialize = "..."))]
+ let (ser, de) = get_where_predicates(cx, &meta)?;
+ ser_bound.set_opt(&meta.path, ser);
+ de_bound.set_opt(&meta.path, de);
+ } else if meta.path == WITH {
+ // #[serde(with = "...")]
+ if let Some(path) = parse_lit_into_expr_path(cx, WITH, &meta)? {
+ let mut ser_path = path.clone();
+ ser_path
+ .path
+ .segments
+ .push(Ident::new("serialize", Span::call_site()).into());
+ serialize_with.set(&meta.path, ser_path);
+ let mut de_path = path;
+ de_path
+ .path
+ .segments
+ .push(Ident::new("deserialize", Span::call_site()).into());
+ deserialize_with.set(&meta.path, de_path);
+ }
+ } else if meta.path == SERIALIZE_WITH {
+ // #[serde(serialize_with = "...")]
+ if let Some(path) = parse_lit_into_expr_path(cx, SERIALIZE_WITH, &meta)? {
+ serialize_with.set(&meta.path, path);
+ }
+ } else if meta.path == DESERIALIZE_WITH {
+ // #[serde(deserialize_with = "...")]
+ if let Some(path) = parse_lit_into_expr_path(cx, DESERIALIZE_WITH, &meta)? {
+ deserialize_with.set(&meta.path, path);
+ }
+ } else if meta.path == BORROW {
+ let borrow_attribute = if meta.input.peek(Token![=]) {
+ // #[serde(borrow = "'a + 'b")]
+ let lifetimes = parse_lit_into_lifetimes(cx, &meta)?;
+ BorrowAttribute {
+ path: meta.path.clone(),
+ lifetimes: Some(lifetimes),
+ }
+ } else {
+ // #[serde(borrow)]
+ BorrowAttribute {
+ path: meta.path.clone(),
+ lifetimes: None,
+ }
+ };
+ match &variant.fields {
+ syn::Fields::Unnamed(fields) if fields.unnamed.len() == 1 => {
+ borrow.set(&meta.path, borrow_attribute);
+ }
+ _ => {
+ let msg = "#[serde(borrow)] may only be used on newtype variants";
+ cx.error_spanned_by(variant, msg);
+ }
+ }
+ } else if meta.path == UNTAGGED {
+ untagged.set_true(&meta.path);
+ } else {
+ let path = meta.path.to_token_stream().to_string().replace(' ', "");
+ return Err(
+ meta.error(format_args!("unknown serde variant attribute `{}`", path))
+ );
+ }
+ Ok(())
+ }) {
+ cx.syn_error(err);
+ }
+ }
+
+ Variant {
+ name: Name::from_attrs(unraw(&variant.ident), ser_name, de_name, Some(de_aliases)),
+ rename_all_rules: RenameAllRules {
+ serialize: rename_all_ser_rule.get().unwrap_or(RenameRule::None),
+ deserialize: rename_all_de_rule.get().unwrap_or(RenameRule::None),
+ },
+ ser_bound: ser_bound.get(),
+ de_bound: de_bound.get(),
+ skip_deserializing: skip_deserializing.get(),
+ skip_serializing: skip_serializing.get(),
+ other: other.get(),
+ serialize_with: serialize_with.get(),
+ deserialize_with: deserialize_with.get(),
+ borrow: borrow.get(),
+ untagged: untagged.get(),
+ }
+ }
+
+ pub fn name(&self) -> &Name {
+ &self.name
+ }
+
+ pub fn aliases(&self) -> &BTreeSet<String> {
+ self.name.deserialize_aliases()
+ }
+
+ pub fn rename_by_rules(&mut self, rules: RenameAllRules) {
+ if !self.name.serialize_renamed {
+ self.name.serialize = rules.serialize.apply_to_variant(&self.name.serialize);
+ }
+ if !self.name.deserialize_renamed {
+ self.name.deserialize = rules.deserialize.apply_to_variant(&self.name.deserialize);
+ }
+ self.name
+ .deserialize_aliases
+ .insert(self.name.deserialize.clone());
+ }
+
+ pub fn rename_all_rules(&self) -> RenameAllRules {
+ self.rename_all_rules
+ }
+
+ pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> {
+ self.ser_bound.as_ref().map(|vec| &vec[..])
+ }
+
+ pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> {
+ self.de_bound.as_ref().map(|vec| &vec[..])
+ }
+
+ pub fn skip_deserializing(&self) -> bool {
+ self.skip_deserializing
+ }
+
+ pub fn skip_serializing(&self) -> bool {
+ self.skip_serializing
+ }
+
+ pub fn other(&self) -> bool {
+ self.other
+ }
+
+ pub fn serialize_with(&self) -> Option<&syn::ExprPath> {
+ self.serialize_with.as_ref()
+ }
+
+ pub fn deserialize_with(&self) -> Option<&syn::ExprPath> {
+ self.deserialize_with.as_ref()
+ }
+
+ pub fn untagged(&self) -> bool {
+ self.untagged
+ }
+}
+
+/// Represents field attribute information
+pub struct Field {
+ name: Name,
+ skip_serializing: bool,
+ skip_deserializing: bool,
+ skip_serializing_if: Option<syn::ExprPath>,
+ default: Default,
+ serialize_with: Option<syn::ExprPath>,
+ deserialize_with: Option<syn::ExprPath>,
+ ser_bound: Option<Vec<syn::WherePredicate>>,
+ de_bound: Option<Vec<syn::WherePredicate>>,
+ borrowed_lifetimes: BTreeSet<syn::Lifetime>,
+ getter: Option<syn::ExprPath>,
+ flatten: bool,
+ transparent: bool,
+}
+
+/// Represents the default to use for a field when deserializing.
+pub enum Default {
+ /// Field must always be specified because it does not have a default.
+ None,
+ /// The default is given by `std::default::Default::default()`.
+ Default,
+ /// The default is given by this function.
+ Path(syn::ExprPath),
+}
+
+impl Default {
+ pub fn is_none(&self) -> bool {
+ match self {
+ Default::None => true,
+ Default::Default | Default::Path(_) => false,
+ }
+ }
+}
+
+impl Field {
+ /// Extract out the `#[serde(...)]` attributes from a struct field.
+ pub fn from_ast(
+ cx: &Ctxt,
+ index: usize,
+ field: &syn::Field,
+ attrs: Option<&Variant>,
+ container_default: &Default,
+ ) -> Self {
+ let mut ser_name = Attr::none(cx, RENAME);
+ let mut de_name = Attr::none(cx, RENAME);
+ let mut de_aliases = VecAttr::none(cx, RENAME);
+ let mut skip_serializing = BoolAttr::none(cx, SKIP_SERIALIZING);
+ let mut skip_deserializing = BoolAttr::none(cx, SKIP_DESERIALIZING);
+ let mut skip_serializing_if = Attr::none(cx, SKIP_SERIALIZING_IF);
+ let mut default = Attr::none(cx, DEFAULT);
+ let mut serialize_with = Attr::none(cx, SERIALIZE_WITH);
+ let mut deserialize_with = Attr::none(cx, DESERIALIZE_WITH);
+ let mut ser_bound = Attr::none(cx, BOUND);
+ let mut de_bound = Attr::none(cx, BOUND);
+ let mut borrowed_lifetimes = Attr::none(cx, BORROW);
+ let mut getter = Attr::none(cx, GETTER);
+ let mut flatten = BoolAttr::none(cx, FLATTEN);
+
+ let ident = match &field.ident {
+ Some(ident) => unraw(ident),
+ None => index.to_string(),
+ };
+
+ if let Some(borrow_attribute) = attrs.and_then(|variant| variant.borrow.as_ref()) {
+ if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, field) {
+ if let Some(lifetimes) = &borrow_attribute.lifetimes {
+ for lifetime in lifetimes {
+ if !borrowable.contains(lifetime) {
+ let msg =
+ format!("field `{}` does not have lifetime {}", ident, lifetime);
+ cx.error_spanned_by(field, msg);
+ }
+ }
+ borrowed_lifetimes.set(&borrow_attribute.path, lifetimes.clone());
+ } else {
+ borrowed_lifetimes.set(&borrow_attribute.path, borrowable);
+ }
+ }
+ }
+
+ for attr in &field.attrs {
+ if attr.path() != SERDE {
+ continue;
+ }
+
+ if let syn::Meta::List(meta) = &attr.meta {
+ if meta.tokens.is_empty() {
+ continue;
+ }
+ }
+
+ if let Err(err) = attr.parse_nested_meta(|meta| {
+ if meta.path == RENAME {
+ // #[serde(rename = "foo")]
+ // #[serde(rename(serialize = "foo", deserialize = "bar"))]
+ let (ser, de) = get_multiple_renames(cx, &meta)?;
+ ser_name.set_opt(&meta.path, ser.as_ref().map(syn::LitStr::value));
+ for de_value in de {
+ de_name.set_if_none(de_value.value());
+ de_aliases.insert(&meta.path, de_value.value());
+ }
+ } else if meta.path == ALIAS {
+ // #[serde(alias = "foo")]
+ if let Some(s) = get_lit_str(cx, ALIAS, &meta)? {
+ de_aliases.insert(&meta.path, s.value());
+ }
+ } else if meta.path == DEFAULT {
+ if meta.input.peek(Token![=]) {
+ // #[serde(default = "...")]
+ if let Some(path) = parse_lit_into_expr_path(cx, DEFAULT, &meta)? {
+ default.set(&meta.path, Default::Path(path));
+ }
+ } else {
+ // #[serde(default)]
+ default.set(&meta.path, Default::Default);
+ }
+ } else if meta.path == SKIP_SERIALIZING {
+ // #[serde(skip_serializing)]
+ skip_serializing.set_true(&meta.path);
+ } else if meta.path == SKIP_DESERIALIZING {
+ // #[serde(skip_deserializing)]
+ skip_deserializing.set_true(&meta.path);
+ } else if meta.path == SKIP {
+ // #[serde(skip)]
+ skip_serializing.set_true(&meta.path);
+ skip_deserializing.set_true(&meta.path);
+ } else if meta.path == SKIP_SERIALIZING_IF {
+ // #[serde(skip_serializing_if = "...")]
+ if let Some(path) = parse_lit_into_expr_path(cx, SKIP_SERIALIZING_IF, &meta)? {
+ skip_serializing_if.set(&meta.path, path);
+ }
+ } else if meta.path == SERIALIZE_WITH {
+ // #[serde(serialize_with = "...")]
+ if let Some(path) = parse_lit_into_expr_path(cx, SERIALIZE_WITH, &meta)? {
+ serialize_with.set(&meta.path, path);
+ }
+ } else if meta.path == DESERIALIZE_WITH {
+ // #[serde(deserialize_with = "...")]
+ if let Some(path) = parse_lit_into_expr_path(cx, DESERIALIZE_WITH, &meta)? {
+ deserialize_with.set(&meta.path, path);
+ }
+ } else if meta.path == WITH {
+ // #[serde(with = "...")]
+ if let Some(path) = parse_lit_into_expr_path(cx, WITH, &meta)? {
+ let mut ser_path = path.clone();
+ ser_path
+ .path
+ .segments
+ .push(Ident::new("serialize", Span::call_site()).into());
+ serialize_with.set(&meta.path, ser_path);
+ let mut de_path = path;
+ de_path
+ .path
+ .segments
+ .push(Ident::new("deserialize", Span::call_site()).into());
+ deserialize_with.set(&meta.path, de_path);
+ }
+ } else if meta.path == BOUND {
+ // #[serde(bound = "T: SomeBound")]
+ // #[serde(bound(serialize = "...", deserialize = "..."))]
+ let (ser, de) = get_where_predicates(cx, &meta)?;
+ ser_bound.set_opt(&meta.path, ser);
+ de_bound.set_opt(&meta.path, de);
+ } else if meta.path == BORROW {
+ if meta.input.peek(Token![=]) {
+ // #[serde(borrow = "'a + 'b")]
+ let lifetimes = parse_lit_into_lifetimes(cx, &meta)?;
+ if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, field) {
+ for lifetime in &lifetimes {
+ if !borrowable.contains(lifetime) {
+ let msg = format!(
+ "field `{}` does not have lifetime {}",
+ ident, lifetime,
+ );
+ cx.error_spanned_by(field, msg);
+ }
+ }
+ borrowed_lifetimes.set(&meta.path, lifetimes);
+ }
+ } else {
+ // #[serde(borrow)]
+ if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, field) {
+ borrowed_lifetimes.set(&meta.path, borrowable);
+ }
+ }
+ } else if meta.path == GETTER {
+ // #[serde(getter = "...")]
+ if let Some(path) = parse_lit_into_expr_path(cx, GETTER, &meta)? {
+ getter.set(&meta.path, path);
+ }
+ } else if meta.path == FLATTEN {
+ // #[serde(flatten)]
+ flatten.set_true(&meta.path);
+ } else {
+ let path = meta.path.to_token_stream().to_string().replace(' ', "");
+ return Err(
+ meta.error(format_args!("unknown serde field attribute `{}`", path))
+ );
+ }
+ Ok(())
+ }) {
+ cx.syn_error(err);
+ }
+ }
+
+ // Is skip_deserializing, initialize the field to Default::default() unless a
+ // different default is specified by `#[serde(default = "...")]` on
+ // ourselves or our container (e.g. the struct we are in).
+ if let Default::None = *container_default {
+ if skip_deserializing.0.value.is_some() {
+ default.set_if_none(Default::Default);
+ }
+ }
+
+ let mut borrowed_lifetimes = borrowed_lifetimes.get().unwrap_or_default();
+ if !borrowed_lifetimes.is_empty() {
+ // Cow<str> and Cow<[u8]> never borrow by default:
+ //
+ // impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T>
+ //
+ // A #[serde(borrow)] attribute enables borrowing that corresponds
+ // roughly to these impls:
+ //
+ // impl<'de: 'a, 'a> Deserialize<'de> for Cow<'a, str>
+ // impl<'de: 'a, 'a> Deserialize<'de> for Cow<'a, [u8]>
+ if is_cow(&field.ty, is_str) {
+ let mut path = syn::Path {
+ leading_colon: None,
+ segments: Punctuated::new(),
+ };
+ let span = Span::call_site();
+ path.segments.push(Ident::new("_serde", span).into());
+ path.segments.push(Ident::new("__private", span).into());
+ path.segments.push(Ident::new("de", span).into());
+ path.segments
+ .push(Ident::new("borrow_cow_str", span).into());
+ let expr = syn::ExprPath {
+ attrs: Vec::new(),
+ qself: None,
+ path,
+ };
+ deserialize_with.set_if_none(expr);
+ } else if is_cow(&field.ty, is_slice_u8) {
+ let mut path = syn::Path {
+ leading_colon: None,
+ segments: Punctuated::new(),
+ };
+ let span = Span::call_site();
+ path.segments.push(Ident::new("_serde", span).into());
+ path.segments.push(Ident::new("__private", span).into());
+ path.segments.push(Ident::new("de", span).into());
+ path.segments
+ .push(Ident::new("borrow_cow_bytes", span).into());
+ let expr = syn::ExprPath {
+ attrs: Vec::new(),
+ qself: None,
+ path,
+ };
+ deserialize_with.set_if_none(expr);
+ }
+ } else if is_implicitly_borrowed(&field.ty) {
+ // Types &str and &[u8] are always implicitly borrowed. No need for
+ // a #[serde(borrow)].
+ collect_lifetimes(&field.ty, &mut borrowed_lifetimes);
+ }
+
+ Field {
+ name: Name::from_attrs(ident, ser_name, de_name, Some(de_aliases)),
+ skip_serializing: skip_serializing.get(),
+ skip_deserializing: skip_deserializing.get(),
+ skip_serializing_if: skip_serializing_if.get(),
+ default: default.get().unwrap_or(Default::None),
+ serialize_with: serialize_with.get(),
+ deserialize_with: deserialize_with.get(),
+ ser_bound: ser_bound.get(),
+ de_bound: de_bound.get(),
+ borrowed_lifetimes,
+ getter: getter.get(),
+ flatten: flatten.get(),
+ transparent: false,
+ }
+ }
+
+ pub fn name(&self) -> &Name {
+ &self.name
+ }
+
+ pub fn aliases(&self) -> &BTreeSet<String> {
+ self.name.deserialize_aliases()
+ }
+
+ pub fn rename_by_rules(&mut self, rules: RenameAllRules) {
+ if !self.name.serialize_renamed {
+ self.name.serialize = rules.serialize.apply_to_field(&self.name.serialize);
+ }
+ if !self.name.deserialize_renamed {
+ self.name.deserialize = rules.deserialize.apply_to_field(&self.name.deserialize);
+ }
+ self.name
+ .deserialize_aliases
+ .insert(self.name.deserialize.clone());
+ }
+
+ pub fn skip_serializing(&self) -> bool {
+ self.skip_serializing
+ }
+
+ pub fn skip_deserializing(&self) -> bool {
+ self.skip_deserializing
+ }
+
+ pub fn skip_serializing_if(&self) -> Option<&syn::ExprPath> {
+ self.skip_serializing_if.as_ref()
+ }
+
+ pub fn default(&self) -> &Default {
+ &self.default
+ }
+
+ pub fn serialize_with(&self) -> Option<&syn::ExprPath> {
+ self.serialize_with.as_ref()
+ }
+
+ pub fn deserialize_with(&self) -> Option<&syn::ExprPath> {
+ self.deserialize_with.as_ref()
+ }
+
+ pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> {
+ self.ser_bound.as_ref().map(|vec| &vec[..])
+ }
+
+ pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> {
+ self.de_bound.as_ref().map(|vec| &vec[..])
+ }
+
+ pub fn borrowed_lifetimes(&self) -> &BTreeSet<syn::Lifetime> {
+ &self.borrowed_lifetimes
+ }
+
+ pub fn getter(&self) -> Option<&syn::ExprPath> {
+ self.getter.as_ref()
+ }
+
+ pub fn flatten(&self) -> bool {
+ self.flatten
+ }
+
+ pub fn transparent(&self) -> bool {
+ self.transparent
+ }
+
+ pub fn mark_transparent(&mut self) {
+ self.transparent = true;
+ }
+}
+
+type SerAndDe<T> = (Option<T>, Option<T>);
+
+fn get_ser_and_de<'c, T, F, R>(
+ cx: &'c Ctxt,
+ attr_name: Symbol,
+ meta: &ParseNestedMeta,
+ f: F,
+) -> syn::Result<(VecAttr<'c, T>, VecAttr<'c, T>)>
+where
+ T: Clone,
+ F: Fn(&Ctxt, Symbol, Symbol, &ParseNestedMeta) -> syn::Result<R>,
+ R: Into<Option<T>>,
+{
+ let mut ser_meta = VecAttr::none(cx, attr_name);
+ let mut de_meta = VecAttr::none(cx, attr_name);
+
+ let lookahead = meta.input.lookahead1();
+ if lookahead.peek(Token![=]) {
+ if let Some(both) = f(cx, attr_name, attr_name, meta)?.into() {
+ ser_meta.insert(&meta.path, both.clone());
+ de_meta.insert(&meta.path, both);
+ }
+ } else if lookahead.peek(token::Paren) {
+ meta.parse_nested_meta(|meta| {
+ if meta.path == SERIALIZE {
+ if let Some(v) = f(cx, attr_name, SERIALIZE, &meta)?.into() {
+ ser_meta.insert(&meta.path, v);
+ }
+ } else if meta.path == DESERIALIZE {
+ if let Some(v) = f(cx, attr_name, DESERIALIZE, &meta)?.into() {
+ de_meta.insert(&meta.path, v);
+ }
+ } else {
+ return Err(meta.error(format_args!(
+ "malformed {0} attribute, expected `{0}(serialize = ..., deserialize = ...)`",
+ attr_name,
+ )));
+ }
+ Ok(())
+ })?;
+ } else {
+ return Err(lookahead.error());
+ }
+
+ Ok((ser_meta, de_meta))
+}
+
+fn get_renames(
+ cx: &Ctxt,
+ attr_name: Symbol,
+ meta: &ParseNestedMeta,
+) -> syn::Result<SerAndDe<syn::LitStr>> {
+ let (ser, de) = get_ser_and_de(cx, attr_name, meta, get_lit_str2)?;
+ Ok((ser.at_most_one(), de.at_most_one()))
+}
+
+fn get_multiple_renames(
+ cx: &Ctxt,
+ meta: &ParseNestedMeta,
+) -> syn::Result<(Option<syn::LitStr>, Vec<syn::LitStr>)> {
+ let (ser, de) = get_ser_and_de(cx, RENAME, meta, get_lit_str2)?;
+ Ok((ser.at_most_one(), de.get()))
+}
+
+fn get_where_predicates(
+ cx: &Ctxt,
+ meta: &ParseNestedMeta,
+) -> syn::Result<SerAndDe<Vec<syn::WherePredicate>>> {
+ let (ser, de) = get_ser_and_de(cx, BOUND, meta, parse_lit_into_where)?;
+ Ok((ser.at_most_one(), de.at_most_one()))
+}
+
+fn get_lit_str(
+ cx: &Ctxt,
+ attr_name: Symbol,
+ meta: &ParseNestedMeta,
+) -> syn::Result<Option<syn::LitStr>> {
+ get_lit_str2(cx, attr_name, attr_name, meta)
+}
+
+fn get_lit_str2(
+ cx: &Ctxt,
+ attr_name: Symbol,
+ meta_item_name: Symbol,
+ meta: &ParseNestedMeta,
+) -> syn::Result<Option<syn::LitStr>> {
+ let expr: syn::Expr = meta.value()?.parse()?;
+ let mut value = &expr;
+ while let syn::Expr::Group(e) = value {
+ value = &e.expr;
+ }
+ if let syn::Expr::Lit(syn::ExprLit {
+ lit: syn::Lit::Str(lit),
+ ..
+ }) = value
+ {
+ let suffix = lit.suffix();
+ if !suffix.is_empty() {
+ cx.error_spanned_by(
+ lit,
+ format!("unexpected suffix `{}` on string literal", suffix),
+ );
+ }
+ Ok(Some(lit.clone()))
+ } else {
+ cx.error_spanned_by(
+ expr,
+ format!(
+ "expected serde {} attribute to be a string: `{} = \"...\"`",
+ attr_name, meta_item_name
+ ),
+ );
+ Ok(None)
+ }
+}
+
+fn parse_lit_into_path(
+ cx: &Ctxt,
+ attr_name: Symbol,
+ meta: &ParseNestedMeta,
+) -> syn::Result<Option<syn::Path>> {
+ let string = match get_lit_str(cx, attr_name, meta)? {
+ Some(string) => string,
+ None => return Ok(None),
+ };
+
+ Ok(match string.parse() {
+ Ok(path) => Some(path),
+ Err(_) => {
+ cx.error_spanned_by(
+ &string,
+ format!("failed to parse path: {:?}", string.value()),
+ );
+ None
+ }
+ })
+}
+
+fn parse_lit_into_expr_path(
+ cx: &Ctxt,
+ attr_name: Symbol,
+ meta: &ParseNestedMeta,
+) -> syn::Result<Option<syn::ExprPath>> {
+ let string = match get_lit_str(cx, attr_name, meta)? {
+ Some(string) => string,
+ None => return Ok(None),
+ };
+
+ Ok(match string.parse() {
+ Ok(expr) => Some(expr),
+ Err(_) => {
+ cx.error_spanned_by(
+ &string,
+ format!("failed to parse path: {:?}", string.value()),
+ );
+ None
+ }
+ })
+}
+
+fn parse_lit_into_where(
+ cx: &Ctxt,
+ attr_name: Symbol,
+ meta_item_name: Symbol,
+ meta: &ParseNestedMeta,
+) -> syn::Result<Vec<syn::WherePredicate>> {
+ let string = match get_lit_str2(cx, attr_name, meta_item_name, meta)? {
+ Some(string) => string,
+ None => return Ok(Vec::new()),
+ };
+
+ Ok(
+ match string.parse_with(Punctuated::<syn::WherePredicate, Token![,]>::parse_terminated) {
+ Ok(predicates) => Vec::from_iter(predicates),
+ Err(err) => {
+ cx.error_spanned_by(string, err);
+ Vec::new()
+ }
+ },
+ )
+}
+
+fn parse_lit_into_ty(
+ cx: &Ctxt,
+ attr_name: Symbol,
+ meta: &ParseNestedMeta,
+) -> syn::Result<Option<syn::Type>> {
+ let string = match get_lit_str(cx, attr_name, meta)? {
+ Some(string) => string,
+ None => return Ok(None),
+ };
+
+ Ok(match string.parse() {
+ Ok(ty) => Some(ty),
+ Err(_) => {
+ cx.error_spanned_by(
+ &string,
+ format!("failed to parse type: {} = {:?}", attr_name, string.value()),
+ );
+ None
+ }
+ })
+}
+
+// Parses a string literal like "'a + 'b + 'c" containing a nonempty list of
+// lifetimes separated by `+`.
+fn parse_lit_into_lifetimes(
+ cx: &Ctxt,
+ meta: &ParseNestedMeta,
+) -> syn::Result<BTreeSet<syn::Lifetime>> {
+ let string = match get_lit_str(cx, BORROW, meta)? {
+ Some(string) => string,
+ None => return Ok(BTreeSet::new()),
+ };
+
+ if let Ok(lifetimes) = string.parse_with(|input: ParseStream| {
+ let mut set = BTreeSet::new();
+ while !input.is_empty() {
+ let lifetime: Lifetime = input.parse()?;
+ if !set.insert(lifetime.clone()) {
+ cx.error_spanned_by(
+ &string,
+ format!("duplicate borrowed lifetime `{}`", lifetime),
+ );
+ }
+ if input.is_empty() {
+ break;
+ }
+ input.parse::<Token![+]>()?;
+ }
+ Ok(set)
+ }) {
+ if lifetimes.is_empty() {
+ cx.error_spanned_by(string, "at least one lifetime must be borrowed");
+ }
+ return Ok(lifetimes);
+ }
+
+ cx.error_spanned_by(
+ &string,
+ format!("failed to parse borrowed lifetimes: {:?}", string.value()),
+ );
+ Ok(BTreeSet::new())
+}
+
+fn is_implicitly_borrowed(ty: &syn::Type) -> bool {
+ is_implicitly_borrowed_reference(ty) || is_option(ty, is_implicitly_borrowed_reference)
+}
+
+fn is_implicitly_borrowed_reference(ty: &syn::Type) -> bool {
+ is_reference(ty, is_str) || is_reference(ty, is_slice_u8)
+}
+
+// Whether the type looks like it might be `std::borrow::Cow<T>` where elem="T".
+// This can have false negatives and false positives.
+//
+// False negative:
+//
+// use std::borrow::Cow as Pig;
+//
+// #[derive(Deserialize)]
+// struct S<'a> {
+// #[serde(borrow)]
+// pig: Pig<'a, str>,
+// }
+//
+// False positive:
+//
+// type str = [i16];
+//
+// #[derive(Deserialize)]
+// struct S<'a> {
+// #[serde(borrow)]
+// cow: Cow<'a, str>,
+// }
+fn is_cow(ty: &syn::Type, elem: fn(&syn::Type) -> bool) -> bool {
+ let path = match ungroup(ty) {
+ syn::Type::Path(ty) => &ty.path,
+ _ => {
+ return false;
+ }
+ };
+ let seg = match path.segments.last() {
+ Some(seg) => seg,
+ None => {
+ return false;
+ }
+ };
+ let args = match &seg.arguments {
+ syn::PathArguments::AngleBracketed(bracketed) => &bracketed.args,
+ _ => {
+ return false;
+ }
+ };
+ seg.ident == "Cow"
+ && args.len() == 2
+ && match (&args[0], &args[1]) {
+ (syn::GenericArgument::Lifetime(_), syn::GenericArgument::Type(arg)) => elem(arg),
+ _ => false,
+ }
+}
+
+fn is_option(ty: &syn::Type, elem: fn(&syn::Type) -> bool) -> bool {
+ let path = match ungroup(ty) {
+ syn::Type::Path(ty) => &ty.path,
+ _ => {
+ return false;
+ }
+ };
+ let seg = match path.segments.last() {
+ Some(seg) => seg,
+ None => {
+ return false;
+ }
+ };
+ let args = match &seg.arguments {
+ syn::PathArguments::AngleBracketed(bracketed) => &bracketed.args,
+ _ => {
+ return false;
+ }
+ };
+ seg.ident == "Option"
+ && args.len() == 1
+ && match &args[0] {
+ syn::GenericArgument::Type(arg) => elem(arg),
+ _ => false,
+ }
+}
+
+// Whether the type looks like it might be `&T` where elem="T". This can have
+// false negatives and false positives.
+//
+// False negative:
+//
+// type Yarn = str;
+//
+// #[derive(Deserialize)]
+// struct S<'a> {
+// r: &'a Yarn,
+// }
+//
+// False positive:
+//
+// type str = [i16];
+//
+// #[derive(Deserialize)]
+// struct S<'a> {
+// r: &'a str,
+// }
+fn is_reference(ty: &syn::Type, elem: fn(&syn::Type) -> bool) -> bool {
+ match ungroup(ty) {
+ syn::Type::Reference(ty) => ty.mutability.is_none() && elem(&ty.elem),
+ _ => false,
+ }
+}
+
+fn is_str(ty: &syn::Type) -> bool {
+ is_primitive_type(ty, "str")
+}
+
+fn is_slice_u8(ty: &syn::Type) -> bool {
+ match ungroup(ty) {
+ syn::Type::Slice(ty) => is_primitive_type(&ty.elem, "u8"),
+ _ => false,
+ }
+}
+
+fn is_primitive_type(ty: &syn::Type, primitive: &str) -> bool {
+ match ungroup(ty) {
+ syn::Type::Path(ty) => ty.qself.is_none() && is_primitive_path(&ty.path, primitive),
+ _ => false,
+ }
+}
+
+fn is_primitive_path(path: &syn::Path, primitive: &str) -> bool {
+ path.leading_colon.is_none()
+ && path.segments.len() == 1
+ && path.segments[0].ident == primitive
+ && path.segments[0].arguments.is_empty()
+}
+
+// All lifetimes that this type could borrow from a Deserializer.
+//
+// For example a type `S<'a, 'b>` could borrow `'a` and `'b`. On the other hand
+// a type `for<'a> fn(&'a str)` could not borrow `'a` from the Deserializer.
+//
+// This is used when there is an explicit or implicit `#[serde(borrow)]`
+// attribute on the field so there must be at least one borrowable lifetime.
+fn borrowable_lifetimes(
+ cx: &Ctxt,
+ name: &str,
+ field: &syn::Field,
+) -> Result<BTreeSet<syn::Lifetime>, ()> {
+ let mut lifetimes = BTreeSet::new();
+ collect_lifetimes(&field.ty, &mut lifetimes);
+ if lifetimes.is_empty() {
+ let msg = format!("field `{}` has no lifetimes to borrow", name);
+ cx.error_spanned_by(field, msg);
+ Err(())
+ } else {
+ Ok(lifetimes)
+ }
+}
+
+fn collect_lifetimes(ty: &syn::Type, out: &mut BTreeSet<syn::Lifetime>) {
+ match ty {
+ #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ syn::Type::Slice(ty) => {
+ collect_lifetimes(&ty.elem, out);
+ }
+ syn::Type::Array(ty) => {
+ collect_lifetimes(&ty.elem, out);
+ }
+ syn::Type::Ptr(ty) => {
+ collect_lifetimes(&ty.elem, out);
+ }
+ syn::Type::Reference(ty) => {
+ out.extend(ty.lifetime.iter().cloned());
+ collect_lifetimes(&ty.elem, out);
+ }
+ syn::Type::Tuple(ty) => {
+ for elem in &ty.elems {
+ collect_lifetimes(elem, out);
+ }
+ }
+ syn::Type::Path(ty) => {
+ if let Some(qself) = &ty.qself {
+ collect_lifetimes(&qself.ty, out);
+ }
+ for seg in &ty.path.segments {
+ if let syn::PathArguments::AngleBracketed(bracketed) = &seg.arguments {
+ for arg in &bracketed.args {
+ match arg {
+ syn::GenericArgument::Lifetime(lifetime) => {
+ out.insert(lifetime.clone());
+ }
+ syn::GenericArgument::Type(ty) => {
+ collect_lifetimes(ty, out);
+ }
+ syn::GenericArgument::AssocType(binding) => {
+ collect_lifetimes(&binding.ty, out);
+ }
+ syn::GenericArgument::Const(_)
+ | syn::GenericArgument::AssocConst(_)
+ | syn::GenericArgument::Constraint(_)
+ | _ => {}
+ }
+ }
+ }
+ }
+ }
+ syn::Type::Paren(ty) => {
+ collect_lifetimes(&ty.elem, out);
+ }
+ syn::Type::Group(ty) => {
+ collect_lifetimes(&ty.elem, out);
+ }
+ syn::Type::Macro(ty) => {
+ collect_lifetimes_from_tokens(ty.mac.tokens.clone(), out);
+ }
+ syn::Type::BareFn(_)
+ | syn::Type::Never(_)
+ | syn::Type::TraitObject(_)
+ | syn::Type::ImplTrait(_)
+ | syn::Type::Infer(_)
+ | syn::Type::Verbatim(_) => {}
+
+ _ => {}
+ }
+}
+
+fn collect_lifetimes_from_tokens(tokens: TokenStream, out: &mut BTreeSet<syn::Lifetime>) {
+ let mut iter = tokens.into_iter();
+ while let Some(tt) = iter.next() {
+ match &tt {
+ TokenTree::Punct(op) if op.as_char() == '\'' && op.spacing() == Spacing::Joint => {
+ if let Some(TokenTree::Ident(ident)) = iter.next() {
+ out.insert(syn::Lifetime {
+ apostrophe: op.span(),
+ ident,
+ });
+ }
+ }
+ TokenTree::Group(group) => {
+ let tokens = group.stream();
+ collect_lifetimes_from_tokens(tokens, out);
+ }
+ _ => {}
+ }
+ }
+}
diff --git a/third_party/rust/serde_derive/src/internals/case.rs b/third_party/rust/serde_derive/src/internals/case.rs
new file mode 100644
index 0000000000..8c8c02e757
--- /dev/null
+++ b/third_party/rust/serde_derive/src/internals/case.rs
@@ -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);
+ }
+}
diff --git a/third_party/rust/serde_derive/src/internals/check.rs b/third_party/rust/serde_derive/src/internals/check.rs
new file mode 100644
index 0000000000..52b0f379fd
--- /dev/null
+++ b/third_party/rust/serde_derive/src/internals/check.rs
@@ -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 == tag {
+ diagnose_conflict();
+ return;
+ }
+
+ for de_name in field.attrs.aliases() {
+ if check_de && de_name == 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",
+ );
+ }
+}
diff --git a/third_party/rust/serde_derive/src/internals/ctxt.rs b/third_party/rust/serde_derive/src/internals/ctxt.rs
new file mode 100644
index 0000000000..a47bfa4102
--- /dev/null
+++ b/third_party/rust/serde_derive/src/internals/ctxt.rs
@@ -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");
+ }
+ }
+}
diff --git a/third_party/rust/serde_derive/src/internals/mod.rs b/third_party/rust/serde_derive/src/internals/mod.rs
new file mode 100644
index 0000000000..f98ef08e8c
--- /dev/null
+++ b/third_party/rust/serde_derive/src/internals/mod.rs
@@ -0,0 +1,27 @@
+pub mod ast;
+pub mod attr;
+
+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
+}
diff --git a/third_party/rust/serde_derive/src/internals/receiver.rs b/third_party/rust/serde_derive/src/internals/receiver.rs
new file mode 100644
index 0000000000..fa2a77d240
--- /dev/null
+++ b/third_party/rust/serde_derive/src/internals/receiver.rs
@@ -0,0 +1,292 @@
+use crate::internals::respan::respan;
+use proc_macro2::Span;
+use quote::ToTokens;
+use std::mem;
+use syn::punctuated::Punctuated;
+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::replace(&mut path.segments, Punctuated::new());
+ 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 = self.self_ty(span).into();
+ }
+
+ // `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::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) {}
+}
diff --git a/third_party/rust/serde_derive/src/internals/respan.rs b/third_party/rust/serde_derive/src/internals/respan.rs
new file mode 100644
index 0000000000..dcec7017b3
--- /dev/null
+++ b/third_party/rust/serde_derive/src/internals/respan.rs
@@ -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
+}
diff --git a/third_party/rust/serde_derive/src/internals/symbol.rs b/third_party/rust/serde_derive/src/internals/symbol.rs
new file mode 100644
index 0000000000..572391a807
--- /dev/null
+++ b/third_party/rust/serde_derive/src/internals/symbol.rs
@@ -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<'a> PartialEq<Symbol> for &'a 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<'a> PartialEq<Symbol> for &'a 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)
+ }
+}
diff --git a/third_party/rust/serde_derive/src/lib.rs b/third_party/rust/serde_derive/src/lib.rs
new file mode 100644
index 0000000000..8c4a6cacc7
--- /dev/null
+++ b/third_party/rust/serde_derive/src/lib.rs
@@ -0,0 +1,101 @@
+//! 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.195")]
+// 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_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::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::unseparated_literal_suffix,
+ clippy::unused_self,
+ clippy::use_self,
+ clippy::wildcard_imports
+)]
+#![cfg_attr(all(test, exhaustive), feature(non_exhaustive_omitted_patterns_lint))]
+
+extern crate proc_macro2;
+extern crate quote;
+extern crate syn;
+
+extern crate proc_macro;
+
+mod internals;
+
+use proc_macro::TokenStream;
+use syn::parse_macro_input;
+use syn::DeriveInput;
+
+#[macro_use]
+mod bound;
+#[macro_use]
+mod fragment;
+
+mod de;
+mod dummy;
+mod pretend;
+mod ser;
+mod this;
+
+#[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()
+}
diff --git a/third_party/rust/serde_derive/src/pretend.rs b/third_party/rust/serde_derive/src/pretend.rs
new file mode 100644
index 0000000000..2c9e779368
--- /dev/null
+++ b/third_party/rust/serde_derive/src/pretend.rs
@@ -0,0 +1,185 @@
+use crate::internals::ast::{Container, Data, Field, Style, Variant};
+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<_>>();
+
+ quote! {
+ match _serde::__private::None::<&#type_ident #ty_generics> {
+ _serde::__private::Some(__v @ #type_ident { #(#members: _),* }) => {
+ #(
+ let _ = _serde::__private::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<_>>();
+
+ quote! {
+ match _serde::__private::None::<&#type_ident #ty_generics> {
+ #(
+ _serde::__private::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)*)
+}
diff --git a/third_party/rust/serde_derive/src/ser.rs b/third_party/rust/serde_derive/src/ser.rs
new file mode 100644
index 0000000000..3be51ee52d
--- /dev/null
+++ b/third_party/rust/serde_derive/src/ser.rs
@@ -0,0 +1,1359 @@
+use crate::fragment::{Fragment, Match, Stmts};
+use crate::internals::ast::{Container, Data, Field, Style, Variant};
+use crate::internals::{attr, replace_receiver, Ctxt, Derive};
+use crate::{bound, dummy, pretend, this};
+use proc_macro2::{Span, TokenStream};
+use quote::{quote, quote_spanned};
+use syn::spanned::Spanned;
+use syn::{parse_quote, Ident, Index, Member};
+
+pub fn expand_derive_serialize(input: &mut syn::DeriveInput) -> syn::Result<TokenStream> {
+ replace_receiver(input);
+
+ let ctxt = Ctxt::new();
+ let cont = match Container::from_ast(&ctxt, input, Derive::Serialize) {
+ 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 (impl_generics, ty_generics, where_clause) = params.generics.split_for_impl();
+ let body = Stmts(serialize_body(&cont, &params));
+ let serde = cont.attrs.serde_path();
+
+ let impl_block = if let Some(remote) = cont.attrs.remote() {
+ let vis = &input.vis;
+ let used = pretend::pretend_used(&cont, params.is_packed);
+ quote! {
+ impl #impl_generics #ident #ty_generics #where_clause {
+ #vis fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> #serde::__private::Result<__S::Ok, __S::Error>
+ where
+ __S: #serde::Serializer,
+ {
+ #used
+ #body
+ }
+ }
+ }
+ } else {
+ quote! {
+ #[automatically_derived]
+ impl #impl_generics #serde::Serialize for #ident #ty_generics #where_clause {
+ fn serialize<__S>(&self, __serializer: __S) -> #serde::__private::Result<__S::Ok, __S::Error>
+ where
+ __S: #serde::Serializer,
+ {
+ #body
+ }
+ }
+ }
+ };
+
+ Ok(dummy::wrap_in_const(
+ cont.attrs.custom_serde_path(),
+ impl_block,
+ ))
+}
+
+fn precondition(cx: &Ctxt, cont: &Container) {
+ match cont.attrs.identifier() {
+ attr::Identifier::No => {}
+ attr::Identifier::Field => {
+ cx.error_spanned_by(cont.original, "field identifiers cannot be serialized");
+ }
+ attr::Identifier::Variant => {
+ cx.error_spanned_by(cont.original, "variant identifiers cannot be serialized");
+ }
+ }
+}
+
+struct Parameters {
+ /// Variable holding the value being serialized. Either `self` for local
+ /// types or `__self` for remote types.
+ self_var: 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,
+
+ /// Type has a `serde(remote = "...")` attribute.
+ is_remote: bool,
+
+ /// Type has a repr(packed) attribute.
+ is_packed: bool,
+}
+
+impl Parameters {
+ fn new(cont: &Container) -> Self {
+ let is_remote = cont.attrs.remote().is_some();
+ let self_var = if is_remote {
+ Ident::new("__self", Span::call_site())
+ } else {
+ Ident::new("self", Span::call_site())
+ };
+
+ let this_type = this::this_type(cont);
+ let this_value = this::this_value(cont);
+ let is_packed = cont.attrs.is_packed();
+ let generics = build_generics(cont);
+
+ Parameters {
+ self_var,
+ this_type,
+ this_value,
+ generics,
+ is_remote,
+ is_packed,
+ }
+ }
+
+ /// Type name to use in error messages and `&'static str` arguments to
+ /// various Serializer methods.
+ fn type_name(&self) -> String {
+ self.this_type.segments.last().unwrap().ident.to_string()
+ }
+}
+
+// All the generics in the input, plus a bound `T: Serialize` for each generic
+// field type that will be serialized by us.
+fn build_generics(cont: &Container) -> syn::Generics {
+ let generics = bound::without_defaults(cont.generics);
+
+ let generics =
+ bound::with_where_predicates_from_fields(cont, &generics, attr::Field::ser_bound);
+
+ let generics =
+ bound::with_where_predicates_from_variants(cont, &generics, attr::Variant::ser_bound);
+
+ match cont.attrs.ser_bound() {
+ Some(predicates) => bound::with_where_predicates(&generics, predicates),
+ None => bound::with_bound(
+ cont,
+ &generics,
+ needs_serialize_bound,
+ &parse_quote!(_serde::Serialize),
+ ),
+ }
+}
+
+// Fields with a `skip_serializing` or `serialize_with` attribute, or which
+// belong to a variant with a 'skip_serializing` or `serialize_with` attribute,
+// are not serialized 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: Serialize` bound where T is the type of the field.
+fn needs_serialize_bound(field: &attr::Field, variant: Option<&attr::Variant>) -> bool {
+ !field.skip_serializing()
+ && field.serialize_with().is_none()
+ && field.ser_bound().is_none()
+ && variant.map_or(true, |variant| {
+ !variant.skip_serializing()
+ && variant.serialize_with().is_none()
+ && variant.ser_bound().is_none()
+ })
+}
+
+fn serialize_body(cont: &Container, params: &Parameters) -> Fragment {
+ if cont.attrs.transparent() {
+ serialize_transparent(cont, params)
+ } else if let Some(type_into) = cont.attrs.type_into() {
+ serialize_into(params, type_into)
+ } else {
+ match &cont.data {
+ Data::Enum(variants) => serialize_enum(params, variants, &cont.attrs),
+ Data::Struct(Style::Struct, fields) => serialize_struct(params, fields, &cont.attrs),
+ Data::Struct(Style::Tuple, fields) => {
+ serialize_tuple_struct(params, fields, &cont.attrs)
+ }
+ Data::Struct(Style::Newtype, fields) => {
+ serialize_newtype_struct(params, &fields[0], &cont.attrs)
+ }
+ Data::Struct(Style::Unit, _) => serialize_unit_struct(&cont.attrs),
+ }
+ }
+}
+
+fn serialize_transparent(cont: &Container, params: &Parameters) -> Fragment {
+ let fields = match &cont.data {
+ Data::Struct(_, fields) => fields,
+ Data::Enum(_) => unreachable!(),
+ };
+
+ let self_var = &params.self_var;
+ let transparent_field = fields.iter().find(|f| f.attrs.transparent()).unwrap();
+ let member = &transparent_field.member;
+
+ let path = match transparent_field.attrs.serialize_with() {
+ Some(path) => quote!(#path),
+ None => {
+ let span = transparent_field.original.span();
+ quote_spanned!(span=> _serde::Serialize::serialize)
+ }
+ };
+
+ quote_block! {
+ #path(&#self_var.#member, __serializer)
+ }
+}
+
+fn serialize_into(params: &Parameters, type_into: &syn::Type) -> Fragment {
+ let self_var = &params.self_var;
+ quote_block! {
+ _serde::Serialize::serialize(
+ &_serde::__private::Into::<#type_into>::into(_serde::__private::Clone::clone(#self_var)),
+ __serializer)
+ }
+}
+
+fn serialize_unit_struct(cattrs: &attr::Container) -> Fragment {
+ let type_name = cattrs.name().serialize_name();
+
+ quote_expr! {
+ _serde::Serializer::serialize_unit_struct(__serializer, #type_name)
+ }
+}
+
+fn serialize_newtype_struct(
+ params: &Parameters,
+ field: &Field,
+ cattrs: &attr::Container,
+) -> Fragment {
+ let type_name = cattrs.name().serialize_name();
+
+ let mut field_expr = get_member(
+ params,
+ field,
+ &Member::Unnamed(Index {
+ index: 0,
+ span: Span::call_site(),
+ }),
+ );
+ if let Some(path) = field.attrs.serialize_with() {
+ field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
+ }
+
+ let span = field.original.span();
+ let func = quote_spanned!(span=> _serde::Serializer::serialize_newtype_struct);
+ quote_expr! {
+ #func(__serializer, #type_name, #field_expr)
+ }
+}
+
+fn serialize_tuple_struct(
+ params: &Parameters,
+ fields: &[Field],
+ cattrs: &attr::Container,
+) -> Fragment {
+ let serialize_stmts =
+ serialize_tuple_struct_visitor(fields, params, false, &TupleTrait::SerializeTupleStruct);
+
+ let type_name = cattrs.name().serialize_name();
+
+ let mut serialized_fields = fields
+ .iter()
+ .enumerate()
+ .filter(|(_, field)| !field.attrs.skip_serializing())
+ .peekable();
+
+ let let_mut = mut_if(serialized_fields.peek().is_some());
+
+ let len = serialized_fields
+ .map(|(i, field)| match field.attrs.skip_serializing_if() {
+ None => quote!(1),
+ Some(path) => {
+ let index = syn::Index {
+ index: i as u32,
+ span: Span::call_site(),
+ };
+ let field_expr = get_member(params, field, &Member::Unnamed(index));
+ quote!(if #path(#field_expr) { 0 } else { 1 })
+ }
+ })
+ .fold(quote!(0), |sum, expr| quote!(#sum + #expr));
+
+ quote_block! {
+ let #let_mut __serde_state = _serde::Serializer::serialize_tuple_struct(__serializer, #type_name, #len)?;
+ #(#serialize_stmts)*
+ _serde::ser::SerializeTupleStruct::end(__serde_state)
+ }
+}
+
+fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Container) -> Fragment {
+ assert!(fields.len() as u64 <= u64::from(u32::max_value()));
+
+ if cattrs.has_flatten() {
+ serialize_struct_as_map(params, fields, cattrs)
+ } else {
+ serialize_struct_as_struct(params, fields, cattrs)
+ }
+}
+
+fn serialize_struct_tag_field(cattrs: &attr::Container, struct_trait: &StructTrait) -> TokenStream {
+ match cattrs.tag() {
+ attr::TagType::Internal { tag } => {
+ let type_name = cattrs.name().serialize_name();
+ let func = struct_trait.serialize_field(Span::call_site());
+ quote! {
+ #func(&mut __serde_state, #tag, #type_name)?;
+ }
+ }
+ _ => quote! {},
+ }
+}
+
+fn serialize_struct_as_struct(
+ params: &Parameters,
+ fields: &[Field],
+ cattrs: &attr::Container,
+) -> Fragment {
+ let serialize_fields =
+ serialize_struct_visitor(fields, params, false, &StructTrait::SerializeStruct);
+
+ let type_name = cattrs.name().serialize_name();
+
+ let tag_field = serialize_struct_tag_field(cattrs, &StructTrait::SerializeStruct);
+ let tag_field_exists = !tag_field.is_empty();
+
+ let mut serialized_fields = fields
+ .iter()
+ .filter(|&field| !field.attrs.skip_serializing())
+ .peekable();
+
+ let let_mut = mut_if(serialized_fields.peek().is_some() || tag_field_exists);
+
+ let len = serialized_fields
+ .map(|field| match field.attrs.skip_serializing_if() {
+ None => quote!(1),
+ Some(path) => {
+ let field_expr = get_member(params, field, &field.member);
+ quote!(if #path(#field_expr) { 0 } else { 1 })
+ }
+ })
+ .fold(
+ quote!(#tag_field_exists as usize),
+ |sum, expr| quote!(#sum + #expr),
+ );
+
+ quote_block! {
+ let #let_mut __serde_state = _serde::Serializer::serialize_struct(__serializer, #type_name, #len)?;
+ #tag_field
+ #(#serialize_fields)*
+ _serde::ser::SerializeStruct::end(__serde_state)
+ }
+}
+
+fn serialize_struct_as_map(
+ params: &Parameters,
+ fields: &[Field],
+ cattrs: &attr::Container,
+) -> Fragment {
+ let serialize_fields =
+ serialize_struct_visitor(fields, params, false, &StructTrait::SerializeMap);
+
+ let tag_field = serialize_struct_tag_field(cattrs, &StructTrait::SerializeMap);
+ let tag_field_exists = !tag_field.is_empty();
+
+ let mut serialized_fields = fields
+ .iter()
+ .filter(|&field| !field.attrs.skip_serializing())
+ .peekable();
+
+ let let_mut = mut_if(serialized_fields.peek().is_some() || tag_field_exists);
+
+ let len = if cattrs.has_flatten() {
+ quote!(_serde::__private::None)
+ } else {
+ let len = serialized_fields
+ .map(|field| match field.attrs.skip_serializing_if() {
+ None => quote!(1),
+ Some(path) => {
+ let field_expr = get_member(params, field, &field.member);
+ quote!(if #path(#field_expr) { 0 } else { 1 })
+ }
+ })
+ .fold(
+ quote!(#tag_field_exists as usize),
+ |sum, expr| quote!(#sum + #expr),
+ );
+ quote!(_serde::__private::Some(#len))
+ };
+
+ quote_block! {
+ let #let_mut __serde_state = _serde::Serializer::serialize_map(__serializer, #len)?;
+ #tag_field
+ #(#serialize_fields)*
+ _serde::ser::SerializeMap::end(__serde_state)
+ }
+}
+
+fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Container) -> Fragment {
+ assert!(variants.len() as u64 <= u64::from(u32::max_value()));
+
+ let self_var = &params.self_var;
+
+ let mut arms: Vec<_> = variants
+ .iter()
+ .enumerate()
+ .map(|(variant_index, variant)| {
+ serialize_variant(params, variant, variant_index as u32, cattrs)
+ })
+ .collect();
+
+ if cattrs.remote().is_some() && cattrs.non_exhaustive() {
+ arms.push(quote! {
+ ref unrecognized => _serde::__private::Err(_serde::ser::Error::custom(_serde::__private::ser::CannotSerializeVariant(unrecognized))),
+ });
+ }
+
+ quote_expr! {
+ match *#self_var {
+ #(#arms)*
+ }
+ }
+}
+
+fn serialize_variant(
+ params: &Parameters,
+ variant: &Variant,
+ variant_index: u32,
+ cattrs: &attr::Container,
+) -> TokenStream {
+ let this_value = &params.this_value;
+ let variant_ident = &variant.ident;
+
+ if variant.attrs.skip_serializing() {
+ let skipped_msg = format!(
+ "the enum variant {}::{} cannot be serialized",
+ params.type_name(),
+ variant_ident
+ );
+ let skipped_err = quote! {
+ _serde::__private::Err(_serde::ser::Error::custom(#skipped_msg))
+ };
+ let fields_pat = match variant.style {
+ Style::Unit => quote!(),
+ Style::Newtype | Style::Tuple => quote!((..)),
+ Style::Struct => quote!({ .. }),
+ };
+ quote! {
+ #this_value::#variant_ident #fields_pat => #skipped_err,
+ }
+ } else {
+ // variant wasn't skipped
+ let case = match variant.style {
+ Style::Unit => {
+ quote! {
+ #this_value::#variant_ident
+ }
+ }
+ Style::Newtype => {
+ quote! {
+ #this_value::#variant_ident(ref __field0)
+ }
+ }
+ Style::Tuple => {
+ let field_names = (0..variant.fields.len())
+ .map(|i| Ident::new(&format!("__field{}", i), Span::call_site()));
+ quote! {
+ #this_value::#variant_ident(#(ref #field_names),*)
+ }
+ }
+ Style::Struct => {
+ let members = variant.fields.iter().map(|f| &f.member);
+ quote! {
+ #this_value::#variant_ident { #(ref #members),* }
+ }
+ }
+ };
+
+ let body = Match(match (cattrs.tag(), variant.attrs.untagged()) {
+ (attr::TagType::External, false) => {
+ serialize_externally_tagged_variant(params, variant, variant_index, cattrs)
+ }
+ (attr::TagType::Internal { tag }, false) => {
+ serialize_internally_tagged_variant(params, variant, cattrs, tag)
+ }
+ (attr::TagType::Adjacent { tag, content }, false) => {
+ serialize_adjacently_tagged_variant(
+ params,
+ variant,
+ cattrs,
+ variant_index,
+ tag,
+ content,
+ )
+ }
+ (attr::TagType::None, _) | (_, true) => {
+ serialize_untagged_variant(params, variant, cattrs)
+ }
+ });
+
+ quote! {
+ #case => #body
+ }
+ }
+}
+
+fn serialize_externally_tagged_variant(
+ params: &Parameters,
+ variant: &Variant,
+ variant_index: u32,
+ cattrs: &attr::Container,
+) -> Fragment {
+ let type_name = cattrs.name().serialize_name();
+ let variant_name = variant.attrs.name().serialize_name();
+
+ if let Some(path) = variant.attrs.serialize_with() {
+ let ser = wrap_serialize_variant_with(params, path, variant);
+ return quote_expr! {
+ _serde::Serializer::serialize_newtype_variant(
+ __serializer,
+ #type_name,
+ #variant_index,
+ #variant_name,
+ #ser,
+ )
+ };
+ }
+
+ match effective_style(variant) {
+ Style::Unit => {
+ quote_expr! {
+ _serde::Serializer::serialize_unit_variant(
+ __serializer,
+ #type_name,
+ #variant_index,
+ #variant_name,
+ )
+ }
+ }
+ Style::Newtype => {
+ let field = &variant.fields[0];
+ let mut field_expr = quote!(__field0);
+ if let Some(path) = field.attrs.serialize_with() {
+ field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
+ }
+
+ let span = field.original.span();
+ let func = quote_spanned!(span=> _serde::Serializer::serialize_newtype_variant);
+ quote_expr! {
+ #func(
+ __serializer,
+ #type_name,
+ #variant_index,
+ #variant_name,
+ #field_expr,
+ )
+ }
+ }
+ Style::Tuple => serialize_tuple_variant(
+ TupleVariant::ExternallyTagged {
+ type_name,
+ variant_index,
+ variant_name,
+ },
+ params,
+ &variant.fields,
+ ),
+ Style::Struct => serialize_struct_variant(
+ StructVariant::ExternallyTagged {
+ variant_index,
+ variant_name,
+ },
+ params,
+ &variant.fields,
+ type_name,
+ ),
+ }
+}
+
+fn serialize_internally_tagged_variant(
+ params: &Parameters,
+ variant: &Variant,
+ cattrs: &attr::Container,
+ tag: &str,
+) -> Fragment {
+ let type_name = cattrs.name().serialize_name();
+ let variant_name = variant.attrs.name().serialize_name();
+
+ let enum_ident_str = params.type_name();
+ let variant_ident_str = variant.ident.to_string();
+
+ if let Some(path) = variant.attrs.serialize_with() {
+ let ser = wrap_serialize_variant_with(params, path, variant);
+ return quote_expr! {
+ _serde::__private::ser::serialize_tagged_newtype(
+ __serializer,
+ #enum_ident_str,
+ #variant_ident_str,
+ #tag,
+ #variant_name,
+ #ser,
+ )
+ };
+ }
+
+ match effective_style(variant) {
+ Style::Unit => {
+ quote_block! {
+ let mut __struct = _serde::Serializer::serialize_struct(
+ __serializer, #type_name, 1)?;
+ _serde::ser::SerializeStruct::serialize_field(
+ &mut __struct, #tag, #variant_name)?;
+ _serde::ser::SerializeStruct::end(__struct)
+ }
+ }
+ Style::Newtype => {
+ let field = &variant.fields[0];
+ let mut field_expr = quote!(__field0);
+ if let Some(path) = field.attrs.serialize_with() {
+ field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
+ }
+
+ let span = field.original.span();
+ let func = quote_spanned!(span=> _serde::__private::ser::serialize_tagged_newtype);
+ quote_expr! {
+ #func(
+ __serializer,
+ #enum_ident_str,
+ #variant_ident_str,
+ #tag,
+ #variant_name,
+ #field_expr,
+ )
+ }
+ }
+ Style::Struct => serialize_struct_variant(
+ StructVariant::InternallyTagged { tag, variant_name },
+ params,
+ &variant.fields,
+ type_name,
+ ),
+ Style::Tuple => unreachable!("checked in serde_derive_internals"),
+ }
+}
+
+fn serialize_adjacently_tagged_variant(
+ params: &Parameters,
+ variant: &Variant,
+ cattrs: &attr::Container,
+ variant_index: u32,
+ tag: &str,
+ content: &str,
+) -> Fragment {
+ let this_type = &params.this_type;
+ let type_name = cattrs.name().serialize_name();
+ let variant_name = variant.attrs.name().serialize_name();
+ let serialize_variant = quote! {
+ &_serde::__private::ser::AdjacentlyTaggedEnumVariant {
+ enum_name: #type_name,
+ variant_index: #variant_index,
+ variant_name: #variant_name,
+ }
+ };
+
+ let inner = Stmts(if let Some(path) = variant.attrs.serialize_with() {
+ let ser = wrap_serialize_variant_with(params, path, variant);
+ quote_expr! {
+ _serde::Serialize::serialize(#ser, __serializer)
+ }
+ } else {
+ match effective_style(variant) {
+ Style::Unit => {
+ return quote_block! {
+ let mut __struct = _serde::Serializer::serialize_struct(
+ __serializer, #type_name, 1)?;
+ _serde::ser::SerializeStruct::serialize_field(
+ &mut __struct, #tag, #serialize_variant)?;
+ _serde::ser::SerializeStruct::end(__struct)
+ };
+ }
+ Style::Newtype => {
+ let field = &variant.fields[0];
+ let mut field_expr = quote!(__field0);
+ if let Some(path) = field.attrs.serialize_with() {
+ field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
+ }
+
+ let span = field.original.span();
+ let func = quote_spanned!(span=> _serde::ser::SerializeStruct::serialize_field);
+ return quote_block! {
+ let mut __struct = _serde::Serializer::serialize_struct(
+ __serializer, #type_name, 2)?;
+ _serde::ser::SerializeStruct::serialize_field(
+ &mut __struct, #tag, #serialize_variant)?;
+ #func(
+ &mut __struct, #content, #field_expr)?;
+ _serde::ser::SerializeStruct::end(__struct)
+ };
+ }
+ Style::Tuple => {
+ serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields)
+ }
+ Style::Struct => serialize_struct_variant(
+ StructVariant::Untagged,
+ params,
+ &variant.fields,
+ variant_name,
+ ),
+ }
+ });
+
+ let fields_ty = variant.fields.iter().map(|f| &f.ty);
+ let fields_ident: &[_] = &match variant.style {
+ Style::Unit => {
+ if variant.attrs.serialize_with().is_some() {
+ vec![]
+ } else {
+ unreachable!()
+ }
+ }
+ Style::Newtype => vec![Member::Named(Ident::new("__field0", Span::call_site()))],
+ Style::Tuple => (0..variant.fields.len())
+ .map(|i| Member::Named(Ident::new(&format!("__field{}", i), Span::call_site())))
+ .collect(),
+ Style::Struct => variant.fields.iter().map(|f| f.member.clone()).collect(),
+ };
+
+ let (_, ty_generics, where_clause) = params.generics.split_for_impl();
+
+ let wrapper_generics = if fields_ident.is_empty() {
+ params.generics.clone()
+ } else {
+ bound::with_lifetime_bound(&params.generics, "'__a")
+ };
+ let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
+
+ quote_block! {
+ #[doc(hidden)]
+ struct __AdjacentlyTagged #wrapper_generics #where_clause {
+ data: (#(&'__a #fields_ty,)*),
+ phantom: _serde::__private::PhantomData<#this_type #ty_generics>,
+ }
+
+ impl #wrapper_impl_generics _serde::Serialize for __AdjacentlyTagged #wrapper_ty_generics #where_clause {
+ fn serialize<__S>(&self, __serializer: __S) -> _serde::__private::Result<__S::Ok, __S::Error>
+ where
+ __S: _serde::Serializer,
+ {
+ // Elements that have skip_serializing will be unused.
+ #[allow(unused_variables)]
+ let (#(#fields_ident,)*) = self.data;
+ #inner
+ }
+ }
+
+ let mut __struct = _serde::Serializer::serialize_struct(
+ __serializer, #type_name, 2)?;
+ _serde::ser::SerializeStruct::serialize_field(
+ &mut __struct, #tag, #serialize_variant)?;
+ _serde::ser::SerializeStruct::serialize_field(
+ &mut __struct, #content, &__AdjacentlyTagged {
+ data: (#(#fields_ident,)*),
+ phantom: _serde::__private::PhantomData::<#this_type #ty_generics>,
+ })?;
+ _serde::ser::SerializeStruct::end(__struct)
+ }
+}
+
+fn serialize_untagged_variant(
+ params: &Parameters,
+ variant: &Variant,
+ cattrs: &attr::Container,
+) -> Fragment {
+ if let Some(path) = variant.attrs.serialize_with() {
+ let ser = wrap_serialize_variant_with(params, path, variant);
+ return quote_expr! {
+ _serde::Serialize::serialize(#ser, __serializer)
+ };
+ }
+
+ match effective_style(variant) {
+ Style::Unit => {
+ quote_expr! {
+ _serde::Serializer::serialize_unit(__serializer)
+ }
+ }
+ Style::Newtype => {
+ let field = &variant.fields[0];
+ let mut field_expr = quote!(__field0);
+ if let Some(path) = field.attrs.serialize_with() {
+ field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
+ }
+
+ let span = field.original.span();
+ let func = quote_spanned!(span=> _serde::Serialize::serialize);
+ quote_expr! {
+ #func(#field_expr, __serializer)
+ }
+ }
+ Style::Tuple => serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields),
+ Style::Struct => {
+ let type_name = cattrs.name().serialize_name();
+ serialize_struct_variant(StructVariant::Untagged, params, &variant.fields, type_name)
+ }
+ }
+}
+
+enum TupleVariant<'a> {
+ ExternallyTagged {
+ type_name: &'a str,
+ variant_index: u32,
+ variant_name: &'a str,
+ },
+ Untagged,
+}
+
+fn serialize_tuple_variant(
+ context: TupleVariant,
+ params: &Parameters,
+ fields: &[Field],
+) -> Fragment {
+ let tuple_trait = match context {
+ TupleVariant::ExternallyTagged { .. } => TupleTrait::SerializeTupleVariant,
+ TupleVariant::Untagged => TupleTrait::SerializeTuple,
+ };
+
+ let serialize_stmts = serialize_tuple_struct_visitor(fields, params, true, &tuple_trait);
+
+ let mut serialized_fields = fields
+ .iter()
+ .enumerate()
+ .filter(|(_, field)| !field.attrs.skip_serializing())
+ .peekable();
+
+ let let_mut = mut_if(serialized_fields.peek().is_some());
+
+ let len = serialized_fields
+ .map(|(i, field)| match field.attrs.skip_serializing_if() {
+ None => quote!(1),
+ Some(path) => {
+ let field_expr = Ident::new(&format!("__field{}", i), Span::call_site());
+ quote!(if #path(#field_expr) { 0 } else { 1 })
+ }
+ })
+ .fold(quote!(0), |sum, expr| quote!(#sum + #expr));
+
+ match context {
+ TupleVariant::ExternallyTagged {
+ type_name,
+ variant_index,
+ variant_name,
+ } => {
+ quote_block! {
+ let #let_mut __serde_state = _serde::Serializer::serialize_tuple_variant(
+ __serializer,
+ #type_name,
+ #variant_index,
+ #variant_name,
+ #len)?;
+ #(#serialize_stmts)*
+ _serde::ser::SerializeTupleVariant::end(__serde_state)
+ }
+ }
+ TupleVariant::Untagged => {
+ quote_block! {
+ let #let_mut __serde_state = _serde::Serializer::serialize_tuple(
+ __serializer,
+ #len)?;
+ #(#serialize_stmts)*
+ _serde::ser::SerializeTuple::end(__serde_state)
+ }
+ }
+ }
+}
+
+enum StructVariant<'a> {
+ ExternallyTagged {
+ variant_index: u32,
+ variant_name: &'a str,
+ },
+ InternallyTagged {
+ tag: &'a str,
+ variant_name: &'a str,
+ },
+ Untagged,
+}
+
+fn serialize_struct_variant(
+ context: StructVariant,
+ params: &Parameters,
+ fields: &[Field],
+ name: &str,
+) -> Fragment {
+ if fields.iter().any(|field| field.attrs.flatten()) {
+ return serialize_struct_variant_with_flatten(context, params, fields, name);
+ }
+
+ let struct_trait = match context {
+ StructVariant::ExternallyTagged { .. } => StructTrait::SerializeStructVariant,
+ StructVariant::InternallyTagged { .. } | StructVariant::Untagged => {
+ StructTrait::SerializeStruct
+ }
+ };
+
+ let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait);
+
+ let mut serialized_fields = fields
+ .iter()
+ .filter(|&field| !field.attrs.skip_serializing())
+ .peekable();
+
+ let let_mut = mut_if(serialized_fields.peek().is_some());
+
+ let len = serialized_fields
+ .map(|field| {
+ let member = &field.member;
+
+ match field.attrs.skip_serializing_if() {
+ Some(path) => quote!(if #path(#member) { 0 } else { 1 }),
+ None => quote!(1),
+ }
+ })
+ .fold(quote!(0), |sum, expr| quote!(#sum + #expr));
+
+ match context {
+ StructVariant::ExternallyTagged {
+ variant_index,
+ variant_name,
+ } => {
+ quote_block! {
+ let #let_mut __serde_state = _serde::Serializer::serialize_struct_variant(
+ __serializer,
+ #name,
+ #variant_index,
+ #variant_name,
+ #len,
+ )?;
+ #(#serialize_fields)*
+ _serde::ser::SerializeStructVariant::end(__serde_state)
+ }
+ }
+ StructVariant::InternallyTagged { tag, variant_name } => {
+ quote_block! {
+ let mut __serde_state = _serde::Serializer::serialize_struct(
+ __serializer,
+ #name,
+ #len + 1,
+ )?;
+ _serde::ser::SerializeStruct::serialize_field(
+ &mut __serde_state,
+ #tag,
+ #variant_name,
+ )?;
+ #(#serialize_fields)*
+ _serde::ser::SerializeStruct::end(__serde_state)
+ }
+ }
+ StructVariant::Untagged => {
+ quote_block! {
+ let #let_mut __serde_state = _serde::Serializer::serialize_struct(
+ __serializer,
+ #name,
+ #len,
+ )?;
+ #(#serialize_fields)*
+ _serde::ser::SerializeStruct::end(__serde_state)
+ }
+ }
+ }
+}
+
+fn serialize_struct_variant_with_flatten(
+ context: StructVariant,
+ params: &Parameters,
+ fields: &[Field],
+ name: &str,
+) -> Fragment {
+ let struct_trait = StructTrait::SerializeMap;
+ let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait);
+
+ let mut serialized_fields = fields
+ .iter()
+ .filter(|&field| !field.attrs.skip_serializing())
+ .peekable();
+
+ let let_mut = mut_if(serialized_fields.peek().is_some());
+
+ match context {
+ StructVariant::ExternallyTagged {
+ variant_index,
+ variant_name,
+ } => {
+ let this_type = &params.this_type;
+ let fields_ty = fields.iter().map(|f| &f.ty);
+ let members = &fields.iter().map(|f| &f.member).collect::<Vec<_>>();
+
+ let (_, ty_generics, where_clause) = params.generics.split_for_impl();
+ let wrapper_generics = bound::with_lifetime_bound(&params.generics, "'__a");
+ let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
+
+ quote_block! {
+ #[doc(hidden)]
+ struct __EnumFlatten #wrapper_generics #where_clause {
+ data: (#(&'__a #fields_ty,)*),
+ phantom: _serde::__private::PhantomData<#this_type #ty_generics>,
+ }
+
+ impl #wrapper_impl_generics _serde::Serialize for __EnumFlatten #wrapper_ty_generics #where_clause {
+ fn serialize<__S>(&self, __serializer: __S) -> _serde::__private::Result<__S::Ok, __S::Error>
+ where
+ __S: _serde::Serializer,
+ {
+ let (#(#members,)*) = self.data;
+ let #let_mut __serde_state = _serde::Serializer::serialize_map(
+ __serializer,
+ _serde::__private::None)?;
+ #(#serialize_fields)*
+ _serde::ser::SerializeMap::end(__serde_state)
+ }
+ }
+
+ _serde::Serializer::serialize_newtype_variant(
+ __serializer,
+ #name,
+ #variant_index,
+ #variant_name,
+ &__EnumFlatten {
+ data: (#(#members,)*),
+ phantom: _serde::__private::PhantomData::<#this_type #ty_generics>,
+ })
+ }
+ }
+ StructVariant::InternallyTagged { tag, variant_name } => {
+ quote_block! {
+ let #let_mut __serde_state = _serde::Serializer::serialize_map(
+ __serializer,
+ _serde::__private::None)?;
+ _serde::ser::SerializeMap::serialize_entry(
+ &mut __serde_state,
+ #tag,
+ #variant_name,
+ )?;
+ #(#serialize_fields)*
+ _serde::ser::SerializeMap::end(__serde_state)
+ }
+ }
+ StructVariant::Untagged => {
+ quote_block! {
+ let #let_mut __serde_state = _serde::Serializer::serialize_map(
+ __serializer,
+ _serde::__private::None)?;
+ #(#serialize_fields)*
+ _serde::ser::SerializeMap::end(__serde_state)
+ }
+ }
+ }
+}
+
+fn serialize_tuple_struct_visitor(
+ fields: &[Field],
+ params: &Parameters,
+ is_enum: bool,
+ tuple_trait: &TupleTrait,
+) -> Vec<TokenStream> {
+ fields
+ .iter()
+ .enumerate()
+ .filter(|(_, field)| !field.attrs.skip_serializing())
+ .map(|(i, field)| {
+ let mut field_expr = if is_enum {
+ let id = Ident::new(&format!("__field{}", i), Span::call_site());
+ quote!(#id)
+ } else {
+ get_member(
+ params,
+ field,
+ &Member::Unnamed(Index {
+ index: i as u32,
+ span: Span::call_site(),
+ }),
+ )
+ };
+
+ let skip = field
+ .attrs
+ .skip_serializing_if()
+ .map(|path| quote!(#path(#field_expr)));
+
+ if let Some(path) = field.attrs.serialize_with() {
+ field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
+ }
+
+ let span = field.original.span();
+ let func = tuple_trait.serialize_element(span);
+ let ser = quote! {
+ #func(&mut __serde_state, #field_expr)?;
+ };
+
+ match skip {
+ None => ser,
+ Some(skip) => quote!(if !#skip { #ser }),
+ }
+ })
+ .collect()
+}
+
+fn serialize_struct_visitor(
+ fields: &[Field],
+ params: &Parameters,
+ is_enum: bool,
+ struct_trait: &StructTrait,
+) -> Vec<TokenStream> {
+ fields
+ .iter()
+ .filter(|&field| !field.attrs.skip_serializing())
+ .map(|field| {
+ let member = &field.member;
+
+ let mut field_expr = if is_enum {
+ quote!(#member)
+ } else {
+ get_member(params, field, member)
+ };
+
+ let key_expr = field.attrs.name().serialize_name();
+
+ let skip = field
+ .attrs
+ .skip_serializing_if()
+ .map(|path| quote!(#path(#field_expr)));
+
+ if let Some(path) = field.attrs.serialize_with() {
+ field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
+ }
+
+ let span = field.original.span();
+ let ser = if field.attrs.flatten() {
+ let func = quote_spanned!(span=> _serde::Serialize::serialize);
+ quote! {
+ #func(&#field_expr, _serde::__private::ser::FlatMapSerializer(&mut __serde_state))?;
+ }
+ } else {
+ let func = struct_trait.serialize_field(span);
+ quote! {
+ #func(&mut __serde_state, #key_expr, #field_expr)?;
+ }
+ };
+
+ match skip {
+ None => ser,
+ Some(skip) => {
+ if let Some(skip_func) = struct_trait.skip_field(span) {
+ quote! {
+ if !#skip {
+ #ser
+ } else {
+ #skip_func(&mut __serde_state, #key_expr)?;
+ }
+ }
+ } else {
+ quote! {
+ if !#skip {
+ #ser
+ }
+ }
+ }
+ }
+ }
+ })
+ .collect()
+}
+
+fn wrap_serialize_field_with(
+ params: &Parameters,
+ field_ty: &syn::Type,
+ serialize_with: &syn::ExprPath,
+ field_expr: &TokenStream,
+) -> TokenStream {
+ wrap_serialize_with(params, serialize_with, &[field_ty], &[quote!(#field_expr)])
+}
+
+fn wrap_serialize_variant_with(
+ params: &Parameters,
+ serialize_with: &syn::ExprPath,
+ variant: &Variant,
+) -> TokenStream {
+ let field_tys: Vec<_> = variant.fields.iter().map(|field| field.ty).collect();
+ let field_exprs: Vec<_> = variant
+ .fields
+ .iter()
+ .map(|field| {
+ let id = match &field.member {
+ Member::Named(ident) => ident.clone(),
+ Member::Unnamed(member) => {
+ Ident::new(&format!("__field{}", member.index), Span::call_site())
+ }
+ };
+ quote!(#id)
+ })
+ .collect();
+ wrap_serialize_with(
+ params,
+ serialize_with,
+ field_tys.as_slice(),
+ field_exprs.as_slice(),
+ )
+}
+
+fn wrap_serialize_with(
+ params: &Parameters,
+ serialize_with: &syn::ExprPath,
+ field_tys: &[&syn::Type],
+ field_exprs: &[TokenStream],
+) -> TokenStream {
+ let this_type = &params.this_type;
+ let (_, ty_generics, where_clause) = params.generics.split_for_impl();
+
+ let wrapper_generics = if field_exprs.is_empty() {
+ params.generics.clone()
+ } else {
+ bound::with_lifetime_bound(&params.generics, "'__a")
+ };
+ let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
+
+ let field_access = (0..field_exprs.len()).map(|n| {
+ Member::Unnamed(Index {
+ index: n as u32,
+ span: Span::call_site(),
+ })
+ });
+
+ quote!({
+ #[doc(hidden)]
+ struct __SerializeWith #wrapper_impl_generics #where_clause {
+ values: (#(&'__a #field_tys, )*),
+ phantom: _serde::__private::PhantomData<#this_type #ty_generics>,
+ }
+
+ impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause {
+ fn serialize<__S>(&self, __s: __S) -> _serde::__private::Result<__S::Ok, __S::Error>
+ where
+ __S: _serde::Serializer,
+ {
+ #serialize_with(#(self.values.#field_access, )* __s)
+ }
+ }
+
+ &__SerializeWith {
+ values: (#(#field_exprs, )*),
+ phantom: _serde::__private::PhantomData::<#this_type #ty_generics>,
+ }
+ })
+}
+
+// Serialization of an empty struct results in code like:
+//
+// let mut __serde_state = serializer.serialize_struct("S", 0)?;
+// _serde::ser::SerializeStruct::end(__serde_state)
+//
+// where we want to omit the `mut` to avoid a warning.
+fn mut_if(is_mut: bool) -> Option<TokenStream> {
+ if is_mut {
+ Some(quote!(mut))
+ } else {
+ None
+ }
+}
+
+fn get_member(params: &Parameters, field: &Field, member: &Member) -> TokenStream {
+ let self_var = &params.self_var;
+ match (params.is_remote, field.attrs.getter()) {
+ (false, None) => {
+ if params.is_packed {
+ quote!(&{#self_var.#member})
+ } else {
+ quote!(&#self_var.#member)
+ }
+ }
+ (true, None) => {
+ let inner = if params.is_packed {
+ quote!(&{#self_var.#member})
+ } else {
+ quote!(&#self_var.#member)
+ };
+ let ty = field.ty;
+ quote!(_serde::__private::ser::constrain::<#ty>(#inner))
+ }
+ (true, Some(getter)) => {
+ let ty = field.ty;
+ quote!(_serde::__private::ser::constrain::<#ty>(&#getter(#self_var)))
+ }
+ (false, Some(_)) => {
+ unreachable!("getter is only allowed for remote impls");
+ }
+ }
+}
+
+fn effective_style(variant: &Variant) -> Style {
+ match variant.style {
+ Style::Newtype if variant.fields[0].attrs.skip_serializing() => Style::Unit,
+ other => other,
+ }
+}
+
+enum StructTrait {
+ SerializeMap,
+ SerializeStruct,
+ SerializeStructVariant,
+}
+
+impl StructTrait {
+ fn serialize_field(&self, span: Span) -> TokenStream {
+ match *self {
+ StructTrait::SerializeMap => {
+ quote_spanned!(span=> _serde::ser::SerializeMap::serialize_entry)
+ }
+ StructTrait::SerializeStruct => {
+ quote_spanned!(span=> _serde::ser::SerializeStruct::serialize_field)
+ }
+ StructTrait::SerializeStructVariant => {
+ quote_spanned!(span=> _serde::ser::SerializeStructVariant::serialize_field)
+ }
+ }
+ }
+
+ fn skip_field(&self, span: Span) -> Option<TokenStream> {
+ match *self {
+ StructTrait::SerializeMap => None,
+ StructTrait::SerializeStruct => {
+ Some(quote_spanned!(span=> _serde::ser::SerializeStruct::skip_field))
+ }
+ StructTrait::SerializeStructVariant => {
+ Some(quote_spanned!(span=> _serde::ser::SerializeStructVariant::skip_field))
+ }
+ }
+ }
+}
+
+enum TupleTrait {
+ SerializeTuple,
+ SerializeTupleStruct,
+ SerializeTupleVariant,
+}
+
+impl TupleTrait {
+ fn serialize_element(&self, span: Span) -> TokenStream {
+ match *self {
+ TupleTrait::SerializeTuple => {
+ quote_spanned!(span=> _serde::ser::SerializeTuple::serialize_element)
+ }
+ TupleTrait::SerializeTupleStruct => {
+ quote_spanned!(span=> _serde::ser::SerializeTupleStruct::serialize_field)
+ }
+ TupleTrait::SerializeTupleVariant => {
+ quote_spanned!(span=> _serde::ser::SerializeTupleVariant::serialize_field)
+ }
+ }
+ }
+}
diff --git a/third_party/rust/serde_derive/src/this.rs b/third_party/rust/serde_derive/src/this.rs
new file mode 100644
index 0000000000..941cea40c1
--- /dev/null
+++ b/third_party/rust/serde_derive/src/this.rs
@@ -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())
+ }
+}