mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-04-27 14:37:55 +00:00
Compare commits
81 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a587eb8953 | |||
| 990f7eb6c1 | |||
| 082e18f9a1 | |||
| f309485787 | |||
| e2f85681fe | |||
| 8b840c3030 | |||
| 9c39115f82 | |||
| 89342af71e | |||
| 3c5e2d11f6 | |||
| 3805c037a8 | |||
| 7045fee260 | |||
| 9d81532e41 | |||
| 5e47432ef0 | |||
| 7b840897a9 | |||
| 967795414b | |||
| 985725f820 | |||
| 0c303d85d7 | |||
| f68e9e901e | |||
| 1094e2d334 | |||
| d9c338ec4a | |||
| 699bf3a75d | |||
| dd29825217 | |||
| 6366f17da7 | |||
| 1120e5af4a | |||
| 1093f7e232 | |||
| 2ea132b8c4 | |||
| 2ebc771b88 | |||
| c17c4eef18 | |||
| 7aa4950504 | |||
| 47015a2727 | |||
| dc4c31eb50 | |||
| b53ebef438 | |||
| 6c3bf7a2fc | |||
| ce0844b9ec | |||
| e9270e59f0 | |||
| 72060b779a | |||
| 1bb23ad9d1 | |||
| 9be4c9654a | |||
| 4114e90bac | |||
| 8bb07b0743 | |||
| ba8c1d63c8 | |||
| 857a805993 | |||
| 5a8dcac2ed | |||
| 697b082e90 | |||
| d91075c8d5 | |||
| 4118cec731 | |||
| c261015325 | |||
| 6b5e5a83d0 | |||
| bc6b2b1dee | |||
| beb21cb640 | |||
| 7cfebbcd72 | |||
| b60c03ec3f | |||
| 3257851192 | |||
| 9a84622c56 | |||
| de8ac1c0be | |||
| 3d6c4149b1 | |||
| 29cdf888c0 | |||
| 2ba97394fb | |||
| 6699b0bc40 | |||
| b054ea4105 | |||
| e5efb6ad93 | |||
| 1f423580a5 | |||
| 033114a4ae | |||
| 7cec99c7fd | |||
| 6c5bf701be | |||
| 6e800ff826 | |||
| 68bda7a004 | |||
| dfeaf77bb2 | |||
| b0cc213e57 | |||
| 74ca06662e | |||
| 38edb473de | |||
| 1c03647656 | |||
| aeee73fe92 | |||
| 1a3ef39040 | |||
| deaf600af7 | |||
| 48556a4c7f | |||
| d88a4748f7 | |||
| e81f54fbc8 | |||
| c67017d466 | |||
| a227a87865 | |||
| 010444dfa4 |
+10
-11
@@ -23,25 +23,22 @@ jobs:
|
|||||||
- run: cd test_suite && cargo test --features unstable -- --skip ui --exact
|
- run: cd test_suite && cargo test --features unstable -- --skip ui --exact
|
||||||
|
|
||||||
stable:
|
stable:
|
||||||
name: Rust stable
|
name: Rust ${{matrix.rust}}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
rust: [stable, beta]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
- uses: dtolnay/rust-toolchain@master
|
||||||
|
with:
|
||||||
|
toolchain: ${{matrix.rust}}
|
||||||
- run: cd serde && cargo build --features rc
|
- run: cd serde && cargo build --features rc
|
||||||
- run: cd serde && cargo build --no-default-features
|
- run: cd serde && cargo build --no-default-features
|
||||||
- run: cd serde_test && cargo build
|
- run: cd serde_test && cargo build
|
||||||
- run: cd serde_test && cargo test --features serde/derive,serde/rc
|
- run: cd serde_test && cargo test --features serde/derive,serde/rc
|
||||||
|
|
||||||
beta:
|
|
||||||
name: Rust beta
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- uses: dtolnay/rust-toolchain@beta
|
|
||||||
- run: cd serde && cargo build --features rc
|
|
||||||
- run: cd test_suite && cargo test
|
|
||||||
|
|
||||||
nightly:
|
nightly:
|
||||||
name: Rust nightly ${{matrix.os == 'windows' && '(windows)' || ''}}
|
name: Rust nightly ${{matrix.os == 'windows' && '(windows)' || ''}}
|
||||||
runs-on: ${{matrix.os}}-latest
|
runs-on: ${{matrix.os}}-latest
|
||||||
@@ -115,6 +112,8 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: dtolnay/rust-toolchain@1.31.0
|
- uses: dtolnay/rust-toolchain@1.31.0
|
||||||
|
- run: cd serde && cargo check --no-default-features
|
||||||
|
- run: cd serde && cargo check
|
||||||
- run: cd serde_derive && cargo check
|
- run: cd serde_derive && cargo check
|
||||||
|
|
||||||
alloc:
|
alloc:
|
||||||
|
|||||||
+4
-10
@@ -31,25 +31,19 @@ tests for you.
|
|||||||
|
|
||||||
```sh
|
```sh
|
||||||
# Test all the example code in Serde documentation
|
# Test all the example code in Serde documentation
|
||||||
cargo test
|
cargo test --features derive
|
||||||
```
|
|
||||||
|
|
||||||
##### In the [`test_suite/deps`] directory
|
|
||||||
|
|
||||||
```sh
|
|
||||||
# This is a prerequisite for running the full test suite
|
|
||||||
cargo clean && cargo update && cargo build
|
|
||||||
```
|
```
|
||||||
|
|
||||||
##### In the [`test_suite`] directory
|
##### In the [`test_suite`] directory
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
# Run the full test suite, including tests of unstable functionality
|
# Run the full test suite, including tests of unstable functionality
|
||||||
cargo test --features unstable
|
cargo +nightly test --features unstable
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Note that this test suite currently only supports running on a nightly compiler.
|
||||||
|
|
||||||
[`serde`]: https://github.com/serde-rs/serde/tree/master/serde
|
[`serde`]: https://github.com/serde-rs/serde/tree/master/serde
|
||||||
[`test_suite/deps`]: https://github.com/serde-rs/serde/tree/master/test_suite/deps
|
|
||||||
[`test_suite`]: https://github.com/serde-rs/serde/tree/master/test_suite
|
[`test_suite`]: https://github.com/serde-rs/serde/tree/master/test_suite
|
||||||
|
|
||||||
## Conduct
|
## Conduct
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.122" # remember to update html_root_url and serde_derive dependency
|
version = "1.0.128" # remember to update html_root_url and serde_derive dependency
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
description = "A generic serialization/deserialization framework"
|
description = "A generic serialization/deserialization framework"
|
||||||
@@ -14,7 +14,7 @@ include = ["build.rs", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APAC
|
|||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde_derive = { version = "=1.0.122", optional = true, path = "../serde_derive" }
|
serde_derive = { version = "=1.0.128", optional = true, path = "../serde_derive" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
serde_derive = { version = "1.0", path = "../serde_derive" }
|
serde_derive = { version = "1.0", path = "../serde_derive" }
|
||||||
|
|||||||
+12
-4
@@ -53,9 +53,10 @@ fn main() {
|
|||||||
// 128-bit integers stabilized in Rust 1.26:
|
// 128-bit integers stabilized in Rust 1.26:
|
||||||
// https://blog.rust-lang.org/2018/05/10/Rust-1.26.html
|
// https://blog.rust-lang.org/2018/05/10/Rust-1.26.html
|
||||||
//
|
//
|
||||||
// Disabled on Emscripten targets as Emscripten doesn't
|
// Disabled on Emscripten targets before Rust 1.40 since
|
||||||
// currently support integers larger than 64 bits.
|
// Emscripten did not support 128-bit integers until Rust 1.40
|
||||||
if minor >= 26 && !emscripten {
|
// (https://github.com/rust-lang/rust/pull/65251)
|
||||||
|
if minor >= 26 && (!emscripten || minor >= 40) {
|
||||||
println!("cargo:rustc-cfg=integer128");
|
println!("cargo:rustc-cfg=integer128");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,12 +72,19 @@ fn main() {
|
|||||||
println!("cargo:rustc-cfg=num_nonzero");
|
println!("cargo:rustc-cfg=num_nonzero");
|
||||||
}
|
}
|
||||||
|
|
||||||
// TryFrom, Atomic types, and non-zero signed integers stabilized in Rust 1.34:
|
// Current minimum supported version of serde_derive crate is Rust 1.31.
|
||||||
|
if minor >= 31 {
|
||||||
|
println!("cargo:rustc-cfg=serde_derive");
|
||||||
|
}
|
||||||
|
|
||||||
|
// TryFrom, Atomic types, non-zero signed integers, and SystemTime::checked_add
|
||||||
|
// stabilized in Rust 1.34:
|
||||||
// https://blog.rust-lang.org/2019/04/11/Rust-1.34.0.html#tryfrom-and-tryinto
|
// https://blog.rust-lang.org/2019/04/11/Rust-1.34.0.html#tryfrom-and-tryinto
|
||||||
// https://blog.rust-lang.org/2019/04/11/Rust-1.34.0.html#library-stabilizations
|
// https://blog.rust-lang.org/2019/04/11/Rust-1.34.0.html#library-stabilizations
|
||||||
if minor >= 34 {
|
if minor >= 34 {
|
||||||
println!("cargo:rustc-cfg=core_try_from");
|
println!("cargo:rustc-cfg=core_try_from");
|
||||||
println!("cargo:rustc-cfg=num_nonzero_signed");
|
println!("cargo:rustc-cfg=num_nonzero_signed");
|
||||||
|
println!("cargo:rustc-cfg=systemtime_checked_add");
|
||||||
|
|
||||||
// Whitelist of archs that support std::sync::atomic module. Ideally we
|
// Whitelist of archs that support std::sync::atomic module. Ideally we
|
||||||
// would use #[cfg(target_has_atomic = "...")] but it is not stable yet.
|
// would use #[cfg(target_has_atomic = "...")] but it is not stable yet.
|
||||||
|
|||||||
@@ -1,260 +0,0 @@
|
|||||||
use lib::*;
|
|
||||||
|
|
||||||
macro_rules! int_to_int {
|
|
||||||
($dst:ident, $n:ident) => {
|
|
||||||
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_value() as u64 {
|
|
||||||
Some($n as $dst)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! uint_to {
|
|
||||||
($dst:ident, $n:ident) => {
|
|
||||||
if $n as u64 <= $dst::max_value() as u64 {
|
|
||||||
Some($n as $dst)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait FromPrimitive: Sized {
|
|
||||||
fn from_i8(n: i8) -> Option<Self>;
|
|
||||||
fn from_i16(n: i16) -> Option<Self>;
|
|
||||||
fn from_i32(n: i32) -> Option<Self>;
|
|
||||||
fn from_i64(n: i64) -> Option<Self>;
|
|
||||||
fn from_u8(n: u8) -> Option<Self>;
|
|
||||||
fn from_u16(n: u16) -> Option<Self>;
|
|
||||||
fn from_u32(n: u32) -> Option<Self>;
|
|
||||||
fn from_u64(n: u64) -> Option<Self>;
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_from_primitive_for_int {
|
|
||||||
($t:ident) => {
|
|
||||||
impl FromPrimitive for $t {
|
|
||||||
#[inline]
|
|
||||||
fn from_i8(n: i8) -> Option<Self> {
|
|
||||||
int_to_int!($t, n)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_i16(n: i16) -> Option<Self> {
|
|
||||||
int_to_int!($t, n)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_i32(n: i32) -> Option<Self> {
|
|
||||||
int_to_int!($t, n)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_i64(n: i64) -> Option<Self> {
|
|
||||||
int_to_int!($t, n)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_u8(n: u8) -> Option<Self> {
|
|
||||||
uint_to!($t, n)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_u16(n: u16) -> Option<Self> {
|
|
||||||
uint_to!($t, n)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_u32(n: u32) -> Option<Self> {
|
|
||||||
uint_to!($t, n)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_u64(n: u64) -> Option<Self> {
|
|
||||||
uint_to!($t, n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_from_primitive_for_uint {
|
|
||||||
($t:ident) => {
|
|
||||||
impl FromPrimitive for $t {
|
|
||||||
#[inline]
|
|
||||||
fn from_i8(n: i8) -> Option<Self> {
|
|
||||||
int_to_uint!($t, n)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_i16(n: i16) -> Option<Self> {
|
|
||||||
int_to_uint!($t, n)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_i32(n: i32) -> Option<Self> {
|
|
||||||
int_to_uint!($t, n)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_i64(n: i64) -> Option<Self> {
|
|
||||||
int_to_uint!($t, n)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_u8(n: u8) -> Option<Self> {
|
|
||||||
uint_to!($t, n)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_u16(n: u16) -> Option<Self> {
|
|
||||||
uint_to!($t, n)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_u32(n: u32) -> Option<Self> {
|
|
||||||
uint_to!($t, n)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_u64(n: u64) -> Option<Self> {
|
|
||||||
uint_to!($t, n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_from_primitive_for_float {
|
|
||||||
($t:ident) => {
|
|
||||||
impl FromPrimitive for $t {
|
|
||||||
#[inline]
|
|
||||||
fn from_i8(n: i8) -> Option<Self> {
|
|
||||||
Some(n as Self)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_i16(n: i16) -> Option<Self> {
|
|
||||||
Some(n as Self)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_i32(n: i32) -> Option<Self> {
|
|
||||||
Some(n as Self)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_i64(n: i64) -> Option<Self> {
|
|
||||||
Some(n as Self)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_u8(n: u8) -> Option<Self> {
|
|
||||||
Some(n as Self)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_u16(n: u16) -> Option<Self> {
|
|
||||||
Some(n as Self)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_u32(n: u32) -> Option<Self> {
|
|
||||||
Some(n as Self)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_u64(n: u64) -> Option<Self> {
|
|
||||||
Some(n as Self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_from_primitive_for_int!(isize);
|
|
||||||
impl_from_primitive_for_int!(i8);
|
|
||||||
impl_from_primitive_for_int!(i16);
|
|
||||||
impl_from_primitive_for_int!(i32);
|
|
||||||
impl_from_primitive_for_int!(i64);
|
|
||||||
impl_from_primitive_for_uint!(usize);
|
|
||||||
impl_from_primitive_for_uint!(u8);
|
|
||||||
impl_from_primitive_for_uint!(u16);
|
|
||||||
impl_from_primitive_for_uint!(u32);
|
|
||||||
impl_from_primitive_for_uint!(u64);
|
|
||||||
impl_from_primitive_for_float!(f32);
|
|
||||||
impl_from_primitive_for_float!(f64);
|
|
||||||
|
|
||||||
serde_if_integer128! {
|
|
||||||
impl FromPrimitive for i128 {
|
|
||||||
#[inline]
|
|
||||||
fn from_i8(n: i8) -> Option<Self> {
|
|
||||||
Some(n as i128)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_i16(n: i16) -> Option<Self> {
|
|
||||||
Some(n as i128)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_i32(n: i32) -> Option<Self> {
|
|
||||||
Some(n as i128)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_i64(n: i64) -> Option<Self> {
|
|
||||||
Some(n as i128)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_u8(n: u8) -> Option<Self> {
|
|
||||||
Some(n as i128)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_u16(n: u16) -> Option<Self> {
|
|
||||||
Some(n as i128)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_u32(n: u32) -> Option<Self> {
|
|
||||||
Some(n as i128)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_u64(n: u64) -> Option<Self> {
|
|
||||||
Some(n as i128)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromPrimitive for u128 {
|
|
||||||
#[inline]
|
|
||||||
fn from_i8(n: i8) -> Option<Self> {
|
|
||||||
if n >= 0 {
|
|
||||||
Some(n as u128)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_i16(n: i16) -> Option<Self> {
|
|
||||||
if n >= 0 {
|
|
||||||
Some(n as u128)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_i32(n: i32) -> Option<Self> {
|
|
||||||
if n >= 0 {
|
|
||||||
Some(n as u128)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_i64(n: i64) -> Option<Self> {
|
|
||||||
if n >= 0 {
|
|
||||||
Some(n as u128)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_u8(n: u8) -> Option<Self> {
|
|
||||||
Some(n as u128)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_u16(n: u16) -> Option<Self> {
|
|
||||||
Some(n as u128)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_u32(n: u32) -> Option<Self> {
|
|
||||||
Some(n as u128)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_u64(n: u64) -> Option<Self> {
|
|
||||||
Some(n as u128)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+216
-138
@@ -7,11 +7,10 @@ use de::{
|
|||||||
#[cfg(any(core_duration, feature = "std", feature = "alloc"))]
|
#[cfg(any(core_duration, feature = "std", feature = "alloc"))]
|
||||||
use de::MapAccess;
|
use de::MapAccess;
|
||||||
|
|
||||||
use __private::de::InPlaceSeed;
|
use seed::InPlaceSeed;
|
||||||
use de::from_primitive::FromPrimitive;
|
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
use __private::de::size_hint;
|
use __private::size_hint;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -81,38 +80,8 @@ impl<'de> Deserialize<'de> for bool {
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
macro_rules! visit_integer_method {
|
|
||||||
($src_ty:ident, $method:ident, $from_method:ident, $group:ident, $group_ty:ident) => {
|
|
||||||
#[inline]
|
|
||||||
fn $method<E>(self, v: $src_ty) -> Result<Self::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
match FromPrimitive::$from_method(v) {
|
|
||||||
Some(v) => Ok(v),
|
|
||||||
None => Err(Error::invalid_value(
|
|
||||||
Unexpected::$group(v as $group_ty),
|
|
||||||
&self,
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! visit_float_method {
|
|
||||||
($src_ty:ident, $method:ident) => {
|
|
||||||
#[inline]
|
|
||||||
fn $method<E>(self, v: $src_ty) -> Result<Self::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
Ok(v as Self::Value)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_deserialize_num {
|
macro_rules! impl_deserialize_num {
|
||||||
($ty:ident, $method:ident, $($visit:ident),*) => {
|
($ty:ident, $deserialize:ident $($methods:tt)*) => {
|
||||||
impl<'de> Deserialize<'de> for $ty {
|
impl<'de> Deserialize<'de> for $ty {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
@@ -128,131 +97,221 @@ macro_rules! impl_deserialize_num {
|
|||||||
formatter.write_str(stringify!($ty))
|
formatter.write_str(stringify!($ty))
|
||||||
}
|
}
|
||||||
|
|
||||||
$(
|
$($methods)*
|
||||||
impl_deserialize_num!($visit $ty);
|
|
||||||
)*
|
|
||||||
}
|
}
|
||||||
|
|
||||||
deserializer.$method(PrimitiveVisitor)
|
deserializer.$deserialize(PrimitiveVisitor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
(integer $ty:ident) => {
|
|
||||||
visit_integer_method!(i8, visit_i8, from_i8, Signed, i64);
|
|
||||||
visit_integer_method!(i16, visit_i16, from_i16, Signed, i64);
|
|
||||||
visit_integer_method!(i32, visit_i32, from_i32, Signed, i64);
|
|
||||||
visit_integer_method!(i64, visit_i64, from_i64, Signed, i64);
|
|
||||||
|
|
||||||
visit_integer_method!(u8, visit_u8, from_u8, Unsigned, u64);
|
|
||||||
visit_integer_method!(u16, visit_u16, from_u16, Unsigned, u64);
|
|
||||||
visit_integer_method!(u32, visit_u32, from_u32, Unsigned, u64);
|
|
||||||
visit_integer_method!(u64, visit_u64, from_u64, Unsigned, u64);
|
|
||||||
};
|
|
||||||
|
|
||||||
(float $ty:ident) => {
|
|
||||||
visit_float_method!(f32, visit_f32);
|
|
||||||
visit_float_method!(f64, visit_f64);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_deserialize_num!(i8, deserialize_i8, integer);
|
macro_rules! num_self {
|
||||||
impl_deserialize_num!(i16, deserialize_i16, integer);
|
($ty:ident : $visit:ident) => {
|
||||||
impl_deserialize_num!(i32, deserialize_i32, integer);
|
|
||||||
impl_deserialize_num!(i64, deserialize_i64, integer);
|
|
||||||
impl_deserialize_num!(isize, deserialize_i64, integer);
|
|
||||||
|
|
||||||
impl_deserialize_num!(u8, deserialize_u8, integer);
|
|
||||||
impl_deserialize_num!(u16, deserialize_u16, integer);
|
|
||||||
impl_deserialize_num!(u32, deserialize_u32, integer);
|
|
||||||
impl_deserialize_num!(u64, deserialize_u64, integer);
|
|
||||||
impl_deserialize_num!(usize, deserialize_u64, integer);
|
|
||||||
|
|
||||||
impl_deserialize_num!(f32, deserialize_f32, integer, float);
|
|
||||||
impl_deserialize_num!(f64, deserialize_f64, integer, float);
|
|
||||||
|
|
||||||
serde_if_integer128! {
|
|
||||||
impl<'de> Deserialize<'de> for i128 {
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
|
||||||
where
|
where
|
||||||
D: Deserializer<'de>,
|
E: Error,
|
||||||
{
|
{
|
||||||
struct PrimitiveVisitor;
|
Ok(v)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
impl<'de> Visitor<'de> for PrimitiveVisitor {
|
macro_rules! num_as_self {
|
||||||
type Value = i128;
|
($($ty:ident : $visit:ident)*) => {
|
||||||
|
$(
|
||||||
|
#[inline]
|
||||||
|
fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: Error,
|
||||||
|
{
|
||||||
|
Ok(v as Self::Value)
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
macro_rules! int_to_int {
|
||||||
formatter.write_str("i128")
|
($($ty:ident : $visit:ident)*) => {
|
||||||
}
|
$(
|
||||||
|
#[inline]
|
||||||
impl_deserialize_num!(integer i128);
|
fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
#[inline]
|
E: Error,
|
||||||
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
|
{
|
||||||
where
|
if Self::Value::min_value() as i64 <= v as i64 && v as i64 <= Self::Value::max_value() as i64 {
|
||||||
E: Error,
|
Ok(v as Self::Value)
|
||||||
{
|
} else {
|
||||||
Ok(v)
|
Err(Error::invalid_value(Unexpected::Signed(v as i64), &self))
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
if v <= i128::max_value() as u128 {
|
|
||||||
Ok(v as i128)
|
|
||||||
} else {
|
|
||||||
Err(Error::invalid_value(Unexpected::Other("u128"), &self))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
deserializer.deserialize_i128(PrimitiveVisitor)
|
macro_rules! int_to_uint {
|
||||||
|
($($ty:ident : $visit:ident)*) => {
|
||||||
|
$(
|
||||||
|
#[inline]
|
||||||
|
fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: Error,
|
||||||
|
{
|
||||||
|
if 0 <= v && v as u64 <= Self::Value::max_value() as u64 {
|
||||||
|
Ok(v as Self::Value)
|
||||||
|
} else {
|
||||||
|
Err(Error::invalid_value(Unexpected::Signed(v as i64), &self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! uint_to_self {
|
||||||
|
($($ty:ident : $visit:ident)*) => {
|
||||||
|
$(
|
||||||
|
#[inline]
|
||||||
|
fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: Error,
|
||||||
|
{
|
||||||
|
if v as u64 <= Self::Value::max_value() as u64 {
|
||||||
|
Ok(v as Self::Value)
|
||||||
|
} else {
|
||||||
|
Err(Error::invalid_value(Unexpected::Unsigned(v as u64), &self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_deserialize_num! {
|
||||||
|
i8, deserialize_i8
|
||||||
|
num_self!(i8:visit_i8);
|
||||||
|
int_to_int!(i16:visit_i16 i32:visit_i32 i64:visit_i64);
|
||||||
|
uint_to_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_deserialize_num! {
|
||||||
|
i16, deserialize_i16
|
||||||
|
num_self!(i16:visit_i16);
|
||||||
|
num_as_self!(i8:visit_i8);
|
||||||
|
int_to_int!(i32:visit_i32 i64:visit_i64);
|
||||||
|
uint_to_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_deserialize_num! {
|
||||||
|
i32, deserialize_i32
|
||||||
|
num_self!(i32:visit_i32);
|
||||||
|
num_as_self!(i8:visit_i8 i16:visit_i16);
|
||||||
|
int_to_int!(i64:visit_i64);
|
||||||
|
uint_to_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_deserialize_num! {
|
||||||
|
i64, deserialize_i64
|
||||||
|
num_self!(i64:visit_i64);
|
||||||
|
num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32);
|
||||||
|
uint_to_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_deserialize_num! {
|
||||||
|
isize, deserialize_i64
|
||||||
|
num_as_self!(i8:visit_i8 i16:visit_i16);
|
||||||
|
int_to_int!(i32:visit_i32 i64:visit_i64);
|
||||||
|
uint_to_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_deserialize_num! {
|
||||||
|
u8, deserialize_u8
|
||||||
|
num_self!(u8:visit_u8);
|
||||||
|
int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
|
||||||
|
uint_to_self!(u16:visit_u16 u32:visit_u32 u64:visit_u64);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_deserialize_num! {
|
||||||
|
u16, deserialize_u16
|
||||||
|
num_self!(u16:visit_u16);
|
||||||
|
num_as_self!(u8:visit_u8);
|
||||||
|
int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
|
||||||
|
uint_to_self!(u32:visit_u32 u64:visit_u64);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_deserialize_num! {
|
||||||
|
u32, deserialize_u32
|
||||||
|
num_self!(u32:visit_u32);
|
||||||
|
num_as_self!(u8:visit_u8 u16:visit_u16);
|
||||||
|
int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
|
||||||
|
uint_to_self!(u64:visit_u64);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_deserialize_num! {
|
||||||
|
u64, deserialize_u64
|
||||||
|
num_self!(u64:visit_u64);
|
||||||
|
num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32);
|
||||||
|
int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_deserialize_num! {
|
||||||
|
usize, deserialize_u64
|
||||||
|
num_as_self!(u8:visit_u8 u16:visit_u16);
|
||||||
|
int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
|
||||||
|
uint_to_self!(u32:visit_u32 u64:visit_u64);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_deserialize_num! {
|
||||||
|
f32, deserialize_f32
|
||||||
|
num_self!(f32:visit_f32);
|
||||||
|
num_as_self!(f64:visit_f64);
|
||||||
|
num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
|
||||||
|
num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_deserialize_num! {
|
||||||
|
f64, deserialize_f64
|
||||||
|
num_self!(f64:visit_f64);
|
||||||
|
num_as_self!(f32:visit_f32);
|
||||||
|
num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
|
||||||
|
num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
|
||||||
|
}
|
||||||
|
|
||||||
|
serde_if_integer128! {
|
||||||
|
impl_deserialize_num! {
|
||||||
|
i128, deserialize_i128
|
||||||
|
num_self!(i128:visit_i128);
|
||||||
|
num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
|
||||||
|
num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: Error,
|
||||||
|
{
|
||||||
|
if v <= i128::max_value() as u128 {
|
||||||
|
Ok(v as i128)
|
||||||
|
} else {
|
||||||
|
Err(Error::invalid_value(Unexpected::Other("u128"), &self))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for u128 {
|
impl_deserialize_num! {
|
||||||
|
u128, deserialize_u128
|
||||||
|
num_self!(u128:visit_u128);
|
||||||
|
num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
|
||||||
|
int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
|
||||||
where
|
where
|
||||||
D: Deserializer<'de>,
|
E: Error,
|
||||||
{
|
{
|
||||||
struct PrimitiveVisitor;
|
if 0 <= v {
|
||||||
|
Ok(v as u128)
|
||||||
impl<'de> Visitor<'de> for PrimitiveVisitor {
|
} else {
|
||||||
type Value = u128;
|
Err(Error::invalid_value(Unexpected::Other("i128"), &self))
|
||||||
|
|
||||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
formatter.write_str("u128")
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_deserialize_num!(integer u128);
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
if v >= 0 {
|
|
||||||
Ok(v as u128)
|
|
||||||
} else {
|
|
||||||
Err(Error::invalid_value(Unexpected::Other("i128"), &self))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
Ok(v)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
deserializer.deserialize_u128(PrimitiveVisitor)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1987,6 +2046,17 @@ impl<'de> Deserialize<'de> for SystemTime {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_overflow<E>(secs: u64, nanos: u32) -> Result<(), E>
|
||||||
|
where
|
||||||
|
E: Error,
|
||||||
|
{
|
||||||
|
static NANOS_PER_SEC: u32 = 1_000_000_000;
|
||||||
|
match secs.checked_add((nanos / NANOS_PER_SEC) as u64) {
|
||||||
|
Some(_) => Ok(()),
|
||||||
|
None => Err(E::custom("overflow deserializing SystemTime epoch offset")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct DurationVisitor;
|
struct DurationVisitor;
|
||||||
|
|
||||||
impl<'de> Visitor<'de> for DurationVisitor {
|
impl<'de> Visitor<'de> for DurationVisitor {
|
||||||
@@ -2012,6 +2082,7 @@ impl<'de> Deserialize<'de> for SystemTime {
|
|||||||
return Err(Error::invalid_length(1, &self));
|
return Err(Error::invalid_length(1, &self));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
try!(check_overflow(secs, nanos));
|
||||||
Ok(Duration::new(secs, nanos))
|
Ok(Duration::new(secs, nanos))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2049,13 +2120,20 @@ impl<'de> Deserialize<'de> for SystemTime {
|
|||||||
Some(nanos) => nanos,
|
Some(nanos) => nanos,
|
||||||
None => return Err(<A::Error as Error>::missing_field("nanos_since_epoch")),
|
None => return Err(<A::Error as Error>::missing_field("nanos_since_epoch")),
|
||||||
};
|
};
|
||||||
|
try!(check_overflow(secs, nanos));
|
||||||
Ok(Duration::new(secs, nanos))
|
Ok(Duration::new(secs, nanos))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const FIELDS: &'static [&'static str] = &["secs_since_epoch", "nanos_since_epoch"];
|
const FIELDS: &'static [&'static str] = &["secs_since_epoch", "nanos_since_epoch"];
|
||||||
let duration = try!(deserializer.deserialize_struct("SystemTime", FIELDS, DurationVisitor));
|
let duration = try!(deserializer.deserialize_struct("SystemTime", FIELDS, DurationVisitor));
|
||||||
Ok(UNIX_EPOCH + duration)
|
#[cfg(systemtime_checked_add)]
|
||||||
|
let ret = UNIX_EPOCH
|
||||||
|
.checked_add(duration)
|
||||||
|
.ok_or_else(|| D::Error::custom("overflow deserializing SystemTime"));
|
||||||
|
#[cfg(not(systemtime_checked_add))]
|
||||||
|
let ret = Ok(UNIX_EPOCH + duration);
|
||||||
|
ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -118,7 +118,6 @@ use lib::*;
|
|||||||
|
|
||||||
pub mod value;
|
pub mod value;
|
||||||
|
|
||||||
mod from_primitive;
|
|
||||||
mod ignored_any;
|
mod ignored_any;
|
||||||
mod impls;
|
mod impls;
|
||||||
mod utf8;
|
mod utf8;
|
||||||
@@ -1008,7 +1007,7 @@ pub trait Deserializer<'de>: Sized {
|
|||||||
/// `Deserializer`.
|
/// `Deserializer`.
|
||||||
///
|
///
|
||||||
/// If the `Visitor` would benefit from taking ownership of `String` data,
|
/// If the `Visitor` would benefit from taking ownership of `String` data,
|
||||||
/// indiciate this to the `Deserializer` by using `deserialize_string`
|
/// indicate this to the `Deserializer` by using `deserialize_string`
|
||||||
/// instead.
|
/// instead.
|
||||||
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
where
|
where
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
use de::{Deserialize, DeserializeSeed, Deserializer};
|
||||||
|
|
||||||
|
/// A DeserializeSeed helper for implementing deserialize_in_place Visitors.
|
||||||
|
///
|
||||||
|
/// Wraps a mutable reference and calls deserialize_in_place on it.
|
||||||
|
pub struct InPlaceSeed<'a, T: 'a>(pub &'a mut T);
|
||||||
|
|
||||||
|
impl<'a, 'de, T> DeserializeSeed<'de> for InPlaceSeed<'a, T>
|
||||||
|
where
|
||||||
|
T: Deserialize<'de>,
|
||||||
|
{
|
||||||
|
type Value = ();
|
||||||
|
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
T::deserialize_in_place(deserializer, self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
use lib::*;
|
use lib::*;
|
||||||
|
|
||||||
use self::private::{First, Second};
|
use self::private::{First, Second};
|
||||||
use __private::de::size_hint;
|
use __private::size_hint;
|
||||||
use de::{self, Deserializer, Expected, IntoDeserializer, SeqAccess, Visitor};
|
use de::{self, Deserializer, Expected, IntoDeserializer, SeqAccess, Visitor};
|
||||||
use ser;
|
use ser;
|
||||||
|
|
||||||
|
|||||||
+6
-3
@@ -44,7 +44,7 @@
|
|||||||
//! - [BSON], the data storage and network transfer format used by MongoDB.
|
//! - [BSON], the data storage and network transfer format used by MongoDB.
|
||||||
//! - [Avro], a binary format used within Apache Hadoop, with support for schema
|
//! - [Avro], a binary format used within Apache Hadoop, with support for schema
|
||||||
//! definition.
|
//! definition.
|
||||||
//! - [JSON5], A superset of JSON including some productions from ES5.
|
//! - [JSON5], a superset of JSON including some productions from ES5.
|
||||||
//! - [Postcard], a no\_std and embedded-systems friendly compact binary format.
|
//! - [Postcard], a no\_std and embedded-systems friendly compact binary format.
|
||||||
//! - [URL] query strings, in the x-www-form-urlencoded format.
|
//! - [URL] query strings, in the x-www-form-urlencoded format.
|
||||||
//! - [Envy], a way to deserialize environment variables into Rust structs.
|
//! - [Envy], a way to deserialize environment variables into Rust structs.
|
||||||
@@ -84,7 +84,7 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Serde types in rustdoc of other crates get linked to here.
|
// Serde types in rustdoc of other crates get linked to here.
|
||||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.122")]
|
#![doc(html_root_url = "https://docs.rs/serde/1.0.128")]
|
||||||
// Support using Serde without the standard library!
|
// Support using Serde without the standard library!
|
||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
// Unstable functionality only if the user asks for it. For tracking and
|
// Unstable functionality only if the user asks for it. For tracking and
|
||||||
@@ -120,6 +120,7 @@
|
|||||||
zero_prefixed_literal,
|
zero_prefixed_literal,
|
||||||
// correctly used
|
// correctly used
|
||||||
enum_glob_use,
|
enum_glob_use,
|
||||||
|
let_underscore_drop,
|
||||||
map_err_ignore,
|
map_err_ignore,
|
||||||
result_unit_err,
|
result_unit_err,
|
||||||
wildcard_imports,
|
wildcard_imports,
|
||||||
@@ -138,7 +139,6 @@
|
|||||||
)
|
)
|
||||||
)]
|
)]
|
||||||
// Rustc lints.
|
// Rustc lints.
|
||||||
#![forbid(unsafe_code)]
|
|
||||||
#![deny(missing_docs, unused_imports)]
|
#![deny(missing_docs, unused_imports)]
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -276,6 +276,9 @@ use self::__private as export;
|
|||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use self::__private as private;
|
use self::__private as private;
|
||||||
|
|
||||||
|
#[path = "de/seed.rs"]
|
||||||
|
mod seed;
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
mod std_error;
|
mod std_error;
|
||||||
|
|
||||||
|
|||||||
+51
-73
@@ -1,10 +1,10 @@
|
|||||||
use lib::*;
|
use lib::*;
|
||||||
|
|
||||||
use de::value::{BorrowedBytesDeserializer, BytesDeserializer};
|
use de::value::{BorrowedBytesDeserializer, BytesDeserializer};
|
||||||
use de::{Deserialize, DeserializeSeed, Deserializer, Error, IntoDeserializer, Visitor};
|
use de::{Deserialize, Deserializer, Error, IntoDeserializer, Visitor};
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
use de::{MapAccess, Unexpected};
|
use de::{DeserializeSeed, MapAccess, Unexpected};
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
pub use self::content::{
|
pub use self::content::{
|
||||||
@@ -13,6 +13,8 @@ pub use self::content::{
|
|||||||
TagOrContentField, TagOrContentFieldVisitor, TaggedContentVisitor, UntaggedUnitVisitor,
|
TagOrContentField, TagOrContentFieldVisitor, TaggedContentVisitor, UntaggedUnitVisitor,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub use seed::InPlaceSeed;
|
||||||
|
|
||||||
/// If the missing field is of type `Option<T>` then treat is as `None`,
|
/// If the missing field is of type `Option<T>` then treat is as `None`,
|
||||||
/// otherwise it is an error.
|
/// otherwise it is an error.
|
||||||
pub fn missing_field<'de, V, E>(field: &'static str) -> Result<V, E>
|
pub fn missing_field<'de, V, E>(field: &'static str) -> Result<V, E>
|
||||||
@@ -189,29 +191,6 @@ where
|
|||||||
.map(From::from)
|
.map(From::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod size_hint {
|
|
||||||
use lib::*;
|
|
||||||
|
|
||||||
pub fn from_bounds<I>(iter: &I) -> Option<usize>
|
|
||||||
where
|
|
||||||
I: Iterator,
|
|
||||||
{
|
|
||||||
helper(iter.size_hint())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn cautious(hint: Option<usize>) -> usize {
|
|
||||||
cmp::min(hint.unwrap_or(0), 4096)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn helper(bounds: (usize, Option<usize>)) -> Option<usize> {
|
|
||||||
match bounds {
|
|
||||||
(lower, Some(upper)) if lower == upper => Some(upper),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
mod content {
|
mod content {
|
||||||
// This module is private and nothing here should be used outside of
|
// This module is private and nothing here should be used outside of
|
||||||
@@ -226,7 +205,7 @@ mod content {
|
|||||||
|
|
||||||
use lib::*;
|
use lib::*;
|
||||||
|
|
||||||
use super::size_hint;
|
use __private::size_hint;
|
||||||
use de::{
|
use de::{
|
||||||
self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, IgnoredAny,
|
self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, IgnoredAny,
|
||||||
MapAccess, SeqAccess, Unexpected, Visitor,
|
MapAccess, SeqAccess, Unexpected, Visitor,
|
||||||
@@ -1043,6 +1022,25 @@ mod content {
|
|||||||
_ => Err(self.invalid_type(&visitor)),
|
_ => Err(self.invalid_type(&visitor)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deserialize_float<V>(self, visitor: V) -> Result<V::Value, E>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self.content {
|
||||||
|
Content::F32(v) => visitor.visit_f32(v),
|
||||||
|
Content::F64(v) => visitor.visit_f64(v),
|
||||||
|
Content::U8(v) => visitor.visit_u8(v),
|
||||||
|
Content::U16(v) => visitor.visit_u16(v),
|
||||||
|
Content::U32(v) => visitor.visit_u32(v),
|
||||||
|
Content::U64(v) => visitor.visit_u64(v),
|
||||||
|
Content::I8(v) => visitor.visit_i8(v),
|
||||||
|
Content::I16(v) => visitor.visit_i16(v),
|
||||||
|
Content::I32(v) => visitor.visit_i32(v),
|
||||||
|
Content::I64(v) => visitor.visit_i64(v),
|
||||||
|
_ => Err(self.invalid_type(&visitor)),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_content_seq<'de, V, E>(content: Vec<Content<'de>>, visitor: V) -> Result<V::Value, E>
|
fn visit_content_seq<'de, V, E>(content: Vec<Content<'de>>, visitor: V) -> Result<V::Value, E>
|
||||||
@@ -1182,25 +1180,14 @@ mod content {
|
|||||||
where
|
where
|
||||||
V: Visitor<'de>,
|
V: Visitor<'de>,
|
||||||
{
|
{
|
||||||
match self.content {
|
self.deserialize_float(visitor)
|
||||||
Content::F32(v) => visitor.visit_f32(v),
|
|
||||||
Content::F64(v) => visitor.visit_f64(v),
|
|
||||||
Content::U64(v) => visitor.visit_u64(v),
|
|
||||||
Content::I64(v) => visitor.visit_i64(v),
|
|
||||||
_ => Err(self.invalid_type(&visitor)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
where
|
where
|
||||||
V: Visitor<'de>,
|
V: Visitor<'de>,
|
||||||
{
|
{
|
||||||
match self.content {
|
self.deserialize_float(visitor)
|
||||||
Content::F64(v) => visitor.visit_f64(v),
|
|
||||||
Content::U64(v) => visitor.visit_u64(v),
|
|
||||||
Content::I64(v) => visitor.visit_i64(v),
|
|
||||||
_ => Err(self.invalid_type(&visitor)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
@@ -1300,8 +1287,9 @@ mod content {
|
|||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// We want {"topic":"Info"} to deserialize even though
|
// We want {"topic":"Info"} to deserialize even though
|
||||||
// ordinarily unit structs do not deserialize from empty map.
|
// ordinarily unit structs do not deserialize from empty map/seq.
|
||||||
Content::Map(ref v) if v.is_empty() => visitor.visit_unit(),
|
Content::Map(ref v) if v.is_empty() => visitor.visit_unit(),
|
||||||
|
Content::Seq(ref v) if v.is_empty() => visitor.visit_unit(),
|
||||||
_ => self.deserialize_any(visitor),
|
_ => self.deserialize_any(visitor),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1754,6 +1742,25 @@ mod content {
|
|||||||
_ => Err(self.invalid_type(&visitor)),
|
_ => Err(self.invalid_type(&visitor)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deserialize_float<V>(self, visitor: V) -> Result<V::Value, E>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match *self.content {
|
||||||
|
Content::F32(v) => visitor.visit_f32(v),
|
||||||
|
Content::F64(v) => visitor.visit_f64(v),
|
||||||
|
Content::U8(v) => visitor.visit_u8(v),
|
||||||
|
Content::U16(v) => visitor.visit_u16(v),
|
||||||
|
Content::U32(v) => visitor.visit_u32(v),
|
||||||
|
Content::U64(v) => visitor.visit_u64(v),
|
||||||
|
Content::I8(v) => visitor.visit_i8(v),
|
||||||
|
Content::I16(v) => visitor.visit_i16(v),
|
||||||
|
Content::I32(v) => visitor.visit_i32(v),
|
||||||
|
Content::I64(v) => visitor.visit_i64(v),
|
||||||
|
_ => Err(self.invalid_type(&visitor)),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_content_seq_ref<'a, 'de, V, E>(
|
fn visit_content_seq_ref<'a, 'de, V, E>(
|
||||||
@@ -1901,25 +1908,14 @@ mod content {
|
|||||||
where
|
where
|
||||||
V: Visitor<'de>,
|
V: Visitor<'de>,
|
||||||
{
|
{
|
||||||
match *self.content {
|
self.deserialize_float(visitor)
|
||||||
Content::F32(v) => visitor.visit_f32(v),
|
|
||||||
Content::F64(v) => visitor.visit_f64(v),
|
|
||||||
Content::U64(v) => visitor.visit_u64(v),
|
|
||||||
Content::I64(v) => visitor.visit_i64(v),
|
|
||||||
_ => Err(self.invalid_type(&visitor)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
where
|
where
|
||||||
V: Visitor<'de>,
|
V: Visitor<'de>,
|
||||||
{
|
{
|
||||||
match *self.content {
|
self.deserialize_float(visitor)
|
||||||
Content::F64(v) => visitor.visit_f64(v),
|
|
||||||
Content::U64(v) => visitor.visit_u64(v),
|
|
||||||
Content::I64(v) => visitor.visit_i64(v),
|
|
||||||
_ => Err(self.invalid_type(&visitor)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
@@ -2658,24 +2654,6 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A DeserializeSeed helper for implementing deserialize_in_place Visitors.
|
|
||||||
///
|
|
||||||
/// Wraps a mutable reference and calls deserialize_in_place on it.
|
|
||||||
pub struct InPlaceSeed<'a, T: 'a>(pub &'a mut T);
|
|
||||||
|
|
||||||
impl<'a, 'de, T> DeserializeSeed<'de> for InPlaceSeed<'a, T>
|
|
||||||
where
|
|
||||||
T: Deserialize<'de>,
|
|
||||||
{
|
|
||||||
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"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
pub struct FlatMapDeserializer<'a, 'de: 'a, E>(
|
pub struct FlatMapDeserializer<'a, 'de: 'a, E>(
|
||||||
pub &'a mut Vec<Option<(Content<'de>, Content<'de>)>>,
|
pub &'a mut Vec<Option<(Content<'de>, Content<'de>)>>,
|
||||||
@@ -2854,7 +2832,7 @@ where
|
|||||||
where
|
where
|
||||||
T: DeserializeSeed<'de>,
|
T: DeserializeSeed<'de>,
|
||||||
{
|
{
|
||||||
while let Some(item) = self.iter.next() {
|
for item in &mut self.iter {
|
||||||
// Items in the vector are nulled out when used by a struct.
|
// Items in the vector are nulled out when used by a struct.
|
||||||
if let Some((ref key, ref content)) = *item {
|
if let Some((ref key, ref content)) = *item {
|
||||||
self.pending_content = Some(content);
|
self.pending_content = Some(content);
|
||||||
@@ -2956,7 +2934,7 @@ where
|
|||||||
where
|
where
|
||||||
T: DeserializeSeed<'de>,
|
T: DeserializeSeed<'de>,
|
||||||
{
|
{
|
||||||
while let Some(item) = self.iter.next() {
|
for item in &mut self.iter {
|
||||||
if let Some((ref key, ref content)) = *item {
|
if let Some((ref key, ref content)) = *item {
|
||||||
// Do not take(), instead borrow this entry. The internally tagged
|
// Do not take(), instead borrow this entry. The internally tagged
|
||||||
// enum does its own buffering so we can't tell whether this entry
|
// enum does its own buffering so we can't tell whether this entry
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
|
#[cfg(serde_derive)]
|
||||||
pub mod de;
|
pub mod de;
|
||||||
|
#[cfg(serde_derive)]
|
||||||
pub mod ser;
|
pub mod ser;
|
||||||
|
|
||||||
|
pub mod size_hint;
|
||||||
|
|
||||||
// FIXME: #[cfg(doctest)] once https://github.com/rust-lang/rust/issues/67295 is fixed.
|
// FIXME: #[cfg(doctest)] once https://github.com/rust-lang/rust/issues/67295 is fixed.
|
||||||
pub mod doc;
|
pub mod doc;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
use lib::*;
|
||||||
|
|
||||||
|
pub fn from_bounds<I>(iter: &I) -> Option<usize>
|
||||||
|
where
|
||||||
|
I: Iterator,
|
||||||
|
{
|
||||||
|
helper(iter.size_hint())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[inline]
|
||||||
|
pub fn cautious(hint: Option<usize>) -> usize {
|
||||||
|
cmp::min(hint.unwrap_or(0), 4096)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn helper(bounds: (usize, Option<usize>)) -> Option<usize> {
|
||||||
|
match bounds {
|
||||||
|
(lower, Some(upper)) if lower == upper => Some(upper),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
+54
-1
@@ -674,6 +674,52 @@ impl Serialize for net::IpAddr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
const DEC_DIGITS_LUT: &'static [u8] = b"\
|
||||||
|
0001020304050607080910111213141516171819\
|
||||||
|
2021222324252627282930313233343536373839\
|
||||||
|
4041424344454647484950515253545556575859\
|
||||||
|
6061626364656667686970717273747576777879\
|
||||||
|
8081828384858687888990919293949596979899";
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
#[inline]
|
||||||
|
fn format_u8(mut n: u8, out: &mut [u8]) -> usize {
|
||||||
|
if n >= 100 {
|
||||||
|
let d1 = ((n % 100) << 1) as usize;
|
||||||
|
n /= 100;
|
||||||
|
out[0] = b'0' + n;
|
||||||
|
out[1] = DEC_DIGITS_LUT[d1];
|
||||||
|
out[2] = DEC_DIGITS_LUT[d1 + 1];
|
||||||
|
3
|
||||||
|
} else if n >= 10 {
|
||||||
|
let d1 = (n << 1) as usize;
|
||||||
|
out[0] = DEC_DIGITS_LUT[d1];
|
||||||
|
out[1] = DEC_DIGITS_LUT[d1 + 1];
|
||||||
|
2
|
||||||
|
} else {
|
||||||
|
out[0] = b'0' + n;
|
||||||
|
1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
#[test]
|
||||||
|
fn test_format_u8() {
|
||||||
|
let mut i = 0u8;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let mut buf = [0u8; 3];
|
||||||
|
let written = format_u8(i, &mut buf);
|
||||||
|
assert_eq!(i.to_string().as_bytes(), &buf[..written]);
|
||||||
|
|
||||||
|
match i.checked_add(1) {
|
||||||
|
Some(next) => i = next,
|
||||||
|
None => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl Serialize for net::Ipv4Addr {
|
impl Serialize for net::Ipv4Addr {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
@@ -683,7 +729,14 @@ impl Serialize for net::Ipv4Addr {
|
|||||||
if serializer.is_human_readable() {
|
if serializer.is_human_readable() {
|
||||||
const MAX_LEN: usize = 15;
|
const MAX_LEN: usize = 15;
|
||||||
debug_assert_eq!(MAX_LEN, "101.102.103.104".len());
|
debug_assert_eq!(MAX_LEN, "101.102.103.104".len());
|
||||||
serialize_display_bounded_length!(self, MAX_LEN, serializer)
|
let mut buf = [b'.'; MAX_LEN];
|
||||||
|
let mut written = format_u8(self.octets()[0], &mut buf);
|
||||||
|
for oct in &self.octets()[1..] {
|
||||||
|
// Skip over delimiters that we initialized buf with
|
||||||
|
written += format_u8(*oct, &mut buf[written + 1..]) + 1;
|
||||||
|
}
|
||||||
|
// We've only written ASCII bytes to the buffer, so it is valid UTF-8
|
||||||
|
serializer.serialize_str(unsafe { str::from_utf8_unchecked(&buf[..written]) })
|
||||||
} else {
|
} else {
|
||||||
self.octets().serialize(serializer)
|
self.octets().serialize(serializer)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.122" # remember to update html_root_url
|
version = "1.0.128" # remember to update html_root_url
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ pub fn with_where_predicates_from_fields(
|
|||||||
let predicates = cont
|
let predicates = cont
|
||||||
.data
|
.data
|
||||||
.all_fields()
|
.all_fields()
|
||||||
.flat_map(|field| from_field(&field.attrs))
|
.filter_map(|field| from_field(&field.attrs))
|
||||||
.flat_map(|predicates| predicates.to_vec());
|
.flat_map(|predicates| predicates.to_vec());
|
||||||
|
|
||||||
let mut generics = generics.clone();
|
let mut generics = generics.clone();
|
||||||
@@ -71,7 +71,7 @@ pub fn with_where_predicates_from_variants(
|
|||||||
|
|
||||||
let predicates = variants
|
let predicates = variants
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|variant| from_variant(&variant.attrs))
|
.filter_map(|variant| from_variant(&variant.attrs))
|
||||||
.flat_map(|predicates| predicates.to_vec());
|
.flat_map(|predicates| predicates.to_vec());
|
||||||
|
|
||||||
let mut generics = generics.clone();
|
let mut generics = generics.clone();
|
||||||
|
|||||||
+12
-8
@@ -8,13 +8,17 @@ use bound;
|
|||||||
use dummy;
|
use dummy;
|
||||||
use fragment::{Expr, Fragment, Match, Stmts};
|
use fragment::{Expr, Fragment, Match, Stmts};
|
||||||
use internals::ast::{Container, Data, Field, Style, Variant};
|
use internals::ast::{Container, Data, Field, Style, Variant};
|
||||||
use internals::{attr, ungroup, Ctxt, Derive};
|
use internals::{attr, replace_receiver, ungroup, Ctxt, Derive};
|
||||||
use pretend;
|
use pretend;
|
||||||
|
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result<TokenStream, Vec<syn::Error>> {
|
pub fn expand_derive_deserialize(
|
||||||
|
input: &mut syn::DeriveInput,
|
||||||
|
) -> Result<TokenStream, Vec<syn::Error>> {
|
||||||
|
replace_receiver(input);
|
||||||
|
|
||||||
let ctxt = Ctxt::new();
|
let ctxt = Ctxt::new();
|
||||||
let cont = match Container::from_ast(&ctxt, input, Derive::Deserialize) {
|
let cont = match Container::from_ast(&ctxt, input, Derive::Deserialize) {
|
||||||
Some(cont) => cont,
|
Some(cont) => cont,
|
||||||
@@ -471,7 +475,7 @@ fn deserialize_tuple(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let visit_seq = Stmts(deserialize_seq(
|
let visit_seq = Stmts(deserialize_seq(
|
||||||
&type_path, params, fields, false, cattrs, &expecting,
|
&type_path, params, fields, false, cattrs, expecting,
|
||||||
));
|
));
|
||||||
|
|
||||||
let visitor_expr = quote! {
|
let visitor_expr = quote! {
|
||||||
@@ -557,7 +561,7 @@ fn deserialize_tuple_in_place(
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, &expecting));
|
let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, expecting));
|
||||||
|
|
||||||
let visitor_expr = quote! {
|
let visitor_expr = quote! {
|
||||||
__Visitor {
|
__Visitor {
|
||||||
@@ -918,7 +922,7 @@ fn deserialize_struct(
|
|||||||
let expecting = cattrs.expecting().unwrap_or(&expecting);
|
let expecting = cattrs.expecting().unwrap_or(&expecting);
|
||||||
|
|
||||||
let visit_seq = Stmts(deserialize_seq(
|
let visit_seq = Stmts(deserialize_seq(
|
||||||
&type_path, params, fields, true, cattrs, &expecting,
|
&type_path, params, fields, true, cattrs, expecting,
|
||||||
));
|
));
|
||||||
|
|
||||||
let (field_visitor, fields_stmt, visit_map) = if cattrs.has_flatten() {
|
let (field_visitor, fields_stmt, visit_map) = if cattrs.has_flatten() {
|
||||||
@@ -1059,7 +1063,7 @@ fn deserialize_struct_in_place(
|
|||||||
};
|
};
|
||||||
let expecting = cattrs.expecting().unwrap_or(&expecting);
|
let expecting = cattrs.expecting().unwrap_or(&expecting);
|
||||||
|
|
||||||
let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, &expecting));
|
let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, expecting));
|
||||||
|
|
||||||
let (field_visitor, fields_stmt, visit_map) =
|
let (field_visitor, fields_stmt, visit_map) =
|
||||||
deserialize_struct_as_struct_in_place_visitor(params, fields, cattrs);
|
deserialize_struct_as_struct_in_place_visitor(params, fields, cattrs);
|
||||||
@@ -2083,7 +2087,7 @@ fn deserialize_identifier(
|
|||||||
) -> Fragment {
|
) -> Fragment {
|
||||||
let mut flat_fields = Vec::new();
|
let mut flat_fields = Vec::new();
|
||||||
for (_, ident, aliases) in fields {
|
for (_, ident, aliases) in fields {
|
||||||
flat_fields.extend(aliases.iter().map(|alias| (alias, ident)))
|
flat_fields.extend(aliases.iter().map(|alias| (alias, ident)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let field_strs: &Vec<_> = &flat_fields.iter().map(|(name, _)| name).collect();
|
let field_strs: &Vec<_> = &flat_fields.iter().map(|(name, _)| name).collect();
|
||||||
@@ -2281,7 +2285,7 @@ fn deserialize_identifier(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let visit_borrowed = if fallthrough_borrowed.is_some() || collect_other_fields {
|
let visit_borrowed = if fallthrough_borrowed.is_some() || collect_other_fields {
|
||||||
let fallthrough_borrowed_arm = fallthrough_borrowed.as_ref().unwrap_or(&fallthrough_arm);
|
let fallthrough_borrowed_arm = fallthrough_borrowed.as_ref().unwrap_or(fallthrough_arm);
|
||||||
Some(quote! {
|
Some(quote! {
|
||||||
fn visit_borrowed_str<__E>(self, __value: &'de str) -> _serde::__private::Result<Self::Value, __E>
|
fn visit_borrowed_str<__E>(self, __value: &'de str) -> _serde::__private::Result<Self::Value, __E>
|
||||||
where
|
where
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ pub fn wrap_in_const(
|
|||||||
use #path as _serde;
|
use #path as _serde;
|
||||||
},
|
},
|
||||||
None => quote! {
|
None => quote! {
|
||||||
#[allow(rust_2018_idioms, clippy::useless_attribute)]
|
#[allow(unused_extern_crates, clippy::useless_attribute)]
|
||||||
extern crate serde as _serde;
|
extern crate serde as _serde;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ pub struct Container<'a> {
|
|||||||
|
|
||||||
/// The fields of a struct or enum.
|
/// The fields of a struct or enum.
|
||||||
///
|
///
|
||||||
/// Analagous to `syn::Data`.
|
/// Analogous to `syn::Data`.
|
||||||
pub enum Data<'a> {
|
pub enum Data<'a> {
|
||||||
Enum(Vec<Variant<'a>>),
|
Enum(Vec<Variant<'a>>),
|
||||||
Struct(Style, Vec<Field<'a>>),
|
Struct(Style, Vec<Field<'a>>),
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
use internals::respan::respan;
|
||||||
use internals::symbol::*;
|
use internals::symbol::*;
|
||||||
use internals::{ungroup, Ctxt};
|
use internals::{ungroup, Ctxt};
|
||||||
use proc_macro2::{Group, Span, TokenStream, TokenTree};
|
use proc_macro2::{Spacing, Span, TokenStream, TokenTree};
|
||||||
use quote::ToTokens;
|
use quote::ToTokens;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
@@ -555,7 +556,7 @@ impl Container {
|
|||||||
// Parse `#[serde(crate = "foo")]`
|
// Parse `#[serde(crate = "foo")]`
|
||||||
Meta(NameValue(m)) if m.path == CRATE => {
|
Meta(NameValue(m)) if m.path == CRATE => {
|
||||||
if let Ok(path) = parse_lit_into_path(cx, CRATE, &m.lit) {
|
if let Ok(path) = parse_lit_into_path(cx, CRATE, &m.lit) {
|
||||||
serde_path.set(&m.path, path)
|
serde_path.set(&m.path, path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1608,7 +1609,7 @@ fn get_lit_str2<'a>(
|
|||||||
fn parse_lit_into_path(cx: &Ctxt, attr_name: Symbol, lit: &syn::Lit) -> Result<syn::Path, ()> {
|
fn parse_lit_into_path(cx: &Ctxt, attr_name: Symbol, lit: &syn::Lit) -> Result<syn::Path, ()> {
|
||||||
let string = get_lit_str(cx, attr_name, lit)?;
|
let string = get_lit_str(cx, attr_name, lit)?;
|
||||||
parse_lit_str(string).map_err(|_| {
|
parse_lit_str(string).map_err(|_| {
|
||||||
cx.error_spanned_by(lit, format!("failed to parse path: {:?}", string.value()))
|
cx.error_spanned_by(lit, format!("failed to parse path: {:?}", string.value()));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1619,7 +1620,7 @@ fn parse_lit_into_expr_path(
|
|||||||
) -> Result<syn::ExprPath, ()> {
|
) -> Result<syn::ExprPath, ()> {
|
||||||
let string = get_lit_str(cx, attr_name, lit)?;
|
let string = get_lit_str(cx, attr_name, lit)?;
|
||||||
parse_lit_str(string).map_err(|_| {
|
parse_lit_str(string).map_err(|_| {
|
||||||
cx.error_spanned_by(lit, format!("failed to parse path: {:?}", string.value()))
|
cx.error_spanned_by(lit, format!("failed to parse path: {:?}", string.value()));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1648,7 +1649,7 @@ fn parse_lit_into_ty(cx: &Ctxt, attr_name: Symbol, lit: &syn::Lit) -> Result<syn
|
|||||||
cx.error_spanned_by(
|
cx.error_spanned_by(
|
||||||
lit,
|
lit,
|
||||||
format!("failed to parse type: {} = {:?}", attr_name, string.value()),
|
format!("failed to parse type: {} = {:?}", attr_name, string.value()),
|
||||||
)
|
);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1901,14 +1902,41 @@ fn collect_lifetimes(ty: &syn::Type, out: &mut BTreeSet<syn::Lifetime>) {
|
|||||||
syn::Type::Group(ty) => {
|
syn::Type::Group(ty) => {
|
||||||
collect_lifetimes(&ty.elem, out);
|
collect_lifetimes(&ty.elem, out);
|
||||||
}
|
}
|
||||||
|
syn::Type::Macro(ty) => {
|
||||||
|
collect_lifetimes_from_tokens(ty.mac.tokens.clone(), out);
|
||||||
|
}
|
||||||
syn::Type::BareFn(_)
|
syn::Type::BareFn(_)
|
||||||
| syn::Type::Never(_)
|
| syn::Type::Never(_)
|
||||||
| syn::Type::TraitObject(_)
|
| syn::Type::TraitObject(_)
|
||||||
| syn::Type::ImplTrait(_)
|
| syn::Type::ImplTrait(_)
|
||||||
| syn::Type::Infer(_)
|
| syn::Type::Infer(_)
|
||||||
| syn::Type::Macro(_)
|
| syn::Type::Verbatim(_) => {}
|
||||||
| syn::Type::Verbatim(_)
|
|
||||||
| _ => {}
|
#[cfg(test)]
|
||||||
|
syn::Type::__TestExhaustive(_) => unimplemented!(),
|
||||||
|
#[cfg(not(test))]
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn collect_lifetimes_from_tokens(tokens: TokenStream, out: &mut BTreeSet<syn::Lifetime>) {
|
||||||
|
let mut iter = tokens.into_iter();
|
||||||
|
while let Some(tt) = iter.next() {
|
||||||
|
match &tt {
|
||||||
|
TokenTree::Punct(op) if op.as_char() == '\'' && op.spacing() == Spacing::Joint => {
|
||||||
|
if let Some(TokenTree::Ident(ident)) = iter.next() {
|
||||||
|
out.insert(syn::Lifetime {
|
||||||
|
apostrophe: op.span(),
|
||||||
|
ident,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TokenTree::Group(group) => {
|
||||||
|
let tokens = group.stream();
|
||||||
|
collect_lifetimes_from_tokens(tokens, out);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1922,20 +1950,5 @@ where
|
|||||||
|
|
||||||
fn spanned_tokens(s: &syn::LitStr) -> parse::Result<TokenStream> {
|
fn spanned_tokens(s: &syn::LitStr) -> parse::Result<TokenStream> {
|
||||||
let stream = syn::parse_str(&s.value())?;
|
let stream = syn::parse_str(&s.value())?;
|
||||||
Ok(respan_token_stream(stream, s.span()))
|
Ok(respan(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(mut token: TokenTree, span: Span) -> TokenTree {
|
|
||||||
if let TokenTree::Group(g) = &mut token {
|
|
||||||
*g = Group::new(g.delimiter(), respan_token_stream(g.stream(), span));
|
|
||||||
}
|
|
||||||
token.set_span(span);
|
|
||||||
token
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -260,7 +260,7 @@ fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) {
|
|||||||
cx.error_spanned_by(
|
cx.error_spanned_by(
|
||||||
cont.original,
|
cont.original,
|
||||||
format!("variant field name `{}` conflicts with internal tag", tag),
|
format!("variant field name `{}` conflicts with internal tag", tag),
|
||||||
)
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
for variant in variants {
|
for variant in variants {
|
||||||
@@ -396,7 +396,7 @@ fn member_message(member: &Member) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn allow_transparent(field: &Field, derive: Derive) -> bool {
|
fn allow_transparent(field: &Field, derive: Derive) -> bool {
|
||||||
if let Type::Path(ty) = ungroup(&field.ty) {
|
if let Type::Path(ty) = ungroup(field.ty) {
|
||||||
if let Some(seg) = ty.path.segments.last() {
|
if let Some(seg) = ty.path.segments.last() {
|
||||||
if seg.ident == "PhantomData" {
|
if seg.ident == "PhantomData" {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -4,8 +4,12 @@ pub mod attr;
|
|||||||
mod ctxt;
|
mod ctxt;
|
||||||
pub use self::ctxt::Ctxt;
|
pub use self::ctxt::Ctxt;
|
||||||
|
|
||||||
|
mod receiver;
|
||||||
|
pub use self::receiver::replace_receiver;
|
||||||
|
|
||||||
mod case;
|
mod case;
|
||||||
mod check;
|
mod check;
|
||||||
|
mod respan;
|
||||||
mod symbol;
|
mod symbol;
|
||||||
|
|
||||||
use syn::Type;
|
use syn::Type;
|
||||||
|
|||||||
@@ -0,0 +1,287 @@
|
|||||||
|
use internals::respan::respan;
|
||||||
|
use proc_macro2::Span;
|
||||||
|
use quote::ToTokens;
|
||||||
|
use std::mem;
|
||||||
|
use syn::punctuated::Punctuated;
|
||||||
|
use syn::{
|
||||||
|
parse_quote, Data, DeriveInput, Expr, ExprPath, GenericArgument, GenericParam, Generics, Macro,
|
||||||
|
Path, PathArguments, QSelf, ReturnType, Type, TypeParamBound, TypePath, WherePredicate,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn replace_receiver(input: &mut DeriveInput) {
|
||||||
|
let self_ty = {
|
||||||
|
let ident = &input.ident;
|
||||||
|
let ty_generics = input.generics.split_for_impl().1;
|
||||||
|
parse_quote!(#ident #ty_generics)
|
||||||
|
};
|
||||||
|
let mut visitor = ReplaceReceiver(&self_ty);
|
||||||
|
visitor.visit_generics_mut(&mut input.generics);
|
||||||
|
visitor.visit_data_mut(&mut input.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ReplaceReceiver<'a>(&'a TypePath);
|
||||||
|
|
||||||
|
impl ReplaceReceiver<'_> {
|
||||||
|
fn self_ty(&self, span: Span) -> TypePath {
|
||||||
|
let tokens = self.0.to_token_stream();
|
||||||
|
let respanned = respan(tokens, span);
|
||||||
|
syn::parse2(respanned).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn self_to_qself(&self, qself: &mut Option<QSelf>, path: &mut Path) {
|
||||||
|
if path.leading_colon.is_some() || path.segments[0].ident != "Self" {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if path.segments.len() == 1 {
|
||||||
|
self.self_to_expr_path(path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let span = path.segments[0].ident.span();
|
||||||
|
*qself = Some(QSelf {
|
||||||
|
lt_token: Token,
|
||||||
|
ty: Box::new(Type::Path(self.self_ty(span))),
|
||||||
|
position: 0,
|
||||||
|
as_token: None,
|
||||||
|
gt_token: Token,
|
||||||
|
});
|
||||||
|
|
||||||
|
path.leading_colon = Some(**path.segments.pairs().next().unwrap().punct().unwrap());
|
||||||
|
|
||||||
|
let segments = mem::replace(&mut path.segments, Punctuated::new());
|
||||||
|
path.segments = segments.into_pairs().skip(1).collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn self_to_expr_path(&self, path: &mut Path) {
|
||||||
|
let self_ty = self.self_ty(path.segments[0].ident.span());
|
||||||
|
let variant = mem::replace(path, self_ty.path);
|
||||||
|
for segment in &mut path.segments {
|
||||||
|
if let PathArguments::AngleBracketed(bracketed) = &mut segment.arguments {
|
||||||
|
if bracketed.colon2_token.is_none() && !bracketed.args.is_empty() {
|
||||||
|
bracketed.colon2_token = Some(<Token![::]>::default());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if variant.segments.len() > 1 {
|
||||||
|
path.segments.push_punct(<Token![::]>::default());
|
||||||
|
path.segments.extend(variant.segments.into_pairs().skip(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ReplaceReceiver<'_> {
|
||||||
|
// `Self` -> `Receiver`
|
||||||
|
fn visit_type_mut(&mut self, ty: &mut Type) {
|
||||||
|
let span = if let Type::Path(node) = ty {
|
||||||
|
if node.qself.is_none() && node.path.is_ident("Self") {
|
||||||
|
node.path.segments[0].ident.span()
|
||||||
|
} else {
|
||||||
|
self.visit_type_path_mut(node);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.visit_type_mut_impl(ty);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
*ty = self.self_ty(span).into();
|
||||||
|
}
|
||||||
|
|
||||||
|
// `Self::Assoc` -> `<Receiver>::Assoc`
|
||||||
|
fn visit_type_path_mut(&mut self, ty: &mut TypePath) {
|
||||||
|
if ty.qself.is_none() {
|
||||||
|
self.self_to_qself(&mut ty.qself, &mut ty.path);
|
||||||
|
}
|
||||||
|
self.visit_type_path_mut_impl(ty);
|
||||||
|
}
|
||||||
|
|
||||||
|
// `Self::method` -> `<Receiver>::method`
|
||||||
|
fn visit_expr_path_mut(&mut self, expr: &mut ExprPath) {
|
||||||
|
if expr.qself.is_none() {
|
||||||
|
self.self_to_qself(&mut expr.qself, &mut expr.path);
|
||||||
|
}
|
||||||
|
self.visit_expr_path_mut_impl(expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Everything below is simply traversing the syntax tree.
|
||||||
|
|
||||||
|
fn visit_type_mut_impl(&mut self, ty: &mut Type) {
|
||||||
|
match ty {
|
||||||
|
Type::Array(ty) => {
|
||||||
|
self.visit_type_mut(&mut ty.elem);
|
||||||
|
self.visit_expr_mut(&mut ty.len);
|
||||||
|
}
|
||||||
|
Type::BareFn(ty) => {
|
||||||
|
for arg in &mut ty.inputs {
|
||||||
|
self.visit_type_mut(&mut arg.ty);
|
||||||
|
}
|
||||||
|
self.visit_return_type_mut(&mut ty.output);
|
||||||
|
}
|
||||||
|
Type::Group(ty) => self.visit_type_mut(&mut ty.elem),
|
||||||
|
Type::ImplTrait(ty) => {
|
||||||
|
for bound in &mut ty.bounds {
|
||||||
|
self.visit_type_param_bound_mut(bound);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Type::Macro(ty) => self.visit_macro_mut(&mut ty.mac),
|
||||||
|
Type::Paren(ty) => self.visit_type_mut(&mut ty.elem),
|
||||||
|
Type::Path(ty) => {
|
||||||
|
if let Some(qself) = &mut ty.qself {
|
||||||
|
self.visit_type_mut(&mut qself.ty);
|
||||||
|
}
|
||||||
|
self.visit_path_mut(&mut ty.path);
|
||||||
|
}
|
||||||
|
Type::Ptr(ty) => self.visit_type_mut(&mut ty.elem),
|
||||||
|
Type::Reference(ty) => self.visit_type_mut(&mut ty.elem),
|
||||||
|
Type::Slice(ty) => self.visit_type_mut(&mut ty.elem),
|
||||||
|
Type::TraitObject(ty) => {
|
||||||
|
for bound in &mut ty.bounds {
|
||||||
|
self.visit_type_param_bound_mut(bound);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Type::Tuple(ty) => {
|
||||||
|
for elem in &mut ty.elems {
|
||||||
|
self.visit_type_mut(elem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Type::Infer(_) | Type::Never(_) | Type::Verbatim(_) => {}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
Type::__TestExhaustive(_) => unimplemented!(),
|
||||||
|
#[cfg(not(test))]
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_type_path_mut_impl(&mut self, ty: &mut TypePath) {
|
||||||
|
if let Some(qself) = &mut ty.qself {
|
||||||
|
self.visit_type_mut(&mut qself.ty);
|
||||||
|
}
|
||||||
|
self.visit_path_mut(&mut ty.path);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_expr_path_mut_impl(&mut self, expr: &mut ExprPath) {
|
||||||
|
if let Some(qself) = &mut expr.qself {
|
||||||
|
self.visit_type_mut(&mut qself.ty);
|
||||||
|
}
|
||||||
|
self.visit_path_mut(&mut expr.path);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_path_mut(&mut self, path: &mut Path) {
|
||||||
|
for segment in &mut path.segments {
|
||||||
|
self.visit_path_arguments_mut(&mut segment.arguments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_path_arguments_mut(&mut self, arguments: &mut PathArguments) {
|
||||||
|
match arguments {
|
||||||
|
PathArguments::None => {}
|
||||||
|
PathArguments::AngleBracketed(arguments) => {
|
||||||
|
for arg in &mut arguments.args {
|
||||||
|
match arg {
|
||||||
|
GenericArgument::Type(arg) => self.visit_type_mut(arg),
|
||||||
|
GenericArgument::Binding(arg) => self.visit_type_mut(&mut arg.ty),
|
||||||
|
GenericArgument::Lifetime(_)
|
||||||
|
| GenericArgument::Constraint(_)
|
||||||
|
| GenericArgument::Const(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PathArguments::Parenthesized(arguments) => {
|
||||||
|
for argument in &mut arguments.inputs {
|
||||||
|
self.visit_type_mut(argument);
|
||||||
|
}
|
||||||
|
self.visit_return_type_mut(&mut arguments.output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_return_type_mut(&mut self, return_type: &mut ReturnType) {
|
||||||
|
match return_type {
|
||||||
|
ReturnType::Default => {}
|
||||||
|
ReturnType::Type(_, output) => self.visit_type_mut(output),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_type_param_bound_mut(&mut self, bound: &mut TypeParamBound) {
|
||||||
|
match bound {
|
||||||
|
TypeParamBound::Trait(bound) => self.visit_path_mut(&mut bound.path),
|
||||||
|
TypeParamBound::Lifetime(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_generics_mut(&mut self, generics: &mut Generics) {
|
||||||
|
for param in &mut generics.params {
|
||||||
|
match param {
|
||||||
|
GenericParam::Type(param) => {
|
||||||
|
for bound in &mut param.bounds {
|
||||||
|
self.visit_type_param_bound_mut(bound);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GenericParam::Lifetime(_) | GenericParam::Const(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(where_clause) = &mut generics.where_clause {
|
||||||
|
for predicate in &mut where_clause.predicates {
|
||||||
|
match predicate {
|
||||||
|
WherePredicate::Type(predicate) => {
|
||||||
|
self.visit_type_mut(&mut predicate.bounded_ty);
|
||||||
|
for bound in &mut predicate.bounds {
|
||||||
|
self.visit_type_param_bound_mut(bound);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WherePredicate::Lifetime(_) | WherePredicate::Eq(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_data_mut(&mut self, data: &mut Data) {
|
||||||
|
match data {
|
||||||
|
Data::Struct(data) => {
|
||||||
|
for field in &mut data.fields {
|
||||||
|
self.visit_type_mut(&mut field.ty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Data::Enum(data) => {
|
||||||
|
for variant in &mut data.variants {
|
||||||
|
for field in &mut variant.fields {
|
||||||
|
self.visit_type_mut(&mut field.ty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Data::Union(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_expr_mut(&mut self, expr: &mut Expr) {
|
||||||
|
match expr {
|
||||||
|
Expr::Binary(expr) => {
|
||||||
|
self.visit_expr_mut(&mut expr.left);
|
||||||
|
self.visit_expr_mut(&mut expr.right);
|
||||||
|
}
|
||||||
|
Expr::Call(expr) => {
|
||||||
|
self.visit_expr_mut(&mut expr.func);
|
||||||
|
for arg in &mut expr.args {
|
||||||
|
self.visit_expr_mut(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Expr::Cast(expr) => {
|
||||||
|
self.visit_expr_mut(&mut expr.expr);
|
||||||
|
self.visit_type_mut(&mut expr.ty);
|
||||||
|
}
|
||||||
|
Expr::Field(expr) => self.visit_expr_mut(&mut expr.base),
|
||||||
|
Expr::Index(expr) => {
|
||||||
|
self.visit_expr_mut(&mut expr.expr);
|
||||||
|
self.visit_expr_mut(&mut expr.index);
|
||||||
|
}
|
||||||
|
Expr::Paren(expr) => self.visit_expr_mut(&mut expr.expr),
|
||||||
|
Expr::Path(expr) => self.visit_expr_path_mut(expr),
|
||||||
|
Expr::Unary(expr) => self.visit_expr_mut(&mut expr.expr),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_macro_mut(&mut self, _mac: &mut Macro) {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
use proc_macro2::{Group, Span, TokenStream, TokenTree};
|
||||||
|
|
||||||
|
pub(crate) fn respan(stream: TokenStream, span: Span) -> TokenStream {
|
||||||
|
stream
|
||||||
|
.into_iter()
|
||||||
|
.map(|token| respan_token(token, span))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn respan_token(mut token: TokenTree, span: Span) -> TokenTree {
|
||||||
|
if let TokenTree::Group(g) = &mut token {
|
||||||
|
*g = Group::new(g.delimiter(), respan(g.stream(), span));
|
||||||
|
}
|
||||||
|
token.set_span(span);
|
||||||
|
token
|
||||||
|
}
|
||||||
+14
-6
@@ -13,13 +13,19 @@
|
|||||||
//!
|
//!
|
||||||
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
|
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
|
||||||
|
|
||||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.122")]
|
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.128")]
|
||||||
#![allow(unknown_lints, bare_trait_objects)]
|
#![allow(unknown_lints, bare_trait_objects)]
|
||||||
#![deny(clippy::all, clippy::pedantic)]
|
#![deny(clippy::all, clippy::pedantic)]
|
||||||
// Ignored clippy lints
|
// Ignored clippy lints
|
||||||
#![allow(
|
#![allow(
|
||||||
|
// clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054
|
||||||
|
clippy::branches_sharing_code,
|
||||||
clippy::cognitive_complexity,
|
clippy::cognitive_complexity,
|
||||||
|
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/7575
|
||||||
|
clippy::collapsible_match,
|
||||||
clippy::enum_variant_names,
|
clippy::enum_variant_names,
|
||||||
|
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/6797
|
||||||
|
clippy::manual_map,
|
||||||
clippy::match_like_matches_macro,
|
clippy::match_like_matches_macro,
|
||||||
clippy::needless_pass_by_value,
|
clippy::needless_pass_by_value,
|
||||||
clippy::too_many_arguments,
|
clippy::too_many_arguments,
|
||||||
@@ -35,11 +41,13 @@
|
|||||||
clippy::checked_conversions,
|
clippy::checked_conversions,
|
||||||
clippy::doc_markdown,
|
clippy::doc_markdown,
|
||||||
clippy::enum_glob_use,
|
clippy::enum_glob_use,
|
||||||
clippy::filter_map,
|
|
||||||
clippy::indexing_slicing,
|
clippy::indexing_slicing,
|
||||||
clippy::items_after_statements,
|
clippy::items_after_statements,
|
||||||
|
clippy::let_underscore_drop,
|
||||||
clippy::map_err_ignore,
|
clippy::map_err_ignore,
|
||||||
clippy::match_same_arms,
|
clippy::match_same_arms,
|
||||||
|
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/6984
|
||||||
|
clippy::match_wildcard_for_single_variants,
|
||||||
clippy::module_name_repetitions,
|
clippy::module_name_repetitions,
|
||||||
clippy::must_use_candidate,
|
clippy::must_use_candidate,
|
||||||
clippy::option_if_let_else,
|
clippy::option_if_let_else,
|
||||||
@@ -79,16 +87,16 @@ mod try;
|
|||||||
|
|
||||||
#[proc_macro_derive(Serialize, attributes(serde))]
|
#[proc_macro_derive(Serialize, attributes(serde))]
|
||||||
pub fn derive_serialize(input: TokenStream) -> TokenStream {
|
pub fn derive_serialize(input: TokenStream) -> TokenStream {
|
||||||
let input = parse_macro_input!(input as DeriveInput);
|
let mut input = parse_macro_input!(input as DeriveInput);
|
||||||
ser::expand_derive_serialize(&input)
|
ser::expand_derive_serialize(&mut input)
|
||||||
.unwrap_or_else(to_compile_errors)
|
.unwrap_or_else(to_compile_errors)
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro_derive(Deserialize, attributes(serde))]
|
#[proc_macro_derive(Deserialize, attributes(serde))]
|
||||||
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
|
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
|
||||||
let input = parse_macro_input!(input as DeriveInput);
|
let mut input = parse_macro_input!(input as DeriveInput);
|
||||||
de::expand_derive_deserialize(&input)
|
de::expand_derive_deserialize(&mut input)
|
||||||
.unwrap_or_else(to_compile_errors)
|
.unwrap_or_else(to_compile_errors)
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,10 +6,14 @@ use bound;
|
|||||||
use dummy;
|
use dummy;
|
||||||
use fragment::{Fragment, Match, Stmts};
|
use fragment::{Fragment, Match, Stmts};
|
||||||
use internals::ast::{Container, Data, Field, Style, Variant};
|
use internals::ast::{Container, Data, Field, Style, Variant};
|
||||||
use internals::{attr, Ctxt, Derive};
|
use internals::{attr, replace_receiver, Ctxt, Derive};
|
||||||
use pretend;
|
use pretend;
|
||||||
|
|
||||||
pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<TokenStream, Vec<syn::Error>> {
|
pub fn expand_derive_serialize(
|
||||||
|
input: &mut syn::DeriveInput,
|
||||||
|
) -> Result<TokenStream, Vec<syn::Error>> {
|
||||||
|
replace_receiver(input);
|
||||||
|
|
||||||
let ctxt = Ctxt::new();
|
let ctxt = Ctxt::new();
|
||||||
let cont = match Container::from_ast(&ctxt, input, Derive::Serialize) {
|
let cont = match Container::from_ast(&ctxt, input, Derive::Serialize) {
|
||||||
Some(cont) => cont,
|
Some(cont) => cont,
|
||||||
@@ -1095,7 +1099,7 @@ fn serialize_struct_visitor(
|
|||||||
let mut field_expr = if is_enum {
|
let mut field_expr = if is_enum {
|
||||||
quote!(#member)
|
quote!(#member)
|
||||||
} else {
|
} else {
|
||||||
get_member(params, field, &member)
|
get_member(params, field, member)
|
||||||
};
|
};
|
||||||
|
|
||||||
let key_expr = field.attrs.name().serialize_name();
|
let key_expr = field.attrs.name().serialize_name();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde_derive_internals"
|
name = "serde_derive_internals"
|
||||||
version = "0.25.0" # remember to update html_root_url
|
version = "0.26.0" # remember to update html_root_url
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
description = "AST representation used by Serde derive macros. Unstable."
|
description = "AST representation used by Serde derive macros. Unstable."
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Sometimes on Windows the git checkout does not correctly wire up the
|
||||||
|
// symlink from serde_derive_internals/src to serde_derive/src/internals.
|
||||||
|
// When this happens we'll just build based on relative paths within the git
|
||||||
|
// repo.
|
||||||
|
let mod_behind_symlink = Path::new("src/mod.rs");
|
||||||
|
if !mod_behind_symlink.exists() {
|
||||||
|
println!("cargo:rustc-cfg=serde_build_from_git");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,14 @@
|
|||||||
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.25.0")]
|
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.26.0")]
|
||||||
#![allow(unknown_lints, bare_trait_objects)]
|
#![allow(unknown_lints, bare_trait_objects)]
|
||||||
#![deny(clippy::all, clippy::pedantic)]
|
#![deny(clippy::all, clippy::pedantic)]
|
||||||
// Ignored clippy lints
|
// Ignored clippy lints
|
||||||
#![allow(
|
#![allow(
|
||||||
clippy::cognitive_complexity,
|
clippy::cognitive_complexity,
|
||||||
|
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/7575
|
||||||
|
clippy::collapsible_match,
|
||||||
|
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/6797
|
||||||
|
clippy::manual_map,
|
||||||
|
clippy::missing_panics_doc,
|
||||||
clippy::redundant_field_names,
|
clippy::redundant_field_names,
|
||||||
clippy::result_unit_err,
|
clippy::result_unit_err,
|
||||||
clippy::should_implement_trait,
|
clippy::should_implement_trait,
|
||||||
@@ -17,11 +22,17 @@
|
|||||||
clippy::doc_markdown,
|
clippy::doc_markdown,
|
||||||
clippy::enum_glob_use,
|
clippy::enum_glob_use,
|
||||||
clippy::items_after_statements,
|
clippy::items_after_statements,
|
||||||
|
clippy::let_underscore_drop,
|
||||||
clippy::match_same_arms,
|
clippy::match_same_arms,
|
||||||
|
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/6984
|
||||||
|
clippy::match_wildcard_for_single_variants,
|
||||||
clippy::missing_errors_doc,
|
clippy::missing_errors_doc,
|
||||||
|
clippy::module_name_repetitions,
|
||||||
clippy::must_use_candidate,
|
clippy::must_use_candidate,
|
||||||
|
clippy::similar_names,
|
||||||
clippy::struct_excessive_bools,
|
clippy::struct_excessive_bools,
|
||||||
clippy::too_many_lines,
|
clippy::too_many_lines,
|
||||||
|
clippy::unused_self,
|
||||||
clippy::wildcard_imports
|
clippy::wildcard_imports
|
||||||
)]
|
)]
|
||||||
|
|
||||||
@@ -31,7 +42,8 @@ extern crate syn;
|
|||||||
extern crate proc_macro2;
|
extern crate proc_macro2;
|
||||||
extern crate quote;
|
extern crate quote;
|
||||||
|
|
||||||
#[path = "src/mod.rs"]
|
#[cfg_attr(serde_build_from_git, path = "../serde_derive/src/internals/mod.rs")]
|
||||||
|
#[cfg_attr(not(serde_build_from_git), path = "src/mod.rs")]
|
||||||
mod internals;
|
mod internals;
|
||||||
|
|
||||||
pub use internals::*;
|
pub use internals::*;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde_test"
|
name = "serde_test"
|
||||||
version = "1.0.122" # remember to update html_root_url
|
version = "1.0.128" # remember to update html_root_url
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
description = "Token De/Serializer for testing De/Serialize implementations"
|
description = "Token De/Serializer for testing De/Serialize implementations"
|
||||||
|
|||||||
@@ -144,7 +144,7 @@
|
|||||||
//! # }
|
//! # }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.122")]
|
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.128")]
|
||||||
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
|
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
|
||||||
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
|
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
|
||||||
// Ignored clippy lints
|
// Ignored clippy lints
|
||||||
@@ -153,8 +153,10 @@
|
|||||||
#![cfg_attr(
|
#![cfg_attr(
|
||||||
feature = "cargo-clippy",
|
feature = "cargo-clippy",
|
||||||
allow(
|
allow(
|
||||||
|
cloned_instead_of_copied,
|
||||||
empty_line_after_outer_attr,
|
empty_line_after_outer_attr,
|
||||||
missing_docs_in_private_items,
|
missing_docs_in_private_items,
|
||||||
|
missing_panics_doc,
|
||||||
module_name_repetitions,
|
module_name_repetitions,
|
||||||
must_use_candidate,
|
must_use_candidate,
|
||||||
redundant_field_names,
|
redundant_field_names,
|
||||||
|
|||||||
@@ -32,18 +32,18 @@ impl<'a> Serializer<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! assert_next_token {
|
macro_rules! assert_next_token {
|
||||||
($ser:expr, $actual:ident) => {
|
($ser:expr, $actual:ident) => {{
|
||||||
assert_next_token!($ser, stringify!($actual), Token::$actual, true);
|
assert_next_token!($ser, stringify!($actual), Token::$actual, true);
|
||||||
};
|
}};
|
||||||
($ser:expr, $actual:ident($v:expr)) => {
|
($ser:expr, $actual:ident($v:expr)) => {{
|
||||||
assert_next_token!(
|
assert_next_token!(
|
||||||
$ser,
|
$ser,
|
||||||
format_args!(concat!(stringify!($actual), "({:?})"), $v),
|
format_args!(concat!(stringify!($actual), "({:?})"), $v),
|
||||||
Token::$actual(v),
|
Token::$actual(v),
|
||||||
v == $v
|
v == $v
|
||||||
);
|
);
|
||||||
};
|
}};
|
||||||
($ser:expr, $actual:ident { $($k:ident),* }) => {
|
($ser:expr, $actual:ident { $($k:ident),* }) => {{
|
||||||
let compare = ($($k,)*);
|
let compare = ($($k,)*);
|
||||||
let field_format = || {
|
let field_format = || {
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
@@ -59,7 +59,7 @@ macro_rules! assert_next_token {
|
|||||||
Token::$actual { $($k),* },
|
Token::$actual { $($k),* },
|
||||||
($($k,)*) == compare
|
($($k,)*) == compare
|
||||||
);
|
);
|
||||||
};
|
}};
|
||||||
($ser:expr, $actual:expr, $pat:pat, $guard:expr) => {
|
($ser:expr, $actual:expr, $pat:pat, $guard:expr) => {
|
||||||
match $ser.next_token() {
|
match $ser.next_token() {
|
||||||
Some($pat) if $guard => {}
|
Some($pat) if $guard => {}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ enum DeEnum<B, C, D> {
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||||
const _: () = {
|
const _: () = {
|
||||||
#[allow(rust_2018_idioms, clippy::useless_attribute)]
|
#[allow(unused_extern_crates, clippy::useless_attribute)]
|
||||||
extern crate serde as _serde;
|
extern crate serde as _serde;
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl<B, C, D> _serde::Serialize for DeEnum<B, C, D>
|
impl<B, C, D> _serde::Serialize for DeEnum<B, C, D>
|
||||||
@@ -265,7 +265,7 @@ const _: () = {
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||||
const _: () = {
|
const _: () = {
|
||||||
#[allow(rust_2018_idioms, clippy::useless_attribute)]
|
#[allow(unused_extern_crates, clippy::useless_attribute)]
|
||||||
extern crate serde as _serde;
|
extern crate serde as _serde;
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl<'de, B, C, D> _serde::Deserialize<'de> for DeEnum<B, C, D>
|
impl<'de, B, C, D> _serde::Deserialize<'de> for DeEnum<B, C, D>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ struct DefaultTyParam<T: AssociatedType<X = i32> = i32> {
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||||
const _: () = {
|
const _: () = {
|
||||||
#[allow(rust_2018_idioms, clippy::useless_attribute)]
|
#[allow(unused_extern_crates, clippy::useless_attribute)]
|
||||||
extern crate serde as _serde;
|
extern crate serde as _serde;
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl<T: AssociatedType<X = i32>> _serde::Serialize for DefaultTyParam<T> {
|
impl<T: AssociatedType<X = i32>> _serde::Serialize for DefaultTyParam<T> {
|
||||||
@@ -49,7 +49,7 @@ const _: () = {
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||||
const _: () = {
|
const _: () = {
|
||||||
#[allow(rust_2018_idioms, clippy::useless_attribute)]
|
#[allow(unused_extern_crates, clippy::useless_attribute)]
|
||||||
extern crate serde as _serde;
|
extern crate serde as _serde;
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl<'de, T: AssociatedType<X = i32>> _serde::Deserialize<'de> for DefaultTyParam<T> {
|
impl<'de, T: AssociatedType<X = i32>> _serde::Deserialize<'de> for DefaultTyParam<T> {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ pub enum GenericEnum<T, U> {
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||||
const _: () = {
|
const _: () = {
|
||||||
#[allow(rust_2018_idioms, clippy::useless_attribute)]
|
#[allow(unused_extern_crates, clippy::useless_attribute)]
|
||||||
extern crate serde as _serde;
|
extern crate serde as _serde;
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl<T, U> _serde::Serialize for GenericEnum<T, U>
|
impl<T, U> _serde::Serialize for GenericEnum<T, U>
|
||||||
@@ -114,7 +114,7 @@ const _: () = {
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||||
const _: () = {
|
const _: () = {
|
||||||
#[allow(rust_2018_idioms, clippy::useless_attribute)]
|
#[allow(unused_extern_crates, clippy::useless_attribute)]
|
||||||
extern crate serde as _serde;
|
extern crate serde as _serde;
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl<'de, T, U> _serde::Deserialize<'de> for GenericEnum<T, U>
|
impl<'de, T, U> _serde::Deserialize<'de> for GenericEnum<T, U>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ pub struct GenericStruct<T> {
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||||
const _: () = {
|
const _: () = {
|
||||||
#[allow(rust_2018_idioms, clippy::useless_attribute)]
|
#[allow(unused_extern_crates, clippy::useless_attribute)]
|
||||||
extern crate serde as _serde;
|
extern crate serde as _serde;
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl<T> _serde::Serialize for GenericStruct<T>
|
impl<T> _serde::Serialize for GenericStruct<T>
|
||||||
@@ -42,7 +42,7 @@ const _: () = {
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||||
const _: () = {
|
const _: () = {
|
||||||
#[allow(rust_2018_idioms, clippy::useless_attribute)]
|
#[allow(unused_extern_crates, clippy::useless_attribute)]
|
||||||
extern crate serde as _serde;
|
extern crate serde as _serde;
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl<'de, T> _serde::Deserialize<'de> for GenericStruct<T>
|
impl<'de, T> _serde::Deserialize<'de> for GenericStruct<T>
|
||||||
@@ -410,7 +410,7 @@ pub struct GenericNewTypeStruct<T>(T);
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||||
const _: () = {
|
const _: () = {
|
||||||
#[allow(rust_2018_idioms, clippy::useless_attribute)]
|
#[allow(unused_extern_crates, clippy::useless_attribute)]
|
||||||
extern crate serde as _serde;
|
extern crate serde as _serde;
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl<T> _serde::Serialize for GenericNewTypeStruct<T>
|
impl<T> _serde::Serialize for GenericNewTypeStruct<T>
|
||||||
@@ -435,7 +435,7 @@ const _: () = {
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||||
const _: () = {
|
const _: () = {
|
||||||
#[allow(rust_2018_idioms, clippy::useless_attribute)]
|
#[allow(unused_extern_crates, clippy::useless_attribute)]
|
||||||
extern crate serde as _serde;
|
extern crate serde as _serde;
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl<'de, T> _serde::Deserialize<'de> for GenericNewTypeStruct<T>
|
impl<'de, T> _serde::Deserialize<'de> for GenericNewTypeStruct<T>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ pub struct GenericTupleStruct<T, U>(T, U);
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||||
const _: () = {
|
const _: () = {
|
||||||
#[allow(rust_2018_idioms, clippy::useless_attribute)]
|
#[allow(unused_extern_crates, clippy::useless_attribute)]
|
||||||
extern crate serde as _serde;
|
extern crate serde as _serde;
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl<'de, T, U> _serde::Deserialize<'de> for GenericTupleStruct<T, U>
|
impl<'de, T, U> _serde::Deserialize<'de> for GenericTupleStruct<T, U>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ enum Lifetimes<'a> {
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||||
const _: () = {
|
const _: () = {
|
||||||
#[allow(rust_2018_idioms, clippy::useless_attribute)]
|
#[allow(unused_extern_crates, clippy::useless_attribute)]
|
||||||
extern crate serde as _serde;
|
extern crate serde as _serde;
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl<'a> _serde::Serialize for Lifetimes<'a> {
|
impl<'a> _serde::Serialize for Lifetimes<'a> {
|
||||||
@@ -95,7 +95,7 @@ const _: () = {
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||||
const _: () = {
|
const _: () = {
|
||||||
#[allow(rust_2018_idioms, clippy::useless_attribute)]
|
#[allow(unused_extern_crates, clippy::useless_attribute)]
|
||||||
extern crate serde as _serde;
|
extern crate serde as _serde;
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl<'de, 'a> _serde::Deserialize<'de> for Lifetimes<'a> {
|
impl<'de, 'a> _serde::Deserialize<'de> for Lifetimes<'a> {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ struct SerNamedMap<'a, 'b, A: 'a, B: 'b, C> {
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||||
const _: () = {
|
const _: () = {
|
||||||
#[allow(rust_2018_idioms, clippy::useless_attribute)]
|
#[allow(unused_extern_crates, clippy::useless_attribute)]
|
||||||
extern crate serde as _serde;
|
extern crate serde as _serde;
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl<'a, 'b, A: 'a, B: 'b, C> _serde::Serialize for SerNamedMap<'a, 'b, A, B, C>
|
impl<'a, 'b, A: 'a, B: 'b, C> _serde::Serialize for SerNamedMap<'a, 'b, A, B, C>
|
||||||
@@ -63,7 +63,7 @@ struct DeNamedMap<A, B, C> {
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||||
const _: () = {
|
const _: () = {
|
||||||
#[allow(rust_2018_idioms, clippy::useless_attribute)]
|
#[allow(unused_extern_crates, clippy::useless_attribute)]
|
||||||
extern crate serde as _serde;
|
extern crate serde as _serde;
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl<'de, A, B, C> _serde::Deserialize<'de> for DeNamedMap<A, B, C>
|
impl<'de, A, B, C> _serde::Deserialize<'de> for DeNamedMap<A, B, C>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ struct SerNamedTuple<'a, 'b, A: 'a, B: 'b, C>(&'a A, &'b mut B, C);
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||||
const _: () = {
|
const _: () = {
|
||||||
#[allow(rust_2018_idioms, clippy::useless_attribute)]
|
#[allow(unused_extern_crates, clippy::useless_attribute)]
|
||||||
extern crate serde as _serde;
|
extern crate serde as _serde;
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl<'a, 'b, A: 'a, B: 'b, C> _serde::Serialize for SerNamedTuple<'a, 'b, A, B, C>
|
impl<'a, 'b, A: 'a, B: 'b, C> _serde::Serialize for SerNamedTuple<'a, 'b, A, B, C>
|
||||||
@@ -55,7 +55,7 @@ struct DeNamedTuple<A, B, C>(A, B, C);
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||||
const _: () = {
|
const _: () = {
|
||||||
#[allow(rust_2018_idioms, clippy::useless_attribute)]
|
#[allow(unused_extern_crates, clippy::useless_attribute)]
|
||||||
extern crate serde as _serde;
|
extern crate serde as _serde;
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl<'de, A, B, C> _serde::Deserialize<'de> for DeNamedTuple<A, B, C>
|
impl<'de, A, B, C> _serde::Deserialize<'de> for DeNamedTuple<A, B, C>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ struct NamedUnit;
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||||
const _: () = {
|
const _: () = {
|
||||||
#[allow(rust_2018_idioms, clippy::useless_attribute)]
|
#[allow(unused_extern_crates, clippy::useless_attribute)]
|
||||||
extern crate serde as _serde;
|
extern crate serde as _serde;
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl _serde::Serialize for NamedUnit {
|
impl _serde::Serialize for NamedUnit {
|
||||||
@@ -21,7 +21,7 @@ const _: () = {
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||||
const _: () = {
|
const _: () = {
|
||||||
#[allow(rust_2018_idioms, clippy::useless_attribute)]
|
#[allow(unused_extern_crates, clippy::useless_attribute)]
|
||||||
extern crate serde as _serde;
|
extern crate serde as _serde;
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl<'de> _serde::Deserialize<'de> for NamedUnit {
|
impl<'de> _serde::Deserialize<'de> for NamedUnit {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ where
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||||
const _: () = {
|
const _: () = {
|
||||||
#[allow(rust_2018_idioms, clippy::useless_attribute)]
|
#[allow(unused_extern_crates, clippy::useless_attribute)]
|
||||||
extern crate serde as _serde;
|
extern crate serde as _serde;
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl<'a, B: 'a, C: 'a, D> _serde::Serialize for SerEnum<'a, B, C, D>
|
impl<'a, B: 'a, C: 'a, D> _serde::Serialize for SerEnum<'a, B, C, D>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ enum Void {}
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||||
const _: () = {
|
const _: () = {
|
||||||
#[allow(rust_2018_idioms, clippy::useless_attribute)]
|
#[allow(unused_extern_crates, clippy::useless_attribute)]
|
||||||
extern crate serde as _serde;
|
extern crate serde as _serde;
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl _serde::Serialize for Void {
|
impl _serde::Serialize for Void {
|
||||||
@@ -21,7 +21,7 @@ const _: () = {
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||||
const _: () = {
|
const _: () = {
|
||||||
#[allow(rust_2018_idioms, clippy::useless_attribute)]
|
#[allow(unused_extern_crates, clippy::useless_attribute)]
|
||||||
extern crate serde as _serde;
|
extern crate serde as _serde;
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl<'de> _serde::Deserialize<'de> for Void {
|
impl<'de> _serde::Deserialize<'de> for Void {
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#![allow(
|
#![allow(
|
||||||
clippy::cast_lossless,
|
clippy::cast_lossless,
|
||||||
clippy::from_over_into,
|
clippy::from_over_into,
|
||||||
|
// Clippy bug: https://github.com/rust-lang/rust-clippy/issues/7422
|
||||||
|
clippy::nonstandard_macro_braces,
|
||||||
clippy::trivially_copy_pass_by_ref
|
clippy::trivially_copy_pass_by_ref
|
||||||
)]
|
)]
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ use std::sync::atomic::{
|
|||||||
AtomicUsize, Ordering,
|
AtomicUsize, Ordering,
|
||||||
};
|
};
|
||||||
use std::sync::{Arc, Weak as ArcWeak};
|
use std::sync::{Arc, Weak as ArcWeak};
|
||||||
use std::time::{Duration, UNIX_EPOCH};
|
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
use std::sync::atomic::{AtomicI64, AtomicU64};
|
use std::sync::atomic::{AtomicI64, AtomicU64};
|
||||||
@@ -192,8 +192,12 @@ macro_rules! declare_tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! declare_error_tests {
|
macro_rules! declare_error_tests {
|
||||||
($($name:ident<$target:ty> { $tokens:expr, $expected:expr, })+) => {
|
($(
|
||||||
|
$(#[$cfg:meta])*
|
||||||
|
$name:ident<$target:ty> { $tokens:expr, $expected:expr, }
|
||||||
|
)+) => {
|
||||||
$(
|
$(
|
||||||
|
$(#[$cfg])*
|
||||||
#[test]
|
#[test]
|
||||||
fn $name() {
|
fn $name() {
|
||||||
assert_de_tokens_error::<$target>($tokens, $expected);
|
assert_de_tokens_error::<$target>($tokens, $expected);
|
||||||
@@ -1614,4 +1618,35 @@ declare_error_tests! {
|
|||||||
],
|
],
|
||||||
"overflow deserializing Duration",
|
"overflow deserializing Duration",
|
||||||
}
|
}
|
||||||
|
test_systemtime_overflow_seq<SystemTime> {
|
||||||
|
&[
|
||||||
|
Token::Seq { len: Some(2) },
|
||||||
|
Token::U64(u64::max_value()),
|
||||||
|
Token::U32(1_000_000_000),
|
||||||
|
Token::SeqEnd,
|
||||||
|
],
|
||||||
|
"overflow deserializing SystemTime epoch offset",
|
||||||
|
}
|
||||||
|
test_systemtime_overflow_struct<SystemTime> {
|
||||||
|
&[
|
||||||
|
Token::Struct { name: "SystemTime", len: 2 },
|
||||||
|
Token::Str("secs_since_epoch"),
|
||||||
|
Token::U64(u64::max_value()),
|
||||||
|
|
||||||
|
Token::Str("nanos_since_epoch"),
|
||||||
|
Token::U32(1_000_000_000),
|
||||||
|
Token::StructEnd,
|
||||||
|
],
|
||||||
|
"overflow deserializing SystemTime epoch offset",
|
||||||
|
}
|
||||||
|
#[cfg(systemtime_checked_add)]
|
||||||
|
test_systemtime_overflow<SystemTime> {
|
||||||
|
&[
|
||||||
|
Token::Seq { len: Some(2) },
|
||||||
|
Token::U64(u64::max_value()),
|
||||||
|
Token::U32(0),
|
||||||
|
Token::SeqEnd,
|
||||||
|
],
|
||||||
|
"overflow deserializing SystemTime",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,12 @@
|
|||||||
// types involved.
|
// types involved.
|
||||||
|
|
||||||
#![deny(warnings)]
|
#![deny(warnings)]
|
||||||
#![cfg_attr(feature = "unstable", feature(non_ascii_idents))]
|
|
||||||
#![allow(
|
#![allow(
|
||||||
unknown_lints,
|
unknown_lints,
|
||||||
mixed_script_confusables,
|
mixed_script_confusables,
|
||||||
|
// Clippy bug: https://github.com/rust-lang/rust-clippy/issues/7422
|
||||||
|
clippy::nonstandard_macro_braces,
|
||||||
|
clippy::ptr_arg,
|
||||||
clippy::trivially_copy_pass_by_ref
|
clippy::trivially_copy_pass_by_ref
|
||||||
)]
|
)]
|
||||||
|
|
||||||
@@ -266,7 +268,6 @@ fn test_gen() {
|
|||||||
}
|
}
|
||||||
assert::<EmptyEnumVariant>();
|
assert::<EmptyEnumVariant>();
|
||||||
|
|
||||||
#[cfg(feature = "unstable")]
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct NonAsciiIdents {
|
struct NonAsciiIdents {
|
||||||
σ: f64,
|
σ: f64,
|
||||||
@@ -642,7 +643,7 @@ fn test_gen() {
|
|||||||
assert::<SkippedVariant<X>>();
|
assert::<SkippedVariant<X>>();
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct ImpliciltyBorrowedOption<'a> {
|
struct ImplicitlyBorrowedOption<'a> {
|
||||||
option: std::option::Option<&'a str>,
|
option: std::option::Option<&'a str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -723,6 +724,24 @@ fn test_gen() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
deriving!(&'a str);
|
deriving!(&'a str);
|
||||||
|
|
||||||
|
macro_rules! mac {
|
||||||
|
($($tt:tt)*) => {
|
||||||
|
$($tt)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct BorrowLifetimeInsideMacro<'a> {
|
||||||
|
#[serde(borrow = "'a")]
|
||||||
|
f: mac!(Cow<'a, str>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
struct Struct {
|
||||||
|
#[serde(serialize_with = "vec_first_element")]
|
||||||
|
vec: Vec<Self>,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@@ -796,3 +815,11 @@ where
|
|||||||
pub fn is_zero(n: &u8) -> bool {
|
pub fn is_zero(n: &u8) -> bool {
|
||||||
*n == 0
|
*n == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn vec_first_element<T, S>(vec: &Vec<T>, serializer: S) -> StdResult<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
T: Serialize,
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
vec.first().serialize(serializer)
|
||||||
|
}
|
||||||
|
|||||||
@@ -994,6 +994,28 @@ fn test_internally_tagged_struct_variant_containing_unit_variant() {
|
|||||||
Token::StructEnd,
|
Token::StructEnd,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&Message::Log { level: Level::Info },
|
||||||
|
&[
|
||||||
|
Token::Map { len: Some(2) },
|
||||||
|
Token::Str("action"),
|
||||||
|
Token::Str("Log"),
|
||||||
|
Token::Str("level"),
|
||||||
|
Token::BorrowedStr("Info"),
|
||||||
|
Token::MapEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&Message::Log { level: Level::Info },
|
||||||
|
&[
|
||||||
|
Token::Seq { len: Some(2) },
|
||||||
|
Token::Str("Log"),
|
||||||
|
Token::BorrowedStr("Info"),
|
||||||
|
Token::SeqEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -1877,9 +1899,31 @@ fn test_internally_tagged_newtype_variant_containing_unit_struct() {
|
|||||||
Token::MapEnd,
|
Token::MapEnd,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&Message::Info(Info),
|
||||||
|
&[
|
||||||
|
Token::Struct {
|
||||||
|
name: "Message",
|
||||||
|
len: 1,
|
||||||
|
},
|
||||||
|
Token::Str("topic"),
|
||||||
|
Token::Str("Info"),
|
||||||
|
Token::StructEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&Message::Info(Info),
|
||||||
|
&[
|
||||||
|
Token::Seq { len: Some(1) },
|
||||||
|
Token::Str("Info"),
|
||||||
|
Token::SeqEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deny(safe_packed_borrows)]
|
#[deny(unaligned_references)]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_packed_struct_can_derive_serialize() {
|
fn test_packed_struct_can_derive_serialize() {
|
||||||
#[derive(Copy, Clone, Serialize)]
|
#[derive(Copy, Clone, Serialize)]
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_self() {
|
||||||
|
pub trait Trait {
|
||||||
|
type Assoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
pub struct Generics<T: Trait<Assoc = Self>>
|
||||||
|
where
|
||||||
|
Self: Trait<Assoc = Self>,
|
||||||
|
<Self as Trait>::Assoc: Sized,
|
||||||
|
{
|
||||||
|
_f: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Trait<Assoc = Self>> Trait for Generics<T> {
|
||||||
|
type Assoc = Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
pub struct Struct {
|
||||||
|
_f1: Box<Self>,
|
||||||
|
_f2: Box<<Self as Trait>::Assoc>,
|
||||||
|
_f4: [(); Self::ASSOC],
|
||||||
|
_f5: [(); Self::assoc()],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Struct {
|
||||||
|
const ASSOC: usize = 1;
|
||||||
|
const fn assoc() -> usize {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Trait for Struct {
|
||||||
|
type Assoc = Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
struct Tuple(
|
||||||
|
Box<Self>,
|
||||||
|
Box<<Self as Trait>::Assoc>,
|
||||||
|
[(); Self::ASSOC],
|
||||||
|
[(); Self::assoc()],
|
||||||
|
);
|
||||||
|
|
||||||
|
impl Tuple {
|
||||||
|
const ASSOC: usize = 1;
|
||||||
|
const fn assoc() -> usize {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Trait for Tuple {
|
||||||
|
type Assoc = Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
enum Enum {
|
||||||
|
Struct {
|
||||||
|
_f1: Box<Self>,
|
||||||
|
_f2: Box<<Self as Trait>::Assoc>,
|
||||||
|
_f4: [(); Self::ASSOC],
|
||||||
|
_f5: [(); Self::assoc()],
|
||||||
|
},
|
||||||
|
Tuple(
|
||||||
|
Box<Self>,
|
||||||
|
Box<<Self as Trait>::Assoc>,
|
||||||
|
[(); Self::ASSOC],
|
||||||
|
[(); Self::assoc()],
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Enum {
|
||||||
|
const ASSOC: usize = 1;
|
||||||
|
const fn assoc() -> usize {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Trait for Enum {
|
||||||
|
type Assoc = Self;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,4 +7,4 @@ error[E0308]: mismatched types
|
|||||||
| expected `u16`, found `u8`
|
| expected `u16`, found `u8`
|
||||||
| help: you can convert a `u8` to a `u16`: `Deserialize.into()`
|
| help: you can convert a `u8` to a `u16`: `Deserialize.into()`
|
||||||
|
|
|
|
||||||
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|||||||
@@ -6,4 +6,4 @@ error[E0308]: mismatched types
|
|||||||
|
|
|
|
||||||
= note: expected reference `&u8`
|
= note: expected reference `&u8`
|
||||||
found reference `&u16`
|
found reference `&u16`
|
||||||
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `Serialize` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|||||||
@@ -6,4 +6,4 @@ error[E0308]: mismatched types
|
|||||||
|
|
|
|
||||||
= note: expected reference `&u8`
|
= note: expected reference `&u8`
|
||||||
found reference `&u16`
|
found reference `&u16`
|
||||||
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `Serialize` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|||||||
@@ -4,4 +4,4 @@ error: #[serde(tag = "...")] can only be used on enums and structs with named fi
|
|||||||
3 | #[derive(Serialize)]
|
3 | #[derive(Serialize)]
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `Serialize` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|||||||
Reference in New Issue
Block a user