summaryrefslogtreecommitdiffstats
path: root/vendor/serde_derive
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/serde_derive')
-rw-r--r--vendor/serde_derive/.cargo-checksum.json2
-rw-r--r--vendor/serde_derive/Cargo.toml6
-rw-r--r--vendor/serde_derive/LICENSE-APACHE25
-rw-r--r--vendor/serde_derive/README.md10
-rw-r--r--vendor/serde_derive/src/bound.rs18
-rw-r--r--vendor/serde_derive/src/de.rs36
-rw-r--r--vendor/serde_derive/src/dummy.rs6
-rw-r--r--vendor/serde_derive/src/internals/attr.rs1288
-rw-r--r--vendor/serde_derive/src/internals/check.rs63
-rw-r--r--vendor/serde_derive/src/internals/receiver.rs17
-rw-r--r--vendor/serde_derive/src/internals/symbol.rs3
-rw-r--r--vendor/serde_derive/src/lib.rs3
12 files changed, 656 insertions, 821 deletions
diff --git a/vendor/serde_derive/.cargo-checksum.json b/vendor/serde_derive/.cargo-checksum.json
index 4f033d7fe..d4d5dc569 100644
--- a/vendor/serde_derive/.cargo-checksum.json
+++ b/vendor/serde_derive/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"72ed2b0578c6c4fbbd14ab2062502092990c48f4687a01a4a07d7fdbb6330756","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"3c12b60b6c77a201665344a7612b42392e77ddc3e907f5a14e3f3a4bb6c4692e","build.rs":"d9a0df0c4dd552ff7fd0c3b3828cb1fff4fc4ab15bd98539881929b76b98003b","crates-io.md":"ee22254ee64c3189eef3e707c8d75dc66a8df2a7ee9e518d95238950780ec387","src/bound.rs":"268b4995a5d0a129dcbd6e32ef11f587bd271df3f6c4f7230ed54bc99f5ce871","src/de.rs":"b28c2fcf5214d33ba1dc855b60634db18608a26f39f9f92bbedf62c456fa8d10","src/dummy.rs":"cb154465020973be8ab6079ab8574df46f38fbe028a5561cd6b1a8bfa1a35478","src/fragment.rs":"5548ba65a53d90a296f60c1328a7a7fb040db467f59c2f5210b2fb320457145d","src/internals/ast.rs":"b019865eef92c1ddbb9029423ac22179f132dc655a51c09fb2a42f4aaef172fd","src/internals/attr.rs":"778074380c4e353b77e03aff9edf15fda9e15a0e7ec25cdfc51d79a26636ddef","src/internals/case.rs":"9492f0c5142d7b7e8cd39c86d13a855e5ce4489425adb2b96aed89e1b7851ac0","src/internals/check.rs":"6b84278b034a156784fc56153df3def1660bcfcfde0cd59f8facce1750717c7d","src/internals/ctxt.rs":"6fa544ae52914498a62a395818ebdc1b36ac2fb5903c60afb741a864ad559f1c","src/internals/mod.rs":"f32138ff19d57eb00f88ba11f6b015efab2102657804f71ebbf386a3698dad91","src/internals/receiver.rs":"cd125ba4a3dd6250ed4737555c58627bffd630a536cd7223068eed7c10a170d8","src/internals/respan.rs":"899753859c58ce5f532a3ec4584796a52f13ed5a0533191e48c953ba5c1b52ff","src/internals/symbol.rs":"3c9ce461773b7df3bb64d82aa5a0d93052c3bb0e60209db6c0b5c10ee9cfc9cf","src/lib.rs":"6a80c0114dcf9924cbbbc03f443cfd0d299be9f89ba6c4fdc2867d990aba5063","src/pretend.rs":"4aa53bf6c1350fbcfc8c4997f720cde61a8eb3aab73bb8c101b0f0a74901892b","src/ser.rs":"8f9ffe1d8bcd28bd40e8d94d688547fa1d518cc722d0292f47d951152c406dd9","src/this.rs":"a2c128955324c2994ed7cdc3fe4eeceb7ad8a0f9d071665a8378c85c8df64ce2","src/try.rs":"b171b0088c23ebf4bfa07ba457881b41ac5e547d55dd16f737ea988d34badf61"},"package":"af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"} \ No newline at end of file
+{"files":{"Cargo.toml":"bab2b45721a34200f27daa6ef33269a9e1f3ae3933c7ad96ca68c086c1ff0cbe","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"13c66875efb67f64fdec817725f34ceb07913e1ebea4adc240868d2ed581d3da","build.rs":"d9a0df0c4dd552ff7fd0c3b3828cb1fff4fc4ab15bd98539881929b76b98003b","crates-io.md":"ee22254ee64c3189eef3e707c8d75dc66a8df2a7ee9e518d95238950780ec387","src/bound.rs":"9211d852730380be8e0af9ed5daa52e61563e598eef458739025551ba76aa7c6","src/de.rs":"c6793f652a1f8161f802c60f757e5c97fb0fdd772fb2b29d471e7bff577b592b","src/dummy.rs":"31e02c3313d12c88b3b26baa49a9cb143440804b557b5255aad9a9b80b8ea1c6","src/fragment.rs":"5548ba65a53d90a296f60c1328a7a7fb040db467f59c2f5210b2fb320457145d","src/internals/ast.rs":"b019865eef92c1ddbb9029423ac22179f132dc655a51c09fb2a42f4aaef172fd","src/internals/attr.rs":"7407c6e85afd197bdbf715bd681bd171db37b2264f617e148ca340817f56e684","src/internals/case.rs":"9492f0c5142d7b7e8cd39c86d13a855e5ce4489425adb2b96aed89e1b7851ac0","src/internals/check.rs":"0449cc7653fc9e596f65028835bbb7d1545c10002c79c7608547f45a722c0040","src/internals/ctxt.rs":"6fa544ae52914498a62a395818ebdc1b36ac2fb5903c60afb741a864ad559f1c","src/internals/mod.rs":"f32138ff19d57eb00f88ba11f6b015efab2102657804f71ebbf386a3698dad91","src/internals/receiver.rs":"6b016351b8294539039095863d8c99e81dd4530d7f769003d12d4ca73cca172c","src/internals/respan.rs":"899753859c58ce5f532a3ec4584796a52f13ed5a0533191e48c953ba5c1b52ff","src/internals/symbol.rs":"2bf0287da64d28da7e8673af60f66aaf6b29efe33131e56b24d6fa55edb533ad","src/lib.rs":"31da4dfdf5df8dbce5752bc8ba85f13bdb6b418fc9f0f91e2eca73dbadbadbb3","src/pretend.rs":"4aa53bf6c1350fbcfc8c4997f720cde61a8eb3aab73bb8c101b0f0a74901892b","src/ser.rs":"8f9ffe1d8bcd28bd40e8d94d688547fa1d518cc722d0292f47d951152c406dd9","src/this.rs":"a2c128955324c2994ed7cdc3fe4eeceb7ad8a0f9d071665a8378c85c8df64ce2","src/try.rs":"b171b0088c23ebf4bfa07ba457881b41ac5e547d55dd16f737ea988d34badf61"},"package":"4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585"} \ No newline at end of file
diff --git a/vendor/serde_derive/Cargo.toml b/vendor/serde_derive/Cargo.toml
index 6258d9df1..7b761ea89 100644
--- a/vendor/serde_derive/Cargo.toml
+++ b/vendor/serde_derive/Cargo.toml
@@ -10,9 +10,9 @@
# See Cargo.toml.orig for the original contents.
[package]
-rust-version = "1.31"
+rust-version = "1.56"
name = "serde_derive"
-version = "1.0.152"
+version = "1.0.159"
authors = [
"Erick Tryzelaar <erick.tryzelaar@gmail.com>",
"David Tolnay <dtolnay@gmail.com>",
@@ -53,7 +53,7 @@ version = "1.0"
version = "1.0"
[dependencies.syn]
-version = "1.0.104"
+version = "2.0.3"
[dev-dependencies.serde]
version = "1.0"
diff --git a/vendor/serde_derive/LICENSE-APACHE b/vendor/serde_derive/LICENSE-APACHE
index 16fe87b06..1b5ec8b78 100644
--- a/vendor/serde_derive/LICENSE-APACHE
+++ b/vendor/serde_derive/LICENSE-APACHE
@@ -174,28 +174,3 @@ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
-Copyright [yyyy] [name of copyright owner]
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
diff --git a/vendor/serde_derive/README.md b/vendor/serde_derive/README.md
index c3f6575ef..d53e57234 100644
--- a/vendor/serde_derive/README.md
+++ b/vendor/serde_derive/README.md
@@ -1,13 +1,13 @@
-# Serde &emsp; [![Build Status]][actions] [![Latest Version]][crates.io] [![serde: rustc 1.13+]][Rust 1.13] [![serde_derive: rustc 1.31+]][Rust 1.31]
+# Serde &emsp; [![Build Status]][actions] [![Latest Version]][crates.io] [![serde: rustc 1.19+]][Rust 1.19] [![serde_derive: rustc 1.56+]][Rust 1.56]
[Build Status]: https://img.shields.io/github/actions/workflow/status/serde-rs/serde/ci.yml?branch=master
[actions]: https://github.com/serde-rs/serde/actions?query=branch%3Amaster
[Latest Version]: https://img.shields.io/crates/v/serde.svg
[crates.io]: https://crates.io/crates/serde
-[serde: rustc 1.13+]: https://img.shields.io/badge/serde-rustc_1.13+-lightgray.svg
-[serde_derive: rustc 1.31+]: https://img.shields.io/badge/serde_derive-rustc_1.31+-lightgray.svg
-[Rust 1.13]: https://blog.rust-lang.org/2016/11/10/Rust-1.13.html
-[Rust 1.31]: https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html
+[serde: rustc 1.19+]: https://img.shields.io/badge/serde-rustc_1.19+-lightgray.svg
+[serde_derive: rustc 1.56+]: https://img.shields.io/badge/serde_derive-rustc_1.56+-lightgray.svg
+[Rust 1.19]: https://blog.rust-lang.org/2017/07/20/Rust-1.19.html
+[Rust 1.56]: https://blog.rust-lang.org/2021/10/21/Rust-1.56.0.html
**Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.**
diff --git a/vendor/serde_derive/src/bound.rs b/vendor/serde_derive/src/bound.rs
index 74c95069c..7bdb046ea 100644
--- a/vendor/serde_derive/src/bound.rs
+++ b/vendor/serde_derive/src/bound.rs
@@ -200,10 +200,16 @@ pub fn with_bound(
for arg in &arguments.args {
match arg {
syn::GenericArgument::Type(arg) => self.visit_type(arg),
- syn::GenericArgument::Binding(arg) => self.visit_type(&arg.ty),
+ syn::GenericArgument::AssocType(arg) => self.visit_type(&arg.ty),
syn::GenericArgument::Lifetime(_)
- | syn::GenericArgument::Constraint(_)
- | syn::GenericArgument::Const(_) => {}
+ | syn::GenericArgument::Const(_)
+ | syn::GenericArgument::AssocConst(_)
+ | syn::GenericArgument::Constraint(_) => {}
+ #[cfg_attr(
+ all(test, exhaustive),
+ deny(non_exhaustive_omitted_patterns)
+ )]
+ _ => {}
}
}
}
@@ -226,7 +232,9 @@ pub fn with_bound(
fn visit_type_param_bound(&mut self, bound: &'ast syn::TypeParamBound) {
match bound {
syn::TypeParamBound::Trait(bound) => self.visit_path(&bound.path),
- syn::TypeParamBound::Lifetime(_) => {}
+ syn::TypeParamBound::Lifetime(_) | syn::TypeParamBound::Verbatim(_) => {}
+ #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ _ => {}
}
}
@@ -334,7 +342,7 @@ pub fn with_self_bound(
pub fn with_lifetime_bound(generics: &syn::Generics, lifetime: &str) -> syn::Generics {
let bound = syn::Lifetime::new(lifetime, Span::call_site());
- let def = syn::LifetimeDef {
+ let def = syn::LifetimeParam {
attrs: Vec::new(),
lifetime: bound.clone(),
colon_token: None,
diff --git a/vendor/serde_derive/src/de.rs b/vendor/serde_derive/src/de.rs
index a703adaf7..d4238f13e 100644
--- a/vendor/serde_derive/src/de.rs
+++ b/vendor/serde_derive/src/de.rs
@@ -244,9 +244,9 @@ impl BorrowedLifetimes {
}
}
- fn de_lifetime_def(&self) -> Option<syn::LifetimeDef> {
+ fn de_lifetime_param(&self) -> Option<syn::LifetimeParam> {
match self {
- BorrowedLifetimes::Borrowed(bounds) => Some(syn::LifetimeDef {
+ BorrowedLifetimes::Borrowed(bounds) => Some(syn::LifetimeParam {
attrs: Vec::new(),
lifetime: syn::Lifetime::new("'de", Span::call_site()),
colon_token: None,
@@ -954,6 +954,7 @@ fn deserialize_struct(
lifetime: _serde::__private::PhantomData,
}
};
+ let need_seed = deserializer.is_none();
let dispatch = if let Some(deserializer) = deserializer {
quote! {
_serde::Deserializer::deserialize_any(#deserializer, #visitor_expr)
@@ -999,14 +1000,14 @@ fn deserialize_struct(
_ => None,
};
- let visitor_seed = if is_enum && cattrs.has_flatten() {
+ let visitor_seed = if need_seed && is_enum && 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<'de>,
+ __D: _serde::Deserializer<#delife>,
{
_serde::Deserializer::deserialize_map(__deserializer, self)
}
@@ -1256,7 +1257,7 @@ fn deserialize_externally_tagged_enum(
// This is an empty enum like `enum Impossible {}` or an enum in which
// all variants have `#[serde(skip_deserializing)]`.
quote! {
- // FIXME: Once we drop support for Rust 1.15:
+ // 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(
@@ -2400,7 +2401,10 @@ fn deserialize_struct_as_struct_visitor(
.collect();
let fields_stmt = {
- let field_names = field_names_idents.iter().map(|(name, _, _)| name);
+ let field_names = field_names_idents
+ .iter()
+ .flat_map(|(_, _, aliases)| aliases);
+
quote_block! {
const FIELDS: &'static [&'static str] = &[ #(#field_names),* ];
}
@@ -2535,7 +2539,7 @@ fn deserialize_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 we drop support for Rust 1.15:
+ // FIXME: Once feature(exhaustive_patterns) is stable:
// let _serde::__private::None::<__Field> = try!(_serde::de::MapAccess::next_key(&mut __map));
_serde::__private::Option::map(
try!(_serde::de::MapAccess::next_key::<__Field>(&mut __map)),
@@ -2768,7 +2772,7 @@ fn deserialize_map_in_place(
let match_keys = if cattrs.deny_unknown_fields() && all_skipped {
quote! {
- // FIXME: Once we drop support for Rust 1.15:
+ // FIXME: Once feature(exhaustive_patterns) is stable:
// let _serde::__private::None::<__Field> = try!(_serde::de::MapAccess::next_key(&mut __map));
_serde::__private::Option::map(
try!(_serde::de::MapAccess::next_key::<__Field>(&mut __map)),
@@ -3007,7 +3011,7 @@ 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_def() {
+ if let Some(de_lifetime) = self.0.borrowed.de_lifetime_param() {
generics.params = Some(syn::GenericParam::Lifetime(de_lifetime))
.into_iter()
.chain(generics.params)
@@ -3042,7 +3046,7 @@ impl<'a> ToTokens for InPlaceImplGenerics<'a> {
.into_iter()
.chain(generics.params)
.collect();
- if let Some(de_lifetime) = self.0.borrowed.de_lifetime_def() {
+ if let Some(de_lifetime) = self.0.borrowed.de_lifetime_param() {
generics.params = Some(syn::GenericParam::Lifetime(de_lifetime))
.into_iter()
.chain(generics.params)
@@ -3067,8 +3071,8 @@ struct InPlaceTypeGenerics<'a>(&'a Parameters);
impl<'a> ToTokens for DeTypeGenerics<'a> {
fn to_tokens(&self, tokens: &mut TokenStream) {
let mut generics = self.0.generics.clone();
- if self.0.borrowed.de_lifetime_def().is_some() {
- let def = syn::LifetimeDef {
+ if self.0.borrowed.de_lifetime_param().is_some() {
+ let def = syn::LifetimeParam {
attrs: Vec::new(),
lifetime: syn::Lifetime::new("'de", Span::call_site()),
colon_token: None,
@@ -3093,8 +3097,8 @@ impl<'a> ToTokens for InPlaceTypeGenerics<'a> {
.chain(generics.params)
.collect();
- if self.0.borrowed.de_lifetime_def().is_some() {
- let def = syn::LifetimeDef {
+ if self.0.borrowed.de_lifetime_param().is_some() {
+ let def = syn::LifetimeParam {
attrs: Vec::new(),
lifetime: syn::Lifetime::new("'de", Span::call_site()),
colon_token: None,
@@ -3118,8 +3122,8 @@ impl<'a> DeTypeGenerics<'a> {
}
#[cfg(feature = "deserialize_in_place")]
-fn place_lifetime() -> syn::LifetimeDef {
- syn::LifetimeDef {
+fn place_lifetime() -> syn::LifetimeParam {
+ syn::LifetimeParam {
attrs: Vec::new(),
lifetime: syn::Lifetime::new("'place", Span::call_site()),
colon_token: None,
diff --git a/vendor/serde_derive/src/dummy.rs b/vendor/serde_derive/src/dummy.rs
index a02bd3762..2be502713 100644
--- a/vendor/serde_derive/src/dummy.rs
+++ b/vendor/serde_derive/src/dummy.rs
@@ -39,10 +39,6 @@ pub fn wrap_in_const(
}
}
-#[allow(deprecated)]
fn unraw(ident: &Ident) -> String {
- // str::trim_start_matches was added in 1.30, trim_left_matches deprecated
- // in 1.33. We currently support rustc back to 1.15 so we need to continue
- // to use the deprecated one.
- ident.to_string().trim_left_matches("r#").to_owned()
+ ident.to_string().trim_start_matches("r#").to_owned()
}
diff --git a/vendor/serde_derive/src/internals/attr.rs b/vendor/serde_derive/src/internals/attr.rs
index dc532484d..b0a7d08a2 100644
--- a/vendor/serde_derive/src/internals/attr.rs
+++ b/vendor/serde_derive/src/internals/attr.rs
@@ -1,16 +1,15 @@
-use internals::respan::respan;
use internals::symbol::*;
use 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;
-use syn::parse::{self, Parse, ParseStream};
+use syn::meta::ParseNestedMeta;
+use syn::parse::ParseStream;
use syn::punctuated::Punctuated;
-use syn::Ident;
-use syn::Meta::{List, NameValue, Path};
-use syn::NestedMeta::{Lit, Meta};
+use syn::{token, Ident, Lifetime};
// This module handles parsing of `#[serde(...)]` attributes. The entrypoints
// are `attr::Container::from_ast`, `attr::Variant::from_ast`, and
@@ -43,8 +42,8 @@ impl<'c, T> Attr<'c, T> {
let tokens = obj.into_token_stream();
if self.value.is_some() {
- self.cx
- .error_spanned_by(tokens, format!("duplicate serde attribute `{}`", self.name));
+ let msg = format!("duplicate serde attribute `{}`", self.name);
+ self.cx.error_spanned_by(tokens, msg);
} else {
self.tokens = tokens;
self.value = Some(value);
@@ -115,16 +114,14 @@ impl<'c, T> VecAttr<'c, T> {
self.values.push(value);
}
- fn at_most_one(mut self) -> Result<Option<T>, ()> {
+ fn at_most_one(mut self) -> Option<T> {
if self.values.len() > 1 {
let dup_token = self.first_dup_tokens;
- self.cx.error_spanned_by(
- dup_token,
- format!("duplicate serde attribute `{}`", self.name),
- );
- Err(())
+ let msg = format!("duplicate serde attribute `{}`", self.name);
+ self.cx.error_spanned_by(dup_token, msg);
+ None
} else {
- Ok(self.values.pop())
+ self.values.pop()
}
}
@@ -141,12 +138,8 @@ pub struct Name {
deserialize_aliases: Vec<String>,
}
-#[allow(deprecated)]
fn unraw(ident: &Ident) -> String {
- // str::trim_start_matches was added in 1.30, trim_left_matches deprecated
- // in 1.33. We currently support rustc back to 1.15 so we need to continue
- // to use the deprecated one.
- ident.to_string().trim_left_matches("r#").to_owned()
+ ident.to_string().trim_start_matches("r#").to_owned()
}
impl Name {
@@ -309,285 +302,212 @@ impl Container {
let mut serde_path = Attr::none(cx, CRATE);
let mut expecting = Attr::none(cx, EXPECTING);
- for meta_item in item
- .attrs
- .iter()
- .flat_map(|attr| get_serde_meta_items(cx, attr))
- .flatten()
- {
- match &meta_item {
- // Parse `#[serde(rename = "foo")]`
- Meta(NameValue(m)) if m.path == RENAME => {
- if let Ok(s) = get_lit_str(cx, RENAME, &m.lit) {
- ser_name.set(&m.path, s.value());
- de_name.set(&m.path, s.value());
- }
- }
+ for attr in &item.attrs {
+ if attr.path() != SERDE {
+ continue;
+ }
- // Parse `#[serde(rename(serialize = "foo", deserialize = "bar"))]`
- Meta(List(m)) if m.path == RENAME => {
- if let Ok((ser, de)) = get_renames(cx, &m.nested) {
- ser_name.set_opt(&m.path, ser.map(syn::LitStr::value));
- de_name.set_opt(&m.path, de.map(syn::LitStr::value));
- }
+ if let syn::Meta::List(meta) = &attr.meta {
+ if meta.tokens.is_empty() {
+ continue;
}
+ }
- // Parse `#[serde(rename_all = "foo")]`
- Meta(NameValue(m)) if m.path == RENAME_ALL => {
- if let Ok(s) = get_lit_str(cx, RENAME_ALL, &m.lit) {
- match RenameRule::from_str(&s.value()) {
- Ok(rename_rule) => {
- rename_all_ser_rule.set(&m.path, rename_rule);
- rename_all_de_rule.set(&m.path, rename_rule);
- }
- Err(err) => cx.error_spanned_by(s, err),
+ 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),
}
}
- }
-
- // Parse `#[serde(rename_all(serialize = "foo", deserialize = "bar"))]`
- Meta(List(m)) if m.path == RENAME_ALL => {
- if let Ok((ser, de)) = get_renames(cx, &m.nested) {
- if let Some(ser) = ser {
- match RenameRule::from_str(&ser.value()) {
- Ok(rename_rule) => rename_all_ser_rule.set(&m.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(&m.path, rename_rule),
- Err(err) => cx.error_spanned_by(de, 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);
+ }
}
}
}
- }
-
- // Parse `#[serde(transparent)]`
- Meta(Path(word)) if word == TRANSPARENT => {
- transparent.set_true(word);
- }
-
- // Parse `#[serde(deny_unknown_fields)]`
- Meta(Path(word)) if word == DENY_UNKNOWN_FIELDS => {
- deny_unknown_fields.set_true(word);
- }
-
- // Parse `#[serde(default)]`
- Meta(Path(word)) if word == DEFAULT => match &item.data {
- syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields {
- syn::Fields::Named(_) => {
- default.set(word, Default::Default);
- }
- syn::Fields::Unnamed(_) | syn::Fields::Unit => cx.error_spanned_by(
- fields,
- "#[serde(default)] can only be used on structs with named fields",
- ),
- },
- syn::Data::Enum(syn::DataEnum { enum_token, .. }) => cx.error_spanned_by(
- enum_token,
- "#[serde(default)] can only be used on structs with named fields",
- ),
- syn::Data::Union(syn::DataUnion { union_token, .. }) => cx.error_spanned_by(
- union_token,
- "#[serde(default)] can only be used on structs with named fields",
- ),
- },
-
- // Parse `#[serde(default = "...")]`
- Meta(NameValue(m)) if m.path == DEFAULT => {
- if let Ok(path) = parse_lit_into_expr_path(cx, DEFAULT, &m.lit) {
- match &item.data {
- syn::Data::Struct(syn::DataStruct { fields, .. }) => {
- match fields {
+ } 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(_) => {
- default.set(&m.path, Default::Path(path));
+ default.set(&meta.path, Default::Path(path));
}
- syn::Fields::Unnamed(_) | syn::Fields::Unit => cx
- .error_spanned_by(
- fields,
- "#[serde(default = \"...\")] can only be used on structs with named fields",
- ),
+ syn::Fields::Unnamed(_) | syn::Fields::Unit => {
+ let msg = "#[serde(default = \"...\")] can only be used on structs with named fields";
+ cx.error_spanned_by(fields, msg);
+ }
+ },
+ syn::Data::Enum(syn::DataEnum { enum_token, .. }) => {
+ let msg = "#[serde(default = \"...\")] can only be used on structs with named fields";
+ cx.error_spanned_by(enum_token, msg);
+ }
+ syn::Data::Union(syn::DataUnion { union_token, .. }) => {
+ let msg = "#[serde(default = \"...\")] can only be used on structs with named fields";
+ cx.error_spanned_by(union_token, msg);
}
}
- syn::Data::Enum(syn::DataEnum { enum_token, .. }) => cx
- .error_spanned_by(
- enum_token,
- "#[serde(default = \"...\")] can only be used on structs with named fields",
- ),
- syn::Data::Union(syn::DataUnion {
- union_token, ..
- }) => cx.error_spanned_by(
- union_token,
- "#[serde(default = \"...\")] can only be used on structs with named fields",
- ),
+ }
+ } else {
+ // #[serde(default)]
+ match &item.data {
+ syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields {
+ syn::Fields::Named(_) => {
+ default.set(meta.path, Default::Default);
+ }
+ syn::Fields::Unnamed(_) | syn::Fields::Unit => {
+ let msg = "#[serde(default)] can only be used on structs with named fields";
+ cx.error_spanned_by(fields, msg);
+ }
+ },
+ syn::Data::Enum(syn::DataEnum { enum_token, .. }) => {
+ let msg = "#[serde(default)] can only be used on structs with named fields";
+ cx.error_spanned_by(enum_token, msg);
+ }
+ syn::Data::Union(syn::DataUnion { union_token, .. }) => {
+ let msg = "#[serde(default)] can only be used on structs with named fields";
+ cx.error_spanned_by(union_token, msg);
+ }
}
}
- }
-
- // Parse `#[serde(bound = "T: SomeBound")]`
- Meta(NameValue(m)) if m.path == BOUND => {
- if let Ok(where_predicates) = parse_lit_into_where(cx, BOUND, BOUND, &m.lit) {
- ser_bound.set(&m.path, where_predicates.clone());
- de_bound.set(&m.path, where_predicates);
- }
- }
-
- // Parse `#[serde(bound(serialize = "...", deserialize = "..."))]`
- Meta(List(m)) if m.path == BOUND => {
- if let Ok((ser, de)) = get_where_predicates(cx, &m.nested) {
- ser_bound.set_opt(&m.path, ser);
- de_bound.set_opt(&m.path, de);
- }
- }
-
- // Parse `#[serde(untagged)]`
- Meta(Path(word)) if word == UNTAGGED => match item.data {
- syn::Data::Enum(_) => {
- untagged.set_true(word);
- }
- syn::Data::Struct(syn::DataStruct { struct_token, .. }) => {
- cx.error_spanned_by(
- struct_token,
- "#[serde(untagged)] can only be used on enums",
- );
- }
- syn::Data::Union(syn::DataUnion { union_token, .. }) => {
- cx.error_spanned_by(
- union_token,
- "#[serde(untagged)] can only be used on enums",
- );
+ } 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(syn::DataStruct { struct_token, .. }) => {
+ let msg = "#[serde(untagged)] can only be used on enums";
+ cx.error_spanned_by(struct_token, msg);
+ }
+ syn::Data::Union(syn::DataUnion { union_token, .. }) => {
+ let msg = "#[serde(untagged)] can only be used on enums";
+ cx.error_spanned_by(union_token, msg);
+ }
}
- },
-
- // Parse `#[serde(tag = "type")]`
- Meta(NameValue(m)) if m.path == TAG => {
- if let Ok(s) = get_lit_str(cx, TAG, &m.lit) {
+ } 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(&m.path, s.value());
+ internal_tag.set(&meta.path, s.value());
}
syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields {
syn::Fields::Named(_) => {
- internal_tag.set(&m.path, s.value());
+ internal_tag.set(&meta.path, s.value());
}
syn::Fields::Unnamed(_) | syn::Fields::Unit => {
- cx.error_spanned_by(
- fields,
- "#[serde(tag = \"...\")] can only be used on enums and structs with named fields",
- );
+ let msg = "#[serde(tag = \"...\")] can only be used on enums and structs with named fields";
+ cx.error_spanned_by(fields, msg);
}
},
syn::Data::Union(syn::DataUnion { union_token, .. }) => {
- cx.error_spanned_by(
- union_token,
- "#[serde(tag = \"...\")] can only be used on enums and structs with named fields",
- );
+ let msg = "#[serde(tag = \"...\")] can only be used on enums and structs with named fields";
+ cx.error_spanned_by(union_token, msg);
}
}
}
- }
-
- // Parse `#[serde(content = "c")]`
- Meta(NameValue(m)) if m.path == CONTENT => {
- if let Ok(s) = get_lit_str(cx, CONTENT, &m.lit) {
+ } 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(&m.path, s.value());
+ content.set(&meta.path, s.value());
}
syn::Data::Struct(syn::DataStruct { struct_token, .. }) => {
- cx.error_spanned_by(
- struct_token,
- "#[serde(content = \"...\")] can only be used on enums",
- );
+ let msg = "#[serde(content = \"...\")] can only be used on enums";
+ cx.error_spanned_by(struct_token, msg);
}
syn::Data::Union(syn::DataUnion { union_token, .. }) => {
- cx.error_spanned_by(
- union_token,
- "#[serde(content = \"...\")] can only be used on enums",
- );
+ let msg = "#[serde(content = \"...\")] can only be used on enums";
+ cx.error_spanned_by(union_token, msg);
}
}
}
- }
-
- // Parse `#[serde(from = "Type")]
- Meta(NameValue(m)) if m.path == FROM => {
- if let Ok(from_ty) = parse_lit_into_ty(cx, FROM, &m.lit) {
- type_from.set_opt(&m.path, Some(from_ty));
+ } 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));
}
- }
-
- // Parse `#[serde(try_from = "Type")]
- Meta(NameValue(m)) if m.path == TRY_FROM => {
- if let Ok(try_from_ty) = parse_lit_into_ty(cx, TRY_FROM, &m.lit) {
- type_try_from.set_opt(&m.path, Some(try_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));
}
- }
-
- // Parse `#[serde(into = "Type")]
- Meta(NameValue(m)) if m.path == INTO => {
- if let Ok(into_ty) = parse_lit_into_ty(cx, INTO, &m.lit) {
- type_into.set_opt(&m.path, Some(into_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));
}
- }
-
- // Parse `#[serde(remote = "...")]`
- Meta(NameValue(m)) if m.path == REMOTE => {
- if let Ok(path) = parse_lit_into_path(cx, REMOTE, &m.lit) {
+ } 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(&m.path, item.ident.clone().into());
+ remote.set(&meta.path, item.ident.clone().into());
} else {
- remote.set(&m.path, path);
+ remote.set(&meta.path, path);
}
}
- }
-
- // Parse `#[serde(field_identifier)]`
- Meta(Path(word)) if word == FIELD_IDENTIFIER => {
- field_identifier.set_true(word);
- }
-
- // Parse `#[serde(variant_identifier)]`
- Meta(Path(word)) if word == VARIANT_IDENTIFIER => {
- variant_identifier.set_true(word);
- }
-
- // Parse `#[serde(crate = "foo")]`
- Meta(NameValue(m)) if m.path == CRATE => {
- if let Ok(path) = parse_lit_into_path(cx, CRATE, &m.lit) {
- serde_path.set(&m.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);
}
- }
-
- // Parse `#[serde(expecting = "a message")]`
- Meta(NameValue(m)) if m.path == EXPECTING => {
- if let Ok(s) = get_lit_str(cx, EXPECTING, &m.lit) {
- expecting.set(&m.path, s.value());
+ } 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());
}
- }
-
- Meta(meta_item) => {
- let path = meta_item
- .path()
- .into_token_stream()
- .to_string()
- .replace(' ', "");
- cx.error_spanned_by(
- meta_item.path(),
- format!("unknown serde container attribute `{}`", path),
+ } else {
+ let path = meta.path.to_token_stream().to_string().replace(' ', "");
+ return Err(
+ meta.error(format_args!("unknown serde container attribute `{}`", path))
);
}
-
- Lit(lit) => {
- cx.error_spanned_by(lit, "unexpected literal in serde container attribute");
- }
+ Ok(())
+ }) {
+ cx.syn_error(err);
}
}
let mut is_packed = false;
for attr in &item.attrs {
- if attr.path.is_ident("repr") {
+ if attr.path() == REPR {
let _ = attr.parse_args_with(|input: ParseStream| {
while let Some(token) = input.parse()? {
if let TokenTree::Ident(ident) = token {
@@ -725,10 +645,9 @@ fn decide_tag(
syn::Fields::Named(_) | syn::Fields::Unit => {}
syn::Fields::Unnamed(fields) => {
if fields.unnamed.len() != 1 {
- cx.error_spanned_by(
- variant,
- "#[serde(tag = \"...\")] cannot be used with tuple variants",
- );
+ let msg =
+ "#[serde(tag = \"...\")] cannot be used with tuple variants";
+ cx.error_spanned_by(variant, msg);
break;
}
}
@@ -738,48 +657,28 @@ fn decide_tag(
TagType::Internal { tag }
}
(Some((untagged_tokens, _)), Some((tag_tokens, _)), None) => {
- cx.error_spanned_by(
- untagged_tokens,
- "enum cannot be both untagged and internally tagged",
- );
- cx.error_spanned_by(
- tag_tokens,
- "enum cannot be both untagged and internally tagged",
- );
+ 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, _))) => {
- cx.error_spanned_by(
- content_tokens,
- "#[serde(tag = \"...\", content = \"...\")] must be used together",
- );
+ 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, _))) => {
- cx.error_spanned_by(
- untagged_tokens,
- "untagged enum cannot have #[serde(content = \"...\")]",
- );
- cx.error_spanned_by(
- content_tokens,
- "untagged enum cannot have #[serde(content = \"...\")]",
- );
+ 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, _))) => {
- cx.error_spanned_by(
- untagged_tokens,
- "untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]",
- );
- cx.error_spanned_by(
- tag_tokens,
- "untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]",
- );
- cx.error_spanned_by(
- content_tokens,
- "untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]",
- );
+ 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
}
}
@@ -798,44 +697,32 @@ fn decide_identifier(
) {
(_, None, None) => Identifier::No,
(_, Some((field_identifier_tokens, _)), Some((variant_identifier_tokens, _))) => {
- cx.error_spanned_by(
- field_identifier_tokens,
- "#[serde(field_identifier)] and #[serde(variant_identifier)] cannot both be set",
- );
- cx.error_spanned_by(
- variant_identifier_tokens,
- "#[serde(field_identifier)] and #[serde(variant_identifier)] cannot both be set",
- );
+ 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) => {
- cx.error_spanned_by(
- struct_token,
- "#[serde(field_identifier)] can only be used on an enum",
- );
+ 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) => {
- cx.error_spanned_by(
- union_token,
- "#[serde(field_identifier)] can only be used on an enum",
- );
+ 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(_)) => {
- cx.error_spanned_by(
- struct_token,
- "#[serde(variant_identifier)] can only be used on an enum",
- );
+ 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(_)) => {
- cx.error_spanned_by(
- union_token,
- "#[serde(variant_identifier)] can only be used on an enum",
- );
+ let msg = "#[serde(variant_identifier)] can only be used on an enum";
+ cx.error_spanned_by(union_token, msg);
Identifier::No
}
}
@@ -852,7 +739,12 @@ pub struct Variant {
other: bool,
serialize_with: Option<syn::ExprPath>,
deserialize_with: Option<syn::ExprPath>,
- borrow: Option<syn::Meta>,
+ borrow: Option<BorrowAttribute>,
+}
+
+struct BorrowAttribute {
+ path: syn::Path,
+ lifetimes: Option<BTreeSet<syn::Lifetime>>,
}
impl Variant {
@@ -871,168 +763,131 @@ impl Variant {
let mut deserialize_with = Attr::none(cx, DESERIALIZE_WITH);
let mut borrow = Attr::none(cx, BORROW);
- for meta_item in variant
- .attrs
- .iter()
- .flat_map(|attr| get_serde_meta_items(cx, attr))
- .flatten()
- {
- match &meta_item {
- // Parse `#[serde(rename = "foo")]`
- Meta(NameValue(m)) if m.path == RENAME => {
- if let Ok(s) = get_lit_str(cx, RENAME, &m.lit) {
- ser_name.set(&m.path, s.value());
- de_name.set_if_none(s.value());
- de_aliases.insert(&m.path, s.value());
- }
- }
+ for attr in &variant.attrs {
+ if attr.path() != SERDE {
+ continue;
+ }
- // Parse `#[serde(rename(serialize = "foo", deserialize = "bar"))]`
- Meta(List(m)) if m.path == RENAME => {
- if let Ok((ser, de)) = get_multiple_renames(cx, &m.nested) {
- ser_name.set_opt(&m.path, ser.map(syn::LitStr::value));
- for de_value in de {
- de_name.set_if_none(de_value.value());
- de_aliases.insert(&m.path, de_value.value());
- }
- }
+ if let syn::Meta::List(meta) = &attr.meta {
+ if meta.tokens.is_empty() {
+ continue;
}
+ }
- // Parse `#[serde(alias = "foo")]`
- Meta(NameValue(m)) if m.path == ALIAS => {
- if let Ok(s) = get_lit_str(cx, ALIAS, &m.lit) {
- de_aliases.insert(&m.path, s.value());
+ 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());
}
- }
-
- // Parse `#[serde(rename_all = "foo")]`
- Meta(NameValue(m)) if m.path == RENAME_ALL => {
- if let Ok(s) = get_lit_str(cx, RENAME_ALL, &m.lit) {
- match RenameRule::from_str(&s.value()) {
- Ok(rename_rule) => {
- rename_all_ser_rule.set(&m.path, rename_rule);
- rename_all_de_rule.set(&m.path, rename_rule);
- }
- Err(err) => cx.error_spanned_by(s, err),
- }
+ } 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());
}
- }
-
- // Parse `#[serde(rename_all(serialize = "foo", deserialize = "bar"))]`
- Meta(List(m)) if m.path == RENAME_ALL => {
- if let Ok((ser, de)) = get_renames(cx, &m.nested) {
- if let Some(ser) = ser {
- match RenameRule::from_str(&ser.value()) {
- Ok(rename_rule) => rename_all_ser_rule.set(&m.path, rename_rule),
- Err(err) => cx.error_spanned_by(ser, err),
- }
+ } 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(&m.path, rename_rule),
- Err(err) => cx.error_spanned_by(de, 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);
+ }
}
}
}
- }
-
- // Parse `#[serde(skip)]`
- Meta(Path(word)) if word == SKIP => {
- skip_serializing.set_true(word);
- skip_deserializing.set_true(word);
- }
-
- // Parse `#[serde(skip_deserializing)]`
- Meta(Path(word)) if word == SKIP_DESERIALIZING => {
- skip_deserializing.set_true(word);
- }
-
- // Parse `#[serde(skip_serializing)]`
- Meta(Path(word)) if word == SKIP_SERIALIZING => {
- skip_serializing.set_true(word);
- }
-
- // Parse `#[serde(other)]`
- Meta(Path(word)) if word == OTHER => {
- other.set_true(word);
- }
-
- // Parse `#[serde(bound = "T: SomeBound")]`
- Meta(NameValue(m)) if m.path == BOUND => {
- if let Ok(where_predicates) = parse_lit_into_where(cx, BOUND, BOUND, &m.lit) {
- ser_bound.set(&m.path, where_predicates.clone());
- de_bound.set(&m.path, where_predicates);
- }
- }
-
- // Parse `#[serde(bound(serialize = "...", deserialize = "..."))]`
- Meta(List(m)) if m.path == BOUND => {
- if let Ok((ser, de)) = get_where_predicates(cx, &m.nested) {
- ser_bound.set_opt(&m.path, ser);
- de_bound.set_opt(&m.path, de);
- }
- }
-
- // Parse `#[serde(with = "...")]`
- Meta(NameValue(m)) if m.path == WITH => {
- if let Ok(path) = parse_lit_into_expr_path(cx, WITH, &m.lit) {
+ } 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(&m.path, ser_path);
+ 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(&m.path, de_path);
- }
- }
-
- // Parse `#[serde(serialize_with = "...")]`
- Meta(NameValue(m)) if m.path == SERIALIZE_WITH => {
- if let Ok(path) = parse_lit_into_expr_path(cx, SERIALIZE_WITH, &m.lit) {
- serialize_with.set(&m.path, path);
+ deserialize_with.set(&meta.path, de_path);
}
- }
-
- // Parse `#[serde(deserialize_with = "...")]`
- Meta(NameValue(m)) if m.path == DESERIALIZE_WITH => {
- if let Ok(path) = parse_lit_into_expr_path(cx, DESERIALIZE_WITH, &m.lit) {
- deserialize_with.set(&m.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);
}
- }
-
- // Defer `#[serde(borrow)]` and `#[serde(borrow = "'a + 'b")]`
- Meta(m) if m.path() == BORROW => match &variant.fields {
- syn::Fields::Unnamed(fields) if fields.unnamed.len() == 1 => {
- borrow.set(m.path(), m.clone());
+ } 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);
}
- _ => {
- cx.error_spanned_by(
- variant,
- "#[serde(borrow)] may only be used on newtype variants",
- );
+ } 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);
+ }
}
- },
-
- Meta(meta_item) => {
- let path = meta_item
- .path()
- .into_token_stream()
- .to_string()
- .replace(' ', "");
- cx.error_spanned_by(
- meta_item.path(),
- format!("unknown serde variant attribute `{}`", path),
+ } else {
+ let path = meta.path.to_token_stream().to_string().replace(' ', "");
+ return Err(
+ meta.error(format_args!("unknown serde variant attribute `{}`", path))
);
}
-
- Lit(lit) => {
- cx.error_spanned_by(lit, "unexpected literal in serde variant attribute");
- }
+ Ok(())
+ }) {
+ cx.syn_error(err);
}
}
@@ -1168,182 +1023,145 @@ impl Field {
None => index.to_string(),
};
- let variant_borrow = attrs
- .and_then(|variant| variant.borrow.as_ref())
- .map(|borrow| Meta(borrow.clone()));
-
- for meta_item in field
- .attrs
- .iter()
- .flat_map(|attr| get_serde_meta_items(cx, attr))
- .flatten()
- .chain(variant_borrow)
- {
- match &meta_item {
- // Parse `#[serde(rename = "foo")]`
- Meta(NameValue(m)) if m.path == RENAME => {
- if let Ok(s) = get_lit_str(cx, RENAME, &m.lit) {
- ser_name.set(&m.path, s.value());
- de_name.set_if_none(s.value());
- de_aliases.insert(&m.path, s.value());
- }
- }
-
- // Parse `#[serde(rename(serialize = "foo", deserialize = "bar"))]`
- Meta(List(m)) if m.path == RENAME => {
- if let Ok((ser, de)) = get_multiple_renames(cx, &m.nested) {
- ser_name.set_opt(&m.path, ser.map(syn::LitStr::value));
- for de_value in de {
- de_name.set_if_none(de_value.value());
- de_aliases.insert(&m.path, de_value.value());
+ 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);
}
+ }
+ }
- // Parse `#[serde(alias = "foo")]`
- Meta(NameValue(m)) if m.path == ALIAS => {
- if let Ok(s) = get_lit_str(cx, ALIAS, &m.lit) {
- de_aliases.insert(&m.path, s.value());
- }
- }
+ for attr in &field.attrs {
+ if attr.path() != SERDE {
+ continue;
+ }
- // Parse `#[serde(default)]`
- Meta(Path(word)) if word == DEFAULT => {
- default.set(word, Default::Default);
+ if let syn::Meta::List(meta) = &attr.meta {
+ if meta.tokens.is_empty() {
+ continue;
}
+ }
- // Parse `#[serde(default = "...")]`
- Meta(NameValue(m)) if m.path == DEFAULT => {
- if let Ok(path) = parse_lit_into_expr_path(cx, DEFAULT, &m.lit) {
- default.set(&m.path, Default::Path(path));
+ 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());
}
- }
-
- // Parse `#[serde(skip_serializing)]`
- Meta(Path(word)) if word == SKIP_SERIALIZING => {
- skip_serializing.set_true(word);
- }
-
- // Parse `#[serde(skip_deserializing)]`
- Meta(Path(word)) if word == SKIP_DESERIALIZING => {
- skip_deserializing.set_true(word);
- }
-
- // Parse `#[serde(skip)]`
- Meta(Path(word)) if word == SKIP => {
- skip_serializing.set_true(word);
- skip_deserializing.set_true(word);
- }
-
- // Parse `#[serde(skip_serializing_if = "...")]`
- Meta(NameValue(m)) if m.path == SKIP_SERIALIZING_IF => {
- if let Ok(path) = parse_lit_into_expr_path(cx, SKIP_SERIALIZING_IF, &m.lit) {
- skip_serializing_if.set(&m.path, path);
+ } 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());
}
- }
-
- // Parse `#[serde(serialize_with = "...")]`
- Meta(NameValue(m)) if m.path == SERIALIZE_WITH => {
- if let Ok(path) = parse_lit_into_expr_path(cx, SERIALIZE_WITH, &m.lit) {
- serialize_with.set(&m.path, 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)? {
+ default.set(&meta.path, Default::Path(path));
+ }
+ } else {
+ // #[serde(default)]
+ default.set(&meta.path, Default::Default);
}
- }
-
- // Parse `#[serde(deserialize_with = "...")]`
- Meta(NameValue(m)) if m.path == DESERIALIZE_WITH => {
- if let Ok(path) = parse_lit_into_expr_path(cx, DESERIALIZE_WITH, &m.lit) {
- deserialize_with.set(&m.path, path);
+ } 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);
}
- }
-
- // Parse `#[serde(with = "...")]`
- Meta(NameValue(m)) if m.path == WITH => {
- if let Ok(path) = parse_lit_into_expr_path(cx, WITH, &m.lit) {
+ } 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(&m.path, ser_path);
+ 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(&m.path, de_path);
- }
- }
-
- // Parse `#[serde(bound = "T: SomeBound")]`
- Meta(NameValue(m)) if m.path == BOUND => {
- if let Ok(where_predicates) = parse_lit_into_where(cx, BOUND, BOUND, &m.lit) {
- ser_bound.set(&m.path, where_predicates.clone());
- de_bound.set(&m.path, where_predicates);
- }
- }
-
- // Parse `#[serde(bound(serialize = "...", deserialize = "..."))]`
- Meta(List(m)) if m.path == BOUND => {
- if let Ok((ser, de)) = get_where_predicates(cx, &m.nested) {
- ser_bound.set_opt(&m.path, ser);
- de_bound.set_opt(&m.path, de);
+ deserialize_with.set(&meta.path, de_path);
}
- }
-
- // Parse `#[serde(borrow)]`
- Meta(Path(word)) if word == BORROW => {
- if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, field) {
- borrowed_lifetimes.set(word, borrowable);
- }
- }
-
- // Parse `#[serde(borrow = "'a + 'b")]`
- Meta(NameValue(m)) if m.path == BORROW => {
- if let Ok(lifetimes) = parse_lit_into_lifetimes(cx, BORROW, &m.lit) {
+ } 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) {
- cx.error_spanned_by(
- field,
- format!(
- "field `{}` does not have lifetime {}",
- ident, lifetime
- ),
+ let msg = format!(
+ "field `{}` does not have lifetime {}",
+ ident, lifetime,
);
+ cx.error_spanned_by(field, msg);
}
}
- borrowed_lifetimes.set(&m.path, lifetimes);
+ borrowed_lifetimes.set(&meta.path, lifetimes);
+ }
+ } else {
+ // #[serde(borrow)]
+ if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, field) {
+ borrowed_lifetimes.set(&meta.path, borrowable);
}
}
- }
-
- // Parse `#[serde(getter = "...")]`
- Meta(NameValue(m)) if m.path == GETTER => {
- if let Ok(path) = parse_lit_into_expr_path(cx, GETTER, &m.lit) {
- getter.set(&m.path, path);
+ } else if meta.path == GETTER {
+ // #[serde(getter = "...")]
+ if let Some(path) = parse_lit_into_expr_path(cx, GETTER, &meta)? {
+ getter.set(&meta.path, path);
}
- }
-
- // Parse `#[serde(flatten)]`
- Meta(Path(word)) if word == FLATTEN => {
- flatten.set_true(word);
- }
-
- Meta(meta_item) => {
- let path = meta_item
- .path()
- .into_token_stream()
- .to_string()
- .replace(' ', "");
- cx.error_spanned_by(
- meta_item.path(),
- format!("unknown serde field attribute `{}`", 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))
);
}
-
- Lit(lit) => {
- cx.error_spanned_by(lit, "unexpected literal in serde field attribute");
- }
+ Ok(())
+ }) {
+ cx.syn_error(err);
}
}
@@ -1497,130 +1315,154 @@ impl Field {
type SerAndDe<T> = (Option<T>, Option<T>);
-fn get_ser_and_de<'a, 'b, T, F>(
- cx: &'b Ctxt,
+fn get_ser_and_de<'c, T, F, R>(
+ cx: &'c Ctxt,
attr_name: Symbol,
- metas: &'a Punctuated<syn::NestedMeta, Token![,]>,
+ meta: &ParseNestedMeta,
f: F,
-) -> Result<(VecAttr<'b, T>, VecAttr<'b, T>), ()>
+) -> syn::Result<(VecAttr<'c, T>, VecAttr<'c, T>)>
where
- T: 'a,
- F: Fn(&Ctxt, Symbol, Symbol, &'a syn::Lit) -> Result<T, ()>,
+ 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);
- for meta in metas {
- match meta {
- Meta(NameValue(meta)) if meta.path == SERIALIZE => {
- if let Ok(v) = f(cx, attr_name, SERIALIZE, &meta.lit) {
+ 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);
}
- }
-
- Meta(NameValue(meta)) if meta.path == DESERIALIZE => {
- if let Ok(v) = f(cx, attr_name, DESERIALIZE, &meta.lit) {
+ } 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,
+ )));
}
-
- _ => {
- cx.error_spanned_by(
- meta,
- format!(
- "malformed {0} attribute, expected `{0}(serialize = ..., deserialize = ...)`",
- attr_name
- ),
- );
- return Err(());
- }
- }
+ Ok(())
+ })?;
+ } else {
+ return Err(lookahead.error());
}
Ok((ser_meta, de_meta))
}
-fn get_renames<'a>(
+fn get_renames(
cx: &Ctxt,
- items: &'a Punctuated<syn::NestedMeta, Token![,]>,
-) -> Result<SerAndDe<&'a syn::LitStr>, ()> {
- let (ser, de) = get_ser_and_de(cx, RENAME, items, get_lit_str2)?;
- Ok((ser.at_most_one()?, de.at_most_one()?))
+ 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<'a>(
+fn get_multiple_renames(
cx: &Ctxt,
- items: &'a Punctuated<syn::NestedMeta, Token![,]>,
-) -> Result<(Option<&'a syn::LitStr>, Vec<&'a syn::LitStr>), ()> {
- let (ser, de) = get_ser_and_de(cx, RENAME, items, get_lit_str2)?;
- Ok((ser.at_most_one()?, de.get()))
+ 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,
- items: &Punctuated<syn::NestedMeta, Token![,]>,
-) -> Result<SerAndDe<Vec<syn::WherePredicate>>, ()> {
- let (ser, de) = get_ser_and_de(cx, BOUND, items, parse_lit_into_where)?;
- Ok((ser.at_most_one()?, de.at_most_one()?))
-}
-
-pub fn get_serde_meta_items(cx: &Ctxt, attr: &syn::Attribute) -> Result<Vec<syn::NestedMeta>, ()> {
- if attr.path != SERDE {
- return Ok(Vec::new());
- }
-
- match attr.parse_meta() {
- Ok(List(meta)) => Ok(meta.nested.into_iter().collect()),
- Ok(other) => {
- cx.error_spanned_by(other, "expected #[serde(...)]");
- Err(())
- }
- Err(err) => {
- cx.syn_error(err);
- Err(())
- }
- }
+ 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<'a>(cx: &Ctxt, attr_name: Symbol, lit: &'a syn::Lit) -> Result<&'a syn::LitStr, ()> {
- get_lit_str2(cx, attr_name, attr_name, lit)
+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<'a>(
+fn get_lit_str2(
cx: &Ctxt,
attr_name: Symbol,
meta_item_name: Symbol,
- lit: &'a syn::Lit,
-) -> Result<&'a syn::LitStr, ()> {
- if let syn::Lit::Str(lit) = lit {
- Ok(lit)
+ 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
+ {
+ Ok(Some(lit.clone()))
} else {
cx.error_spanned_by(
- lit,
+ expr,
format!(
"expected serde {} attribute to be a string: `{} = \"...\"`",
attr_name, meta_item_name
),
);
- Err(())
+ Ok(None)
}
}
-fn parse_lit_into_path(cx: &Ctxt, attr_name: Symbol, lit: &syn::Lit) -> Result<syn::Path, ()> {
- let string = get_lit_str(cx, attr_name, lit)?;
- parse_lit_str(string).map_err(|_| {
- cx.error_spanned_by(lit, format!("failed to parse path: {:?}", string.value()));
+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,
- lit: &syn::Lit,
-) -> Result<syn::ExprPath, ()> {
- let string = get_lit_str(cx, attr_name, lit)?;
- parse_lit_str(string).map_err(|_| {
- cx.error_spanned_by(lit, format!("failed to parse path: {:?}", string.value()));
+ 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
+ }
})
}
@@ -1628,28 +1470,43 @@ fn parse_lit_into_where(
cx: &Ctxt,
attr_name: Symbol,
meta_item_name: Symbol,
- lit: &syn::Lit,
-) -> Result<Vec<syn::WherePredicate>, ()> {
- let string = get_lit_str2(cx, attr_name, meta_item_name, lit)?;
- if string.value().is_empty() {
- return Ok(Vec::new());
- }
-
- let where_string = syn::LitStr::new(&format!("where {}", string.value()), string.span());
+ 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()),
+ };
- parse_lit_str::<syn::WhereClause>(&where_string)
- .map(|wh| wh.predicates.into_iter().collect())
- .map_err(|err| cx.error_spanned_by(lit, err))
+ 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, lit: &syn::Lit) -> Result<syn::Type, ()> {
- let string = get_lit_str(cx, attr_name, lit)?;
+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),
+ };
- parse_lit_str(string).map_err(|_| {
- cx.error_spanned_by(
- lit,
- format!("failed to parse type: {} = {:?}", attr_name, string.value()),
- );
+ Ok(match string.parse() {
+ Ok(ty) => Some(ty),
+ Err(_) => {
+ cx.error_spanned_by(
+ &string,
+ format!("failed to parse type: {} = {:?}", attr_name, string.value()),
+ );
+ None
+ }
})
}
@@ -1657,38 +1514,41 @@ fn parse_lit_into_ty(cx: &Ctxt, attr_name: Symbol, lit: &syn::Lit) -> Result<syn
// lifetimes separated by `+`.
fn parse_lit_into_lifetimes(
cx: &Ctxt,
- attr_name: Symbol,
- lit: &syn::Lit,
-) -> Result<BTreeSet<syn::Lifetime>, ()> {
- let string = get_lit_str(cx, attr_name, lit)?;
- if string.value().is_empty() {
- cx.error_spanned_by(lit, "at least one lifetime must be borrowed");
- return Err(());
- }
-
- struct BorrowedLifetimes(Punctuated<syn::Lifetime, Token![+]>);
-
- impl Parse for BorrowedLifetimes {
- fn parse(input: ParseStream) -> parse::Result<Self> {
- Punctuated::parse_separated_nonempty(input).map(BorrowedLifetimes)
- }
- }
+ 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(BorrowedLifetimes(lifetimes)) = parse_lit_str(string) {
+ if let Ok(lifetimes) = string.parse_with(|input: ParseStream| {
let mut set = BTreeSet::new();
- for lifetime in lifetimes {
+ while !input.is_empty() {
+ let lifetime: Lifetime = input.parse()?;
if !set.insert(lifetime.clone()) {
- cx.error_spanned_by(lit, format!("duplicate borrowed lifetime `{}`", lifetime));
+ 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(set);
+ return Ok(lifetimes);
}
cx.error_spanned_by(
- lit,
+ &string,
format!("failed to parse borrowed lifetimes: {:?}", string.value()),
);
- Err(())
+ Ok(BTreeSet::new())
}
fn is_implicitly_borrowed(ty: &syn::Type) -> bool {
@@ -1842,10 +1702,8 @@ fn borrowable_lifetimes(
let mut lifetimes = BTreeSet::new();
collect_lifetimes(&field.ty, &mut lifetimes);
if lifetimes.is_empty() {
- cx.error_spanned_by(
- field,
- format!("field `{}` has no lifetimes to borrow", name),
- );
+ let msg = format!("field `{}` has no lifetimes to borrow", name);
+ cx.error_spanned_by(field, msg);
Err(())
} else {
Ok(lifetimes)
@@ -1886,11 +1744,10 @@ fn collect_lifetimes(ty: &syn::Type, out: &mut BTreeSet<syn::Lifetime>) {
syn::GenericArgument::Type(ty) => {
collect_lifetimes(ty, out);
}
- syn::GenericArgument::Binding(binding) => {
+ syn::GenericArgument::AssocType(binding) => {
collect_lifetimes(&binding.ty, out);
}
- syn::GenericArgument::Constraint(_)
- | syn::GenericArgument::Const(_) => {}
+ _ => {}
}
}
}
@@ -1937,16 +1794,3 @@ fn collect_lifetimes_from_tokens(tokens: TokenStream, out: &mut BTreeSet<syn::Li
}
}
}
-
-fn parse_lit_str<T>(s: &syn::LitStr) -> parse::Result<T>
-where
- T: Parse,
-{
- let tokens = spanned_tokens(s)?;
- syn::parse2(tokens)
-}
-
-fn spanned_tokens(s: &syn::LitStr) -> parse::Result<TokenStream> {
- let stream = syn::parse_str(&s.value())?;
- Ok(respan(stream, s.span()))
-}
diff --git a/vendor/serde_derive/src/internals/check.rs b/vendor/serde_derive/src/internals/check.rs
index eb1297aa7..05b4b8ff8 100644
--- a/vendor/serde_derive/src/internals/check.rs
+++ b/vendor/serde_derive/src/internals/check.rs
@@ -3,8 +3,8 @@ use internals::attr::{Identifier, TagType};
use 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.
+// 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_remote_generic(cx, cont);
check_getter(cx, cont);
@@ -17,18 +17,18 @@ pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) {
check_from_and_try_from(cx, cont);
}
-/// 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 {…}
-///
+// 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();
@@ -39,8 +39,8 @@ fn check_remote_generic(cx: &Ctxt, cont: &Container) {
}
}
-/// Getters are only allowed inside structs (not enums) with the `remote`
-/// attribute.
+// Getters are only allowed inside structs (not enums) with the `remote`
+// attribute.
fn check_getter(cx: &Ctxt, cont: &Container) {
match cont.data {
Data::Enum(_) => {
@@ -62,7 +62,7 @@ fn check_getter(cx: &Ctxt, cont: &Container) {
}
}
-/// Flattening has some restrictions we can test.
+// Flattening has some restrictions we can test.
fn check_flatten(cx: &Ctxt, cont: &Container) {
match &cont.data {
Data::Enum(variants) => {
@@ -101,12 +101,12 @@ fn check_flatten_field(cx: &Ctxt, style: Style, field: &Field) {
}
}
-/// 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.
+// 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,
@@ -189,8 +189,8 @@ fn check_identifier(cx: &Ctxt, cont: &Container) {
}
}
-/// Skip-(de)serializing attributes are not allowed on variants marked
-/// (de)serialize_with.
+// 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,
@@ -264,10 +264,9 @@ fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
}
}
-/// 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.
+// 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,
@@ -313,8 +312,8 @@ fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) {
}
}
-/// In the case of adjacently-tagged enums, the type and the
-/// contents tag must differ, for the same reason.
+// 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),
@@ -332,7 +331,7 @@ fn check_adjacent_tag_conflict(cx: &Ctxt, cont: &Container) {
}
}
-/// Enums and unit structs cannot be transparent.
+// Enums and unit structs cannot be transparent.
fn check_transparent(cx: &Ctxt, cont: &mut Container, derive: Derive) {
if !cont.attrs.transparent() {
return;
diff --git a/vendor/serde_derive/src/internals/receiver.rs b/vendor/serde_derive/src/internals/receiver.rs
index b08c67096..5dc01db26 100644
--- a/vendor/serde_derive/src/internals/receiver.rs
+++ b/vendor/serde_derive/src/internals/receiver.rs
@@ -179,10 +179,13 @@ impl ReplaceReceiver<'_> {
for arg in &mut arguments.args {
match arg {
GenericArgument::Type(arg) => self.visit_type_mut(arg),
- GenericArgument::Binding(arg) => self.visit_type_mut(&mut arg.ty),
+ GenericArgument::AssocType(arg) => self.visit_type_mut(&mut arg.ty),
GenericArgument::Lifetime(_)
- | GenericArgument::Constraint(_)
- | GenericArgument::Const(_) => {}
+ | GenericArgument::Const(_)
+ | GenericArgument::AssocConst(_)
+ | GenericArgument::Constraint(_) => {}
+ #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ _ => {}
}
}
}
@@ -205,7 +208,9 @@ impl ReplaceReceiver<'_> {
fn visit_type_param_bound_mut(&mut self, bound: &mut TypeParamBound) {
match bound {
TypeParamBound::Trait(bound) => self.visit_path_mut(&mut bound.path),
- TypeParamBound::Lifetime(_) => {}
+ TypeParamBound::Lifetime(_) | TypeParamBound::Verbatim(_) => {}
+ #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ _ => {}
}
}
@@ -229,7 +234,9 @@ impl ReplaceReceiver<'_> {
self.visit_type_param_bound_mut(bound);
}
}
- WherePredicate::Lifetime(_) | WherePredicate::Eq(_) => {}
+ WherePredicate::Lifetime(_) => {}
+ #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
+ _ => {}
}
}
}
diff --git a/vendor/serde_derive/src/internals/symbol.rs b/vendor/serde_derive/src/internals/symbol.rs
index 1fedd2754..9606edb5f 100644
--- a/vendor/serde_derive/src/internals/symbol.rs
+++ b/vendor/serde_derive/src/internals/symbol.rs
@@ -13,6 +13,7 @@ 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");
@@ -22,6 +23,7 @@ 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 REPR: Symbol = Symbol("repr");
pub const SERDE: Symbol = Symbol("serde");
pub const SERIALIZE: Symbol = Symbol("serialize");
pub const SERIALIZE_WITH: Symbol = Symbol("serialize_with");
@@ -35,7 +37,6 @@ 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");
-pub const EXPECTING: Symbol = Symbol("expecting");
impl PartialEq<Symbol> for Ident {
fn eq(&self, word: &Symbol) -> bool {
diff --git a/vendor/serde_derive/src/lib.rs b/vendor/serde_derive/src/lib.rs
index 410078911..b2be16547 100644
--- a/vendor/serde_derive/src/lib.rs
+++ b/vendor/serde_derive/src/lib.rs
@@ -13,7 +13,7 @@
//!
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
-#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.152")]
+#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.159")]
#![allow(unknown_lints, bare_trait_objects)]
// Ignored clippy lints
#![allow(
@@ -43,6 +43,7 @@
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,