--- a/Cargo.lock
+++ b/Cargo.lock
@@ -17,17 +17,17 @@ version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "app_units"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "arrayvec"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -57,18 +57,18 @@ dependencies = [
"cubeb 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
"iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"memmap 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.27 (git+https://github.com/gankro/serde?branch=deserialize_from_enums4)",
+ "serde 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.35 (git+https://github.com/servo/serde?branch=deserialize_from_enums5)",
"tokio-core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "audioipc-client"
version = "0.4.0"
@@ -116,17 +116,17 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bincode"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bindgen"
version = "0.33.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -503,18 +503,18 @@ dependencies = [
name = "dwrote"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.27 (git+https://github.com/gankro/serde?branch=deserialize_from_enums4)",
+ "serde 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.35 (git+https://github.com/servo/serde?branch=deserialize_from_enums5)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "either"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -558,17 +558,17 @@ version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "euclid"
version = "0.17.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fallible"
version = "0.0.1"
dependencies = [
"hashglobe 0.1.0",
"smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1439,17 +1439,17 @@ name = "regex-syntax"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ron"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rsdparsa"
version = "0.1.0"
[[package]]
name = "rsdparsa_capi"
@@ -1539,39 +1539,40 @@ dependencies = [
[[package]]
name = "semver-parser"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde"
-version = "1.0.27"
+version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "serde_derive 1.0.27 (git+https://github.com/gankro/serde?branch=deserialize_from_enums4)",
+ "serde_derive 1.0.35 (git+https://github.com/servo/serde?branch=deserialize_from_enums5)",
]
[[package]]
name = "serde_derive"
-version = "1.0.27"
-source = "git+https://github.com/gankro/serde?branch=deserialize_from_enums4#93e24f268ab99c0df10e2183587284e02ca30e9e"
+version = "1.0.35"
+source = "git+https://github.com/servo/serde?branch=deserialize_from_enums5#de4534b21f263752ed3b641c3c07e012574985bf"
dependencies = [
- "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive_internals 0.19.0 (git+https://github.com/gankro/serde?branch=deserialize_from_enums4)",
- "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive_internals 0.22.1 (git+https://github.com/servo/serde?branch=deserialize_from_enums5)",
+ "syn 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_derive_internals"
-version = "0.19.0"
-source = "git+https://github.com/gankro/serde?branch=deserialize_from_enums4#93e24f268ab99c0df10e2183587284e02ca30e9e"
+version = "0.22.1"
+source = "git+https://github.com/servo/serde?branch=deserialize_from_enums5#de4534b21f263752ed3b641c3c07e012574985bf"
dependencies = [
- "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "synom 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "servo_arc"
version = "0.1.1"
dependencies = [
"nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
"stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1843,17 +1844,17 @@ dependencies = [
"tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "toml"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "traitobject"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -2026,17 +2027,17 @@ dependencies = [
"fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"gleam 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
"plane-split 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_api 0.57.0",
]
[[package]]
name = "webrender_api"
@@ -2045,18 +2046,18 @@ dependencies = [
"app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"core-graphics 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"dwrote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.27 (git+https://github.com/gankro/serde?branch=deserialize_from_enums4)",
+ "serde 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.35 (git+https://github.com/servo/serde?branch=deserialize_from_enums5)",
"time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "webrender_bindings"
version = "0.1.0"
dependencies = [
"app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2318,19 +2319,19 @@ dependencies = [
"checksum rust-ini 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "22dab655e8122ccb15db25a56852ce62506f1486cdefd37e86371bf34ea8f601"
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
"checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f"
"checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
"checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d"
"checksum scopeguard 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c79eb2c3ac4bc2507cda80e7f3ac5b88bd8eae4c0914d5663e6a8933994be918"
"checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537"
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
-"checksum serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "db99f3919e20faa51bb2996057f5031d8685019b5a06139b1ce761da671b8526"
-"checksum serde_derive 1.0.27 (git+https://github.com/gankro/serde?branch=deserialize_from_enums4)" = "<none>"
-"checksum serde_derive_internals 0.19.0 (git+https://github.com/gankro/serde?branch=deserialize_from_enums4)" = "<none>"
+"checksum serde 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)" = "800fdb0a894572994f3970035a8a5f65d8ec2cd40e6cdf7d8cd9001d7b30648e"
+"checksum serde_derive 1.0.35 (git+https://github.com/servo/serde?branch=deserialize_from_enums5)" = "<none>"
+"checksum serde_derive_internals 0.22.1 (git+https://github.com/servo/serde?branch=deserialize_from_enums5)" = "<none>"
"checksum simd 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3dd0805c7363ab51a829a1511ad24b6ed0349feaa756c4bc2f977f9f496e6673"
"checksum siphasher 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2ffc669b726f2bc9a3bcff66e5e23b56ba6bf70e22a34c3d7b6d0b3450b65b84"
"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23"
"checksum smallbitvec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "79b776f00dfe01df905fa3b2eaa1659522e99e3fc4a7b1334171622205c4bdcf"
"checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9"
"checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
--- a/third_party/rust/serde/.cargo-checksum.json
+++ b/third_party/rust/serde/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"b5e865ec105f4f546fecdf164172e670b2b82a2533700f556cc1c1c246a4ce14","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"7dc6376a88195594cd6b43cb891aad10f57144ff737178b55d046aa04739b43a","src/de/from_primitive.rs":"28ec3ab1c430cf27d632b642ccfccb6d055eeb9fb576e7e446ba24c66f507fb4","src/de/ignored_any.rs":"864eaefef0aaae36daf0c2bdee08165dabbf60710f3217142d5e280c0a35c1fe","src/de/impls.rs":"e0d8b5255afb175daf720dd5b1072d2d1888fce6790de57fe51d8d2b51fc1603","src/de/mod.rs":"2984925d7844816cacc290067db049766912d1393732d9df280e6ba020582afc","src/de/utf8.rs":"956b124b7ce98353cb781b56e43a6fed2e67f1389d35b7a468d5be75b1485853","src/de/value.rs":"463e107e9ce9a56cc22901aeb60edbf0d10b144ca03dcdb78988d68f6c96022b","src/export.rs":"dd08253f225862aa5009b27900e04187480c96562c35205b71b36b2ac64c4cce","src/lib.rs":"d8411e8311ec29d8d7184556e014a11f03fe84af26f64daeaf34ad449310084d","src/macros.rs":"e1d542b1dac2c1d1f9d5ada7cc5b6639767fc67851421cc3adfb942a7cf750b6","src/private/de.rs":"55403af32b5b4112ab2203c1598bb033308f8c59ed5c4b5f4730dc2f26d3808d","src/private/macros.rs":"6861a4f332ea24d0ed5db1c28fe3105d2716523902f045c0bbbd439ebf9e44de","src/private/mod.rs":"bcd7c54838e139475c23a323678e20eccbe88c0be93f7977f7675cead4d3b6ed","src/private/ser.rs":"fed0c80a55a214c9bf411fe591f8f99562b01fcd27dfe968f6cc9d694a9c60b2","src/ser/impls.rs":"7eb99e5a74a3fcbb611a6ad762d1915a0ae1f5bb7a95f54115936db3bdde32ca","src/ser/impossible.rs":"009dce92e20bd25335db7d747c595111f5eb8d21dda0f6c75bccf0d0608c5751","src/ser/mod.rs":"b0b970c9e4987db7fbd7bc3bb9f32448e2de864c6596829922cf8fe131dae23d"},"package":"db99f3919e20faa51bb2996057f5031d8685019b5a06139b1ce761da671b8526"}
\ No newline at end of file
+{"files":{"Cargo.toml":"921c55ce109f76220ebcd8f8ba6d7e97816e804818ba33772266eb98413fd024","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"7dc6376a88195594cd6b43cb891aad10f57144ff737178b55d046aa04739b43a","src/de/from_primitive.rs":"2ddd1b60696f125652ea69da94575d9a3b76ba667924860df112abc35f56b90b","src/de/ignored_any.rs":"864eaefef0aaae36daf0c2bdee08165dabbf60710f3217142d5e280c0a35c1fe","src/de/impls.rs":"6ea6a19598bb5393de2063deed32c82ebe904b56328ec033f57b55c0e6eea4d7","src/de/mod.rs":"e020b1f027d9e552ff024b44379e87969decf96e4c6cef0e2e7827e2dc4f56c3","src/de/utf8.rs":"956b124b7ce98353cb781b56e43a6fed2e67f1389d35b7a468d5be75b1485853","src/de/value.rs":"463e107e9ce9a56cc22901aeb60edbf0d10b144ca03dcdb78988d68f6c96022b","src/export.rs":"dd08253f225862aa5009b27900e04187480c96562c35205b71b36b2ac64c4cce","src/lib.rs":"22746e82049e9b3f9c60399f552e10fddb4c33a037d00b097f3fc8083d193138","src/macros.rs":"e1d542b1dac2c1d1f9d5ada7cc5b6639767fc67851421cc3adfb942a7cf750b6","src/private/de.rs":"8f2461ead2df284d7b1b84a293b921f0138c368f88af9efd5b82ae345fbcfd59","src/private/macros.rs":"6861a4f332ea24d0ed5db1c28fe3105d2716523902f045c0bbbd439ebf9e44de","src/private/mod.rs":"bcd7c54838e139475c23a323678e20eccbe88c0be93f7977f7675cead4d3b6ed","src/private/ser.rs":"e27af87342c199a494d0001c1684ee6573a3eb330723a86fca3c3b6add38df7a","src/ser/impls.rs":"aaeeb2dd86a86808a292db73764617cce81382a346d117c725f5b48dd7e69212","src/ser/impossible.rs":"009dce92e20bd25335db7d747c595111f5eb8d21dda0f6c75bccf0d0608c5751","src/ser/mod.rs":"97c36fa5b8da27f1f95be9af54c441c8e59437e9533cdd90e376691737fc3d0f"},"package":"800fdb0a894572994f3970035a8a5f65d8ec2cd40e6cdf7d8cd9001d7b30648e"}
\ No newline at end of file
--- a/third_party/rust/serde/Cargo.toml
+++ b/third_party/rust/serde/Cargo.toml
@@ -7,17 +7,17 @@
#
# If you believe there's an error in this file please file an
# issue against the rust-lang/cargo repository. If you're
# editing this file be aware that the upstream Cargo.toml
# will likely look very different (and much more reasonable)
[package]
name = "serde"
-version = "1.0.27"
+version = "1.0.35"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
description = "A generic serialization/deserialization framework"
homepage = "https://serde.rs"
documentation = "https://docs.serde.rs/serde/"
readme = "README.md"
keywords = ["serde", "serialization", "no_std"]
categories = ["encoding"]
--- a/third_party/rust/serde/src/de/from_primitive.rs
+++ b/third_party/rust/serde/src/de/from_primitive.rs
@@ -5,37 +5,37 @@
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use lib::*;
macro_rules! int_to_int {
($dst:ident, $n:ident) => (
- if $dst::MIN as i64 <= $n as i64 && $n as i64 <= $dst::MAX as i64 {
+ if $dst::min_value() as i64 <= $n as i64 && $n as i64 <= $dst::max_value() as i64 {
Some($n as $dst)
} else {
None
}
)
}
macro_rules! int_to_uint {
($dst:ident, $n:ident) => (
- if 0 <= $n && $n as u64 <= $dst::MAX as u64 {
+ if 0 <= $n && $n as u64 <= $dst::max_value() as u64 {
Some($n as $dst)
} else {
None
}
)
}
macro_rules! uint_to {
($dst:ident, $n:ident) => (
- if $n as u64 <= $dst::MAX as u64 {
+ if $n as u64 <= $dst::max_value() as u64 {
Some($n as $dst)
} else {
None
}
)
}
pub trait FromPrimitive: Sized {
--- a/third_party/rust/serde/src/de/impls.rs
+++ b/third_party/rust/serde/src/de/impls.rs
@@ -1913,32 +1913,63 @@ where
},
)
}
}
////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "unstable")]
+#[allow(deprecated)]
impl<'de, T> Deserialize<'de> for NonZero<T>
where
T: Deserialize<'de> + Zeroable,
{
fn deserialize<D>(deserializer: D) -> Result<NonZero<T>, D::Error>
where
D: Deserializer<'de>,
{
let value = try!(Deserialize::deserialize(deserializer));
match NonZero::new(value) {
Some(nonzero) => Ok(nonzero),
None => Err(Error::custom("expected a non-zero value")),
}
}
}
+macro_rules! nonzero_integers {
+ ( $( $T: ty, )+ ) => {
+ $(
+ #[cfg(feature = "unstable")]
+ impl<'de> Deserialize<'de> for $T {
+ fn deserialize<D>(deserializer: D) -> Result<$T, D::Error>
+ where
+ D: Deserializer<'de>,
+ {
+ let value = try!(Deserialize::deserialize(deserializer));
+ match <$T>::new(value) {
+ Some(nonzero) => Ok(nonzero),
+ None => Err(Error::custom("expected a non-zero value")),
+ }
+ }
+ }
+ )+
+ };
+}
+
+nonzero_integers! {
+ // Not including signed NonZeroI* since they might be removed
+ NonZeroU8,
+ NonZeroU16,
+ NonZeroU32,
+ NonZeroU64,
+ // FIXME: https://github.com/serde-rs/serde/issues/1136 NonZeroU128,
+ NonZeroUsize,
+}
+
////////////////////////////////////////////////////////////////////////////////
impl<'de, T, E> Deserialize<'de> for Result<T, E>
where
T: Deserialize<'de>,
E: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Result<T, E>, D::Error>
--- a/third_party/rust/serde/src/de/mod.rs
+++ b/third_party/rust/serde/src/de/mod.rs
@@ -93,17 +93,18 @@
//! - Box\<CStr\>
//! - OsString
//! - **Miscellaneous standard library types**:
//! - Duration
//! - SystemTime
//! - Path
//! - PathBuf
//! - Range\<T\>
-//! - NonZero\<T\> (unstable)
+//! - NonZero\<T\> (unstable, deprecated)
+//! - num::NonZero* (unstable)
//! - **Net types**:
//! - IpAddr
//! - Ipv4Addr
//! - Ipv6Addr
//! - SocketAddr
//! - SocketAddrV4
//! - SocketAddrV6
//!
@@ -508,17 +509,17 @@ pub trait Deserialize<'de>: Sized {
/// Deserializes a value into `self` from the given Deserializer.
///
/// The purpose of this method is to allow the deserializer to reuse
/// resources and avoid copies. As such, if this method returns an error,
/// `self` will be in an indeterminate state where some parts of the struct
/// have been overwritten. Although whatever state that is will be
/// memory-safe.
///
- /// This is generally useful when repeateadly deserializing values that
+ /// This is generally useful when repeatedly deserializing values that
/// are processed one at a time, where the value of `self` doesn't matter
/// when the next deserialization occurs.
///
/// If you manually implement this, your recursive deserializations should
/// use `deserialize_in_place`.
///
/// This method is stable and an official public API, but hidden from the
/// documentation because it is almost never what newbies are looking for.
--- a/third_party/rust/serde/src/lib.rs
+++ b/third_party/rust/serde/src/lib.rs
@@ -74,49 +74,52 @@
//! [Envy]: https://github.com/softprops/envy
//! [Redis]: https://github.com/OneSignal/serde-redis
//! [Cargo]: http://doc.crates.io/manifest.html
//! [redis-rs]: https://crates.io/crates/redis
////////////////////////////////////////////////////////////////////////////////
// Serde types in rustdoc of other crates get linked to here.
-#![doc(html_root_url = "https://docs.rs/serde/1.0.27")]
+#![doc(html_root_url = "https://docs.rs/serde/1.0.35")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and
// discussion of these features please refer to this issue:
//
// https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(nonzero, specialization))]
#![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints
#![cfg_attr(feature = "cargo-clippy",
allow(cast_lossless, const_static_lifetime, doc_markdown, linkedlist,
- needless_pass_by_value, type_complexity, unreadable_literal,
- zero_prefixed_literal))]
+ needless_pass_by_value, redundant_field_names, type_complexity,
+ unreadable_literal, zero_prefixed_literal))]
// Whitelisted clippy_pedantic lints
#![cfg_attr(feature = "cargo-clippy", allow(
// integer and float ser/de requires these sorts of casts
cast_possible_truncation,
cast_possible_wrap,
cast_precision_loss,
cast_sign_loss,
// simplifies some macros
invalid_upcast_comparisons,
// things are often more readable this way
+ decimal_literal_representation,
option_unwrap_used,
result_unwrap_used,
shadow_reuse,
single_match_else,
stutter,
use_self,
// not practical
+ many_single_char_names,
missing_docs_in_private_items,
+ similar_names,
// alternative is not stable
empty_enum,
use_debug,
))]
// Blacklisted Rust lints.
#![deny(missing_docs, unused_imports)]
////////////////////////////////////////////////////////////////////////////////
@@ -203,17 +206,21 @@ mod lib {
#[cfg(feature = "std")]
pub use std::path::{Path, PathBuf};
#[cfg(feature = "std")]
pub use std::time::{Duration, SystemTime, UNIX_EPOCH};
#[cfg(feature = "std")]
pub use std::sync::{Mutex, RwLock};
#[cfg(feature = "unstable")]
+ #[allow(deprecated)]
pub use core::nonzero::{NonZero, Zeroable};
+
+ #[cfg(feature = "unstable")]
+ pub use core::num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroUsize};
}
////////////////////////////////////////////////////////////////////////////////
#[macro_use]
mod macros;
pub mod ser;
--- a/third_party/rust/serde/src/private/de.rs
+++ b/third_party/rust/serde/src/private/de.rs
@@ -6,23 +6,23 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use lib::*;
use de::{Deserialize, DeserializeSeed, Deserializer, Error, IntoDeserializer, Visitor};
#[cfg(any(feature = "std", feature = "alloc"))]
-use de::Unexpected;
+use de::{Unexpected, MapAccess};
#[cfg(any(feature = "std", feature = "alloc"))]
pub use self::content::{Content, ContentDeserializer, ContentRefDeserializer,
InternallyTaggedUnitVisitor, TagContentOtherField,
TagContentOtherFieldVisitor, TagOrContentField, TagOrContentFieldVisitor,
- TaggedContentVisitor, UntaggedUnitVisitor};
+ TaggedContentVisitor, UntaggedUnitVisitor, EnumDeserializer};
/// If the missing field is of type `Option<T>` then treat is as `None`,
/// otherwise it is an error.
pub fn missing_field<'de, V, E>(field: &'static str) -> Result<V, E>
where
V: Deserialize<'de>,
E: Error,
{
@@ -183,17 +183,17 @@ where
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
where
E: Error,
{
Ok(Cow::Owned(v))
}
}
- deserializer.deserialize_str(CowBytesVisitor)
+ deserializer.deserialize_bytes(CowBytesVisitor)
}
pub mod size_hint {
use lib::*;
pub fn from_bounds<I>(iter: &I) -> Option<usize>
where
I: Iterator,
@@ -264,16 +264,24 @@ mod content {
Unit,
Newtype(Box<Content<'de>>),
Seq(Vec<Content<'de>>),
Map(Vec<(Content<'de>, Content<'de>)>),
}
impl<'de> Content<'de> {
+ pub fn as_str(&self) -> Option<&str> {
+ match *self {
+ Content::Str(x) => Some(x),
+ Content::String(ref x) => Some(x),
+ _ => None,
+ }
+ }
+
fn unexpected(&self) -> Unexpected {
match *self {
Content::Bool(b) => Unexpected::Bool(b),
Content::U8(n) => Unexpected::Unsigned(n as u64),
Content::U16(n) => Unexpected::Unsigned(n as u64),
Content::U32(n) => Unexpected::Unsigned(n as u64),
Content::U64(n) => Unexpected::Unsigned(n),
Content::I8(n) => Unexpected::Signed(n as i64),
@@ -1113,21 +1121,17 @@ mod content {
other => {
return Err(de::Error::invalid_type(
other.unexpected(),
&"string or map",
));
}
};
- visitor.visit_enum(EnumDeserializer {
- variant: variant,
- value: value,
- err: PhantomData,
- })
+ visitor.visit_enum(EnumDeserializer::new(variant, value))
}
fn deserialize_unit_struct<V>(
self,
_name: &'static str,
visitor: V,
) -> Result<V::Value, Self::Error>
where
@@ -1165,25 +1169,37 @@ mod content {
pub fn new(content: Content<'de>) -> Self {
ContentDeserializer {
content: content,
err: PhantomData,
}
}
}
- struct EnumDeserializer<'de, E>
+ pub struct EnumDeserializer<'de, E>
where
E: de::Error,
{
variant: Content<'de>,
value: Option<Content<'de>>,
err: PhantomData<E>,
}
+ impl<'de, E> EnumDeserializer<'de, E>
+ where E: de::Error
+ {
+ pub fn new(variant: Content<'de>, value: Option<Content<'de>>) -> EnumDeserializer<'de, E> {
+ EnumDeserializer {
+ variant: variant,
+ value: value,
+ err: PhantomData,
+ }
+ }
+ }
+
impl<'de, E> de::EnumAccess<'de> for EnumDeserializer<'de, E>
where
E: de::Error,
{
type Error = E;
type Variant = VariantDeserializer<'de, Self::Error>;
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), E>
@@ -1194,17 +1210,17 @@ mod content {
value: self.value,
err: PhantomData,
};
seed.deserialize(ContentDeserializer::new(self.variant))
.map(|v| (v, visitor))
}
}
- struct VariantDeserializer<'de, E>
+ pub struct VariantDeserializer<'de, E>
where
E: de::Error,
{
value: Option<Content<'de>>,
err: PhantomData<E>,
}
impl<'de, E> de::VariantAccess<'de> for VariantDeserializer<'de, E>
@@ -2057,8 +2073,167 @@ where
type Value = ();
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
T::deserialize_in_place(deserializer, self.0)
}
}
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+pub struct FlatMapDeserializer<'a, 'de: 'a, E>(
+ pub &'a mut Vec<Option<(Content<'de>, Content<'de>)>>,
+ pub PhantomData<E>
+);
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+impl<'a, 'de, E> Deserializer<'de> for FlatMapDeserializer<'a, 'de, E>
+ where E: Error
+{
+ type Error = E;
+
+ fn deserialize_any<V>(self, _: V) -> Result<V::Value, Self::Error>
+ where
+ V: Visitor<'de>,
+ {
+ Err(Error::custom("can only flatten structs and maps"))
+ }
+
+ fn deserialize_enum<V>(
+ self,
+ name: &'static str,
+ variants: &'static [&'static str],
+ visitor: V
+ ) -> Result<V::Value, Self::Error>
+ where
+ V: Visitor<'de>,
+ {
+ for item in self.0.iter_mut() {
+ // items in the vector are nulled out when used. So we can only use
+ // an item if it's still filled in and if the field is one we care
+ // about.
+ let use_item = match *item {
+ None => false,
+ Some((ref c, _)) => c.as_str().map_or(false, |x| variants.contains(&x))
+ };
+
+ if use_item {
+ let (key, value) = item.take().unwrap();
+ return visitor.visit_enum(EnumDeserializer::new(
+ key,
+ Some(value)
+ ));
+ }
+ }
+
+ Err(Error::custom(format_args!(
+ "no variant of enum {} not found in flattened data",
+ name
+ )))
+ }
+
+ fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+ where
+ V: Visitor<'de>,
+ {
+ visitor.visit_map(FlatMapAccess::new(self.0.iter_mut(), None))
+ }
+
+ fn deserialize_struct<V>(
+ self,
+ _: &'static str,
+ fields: &'static [&'static str],
+ visitor: V
+ ) -> Result<V::Value, Self::Error>
+ where
+ V: Visitor<'de>,
+ {
+ visitor.visit_map(FlatMapAccess::new(self.0.iter_mut(), Some(fields)))
+ }
+
+ fn deserialize_newtype_struct<V>(
+ self,
+ _name: &str,
+ visitor: V,
+ ) -> Result<V::Value, Self::Error>
+ where
+ V: Visitor<'de>,
+ {
+ visitor.visit_newtype_struct(self)
+ }
+
+ forward_to_deserialize_any! {
+ bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
+ byte_buf option unit unit_struct seq tuple tuple_struct identifier
+ ignored_any
+ }
+}
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+pub struct FlatMapAccess<'a, 'de: 'a, E> {
+ iter: slice::IterMut<'a, Option<(Content<'de>, Content<'de>)>>,
+ pending_content: Option<Content<'de>>,
+ fields: Option<&'static [&'static str]>,
+ _marker: PhantomData<E>,
+}
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+impl<'a, 'de, E> FlatMapAccess<'a, 'de, E> {
+ fn new(
+ iter: slice::IterMut<'a, Option<(Content<'de>, Content<'de>)>>,
+ fields: Option<&'static [&'static str]>
+ ) -> FlatMapAccess<'a, 'de, E> {
+ FlatMapAccess {
+ iter: iter,
+ pending_content: None,
+ fields: fields,
+ _marker: PhantomData,
+ }
+ }
+}
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+impl<'a, 'de, E> MapAccess<'de> for FlatMapAccess<'a, 'de, E>
+ where E: Error
+{
+ type Error = E;
+
+ fn next_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
+ where
+ T: DeserializeSeed<'de>,
+ {
+ while let Some(item) = self.iter.next() {
+ // items in the vector are nulled out when used. So we can only use
+ // an item if it's still filled in and if the field is one we care
+ // about. In case we do not know which fields we want, we take them all.
+ let use_item = match *item {
+ None => false,
+ Some((ref c, _)) => {
+ c.as_str().map_or(self.fields.is_none(), |key| {
+ match self.fields {
+ None => true,
+ Some(fields) if fields.contains(&key) => true,
+ _ => false
+ }
+ })
+ }
+ };
+
+ if use_item {
+ let (key, content) = item.take().unwrap();
+ self.pending_content = Some(content);
+ return seed.deserialize(ContentDeserializer::new(key)).map(Some);
+ }
+ }
+ Ok(None)
+ }
+
+ fn next_value_seed<T>(&mut self, seed: T) -> Result<T::Value, Self::Error>
+ where
+ T: DeserializeSeed<'de>,
+ {
+ match self.pending_content.take() {
+ Some(value) => seed.deserialize(ContentDeserializer::new(value)),
+ None => Err(Error::custom("value is missing")),
+ }
+ }
+}
--- a/third_party/rust/serde/src/private/ser.rs
+++ b/third_party/rust/serde/src/private/ser.rs
@@ -6,17 +6,22 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use lib::*;
use ser::{self, Impossible, Serialize, SerializeMap, SerializeStruct, Serializer};
#[cfg(any(feature = "std", feature = "alloc"))]
-use self::content::{SerializeStructVariantAsMapValue, SerializeTupleVariantAsMapValue};
+use self::content::{
+ SerializeStructVariantAsMapValue,
+ SerializeTupleVariantAsMapValue,
+ ContentSerializer,
+ Content,
+};
/// Used to check that serde(getter) attributes return the expected type.
/// Not public API.
pub fn constrain<T: ?Sized>(t: &T) -> &T {
t
}
/// Not public API.
@@ -53,38 +58,40 @@ enum Unsupported {
Boolean,
Integer,
Float,
Char,
String,
ByteArray,
Optional,
Unit,
+ #[cfg(any(feature = "std", feature = "alloc"))]
+ UnitStruct,
Sequence,
Tuple,
TupleStruct,
- #[cfg(not(any(feature = "std", feature = "alloc")))]
Enum,
}
impl Display for Unsupported {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match *self {
Unsupported::Boolean => formatter.write_str("a boolean"),
Unsupported::Integer => formatter.write_str("an integer"),
Unsupported::Float => formatter.write_str("a float"),
Unsupported::Char => formatter.write_str("a char"),
Unsupported::String => formatter.write_str("a string"),
Unsupported::ByteArray => formatter.write_str("a byte array"),
Unsupported::Optional => formatter.write_str("an optional"),
Unsupported::Unit => formatter.write_str("unit"),
+ #[cfg(any(feature = "std", feature = "alloc"))]
+ Unsupported::UnitStruct => formatter.write_str("unit struct"),
Unsupported::Sequence => formatter.write_str("a sequence"),
Unsupported::Tuple => formatter.write_str("a tuple"),
Unsupported::TupleStruct => formatter.write_str("a tuple struct"),
- #[cfg(not(any(feature = "std", feature = "alloc")))]
Unsupported::Enum => formatter.write_str("an enum"),
}
}
}
impl<S> TaggedSerializer<S>
where
S: Serializer,
@@ -454,17 +461,17 @@ mod content {
self.map
.serialize_value(&Content::Struct(self.name, self.fields))
);
self.map.end()
}
}
#[derive(Debug)]
- enum Content {
+ pub enum Content {
Bool(bool),
U8(u8),
U16(u16),
U32(u32),
U64(u64),
I8(i8),
@@ -579,22 +586,22 @@ mod content {
try!(sv.serialize_field(k, v));
}
sv.end()
}
}
}
}
- struct ContentSerializer<E> {
+ pub struct ContentSerializer<E> {
error: PhantomData<E>,
}
impl<E> ContentSerializer<E> {
- fn new() -> Self {
+ pub fn new() -> Self {
ContentSerializer { error: PhantomData }
}
}
impl<E> Serializer for ContentSerializer<E>
where
E: ser::Error,
{
@@ -799,17 +806,17 @@ mod content {
variant_index: variant_index,
variant: variant,
fields: Vec::with_capacity(len),
error: PhantomData,
})
}
}
- struct SerializeSeq<E> {
+ pub struct SerializeSeq<E> {
elements: Vec<Content>,
error: PhantomData<E>,
}
impl<E> ser::SerializeSeq for SerializeSeq<E>
where
E: ser::Error,
{
@@ -825,17 +832,17 @@ mod content {
Ok(())
}
fn end(self) -> Result<Content, E> {
Ok(Content::Seq(self.elements))
}
}
- struct SerializeTuple<E> {
+ pub struct SerializeTuple<E> {
elements: Vec<Content>,
error: PhantomData<E>,
}
impl<E> ser::SerializeTuple for SerializeTuple<E>
where
E: ser::Error,
{
@@ -851,17 +858,17 @@ mod content {
Ok(())
}
fn end(self) -> Result<Content, E> {
Ok(Content::Tuple(self.elements))
}
}
- struct SerializeTupleStruct<E> {
+ pub struct SerializeTupleStruct<E> {
name: &'static str,
fields: Vec<Content>,
error: PhantomData<E>,
}
impl<E> ser::SerializeTupleStruct for SerializeTupleStruct<E>
where
E: ser::Error,
@@ -878,17 +885,17 @@ mod content {
Ok(())
}
fn end(self) -> Result<Content, E> {
Ok(Content::TupleStruct(self.name, self.fields))
}
}
- struct SerializeTupleVariant<E> {
+ pub struct SerializeTupleVariant<E> {
name: &'static str,
variant_index: u32,
variant: &'static str,
fields: Vec<Content>,
error: PhantomData<E>,
}
impl<E> ser::SerializeTupleVariant for SerializeTupleVariant<E>
@@ -912,17 +919,17 @@ mod content {
self.name,
self.variant_index,
self.variant,
self.fields,
))
}
}
- struct SerializeMap<E> {
+ pub struct SerializeMap<E> {
entries: Vec<(Content, Content)>,
key: Option<Content>,
error: PhantomData<E>,
}
impl<E> ser::SerializeMap for SerializeMap<E>
where
E: ser::Error,
@@ -962,17 +969,17 @@ mod content {
{
let key = try!(key.serialize(ContentSerializer::<E>::new()));
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.entries.push((key, value));
Ok(())
}
}
- struct SerializeStruct<E> {
+ pub struct SerializeStruct<E> {
name: &'static str,
fields: Vec<(&'static str, Content)>,
error: PhantomData<E>,
}
impl<E> ser::SerializeStruct for SerializeStruct<E>
where
E: ser::Error,
@@ -989,17 +996,17 @@ mod content {
Ok(())
}
fn end(self) -> Result<Content, E> {
Ok(Content::Struct(self.name, self.fields))
}
}
- struct SerializeStructVariant<E> {
+ pub struct SerializeStructVariant<E> {
name: &'static str,
variant_index: u32,
variant: &'static str,
fields: Vec<(&'static str, Content)>,
error: PhantomData<E>,
}
impl<E> ser::SerializeStructVariant for SerializeStructVariant<E>
@@ -1023,8 +1030,288 @@ mod content {
self.name,
self.variant_index,
self.variant,
self.fields,
))
}
}
}
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+pub struct FlatMapSerializer<'a, M: 'a>(pub &'a mut M);
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+impl<'a, M> FlatMapSerializer<'a, M>
+where
+ M: SerializeMap + 'a
+{
+ fn bad_type(self, what: Unsupported) -> M::Error {
+ ser::Error::custom(format_args!("can only flatten structs and maps (got {})", what))
+ }
+}
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+impl<'a, M> Serializer for FlatMapSerializer<'a, M>
+ where M: SerializeMap + 'a
+{
+ type Ok = ();
+ type Error = M::Error;
+
+ type SerializeSeq = Impossible<Self::Ok, M::Error>;
+ type SerializeTuple = Impossible<Self::Ok, M::Error>;
+ type SerializeTupleStruct = Impossible<Self::Ok, M::Error>;
+ type SerializeMap = FlatMapSerializeMap<'a, M>;
+ type SerializeStruct = FlatMapSerializeStruct<'a, M>;
+ type SerializeTupleVariant = Impossible<Self::Ok, M::Error>;
+ type SerializeStructVariant = FlatMapSerializeStructVariantAsMapValue<'a, M>;
+
+ fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
+ Err(self.bad_type(Unsupported::Boolean))
+ }
+
+ fn serialize_i8(self, _: i8) -> Result<Self::Ok, Self::Error> {
+ Err(self.bad_type(Unsupported::Integer))
+ }
+
+ fn serialize_i16(self, _: i16) -> Result<Self::Ok, Self::Error> {
+ Err(self.bad_type(Unsupported::Integer))
+ }
+
+ fn serialize_i32(self, _: i32) -> Result<Self::Ok, Self::Error> {
+ Err(self.bad_type(Unsupported::Integer))
+ }
+
+ fn serialize_i64(self, _: i64) -> Result<Self::Ok, Self::Error> {
+ Err(self.bad_type(Unsupported::Integer))
+ }
+
+ fn serialize_u8(self, _: u8) -> Result<Self::Ok, Self::Error> {
+ Err(self.bad_type(Unsupported::Integer))
+ }
+
+ fn serialize_u16(self, _: u16) -> Result<Self::Ok, Self::Error> {
+ Err(self.bad_type(Unsupported::Integer))
+ }
+
+ fn serialize_u32(self, _: u32) -> Result<Self::Ok, Self::Error> {
+ Err(self.bad_type(Unsupported::Integer))
+ }
+
+ fn serialize_u64(self, _: u64) -> Result<Self::Ok, Self::Error> {
+ Err(self.bad_type(Unsupported::Integer))
+ }
+
+ fn serialize_f32(self, _: f32) -> Result<Self::Ok, Self::Error> {
+ Err(self.bad_type(Unsupported::Float))
+ }
+
+ fn serialize_f64(self, _: f64) -> Result<Self::Ok, Self::Error> {
+ Err(self.bad_type(Unsupported::Float))
+ }
+
+ fn serialize_char(self, _: char) -> Result<Self::Ok, Self::Error> {
+ Err(self.bad_type(Unsupported::Char))
+ }
+
+ fn serialize_str(self, _: &str) -> Result<Self::Ok, Self::Error> {
+ Err(self.bad_type(Unsupported::String))
+ }
+
+ fn serialize_bytes(self, _: &[u8]) -> Result<Self::Ok, Self::Error> {
+ Err(self.bad_type(Unsupported::ByteArray))
+ }
+
+ fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
+ Err(self.bad_type(Unsupported::Optional))
+ }
+
+ fn serialize_some<T: ?Sized>(self, _: &T) -> Result<Self::Ok, Self::Error>
+ where
+ T: Serialize,
+ {
+ Err(self.bad_type(Unsupported::Optional))
+ }
+
+ fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
+ Err(self.bad_type(Unsupported::Unit))
+ }
+
+ fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
+ Err(self.bad_type(Unsupported::UnitStruct))
+ }
+
+ fn serialize_unit_variant(
+ self,
+ _: &'static str,
+ _: u32,
+ _: &'static str,
+ ) -> Result<Self::Ok, Self::Error> {
+ Err(self.bad_type(Unsupported::Enum))
+ }
+
+ fn serialize_newtype_struct<T: ?Sized>(
+ self,
+ _: &'static str,
+ value: &T,
+ ) -> Result<Self::Ok, Self::Error>
+ where
+ T: Serialize,
+ {
+ value.serialize(self)
+ }
+
+ fn serialize_newtype_variant<T: ?Sized>(
+ self,
+ _: &'static str,
+ _: u32,
+ variant: &'static str,
+ value: &T,
+ ) -> Result<Self::Ok, Self::Error>
+ where
+ T: Serialize,
+ {
+ try!(self.0.serialize_key(variant));
+ self.0.serialize_value(value)
+ }
+
+ fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
+ Err(self.bad_type(Unsupported::Sequence))
+ }
+
+ fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple, Self::Error> {
+ Err(self.bad_type(Unsupported::Tuple))
+ }
+
+ fn serialize_tuple_struct(
+ self,
+ _: &'static str,
+ _: usize,
+ ) -> Result<Self::SerializeTupleStruct, Self::Error> {
+ Err(self.bad_type(Unsupported::TupleStruct))
+ }
+
+ fn serialize_tuple_variant(
+ self,
+ _: &'static str,
+ _: u32,
+ _: &'static str,
+ _: usize,
+ ) -> Result<Self::SerializeTupleVariant, Self::Error> {
+ Err(self.bad_type(Unsupported::Enum))
+ }
+
+ fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
+ Ok(FlatMapSerializeMap(self.0))
+ }
+
+ fn serialize_struct(
+ self,
+ _: &'static str,
+ _: usize,
+ ) -> Result<Self::SerializeStruct, Self::Error> {
+ Ok(FlatMapSerializeStruct(self.0))
+ }
+
+ fn serialize_struct_variant(
+ self,
+ _: &'static str,
+ _: u32,
+ inner_variant: &'static str,
+ _: usize,
+ ) -> Result<Self::SerializeStructVariant, Self::Error> {
+ try!(self.0.serialize_key(inner_variant));
+ Ok(FlatMapSerializeStructVariantAsMapValue::new(self.0, inner_variant))
+ }
+}
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+pub struct FlatMapSerializeMap<'a, M: 'a>(&'a mut M);
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+impl<'a, M> ser::SerializeMap for FlatMapSerializeMap<'a, M>
+ where M: SerializeMap + 'a
+{
+ type Ok = ();
+ type Error = M::Error;
+
+ fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
+ where
+ T: Serialize,
+ {
+ self.0.serialize_key(key)
+ }
+
+ fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
+ where
+ T: Serialize,
+ {
+ self.0.serialize_value(value)
+ }
+
+ fn end(self) -> Result<(), Self::Error> {
+ Ok(())
+ }
+}
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+pub struct FlatMapSerializeStruct<'a, M: 'a>(&'a mut M);
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+impl<'a, M> ser::SerializeStruct for FlatMapSerializeStruct<'a, M>
+ where M: SerializeMap + 'a
+{
+ type Ok = ();
+ type Error = M::Error;
+
+ fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
+ where
+ T: Serialize,
+ {
+ self.0.serialize_entry(key, value)
+ }
+
+ fn end(self) -> Result<(), Self::Error> {
+ Ok(())
+ }
+}
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+pub struct FlatMapSerializeStructVariantAsMapValue<'a, M: 'a> {
+ map: &'a mut M,
+ name: &'static str,
+ fields: Vec<(&'static str, Content)>,
+}
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+impl<'a, M> FlatMapSerializeStructVariantAsMapValue<'a, M>
+ where M: SerializeMap + 'a
+{
+ fn new(map: &'a mut M, name: &'static str) -> FlatMapSerializeStructVariantAsMapValue<'a, M> {
+ FlatMapSerializeStructVariantAsMapValue {
+ map: map,
+ name: name,
+ fields: Vec::new(),
+ }
+ }
+}
+
+#[cfg(any(feature = "std", feature = "alloc"))]
+impl<'a, M> ser::SerializeStructVariant for FlatMapSerializeStructVariantAsMapValue<'a, M>
+ where M: SerializeMap + 'a
+{
+ type Ok = ();
+ type Error = M::Error;
+
+ fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
+ where
+ T: Serialize,
+ {
+ let value = try!(value.serialize(ContentSerializer::<M::Error>::new()));
+ self.fields.push((key, value));
+ Ok(())
+ }
+
+ fn end(self) -> Result<(), Self::Error> {
+ try!(self.map.serialize_value(&Content::Struct(self.name, self.fields)));
+ Ok(())
+ }
+}
--- a/third_party/rust/serde/src/ser/impls.rs
+++ b/third_party/rust/serde/src/ser/impls.rs
@@ -346,28 +346,55 @@ deref_impl!(<T: ?Sized> Serialize for Rc
deref_impl!(<T: ?Sized> Serialize for Arc<T> where T: Serialize);
#[cfg(any(feature = "std", feature = "alloc"))]
deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned);
////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "unstable")]
+#[allow(deprecated)]
impl<T> Serialize for NonZero<T>
where
T: Serialize + Zeroable + Clone,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.clone().get().serialize(serializer)
}
}
+macro_rules! nonzero_integers {
+ ( $( $T: ident, )+ ) => {
+ $(
+ #[cfg(feature = "unstable")]
+ impl Serialize for $T {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: Serializer,
+ {
+ self.get().serialize(serializer)
+ }
+ }
+ )+
+ }
+}
+
+nonzero_integers! {
+ // Not including signed NonZeroI* since they might be removed
+ NonZeroU8,
+ NonZeroU16,
+ NonZeroU32,
+ NonZeroU64,
+ // FIXME: https://github.com/serde-rs/serde/issues/1136 NonZeroU128,
+ NonZeroUsize,
+}
+
impl<T> Serialize for Cell<T>
where
T: Serialize + Copy,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
--- a/third_party/rust/serde/src/ser/mod.rs
+++ b/third_party/rust/serde/src/ser/mod.rs
@@ -88,17 +88,18 @@
//! - OsStr
//! - OsString
//! - **Miscellaneous standard library types**:
//! - Duration
//! - SystemTime
//! - Path
//! - PathBuf
//! - Range\<T\>
-//! - NonZero\<T\> (unstable)
+//! - NonZero\<T\> (unstable, deprecated)
+//! - num::NonZero* (unstable)
//! - **Net types**:
//! - IpAddr
//! - Ipv4Addr
//! - Ipv6Addr
//! - SocketAddr
//! - SocketAddrV4
//! - SocketAddrV6
//!
--- a/third_party/rust/serde_derive/.cargo-checksum.json
+++ b/third_party/rust/serde_derive/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"f4d63b1c5051b3e0e32fe70dabff07245e8d7e89381b1ed99789072083453201","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"7dc6376a88195594cd6b43cb891aad10f57144ff737178b55d046aa04739b43a","src/bound.rs":"a10e5a103ce3866f8701e80c429106aa6b67b8250026ed2c0d36977748d4cc97","src/de.rs":"991ec19db1b486c2e91bce3f097f8f247ab6122eb8900a2c9267fa9c9e493417","src/fragment.rs":"5a63181171d4d05cea9f28d8ed27a550bc8ac176ee90a911a0598fbe340eec1a","src/lib.rs":"40817849b19a73459fbe5955cf22fb73f634e54df53bb309a0b6e4750b310ea6","src/ser.rs":"0ca344ccbe227f99bb875fe583b97757beb8233dc39acb1836782937c9036bd6"},"package":null}
\ No newline at end of file
+{"files":{"Cargo.toml":"cca09c175616b8390468aae4db4cb82688934de6f9e8bb70d7765e775d1304c9","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"7dc6376a88195594cd6b43cb891aad10f57144ff737178b55d046aa04739b43a","src/bound.rs":"44373ac15601ad92d7862fa33b59219bce111a5d3d8a1de6386e3490a8e4fbf5","src/de.rs":"fbe74de7a3bbcfe2128f016782d24b0ba925f7976563766f728744889d107020","src/fragment.rs":"4e34eca12e6ac4bd89f55e85786cfb677e98182f21ce1f51c0573bca5a8bcd27","src/lib.rs":"389815c14539bc1b394a53fd838a2d97d10def55acf034b67e87435c9d8287fa","src/ser.rs":"190bd80a820cf05155506c34bf5f512c26bae10f67b5877929b0b859d70a8431"},"package":null}
\ No newline at end of file
--- a/third_party/rust/serde_derive/Cargo.toml
+++ b/third_party/rust/serde_derive/Cargo.toml
@@ -1,11 +1,11 @@
[package]
name = "serde_derive"
-version = "1.0.27" # remember to update html_root_url
+version = "1.0.35" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://serde.rs/codegen.html"
keywords = ["serde", "serialization", "no_std"]
readme = "README.md"
@@ -18,14 +18,15 @@ travis-ci = { repository = "serde-rs/ser
default = []
deserialize_in_place = []
[lib]
name = "serde_derive"
proc-macro = true
[dependencies]
-quote = "0.3.8"
-serde_derive_internals = { version = "=0.19.0", default-features = false, path = "../serde_derive_internals" }
-syn = { version = "0.11", features = ["visit"] }
+proc-macro2 = "0.2"
+quote = "0.4"
+serde_derive_internals = { version = "=0.22.1", default-features = false, path = "../serde_derive_internals" }
+syn = { version = "0.12", features = ["visit"] }
[dev-dependencies]
serde = { version = "1.0", path = "../serde" }
--- a/third_party/rust/serde_derive/src/bound.rs
+++ b/third_party/rust/serde_derive/src/bound.rs
@@ -4,70 +4,90 @@
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::collections::HashSet;
use syn::{self, visit};
+use syn::punctuated::Punctuated;
-use internals::ast::{Body, Container};
+use internals::ast::{Data, Container};
use internals::attr;
-macro_rules! path {
- ($($path:tt)+) => {
- syn::parse_path(quote!($($path)+).as_str()).unwrap()
- };
-}
+use proc_macro2::{Span, Term};
// 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 {
- ty_params: generics
- .ty_params
+ params: generics
+ .params
.iter()
- .map(|ty_param| syn::TyParam {
- default: None,
- ..ty_param.clone()
+ .map(|param| match *param {
+ syn::GenericParam::Type(ref 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
- .where_clause
+ if generics.where_clause.is_none() {
+ generics.where_clause = Some(syn::WhereClause {
+ where_token: Default::default(),
+ predicates: Punctuated::new(),
+ });
+ }
+ generics.where_clause
+ .as_mut()
+ .unwrap()
.predicates
- .extend_from_slice(predicates);
+ .extend(predicates.into_iter().cloned());
generics
}
pub fn with_where_predicates_from_fields<F>(
cont: &Container,
generics: &syn::Generics,
from_field: F,
) -> syn::Generics
where
F: Fn(&attr::Field) -> Option<&[syn::WherePredicate]>,
{
- let predicates = cont.body
+ let predicates = cont.data
.all_fields()
.flat_map(|field| from_field(&field.attrs))
.flat_map(|predicates| predicates.to_vec());
let mut generics = generics.clone();
- generics.where_clause.predicates.extend(predicates);
+ if generics.where_clause.is_none() {
+ generics.where_clause = Some(syn::WhereClause {
+ where_token: Default::default(),
+ predicates: Punctuated::new(),
+ });
+ }
+ generics.where_clause
+ .as_mut()
+ .unwrap()
+ .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`.
//
@@ -90,169 +110,213 @@ where
// Set of all generic type parameters on the current struct (A, B, C in
// the example). Initialized up front.
all_ty_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_ty_params: HashSet<syn::Ident>,
}
- impl visit::Visitor for FindTyParams {
+ impl<'ast> visit::Visit<'ast> for FindTyParams {
fn visit_path(&mut self, path: &syn::Path) {
if let Some(seg) = path.segments.last() {
- if seg.ident == "PhantomData" {
+ if seg.into_value().ident == "PhantomData" {
// Hardcoded exception, because PhantomData<T> implements
// Serialize and Deserialize whether or not T implements it.
return;
}
}
- if !path.global && path.segments.len() == 1 {
- let id = path.segments[0].ident.clone();
+ if path.leading_colon.is_none() && path.segments.len() == 1 {
+ let id = path.segments[0].ident;
if self.all_ty_params.contains(&id) {
self.relevant_ty_params.insert(id);
}
}
- visit::walk_path(self, path);
+ visit::visit_path(self, path);
}
// Type parameter should not be considered used by a macro path.
//
// struct TypeMacro<T> {
// mac: T!(),
// marker: PhantomData<T>,
// }
- fn visit_mac(&mut self, _mac: &syn::Mac) {}
+ fn visit_macro(&mut self, _mac: &syn::Macro) {}
}
let all_ty_params: HashSet<_> = generics
- .ty_params
+ .params
.iter()
- .map(|ty_param| ty_param.ident.clone())
+ .filter_map(|param| match *param {
+ syn::GenericParam::Type(ref param) => Some(param.ident),
+ _ => None,
+ })
.collect();
let mut visitor = FindTyParams {
all_ty_params: all_ty_params,
relevant_ty_params: HashSet::new(),
};
- match cont.body {
- Body::Enum(_, ref variants) => for variant in variants.iter() {
+ match cont.data {
+ Data::Enum(_, ref variants) => for variant in variants.iter() {
let relevant_fields = variant
.fields
.iter()
.filter(|field| filter(&field.attrs, Some(&variant.attrs)));
for field in relevant_fields {
- visit::walk_ty(&mut visitor, field.ty);
+ visit::visit_type(&mut visitor, field.ty);
}
},
- Body::Struct(_, ref fields) => {
+ Data::Struct(_, ref fields) => {
for field in fields.iter().filter(|field| filter(&field.attrs, None)) {
- visit::walk_ty(&mut visitor, field.ty);
+ visit::visit_type(&mut visitor, field.ty);
}
}
}
let new_predicates = generics
- .ty_params
+ .params
.iter()
- .map(|ty_param| ty_param.ident.clone())
+ .filter_map(|param| match *param {
+ syn::GenericParam::Type(ref param) => Some(param.ident),
+ _ => None,
+ })
.filter(|id| visitor.relevant_ty_params.contains(id))
.map(|id| {
- syn::WherePredicate::BoundPredicate(syn::WhereBoundPredicate {
- bound_lifetimes: Vec::new(),
+ syn::WherePredicate::Type(syn::PredicateType {
+ lifetimes: None,
// the type parameter that is being bounded e.g. T
- bounded_ty: syn::Ty::Path(None, id.into()),
+ bounded_ty: syn::Type::Path(syn::TypePath {
+ qself: None,
+ path: id.into(),
+ }),
+ colon_token: Default::default(),
// the bound e.g. Serialize
bounds: vec![
- syn::TyParamBound::Trait(
- syn::PolyTraitRef {
- bound_lifetimes: Vec::new(),
- trait_ref: bound.clone(),
- },
- syn::TraitBoundModifier::None,
- ),
- ],
+ syn::TypeParamBound::Trait(syn::TraitBound {
+ modifier: syn::TraitBoundModifier::None,
+ lifetimes: None,
+ path: bound.clone(),
+ }),
+ ].into_iter().collect(),
})
});
let mut generics = generics.clone();
- generics.where_clause.predicates.extend(new_predicates);
+ if generics.where_clause.is_none() {
+ generics.where_clause = Some(syn::WhereClause {
+ where_token: Default::default(),
+ predicates: Punctuated::new(),
+ });
+ }
+ generics.where_clause
+ .as_mut()
+ .unwrap()
+ .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
- .where_clause
+ if generics.where_clause.is_none() {
+ generics.where_clause = Some(syn::WhereClause {
+ where_token: Default::default(),
+ predicates: Punctuated::new(),
+ });
+ }
+ generics.where_clause
+ .as_mut()
+ .unwrap()
.predicates
- .push(syn::WherePredicate::BoundPredicate(
- syn::WhereBoundPredicate {
- bound_lifetimes: Vec::new(),
- // the type that is being bounded e.g. MyStruct<'a, T>
- bounded_ty: type_of_item(cont),
- // the bound e.g. Default
- bounds: vec![
- syn::TyParamBound::Trait(
- syn::PolyTraitRef {
- bound_lifetimes: Vec::new(),
- trait_ref: bound.clone(),
- },
- syn::TraitBoundModifier::None,
- ),
- ],
- },
- ));
+ .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: Default::default(),
+ // the bound e.g. Default
+ bounds: vec![
+ syn::TypeParamBound::Trait(syn::TraitBound {
+ 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 mut generics = generics.clone();
-
- for lifetime_def in &mut generics.lifetimes {
- lifetime_def.bounds.push(syn::Lifetime::new(lifetime));
- }
+ let bound = syn::Lifetime::new(Term::intern(lifetime), Span::def_site());
+ let def = syn::LifetimeDef {
+ attrs: Vec::new(),
+ lifetime: bound,
+ colon_token: None,
+ bounds: Punctuated::new(),
+ };
- for ty_param in &mut generics.ty_params {
- ty_param
- .bounds
- .push(syn::TyParamBound::Region(syn::Lifetime::new(lifetime)));
- }
+ let params = Some(syn::GenericParam::Lifetime(def))
+ .into_iter()
+ .chain(generics.params
+ .iter()
+ .cloned()
+ .map(|mut param| {
+ match param {
+ syn::GenericParam::Lifetime(ref mut param) => {
+ param.bounds.push(bound);
+ }
+ syn::GenericParam::Type(ref mut param) => {
+ param.bounds.push(syn::TypeParamBound::Lifetime(bound));
+ }
+ syn::GenericParam::Const(_) => {}
+ }
+ param
+ }))
+ .collect();
- generics.lifetimes.push(syn::LifetimeDef {
- attrs: Vec::new(),
- lifetime: syn::Lifetime::new(lifetime),
- bounds: Vec::new(),
- });
-
- generics
+ syn::Generics {
+ params: params,
+ ..generics.clone()
+ }
}
-fn type_of_item(cont: &Container) -> syn::Ty {
- syn::Ty::Path(
- None,
- syn::Path {
- global: false,
+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(),
- parameters: syn::PathParameters::AngleBracketed(
- syn::AngleBracketedParameterData {
- lifetimes: cont.generics
- .lifetimes
+ ident: cont.ident,
+ arguments: syn::PathArguments::AngleBracketed(
+ syn::AngleBracketedGenericArguments {
+ colon2_token: None,
+ lt_token: Default::default(),
+ args: cont.generics
+ .params
.iter()
- .map(|def| def.lifetime.clone())
+ .map(|param| match *param {
+ syn::GenericParam::Type(ref param) => {
+ syn::GenericArgument::Type(syn::Type::Path(syn::TypePath {
+ qself: None,
+ path: param.ident.into(),
+ }))
+ }
+ syn::GenericParam::Lifetime(ref param) => {
+ syn::GenericArgument::Lifetime(param.lifetime)
+ }
+ syn::GenericParam::Const(_) => {
+ panic!("Serde does not support const generics yet");
+ }
+ })
.collect(),
- types: cont.generics
- .ty_params
- .iter()
- .map(|param| syn::Ty::Path(None, param.ident.clone().into()))
- .collect(),
- bindings: Vec::new(),
+ gt_token: Default::default(),
},
),
},
- ],
+ ].into_iter().collect(),
},
- )
+ })
}
--- a/third_party/rust/serde_derive/src/de.rs
+++ b/third_party/rust/serde_derive/src/de.rs
@@ -1,47 +1,51 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use syn::{self, Ident};
-use quote::{self, ToTokens, Tokens};
+use syn::{self, Ident, Index, Member};
+use syn::punctuated::Punctuated;
+use syn::spanned::Spanned;
+use quote::{ToTokens, Tokens};
+use proc_macro2::{Literal, Span, Term};
use bound;
use fragment::{Expr, Fragment, Match, Stmts};
-use internals::ast::{Body, Container, Field, Style, Variant};
+use internals::ast::{Data, Container, Field, Style, Variant};
use internals::{self, attr};
#[cfg(feature = "deserialize_in_place")]
use internals::ast::Repr;
use std::collections::BTreeSet;
pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result<Tokens, String> {
let ctxt = internals::Ctxt::new();
let cont = Container::from_ast(&ctxt, input);
try!(ctxt.check());
let ident = &cont.ident;
let params = Parameters::new(&cont);
let (de_impl_generics, _, ty_generics, where_clause) = split_with_de_lifetime(¶ms);
- let dummy_const = Ident::new(format!("_IMPL_DESERIALIZE_FOR_{}", ident));
+ let dummy_const = Ident::new(&format!("_IMPL_DESERIALIZE_FOR_{}", ident), Span::def_site());
let body = Stmts(deserialize_body(&cont, ¶ms));
let delife = params.borrowed.de_lifetime();
let impl_block = if let Some(remote) = cont.attrs.remote() {
let vis = &input.vis;
+ let fun = quote_spanned!(Span::call_site()=> deserialize);
quote! {
impl #de_impl_generics #ident #ty_generics #where_clause {
- #vis fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<#remote #ty_generics, __D::Error>
+ #vis fn #fun<__D>(__deserializer: __D) -> _serde::export::Result<#remote #ty_generics, __D::Error>
where __D: _serde::Deserializer<#delife>
{
#body
}
}
}
} else {
let fn_deserialize_in_place = deserialize_in_place_body(&cont, ¶ms);
@@ -89,72 +93,72 @@ struct Parameters {
/// At least one field has a serde(getter) attribute, implying that the
/// remote type has a private field.
has_getter: bool,
}
impl Parameters {
fn new(cont: &Container) -> Self {
- let local = cont.ident.clone();
+ let local = cont.ident;
let this = match cont.attrs.remote() {
Some(remote) => remote.clone(),
- None => cont.ident.clone().into(),
+ None => cont.ident.into(),
};
let borrowed = borrowed_lifetimes(cont);
let generics = build_generics(cont, &borrowed);
- let has_getter = cont.body.has_getter();
+ let has_getter = cont.data.has_getter();
Parameters {
local: local,
this: this,
generics: generics,
borrowed: borrowed,
has_getter: has_getter,
}
}
/// Type name to use in error messages and `&'static str` arguments to
/// various Deserializer methods.
fn type_name(&self) -> &str {
- self.this.segments.last().unwrap().ident.as_ref()
+ self.this.segments.last().unwrap().value().ident.as_ref()
}
}
// 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);
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, &path!(_serde::export::Default))
+ bound::with_self_bound(cont, &generics, &parse_quote!(_serde::export::Default))
}
attr::Default::None | attr::Default::Path(_) => generics,
};
let delife = borrowed.de_lifetime();
let generics = bound::with_bound(
cont,
&generics,
needs_deserialize_bound,
- &path!(_serde::Deserialize<#delife>),
+ &parse_quote!(_serde::Deserialize<#delife>),
);
bound::with_bound(
cont,
&generics,
requires_default,
- &path!(_serde::export::Default),
+ &parse_quote!(_serde::export::Default),
)
}
}
}
// Fields 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
@@ -162,38 +166,43 @@ fn build_generics(cont: &Container, borr
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.deserialize_with().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 {
- field.default() == &attr::Default::Default
+ if let attr::Default::Default = *field.default() {
+ true
+ } else {
+ false
+ }
}
#[derive(Clone)]
enum BorrowedLifetimes {
Borrowed(BTreeSet<syn::Lifetime>),
Static,
}
impl BorrowedLifetimes {
fn de_lifetime(&self) -> syn::Lifetime {
match *self {
- BorrowedLifetimes::Borrowed(_) => syn::Lifetime::new("'de"),
- BorrowedLifetimes::Static => syn::Lifetime::new("'static"),
+ BorrowedLifetimes::Borrowed(_) => syn::Lifetime::new(Term::intern("'de"), Span::def_site()),
+ BorrowedLifetimes::Static => syn::Lifetime::new(Term::intern("'static"), Span::def_site()),
}
}
fn de_lifetime_def(&self) -> Option<syn::LifetimeDef> {
match *self {
BorrowedLifetimes::Borrowed(ref bounds) => Some(syn::LifetimeDef {
attrs: Vec::new(),
- lifetime: syn::Lifetime::new("'de"),
+ lifetime: syn::Lifetime::new(Term::intern("'de"), Span::def_site()),
+ colon_token: None,
bounds: bounds.iter().cloned().collect(),
}),
BorrowedLifetimes::Static => None,
}
}
}
// The union of lifetimes borrowed by each field of the container.
@@ -202,87 +211,91 @@ impl BorrowedLifetimes {
// 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.body.all_fields() {
+ 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.ident == "'static") {
+ if lifetimes.iter().any(|b| b.to_string() == "'static") {
BorrowedLifetimes::Static
} else {
BorrowedLifetimes::Borrowed(lifetimes)
}
}
fn deserialize_body(cont: &Container, params: &Parameters) -> Fragment {
- if let Some(from_type) = cont.attrs.from_type() {
- deserialize_from(from_type)
+ if let Some(type_from) = cont.attrs.type_from() {
+ deserialize_from(type_from)
} else if let attr::Identifier::No = cont.attrs.identifier() {
- match cont.body {
- Body::Enum(_, ref variants) => deserialize_enum(params, variants, &cont.attrs),
- Body::Struct(Style::Struct, ref fields) => {
+ match cont.data {
+ Data::Enum(_, ref variants) => deserialize_enum(params, variants, &cont.attrs),
+ Data::Struct(Style::Struct, ref fields) => {
if fields.iter().any(|field| field.ident.is_none()) {
panic!("struct has unnamed fields");
}
- deserialize_struct(None, params, fields, &cont.attrs, None, Untagged::No)
+ deserialize_struct(None, params, fields, &cont.attrs, None, &Untagged::No)
}
- Body::Struct(Style::Tuple, ref fields) | Body::Struct(Style::Newtype, ref fields) => {
+ Data::Struct(Style::Tuple, ref fields) | Data::Struct(Style::Newtype, ref fields) => {
if fields.iter().any(|field| field.ident.is_some()) {
panic!("tuple struct has named fields");
}
deserialize_tuple(None, params, fields, &cont.attrs, None)
}
- Body::Struct(Style::Unit, _) => deserialize_unit_struct(params, &cont.attrs),
+ Data::Struct(Style::Unit, _) => deserialize_unit_struct(params, &cont.attrs),
}
} else {
- match cont.body {
- Body::Enum(_, ref variants) => {
+ match cont.data {
+ Data::Enum(_, ref variants) => {
deserialize_custom_identifier(params, variants, &cont.attrs)
}
- Body::Struct(_, _) => unreachable!("checked in serde_derive_internals"),
+ 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.from_type().is_some() || cont.attrs.identifier().is_some()
- || cont.body
+ if cont.attrs.type_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.body {
- Body::Struct(Style::Struct, ref fields) => {
- deserialize_struct_in_place(None, params, fields, &cont.attrs, None, Untagged::No)
+ let code = match cont.data {
+ Data::Struct(Style::Struct, ref fields) => {
+ if let Some(code) = deserialize_struct_in_place(None, params, fields, &cont.attrs, None) {
+ code
+ } else {
+ return None;
+ }
}
- Body::Struct(Style::Tuple, ref fields) | Body::Struct(Style::Newtype, ref fields) => {
+ Data::Struct(Style::Tuple, ref fields) | Data::Struct(Style::Newtype, ref fields) => {
deserialize_tuple_in_place(None, params, fields, &cont.attrs, None)
}
- Body::Enum(ref repr, ref variants) => {
+ Data::Enum(ref repr, ref variants) => {
if let Some(x) = deserialize_enum_in_place(params, repr, variants, &cont.attrs) {
x
} else {
return None;
}
}
- Body::Struct(Style::Unit, _) => {
+ Data::Struct(Style::Unit, _) => {
return None;
}
};
let delife = params.borrowed.de_lifetime();
let stmts = Stmts(code);
let fn_deserialize_in_place = quote_block! {
@@ -296,20 +309,20 @@ fn deserialize_in_place_body(cont: &Cont
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_from(from_type: &syn::Ty) -> Fragment {
+fn deserialize_from(type_from: &syn::Type) -> Fragment {
quote_block! {
_serde::export::Result::map(
- <#from_type as _serde::Deserialize>::deserialize(__deserializer),
+ <#type_from as _serde::Deserialize>::deserialize(__deserializer),
_serde::export::From::from)
}
}
fn deserialize_unit_struct(params: &Parameters, cattrs: &attr::Container) -> Fragment {
let this = ¶ms.this;
let type_name = cattrs.name().deserialize_name();
@@ -344,16 +357,18 @@ fn deserialize_tuple(
cattrs: &attr::Container,
deserializer: Option<Tokens>,
) -> Fragment {
let this = ¶ms.this;
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
split_with_de_lifetime(params);
let delife = params.borrowed.de_lifetime();
+ assert!(!cattrs.has_flatten());
+
// If there are getters (implying private fields), construct the local type
// and use an `Into` conversion to get the remote type. If there are no
// getters then construct the target type directly.
let construct = if params.has_getter {
let local = ¶ms.local;
quote!(#local)
} else {
quote!(#this)
@@ -439,16 +454,18 @@ fn deserialize_tuple_in_place(
cattrs: &attr::Container,
deserializer: Option<Tokens>,
) -> Fragment {
let this = ¶ms.this;
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
split_with_de_lifetime(params);
let delife = params.borrowed.de_lifetime();
+ assert!(!cattrs.has_flatten());
+
let is_enum = variant_ident.is_some();
let expecting = match variant_ident {
Some(variant_ident) => format!("tuple variant {}::{}", params.type_name(), variant_ident),
None => format!("tuple struct {}", params.type_name()),
};
let nfields = fields.len();
@@ -530,34 +547,38 @@ fn deserialize_seq(
type_path: &Tokens,
params: &Parameters,
fields: &[Field],
is_struct: bool,
cattrs: &attr::Container,
) -> Fragment {
let vars = (0..fields.len()).map(field_i as fn(_) -> _);
+ // XXX: do we need an error for flattening here?
+
let deserialized_count = fields
.iter()
.filter(|field| !field.attrs.skip_deserializing())
.count();
let expecting = format!("tuple of {} elements", deserialized_count);
let mut index_in_seq = 0usize;
let let_values = vars.clone().zip(fields).map(|(var, field)| {
if field.attrs.skip_deserializing() {
- let default = Expr(expr_is_missing(&field, cattrs));
+ 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;
- quote!(try!(_serde::de::SeqAccess::next_element::<#field_ty>(&mut __seq)))
+ let span = Span::def_site().located_at(field.original.span());
+ let func = quote_spanned!(span=> _serde::de::SeqAccess::next_element::<#field_ty>);
+ quote!(try!(#func(&mut __seq)))
}
Some(path) => {
let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path);
quote!({
#wrapper
_serde::export::Option::map(
try!(_serde::de::SeqAccess::next_element::<#wrapper_ty>(&mut __seq)),
|__wrap| __wrap.value)
@@ -574,21 +595,21 @@ fn deserialize_seq(
};
index_in_seq += 1;
assign
}
});
let mut result = if is_struct {
let names = fields.iter().map(|f| &f.ident);
- quote! {
+ quote_spanned! {Span::call_site()=>
#type_path { #( #names: #vars ),* }
}
} else {
- quote! {
+ quote_spanned! {Span::call_site()=>
#type_path ( #(#vars),* )
}
};
if params.has_getter {
let this = ¶ms.this;
result = quote! {
_serde::export::Into::<#this>::into(#result)
@@ -627,60 +648,66 @@ fn deserialize_seq_in_place(
// so we need to bump all the indices up by 1.
let index_names = if increment_fields {
(0..fields.len())
} else {
(1..fields.len() + 1)
};
let vars = index_names.map(field_i as fn(_) -> _);
+ // XXX: do we need an error for flattening here?
+
let deserialized_count = fields
.iter()
.filter(|field| !field.attrs.skip_deserializing())
.count();
let expecting = format!("tuple of {} elements", deserialized_count);
let mut index_in_seq = 0usize;
let write_values = vars.clone()
.zip(fields)
.enumerate()
.map(|(field_index, (_, field))| {
// If there's no field name, assume we're a tuple-struct and use a numeric index
let field_name = field
.ident
- .clone()
- .unwrap_or_else(|| Ident::new(field_index.to_string()));
-
+ .map(Member::Named)
+ .unwrap_or_else(|| Member::Unnamed(Index {
+ index: field_index as u32,
+ span: Span::call_site(),
+ }));
+
+ let dot = quote_spanned!(Span::call_site()=> .);
if field.attrs.skip_deserializing() {
- let default = Expr(expr_is_missing(&field, cattrs));
+ let default = Expr(expr_is_missing(field, cattrs));
quote! {
- self.place.#field_name = #default;
+ self.place #dot #field_name = #default;
}
} else {
let return_invalid_length = quote! {
return _serde::export::Err(_serde::de::Error::invalid_length(#index_in_seq, &#expecting));
};
let write = match field.attrs.deserialize_with() {
None => {
quote! {
if let _serde::export::None = try!(_serde::de::SeqAccess::next_element_seed(&mut __seq,
- _serde::private::de::InPlaceSeed(&mut self.place.#field_name)))
+ _serde::private::de::InPlaceSeed(&mut self.place #dot #field_name)))
{
#return_invalid_length
}
}
}
Some(path) => {
let (wrapper, wrapper_ty) =
wrap_deserialize_field_with(params, field.ty, path);
quote!({
#wrapper
match try!(_serde::de::SeqAccess::next_element::<#wrapper_ty>(&mut __seq)) {
_serde::export::Some(__wrap) => {
- self.place.#field_name = __wrap.value;
+ self.place #dot #field_name = __wrap.value;
}
_serde::export::None => {
#return_invalid_length
}
}
})
}
};
@@ -726,17 +753,17 @@ fn deserialize_newtype_struct(type_path:
let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path);
quote!({
#wrapper
try!(<#wrapper_ty as _serde::Deserialize>::deserialize(__e)).value
})
}
};
- let mut result = quote!(#type_path(#value));
+ let mut result = quote_spanned!(Span::call_site()=> #type_path(#value));
if params.has_getter {
let this = ¶ms.this;
result = quote! {
_serde::export::Into::<#this>::into(#result)
};
}
quote! {
@@ -751,38 +778,39 @@ fn deserialize_newtype_struct(type_path:
#[cfg(feature = "deserialize_in_place")]
fn deserialize_newtype_struct_in_place(params: &Parameters, field: &Field) -> Tokens {
// We do not generate deserialize_in_place if every field has a deserialize_with.
assert!(field.attrs.deserialize_with().is_none());
let delife = params.borrowed.de_lifetime();
+ let elem = quote_spanned!(Span::call_site()=> .0);
quote! {
#[inline]
fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::export::Result<Self::Value, __E::Error>
where __E: _serde::Deserializer<#delife>
{
- _serde::Deserialize::deserialize_in_place(__e, &mut self.place.0)
+ _serde::Deserialize::deserialize_in_place(__e, &mut self.place #elem)
}
}
}
enum Untagged {
Yes,
No,
}
fn deserialize_struct(
variant_ident: Option<&syn::Ident>,
params: &Parameters,
fields: &[Field],
cattrs: &attr::Container,
deserializer: Option<Tokens>,
- untagged: Untagged,
+ untagged: &Untagged,
) -> Fragment {
let is_enum = variant_ident.is_some();
let this = ¶ms.this;
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
split_with_de_lifetime(params);
let delife = params.borrowed.de_lifetime();
@@ -802,61 +830,69 @@ fn deserialize_struct(
};
let expecting = match variant_ident {
Some(variant_ident) => format!("struct variant {}::{}", params.type_name(), variant_ident),
None => format!("struct {}", params.type_name()),
};
let visit_seq = Stmts(deserialize_seq(&type_path, params, fields, true, cattrs));
- let (field_visitor, fields_stmt, visit_map) =
- deserialize_struct_visitor(type_path, params, fields, cattrs);
+ let (field_visitor, fields_stmt, visit_map) = if cattrs.has_flatten() {
+ deserialize_struct_as_map_visitor(&type_path, params, fields, cattrs)
+ } else {
+ deserialize_struct_as_struct_visitor(&type_path, params, fields, cattrs)
+ };
let field_visitor = Stmts(field_visitor);
- let fields_stmt = Stmts(fields_stmt);
+ let fields_stmt = fields_stmt.map(Stmts);
let visit_map = Stmts(visit_map);
let visitor_expr = quote! {
__Visitor {
marker: _serde::export::PhantomData::<#this #ty_generics>,
lifetime: _serde::export::PhantomData,
}
};
let dispatch = if let Some(deserializer) = deserializer {
quote! {
_serde::Deserializer::deserialize_any(#deserializer, #visitor_expr)
}
} else if is_enum {
quote! {
_serde::de::VariantAccess::struct_variant(__variant, FIELDS, #visitor_expr)
}
+ } else if cattrs.has_flatten() {
+ quote! {
+ _serde::Deserializer::deserialize_map(__deserializer, #visitor_expr)
+ }
} else {
let type_name = cattrs.name().deserialize_name();
quote! {
_serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, #visitor_expr)
}
};
let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing());
let visitor_var = if all_skipped {
quote!(_)
} else {
quote!(mut __seq)
};
- // untagged struct variants do not get a visit_seq method
- let visit_seq = match untagged {
- Untagged::Yes => None,
- Untagged::No => Some(quote! {
+ // 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 *untagged {
+ Untagged::No if !cattrs.has_flatten() => Some(quote! {
#[inline]
fn visit_seq<__A>(self, #visitor_var: __A) -> _serde::export::Result<Self::Value, __A::Error>
where __A: _serde::de::SeqAccess<#delife>
{
#visit_seq
}
}),
+ _ => None,
};
quote_block! {
#field_visitor
struct __Visitor #de_impl_generics #where_clause {
marker: _serde::export::PhantomData<#this #ty_generics>,
lifetime: _serde::export::PhantomData<&#delife ()>,
@@ -887,34 +923,40 @@ fn deserialize_struct(
#[cfg(feature = "deserialize_in_place")]
fn deserialize_struct_in_place(
variant_ident: Option<&syn::Ident>,
params: &Parameters,
fields: &[Field],
cattrs: &attr::Container,
deserializer: Option<Tokens>,
- untagged: Untagged,
-) -> Fragment {
+) -> Option<Fragment> {
let is_enum = variant_ident.is_some();
+ // for now we do not support in_place deserialization for structs that
+ // are represented as map.
+ if cattrs.has_flatten() {
+ return None;
+ }
+
let this = ¶ms.this;
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
split_with_de_lifetime(params);
let delife = params.borrowed.de_lifetime();
let expecting = match variant_ident {
Some(variant_ident) => format!("struct variant {}::{}", params.type_name(), variant_ident),
None => format!("struct {}", params.type_name()),
};
let visit_seq = Stmts(deserialize_seq_in_place(params, fields, false, cattrs));
- let (field_visitor, fields_stmt, visit_map) =
- deserialize_struct_in_place_visitor(params, fields, cattrs);
+ let (field_visitor, fields_stmt, visit_map) = deserialize_struct_as_struct_in_place_visitor(
+ params, fields, cattrs);
+
let field_visitor = Stmts(field_visitor);
let fields_stmt = Stmts(fields_stmt);
let visit_map = Stmts(visit_map);
let visitor_expr = quote! {
__Visitor {
place: __place,
lifetime: _serde::export::PhantomData,
@@ -937,34 +979,30 @@ fn deserialize_struct_in_place(
let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing());
let visitor_var = if all_skipped {
quote!(_)
} else {
quote!(mut __seq)
};
- // untagged struct variants do not get a visit_seq method
- let visit_seq = match untagged {
- Untagged::Yes => None,
- Untagged::No => Some(quote! {
- #[inline]
- fn visit_seq<__A>(self, #visitor_var: __A) -> _serde::export::Result<Self::Value, __A::Error>
- where __A: _serde::de::SeqAccess<#delife>
- {
- #visit_seq
- }
- }),
+ let visit_seq = quote! {
+ #[inline]
+ fn visit_seq<__A>(self, #visitor_var: __A) -> _serde::export::Result<Self::Value, __A::Error>
+ where __A: _serde::de::SeqAccess<#delife>
+ {
+ #visit_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! {
+ Some(quote_block! {
#field_visitor
struct __Visitor #in_place_impl_generics #where_clause {
place: &#place_life mut #this #ty_generics,
lifetime: _serde::export::PhantomData<&#delife ()>,
}
impl #in_place_impl_generics _serde::de::Visitor<#delife> for __Visitor #in_place_ty_generics #where_clause {
@@ -982,17 +1020,17 @@ fn deserialize_struct_in_place(
{
#visit_map
}
}
#fields_stmt
#dispatch
- }
+ })
}
fn deserialize_enum(
params: &Parameters,
variants: &[Variant],
cattrs: &attr::Container,
) -> Fragment {
match *cattrs.tag() {
@@ -1045,17 +1083,17 @@ fn deserialize_externally_tagged_enum(
let variants_stmt = {
let variant_names = variant_names_idents.iter().map(|&(ref name, _)| name);
quote! {
const VARIANTS: &'static [&'static str] = &[ #(#variant_names),* ];
}
};
let variant_visitor = Stmts(deserialize_generated_identifier(
- variant_names_idents,
+ &variant_names_idents,
cattrs,
true,
));
// Match arms to extract a variant from a string
let variant_arms = variants
.iter()
.enumerate()
@@ -1131,17 +1169,17 @@ fn deserialize_externally_tagged_enum(
#[cfg(feature = "deserialize_in_place")]
fn deserialize_externally_tagged_enum_in_place(
params: &Parameters,
repr: &Repr,
variants: &[Variant],
cattrs: &attr::Container,
) -> Option<Fragment> {
let int_repr = repr.get_stable_rust_enum_layout().map(|int_repr| {
- let int_repr = Ident::new(int_repr);
+ let int_repr = Ident::from(int_repr);
quote!(#[repr(#int_repr)])
});
let unit_variant = variants.iter().position(|variant| is_unit(variant));
let non_unit_variant = variants.iter().enumerate().find(|&(_, variant)| !is_unit(variant));
// We need an int_repr, unit variant, and a non-unit variant to proceed
if int_repr.is_none() || unit_variant.is_none() || non_unit_variant.is_none() {
@@ -1169,17 +1207,17 @@ fn deserialize_externally_tagged_enum_in
let variants_stmt = {
let variant_names = variant_names_idents.iter().map(|&(ref name, _)| name);
quote! {
const VARIANTS: &'static [&'static str] = &[ #(#variant_names),* ];
}
};
- let variant_visitor = Stmts(deserialize_generated_identifier(variant_names_idents, cattrs, true),);
+ let variant_visitor = Stmts(deserialize_generated_identifier(&variant_names_idents, cattrs, true),);
let non_unit_field = field_i(non_unit_index);
let tag_access = match non_unit_variant.style {
Style::Struct => {
quote!(repr.#non_unit_field.tag)
}
Style::Tuple | Style::Newtype => {
quote!(repr.#non_unit_field.0)
@@ -1391,17 +1429,17 @@ fn deserialize_internally_tagged_enum(
let variants_stmt = {
let variant_names = variant_names_idents.iter().map(|&(ref name, _)| name);
quote! {
const VARIANTS: &'static [&'static str] = &[ #(#variant_names),* ];
}
};
let variant_visitor = Stmts(deserialize_generated_identifier(
- variant_names_idents,
+ &variant_names_idents,
cattrs,
true,
));
// Match arms to extract a variant from a string
let variant_arms = variants
.iter()
.enumerate()
@@ -1460,22 +1498,22 @@ fn deserialize_adjacently_tagged_enum(
let variants_stmt = {
let variant_names = variant_names_idents.iter().map(|&(ref name, _)| name);
quote! {
const VARIANTS: &'static [&'static str] = &[ #(#variant_names),* ];
}
};
let variant_visitor = Stmts(deserialize_generated_identifier(
- variant_names_idents,
+ &variant_names_idents,
cattrs,
true,
));
- let ref variant_arms: Vec<_> = variants
+ let variant_arms: &Vec<_> = &variants
.iter()
.enumerate()
.filter(|&(_, variant)| !variant.attrs.skip_deserializing())
.map(|(i, variant)| {
let variant_index = field_i(i);
let block = Match(deserialize_untagged_variant(
params,
@@ -1766,17 +1804,17 @@ fn deserialize_untagged_enum(
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);
+ wrap_deserialize_variant_with(params, variant, path);
return quote_block! {
#wrapper
_serde::export::Result::map(
_serde::de::VariantAccess::newtype_variant::<#wrapper_ty>(__variant), #unwrap_fn)
};
}
let variant_ident = &variant.ident;
@@ -1796,17 +1834,17 @@ fn deserialize_externally_tagged_variant
deserialize_tuple(Some(variant_ident), params, &variant.fields, cattrs, None)
}
Style::Struct => deserialize_struct(
Some(variant_ident),
params,
&variant.fields,
cattrs,
None,
- Untagged::No,
+ &Untagged::No,
),
}
}
#[cfg(feature = "deserialize_in_place")]
fn deserialize_externally_tagged_variant_in_place(
params: &Parameters,
variant: &Variant,
@@ -1867,39 +1905,39 @@ fn deserialize_internally_tagged_variant
try!(_serde::Deserializer::deserialize_any(#deserializer, _serde::private::de::InternallyTaggedUnitVisitor::new(#type_name, #variant_name)));
_serde::export::Ok(#this::#variant_ident)
}
}
Style::Newtype => deserialize_untagged_newtype_variant(
variant_ident,
params,
&variant.fields[0],
- deserializer,
+ &deserializer,
),
Style::Struct => deserialize_struct(
Some(variant_ident),
params,
&variant.fields,
cattrs,
Some(deserializer),
- Untagged::No,
+ &Untagged::No,
),
Style::Tuple => unreachable!("checked in serde_derive_internals"),
}
}
fn deserialize_untagged_variant(
params: &Parameters,
variant: &Variant,
cattrs: &attr::Container,
deserializer: Tokens,
) -> Fragment {
if let Some(path) = variant.attrs.deserialize_with() {
let (wrapper, wrapper_ty, unwrap_fn) =
- wrap_deserialize_variant_with(params, &variant, path);
+ wrap_deserialize_variant_with(params, variant, path);
return quote_block! {
#wrapper
_serde::export::Result::map(
<#wrapper_ty as _serde::Deserialize>::deserialize(#deserializer), #unwrap_fn)
};
}
let variant_ident = &variant.ident;
@@ -1917,32 +1955,32 @@ fn deserialize_untagged_variant(
),
|()| #this::#variant_ident)
}
}
Style::Newtype => deserialize_untagged_newtype_variant(
variant_ident,
params,
&variant.fields[0],
- deserializer,
+ &deserializer,
),
Style::Tuple => deserialize_tuple(
Some(variant_ident),
params,
&variant.fields,
cattrs,
Some(deserializer),
),
Style::Struct => deserialize_struct(
Some(variant_ident),
params,
&variant.fields,
cattrs,
Some(deserializer),
- Untagged::Yes,
+ &Untagged::Yes,
),
}
}
fn deserialize_externally_tagged_newtype_variant(
variant_ident: &syn::Ident,
params: &Parameters,
field: &Field,
@@ -1996,17 +2034,17 @@ fn deserialize_externally_tagged_newtype
}
}
}
fn deserialize_untagged_newtype_variant(
variant_ident: &syn::Ident,
params: &Parameters,
field: &Field,
- deserializer: Tokens,
+ deserializer: &Tokens,
) -> Fragment {
let this = ¶ms.this;
match field.attrs.deserialize_with() {
None => {
let field_ty = &field.ty;
quote_expr! {
_serde::export::Result::map(
<#field_ty as _serde::Deserialize>::deserialize(#deserializer),
@@ -2021,54 +2059,65 @@ fn deserialize_untagged_newtype_variant(
<#wrapper_ty as _serde::Deserialize>::deserialize(#deserializer),
|__wrapper| #this::#variant_ident(__wrapper.value))
}
}
}
}
fn deserialize_generated_identifier(
- fields: Vec<(String, Ident)>,
+ fields: &[(String, Ident)],
cattrs: &attr::Container,
- is_variant: bool,
+ is_variant: bool
) -> Fragment {
let this = quote!(__Field);
let field_idents: &Vec<_> = &fields.iter().map(|&(_, ref ident)| ident).collect();
- let (ignore_variant, fallthrough) = if is_variant || cattrs.deny_unknown_fields() {
+ let (ignore_variant, fallthrough) = if cattrs.has_flatten() {
+ let ignore_variant = quote!(__other(_serde::private::de::Content<'de>),);
+ let fallthrough = quote!(_serde::export::Ok(__Field::__other(__value)));
+ (Some(ignore_variant), Some(fallthrough))
+ } else if is_variant || cattrs.deny_unknown_fields() {
(None, None)
} else {
let ignore_variant = quote!(__ignore,);
let fallthrough = quote!(_serde::export::Ok(__Field::__ignore));
(Some(ignore_variant), Some(fallthrough))
};
let visitor_impl = Stmts(deserialize_identifier(
- this,
- &fields,
+ &this,
+ fields,
is_variant,
fallthrough,
+ cattrs.has_flatten(),
));
+ let lifetime = if cattrs.has_flatten() {
+ Some(quote!(<'de>))
+ } else {
+ None
+ };
+
quote_block! {
#[allow(non_camel_case_types)]
- enum __Field {
+ enum __Field #lifetime {
#(#field_idents,)*
#ignore_variant
}
struct __FieldVisitor;
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
- type Value = __Field;
+ type Value = __Field #lifetime;
#visitor_impl
}
- impl<'de> _serde::Deserialize<'de> for __Field {
+ impl<'de> _serde::Deserialize<'de> for __Field #lifetime {
#[inline]
fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error>
where __D: _serde::Deserializer<'de>
{
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor)
}
}
}
@@ -2110,17 +2159,17 @@ fn deserialize_custom_identifier(
(variants, None)
};
let names_idents: Vec<_> = ordinary
.iter()
.map(|variant| {
(
variant.attrs.name().deserialize_name(),
- variant.ident.clone(),
+ variant.ident,
)
})
.collect();
let names = names_idents.iter().map(|&(ref name, _)| name);
let names_const = if fallthrough.is_some() {
None
@@ -2135,20 +2184,21 @@ fn deserialize_custom_identifier(
};
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.clone(),
+ &this,
&names_idents,
is_variant,
fallthrough,
+ false,
));
quote_block! {
#names_const
struct __FieldVisitor #de_impl_generics #where_clause {
marker: _serde::export::PhantomData<#this #ty_generics>,
lifetime: _serde::export::PhantomData<&#delife ()>,
@@ -2164,61 +2214,165 @@ fn deserialize_custom_identifier(
marker: _serde::export::PhantomData::<#this #ty_generics>,
lifetime: _serde::export::PhantomData,
};
_serde::Deserializer::deserialize_identifier(__deserializer, __visitor)
}
}
fn deserialize_identifier(
- this: Tokens,
+ this: &Tokens,
fields: &[(String, Ident)],
is_variant: bool,
fallthrough: Option<Tokens>,
+ collect_other_fields: bool
) -> Fragment {
let field_strs = fields.iter().map(|&(ref name, _)| name);
- let field_bytes = fields.iter().map(|&(ref name, _)| quote::ByteStr(name));
+ let field_borrowed_strs = fields.iter().map(|&(ref name, _)| name);
+ let field_bytes = fields.iter().map(|&(ref name, _)| Literal::byte_string(name.as_bytes()));
+ let field_borrowed_bytes = fields.iter().map(|&(ref name, _)| Literal::byte_string(name.as_bytes()));
let constructors: &Vec<_> = &fields
.iter()
.map(|&(_, ref ident)| quote!(#this::#ident))
.collect();
let expecting = if is_variant {
"variant identifier"
} else {
"field identifier"
};
let index_expecting = if is_variant { "variant" } else { "field" };
let variant_indices = 0u64..;
let fallthrough_msg = format!("{} index 0 <= i < {}", index_expecting, fields.len());
- let visit_index = quote! {
- fn visit_u64<__E>(self, __value: u64) -> _serde::export::Result<Self::Value, __E>
- where __E: _serde::de::Error
- {
- match __value {
- #(
- #variant_indices => _serde::export::Ok(#constructors),
- )*
- _ => _serde::export::Err(_serde::de::Error::invalid_value(
- _serde::de::Unexpected::Unsigned(__value),
- &#fallthrough_msg))
+ let visit_other = if collect_other_fields {
+ Some(quote! {
+ fn visit_bool<__E>(self, __value: bool) -> Result<Self::Value, __E>
+ where __E: _serde::de::Error
+ {
+ Ok(__Field::__other(_serde::private::de::Content::Bool(__value)))
+ }
+
+ fn visit_i8<__E>(self, __value: i8) -> Result<Self::Value, __E>
+ where __E: _serde::de::Error
+ {
+ Ok(__Field::__other(_serde::private::de::Content::I8(__value)))
+ }
+
+ fn visit_i16<__E>(self, __value: i16) -> Result<Self::Value, __E>
+ where __E: _serde::de::Error
+ {
+ Ok(__Field::__other(_serde::private::de::Content::I16(__value)))
+ }
+
+ fn visit_i32<__E>(self, __value: i32) -> Result<Self::Value, __E>
+ where __E: _serde::de::Error
+ {
+ Ok(__Field::__other(_serde::private::de::Content::I32(__value)))
+ }
+
+ fn visit_i64<__E>(self, __value: i64) -> Result<Self::Value, __E>
+ where __E: _serde::de::Error
+ {
+ Ok(__Field::__other(_serde::private::de::Content::I64(__value)))
+ }
+
+ fn visit_u8<__E>(self, __value: u8) -> Result<Self::Value, __E>
+ where __E: _serde::de::Error
+ {
+ Ok(__Field::__other(_serde::private::de::Content::U8(__value)))
+ }
+
+ fn visit_u16<__E>(self, __value: u16) -> Result<Self::Value, __E>
+ where __E: _serde::de::Error
+ {
+ Ok(__Field::__other(_serde::private::de::Content::U16(__value)))
+ }
+
+ fn visit_u32<__E>(self, __value: u32) -> Result<Self::Value, __E>
+ where __E: _serde::de::Error
+ {
+ Ok(__Field::__other(_serde::private::de::Content::U32(__value)))
}
- }
+
+ fn visit_u64<__E>(self, __value: u64) -> Result<Self::Value, __E>
+ where __E: _serde::de::Error
+ {
+ Ok(__Field::__other(_serde::private::de::Content::U64(__value)))
+ }
+
+ fn visit_f32<__E>(self, __value: f32) -> Result<Self::Value, __E>
+ where __E: _serde::de::Error
+ {
+ Ok(__Field::__other(_serde::private::de::Content::F32(__value)))
+ }
+
+ fn visit_f64<__E>(self, __value: f64) -> Result<Self::Value, __E>
+ where __E: _serde::de::Error
+ {
+ Ok(__Field::__other(_serde::private::de::Content::F64(__value)))
+ }
+
+ fn visit_char<__E>(self, __value: char) -> Result<Self::Value, __E>
+ where __E: _serde::de::Error
+ {
+ Ok(__Field::__other(_serde::private::de::Content::Char(__value)))
+ }
+
+ fn visit_unit<__E>(self) -> Result<Self::Value, __E>
+ where __E: _serde::de::Error
+ {
+ Ok(__Field::__other(_serde::private::de::Content::Unit))
+ }
+ })
+ } else {
+ Some(quote! {
+ fn visit_u64<__E>(self, __value: u64) -> _serde::export::Result<Self::Value, __E>
+ where __E: _serde::de::Error
+ {
+ match __value {
+ #(
+ #variant_indices => _serde::export::Ok(#constructors),
+ )*
+ _ => _serde::export::Err(_serde::de::Error::invalid_value(
+ _serde::de::Unexpected::Unsigned(__value),
+ &#fallthrough_msg))
+ }
+ }
+ })
};
- let bytes_to_str = if fallthrough.is_some() {
+ let bytes_to_str = if fallthrough.is_some() || collect_other_fields {
None
} else {
- let conversion = quote! {
+ Some(quote! {
let __value = &_serde::export::from_utf8_lossy(__value);
- };
- Some(conversion)
+ })
+ };
+
+ let (value_as_str_content, value_as_borrowed_str_content,
+ value_as_bytes_content, value_as_borrowed_bytes_content) = if !collect_other_fields {
+ (None, None, None, None)
+ } else {
+ (
+ Some(quote! {
+ let __value = _serde::private::de::Content::String(__value.to_string());
+ }),
+ 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);
+ })
+ )
};
let fallthrough_arm = if let Some(fallthrough) = fallthrough {
fallthrough
} else if is_variant {
quote! {
_serde::export::Err(_serde::de::Error::unknown_variant(__value, VARIANTS))
}
@@ -2228,108 +2382,177 @@ fn deserialize_identifier(
}
};
quote_block! {
fn expecting(&self, formatter: &mut _serde::export::Formatter) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(formatter, #expecting)
}
- #visit_index
+ #visit_other
fn visit_str<__E>(self, __value: &str) -> _serde::export::Result<Self::Value, __E>
where __E: _serde::de::Error
{
match __value {
#(
#field_strs => _serde::export::Ok(#constructors),
)*
- _ => #fallthrough_arm
+ _ => {
+ #value_as_str_content
+ #fallthrough_arm
+ }
+ }
+ }
+
+ fn visit_borrowed_str<__E>(self, __value: &'de str) -> _serde::export::Result<Self::Value, __E>
+ where __E: _serde::de::Error
+ {
+ match __value {
+ #(
+ #field_borrowed_strs => _serde::export::Ok(#constructors),
+ )*
+ _ => {
+ #value_as_borrowed_str_content
+ #fallthrough_arm
+ }
+ }
+ }
+
+ fn visit_borrowed_bytes<__E>(self, __value: &'de [u8]) -> _serde::export::Result<Self::Value, __E>
+ where __E: _serde::de::Error
+ {
+ match __value {
+ #(
+ #field_borrowed_bytes => _serde::export::Ok(#constructors),
+ )*
+ _ => {
+ #bytes_to_str
+ #value_as_borrowed_bytes_content
+ #fallthrough_arm
+ }
}
}
fn visit_bytes<__E>(self, __value: &[u8]) -> _serde::export::Result<Self::Value, __E>
where __E: _serde::de::Error
{
match __value {
#(
#field_bytes => _serde::export::Ok(#constructors),
)*
_ => {
#bytes_to_str
+ #value_as_bytes_content
#fallthrough_arm
}
}
}
}
}
-fn deserialize_struct_visitor(
- struct_path: Tokens,
+fn deserialize_struct_as_struct_visitor(
+ struct_path: &Tokens,
params: &Parameters,
fields: &[Field],
cattrs: &attr::Container,
-) -> (Fragment, Fragment, Fragment) {
+) -> (Fragment, Option<Fragment>, Fragment) {
+ assert!(!cattrs.has_flatten());
+
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)))
.collect();
let fields_stmt = {
let field_names = field_names_idents.iter().map(|&(ref name, _)| name);
quote_block! {
const FIELDS: &'static [&'static str] = &[ #(#field_names),* ];
}
};
- let field_visitor = deserialize_generated_identifier(field_names_idents, cattrs, false);
+ let field_visitor = deserialize_generated_identifier(&field_names_idents, cattrs, false);
let visit_map = deserialize_map(struct_path, params, fields, cattrs);
- (field_visitor, fields_stmt, visit_map)
+ (field_visitor, Some(fields_stmt), visit_map)
+}
+
+fn deserialize_struct_as_map_visitor(
+ struct_path: &Tokens,
+ params: &Parameters,
+ fields: &[Field],
+ cattrs: &attr::Container,
+) -> (Fragment, Option<Fragment>, Fragment) {
+ let field_names_idents: Vec<_> = fields
+ .iter()
+ .enumerate()
+ .filter(|&(_, field)| !field.attrs.skip_deserializing() && !field.attrs.flatten())
+ .map(|(i, field)| (field.attrs.name().deserialize_name(), field_i(i)))
+ .collect();
+
+ let field_visitor = deserialize_generated_identifier(&field_names_idents, cattrs, false);
+
+ let visit_map = deserialize_map(struct_path, params, fields, cattrs);
+
+ (field_visitor, None, visit_map)
}
fn deserialize_map(
- struct_path: Tokens,
+ struct_path: &Tokens,
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())
+ .filter(|&&(field, _)| !field.attrs.skip_deserializing() && !field.attrs.flatten())
.map(|&(field, ref name)| {
let field_ty = &field.ty;
quote! {
let mut #name: _serde::export::Option<#field_ty> = _serde::export::None;
}
});
+ // Collect contents for flatten fields into a buffer
+ let let_collect = if cattrs.has_flatten() {
+ Some(quote! {
+ let mut __collect = Vec::<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())
+ .filter(|&&(field, _)| !field.attrs.skip_deserializing() && !field.attrs.flatten())
.map(|&(field, ref name)| {
let deser_name = field.attrs.name().deserialize_name();
let visit = match field.attrs.deserialize_with() {
None => {
let field_ty = &field.ty;
+ let span = Span::def_site().located_at(field.original.span());
+ let func = quote_spanned!(span=> _serde::de::MapAccess::next_value::<#field_ty>);
quote! {
- try!(_serde::de::MapAccess::next_value::<#field_ty>(&mut __map))
+ try!(#func(&mut __map))
}
}
Some(path) => {
let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path);
quote!({
#wrapper
try!(_serde::de::MapAccess::next_value::<#wrapper_ty>(&mut __map)).value
})
@@ -2341,17 +2564,25 @@ fn deserialize_map(
return _serde::export::Err(<__A::Error as _serde::de::Error>::duplicate_field(#deser_name));
}
#name = _serde::export::Some(#visit);
}
}
});
// Visit ignored values to consume them
- let ignored_arm = if cattrs.deny_unknown_fields() {
+ let ignored_arm = if cattrs.has_flatten() {
+ Some(quote! {
+ __Field::__other(__name) => {
+ __collect.push(Some((
+ __name,
+ try!(_serde::de::MapAccess::next_value(&mut __map)))));
+ }
+ })
+ } else if cattrs.deny_unknown_fields() {
None
} else {
Some(quote! {
_ => { let _ = try!(_serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)); }
})
};
let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing());
@@ -2371,35 +2602,64 @@ fn deserialize_map(
#ignored_arm
}
}
}
};
let extract_values = fields_names
.iter()
- .filter(|&&(field, _)| !field.attrs.skip_deserializing())
+ .filter(|&&(field, _)| !field.attrs.skip_deserializing() && !field.attrs.flatten())
.map(|&(field, ref name)| {
- let missing_expr = Match(expr_is_missing(&field, cattrs));
+ let missing_expr = Match(expr_is_missing(field, cattrs));
quote! {
let #name = match #name {
_serde::export::Some(#name) => #name,
_serde::export::None => #missing_expr
};
}
});
+ let extract_collected = fields_names
+ .iter()
+ .filter(|&&(field, _)| field.attrs.flatten())
+ .map(|&(field, ref name)| {
+ let field_ty = field.ty;
+ quote! {
+ let #name: #field_ty = try!(_serde::de::Deserialize::deserialize(
+ _serde::private::de::FlatMapDeserializer(
+ &mut __collect,
+ _serde::export::PhantomData)));
+ }
+ });
+
+ let collected_deny_unknown_fields = if cattrs.has_flatten() && cattrs.deny_unknown_fields() {
+ Some(quote! {
+ if let Some(Some((__key, _))) = __collect.into_iter().filter(|x| x.is_some()).next() {
+ if let Some(__key) = __key.as_str() {
+ return _serde::export::Err(
+ _serde::de::Error::custom(format_args!("unknown field `{}`", &__key)));
+ } else {
+ return _serde::export::Err(
+ _serde::de::Error::custom(format_args!("unexpected map key")));
+ }
+ }
+ })
+ } else {
+ None
+ };
+
let result = fields_names.iter().map(|&(field, ref name)| {
- let ident = field.ident.clone().expect("struct contains unnamed fields");
+ let ident = field.ident.expect("struct contains unnamed fields");
if field.attrs.skip_deserializing() {
- let value = Expr(expr_is_missing(&field, cattrs));
- quote!(#ident: #value)
+ let value = Expr(expr_is_missing(field, cattrs));
+ quote_spanned!(Span::call_site()=> #ident: #value)
} else {
- quote!(#ident: #name)
+ quote_spanned!(Span::call_site()=> #ident: #name)
}
});
let let_default = match *cattrs.default() {
attr::Default::Default => Some(quote!(
let __default: Self::Value = _serde::export::Default::default();
)),
attr::Default::Path(ref path) => Some(quote!(
@@ -2407,70 +2667,80 @@ fn deserialize_map(
)),
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),* });
+ let mut result = quote_spanned!(Span::call_site()=> #struct_path { #(#result),* });
if params.has_getter {
let this = ¶ms.this;
result = quote! {
_serde::export::Into::<#this>::into(#result)
};
}
quote_block! {
#(#let_values)*
+ #let_collect
+
#match_keys
#let_default
#(#extract_values)*
+ #(#extract_collected)*
+
+ #collected_deny_unknown_fields
+
_serde::export::Ok(#result)
}
}
#[cfg(feature = "deserialize_in_place")]
-fn deserialize_struct_in_place_visitor(
+fn deserialize_struct_as_struct_in_place_visitor(
params: &Parameters,
fields: &[Field],
cattrs: &attr::Container,
) -> (Fragment, Fragment, Fragment) {
+ assert!(!cattrs.has_flatten());
+
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)))
.collect();
let fields_stmt = {
let field_names = field_names_idents.iter().map(|&(ref name, _)| name);
quote_block! {
const FIELDS: &'static [&'static str] = &[ #(#field_names),* ];
}
};
- let field_visitor = deserialize_generated_identifier(field_names_idents, cattrs, false);
+ let field_visitor = deserialize_generated_identifier(&field_names_idents, cattrs, false);
let visit_map = deserialize_map_in_place(params, fields, cattrs);
(field_visitor, fields_stmt, visit_map)
}
#[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.
@@ -2545,21 +2815,21 @@ fn deserialize_map_in_place(
}
}
};
let check_flags = fields_names
.iter()
.filter(|&&(field, _)| !field.attrs.skip_deserializing())
.map(|&(field, ref name)| {
- let missing_expr = expr_is_missing(&field, cattrs);
+ 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. Maybe this could be handled
// more elegantly.
- if missing_expr.as_ref().as_str().starts_with("return ") {
+ if missing_expr.as_ref().into_tokens().to_string().starts_with("return ") {
let missing_expr = Stmts(missing_expr);
quote! {
if !#name {
#missing_expr;
}
}
} else {
let field_name = &field.ident;
@@ -2598,25 +2868,25 @@ fn deserialize_map_in_place(
#(#check_flags)*
_serde::export::Ok(())
}
}
fn field_i(i: usize) -> Ident {
- Ident::new(format!("__field{}", i))
+ Ident::new(&format!("__field{}", i), Span::def_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: Tokens,
- deserialize_with: &syn::Path,
+ value_ty: &Tokens,
+ deserialize_with: &syn::ExprPath,
) -> (Tokens, Tokens) {
let this = ¶ms.this;
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! {
struct __DeserializeWith #de_impl_generics #where_clause {
@@ -2640,35 +2910,38 @@ fn wrap_deserialize_with(
let wrapper_ty = quote!(__DeserializeWith #de_ty_generics);
(wrapper, wrapper_ty)
}
fn wrap_deserialize_field_with(
params: &Parameters,
- field_ty: &syn::Ty,
- deserialize_with: &syn::Path,
+ field_ty: &syn::Type,
+ deserialize_with: &syn::ExprPath,
) -> (Tokens, Tokens) {
- wrap_deserialize_with(params, quote!(#field_ty), deserialize_with)
+ wrap_deserialize_with(params, "e!(#field_ty), deserialize_with)
}
fn wrap_deserialize_variant_with(
params: &Parameters,
variant: &Variant,
- deserialize_with: &syn::Path,
+ deserialize_with: &syn::ExprPath,
) -> (Tokens, Tokens, Tokens) {
let this = ¶ms.this;
let variant_ident = &variant.ident;
let field_tys = variant.fields.iter().map(|field| field.ty);
let (wrapper, wrapper_ty) =
- wrap_deserialize_with(params, quote!((#(#field_tys),*)), deserialize_with);
-
- let field_access = (0..variant.fields.len()).map(|n| Ident::new(format!("{}", n)));
+ wrap_deserialize_with(params, "e!((#(#field_tys),*)), deserialize_with);
+
+ let field_access = (0..variant.fields.len()).map(|n| Member::Unnamed(Index {
+ index: n as u32,
+ span: Span::call_site(),
+ }));
let unwrap_fn = match variant.style {
Style::Struct => {
let field_idents = variant
.fields
.iter()
.map(|field| field.ident.as_ref().unwrap());
quote!({
|__wrap| {
@@ -2711,18 +2984,20 @@ fn expr_is_missing(field: &Field, cattrs
return quote_expr!(__default.#ident);
}
attr::Default::None => { /* below */ }
}
let name = field.attrs.name().deserialize_name();
match field.attrs.deserialize_with() {
None => {
+ let span = Span::def_site().located_at(field.original.span());
+ let func = quote_spanned!(span=> _serde::private::de::missing_field);
quote_expr! {
- try!(_serde::private::de::missing_field(#name))
+ try!(#func(#name))
}
}
Some(_) => {
quote_expr! {
return _serde::export::Err(<__A::Error as _serde::de::Error>::missing_field(#name))
}
}
}
@@ -2731,105 +3006,144 @@ fn expr_is_missing(field: &Field, cattrs
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 Tokens) {
let mut generics = self.0.generics.clone();
if let Some(de_lifetime) = self.0.borrowed.de_lifetime_def() {
- generics.lifetimes.insert(0, de_lifetime);
+ 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 Tokens) {
let place_lifetime = place_lifetime();
let mut generics = self.0.generics.clone();
// Add lifetime for `&'place mut Self, and `'a: 'place`
- for lifetime in &mut generics.lifetimes {
- lifetime.bounds.push(place_lifetime.lifetime.clone());
+ for param in &mut generics.params {
+ match *param {
+ syn::GenericParam::Lifetime(ref mut param) => {
+ param.bounds.push(place_lifetime.lifetime);
+ }
+ syn::GenericParam::Type(ref mut param) => {
+ param.bounds
+ .push(syn::TypeParamBound::Lifetime(place_lifetime.lifetime));
+ }
+ syn::GenericParam::Const(_) => {}
+ }
}
- for generic in &mut generics.ty_params {
- generic
- .bounds
- .push(syn::TyParamBound::Region(place_lifetime.lifetime.clone()));
- }
- generics.lifetimes.insert(0, place_lifetime);
+ generics.params = Some(syn::GenericParam::Lifetime(place_lifetime))
+ .into_iter()
+ .chain(generics.params)
+ .collect();
if let Some(de_lifetime) = self.0.borrowed.de_lifetime_def() {
- generics.lifetimes.insert(0, de_lifetime);
+ 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 DeTyGenerics<'a>(&'a Parameters);
+struct DeTypeGenerics<'a>(&'a Parameters);
#[cfg(feature = "deserialize_in_place")]
-struct InPlaceTyGenerics<'a>(&'a Parameters);
-
-impl<'a> ToTokens for DeTyGenerics<'a> {
+struct InPlaceTypeGenerics<'a>(&'a Parameters);
+
+impl<'a> ToTokens for DeTypeGenerics<'a> {
fn to_tokens(&self, tokens: &mut Tokens) {
let mut generics = self.0.generics.clone();
if self.0.borrowed.de_lifetime_def().is_some() {
- generics.lifetimes.insert(0, syn::LifetimeDef::new("'de"));
+ let def = syn::LifetimeDef {
+ attrs: Vec::new(),
+ lifetime: syn::Lifetime::new(Term::intern("'de"), Span::def_site()),
+ colon_token: None,
+ bounds: Punctuated::new(),
+ };
+ 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);
}
}
#[cfg(feature = "deserialize_in_place")]
-impl<'a> ToTokens for InPlaceTyGenerics<'a> {
+impl<'a> ToTokens for InPlaceTypeGenerics<'a> {
fn to_tokens(&self, tokens: &mut Tokens) {
let mut generics = self.0.generics.clone();
- generics.lifetimes.insert(0, place_lifetime());
+ generics.params = Some(syn::GenericParam::Lifetime(place_lifetime()))
+ .into_iter()
+ .chain(generics.params)
+ .collect();
if self.0.borrowed.de_lifetime_def().is_some() {
- generics.lifetimes.insert(0, syn::LifetimeDef::new("'de"));
+ let def = syn::LifetimeDef {
+ attrs: Vec::new(),
+ lifetime: syn::Lifetime::new(Term::intern("'de"), Span::def_site()),
+ colon_token: None,
+ bounds: Punctuated::new(),
+ };
+ 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);
}
}
#[cfg(feature = "deserialize_in_place")]
-impl<'a> DeTyGenerics<'a> {
- fn in_place(self) -> InPlaceTyGenerics<'a> {
- InPlaceTyGenerics(self.0)
+impl<'a> DeTypeGenerics<'a> {
+ fn in_place(self) -> InPlaceTypeGenerics<'a> {
+ InPlaceTypeGenerics(self.0)
}
}
#[cfg(feature = "deserialize_in_place")]
fn place_lifetime() -> syn::LifetimeDef {
- syn::LifetimeDef::new("'place")
+ syn::LifetimeDef {
+ attrs: Vec::new(),
+ lifetime: syn::Lifetime::new(Term::intern("'place"), Span::def_site()),
+ colon_token: None,
+ bounds: Punctuated::new(),
+ }
}
fn split_with_de_lifetime(
params: &Parameters,
) -> (
DeImplGenerics,
- DeTyGenerics,
- syn::TyGenerics,
- &syn::WhereClause,
+ DeTypeGenerics,
+ syn::TypeGenerics,
+ Option<&syn::WhereClause>,
) {
- let de_impl_generics = DeImplGenerics(¶ms);
- let de_ty_generics = DeTyGenerics(¶ms);
+ 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)
}
fn is_unit(variant: &Variant) -> bool {
match variant.style {
Style::Unit => true,
Style::Struct | Style::Tuple | Style::Newtype => false,
--- a/third_party/rust/serde_derive/src/fragment.rs
+++ b/third_party/rust/serde_derive/src/fragment.rs
@@ -2,16 +2,17 @@
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use quote::{ToTokens, Tokens};
+use syn::token;
pub enum Fragment {
/// Tokens that can be used as an expression.
Expr(Tokens),
/// Tokens that can be used inside a block. The surrounding curly braces are
/// not part of these tokens.
Block(Tokens),
}
@@ -31,19 +32,17 @@ macro_rules! quote_block {
/// 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 Tokens) {
match self.0 {
Fragment::Expr(ref expr) => expr.to_tokens(out),
Fragment::Block(ref block) => {
- out.append("{");
- block.to_tokens(out);
- out.append("}");
+ 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 {
@@ -58,22 +57,20 @@ impl ToTokens for Stmts {
/// 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 Tokens) {
match self.0 {
Fragment::Expr(ref expr) => {
expr.to_tokens(out);
- out.append(",");
+ <Token![,]>::default().to_tokens(out);
}
Fragment::Block(ref block) => {
- out.append("{");
- block.to_tokens(out);
- out.append("}");
+ token::Brace::default().surround(out, |out| block.to_tokens(out));
}
}
}
}
impl AsRef<Tokens> for Fragment {
fn as_ref(&self) -> &Tokens {
match *self {
--- a/third_party/rust/serde_derive/src/lib.rs
+++ b/third_party/rust/serde_derive/src/lib.rs
@@ -17,48 +17,52 @@
//! #
//! # 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.27")]
-#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
-#![cfg_attr(feature = "cargo-clippy", allow(used_underscore_binding))]
+#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.35")]
+#![cfg_attr(feature = "cargo-clippy", allow(enum_variant_names, redundant_field_names,
+ too_many_arguments, used_underscore_binding))]
// The `quote!` macro requires deep recursion.
-#![recursion_limit = "192"]
+#![recursion_limit = "512"]
#[macro_use]
extern crate quote;
+#[macro_use]
extern crate syn;
extern crate serde_derive_internals as internals;
extern crate proc_macro;
+extern crate proc_macro2;
+
use proc_macro::TokenStream;
+use syn::DeriveInput;
#[macro_use]
mod bound;
#[macro_use]
mod fragment;
mod ser;
mod de;
#[proc_macro_derive(Serialize, attributes(serde))]
pub fn derive_serialize(input: TokenStream) -> TokenStream {
- let input = syn::parse_derive_input(&input.to_string()).unwrap();
+ let input: DeriveInput = syn::parse(input).unwrap();
match ser::expand_derive_serialize(&input) {
- Ok(expanded) => expanded.parse().unwrap(),
+ Ok(expanded) => expanded.into(),
Err(msg) => panic!(msg),
}
}
#[proc_macro_derive(Deserialize, attributes(serde))]
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
- let input = syn::parse_derive_input(&input.to_string()).unwrap();
+ let input: DeriveInput = syn::parse(input).unwrap();
match de::expand_derive_deserialize(&input) {
- Ok(expanded) => expanded.parse().unwrap(),
+ Ok(expanded) => expanded.into(),
Err(msg) => panic!(msg),
}
}
--- a/third_party/rust/serde_derive/src/ser.rs
+++ b/third_party/rust/serde_derive/src/ser.rs
@@ -1,43 +1,46 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use syn::{self, Ident};
+use syn::{self, Ident, Index, Member};
+use syn::spanned::Spanned;
use quote::Tokens;
+use proc_macro2::Span;
use bound;
use fragment::{Fragment, Match, Stmts};
-use internals::ast::{Body, Container, Field, Style, Variant};
+use internals::ast::{Data, Container, Field, Style, Variant};
use internals::{attr, Ctxt};
use std::u32;
pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, String> {
let ctxt = Ctxt::new();
let cont = Container::from_ast(&ctxt, input);
precondition(&ctxt, &cont);
try!(ctxt.check());
let ident = &cont.ident;
let params = Parameters::new(&cont);
let (impl_generics, ty_generics, where_clause) = params.generics.split_for_impl();
- let dummy_const = Ident::new(format!("_IMPL_SERIALIZE_FOR_{}", ident));
+ let dummy_const = Ident::new(&format!("_IMPL_SERIALIZE_FOR_{}", ident), Span::def_site());
let body = Stmts(serialize_body(&cont, ¶ms));
let impl_block = if let Some(remote) = cont.attrs.remote() {
let vis = &input.vis;
+ let fun = quote_spanned!(Span::call_site()=> serialize);
quote! {
impl #impl_generics #ident #ty_generics #where_clause {
- #vis fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
+ #vis fn #fun<__S>(__self: &#remote #ty_generics, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where __S: _serde::Serializer
{
#body
}
}
}
} else {
quote! {
@@ -90,40 +93,40 @@ struct Parameters {
/// Type has a `serde(remote = "...")` attribute.
is_remote: 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")
+ Ident::new("__self", Span::def_site())
} else {
- Ident::new("self")
+ Ident::new("self", Span::def_site())
};
let this = match cont.attrs.remote() {
Some(remote) => remote.clone(),
- None => cont.ident.clone().into(),
+ None => cont.ident.into(),
};
let generics = build_generics(cont);
Parameters {
self_var: self_var,
this: this,
generics: generics,
is_remote: is_remote,
}
}
/// Type name to use in error messages and `&'static str` arguments to
/// various Serializer methods.
fn type_name(&self) -> &str {
- self.this.segments.last().unwrap().ident.as_ref()
+ self.this.segments.last().unwrap().value().ident.as_ref()
}
}
// 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);
@@ -131,62 +134,62 @@ fn build_generics(cont: &Container) -> s
bound::with_where_predicates_from_fields(cont, &generics, attr::Field::ser_bound);
match cont.attrs.ser_bound() {
Some(predicates) => bound::with_where_predicates(&generics, predicates),
None => bound::with_bound(
cont,
&generics,
needs_serialize_bound,
- &path!(_serde::Serialize),
+ &parse_quote!(_serde::Serialize),
),
}
}
// Fields with a `skip_serializing` or `serialize_with` attribute, or which
// belong to a variant with a `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.serialize_with().is_none())
}
fn serialize_body(cont: &Container, params: &Parameters) -> Fragment {
- if let Some(into_type) = cont.attrs.into_type() {
- serialize_into(params, into_type)
+ if let Some(type_into) = cont.attrs.type_into() {
+ serialize_into(params, type_into)
} else {
- match cont.body {
- Body::Enum(_, ref variants) => serialize_enum(params, variants, &cont.attrs),
- Body::Struct(Style::Struct, ref fields) => {
+ match cont.data {
+ Data::Enum(_, ref variants) => serialize_enum(params, variants, &cont.attrs),
+ Data::Struct(Style::Struct, ref fields) => {
if fields.iter().any(|field| field.ident.is_none()) {
panic!("struct has unnamed fields");
}
serialize_struct(params, fields, &cont.attrs)
}
- Body::Struct(Style::Tuple, ref fields) => {
+ Data::Struct(Style::Tuple, ref fields) => {
if fields.iter().any(|field| field.ident.is_some()) {
panic!("tuple struct has named fields");
}
serialize_tuple_struct(params, fields, &cont.attrs)
}
- Body::Struct(Style::Newtype, ref fields) => {
+ Data::Struct(Style::Newtype, ref fields) => {
serialize_newtype_struct(params, &fields[0], &cont.attrs)
}
- Body::Struct(Style::Unit, _) => serialize_unit_struct(&cont.attrs),
+ Data::Struct(Style::Unit, _) => serialize_unit_struct(&cont.attrs),
}
}
}
-fn serialize_into(params: &Parameters, into_type: &syn::Ty) -> Fragment {
+fn serialize_into(params: &Parameters, type_into: &syn::Type) -> Fragment {
let self_var = ¶ms.self_var;
quote_block! {
_serde::Serialize::serialize(
- &_serde::export::Into::<#into_type>::into(_serde::export::Clone::clone(#self_var)),
+ &_serde::export::Into::<#type_into>::into(_serde::export::Clone::clone(#self_var)),
__serializer)
}
}
fn serialize_unit_struct(cattrs: &attr::Container) -> Fragment {
let type_name = cattrs.name().serialize_name();
quote_expr! {
@@ -196,89 +199,139 @@ fn serialize_unit_struct(cattrs: &attr::
fn serialize_newtype_struct(
params: &Parameters,
field: &Field,
cattrs: &attr::Container,
) -> Fragment {
let type_name = cattrs.name().serialize_name();
- let mut field_expr = get_field(params, field, 0);
+ 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);
+ field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
}
+ let span = Span::def_site().located_at(field.original.span());
+ let func = quote_spanned!(span=> _serde::Serializer::serialize_newtype_struct);
quote_expr! {
- _serde::Serializer::serialize_newtype_struct(__serializer, #type_name, #field_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,
- quote!(_serde::ser::SerializeTupleStruct::serialize_field),
+ &TupleTrait::SerializeTupleStruct,
);
let type_name = cattrs.name().serialize_name();
let len = serialize_stmts.len();
let let_mut = mut_if(len > 0);
quote_block! {
let #let_mut __serde_state = try!(_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 <= u32::MAX as u64);
+ assert!(fields.len() as u64 <= u64::from(u32::MAX));
+ if cattrs.has_flatten() {
+ serialize_struct_as_map(params, fields, cattrs)
+ } else {
+ serialize_struct_as_struct(params, fields, cattrs)
+ }
+}
+
+fn serialize_struct_as_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Container) -> Fragment {
let serialize_fields = serialize_struct_visitor(
fields,
params,
false,
- quote!(_serde::ser::SerializeStruct::serialize_field),
- quote!(_serde::ser::SerializeStruct::skip_field),
+ &StructTrait::SerializeStruct,
);
let type_name = cattrs.name().serialize_name();
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| match field.attrs.skip_serializing_if() {
None => quote!(1),
Some(path) => {
- let ident = field.ident.clone().expect("struct has unnamed fields");
- let field_expr = get_field(params, field, ident);
+ let ident = field.ident.expect("struct has unnamed fields");
+ let field_expr = get_member(params, field, &Member::Named(ident));
quote!(if #path(#field_expr) { 0 } else { 1 })
}
})
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct(__serializer, #type_name, #len));
#(#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 mut serialized_fields = fields
+ .iter()
+ .filter(|&field| !field.attrs.skip_serializing())
+ .peekable();
+
+ let let_mut = mut_if(serialized_fields.peek().is_some());
+
+ let len = if cattrs.has_flatten() {
+ quote!(_serde::export::None)
+ } else {
+ let len = serialized_fields
+ .map(|field| match field.attrs.skip_serializing_if() {
+ None => quote!(1),
+ Some(path) => {
+ let ident = field.ident.expect("struct has unnamed fields");
+ let field_expr = get_member(params, field, &Member::Named(ident));
+ quote!(if #path(#field_expr) { 0 } else { 1 })
+ }
+ })
+ .fold(quote!(0), |sum, expr| quote!(#sum + #expr));
+ quote!(_serde::export::Some(#len))
+ };
+
+ quote_block! {
+ let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(__serializer, #len));
+ #(#serialize_fields)*
+ _serde::ser::SerializeMap::end(__serde_state)
+ }
+}
+
fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Container) -> Fragment {
- assert!(variants.len() as u64 <= u32::MAX as u64);
+ assert!(variants.len() as u64 <= u64::from(u32::MAX));
let self_var = ¶ms.self_var;
let arms: Vec<_> = variants
.iter()
.enumerate()
.map(|(variant_index, variant)| {
serialize_variant(params, variant, variant_index as u32, cattrs)
@@ -294,17 +347,17 @@ fn serialize_enum(params: &Parameters, v
fn serialize_variant(
params: &Parameters,
variant: &Variant,
variant_index: u32,
cattrs: &attr::Container,
) -> Tokens {
let this = ¶ms.this;
- let variant_ident = variant.ident.clone();
+ 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! {
@@ -328,26 +381,26 @@ fn serialize_variant(
}
Style::Newtype => {
quote! {
#this::#variant_ident(ref __field0)
}
}
Style::Tuple => {
let field_names =
- (0..variant.fields.len()).map(|i| Ident::new(format!("__field{}", i)));
+ (0..variant.fields.len()).map(|i| Ident::new(&format!("__field{}", i), Span::def_site()));
quote! {
#this::#variant_ident(#(ref #field_names),*)
}
}
Style::Struct => {
let fields = variant
.fields
.iter()
- .map(|f| f.ident.clone().expect("struct variant has unnamed fields"));
+ .map(|f| f.ident.expect("struct variant has unnamed fields"));
quote! {
#this::#variant_ident { #(ref #fields),* }
}
}
};
let body = Match(match *cattrs.tag() {
attr::EnumTag::External => {
@@ -374,17 +427,17 @@ fn serialize_externally_tagged_variant(
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);
+ 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,
)
@@ -401,17 +454,17 @@ fn serialize_externally_tagged_variant(
#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);
+ field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
}
quote_expr! {
_serde::Serializer::serialize_newtype_variant(
__serializer,
#type_name,
#variant_index,
#variant_name,
@@ -448,17 +501,17 @@ fn serialize_internally_tagged_variant(
) -> 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.as_ref();
if let Some(path) = variant.attrs.serialize_with() {
- let ser = wrap_serialize_variant_with(params, path, &variant);
+ 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,
@@ -475,17 +528,17 @@ fn serialize_internally_tagged_variant(
&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);
+ field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
}
quote_expr! {
_serde::private::ser::serialize_tagged_newtype(
__serializer,
#enum_ident_str,
#variant_ident_str,
#tag,
@@ -514,17 +567,17 @@ fn serialize_adjacently_tagged_variant(
tag: &str,
content: &str,
) -> Fragment {
let this = ¶ms.this;
let type_name = cattrs.name().serialize_name();
let variant_name = variant.attrs.name().serialize_name();
let inner = Stmts(if let Some(path) = variant.attrs.serialize_with() {
- let ser = wrap_serialize_variant_with(params, path, &variant);
+ let ser = wrap_serialize_variant_with(params, path, variant);
quote_expr! {
_serde::Serialize::serialize(#ser, __serializer)
}
} else {
match variant.style {
Style::Unit => {
return quote_block! {
let mut __struct = try!(_serde::Serializer::serialize_struct(
@@ -533,17 +586,17 @@ fn serialize_adjacently_tagged_variant(
&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);
+ field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
}
quote_expr! {
_serde::Serialize::serialize(#field_expr, __serializer)
}
}
Style::Tuple => {
serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields)
@@ -553,32 +606,32 @@ fn serialize_adjacently_tagged_variant(
params,
&variant.fields,
&variant_name,
),
}
});
let fields_ty = variant.fields.iter().map(|f| &f.ty);
- let ref fields_ident: Vec<_> = match variant.style {
+ let fields_ident: &Vec<_> = &match variant.style {
Style::Unit => {
if variant.attrs.serialize_with().is_some() {
vec![]
} else {
unreachable!()
}
}
- Style::Newtype => vec![Ident::new("__field0")],
+ Style::Newtype => vec![Ident::new("__field0", Span::def_site())],
Style::Tuple => (0..variant.fields.len())
- .map(|i| Ident::new(format!("__field{}", i)))
+ .map(|i| Ident::new(&format!("__field{}", i), Span::def_site()))
.collect(),
Style::Struct => variant
.fields
.iter()
- .map(|f| f.ident.clone().expect("struct variant has unnamed fields"))
+ .map(|f| f.ident.expect("struct variant has unnamed fields"))
.collect(),
};
let (_, ty_generics, where_clause) = params.generics.split_for_impl();
let wrapper_generics = if let Style::Unit = variant.style {
params.generics.clone()
} else {
@@ -615,33 +668,33 @@ fn serialize_adjacently_tagged_variant(
}
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);
+ let ser = wrap_serialize_variant_with(params, path, variant);
return quote_expr! {
_serde::Serialize::serialize(#ser, __serializer)
};
}
match variant.style {
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);
+ field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
}
quote_expr! {
_serde::Serialize::serialize(#field_expr, __serializer)
}
}
Style::Tuple => serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields),
Style::Struct => {
@@ -660,24 +713,22 @@ enum TupleVariant {
Untagged,
}
fn serialize_tuple_variant(
context: TupleVariant,
params: &Parameters,
fields: &[Field],
) -> Fragment {
- let method = match context {
- TupleVariant::ExternallyTagged { .. } => {
- quote!(_serde::ser::SerializeTupleVariant::serialize_field)
- }
- TupleVariant::Untagged => quote!(_serde::ser::SerializeTuple::serialize_element),
+ let tuple_trait = match context {
+ TupleVariant::ExternallyTagged { .. } => TupleTrait::SerializeTupleVariant,
+ TupleVariant::Untagged => TupleTrait::SerializeTuple,
};
- let serialize_stmts = serialize_tuple_struct_visitor(fields, params, true, method);
+ let serialize_stmts = serialize_tuple_struct_visitor(fields, params, true, &tuple_trait);
let len = serialize_stmts.len();
let let_mut = mut_if(len > 0);
match context {
TupleVariant::ExternallyTagged {
type_name,
variant_index,
@@ -719,39 +770,37 @@ enum StructVariant<'a> {
}
fn serialize_struct_variant<'a>(
context: StructVariant<'a>,
params: &Parameters,
fields: &[Field],
name: &str,
) -> Fragment {
- let (method, skip_method) = match context {
+ let struct_trait = match context {
StructVariant::ExternallyTagged { .. } => (
- quote!(_serde::ser::SerializeStructVariant::serialize_field),
- quote!(_serde::ser::SerializeStructVariant::skip_field),
+ StructTrait::SerializeStructVariant
),
StructVariant::InternallyTagged { .. } | StructVariant::Untagged => (
- quote!(_serde::ser::SerializeStruct::serialize_field),
- quote!(_serde::ser::SerializeStruct::skip_field),
+ StructTrait::SerializeStruct
),
};
- let serialize_fields = serialize_struct_visitor(fields, params, true, method, skip_method);
+ 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 ident = field.ident.clone().expect("struct has unnamed fields");
+ let ident = field.ident.expect("struct has unnamed fields");
match field.attrs.skip_serializing_if() {
Some(path) => quote!(if #path(#ident) { 0 } else { 1 }),
None => quote!(1),
}
})
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
@@ -801,151 +850,174 @@ fn serialize_struct_variant<'a>(
}
}
}
fn serialize_tuple_struct_visitor(
fields: &[Field],
params: &Parameters,
is_enum: bool,
- func: Tokens,
+ tuple_trait: &TupleTrait,
) -> Vec<Tokens> {
fields
.iter()
.enumerate()
.map(|(i, field)| {
let mut field_expr = if is_enum {
- let id = Ident::new(format!("__field{}", i));
+ let id = Ident::new(&format!("__field{}", i), Span::def_site());
quote!(#id)
} else {
- get_field(params, field, i)
+ 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);
+ field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
}
+ let span = Span::def_site().located_at(field.original.span());
+ let func = tuple_trait.serialize_element(span);
let ser = quote! {
try!(#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,
- func: Tokens,
- skip_func: Tokens,
+ struct_trait: &StructTrait,
) -> Vec<Tokens> {
fields
.iter()
.filter(|&field| !field.attrs.skip_serializing())
.map(|field| {
- let field_ident = field.ident.clone().expect("struct has unnamed field");
+ let field_ident = field.ident.expect("struct has unnamed field");
+
let mut field_expr = if is_enum {
quote!(#field_ident)
} else {
- get_field(params, field, field_ident)
+ get_member(params, field, &Member::Named(field_ident))
};
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);
+ field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
}
- let ser = quote! {
- try!(#func(&mut __serde_state, #key_expr, #field_expr));
+ let span = Span::def_site().located_at(field.original.span());
+ let ser = if field.attrs.flatten() {
+ quote! {
+ try!(_serde::Serialize::serialize(&#field_expr, _serde::private::ser::FlatMapSerializer(&mut __serde_state)));
+ }
+ } else {
+ let func = struct_trait.serialize_field(span);
+ quote! {
+ try!(#func(&mut __serde_state, #key_expr, #field_expr));
+ }
};
match skip {
None => ser,
Some(skip) => {
- quote! {
- if !#skip {
- #ser
- } else {
- try!(#skip_func(&mut __serde_state, #key_expr));
+ if let Some(skip_func) = struct_trait.skip_field(span) {
+ quote! {
+ if !#skip {
+ #ser
+ } else {
+ try!(#skip_func(&mut __serde_state, #key_expr));
+ }
+ }
+ } else {
+ quote! {
+ if !#skip {
+ #ser
+ }
}
}
}
}
})
.collect()
}
fn wrap_serialize_field_with(
params: &Parameters,
- field_ty: &syn::Ty,
- serialize_with: &syn::Path,
- field_expr: Tokens,
+ field_ty: &syn::Type,
+ serialize_with: &syn::ExprPath,
+ field_expr: &Tokens,
) -> Tokens {
wrap_serialize_with(params, serialize_with, &[field_ty], &[quote!(#field_expr)])
}
fn wrap_serialize_variant_with(
params: &Parameters,
- serialize_with: &syn::Path,
+ serialize_with: &syn::ExprPath,
variant: &Variant,
) -> Tokens {
let field_tys: Vec<_> = variant.fields.iter().map(|field| field.ty).collect();
let field_exprs: Vec<_> = variant
.fields
.iter()
.enumerate()
.map(|(i, field)| {
let id = field
.ident
- .as_ref()
- .map_or_else(|| Ident::new(format!("__field{}", i)), |id| id.clone());
+ .unwrap_or_else(|| Ident::new(&format!("__field{}", i), Span::def_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::Path,
- field_tys: &[&syn::Ty],
+ serialize_with: &syn::ExprPath,
+ field_tys: &[&syn::Type],
field_exprs: &[Tokens],
) -> Tokens {
let this = ¶ms.this;
let (_, ty_generics, where_clause) = params.generics.split_for_impl();
- let wrapper_generics = if field_exprs.len() == 0 {
+ let wrapper_generics = if field_exprs.is_empty() {
params.generics.clone()
} else {
bound::with_lifetime_bound(¶ms.generics, "'__a")
};
let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
- let field_access = (0..field_exprs.len()).map(|n| Ident::new(format!("{}", n)));
+ let field_access = (0..field_exprs.len()).map(|n| Member::Unnamed(Index {
+ index: n as u32,
+ span: Span::call_site(),
+ }));
quote!({
struct __SerializeWith #wrapper_impl_generics #where_clause {
values: (#(&'__a #field_tys, )*),
phantom: _serde::export::PhantomData<#this #ty_generics>,
}
impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause {
@@ -972,32 +1044,84 @@ fn wrap_serialize_with(
fn mut_if(is_mut: bool) -> Option<Tokens> {
if is_mut {
Some(quote!(mut))
} else {
None
}
}
-fn get_field<I>(params: &Parameters, field: &Field, ident: I) -> Tokens
-where
- I: Into<Ident>,
-{
+fn get_member(params: &Parameters, field: &Field, member: &Member) -> Tokens {
let self_var = ¶ms.self_var;
match (params.is_remote, field.attrs.getter()) {
(false, None) => {
- let ident = ident.into();
- quote!(&#self_var.#ident)
+ quote_spanned!(Span::call_site()=> &#self_var.#member)
}
(true, None) => {
+ let inner = quote_spanned!(Span::call_site()=> &#self_var.#member);
let ty = field.ty;
- let ident = ident.into();
- quote!(_serde::private::ser::constrain::<#ty>(&#self_var.#ident))
+ 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");
}
}
}
+
+enum StructTrait {
+ SerializeMap,
+ SerializeStruct,
+ SerializeStructVariant,
+}
+
+impl StructTrait {
+ fn serialize_field(&self, span: Span) -> Tokens {
+ 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<Tokens> {
+ 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) -> Tokens {
+ 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)
+ }
+ }
+ }
+}
--- a/third_party/rust/serde_derive_internals/.cargo-checksum.json
+++ b/third_party/rust/serde_derive_internals/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"714507185f11d1717d52710ca58df5c6427a808590543bb3b33e9b05bb8bbf92","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"7dc6376a88195594cd6b43cb891aad10f57144ff737178b55d046aa04739b43a","src/ast.rs":"803beccc3b527f926596acfe555fcc0069beebb23ffe1fb8cc0d2faac44fa8f7","src/attr.rs":"af9afd1a768db4d272ff13ff06412eae8d5edc57be0a29b396de8895499436c1","src/case.rs":"8d50d3db3c74c569c75bcf4b285d21bf176940a2efae0656bef769334d62793c","src/check.rs":"dd9d9723bd4d21787cdcff00d6b672f16276088ff0373d20e3fb3eca61580518","src/ctxt.rs":"e842cc73bfd648f14f3bad73e3db321d6cd0f94d255d59e81ed768486fe5deda","src/lib.rs":"5546043bf2cc6d81c1f323df0bd391ad53125f759f217e46e18d035df422b981"},"package":null}
\ No newline at end of file
+{"files":{"Cargo.toml":"b9774130c25f51069e3d6d1617d9bbb63d89caf11a30dce332d4553f73f0d07c","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"7dc6376a88195594cd6b43cb891aad10f57144ff737178b55d046aa04739b43a","src/ast.rs":"30d0f819638c1e7482529f3449980e116cd106ad5f1b5552f653390af5387ba3","src/attr.rs":"0a18342c91f03960620f7baa307937806c17d52564f3dbe234c3e67480242d6a","src/case.rs":"03a97fc3996614153cc5bbd33b5df9d55954407c4d37c5a656f70cbc76817708","src/check.rs":"a7f296d4ca97eee073c7104d888b15022d279a2a04c27dacd11afaf897858461","src/ctxt.rs":"30b38bc10c9d90ec1186ad4ab2159339d65bfaa5a1a51b5900b0ca52fbe526d1","src/lib.rs":"9e4fbabbdbd0a5c7fd486bfd0715eb8278cc2a07a8cf5e5fdbdf6a543d123081"},"package":null}
\ No newline at end of file
--- a/third_party/rust/serde_derive_internals/Cargo.toml
+++ b/third_party/rust/serde_derive_internals/Cargo.toml
@@ -1,19 +1,19 @@
[package]
name = "serde_derive_internals"
-version = "0.19.0" # remember to update html_root_url
+version = "0.22.1" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0"
description = "AST representation used by Serde derive macros. Unstable."
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde_derive_internals/"
keywords = ["serde", "serialization"]
readme = "README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[dependencies]
-syn = { version = "0.11.10", default-features = false, features = ["parsing"] }
-synom = "0.11"
+proc-macro2 = "0.2"
+syn = { version = "0.12", default-features = false, features = ["derive", "parsing", "clone-impls", "extra-traits"] }
[badges]
travis-ci = { repository = "serde-rs/serde" }
--- a/third_party/rust/serde_derive_internals/src/ast.rs
+++ b/third_party/rust/serde_derive_internals/src/ast.rs
@@ -5,40 +5,42 @@
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use syn;
use attr;
use check;
use Ctxt;
+use syn::punctuated::Punctuated;
pub struct Container<'a> {
pub ident: syn::Ident,
pub attrs: attr::Container,
- pub body: Body<'a>,
+ pub data: Data<'a>,
pub generics: &'a syn::Generics,
}
-pub enum Body<'a> {
+pub enum Data<'a> {
Enum(Repr, Vec<Variant<'a>>),
Struct(Style, Vec<Field<'a>>),
}
pub struct Variant<'a> {
pub ident: syn::Ident,
pub attrs: attr::Variant,
pub style: Style,
pub fields: Vec<Field<'a>>,
}
pub struct Field<'a> {
pub ident: Option<syn::Ident>,
pub attrs: attr::Field,
- pub ty: &'a syn::Ty,
+ pub ty: &'a syn::Type,
+ pub original: &'a syn::Field,
}
pub struct Repr {
pub int_repr: Option<&'static str>,
pub c_repr: bool,
pub other_repr: bool,
}
@@ -47,59 +49,70 @@ pub enum Style {
Struct,
Tuple,
Newtype,
Unit,
}
impl<'a> Container<'a> {
pub fn from_ast(cx: &Ctxt, item: &'a syn::DeriveInput) -> Container<'a> {
- let attrs = attr::Container::from_ast(cx, item);
+ let mut attrs = attr::Container::from_ast(cx, item);
- let mut body = match item.body {
- syn::Body::Enum(ref variants) => {
- let (repr, variants) = enum_from_ast(cx, item, variants, &attrs.default());
- Body::Enum(repr, variants)
+ let mut data = match item.data {
+ syn::Data::Enum(ref data) => {
+ let (repr, variants) = enum_from_ast(cx, item, &data.variants, attrs.default());
+ Data::Enum(repr, variants)
}
- syn::Body::Struct(ref variant_data) => {
- let (style, fields) = struct_from_ast(cx, variant_data, None, &attrs.default());
- Body::Struct(style, fields)
+ syn::Data::Struct(ref data) => {
+ let (style, fields) = struct_from_ast(cx, &data.fields, None, attrs.default());
+ Data::Struct(style, fields)
+ }
+ syn::Data::Union(_) => {
+ panic!("Serde does not support derive for unions");
}
};
- match body {
- Body::Enum(_, ref mut variants) => for ref mut variant in variants {
+ let mut has_flatten = false;
+ match data {
+ Data::Enum(_, ref mut variants) => for variant in variants {
variant.attrs.rename_by_rule(attrs.rename_all());
- for ref mut field in &mut variant.fields {
+ for field in &mut variant.fields {
field.attrs.rename_by_rule(variant.attrs.rename_all());
}
},
- Body::Struct(_, ref mut fields) => for field in fields {
+ Data::Struct(_, ref mut fields) => for field in fields {
+ if field.attrs.flatten() {
+ has_flatten = true;
+ }
field.attrs.rename_by_rule(attrs.rename_all());
},
}
+ if has_flatten {
+ attrs.mark_has_flatten();
+ }
+
let item = Container {
- ident: item.ident.clone(),
+ ident: item.ident,
attrs: attrs,
- body: body,
+ data: data,
generics: &item.generics,
};
check::check(cx, &item);
item
}
}
-impl<'a> Body<'a> {
+impl<'a> Data<'a> {
pub fn all_fields(&'a self) -> Box<Iterator<Item = &'a Field<'a>> + 'a> {
match *self {
- Body::Enum(_, ref variants) => {
+ Data::Enum(_, ref variants) => {
Box::new(variants.iter().flat_map(|variant| variant.fields.iter()))
}
- Body::Struct(_, ref fields) => Box::new(fields.iter()),
+ Data::Struct(_, ref fields) => Box::new(fields.iter()),
}
}
pub fn has_getter(&self) -> bool {
self.all_fields().any(|f| f.attrs.getter().is_some())
}
}
@@ -121,28 +134,28 @@ impl Repr {
self.int_repr
}
}
}
fn enum_from_ast<'a>(
cx: &Ctxt,
item: &'a syn::DeriveInput,
- variants: &'a [syn::Variant],
+ variants: &'a Punctuated<syn::Variant, Token![,]>,
container_default: &attr::Default
) -> (Repr, Vec<Variant<'a>>) {
let variants = variants
.iter()
.map(
|variant| {
let attrs = attr::Variant::from_ast(cx, variant);
let (style, fields) =
- struct_from_ast(cx, &variant.data, Some(&attrs), container_default);
+ struct_from_ast(cx, &variant.fields, Some(&attrs), container_default);
Variant {
- ident: variant.ident.clone(),
+ ident: variant.ident,
attrs: attrs,
style: style,
fields: fields,
}
},
)
.collect();
@@ -152,21 +165,21 @@ fn enum_from_ast<'a>(
"i8", "i16", "i32", "i64", "i128", "isize",
];
let mut int_repr = None;
let mut c_repr = false;
let mut other_repr = false;
for attr in &item.attrs {
- if let syn::MetaItem::List(ref ident, ref vals) = attr.value {
- if *ident == "repr" {
+ if let Some(syn::Meta::List(ref list)) = attr.interpret_meta() {
+ if list.ident == "repr" {
// has_repr = true;
- for repr in vals {
- if let syn::NestedMetaItem::MetaItem(syn::MetaItem::Word(ref repr)) = *repr {
+ for repr in &list.nested {
+ if let syn::NestedMeta::Meta(syn::Meta::Word(ref repr)) = *repr {
if repr == "C" {
c_repr = true;
} else if let Some(int_type) = INT_TYPES.iter().cloned().find(|int_type| repr == int_type) {
if int_repr.is_some() {
// This shouldn't happen, but we shouldn't crash if we see it.
// So just treat the enum as having a mysterious other repr,
// which makes us discard any attempt to optimize based on layout.
other_repr = true;
@@ -185,45 +198,46 @@ fn enum_from_ast<'a>(
let repr = Repr { int_repr, c_repr, other_repr };
(repr, variants)
}
fn struct_from_ast<'a>(
cx: &Ctxt,
- data: &'a syn::VariantData,
+ fields: &'a syn::Fields,
attrs: Option<&attr::Variant>,
container_default: &attr::Default,
) -> (Style, Vec<Field<'a>>) {
- match *data {
- syn::VariantData::Struct(ref fields) => (
+ match *fields {
+ syn::Fields::Named(ref fields) => (
Style::Struct,
- fields_from_ast(cx, fields, attrs, container_default),
+ fields_from_ast(cx, &fields.named, attrs, container_default),
),
- syn::VariantData::Tuple(ref fields) if fields.len() == 1 => (
+ syn::Fields::Unnamed(ref fields) if fields.unnamed.len() == 1 => (
Style::Newtype,
- fields_from_ast(cx, fields, attrs, container_default),
+ fields_from_ast(cx, &fields.unnamed, attrs, container_default),
),
- syn::VariantData::Tuple(ref fields) => (
+ syn::Fields::Unnamed(ref fields) => (
Style::Tuple,
- fields_from_ast(cx, fields, attrs, container_default),
+ fields_from_ast(cx, &fields.unnamed, attrs, container_default),
),
- syn::VariantData::Unit => (Style::Unit, Vec::new()),
+ syn::Fields::Unit => (Style::Unit, Vec::new()),
}
}
fn fields_from_ast<'a>(
cx: &Ctxt,
- fields: &'a [syn::Field],
+ fields: &'a Punctuated<syn::Field, Token![,]>,
attrs: Option<&attr::Variant>,
container_default: &attr::Default,
) -> Vec<Field<'a>> {
fields
.iter()
.enumerate()
.map(|(i, field)| Field {
- ident: field.ident.clone(),
+ ident: field.ident,
attrs: attr::Field::from_ast(cx, i, field, attrs, container_default),
ty: &field.ty,
+ original: field,
})
.collect()
}
--- a/third_party/rust/serde_derive_internals/src/attr.rs
+++ b/third_party/rust/serde_derive_internals/src/attr.rs
@@ -3,32 +3,36 @@
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use Ctxt;
use syn;
-use syn::MetaItem::{List, NameValue, Word};
-use syn::NestedMetaItem::{Literal, MetaItem};
-use synom::IResult;
+use syn::Ident;
+use syn::Meta::{List, NameValue, Word};
+use syn::NestedMeta::{Literal, Meta};
+use syn::punctuated::Punctuated;
+use syn::synom::{Synom, ParseError};
use std::collections::BTreeSet;
use std::str::FromStr;
+use proc_macro2::{Span, TokenStream, TokenNode, TokenTree};
// 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 case::RenameRule;
+#[derive(Copy, Clone)]
struct Attr<'c, T> {
cx: &'c Ctxt,
name: &'static str,
value: Option<T>,
}
impl<'c, T> Attr<'c, T> {
fn none(cx: &'c Ctxt, name: &'static str) -> Self {
@@ -76,17 +80,16 @@ impl<'c> BoolAttr<'c> {
self.0.set(());
}
fn get(&self) -> bool {
self.0.value.is_some()
}
}
-#[derive(Debug)]
pub struct Name {
serialize: String,
deserialize: String,
}
impl Name {
/// Return the container name for the container when serializing.
pub fn serialize_name(&self) -> String {
@@ -95,33 +98,32 @@ impl Name {
/// Return the container name for the container when deserializing.
pub fn deserialize_name(&self) -> String {
self.deserialize.clone()
}
}
/// Represents container (e.g. struct) attribute information
-#[derive(Debug)]
pub struct Container {
name: Name,
deny_unknown_fields: bool,
default: Default,
rename_all: RenameRule,
ser_bound: Option<Vec<syn::WherePredicate>>,
de_bound: Option<Vec<syn::WherePredicate>>,
tag: EnumTag,
- from_type: Option<syn::Ty>,
- into_type: Option<syn::Ty>,
+ type_from: Option<syn::Type>,
+ type_into: Option<syn::Type>,
remote: Option<syn::Path>,
identifier: Identifier,
+ has_flatten: bool,
}
/// Styles of representing an enum.
-#[derive(Debug)]
pub enum EnumTag {
/// The default.
///
/// ```json
/// {"variant1": {"key1": "value1", "key2": "value2"}}
/// ```
External,
@@ -144,17 +146,17 @@ pub enum EnumTag {
/// ```json
/// {"key1": "value1", "key2": "value2"}
/// ```
None,
}
/// Whether this enum represents the fields of a struct or the variants of an
/// enum.
-#[derive(Copy, Clone, Debug)]
+#[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,
@@ -181,175 +183,175 @@ impl Container {
let mut deny_unknown_fields = BoolAttr::none(cx, "deny_unknown_fields");
let mut default = Attr::none(cx, "default");
let mut rename_all = Attr::none(cx, "rename_all");
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 from_type = Attr::none(cx, "from");
- let mut into_type = Attr::none(cx, "into");
+ let mut type_from = Attr::none(cx, "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");
for meta_items in item.attrs.iter().filter_map(get_serde_meta_items) {
for meta_item in meta_items {
match meta_item {
// Parse `#[serde(rename = "foo")]`
- MetaItem(NameValue(ref name, ref lit)) if name == "rename" => {
- if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
- ser_name.set(s.clone());
- de_name.set(s);
+ Meta(NameValue(ref m)) if m.ident == "rename" => {
+ if let Ok(s) = get_lit_str(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit) {
+ ser_name.set(s.value());
+ de_name.set(s.value());
}
}
// Parse `#[serde(rename(serialize = "foo", deserialize = "bar"))]`
- MetaItem(List(ref name, ref meta_items)) if name == "rename" => {
- if let Ok((ser, de)) = get_renames(cx, meta_items) {
- ser_name.set_opt(ser);
- de_name.set_opt(de);
+ Meta(List(ref m)) if m.ident == "rename" => {
+ if let Ok((ser, de)) = get_renames(cx, &m.nested) {
+ ser_name.set_opt(ser.map(syn::LitStr::value));
+ de_name.set_opt(de.map(syn::LitStr::value));
}
}
// Parse `#[serde(rename_all = "foo")]`
- MetaItem(NameValue(ref name, ref lit)) if name == "rename_all" => {
- if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
- match RenameRule::from_str(&s) {
+ Meta(NameValue(ref m)) if m.ident == "rename_all" => {
+ if let Ok(s) = get_lit_str(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit) {
+ match RenameRule::from_str(&s.value()) {
Ok(rename_rule) => rename_all.set(rename_rule),
Err(()) => cx.error(format!(
"unknown rename rule for #[serde(rename_all \
= {:?})]",
- s
+ s.value()
)),
}
}
}
// Parse `#[serde(deny_unknown_fields)]`
- MetaItem(Word(ref name)) if name == "deny_unknown_fields" => {
+ Meta(Word(word)) if word == "deny_unknown_fields" => {
deny_unknown_fields.set_true();
}
// Parse `#[serde(default)]`
- MetaItem(Word(ref name)) if name == "default" => match item.body {
- syn::Body::Struct(syn::VariantData::Struct(_)) => {
+ Meta(Word(word)) if word == "default" => match item.data {
+ syn::Data::Struct(syn::DataStruct { fields: syn::Fields::Named(_), .. }) => {
default.set(Default::Default);
}
_ => cx.error(
"#[serde(default)] can only be used on structs \
with named fields",
),
},
// Parse `#[serde(default = "...")]`
- MetaItem(NameValue(ref name, ref lit)) if name == "default" => {
- if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
- match item.body {
- syn::Body::Struct(syn::VariantData::Struct(_)) => {
+ Meta(NameValue(ref m)) if m.ident == "default" => {
+ if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
+ match item.data {
+ syn::Data::Struct(syn::DataStruct { fields: syn::Fields::Named(_), .. }) => {
default.set(Default::Path(path));
}
_ => cx.error(
"#[serde(default = \"...\")] can only be used \
on structs with named fields",
),
}
}
}
// Parse `#[serde(bound = "D: Serialize")]`
- MetaItem(NameValue(ref name, ref lit)) if name == "bound" => {
+ Meta(NameValue(ref m)) if m.ident == "bound" => {
if let Ok(where_predicates) =
- parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit)
+ parse_lit_into_where(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit)
{
ser_bound.set(where_predicates.clone());
de_bound.set(where_predicates);
}
}
// Parse `#[serde(bound(serialize = "D: Serialize", deserialize = "D: Deserialize"))]`
- MetaItem(List(ref name, ref meta_items)) if name == "bound" => {
- if let Ok((ser, de)) = get_where_predicates(cx, meta_items) {
+ Meta(List(ref m)) if m.ident == "bound" => {
+ if let Ok((ser, de)) = get_where_predicates(cx, &m.nested) {
ser_bound.set_opt(ser);
de_bound.set_opt(de);
}
}
// Parse `#[serde(untagged)]`
- MetaItem(Word(ref name)) if name == "untagged" => match item.body {
- syn::Body::Enum(_) => {
+ Meta(Word(word)) if word == "untagged" => match item.data {
+ syn::Data::Enum(_) => {
untagged.set_true();
}
- syn::Body::Struct(_) => {
+ syn::Data::Struct(_) | syn::Data::Union(_) => {
cx.error("#[serde(untagged)] can only be used on enums")
}
},
// Parse `#[serde(tag = "type")]`
- MetaItem(NameValue(ref name, ref lit)) if name == "tag" => {
- if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
- match item.body {
- syn::Body::Enum(_) => {
- internal_tag.set(s);
+ Meta(NameValue(ref m)) if m.ident == "tag" => {
+ if let Ok(s) = get_lit_str(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit) {
+ match item.data {
+ syn::Data::Enum(_) => {
+ internal_tag.set(s.value());
}
- syn::Body::Struct(_) => {
+ syn::Data::Struct(_) | syn::Data::Union(_) => {
cx.error("#[serde(tag = \"...\")] can only be used on enums")
}
}
}
}
// Parse `#[serde(content = "c")]`
- MetaItem(NameValue(ref name, ref lit)) if name == "content" => {
- if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
- match item.body {
- syn::Body::Enum(_) => {
- content.set(s);
+ Meta(NameValue(ref m)) if m.ident == "content" => {
+ if let Ok(s) = get_lit_str(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit) {
+ match item.data {
+ syn::Data::Enum(_) => {
+ content.set(s.value());
}
- syn::Body::Struct(_) => cx.error(
+ syn::Data::Struct(_) | syn::Data::Union(_) => cx.error(
"#[serde(content = \"...\")] can only be used on \
enums",
),
}
}
}
// Parse `#[serde(from = "Type")]
- MetaItem(NameValue(ref name, ref lit)) if name == "from" => {
- if let Ok(from_ty) = parse_lit_into_ty(cx, name.as_ref(), lit) {
- from_type.set_opt(Some(from_ty));
+ Meta(NameValue(ref m)) if m.ident == "from" => {
+ if let Ok(from_ty) = parse_lit_into_ty(cx, m.ident.as_ref(), &m.lit) {
+ type_from.set_opt(Some(from_ty));
}
}
// Parse `#[serde(into = "Type")]
- MetaItem(NameValue(ref name, ref lit)) if name == "into" => {
- if let Ok(into_ty) = parse_lit_into_ty(cx, name.as_ref(), lit) {
- into_type.set_opt(Some(into_ty));
+ Meta(NameValue(ref m)) if m.ident == "into" => {
+ if let Ok(into_ty) = parse_lit_into_ty(cx, m.ident.as_ref(), &m.lit) {
+ type_into.set_opt(Some(into_ty));
}
}
// Parse `#[serde(remote = "...")]`
- MetaItem(NameValue(ref name, ref lit)) if name == "remote" => {
- if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
+ Meta(NameValue(ref m)) if m.ident == "remote" => {
+ if let Ok(path) = parse_lit_into_path(cx, m.ident.as_ref(), &m.lit) {
remote.set(path);
}
}
// Parse `#[serde(field_identifier)]`
- MetaItem(Word(ref name)) if name == "field_identifier" => {
+ Meta(Word(word)) if word == "field_identifier" => {
field_identifier.set_true();
}
// Parse `#[serde(variant_identifier)]`
- MetaItem(Word(ref name)) if name == "variant_identifier" => {
+ Meta(Word(word)) if word == "variant_identifier" => {
variant_identifier.set_true();
}
- MetaItem(ref meta_item) => {
+ Meta(ref meta_item) => {
cx.error(format!(
"unknown serde container attribute `{}`",
meta_item.name()
));
}
Literal(_) => {
cx.error("unexpected literal in serde container attribute");
@@ -363,21 +365,22 @@ impl Container {
serialize: ser_name.get().unwrap_or_else(|| item.ident.to_string()),
deserialize: de_name.get().unwrap_or_else(|| item.ident.to_string()),
},
deny_unknown_fields: deny_unknown_fields.get(),
default: default.get().unwrap_or(Default::None),
rename_all: rename_all.get().unwrap_or(RenameRule::None),
ser_bound: ser_bound.get(),
de_bound: de_bound.get(),
- tag: decide_tag(cx, item, untagged, internal_tag, content),
- from_type: from_type.get(),
- into_type: into_type.get(),
+ tag: decide_tag(cx, item, &untagged, internal_tag, content),
+ type_from: type_from.get(),
+ type_into: type_into.get(),
remote: remote.get(),
- identifier: decide_identifier(cx, item, field_identifier, variant_identifier),
+ identifier: decide_identifier(cx, item, &field_identifier, &variant_identifier),
+ has_flatten: false,
}
}
pub fn name(&self) -> &Name {
&self.name
}
pub fn rename_all(&self) -> &RenameRule {
@@ -399,51 +402,59 @@ impl Container {
pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> {
self.de_bound.as_ref().map(|vec| &vec[..])
}
pub fn tag(&self) -> &EnumTag {
&self.tag
}
- pub fn from_type(&self) -> Option<&syn::Ty> {
- self.from_type.as_ref()
+ pub fn type_from(&self) -> Option<&syn::Type> {
+ self.type_from.as_ref()
}
- pub fn into_type(&self) -> Option<&syn::Ty> {
- self.into_type.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 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;
+ }
}
fn decide_tag(
cx: &Ctxt,
item: &syn::DeriveInput,
- untagged: BoolAttr,
+ untagged: &BoolAttr,
internal_tag: Attr<String>,
content: Attr<String>,
) -> EnumTag {
match (untagged.get(), internal_tag.get(), content.get()) {
(false, None, None) => EnumTag::External,
(true, None, None) => EnumTag::None,
(false, Some(tag), None) => {
// Check that there are no tuple variants.
- if let syn::Body::Enum(ref variants) = item.body {
- for variant in variants {
- match variant.data {
- syn::VariantData::Struct(_) | syn::VariantData::Unit => {}
- syn::VariantData::Tuple(ref fields) => {
- if fields.len() != 1 {
+ if let syn::Data::Enum(ref data) = item.data {
+ for variant in &data.variants {
+ match variant.fields {
+ syn::Fields::Named(_) | syn::Fields::Unit => {}
+ syn::Fields::Unnamed(ref fields) => {
+ if fields.unnamed.len() != 1 {
cx.error(
"#[serde(tag = \"...\")] cannot be used with tuple \
variants",
);
break;
}
}
}
@@ -472,51 +483,52 @@ fn decide_tag(
EnumTag::External
}
}
}
fn decide_identifier(
cx: &Ctxt,
item: &syn::DeriveInput,
- field_identifier: BoolAttr,
- variant_identifier: BoolAttr,
+ field_identifier: &BoolAttr,
+ variant_identifier: &BoolAttr,
) -> Identifier {
- match (&item.body, field_identifier.get(), variant_identifier.get()) {
+ match (&item.data, field_identifier.get(), variant_identifier.get()) {
(_, false, false) => Identifier::No,
(_, true, true) => {
cx.error("`field_identifier` and `variant_identifier` cannot both be set");
Identifier::No
}
- (&syn::Body::Struct(_), true, false) => {
+ (&syn::Data::Enum(_), true, false) => Identifier::Field,
+ (&syn::Data::Enum(_), false, true) => Identifier::Variant,
+ (&syn::Data::Struct(_), true, false)
+ | (&syn::Data::Union(_), true, false) => {
cx.error("`field_identifier` can only be used on an enum");
Identifier::No
}
- (&syn::Body::Struct(_), false, true) => {
+ (&syn::Data::Struct(_), false, true)
+ | (&syn::Data::Union(_), false, true) => {
cx.error("`variant_identifier` can only be used on an enum");
Identifier::No
}
- (&syn::Body::Enum(_), true, false) => Identifier::Field,
- (&syn::Body::Enum(_), false, true) => Identifier::Variant,
}
}
/// Represents variant attribute information
-#[derive(Debug)]
pub struct Variant {
name: Name,
ser_renamed: bool,
de_renamed: bool,
rename_all: RenameRule,
skip_deserializing: bool,
skip_serializing: bool,
other: bool,
- serialize_with: Option<syn::Path>,
- deserialize_with: Option<syn::Path>,
- borrow: Option<syn::MetaItem>,
+ serialize_with: Option<syn::ExprPath>,
+ deserialize_with: Option<syn::ExprPath>,
+ borrow: Option<syn::Meta>,
}
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 skip_deserializing = BoolAttr::none(cx, "skip_deserializing");
let mut skip_serializing = BoolAttr::none(cx, "skip_serializing");
@@ -525,97 +537,97 @@ impl Variant {
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");
for meta_items in variant.attrs.iter().filter_map(get_serde_meta_items) {
for meta_item in meta_items {
match meta_item {
// Parse `#[serde(rename = "foo")]`
- MetaItem(NameValue(ref name, ref lit)) if name == "rename" => {
- if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
- ser_name.set(s.clone());
- de_name.set(s);
+ Meta(NameValue(ref m)) if m.ident == "rename" => {
+ if let Ok(s) = get_lit_str(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit) {
+ ser_name.set(s.value());
+ de_name.set(s.value());
}
}
// Parse `#[serde(rename(serialize = "foo", deserialize = "bar"))]`
- MetaItem(List(ref name, ref meta_items)) if name == "rename" => {
- if let Ok((ser, de)) = get_renames(cx, meta_items) {
- ser_name.set_opt(ser);
- de_name.set_opt(de);
+ Meta(List(ref m)) if m.ident == "rename" => {
+ if let Ok((ser, de)) = get_renames(cx, &m.nested) {
+ ser_name.set_opt(ser.map(syn::LitStr::value));
+ de_name.set_opt(de.map(syn::LitStr::value));
}
}
// Parse `#[serde(rename_all = "foo")]`
- MetaItem(NameValue(ref name, ref lit)) if name == "rename_all" => {
- if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
- match RenameRule::from_str(&s) {
+ Meta(NameValue(ref m)) if m.ident == "rename_all" => {
+ if let Ok(s) = get_lit_str(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit) {
+ match RenameRule::from_str(&s.value()) {
Ok(rename_rule) => rename_all.set(rename_rule),
Err(()) => cx.error(format!(
"unknown rename rule for #[serde(rename_all \
= {:?})]",
- s
+ s.value()
)),
}
}
}
// Parse `#[serde(skip_deserializing)]`
- MetaItem(Word(ref name)) if name == "skip_deserializing" => {
+ Meta(Word(word)) if word == "skip_deserializing" => {
skip_deserializing.set_true();
}
// Parse `#[serde(skip_serializing)]`
- MetaItem(Word(ref name)) if name == "skip_serializing" => {
+ Meta(Word(word)) if word == "skip_serializing" => {
skip_serializing.set_true();
}
// Parse `#[serde(other)]`
- MetaItem(Word(ref name)) if name == "other" => {
+ Meta(Word(word)) if word == "other" => {
other.set_true();
}
// Parse `#[serde(with = "...")]`
- MetaItem(NameValue(ref name, ref lit)) if name == "with" => {
- if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
+ Meta(NameValue(ref m)) if m.ident == "with" => {
+ if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
let mut ser_path = path.clone();
- ser_path.segments.push("serialize".into());
+ ser_path.path.segments.push(Ident::new("serialize", Span::call_site()).into());
serialize_with.set(ser_path);
let mut de_path = path;
- de_path.segments.push("deserialize".into());
+ de_path.path.segments.push(Ident::new("deserialize", Span::call_site()).into());
deserialize_with.set(de_path);
}
}
// Parse `#[serde(serialize_with = "...")]`
- MetaItem(NameValue(ref name, ref lit)) if name == "serialize_with" => {
- if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
+ Meta(NameValue(ref m)) if m.ident == "serialize_with" => {
+ if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
serialize_with.set(path);
}
}
// Parse `#[serde(deserialize_with = "...")]`
- MetaItem(NameValue(ref name, ref lit)) if name == "deserialize_with" => {
- if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
+ Meta(NameValue(ref m)) if m.ident == "deserialize_with" => {
+ if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
deserialize_with.set(path);
}
}
// Defer `#[serde(borrow)]` and `#[serde(borrow = "'a + 'b")]`
- MetaItem(ref mi) if mi.name() == "borrow" => match variant.data {
- syn::VariantData::Tuple(ref fields) if fields.len() == 1 => {
- borrow.set(mi.clone());
+ Meta(ref m) if m.name() == "borrow" => match variant.fields {
+ syn::Fields::Unnamed(ref fields) if fields.unnamed.len() == 1 => {
+ borrow.set(m.clone());
}
_ => {
cx.error("#[serde(borrow)] may only be used on newtype variants");
}
},
- MetaItem(ref meta_item) => {
+ Meta(ref meta_item) => {
cx.error(format!(
"unknown serde variant attribute `{}`",
meta_item.name()
));
}
Literal(_) => {
cx.error("unexpected literal in serde variant attribute");
@@ -669,52 +681,51 @@ impl Variant {
pub fn skip_serializing(&self) -> bool {
self.skip_serializing
}
pub fn other(&self) -> bool {
self.other
}
- pub fn serialize_with(&self) -> Option<&syn::Path> {
+ pub fn serialize_with(&self) -> Option<&syn::ExprPath> {
self.serialize_with.as_ref()
}
- pub fn deserialize_with(&self) -> Option<&syn::Path> {
+ pub fn deserialize_with(&self) -> Option<&syn::ExprPath> {
self.deserialize_with.as_ref()
}
}
/// Represents field attribute information
-#[derive(Debug)]
pub struct Field {
name: Name,
ser_renamed: bool,
de_renamed: bool,
skip_serializing: bool,
skip_deserializing: bool,
- skip_serializing_if: Option<syn::Path>,
+ skip_serializing_if: Option<syn::ExprPath>,
default: Default,
- serialize_with: Option<syn::Path>,
- deserialize_with: Option<syn::Path>,
+ 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::Path>,
+ getter: Option<syn::ExprPath>,
+ flatten: bool,
}
/// Represents the default to use for a field when deserializing.
-#[derive(Debug, PartialEq)]
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::Path),
+ Path(syn::ExprPath),
}
impl Field {
/// Extract out the `#[serde(...)]` attributes from a struct field.
pub fn from_ast(
cx: &Ctxt,
index: usize,
field: &syn::Field,
@@ -728,205 +739,237 @@ impl Field {
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(ref ident) => ident.to_string(),
None => index.to_string(),
};
let variant_borrow = attrs
.map(|variant| &variant.borrow)
.unwrap_or(&None)
.as_ref()
- .map(|borrow| vec![MetaItem(borrow.clone())]);
+ .map(|borrow| vec![Meta(borrow.clone())]);
for meta_items in field
.attrs
.iter()
.filter_map(get_serde_meta_items)
.chain(variant_borrow)
{
for meta_item in meta_items {
match meta_item {
// Parse `#[serde(rename = "foo")]`
- MetaItem(NameValue(ref name, ref lit)) if name == "rename" => {
- if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
- ser_name.set(s.clone());
- de_name.set(s);
+ Meta(NameValue(ref m)) if m.ident == "rename" => {
+ if let Ok(s) = get_lit_str(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit) {
+ ser_name.set(s.value());
+ de_name.set(s.value());
}
}
// Parse `#[serde(rename(serialize = "foo", deserialize = "bar"))]`
- MetaItem(List(ref name, ref meta_items)) if name == "rename" => {
- if let Ok((ser, de)) = get_renames(cx, meta_items) {
- ser_name.set_opt(ser);
- de_name.set_opt(de);
+ Meta(List(ref m)) if m.ident == "rename" => {
+ if let Ok((ser, de)) = get_renames(cx, &m.nested) {
+ ser_name.set_opt(ser.map(syn::LitStr::value));
+ de_name.set_opt(de.map(syn::LitStr::value));
}
}
// Parse `#[serde(default)]`
- MetaItem(Word(ref name)) if name == "default" => {
+ Meta(Word(word)) if word == "default" => {
default.set(Default::Default);
}
// Parse `#[serde(default = "...")]`
- MetaItem(NameValue(ref name, ref lit)) if name == "default" => {
- if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
+ Meta(NameValue(ref m)) if m.ident == "default" => {
+ if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
default.set(Default::Path(path));
}
}
// Parse `#[serde(skip_serializing)]`
- MetaItem(Word(ref name)) if name == "skip_serializing" => {
+ Meta(Word(word)) if word == "skip_serializing" => {
skip_serializing.set_true();
}
// Parse `#[serde(skip_deserializing)]`
- MetaItem(Word(ref name)) if name == "skip_deserializing" => {
+ Meta(Word(word)) if word == "skip_deserializing" => {
skip_deserializing.set_true();
}
// Parse `#[serde(skip)]`
- MetaItem(Word(ref name)) if name == "skip" => {
+ Meta(Word(word)) if word == "skip" => {
skip_serializing.set_true();
skip_deserializing.set_true();
}
// Parse `#[serde(skip_serializing_if = "...")]`
- MetaItem(NameValue(ref name, ref lit)) if name == "skip_serializing_if" => {
- if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
+ Meta(NameValue(ref m)) if m.ident == "skip_serializing_if" => {
+ if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
skip_serializing_if.set(path);
}
}
// Parse `#[serde(serialize_with = "...")]`
- MetaItem(NameValue(ref name, ref lit)) if name == "serialize_with" => {
- if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
+ Meta(NameValue(ref m)) if m.ident == "serialize_with" => {
+ if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
serialize_with.set(path);
}
}
// Parse `#[serde(deserialize_with = "...")]`
- MetaItem(NameValue(ref name, ref lit)) if name == "deserialize_with" => {
- if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
+ Meta(NameValue(ref m)) if m.ident == "deserialize_with" => {
+ if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
deserialize_with.set(path);
}
}
// Parse `#[serde(with = "...")]`
- MetaItem(NameValue(ref name, ref lit)) if name == "with" => {
- if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
+ Meta(NameValue(ref m)) if m.ident == "with" => {
+ if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
let mut ser_path = path.clone();
- ser_path.segments.push("serialize".into());
+ ser_path.path.segments.push(Ident::new("serialize", Span::call_site()).into());
serialize_with.set(ser_path);
let mut de_path = path;
- de_path.segments.push("deserialize".into());
+ de_path.path.segments.push(Ident::new("deserialize", Span::call_site()).into());
deserialize_with.set(de_path);
}
}
// Parse `#[serde(bound = "D: Serialize")]`
- MetaItem(NameValue(ref name, ref lit)) if name == "bound" => {
+ Meta(NameValue(ref m)) if m.ident == "bound" => {
if let Ok(where_predicates) =
- parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit)
+ parse_lit_into_where(cx, m.ident.as_ref(), m.ident.as_ref(), &m.lit)
{
ser_bound.set(where_predicates.clone());
de_bound.set(where_predicates);
}
}
// Parse `#[serde(bound(serialize = "D: Serialize", deserialize = "D: Deserialize"))]`
- MetaItem(List(ref name, ref meta_items)) if name == "bound" => {
- if let Ok((ser, de)) = get_where_predicates(cx, meta_items) {
+ Meta(List(ref m)) if m.ident == "bound" => {
+ if let Ok((ser, de)) = get_where_predicates(cx, &m.nested) {
ser_bound.set_opt(ser);
de_bound.set_opt(de);
}
}
// Parse `#[serde(borrow)]`
- MetaItem(Word(ref name)) if name == "borrow" => {
+ Meta(Word(word)) if word == "borrow" => {
if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, &field.ty) {
borrowed_lifetimes.set(borrowable);
}
}
// Parse `#[serde(borrow = "'a + 'b")]`
- MetaItem(NameValue(ref name, ref lit)) if name == "borrow" => {
- if let Ok(lifetimes) = parse_lit_into_lifetimes(cx, name.as_ref(), lit) {
+ Meta(NameValue(ref m)) if m.ident == "borrow" => {
+ if let Ok(lifetimes) = parse_lit_into_lifetimes(cx, m.ident.as_ref(), &m.lit) {
if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, &field.ty) {
for lifetime in &lifetimes {
if !borrowable.contains(lifetime) {
cx.error(format!(
"field `{}` does not have lifetime {}",
- ident, lifetime.ident
+ ident, lifetime
));
}
}
borrowed_lifetimes.set(lifetimes);
}
}
}
// Parse `#[serde(getter = "...")]`
- MetaItem(NameValue(ref name, ref lit)) if name == "getter" => {
- if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
+ Meta(NameValue(ref m)) if m.ident == "getter" => {
+ if let Ok(path) = parse_lit_into_expr_path(cx, m.ident.as_ref(), &m.lit) {
getter.set(path);
}
}
- MetaItem(ref meta_item) => {
+ // Parse `#[serde(flatten)]`
+ Meta(Word(word)) if word == "flatten" => {
+ flatten.set_true();
+ }
+
+ Meta(ref meta_item) => {
cx.error(format!(
"unknown serde field attribute `{}`",
meta_item.name()
));
}
Literal(_) => {
cx.error("unexpected literal in serde field attribute");
}
}
}
}
// 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 container_default == &Default::None && skip_deserializing.0.value.is_some() {
- default.set_if_none(Default::Default);
+ 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, "str") {
- let path = syn::parse_path("_serde::private::de::borrow_cow_str").unwrap();
- deserialize_with.set_if_none(path);
- } else if is_cow(&field.ty, "[u8]") {
- let path = syn::parse_path("_serde::private::de::borrow_cow_bytes").unwrap();
- deserialize_with.set_if_none(path);
+ if is_cow(&field.ty, is_str) {
+ let mut path = syn::Path {
+ leading_colon: None,
+ segments: Punctuated::new(),
+ };
+ path.segments.push(Ident::new("_serde", Span::def_site()).into());
+ path.segments.push(Ident::new("private", Span::def_site()).into());
+ path.segments.push(Ident::new("de", Span::def_site()).into());
+ path.segments.push(Ident::new("borrow_cow_str", Span::def_site()).into());
+ let expr = syn::ExprPath {
+ attrs: Vec::new(),
+ qself: None,
+ path: 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(),
+ };
+ path.segments.push(Ident::new("_serde", Span::def_site()).into());
+ path.segments.push(Ident::new("private", Span::def_site()).into());
+ path.segments.push(Ident::new("de", Span::def_site()).into());
+ path.segments.push(Ident::new("borrow_cow_bytes", Span::def_site()).into());
+ let expr = syn::ExprPath {
+ attrs: Vec::new(),
+ qself: None,
+ path: path,
+ };
+ deserialize_with.set_if_none(expr);
}
- } else if is_rptr(&field.ty, "str") || is_rptr(&field.ty, "[u8]") {
+ } else if is_rptr(&field.ty, is_str) || is_rptr(&field.ty, is_slice_u8) {
// Types &str and &[u8] are always implicitly borrowed. No need for
// a #[serde(borrow)].
- borrowed_lifetimes = borrowable_lifetimes(cx, &ident, &field.ty).unwrap();
+ collect_lifetimes(&field.ty, &mut borrowed_lifetimes);
}
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();
Field {
name: Name {
@@ -940,16 +983,17 @@ impl Field {
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: borrowed_lifetimes,
getter: getter.get(),
+ flatten: flatten.get(),
}
}
pub fn name(&self) -> &Name {
&self.name
}
pub fn rename_by_rule(&mut self, rule: &RenameRule) {
@@ -964,189 +1008,211 @@ impl Field {
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::Path> {
+ 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::Path> {
+ pub fn serialize_with(&self) -> Option<&syn::ExprPath> {
self.serialize_with.as_ref()
}
- pub fn deserialize_with(&self) -> Option<&syn::Path> {
+ 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::Path> {
+ pub fn getter(&self) -> Option<&syn::ExprPath> {
self.getter.as_ref()
}
+
+ pub fn flatten(&self) -> bool {
+ self.flatten
+ }
}
type SerAndDe<T> = (Option<T>, Option<T>);
-fn get_ser_and_de<T, F>(
+fn get_ser_and_de<'a, T, F>(
cx: &Ctxt,
attr_name: &'static str,
- items: &[syn::NestedMetaItem],
+ metas: &'a Punctuated<syn::NestedMeta, Token![,]>,
f: F,
) -> Result<SerAndDe<T>, ()>
where
- F: Fn(&Ctxt, &str, &str, &syn::Lit) -> Result<T, ()>,
+ T: 'a,
+ F: Fn(&Ctxt, &str, &str, &'a syn::Lit) -> Result<T, ()>,
{
- let mut ser_item = Attr::none(cx, attr_name);
- let mut de_item = Attr::none(cx, attr_name);
+ let mut ser_meta = Attr::none(cx, attr_name);
+ let mut de_meta = Attr::none(cx, attr_name);
- for item in items {
- match *item {
- MetaItem(NameValue(ref name, ref lit)) if name == "serialize" => {
- if let Ok(v) = f(cx, attr_name, name.as_ref(), lit) {
- ser_item.set(v);
+ for meta in metas {
+ match *meta {
+ Meta(NameValue(ref meta)) if meta.ident == "serialize" => {
+ if let Ok(v) = f(cx, attr_name, meta.ident.as_ref(), &meta.lit) {
+ ser_meta.set(v);
}
}
- MetaItem(NameValue(ref name, ref lit)) if name == "deserialize" => {
- if let Ok(v) = f(cx, attr_name, name.as_ref(), lit) {
- de_item.set(v);
+ Meta(NameValue(ref meta)) if meta.ident == "deserialize" => {
+ if let Ok(v) = f(cx, attr_name, meta.ident.as_ref(), &meta.lit) {
+ de_meta.set(v);
}
}
_ => {
cx.error(format!(
"malformed {0} attribute, expected `{0}(serialize = ..., \
deserialize = ...)`",
attr_name
));
return Err(());
}
}
}
- Ok((ser_item.get(), de_item.get()))
+ Ok((ser_meta.get(), de_meta.get()))
}
-fn get_renames(cx: &Ctxt, items: &[syn::NestedMetaItem]) -> Result<SerAndDe<String>, ()> {
- get_ser_and_de(cx, "rename", items, get_string_from_lit)
+fn get_renames<'a>(cx: &Ctxt, items: &'a Punctuated<syn::NestedMeta, Token![,]>) -> Result<SerAndDe<&'a syn::LitStr>, ()> {
+ get_ser_and_de(cx, "rename", items, get_lit_str)
}
fn get_where_predicates(
cx: &Ctxt,
- items: &[syn::NestedMetaItem],
+ items: &Punctuated<syn::NestedMeta, Token![,]>,
) -> Result<SerAndDe<Vec<syn::WherePredicate>>, ()> {
get_ser_and_de(cx, "bound", items, parse_lit_into_where)
}
-pub fn get_serde_meta_items(attr: &syn::Attribute) -> Option<Vec<syn::NestedMetaItem>> {
- match attr.value {
- List(ref name, ref items) if name == "serde" => Some(items.iter().cloned().collect()),
- _ => None,
+pub fn get_serde_meta_items(attr: &syn::Attribute) -> Option<Vec<syn::NestedMeta>> {
+ if attr.path.segments.len() == 1 && attr.path.segments[0].ident == "serde" {
+ match attr.interpret_meta() {
+ Some(List(ref meta)) => Some(meta.nested.iter().cloned().collect()),
+ _ => {
+ // TODO: produce an error
+ None
+ }
+ }
+ } else {
+ None
}
}
-fn get_string_from_lit(
+fn get_lit_str<'a>(
cx: &Ctxt,
attr_name: &str,
meta_item_name: &str,
- lit: &syn::Lit,
-) -> Result<String, ()> {
- if let syn::Lit::Str(ref s, _) = *lit {
- Ok(s.clone())
+ lit: &'a syn::Lit,
+) -> Result<&'a syn::LitStr, ()> {
+ if let syn::Lit::Str(ref lit) = *lit {
+ Ok(lit)
} else {
cx.error(format!(
"expected serde {} attribute to be a string: `{} = \"...\"`",
attr_name, meta_item_name
));
Err(())
}
}
fn parse_lit_into_path(cx: &Ctxt, attr_name: &str, lit: &syn::Lit) -> Result<syn::Path, ()> {
- let string = try!(get_string_from_lit(cx, attr_name, attr_name, lit));
- syn::parse_path(&string).map_err(|err| cx.error(err))
+ let string = try!(get_lit_str(cx, attr_name, attr_name, lit));
+ parse_lit_str(string).map_err(|_| cx.error(format!("failed to parse path: {:?}", string.value())))
+}
+
+fn parse_lit_into_expr_path(cx: &Ctxt, attr_name: &str, lit: &syn::Lit) -> Result<syn::ExprPath, ()> {
+ let string = try!(get_lit_str(cx, attr_name, attr_name, lit));
+ parse_lit_str(string).map_err(|_| cx.error(format!("failed to parse path: {:?}", string.value())))
}
fn parse_lit_into_where(
cx: &Ctxt,
attr_name: &str,
meta_item_name: &str,
lit: &syn::Lit,
) -> Result<Vec<syn::WherePredicate>, ()> {
- let string = try!(get_string_from_lit(cx, attr_name, meta_item_name, lit));
- if string.is_empty() {
+ let string = try!(get_lit_str(cx, attr_name, meta_item_name, lit));
+ if string.value().is_empty() {
return Ok(Vec::new());
}
- let where_string = format!("where {}", string);
+ let where_string = syn::LitStr::new(&format!("where {}", string.value()), string.span);
- syn::parse_where_clause(&where_string)
- .map(|wh| wh.predicates)
+ parse_lit_str::<syn::WhereClause>(&where_string)
+ .map(|wh| wh.predicates.into_iter().collect())
.map_err(|err| cx.error(err))
}
-fn parse_lit_into_ty(cx: &Ctxt, attr_name: &str, lit: &syn::Lit) -> Result<syn::Ty, ()> {
- let string = try!(get_string_from_lit(cx, attr_name, attr_name, lit));
+fn parse_lit_into_ty(cx: &Ctxt, attr_name: &str, lit: &syn::Lit) -> Result<syn::Type, ()> {
+ let string = try!(get_lit_str(cx, attr_name, attr_name, lit));
- syn::parse_type(&string).map_err(|_| {
+ parse_lit_str(string).map_err(|_| {
cx.error(format!(
"failed to parse type: {} = {:?}",
- attr_name, string
+ attr_name, string.value()
))
})
}
// Parses a string literal like "'a + 'b + 'c" containing a nonempty list of
// lifetimes separated by `+`.
fn parse_lit_into_lifetimes(
cx: &Ctxt,
attr_name: &str,
lit: &syn::Lit,
) -> Result<BTreeSet<syn::Lifetime>, ()> {
- let string = try!(get_string_from_lit(cx, attr_name, attr_name, lit));
- if string.is_empty() {
+ let string = try!(get_lit_str(cx, attr_name, attr_name, lit));
+ if string.value().is_empty() {
cx.error("at least one lifetime must be borrowed");
return Err(());
}
- named!(lifetimes -> Vec<syn::Lifetime>,
- separated_nonempty_list!(punct!("+"), syn::parse::lifetime)
- );
+ struct BorrowedLifetimes(Punctuated<syn::Lifetime, Token![+]>);
+
+ impl Synom for BorrowedLifetimes {
+ named!(parse -> Self, map!(
+ call!(Punctuated::parse_separated_nonempty),
+ BorrowedLifetimes
+ ));
+ }
- if let IResult::Done(rest, o) = lifetimes(&string) {
- if rest.trim().is_empty() {
- let mut set = BTreeSet::new();
- for lifetime in o {
- if !set.insert(lifetime.clone()) {
- cx.error(format!("duplicate borrowed lifetime `{}`", lifetime.ident));
- }
+ if let Ok(BorrowedLifetimes(lifetimes)) = parse_lit_str(string) {
+ let mut set = BTreeSet::new();
+ for lifetime in lifetimes {
+ if !set.insert(lifetime) {
+ cx.error(format!("duplicate borrowed lifetime `{}`", lifetime));
}
- return Ok(set);
}
+ return Ok(set);
}
- Err(cx.error(format!("failed to parse borrowed lifetimes: {:?}", string)))
+
+ cx.error(format!("failed to parse borrowed lifetimes: {:?}", string.value()));
+ Err(())
}
// 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;
@@ -1161,37 +1227,43 @@ fn parse_lit_into_lifetimes(
//
// type str = [i16];
//
// #[derive(Deserialize)]
// struct S<'a> {
// #[serde(borrow)]
// cow: Cow<'a, str>,
// }
-fn is_cow(ty: &syn::Ty, elem: &str) -> bool {
+fn is_cow(ty: &syn::Type, elem: fn(&syn::Type) -> bool) -> bool {
let path = match *ty {
- syn::Ty::Path(None, ref path) => path,
+ syn::Type::Path(ref ty) => &ty.path,
_ => {
return false;
}
};
let seg = match path.segments.last() {
- Some(seg) => seg,
+ Some(seg) => seg.into_value(),
None => {
return false;
}
};
- let params = match seg.parameters {
- syn::PathParameters::AngleBracketed(ref params) => params,
+ let args = match seg.arguments {
+ syn::PathArguments::AngleBracketed(ref bracketed) => &bracketed.args,
_ => {
return false;
}
};
- seg.ident == "Cow" && params.lifetimes.len() == 1
- && params.types == vec![syn::parse_type(elem).unwrap()] && params.bindings.is_empty()
+ seg.ident == "Cow"
+ && args.len() == 2
+ && match (&args[0], &args[1]) {
+ (&syn::GenericArgument::Lifetime(_), &syn::GenericArgument::Type(ref 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;
@@ -1204,78 +1276,148 @@ fn is_cow(ty: &syn::Ty, elem: &str) -> b
// False positive:
//
// type str = [i16];
//
// #[derive(Deserialize)]
// struct S<'a> {
// r: &'a str,
// }
-fn is_rptr(ty: &syn::Ty, elem: &str) -> bool {
+fn is_rptr(ty: &syn::Type, elem: fn(&syn::Type) -> bool) -> bool {
match *ty {
- syn::Ty::Rptr(Some(_), ref mut_ty) => {
- mut_ty.mutability == syn::Mutability::Immutable
- && mut_ty.ty == syn::parse_type(elem).unwrap()
+ syn::Type::Reference(ref ty) => {
+ ty.mutability.is_none() && elem(&ty.elem)
+ }
+ _ => false,
+ }
+}
+
+fn is_str(ty: &syn::Type) -> bool {
+ is_primitive_path(ty, "str")
+}
+
+fn is_slice_u8(ty: &syn::Type) -> bool {
+ match *ty {
+ syn::Type::Slice(ref ty) => is_primitive_path(&ty.elem, "u8"),
+ _ => false,
+ }
+}
+
+fn is_primitive_path(ty: &syn::Type, primitive: &str) -> bool {
+ match *ty {
+ syn::Type::Path(ref ty) => {
+ ty.qself.is_none()
+ && ty.path.leading_colon.is_none()
+ && ty.path.segments.len() == 1
+ && ty.path.segments[0].ident == primitive
+ && ty.path.segments[0].arguments.is_empty()
}
_ => false,
}
}
// 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,
- ty: &syn::Ty,
+ ty: &syn::Type,
) -> Result<BTreeSet<syn::Lifetime>, ()> {
let mut lifetimes = BTreeSet::new();
collect_lifetimes(ty, &mut lifetimes);
if lifetimes.is_empty() {
- Err(cx.error(format!("field `{}` has no lifetimes to borrow", name)))
+ cx.error(format!("field `{}` has no lifetimes to borrow", name));
+ Err(())
} else {
Ok(lifetimes)
}
}
-fn collect_lifetimes(ty: &syn::Ty, out: &mut BTreeSet<syn::Lifetime>) {
+fn collect_lifetimes(ty: &syn::Type, out: &mut BTreeSet<syn::Lifetime>) {
match *ty {
- syn::Ty::Slice(ref elem) | syn::Ty::Array(ref elem, _) | syn::Ty::Paren(ref elem) => {
- collect_lifetimes(elem, out);
+ syn::Type::Slice(ref ty) => {
+ collect_lifetimes(&ty.elem, out);
+ }
+ syn::Type::Array(ref ty) => {
+ collect_lifetimes(&ty.elem, out);
}
- syn::Ty::Ptr(ref elem) => {
- collect_lifetimes(&elem.ty, out);
+ syn::Type::Ptr(ref ty) => {
+ collect_lifetimes(&ty.elem, out);
}
- syn::Ty::Rptr(ref lifetime, ref elem) => {
- out.extend(lifetime.iter().cloned());
- collect_lifetimes(&elem.ty, out);
+ syn::Type::Reference(ref ty) => {
+ out.extend(ty.lifetime.iter().cloned());
+ collect_lifetimes(&ty.elem, out);
}
- syn::Ty::Tup(ref elems) => for elem in elems {
+ syn::Type::Tuple(ref ty) => for elem in &ty.elems {
collect_lifetimes(elem, out);
},
- syn::Ty::Path(ref qself, ref path) => {
- if let Some(ref qself) = *qself {
+ syn::Type::Path(ref ty) => {
+ if let Some(ref qself) = ty.qself {
collect_lifetimes(&qself.ty, out);
}
- for seg in &path.segments {
- if let syn::PathParameters::AngleBracketed(ref params) = seg.parameters {
- out.extend(params.lifetimes.iter().cloned());
- for ty in ¶ms.types {
- collect_lifetimes(ty, out);
- }
- for binding in ¶ms.bindings {
- collect_lifetimes(&binding.ty, out);
+ for seg in &ty.path.segments {
+ if let syn::PathArguments::AngleBracketed(ref bracketed) = seg.arguments {
+ for arg in &bracketed.args {
+ match *arg {
+ syn::GenericArgument::Lifetime(ref lifetime) => {
+ out.insert(lifetime.clone());
+ }
+ syn::GenericArgument::Type(ref ty) => {
+ collect_lifetimes(ty, out);
+ }
+ syn::GenericArgument::Binding(ref binding) => {
+ collect_lifetimes(&binding.ty, out);
+ }
+ syn::GenericArgument::Const(_) => {}
+ }
}
}
}
}
- syn::Ty::BareFn(_)
- | syn::Ty::Never
- | syn::Ty::TraitObject(_)
- | syn::Ty::ImplTrait(_)
- | syn::Ty::Infer
- | syn::Ty::Mac(_) => {}
+ syn::Type::Paren(ref ty) => {
+ collect_lifetimes(&ty.elem, out);
+ }
+ syn::Type::Group(ref ty) => {
+ collect_lifetimes(&ty.elem, out);
+ }
+ syn::Type::BareFn(_)
+ | syn::Type::Never(_)
+ | syn::Type::TraitObject(_)
+ | syn::Type::ImplTrait(_)
+ | syn::Type::Infer(_)
+ | syn::Type::Macro(_)
+ | syn::Type::Verbatim(_) => {}
}
}
+
+fn parse_lit_str<T>(s: &syn::LitStr) -> Result<T, ParseError>
+where
+ T: Synom,
+{
+ let tokens = try!(spanned_tokens(s));
+ syn::parse2(tokens)
+}
+
+fn spanned_tokens(s: &syn::LitStr) -> Result<TokenStream, ParseError> {
+ let stream = try!(syn::parse_str(&s.value()));
+ Ok(respan_token_stream(stream, s.span))
+}
+
+fn respan_token_stream(stream: TokenStream, span: Span) -> TokenStream {
+ stream.into_iter().map(|token| respan_token_tree(token, span)).collect()
+}
+
+fn respan_token_tree(token: TokenTree, span: Span) -> TokenTree {
+ TokenTree {
+ span: span,
+ kind: match token.kind {
+ TokenNode::Group(delimiter, nested) => {
+ TokenNode::Group(delimiter, respan_token_stream(nested, span))
+ }
+ other => other,
+ },
+ }
+}
--- a/third_party/rust/serde_derive_internals/src/case.rs
+++ b/third_party/rust/serde_derive_internals/src/case.rs
@@ -2,24 +2,24 @@
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// See https://users.rust-lang.org/t/psa-dealing-with-warning-unused-import-std-ascii-asciiext-in-today-s-nightly/13726
-#[allow(unused_imports)]
+#[allow(deprecated, unused_imports)]
use std::ascii::AsciiExt;
use std::str::FromStr;
use self::RenameRule::*;
-#[derive(Debug, PartialEq)]
+#[derive(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.
--- a/third_party/rust/serde_derive_internals/src/check.rs
+++ b/third_party/rust/serde_derive_internals/src/check.rs
@@ -1,58 +1,93 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use ast::{Body, Container, Style};
-use attr::Identifier;
+use ast::{Data, Container, Style};
+use attr::{Identifier, EnumTag};
use Ctxt;
/// 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: &Container) {
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);
}
/// Getters are only allowed inside structs (not enums) with the `remote`
/// attribute.
fn check_getter(cx: &Ctxt, cont: &Container) {
- match cont.body {
- Body::Enum(_, _) => {
- if cont.body.has_getter() {
+ match cont.data {
+ Data::Enum(_, _) => {
+ if cont.data.has_getter() {
cx.error("#[serde(getter = \"...\")] is not allowed in an enum");
}
}
- Body::Struct(_, _) => {
- if cont.body.has_getter() && cont.attrs.remote().is_none() {
+ Data::Struct(_, _) => {
+ if cont.data.has_getter() && cont.attrs.remote().is_none() {
cx.error(
"#[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(_, _) => {
+ assert!(!cont.attrs.has_flatten());
+ }
+ Data::Struct(_, _) => {
+ for field in cont.data.all_fields() {
+ if !field.attrs.flatten() {
+ continue;
+ }
+ if field.attrs.skip_serializing() {
+ cx.error(
+ "#[serde(flatten] can not be combined with \
+ #[serde(skip_serializing)]"
+ );
+ } else if field.attrs.skip_serializing_if().is_some() {
+ cx.error(
+ "#[serde(flatten] can not be combined with \
+ #[serde(skip_serializing_if = \"...\")]"
+ );
+ } else if field.attrs.skip_deserializing() {
+ cx.error(
+ "#[serde(flatten] can not be combined with \
+ #[serde(skip_deserializing)]"
+ );
+ }
+ }
+ }
+ }
+}
+
/// The `other` attribute must be used at most once and it must be the last
/// variant of an enum that has the `field_identifier` attribute.
///
/// 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.body {
- Body::Enum(_, ref variants) => variants,
- Body::Struct(_, _) => {
+ let variants = match cont.data {
+ Data::Enum(_, ref variants) => variants,
+ Data::Struct(_, _) => {
return;
}
};
for (i, variant) in variants.iter().enumerate() {
match (
variant.style,
cont.attrs.identifier(),
@@ -97,19 +132,19 @@ fn check_identifier(cx: &Ctxt, cont: &Co
}
}
}
}
/// 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.body {
- Body::Enum(_, ref variants) => variants,
- Body::Struct(_, _) => {
+ let variants = match cont.data {
+ Data::Enum(_, ref variants) => variants,
+ Data::Struct(_, _) => {
return;
}
};
for variant in variants.iter() {
if variant.attrs.serialize_with().is_some() {
if variant.attrs.skip_serializing() {
cx.error(format!(
@@ -164,8 +199,72 @@ fn check_variant_skip_attrs(cx: &Ctxt, c
and a field {} marked with #[serde(skip_deserializing)]",
variant.ident, ident
));
}
}
}
}
}
+
+/// 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(_, ref variants) => variants,
+ Data::Struct(_, _) => return,
+ };
+
+ let tag = match *cont.attrs.tag() {
+ EnumTag::Internal { ref tag } => tag.as_str(),
+ EnumTag::External | EnumTag::Adjacent { .. } | EnumTag::None => return,
+ };
+
+ let diagnose_conflict = || {
+ let message = format!(
+ "variant field name `{}` conflicts with internal tag",
+ tag
+ );
+ cx.error(message);
+ };
+
+ for variant in variants {
+ match variant.style {
+ Style::Struct => {
+ for field in &variant.fields {
+ let check_ser = !field.attrs.skip_serializing();
+ let check_de = !field.attrs.skip_deserializing();
+ let name = field.attrs.name();
+ let ser_name = name.serialize_name();
+ let de_name = name.deserialize_name();
+
+ if check_ser && ser_name == tag || 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() {
+ EnumTag::Adjacent { ref tag, ref content } => (tag, content),
+ EnumTag::Internal { .. } | EnumTag::External | EnumTag::None => return,
+ };
+
+ if type_tag == content_tag {
+ let message = format!(
+ "enum tags `{}` for type and content conflict with each other",
+ type_tag
+ );
+ cx.error(message);
+ }
+}
--- a/third_party/rust/serde_derive_internals/src/ctxt.rs
+++ b/third_party/rust/serde_derive_internals/src/ctxt.rs
@@ -3,16 +3,17 @@
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::fmt::Display;
use std::cell::RefCell;
+use std::thread;
#[derive(Default)]
pub struct Ctxt {
errors: RefCell<Option<Vec<String>>>,
}
impl Ctxt {
pub fn new() -> Self {
@@ -43,13 +44,13 @@ impl Ctxt {
Err(msg)
}
}
}
}
impl Drop for Ctxt {
fn drop(&mut self) {
- if self.errors.borrow().is_some() {
+ if !thread::panicking() && self.errors.borrow().is_some() {
panic!("forgot to check for errors");
}
}
}
--- a/third_party/rust/serde_derive_internals/src/lib.rs
+++ b/third_party/rust/serde_derive_internals/src/lib.rs
@@ -1,21 +1,24 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.19.0")]
+#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.22.1")]
+#![cfg_attr(feature = "cargo-clippy", allow(cyclomatic_complexity, doc_markdown, match_same_arms,
+ redundant_field_names))]
+#[macro_use]
extern crate syn;
-#[macro_use]
-extern crate synom;
+
+extern crate proc_macro2;
pub mod ast;
pub mod attr;
mod ctxt;
pub use ctxt::Ctxt;
mod case;