diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 323399ce..dd49909b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,8 +3,12 @@ name: CI on: push: pull_request: + workflow_dispatch: schedule: [cron: "40 1 * * *"] +permissions: + contents: read + env: RUSTFLAGS: -Dwarnings @@ -12,16 +16,18 @@ jobs: test: name: Test suite runs-on: ubuntu-latest + timeout-minutes: 45 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@nightly - run: cd test_suite && cargo test --features unstable windows: name: Test suite (windows) runs-on: windows-latest + timeout-minutes: 45 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@nightly - run: cd test_suite && cargo test --features unstable -- --skip ui --exact @@ -32,15 +38,14 @@ jobs: fail-fast: false matrix: rust: [stable, beta] + timeout-minutes: 45 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@master with: toolchain: ${{matrix.rust}} - run: cd serde && cargo build --features rc - run: cd serde && cargo build --no-default-features - - run: cd serde_test && cargo build - - run: cd serde_test && cargo test --features serde/derive,serde/rc nightly: name: Rust nightly ${{matrix.os == 'windows' && '(windows)' || ''}} @@ -49,33 +54,22 @@ jobs: fail-fast: false matrix: os: [ubuntu, windows] + timeout-minutes: 45 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@nightly - run: cd serde && cargo build - run: cd serde && cargo build --no-default-features - run: cd serde && cargo build --no-default-features --features alloc - run: cd serde && cargo build --no-default-features --features rc,alloc + - run: cd serde && cargo build --no-default-features --features unstable - run: cd serde && cargo test --features derive,rc,unstable - run: cd test_suite/no_std && cargo build if: matrix.os != 'windows' - - msrv: - name: Rust 1.13.0 - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: dtolnay/rust-toolchain@1.13.0 - - name: Get timestamp for cache - id: date - run: echo ::set-output name=yearmo::$(date +%Y%m) - - uses: actions/cache@v1 - with: - path: ~/.cargo/registry/index - key: cargo-registry-index-${{steps.date.outputs.yearmo}} - - run: cd serde && cargo build --features rc - - run: cd serde && cargo build --no-default-features - - run: cd serde_test && cargo build + - run: cd serde_derive && cargo check --tests + env: + RUSTFLAGS: --cfg exhaustive ${{env.RUSTFLAGS}} + if: matrix.os != 'windows' build: name: Rust ${{matrix.rust}} @@ -83,38 +77,24 @@ jobs: strategy: fail-fast: false matrix: - rust: [1.19.0, 1.20.0, 1.21.0, 1.25.0, 1.26.0, 1.34.0] + rust: [1.31.0, 1.34.0] + timeout-minutes: 45 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@master with: toolchain: ${{matrix.rust}} - - run: cd serde && cargo build --no-default-features - - run: cd serde && cargo build - - more: - name: Rust ${{matrix.rust}} - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - rust: [1.27.0, 1.28.0] - steps: - - uses: actions/checkout@v2 - - uses: dtolnay/rust-toolchain@master - with: - toolchain: ${{matrix.rust}} - # Work around failing to parse manifest because editions are unstable. - - run: sed -i /test_suite/d Cargo.toml + - run: cd serde && cargo build --features rc - run: cd serde && cargo build --no-default-features - run: cd serde && cargo build derive: - name: Rust 1.31.0 + name: Rust 1.56.0 runs-on: ubuntu-latest + timeout-minutes: 45 steps: - - uses: actions/checkout@v2 - - uses: dtolnay/rust-toolchain@1.31.0 + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@1.56.0 - run: cd serde && cargo check --no-default-features - run: cd serde && cargo check - run: cd serde_derive && cargo check @@ -122,43 +102,71 @@ jobs: alloc: name: Rust 1.36.0 runs-on: ubuntu-latest + timeout-minutes: 45 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@1.36.0 - run: cd serde && cargo build --no-default-features --features alloc - emscripten: - name: Emscripten + minimal: + name: Minimal versions runs-on: ubuntu-latest + timeout-minutes: 45 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@nightly - - uses: actions/setup-node@v1 - with: - node-version: 9 - - name: Install cargo-web - run: | - CARGO_WEB_RELEASE=$(curl -L -s -H Accept:application/json https://github.com/koute/cargo-web/releases/latest) - CARGO_WEB_VERSION=$(echo "${CARGO_WEB_RELEASE}" | jq -r .tag_name) - CARGO_WEB_URL="https://github.com/koute/cargo-web/releases/download/${CARGO_WEB_VERSION}/cargo-web-x86_64-unknown-linux-gnu.gz" - mkdir -p ~/.cargo/bin - curl -L "${CARGO_WEB_URL}" | gzip -d > ~/.cargo/bin/cargo-web - chmod +x ~/.cargo/bin/cargo-web - - run: cd test_suite && cargo web test --target=asmjs-unknown-emscripten --nodejs - continue-on-error: true - - run: cd test_suite && cargo web test --target=wasm32-unknown-emscripten --nodejs - continue-on-error: true + - run: cargo generate-lockfile -Z minimal-versions + - run: cargo check --locked --workspace + + doc: + name: Documentation + runs-on: ubuntu-latest + timeout-minutes: 45 + env: + RUSTDOCFLAGS: -Dwarnings + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + - uses: dtolnay/install@cargo-docs-rs + - run: cargo docs-rs -p serde + - run: cargo docs-rs -p serde_derive + - run: cargo docs-rs -p serde_derive_internals clippy: name: Clippy runs-on: ubuntu-latest if: github.event_name != 'pull_request' + timeout-minutes: 45 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@clippy - run: cd serde && cargo clippy --features rc,unstable -- -Dclippy::all -Dclippy::pedantic - run: cd serde_derive && cargo clippy -- -Dclippy::all -Dclippy::pedantic - run: cd serde_derive_internals && cargo clippy -- -Dclippy::all -Dclippy::pedantic - - run: cd serde_test && cargo clippy -- -Dclippy::all -Dclippy::pedantic - run: cd test_suite && cargo clippy --tests --features unstable -- -Dclippy::all -Dclippy::pedantic - run: cd test_suite/no_std && cargo clippy -- -Dclippy::all -Dclippy::pedantic + + miri: + name: Miri + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@miri + - run: cargo miri setup + - run: cd serde && cargo miri test --features derive,rc,unstable + env: + MIRIFLAGS: -Zmiri-strict-provenance + - run: cd test_suite && cargo miri test --features unstable + env: + MIRIFLAGS: -Zmiri-strict-provenance + + outdated: + name: Outdated + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/install@cargo-outdated + - run: cargo outdated --workspace --exit-code 1 diff --git a/Cargo.toml b/Cargo.toml index cb35f854..ac94fb08 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,13 @@ members = [ "serde", "serde_derive", "serde_derive_internals", - "serde_test", "test_suite", ] + +[patch.crates-io] +serde = { path = "serde" } + +[workspace.dependencies] +proc-macro2 = { version = "1.0.74", default-features = false } +quote = { version = "1.0.35", default-features = false } +syn = { version = "2.0.46", default-features = false } diff --git a/LICENSE-APACHE b/LICENSE-APACHE index 16fe87b0..1b5ec8b7 100644 --- a/LICENSE-APACHE +++ b/LICENSE-APACHE @@ -174,28 +174,3 @@ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/README.OpenSource b/README.OpenSource index 5a549053..d3ebade8 100644 --- a/README.OpenSource +++ b/README.OpenSource @@ -3,7 +3,7 @@ "Name": "serde", "License": "Apache License V2.0", "License File": "LICENSE-APACHE", - "Version Number": "1.0.136", + "Version Number": "1.0.197", "Owner": "xuelei3@huawei.com", "Upstream URL": "https://github.com/serde-rs/serde", "Description": "A generic serialization/deserialization framework." diff --git a/README.md b/README.md index 79409a3f..31292944 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ -# Serde   [![Build Status]][actions] [![Latest Version]][crates.io] [![serde: rustc 1.13+]][Rust 1.13] [![serde_derive: rustc 1.31+]][Rust 1.31] +# Serde   [![Build Status]][actions] [![Latest Version]][crates.io] [![serde msrv]][Rust 1.31] [![serde_derive msrv]][Rust 1.56] -[Build Status]: https://img.shields.io/github/workflow/status/serde-rs/serde/CI/master +[Build Status]: https://img.shields.io/github/actions/workflow/status/serde-rs/serde/ci.yml?branch=master [actions]: https://github.com/serde-rs/serde/actions?query=branch%3Amaster [Latest Version]: https://img.shields.io/crates/v/serde.svg [crates.io]: https://crates.io/crates/serde -[serde: rustc 1.13+]: https://img.shields.io/badge/serde-rustc_1.13+-lightgray.svg -[serde_derive: rustc 1.31+]: https://img.shields.io/badge/serde_derive-rustc_1.31+-lightgray.svg -[Rust 1.13]: https://blog.rust-lang.org/2016/11/10/Rust-1.13.html +[serde msrv]: https://img.shields.io/crates/msrv/serde.svg?label=serde%20msrv&color=lightgray +[serde_derive msrv]: https://img.shields.io/crates/msrv/serde_derive.svg?label=serde_derive%20msrv&color=lightgray [Rust 1.31]: https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html +[Rust 1.56]: https://blog.rust-lang.org/2021/10/21/Rust-1.56.0.html **Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.** @@ -19,7 +19,7 @@ You may be looking for: - [Data formats supported by Serde](https://serde.rs/#data-formats) - [Setting up `#[derive(Serialize, Deserialize)]`](https://serde.rs/derive.html) - [Examples](https://serde.rs/examples.html) -- [API documentation](https://docs.serde.rs/serde/) +- [API documentation](https://docs.rs/serde) - [Release notes](https://github.com/serde-rs/serde/releases) ## Serde in action @@ -48,7 +48,7 @@ serde_json = "1.0"

```rust -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug)] struct Point { diff --git a/crates-io.md b/crates-io.md index b57bc5fd..18710035 100644 --- a/crates-io.md +++ b/crates-io.md @@ -10,13 +10,13 @@ You may be looking for: - [Data formats supported by Serde](https://serde.rs/#data-formats) - [Setting up `#[derive(Serialize, Deserialize)]`](https://serde.rs/derive.html) - [Examples](https://serde.rs/examples.html) -- [API documentation](https://docs.serde.rs/serde/) +- [API documentation](https://docs.rs/serde) - [Release notes](https://github.com/serde-rs/serde/releases) ## Serde in action ```rust -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug)] struct Point { diff --git a/serde/BUILD.gn b/serde/BUILD.gn index 1f30fc56..6978ad7f 100644 --- a/serde/BUILD.gn +++ b/serde/BUILD.gn @@ -19,8 +19,8 @@ ohos_cargo_crate("lib") { crate_root = "src/lib.rs" sources = [ "src/lib.rs" ] - edition = "2015" - cargo_pkg_version = "1.0.136" + edition = "2018" + cargo_pkg_version = "1.0.195" cargo_pkg_authors = "Erick Tryzelaar , David Tolnay " cargo_pkg_name = "serde" cargo_pkg_description = "A generic serialization/deserialization framework" diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 2cf4ca47..73732672 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,30 +1,43 @@ [package] name = "serde" -version = "1.0.136" # remember to update html_root_url and serde_derive dependency +version = "1.0.197" authors = ["Erick Tryzelaar ", "David Tolnay "] -rust-version = "1.15" -license = "MIT OR Apache-2.0" -description = "A generic serialization/deserialization framework" -homepage = "https://serde.rs" -repository = "https://github.com/serde-rs/serde" -documentation = "https://docs.serde.rs/serde/" -keywords = ["serde", "serialization", "no_std"] -categories = ["encoding"] -readme = "crates-io.md" -include = ["build.rs", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] build = "build.rs" +categories = ["encoding", "no-std", "no-std::no-alloc"] +description = "A generic serialization/deserialization framework" +documentation = "https://docs.rs/serde" +edition = "2018" +homepage = "https://serde.rs" +keywords = ["serde", "serialization", "no_std"] +license = "MIT OR Apache-2.0" +readme = "crates-io.md" +repository = "https://github.com/serde-rs/serde" +rust-version = "1.31" [dependencies] -serde_derive = { version = "=1.0.136", optional = true, path = "../serde_derive" } +serde_derive = { version = "1", optional = true, path = "../serde_derive" } [dev-dependencies] -serde_derive = { version = "1.0", path = "../serde_derive" } +serde_derive = { version = "1", path = "../serde_derive" } + +[lib] +doc-scrape-examples = false [package.metadata.playground] features = ["derive", "rc"] [package.metadata.docs.rs] +features = ["derive", "rc", "unstable"] targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = ["--cfg", "doc_cfg", "--generate-link-to-definition"] + +# This cfg cannot be enabled, but it still forces Cargo to keep serde_derive's +# version in lockstep with serde's, even if someone depends on the two crates +# separately with serde's "derive" feature disabled. Every serde_derive release +# is compatible with exactly one serde release because the generated code +# involves nonpublic APIs which are not bound by semver. +[target.'cfg(any())'.dependencies] +serde_derive = { version = "=1.0.197", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/build.rs b/serde/build.rs index a1103b52..fe5486a7 100644 --- a/serde/build.rs +++ b/serde/build.rs @@ -6,6 +6,8 @@ use std::str::{self, FromStr}; // opening a GitHub issue if your build environment requires some way to enable // these cfgs other than by executing our build script. fn main() { + println!("cargo:rerun-if-changed=build.rs"); + let minor = match rustc_minor_version() { Some(minor) => minor, None => return, @@ -14,73 +16,6 @@ fn main() { let target = env::var("TARGET").unwrap(); let emscripten = target == "asmjs-unknown-emscripten" || target == "wasm32-unknown-emscripten"; - // std::collections::Bound was stabilized in Rust 1.17 - // but it was moved to core::ops later in Rust 1.26: - // https://doc.rust-lang.org/core/ops/enum.Bound.html - if minor < 26 { - println!("cargo:rustc-cfg=no_ops_bound"); - if minor < 17 { - println!("cargo:rustc-cfg=no_collections_bound"); - } - } - - // core::cmp::Reverse stabilized in Rust 1.19: - // https://doc.rust-lang.org/stable/core/cmp/struct.Reverse.html - if minor < 19 { - println!("cargo:rustc-cfg=no_core_reverse"); - } - - // CString::into_boxed_c_str and PathBuf::into_boxed_path stabilized in Rust 1.20: - // https://doc.rust-lang.org/std/ffi/struct.CString.html#method.into_boxed_c_str - // https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.into_boxed_path - if minor < 20 { - println!("cargo:rustc-cfg=no_de_boxed_c_str"); - println!("cargo:rustc-cfg=no_de_boxed_path"); - } - - // From> for Rc / Arc stabilized in Rust 1.21: - // https://doc.rust-lang.org/std/rc/struct.Rc.html#impl-From> - // https://doc.rust-lang.org/std/sync/struct.Arc.html#impl-From> - if minor < 21 { - println!("cargo:rustc-cfg=no_de_rc_dst"); - } - - // Duration available in core since Rust 1.25: - // https://blog.rust-lang.org/2018/03/29/Rust-1.25.html#library-stabilizations - if minor < 25 { - println!("cargo:rustc-cfg=no_core_duration"); - } - - // 128-bit integers stabilized in Rust 1.26: - // https://blog.rust-lang.org/2018/05/10/Rust-1.26.html - // - // Disabled on Emscripten targets before Rust 1.40 since - // Emscripten did not support 128-bit integers until Rust 1.40 - // (https://github.com/rust-lang/rust/pull/65251) - if minor < 26 || emscripten && minor < 40 { - println!("cargo:rustc-cfg=no_integer128"); - } - - // Inclusive ranges methods stabilized in Rust 1.27: - // https://github.com/rust-lang/rust/pull/50758 - // Also Iterator::try_for_each: - // https://blog.rust-lang.org/2018/06/21/Rust-1.27.html#library-stabilizations - if minor < 27 { - println!("cargo:rustc-cfg=no_range_inclusive"); - println!("cargo:rustc-cfg=no_iterator_try_fold"); - } - - // Non-zero integers stabilized in Rust 1.28: - // https://blog.rust-lang.org/2018/08/02/Rust-1.28.html#library-stabilizations - if minor < 28 { - println!("cargo:rustc-cfg=no_num_nonzero"); - } - - // Current minimum supported version of serde_derive crate is Rust 1.31. - if minor < 31 { - println!("cargo:rustc-cfg=no_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 @@ -89,24 +24,45 @@ fn main() { println!("cargo:rustc-cfg=no_core_try_from"); println!("cargo:rustc-cfg=no_num_nonzero_signed"); println!("cargo:rustc-cfg=no_systemtime_checked_add"); + println!("cargo:rustc-cfg=no_relaxed_trait_bounds"); } - // Whitelist of archs that support std::sync::atomic module. Ideally we - // would use #[cfg(target_has_atomic = "...")] but it is not stable yet. - // Instead this is based on rustc's compiler/rustc_target/src/spec/*.rs. - let has_atomic64 = target.starts_with("x86_64") - || target.starts_with("i686") - || target.starts_with("aarch64") - || target.starts_with("powerpc64") - || target.starts_with("sparc64") - || target.starts_with("mips64el") - || target.starts_with("riscv64"); - let has_atomic32 = has_atomic64 || emscripten; - if minor < 34 || !has_atomic64 { - println!("cargo:rustc-cfg=no_std_atomic64"); + // f32::copysign and f64::copysign stabilized in Rust 1.35. + // https://blog.rust-lang.org/2019/05/23/Rust-1.35.0.html#copy-the-sign-of-a-floating-point-number-onto-another + if minor < 35 { + println!("cargo:rustc-cfg=no_float_copysign"); } - if minor < 34 || !has_atomic32 { - println!("cargo:rustc-cfg=no_std_atomic"); + + // Current minimum supported version of serde_derive crate is Rust 1.56. + if minor < 56 { + println!("cargo:rustc-cfg=no_serde_derive"); + } + + // Support for #[cfg(target_has_atomic = "...")] stabilized in Rust 1.60. + if minor < 60 { + println!("cargo:rustc-cfg=no_target_has_atomic"); + // Allowlist of archs that support std::sync::atomic module. This is + // based on rustc's compiler/rustc_target/src/spec/*.rs. + let has_atomic64 = target.starts_with("x86_64") + || target.starts_with("i686") + || target.starts_with("aarch64") + || target.starts_with("powerpc64") + || target.starts_with("sparc64") + || target.starts_with("mips64el") + || target.starts_with("riscv64"); + let has_atomic32 = has_atomic64 || emscripten; + if minor < 34 || !has_atomic64 { + println!("cargo:rustc-cfg=no_std_atomic64"); + } + if minor < 34 || !has_atomic32 { + println!("cargo:rustc-cfg=no_std_atomic"); + } + } + + // Support for core::ffi::CStr and alloc::ffi::CString stabilized in Rust 1.64. + // https://blog.rust-lang.org/2022/09/22/Rust-1.64.0.html#c-compatible-ffi-types-in-core-and-alloc + if minor < 64 { + println!("cargo:rustc-cfg=no_core_cstr"); } } diff --git a/serde/src/de/format.rs b/serde/src/de/format.rs index 58ec0968..9053cc07 100644 --- a/serde/src/de/format.rs +++ b/serde/src/de/format.rs @@ -1,7 +1,7 @@ -use lib::fmt::{self, Write}; -use lib::str; +use crate::lib::fmt::{self, Write}; +use crate::lib::str; -pub struct Buf<'a> { +pub(super) struct Buf<'a> { bytes: &'a mut [u8], offset: usize, } diff --git a/serde/src/de/ignored_any.rs b/serde/src/de/ignored_any.rs index 1d50f5ec..2360a174 100644 --- a/serde/src/de/ignored_any.rs +++ b/serde/src/de/ignored_any.rs @@ -1,6 +1,6 @@ -use lib::*; +use crate::lib::*; -use de::{ +use crate::de::{ Deserialize, Deserializer, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor, }; @@ -10,13 +10,12 @@ use de::{ /// any type, except that it does not store any information about the data that /// gets deserialized. /// -/// ```edition2018 -/// use std::fmt; -/// use std::marker::PhantomData; -/// +/// ```edition2021 /// use serde::de::{ /// self, Deserialize, DeserializeSeed, Deserializer, IgnoredAny, SeqAccess, Visitor, /// }; +/// use std::fmt; +/// use std::marker::PhantomData; /// /// /// A seed that can be used to deserialize only the `n`th element of a sequence /// /// while efficiently discarding elements of any type before or after index `n`. @@ -108,7 +107,7 @@ use de::{ /// # Ok(()) /// # } /// ``` -#[derive(Copy, Clone, Debug, Default)] +#[derive(Copy, Clone, Debug, Default, PartialEq)] pub struct IgnoredAny; impl<'de> Visitor<'de> for IgnoredAny { @@ -130,12 +129,10 @@ impl<'de> Visitor<'de> for IgnoredAny { Ok(IgnoredAny) } - serde_if_integer128! { - #[inline] - fn visit_i128(self, x: i128) -> Result { - let _ = x; - Ok(IgnoredAny) - } + #[inline] + fn visit_i128(self, x: i128) -> Result { + let _ = x; + Ok(IgnoredAny) } #[inline] @@ -144,12 +141,10 @@ impl<'de> Visitor<'de> for IgnoredAny { Ok(IgnoredAny) } - serde_if_integer128! { - #[inline] - fn visit_u128(self, x: u128) -> Result { - let _ = x; - Ok(IgnoredAny) - } + #[inline] + fn visit_u128(self, x: u128) -> Result { + let _ = x; + Ok(IgnoredAny) } #[inline] @@ -198,7 +193,7 @@ impl<'de> Visitor<'de> for IgnoredAny { where A: SeqAccess<'de>, { - while let Some(IgnoredAny) = try!(seq.next_element()) { + while let Some(IgnoredAny) = tri!(seq.next_element()) { // Gobble } Ok(IgnoredAny) @@ -209,7 +204,7 @@ impl<'de> Visitor<'de> for IgnoredAny { where A: MapAccess<'de>, { - while let Some((IgnoredAny, IgnoredAny)) = try!(map.next_entry()) { + while let Some((IgnoredAny, IgnoredAny)) = tri!(map.next_entry()) { // Gobble } Ok(IgnoredAny) @@ -228,7 +223,7 @@ impl<'de> Visitor<'de> for IgnoredAny { where A: EnumAccess<'de>, { - data.variant::()?.1.newtype_variant() + tri!(data.variant::()).1.newtype_variant() } } diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index c5aaca72..413c997a 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -1,16 +1,14 @@ -use lib::*; +use crate::lib::*; -use de::{ - Deserialize, Deserializer, EnumAccess, Error, SeqAccess, Unexpected, VariantAccess, Visitor, +use crate::de::{ + Deserialize, Deserializer, EnumAccess, Error, MapAccess, SeqAccess, Unexpected, VariantAccess, + Visitor, }; -#[cfg(any(feature = "std", feature = "alloc", not(no_core_duration)))] -use de::MapAccess; - -use seed::InPlaceSeed; +use crate::seed::InPlaceSeed; #[cfg(any(feature = "std", feature = "alloc"))] -use __private::size_hint; +use crate::de::size_hint; //////////////////////////////////////////////////////////////////////////////// @@ -41,6 +39,7 @@ impl<'de> Deserialize<'de> for () { } #[cfg(feature = "unstable")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "unstable")))] impl<'de> Deserialize<'de> for ! { fn deserialize(_deserializer: D) -> Result where @@ -84,7 +83,7 @@ macro_rules! impl_deserialize_num { ($primitive:ident, $nonzero:ident $(cfg($($cfg:tt)*))*, $deserialize:ident $($method:ident!($($val:ident : $visit:ident)*);)*) => { impl_deserialize_num!($primitive, $deserialize $($method!($($val : $visit)*);)*); - #[cfg(all(not(no_num_nonzero), $($($cfg)*)*))] + $(#[cfg($($cfg)*)])* impl<'de> Deserialize<'de> for num::$nonzero { fn deserialize(deserializer: D) -> Result where @@ -182,6 +181,28 @@ macro_rules! num_as_self { }; } +macro_rules! num_as_copysign_self { + ($ty:ident : $visit:ident) => { + #[inline] + fn $visit(self, v: $ty) -> Result + where + E: Error, + { + #[cfg(any(no_float_copysign, not(feature = "std")))] + { + Ok(v as Self::Value) + } + + #[cfg(all(not(no_float_copysign), feature = "std"))] + { + // Preserve sign of NaN. The `as` produces a nondeterministic sign. + let sign = if v.is_sign_positive() { 1.0 } else { -1.0 }; + Ok((v as Self::Value).copysign(sign)) + } + } + }; +} + macro_rules! int_to_int { ($ty:ident : $visit:ident) => { #[inline] @@ -353,7 +374,7 @@ impl_deserialize_num! { impl_deserialize_num! { f32, deserialize_f32 num_self!(f32:visit_f32); - num_as_self!(f64:visit_f64); + num_as_copysign_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); } @@ -361,69 +382,67 @@ impl_deserialize_num! { impl_deserialize_num! { f64, deserialize_f64 num_self!(f64:visit_f64); - num_as_self!(f32:visit_f32); + num_as_copysign_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! { - macro_rules! num_128 { - ($ty:ident : $visit:ident) => { - fn $visit(self, v: $ty) -> Result - where - E: Error, +macro_rules! num_128 { + ($ty:ident : $visit:ident) => { + fn $visit(self, v: $ty) -> Result + where + E: Error, + { + if v as i128 >= Self::Value::min_value() as i128 + && v as u128 <= Self::Value::max_value() as u128 { - if v as i128 >= Self::Value::min_value() as i128 - && v as u128 <= Self::Value::max_value() as u128 - { - Ok(v as Self::Value) - } else { - Err(Error::invalid_value( - Unexpected::Other(stringify!($ty)), - &self, - )) - } + Ok(v as Self::Value) + } else { + Err(Error::invalid_value( + Unexpected::Other(stringify!($ty)), + &self, + )) } - }; + } + }; - (nonzero $primitive:ident $ty:ident : $visit:ident) => { - fn $visit(self, v: $ty) -> Result - where - E: Error, + (nonzero $primitive:ident $ty:ident : $visit:ident) => { + fn $visit(self, v: $ty) -> Result + where + E: Error, + { + if v as i128 >= $primitive::min_value() as i128 + && v as u128 <= $primitive::max_value() as u128 { - if v as i128 >= $primitive::min_value() as i128 - && v as u128 <= $primitive::max_value() as u128 - { - if let Some(nonzero) = Self::Value::new(v as $primitive) { - Ok(nonzero) - } else { - Err(Error::invalid_value(Unexpected::Unsigned(0), &self)) - } + if let Some(nonzero) = Self::Value::new(v as $primitive) { + Ok(nonzero) } else { - Err(Error::invalid_value( - Unexpected::Other(stringify!($ty)), - &self, - )) + Err(Error::invalid_value(Unexpected::Unsigned(0), &self)) } + } else { + Err(Error::invalid_value( + Unexpected::Other(stringify!($ty)), + &self, + )) } - }; - } + } + }; +} - impl_deserialize_num! { - i128, NonZeroI128 cfg(not(no_num_nonzero_signed)), 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); - num_128!(u128:visit_u128); - } +impl_deserialize_num! { + i128, NonZeroI128 cfg(not(no_num_nonzero_signed)), 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); + num_128!(u128:visit_u128); +} - impl_deserialize_num! { - u128, NonZeroU128, 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); - num_128!(i128:visit_i128); - } +impl_deserialize_num! { + u128, NonZeroU128, 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); + num_128!(i128:visit_i128); } //////////////////////////////////////////////////////////////////////////////// @@ -578,6 +597,7 @@ impl<'a, 'de> Visitor<'de> for StringInPlaceVisitor<'a> { } #[cfg(any(feature = "std", feature = "alloc"))] +#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de> Deserialize<'de> for String { fn deserialize(deserializer: D) -> Result where @@ -666,10 +686,10 @@ impl<'de: 'a, 'a> Deserialize<'de> for &'a [u8] { //////////////////////////////////////////////////////////////////////////////// -#[cfg(feature = "std")] +#[cfg(any(feature = "std", all(not(no_core_cstr), feature = "alloc")))] struct CStringVisitor; -#[cfg(feature = "std")] +#[cfg(any(feature = "std", all(not(no_core_cstr), feature = "alloc")))] impl<'de> Visitor<'de> for CStringVisitor { type Value = CString; @@ -681,10 +701,10 @@ impl<'de> Visitor<'de> for CStringVisitor { where A: SeqAccess<'de>, { - let len = size_hint::cautious(seq.size_hint()); - let mut values = Vec::with_capacity(len); + let capacity = size_hint::cautious::(seq.size_hint()); + let mut values = Vec::::with_capacity(capacity); - while let Some(value) = try!(seq.next_element()) { + while let Some(value) = tri!(seq.next_element()) { values.push(value); } @@ -720,7 +740,8 @@ impl<'de> Visitor<'de> for CStringVisitor { } } -#[cfg(feature = "std")] +#[cfg(any(feature = "std", all(not(no_core_cstr), feature = "alloc")))] +#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de> Deserialize<'de> for CString { fn deserialize(deserializer: D) -> Result where @@ -732,10 +753,10 @@ impl<'de> Deserialize<'de> for CString { macro_rules! forwarded_impl { ( - $(#[doc = $doc:tt])* - ( $($id: ident),* ), $ty: ty, $func: expr + $(#[$attr:meta])* + ($($id:ident),*), $ty:ty, $func:expr ) => { - $(#[doc = $doc])* + $(#[$attr])* impl<'de $(, $id : Deserialize<'de>,)*> Deserialize<'de> for $ty { fn deserialize(deserializer: D) -> Result where @@ -747,11 +768,15 @@ macro_rules! forwarded_impl { } } -#[cfg(all(feature = "std", not(no_de_boxed_c_str)))] -forwarded_impl!((), Box, CString::into_boxed_c_str); +forwarded_impl! { + #[cfg(any(feature = "std", all(not(no_core_cstr), feature = "alloc")))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + (), Box, CString::into_boxed_c_str +} -#[cfg(not(no_core_reverse))] -forwarded_impl!((T), Reverse, Reverse); +forwarded_impl! { + (T), Reverse, Reverse +} //////////////////////////////////////////////////////////////////////////////// @@ -793,7 +818,6 @@ where T::deserialize(deserializer).map(Some) } - #[doc(hidden)] fn __private_visit_untagged_option(self, deserializer: D) -> Result where D: Deserializer<'de>, @@ -858,16 +882,17 @@ impl<'de, T: ?Sized> Deserialize<'de> for PhantomData { //////////////////////////////////////////////////////////////////////////////// -#[cfg(any(feature = "std", feature = "alloc"))] macro_rules! seq_impl { ( - $ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >, + $(#[$attr:meta])* + $ty:ident , $access:ident, $clear:expr, $with_capacity:expr, $reserve:expr, $insert:expr ) => { + $(#[$attr])* impl<'de, T $(, $typaram)*> Deserialize<'de> for $ty where T: Deserialize<'de> $(+ $tbound1 $(+ $tbound2)*)*, @@ -899,7 +924,7 @@ macro_rules! seq_impl { { let mut values = $with_capacity; - while let Some(value) = try!($access.next_element()) { + while let Some(value) = tri!($access.next_element()) { $insert(&mut values, value); } @@ -934,10 +959,10 @@ macro_rules! seq_impl { A: SeqAccess<'de>, { $clear(&mut self.0); - $reserve(&mut self.0, size_hint::cautious($access.size_hint())); + $reserve(&mut self.0, size_hint::cautious::($access.size_hint())); // FIXME: try to overwrite old values here? (Vec, VecDeque, LinkedList) - while let Some(value) = try!($access.next_element()) { + while let Some(value) = tri!($access.next_element()) { $insert(&mut self.0, value); } @@ -955,18 +980,20 @@ macro_rules! seq_impl { #[cfg(any(feature = "std", feature = "alloc"))] fn nop_reserve(_seq: T, _n: usize) {} -#[cfg(any(feature = "std", feature = "alloc"))] seq_impl!( + #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] BinaryHeap, seq, BinaryHeap::clear, - BinaryHeap::with_capacity(size_hint::cautious(seq.size_hint())), + BinaryHeap::with_capacity(size_hint::cautious::(seq.size_hint())), BinaryHeap::reserve, BinaryHeap::push ); -#[cfg(any(feature = "std", feature = "alloc"))] seq_impl!( + #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] BTreeSet, seq, BTreeSet::clear, @@ -975,8 +1002,9 @@ seq_impl!( BTreeSet::insert ); -#[cfg(any(feature = "std", feature = "alloc"))] seq_impl!( + #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] LinkedList, seq, LinkedList::clear, @@ -985,21 +1013,24 @@ seq_impl!( LinkedList::push_back ); -#[cfg(feature = "std")] seq_impl!( + #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] HashSet, seq, HashSet::clear, - HashSet::with_capacity_and_hasher(size_hint::cautious(seq.size_hint()), S::default()), + HashSet::with_capacity_and_hasher(size_hint::cautious::(seq.size_hint()), S::default()), HashSet::reserve, - HashSet::insert); + HashSet::insert +); -#[cfg(any(feature = "std", feature = "alloc"))] seq_impl!( + #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] VecDeque, seq, VecDeque::clear, - VecDeque::with_capacity(size_hint::cautious(seq.size_hint())), + VecDeque::with_capacity(size_hint::cautious::(seq.size_hint())), VecDeque::reserve, VecDeque::push_back ); @@ -1007,6 +1038,7 @@ seq_impl!( //////////////////////////////////////////////////////////////////////////////// #[cfg(any(feature = "std", feature = "alloc"))] +#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de, T> Deserialize<'de> for Vec where T: Deserialize<'de>, @@ -1033,9 +1065,10 @@ where where A: SeqAccess<'de>, { - let mut values = Vec::with_capacity(size_hint::cautious(seq.size_hint())); + let capacity = size_hint::cautious::(seq.size_hint()); + let mut values = Vec::::with_capacity(capacity); - while let Some(value) = try!(seq.next_element()) { + while let Some(value) = tri!(seq.next_element()) { values.push(value); } @@ -1069,7 +1102,7 @@ where where A: SeqAccess<'de>, { - let hint = size_hint::cautious(seq.size_hint()); + let hint = size_hint::cautious::(seq.size_hint()); if let Some(additional) = hint.checked_sub(self.0.len()) { self.0.reserve(additional); } @@ -1077,7 +1110,7 @@ where for i in 0..self.0.len() { let next = { let next_place = InPlaceSeed(&mut self.0[i]); - try!(seq.next_element_seed(next_place)) + tri!(seq.next_element_seed(next_place)) }; if next.is_none() { self.0.truncate(i); @@ -1085,7 +1118,7 @@ where } } - while let Some(value) = try!(seq.next_element()) { + while let Some(value) = tri!(seq.next_element()) { self.0.push(value); } @@ -1157,7 +1190,7 @@ macro_rules! array_impls { A: SeqAccess<'de>, { Ok([$( - match try!(seq.next_element()) { + match tri!(seq.next_element()) { Some(val) => val, None => return Err(Error::invalid_length($n, &self)), } @@ -1182,7 +1215,7 @@ macro_rules! array_impls { { let mut fail_idx = None; for (idx, dest) in self.0[..].iter_mut().enumerate() { - if try!(seq.next_element_seed(InPlaceSeed(dest))).is_none() { + if tri!(seq.next_element_seed(InPlaceSeed(dest))).is_none() { fail_idx = Some(idx); break; } @@ -1280,7 +1313,7 @@ macro_rules! tuple_impls { A: SeqAccess<'de>, { $( - let $name = match try!(seq.next_element()) { + let $name = match tri!(seq.next_element()) { Some(value) => value, None => return Err(Error::invalid_length($n, &self)), }; @@ -1314,7 +1347,7 @@ macro_rules! tuple_impls { A: SeqAccess<'de>, { $( - if try!(seq.next_element_seed(InPlaceSeed(&mut (self.0).$n))).is_none() { + if tri!(seq.next_element_seed(InPlaceSeed(&mut (self.0).$n))).is_none() { return Err(Error::invalid_length($n, &self)); } )+ @@ -1351,13 +1384,14 @@ tuple_impls! { //////////////////////////////////////////////////////////////////////////////// -#[cfg(any(feature = "std", feature = "alloc"))] macro_rules! map_impl { ( - $ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >, + $(#[$attr:meta])* + $ty:ident , $access:ident, - $with_capacity:expr + $with_capacity:expr, ) => { + $(#[$attr])* impl<'de, K, V $(, $typaram)*> Deserialize<'de> for $ty where K: Deserialize<'de> $(+ $kbound1 $(+ $kbound2)*)*, @@ -1391,7 +1425,7 @@ macro_rules! map_impl { { let mut values = $with_capacity; - while let Some((key, value)) = try!($access.next_entry()) { + while let Some((key, value)) = tri!($access.next_entry()) { values.insert(key, value); } @@ -1406,23 +1440,30 @@ macro_rules! map_impl { } } -#[cfg(any(feature = "std", feature = "alloc"))] -map_impl!( +map_impl! { + #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] BTreeMap, map, - BTreeMap::new()); + BTreeMap::new(), +} -#[cfg(feature = "std")] -map_impl!( +map_impl! { + #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] HashMap, map, - HashMap::with_capacity_and_hasher(size_hint::cautious(map.size_hint()), S::default())); + HashMap::with_capacity_and_hasher(size_hint::cautious::<(K, V)>(map.size_hint()), S::default()), +} //////////////////////////////////////////////////////////////////////////////// -#[cfg(feature = "std")] macro_rules! parse_ip_impl { - ($expecting:tt $ty:ty; $size:tt) => { + ( + $(#[$attr:meta])* + $ty:ty, $expecting:expr, $size:tt + ) => { + $(#[$attr])* impl<'de> Deserialize<'de> for $ty { fn deserialize(deserializer: D) -> Result where @@ -1441,15 +1482,15 @@ macro_rules! parse_ip_impl { #[cfg(feature = "std")] macro_rules! variant_identifier { ( - $name_kind: ident ( $($variant: ident; $bytes: expr; $index: expr),* ) - $expecting_message: expr, - $variants_name: ident + $name_kind:ident ($($variant:ident; $bytes:expr; $index:expr),*) + $expecting_message:expr, + $variants_name:ident ) => { enum $name_kind { - $( $variant ),* + $($variant),* } - static $variants_name: &'static [&'static str] = &[ $( stringify!($variant) ),*]; + static $variants_name: &[&str] = &[$(stringify!($variant)),*]; impl<'de> Deserialize<'de> for $name_kind { fn deserialize(deserializer: D) -> Result @@ -1516,12 +1557,12 @@ macro_rules! variant_identifier { #[cfg(feature = "std")] macro_rules! deserialize_enum { ( - $name: ident $name_kind: ident ( $($variant: ident; $bytes: expr; $index: expr),* ) - $expecting_message: expr, - $deserializer: expr + $name:ident $name_kind:ident ($($variant:ident; $bytes:expr; $index:expr),*) + $expecting_message:expr, + $deserializer:expr ) => { - variant_identifier!{ - $name_kind ( $($variant; $bytes; $index),* ) + variant_identifier! { + $name_kind ($($variant; $bytes; $index),*) $expecting_message, VARIANTS } @@ -1539,7 +1580,7 @@ macro_rules! deserialize_enum { where A: EnumAccess<'de>, { - match try!(data.variant()) { + match tri!(data.variant()) { $( ($name_kind :: $variant, v) => v.newtype_variant().map($name :: $variant), )* @@ -1551,6 +1592,7 @@ macro_rules! deserialize_enum { } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl<'de> Deserialize<'de> for net::IpAddr { fn deserialize(deserializer: D) -> Result where @@ -1559,7 +1601,7 @@ impl<'de> Deserialize<'de> for net::IpAddr { if deserializer.is_human_readable() { deserializer.deserialize_str(FromStrVisitor::new("IP address")) } else { - use lib::net::IpAddr; + use crate::lib::net::IpAddr; deserialize_enum! { IpAddr IpAddrKind (V4; b"V4"; 0, V6; b"V6"; 1) "`V4` or `V6`", @@ -1569,15 +1611,25 @@ impl<'de> Deserialize<'de> for net::IpAddr { } } -#[cfg(feature = "std")] -parse_ip_impl!("IPv4 address" net::Ipv4Addr; 4); +parse_ip_impl! { + #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] + net::Ipv4Addr, "IPv4 address", 4 +} -#[cfg(feature = "std")] -parse_ip_impl!("IPv6 address" net::Ipv6Addr; 16); +parse_ip_impl! { + #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] + net::Ipv6Addr, "IPv6 address", 16 +} -#[cfg(feature = "std")] macro_rules! parse_socket_impl { - ($expecting:tt $ty:ty, $new:expr) => { + ( + $(#[$attr:meta])* + $ty:ty, $expecting:tt, + $new:expr, + ) => { + $(#[$attr])* impl<'de> Deserialize<'de> for $ty { fn deserialize(deserializer: D) -> Result where @@ -1586,7 +1638,7 @@ macro_rules! parse_socket_impl { if deserializer.is_human_readable() { deserializer.deserialize_str(FromStrVisitor::new($expecting)) } else { - <(_, u16)>::deserialize(deserializer).map(|(ip, port)| $new(ip, port)) + <(_, u16)>::deserialize(deserializer).map($new) } } } @@ -1594,6 +1646,7 @@ macro_rules! parse_socket_impl { } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl<'de> Deserialize<'de> for net::SocketAddr { fn deserialize(deserializer: D) -> Result where @@ -1602,7 +1655,7 @@ impl<'de> Deserialize<'de> for net::SocketAddr { if deserializer.is_human_readable() { deserializer.deserialize_str(FromStrVisitor::new("socket address")) } else { - use lib::net::SocketAddr; + use crate::lib::net::SocketAddr; deserialize_enum! { SocketAddr SocketAddrKind (V4; b"V4"; 0, V6; b"V6"; 1) "`V4` or `V6`", @@ -1612,13 +1665,19 @@ impl<'de> Deserialize<'de> for net::SocketAddr { } } -#[cfg(feature = "std")] -parse_socket_impl!("IPv4 socket address" net::SocketAddrV4, net::SocketAddrV4::new); +parse_socket_impl! { + #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] + net::SocketAddrV4, "IPv4 socket address", + |(ip, port)| net::SocketAddrV4::new(ip, port), +} -#[cfg(feature = "std")] -parse_socket_impl!("IPv6 socket address" net::SocketAddrV6, |ip, port| net::SocketAddrV6::new( - ip, port, 0, 0 -)); +parse_socket_impl! { + #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] + net::SocketAddrV6, "IPv6 socket address", + |(ip, port)| net::SocketAddrV6::new(ip, port, 0, 0), +} //////////////////////////////////////////////////////////////////////////////// @@ -1651,6 +1710,7 @@ impl<'a> Visitor<'a> for PathVisitor { } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl<'de: 'a, 'a> Deserialize<'de> for &'a Path { fn deserialize(deserializer: D) -> Result where @@ -1705,6 +1765,7 @@ impl<'de> Visitor<'de> for PathBufVisitor { } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl<'de> Deserialize<'de> for PathBuf { fn deserialize(deserializer: D) -> Result where @@ -1714,8 +1775,11 @@ impl<'de> Deserialize<'de> for PathBuf { } } -#[cfg(all(feature = "std", not(no_de_boxed_path)))] -forwarded_impl!((), Box, PathBuf::into_boxed_path); +forwarded_impl! { + #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] + (), Box, PathBuf::into_boxed_path +} //////////////////////////////////////////////////////////////////////////////// @@ -1748,7 +1812,7 @@ impl<'de> Visitor<'de> for OsStringVisitor { { use std::os::unix::ffi::OsStringExt; - match try!(data.variant()) { + match tri!(data.variant()) { (OsStringKind::Unix, v) => v.newtype_variant().map(OsString::from_vec), (OsStringKind::Windows, _) => Err(Error::custom( "cannot deserialize Windows OS string on Unix", @@ -1763,7 +1827,7 @@ impl<'de> Visitor<'de> for OsStringVisitor { { use std::os::windows::ffi::OsStringExt; - match try!(data.variant()) { + match tri!(data.variant()) { (OsStringKind::Windows, v) => v .newtype_variant::>() .map(|vec| OsString::from_wide(&vec)), @@ -1775,6 +1839,7 @@ impl<'de> Visitor<'de> for OsStringVisitor { } #[cfg(all(feature = "std", any(unix, windows)))] +#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", any(unix, windows)))))] impl<'de> Deserialize<'de> for OsString { fn deserialize(deserializer: D) -> Result where @@ -1786,40 +1851,32 @@ impl<'de> Deserialize<'de> for OsString { //////////////////////////////////////////////////////////////////////////////// -#[cfg(any(feature = "std", feature = "alloc"))] -forwarded_impl!((T), Box, Box::new); - -#[cfg(any(feature = "std", feature = "alloc"))] -forwarded_impl!((T), Box<[T]>, Vec::into_boxed_slice); - -#[cfg(any(feature = "std", feature = "alloc"))] -forwarded_impl!((), Box, String::into_boxed_str); - -#[cfg(all(no_de_rc_dst, feature = "rc", any(feature = "std", feature = "alloc")))] forwarded_impl! { - /// This impl requires the [`"rc"`] Cargo feature of Serde. - /// - /// Deserializing a data structure containing `Arc` will not attempt to - /// deduplicate `Arc` references to the same data. Every deserialized `Arc` - /// will end up with a strong count of 1. - /// - /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc - (T), Arc, Arc::new + #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + (T), Box, Box::new } -#[cfg(all(no_de_rc_dst, feature = "rc", any(feature = "std", feature = "alloc")))] forwarded_impl! { - /// This impl requires the [`"rc"`] Cargo feature of Serde. - /// - /// Deserializing a data structure containing `Rc` will not attempt to - /// deduplicate `Rc` references to the same data. Every deserialized `Rc` - /// will end up with a strong count of 1. - /// - /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc - (T), Rc, Rc::new + #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + (T), Box<[T]>, Vec::into_boxed_slice +} + +forwarded_impl! { + #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + (), Box, String::into_boxed_str +} + +forwarded_impl! { + #[cfg(all(feature = "std", any(unix, windows)))] + #[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", any(unix, windows)))))] + (), Box, OsString::into_boxed_os_str } #[cfg(any(feature = "std", feature = "alloc"))] +#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T> where T: ToOwned, @@ -1841,6 +1898,10 @@ where /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] +#[cfg_attr( + doc_cfg, + doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))) +)] impl<'de, T: ?Sized> Deserialize<'de> for RcWeak where T: Deserialize<'de>, @@ -1849,7 +1910,7 @@ where where D: Deserializer<'de>, { - try!(Option::::deserialize(deserializer)); + tri!(Option::::deserialize(deserializer)); Ok(RcWeak::new()) } } @@ -1859,6 +1920,10 @@ where /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] +#[cfg_attr( + doc_cfg, + doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))) +)] impl<'de, T: ?Sized> Deserialize<'de> for ArcWeak where T: Deserialize<'de>, @@ -1867,24 +1932,19 @@ where where D: Deserializer<'de>, { - try!(Option::::deserialize(deserializer)); + tri!(Option::::deserialize(deserializer)); Ok(ArcWeak::new()) } } //////////////////////////////////////////////////////////////////////////////// -#[cfg(all( - not(no_de_rc_dst), - feature = "rc", - any(feature = "std", feature = "alloc") -))] macro_rules! box_forwarded_impl { ( - $(#[doc = $doc:tt])* + $(#[$attr:meta])* $t:ident ) => { - $(#[doc = $doc])* + $(#[$attr])* impl<'de, T: ?Sized> Deserialize<'de> for $t where Box: Deserialize<'de>, @@ -1899,11 +1959,6 @@ macro_rules! box_forwarded_impl { }; } -#[cfg(all( - not(no_de_rc_dst), - feature = "rc", - any(feature = "std", feature = "alloc") -))] box_forwarded_impl! { /// This impl requires the [`"rc"`] Cargo feature of Serde. /// @@ -1912,14 +1967,11 @@ box_forwarded_impl! { /// will end up with a strong count of 1. /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc + #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] + #[cfg_attr(doc_cfg, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))] Rc } -#[cfg(all( - not(no_de_rc_dst), - feature = "rc", - any(feature = "std", feature = "alloc") -))] box_forwarded_impl! { /// This impl requires the [`"rc"`] Cargo feature of Serde. /// @@ -1928,6 +1980,8 @@ box_forwarded_impl! { /// will end up with a strong count of 1. /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc + #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] + #[cfg_attr(doc_cfg, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))] Arc } @@ -1945,13 +1999,21 @@ where } } -forwarded_impl!((T), RefCell, RefCell::new); +forwarded_impl! { + (T), RefCell, RefCell::new +} -#[cfg(feature = "std")] -forwarded_impl!((T), Mutex, Mutex::new); +forwarded_impl! { + #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] + (T), Mutex, Mutex::new +} -#[cfg(feature = "std")] -forwarded_impl!((T), RwLock, RwLock::new); +forwarded_impl! { + #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] + (T), RwLock, RwLock::new +} //////////////////////////////////////////////////////////////////////////////// @@ -1963,7 +2025,6 @@ forwarded_impl!((T), RwLock, RwLock::new); // secs: u64, // nanos: u32, // } -#[cfg(any(feature = "std", not(no_core_duration)))] impl<'de> Deserialize<'de> for Duration { fn deserialize(deserializer: D) -> Result where @@ -2011,8 +2072,8 @@ impl<'de> Deserialize<'de> for Duration { b"secs" => Ok(Field::Secs), b"nanos" => Ok(Field::Nanos), _ => { - let value = ::__private::from_utf8_lossy(value); - Err(Error::unknown_field(&value, FIELDS)) + let value = crate::__private::from_utf8_lossy(value); + Err(Error::unknown_field(&*value, FIELDS)) } } } @@ -2046,19 +2107,19 @@ impl<'de> Deserialize<'de> for Duration { where A: SeqAccess<'de>, { - let secs: u64 = match try!(seq.next_element()) { + let secs: u64 = match tri!(seq.next_element()) { Some(value) => value, None => { return Err(Error::invalid_length(0, &self)); } }; - let nanos: u32 = match try!(seq.next_element()) { + let nanos: u32 = match tri!(seq.next_element()) { Some(value) => value, None => { return Err(Error::invalid_length(1, &self)); } }; - try!(check_overflow(secs, nanos)); + tri!(check_overflow(secs, nanos)); Ok(Duration::new(secs, nanos)) } @@ -2068,19 +2129,19 @@ impl<'de> Deserialize<'de> for Duration { { let mut secs: Option = None; let mut nanos: Option = None; - while let Some(key) = try!(map.next_key()) { + while let Some(key) = tri!(map.next_key()) { match key { Field::Secs => { if secs.is_some() { return Err(::duplicate_field("secs")); } - secs = Some(try!(map.next_value())); + secs = Some(tri!(map.next_value())); } Field::Nanos => { if nanos.is_some() { return Err(::duplicate_field("nanos")); } - nanos = Some(try!(map.next_value())); + nanos = Some(tri!(map.next_value())); } } } @@ -2092,12 +2153,12 @@ impl<'de> Deserialize<'de> for Duration { Some(nanos) => nanos, None => return Err(::missing_field("nanos")), }; - try!(check_overflow(secs, nanos)); + tri!(check_overflow(secs, nanos)); Ok(Duration::new(secs, nanos)) } } - const FIELDS: &'static [&'static str] = &["secs", "nanos"]; + const FIELDS: &[&str] = &["secs", "nanos"]; deserializer.deserialize_struct("Duration", FIELDS, DurationVisitor) } } @@ -2105,6 +2166,7 @@ impl<'de> Deserialize<'de> for Duration { //////////////////////////////////////////////////////////////////////////////// #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl<'de> Deserialize<'de> for SystemTime { fn deserialize(deserializer: D) -> Result where @@ -2184,19 +2246,19 @@ impl<'de> Deserialize<'de> for SystemTime { where A: SeqAccess<'de>, { - let secs: u64 = match try!(seq.next_element()) { + let secs: u64 = match tri!(seq.next_element()) { Some(value) => value, None => { return Err(Error::invalid_length(0, &self)); } }; - let nanos: u32 = match try!(seq.next_element()) { + let nanos: u32 = match tri!(seq.next_element()) { Some(value) => value, None => { return Err(Error::invalid_length(1, &self)); } }; - try!(check_overflow(secs, nanos)); + tri!(check_overflow(secs, nanos)); Ok(Duration::new(secs, nanos)) } @@ -2206,7 +2268,7 @@ impl<'de> Deserialize<'de> for SystemTime { { let mut secs: Option = None; let mut nanos: Option = None; - while let Some(key) = try!(map.next_key()) { + while let Some(key) = tri!(map.next_key()) { match key { Field::Secs => { if secs.is_some() { @@ -2214,7 +2276,7 @@ impl<'de> Deserialize<'de> for SystemTime { "secs_since_epoch", )); } - secs = Some(try!(map.next_value())); + secs = Some(tri!(map.next_value())); } Field::Nanos => { if nanos.is_some() { @@ -2222,7 +2284,7 @@ impl<'de> Deserialize<'de> for SystemTime { "nanos_since_epoch", )); } - nanos = Some(try!(map.next_value())); + nanos = Some(tri!(map.next_value())); } } } @@ -2234,13 +2296,13 @@ impl<'de> Deserialize<'de> for SystemTime { Some(nanos) => nanos, None => return Err(::missing_field("nanos_since_epoch")), }; - try!(check_overflow(secs, nanos)); + tri!(check_overflow(secs, nanos)); Ok(Duration::new(secs, nanos)) } } - const FIELDS: &'static [&'static str] = &["secs_since_epoch", "nanos_since_epoch"]; - let duration = try!(deserializer.deserialize_struct("SystemTime", FIELDS, DurationVisitor)); + const FIELDS: &[&str] = &["secs_since_epoch", "nanos_since_epoch"]; + let duration = tri!(deserializer.deserialize_struct("SystemTime", FIELDS, DurationVisitor)); #[cfg(not(no_systemtime_checked_add))] let ret = UNIX_EPOCH .checked_add(duration) @@ -2257,9 +2319,9 @@ impl<'de> Deserialize<'de> for SystemTime { // // #[derive(Deserialize)] // #[serde(deny_unknown_fields)] -// struct Range { -// start: u64, -// end: u32, +// struct Range { +// start: Idx, +// end: Idx, // } impl<'de, Idx> Deserialize<'de> for Range where @@ -2269,19 +2331,18 @@ where where D: Deserializer<'de>, { - let (start, end) = deserializer.deserialize_struct( + let (start, end) = tri!(deserializer.deserialize_struct( "Range", range::FIELDS, range::RangeVisitor { expecting: "struct Range", phantom: PhantomData, }, - )?; + )); Ok(start..end) } } -#[cfg(not(no_range_inclusive))] impl<'de, Idx> Deserialize<'de> for RangeInclusive where Idx: Deserialize<'de>, @@ -2290,24 +2351,24 @@ where where D: Deserializer<'de>, { - let (start, end) = deserializer.deserialize_struct( + let (start, end) = tri!(deserializer.deserialize_struct( "RangeInclusive", range::FIELDS, range::RangeVisitor { expecting: "struct RangeInclusive", phantom: PhantomData, }, - )?; + )); Ok(RangeInclusive::new(start, end)) } } mod range { - use lib::*; + use crate::lib::*; - use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor}; + use crate::de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor}; - pub const FIELDS: &'static [&'static str] = &["start", "end"]; + pub const FIELDS: &[&str] = &["start", "end"]; // If this were outside of the serde crate, it would just use: // @@ -2351,8 +2412,8 @@ mod range { b"start" => Ok(Field::Start), b"end" => Ok(Field::End), _ => { - let value = ::__private::from_utf8_lossy(value); - Err(Error::unknown_field(&value, FIELDS)) + let value = crate::__private::from_utf8_lossy(value); + Err(Error::unknown_field(&*value, FIELDS)) } } } @@ -2381,13 +2442,13 @@ mod range { where A: SeqAccess<'de>, { - let start: Idx = match try!(seq.next_element()) { + let start: Idx = match tri!(seq.next_element()) { Some(value) => value, None => { return Err(Error::invalid_length(0, &self)); } }; - let end: Idx = match try!(seq.next_element()) { + let end: Idx = match tri!(seq.next_element()) { Some(value) => value, None => { return Err(Error::invalid_length(1, &self)); @@ -2402,19 +2463,19 @@ mod range { { let mut start: Option = None; let mut end: Option = None; - while let Some(key) = try!(map.next_key()) { + while let Some(key) = tri!(map.next_key()) { match key { Field::Start => { if start.is_some() { return Err(::duplicate_field("start")); } - start = Some(try!(map.next_value())); + start = Some(tri!(map.next_value())); } Field::End => { if end.is_some() { return Err(::duplicate_field("end")); } - end = Some(try!(map.next_value())); + end = Some(tri!(map.next_value())); } } } @@ -2433,7 +2494,282 @@ mod range { //////////////////////////////////////////////////////////////////////////////// -#[cfg(any(not(no_ops_bound), all(feature = "std", not(no_collections_bound))))] +// Similar to: +// +// #[derive(Deserialize)] +// #[serde(deny_unknown_fields)] +// struct RangeFrom { +// start: Idx, +// } +impl<'de, Idx> Deserialize<'de> for RangeFrom +where + Idx: Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let start = tri!(deserializer.deserialize_struct( + "RangeFrom", + range_from::FIELDS, + range_from::RangeFromVisitor { + expecting: "struct RangeFrom", + phantom: PhantomData, + }, + )); + Ok(start..) + } +} + +mod range_from { + use crate::lib::*; + + use crate::de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor}; + + pub const FIELDS: &[&str] = &["start"]; + + // If this were outside of the serde crate, it would just use: + // + // #[derive(Deserialize)] + // #[serde(field_identifier, rename_all = "lowercase")] + enum Field { + Start, + } + + impl<'de> Deserialize<'de> for Field { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct FieldVisitor; + + impl<'de> Visitor<'de> for FieldVisitor { + type Value = Field; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("`start`") + } + + fn visit_str(self, value: &str) -> Result + where + E: Error, + { + match value { + "start" => Ok(Field::Start), + _ => Err(Error::unknown_field(value, FIELDS)), + } + } + + fn visit_bytes(self, value: &[u8]) -> Result + where + E: Error, + { + match value { + b"start" => Ok(Field::Start), + _ => { + let value = crate::__private::from_utf8_lossy(value); + Err(Error::unknown_field(&*value, FIELDS)) + } + } + } + } + + deserializer.deserialize_identifier(FieldVisitor) + } + } + + pub struct RangeFromVisitor { + pub expecting: &'static str, + pub phantom: PhantomData, + } + + impl<'de, Idx> Visitor<'de> for RangeFromVisitor + where + Idx: Deserialize<'de>, + { + type Value = Idx; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str(self.expecting) + } + + fn visit_seq(self, mut seq: A) -> Result + where + A: SeqAccess<'de>, + { + let start: Idx = match tri!(seq.next_element()) { + Some(value) => value, + None => { + return Err(Error::invalid_length(0, &self)); + } + }; + Ok(start) + } + + fn visit_map(self, mut map: A) -> Result + where + A: MapAccess<'de>, + { + let mut start: Option = None; + while let Some(key) = tri!(map.next_key()) { + match key { + Field::Start => { + if start.is_some() { + return Err(::duplicate_field("start")); + } + start = Some(tri!(map.next_value())); + } + } + } + let start = match start { + Some(start) => start, + None => return Err(::missing_field("start")), + }; + Ok(start) + } + } +} + +//////////////////////////////////////////////////////////////////////////////// + +// Similar to: +// +// #[derive(Deserialize)] +// #[serde(deny_unknown_fields)] +// struct RangeTo { +// end: Idx, +// } +impl<'de, Idx> Deserialize<'de> for RangeTo +where + Idx: Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let end = tri!(deserializer.deserialize_struct( + "RangeTo", + range_to::FIELDS, + range_to::RangeToVisitor { + expecting: "struct RangeTo", + phantom: PhantomData, + }, + )); + Ok(..end) + } +} + +mod range_to { + use crate::lib::*; + + use crate::de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor}; + + pub const FIELDS: &[&str] = &["end"]; + + // If this were outside of the serde crate, it would just use: + // + // #[derive(Deserialize)] + // #[serde(field_identifier, rename_all = "lowercase")] + enum Field { + End, + } + + impl<'de> Deserialize<'de> for Field { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct FieldVisitor; + + impl<'de> Visitor<'de> for FieldVisitor { + type Value = Field; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("`end`") + } + + fn visit_str(self, value: &str) -> Result + where + E: Error, + { + match value { + "end" => Ok(Field::End), + _ => Err(Error::unknown_field(value, FIELDS)), + } + } + + fn visit_bytes(self, value: &[u8]) -> Result + where + E: Error, + { + match value { + b"end" => Ok(Field::End), + _ => { + let value = crate::__private::from_utf8_lossy(value); + Err(Error::unknown_field(&*value, FIELDS)) + } + } + } + } + + deserializer.deserialize_identifier(FieldVisitor) + } + } + + pub struct RangeToVisitor { + pub expecting: &'static str, + pub phantom: PhantomData, + } + + impl<'de, Idx> Visitor<'de> for RangeToVisitor + where + Idx: Deserialize<'de>, + { + type Value = Idx; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str(self.expecting) + } + + fn visit_seq(self, mut seq: A) -> Result + where + A: SeqAccess<'de>, + { + let end: Idx = match tri!(seq.next_element()) { + Some(value) => value, + None => { + return Err(Error::invalid_length(0, &self)); + } + }; + Ok(end) + } + + fn visit_map(self, mut map: A) -> Result + where + A: MapAccess<'de>, + { + let mut end: Option = None; + while let Some(key) = tri!(map.next_key()) { + match key { + Field::End => { + if end.is_some() { + return Err(::duplicate_field("end")); + } + end = Some(tri!(map.next_value())); + } + } + } + let end = match end { + Some(end) => end, + None => return Err(::missing_field("end")), + }; + Ok(end) + } + } +} + +//////////////////////////////////////////////////////////////////////////////// + impl<'de, T> Deserialize<'de> for Bound where T: Deserialize<'de>, @@ -2525,7 +2861,7 @@ where where A: EnumAccess<'de>, { - match try!(data.variant()) { + match tri!(data.variant()) { (Field::Unbounded, v) => v.unit_variant().map(|()| Bound::Unbounded), (Field::Included, v) => v.newtype_variant().map(Bound::Included), (Field::Excluded, v) => v.newtype_variant().map(Bound::Excluded), @@ -2533,7 +2869,7 @@ where } } - const VARIANTS: &'static [&'static str] = &["Unbounded", "Included", "Excluded"]; + const VARIANTS: &[&str] = &["Unbounded", "Included", "Excluded"]; deserializer.deserialize_enum("Bound", VARIANTS, BoundVisitor(PhantomData)) } @@ -2634,14 +2970,14 @@ where where A: EnumAccess<'de>, { - match try!(data.variant()) { + match tri!(data.variant()) { (Field::Ok, v) => v.newtype_variant().map(Ok), (Field::Err, v) => v.newtype_variant().map(Err), } } } - const VARIANTS: &'static [&'static str] = &["Ok", "Err"]; + const VARIANTS: &[&str] = &["Ok", "Err"]; deserializer.deserialize_enum("Result", VARIANTS, ResultVisitor(PhantomData)) } @@ -2663,8 +2999,10 @@ where #[cfg(all(feature = "std", not(no_std_atomic)))] macro_rules! atomic_impl { - ($($ty:ident)*) => { + ($($ty:ident $size:expr)*) => { $( + #[cfg(any(no_target_has_atomic, target_has_atomic = $size))] + #[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", target_has_atomic = $size))))] impl<'de> Deserialize<'de> for $ty { fn deserialize(deserializer: D) -> Result where @@ -2679,14 +3017,21 @@ macro_rules! atomic_impl { #[cfg(all(feature = "std", not(no_std_atomic)))] atomic_impl! { - AtomicBool - AtomicI8 AtomicI16 AtomicI32 AtomicIsize - AtomicU8 AtomicU16 AtomicU32 AtomicUsize + AtomicBool "8" + AtomicI8 "8" + AtomicI16 "16" + AtomicI32 "32" + AtomicIsize "ptr" + AtomicU8 "8" + AtomicU16 "16" + AtomicU32 "32" + AtomicUsize "ptr" } #[cfg(all(feature = "std", not(no_std_atomic64)))] atomic_impl! { - AtomicI64 AtomicU64 + AtomicI64 "64" + AtomicU64 "64" } #[cfg(feature = "std")] @@ -2699,7 +3044,7 @@ struct FromStrVisitor { impl FromStrVisitor { fn new(expecting: &'static str) -> Self { FromStrVisitor { - expecting: expecting, + expecting, ty: PhantomData, } } diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index 4ae47738..1924fe3d 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -30,7 +30,7 @@ //! # The Deserializer trait //! //! [`Deserializer`] implementations are provided by third-party crates, for -//! example [`serde_json`], [`serde_yaml`] and [`bincode`]. +//! example [`serde_json`], [`serde_yaml`] and [`postcard`]. //! //! A partial list of well-maintained formats is given on the [Serde //! website][data formats]. @@ -64,8 +64,8 @@ //! - RefCell\ //! - Mutex\ //! - RwLock\ -//! - Rc\ *(if* features = ["rc"] *is enabled)* -//! - Arc\ *(if* features = ["rc"] *is enabled)* +//! - Rc\ *(if* features = \["rc"\] *is enabled)* +//! - Arc\ *(if* features = \["rc"\] *is enabled)* //! - **Collection types**: //! - BTreeMap\ //! - BTreeSet\ @@ -104,7 +104,7 @@ //! [`Deserialize`]: ../trait.Deserialize.html //! [`Deserializer`]: ../trait.Deserializer.html //! [`LinkedHashMap`]: https://docs.rs/linked-hash-map/*/linked_hash_map/struct.LinkedHashMap.html -//! [`bincode`]: https://github.com/servo/bincode +//! [`postcard`]: https://github.com/jamesmunns/postcard //! [`linked-hash-map`]: https://crates.io/crates/linked-hash-map //! [`serde_derive`]: https://crates.io/crates/serde_derive //! [`serde_json`]: https://github.com/serde-rs/json @@ -112,26 +112,28 @@ //! [derive section of the manual]: https://serde.rs/derive.html //! [data formats]: https://serde.rs/#data-formats -use lib::*; +use crate::lib::*; //////////////////////////////////////////////////////////////////////////////// pub mod value; -#[cfg(not(no_integer128))] mod format; mod ignored_any; mod impls; -mod utf8; +pub(crate) mod size_hint; pub use self::ignored_any::IgnoredAny; +#[cfg(not(any(feature = "std", feature = "unstable")))] +#[doc(no_inline)] +pub use crate::std_error::Error as StdError; +#[cfg(all(feature = "unstable", not(feature = "std")))] +#[doc(no_inline)] +pub use core::error::Error as StdError; #[cfg(feature = "std")] #[doc(no_inline)] pub use std::error::Error as StdError; -#[cfg(not(feature = "std"))] -#[doc(no_inline)] -pub use std_error::Error as StdError; //////////////////////////////////////////////////////////////////////////////// @@ -162,7 +164,7 @@ macro_rules! declare_error_trait { /// /// The message should not be capitalized and should not end with a period. /// - /// ```edition2018 + /// ```edition2021 /// # use std::str::FromStr; /// # /// # struct IpAddr; @@ -307,7 +309,7 @@ declare_error_trait!(Error: Sized + Debug + Display); /// This is used as an argument to the `invalid_type`, `invalid_value`, and /// `invalid_length` methods of the `Error` trait to build error messages. /// -/// ```edition2018 +/// ```edition2021 /// # use std::fmt; /// # /// # use serde::de::{self, Unexpected, Visitor}; @@ -400,20 +402,20 @@ impl<'a> fmt::Display for Unexpected<'a> { Bool(b) => write!(formatter, "boolean `{}`", b), Unsigned(i) => write!(formatter, "integer `{}`", i), Signed(i) => write!(formatter, "integer `{}`", i), - Float(f) => write!(formatter, "floating point `{}`", f), + Float(f) => write!(formatter, "floating point `{}`", WithDecimalPoint(f)), Char(c) => write!(formatter, "character `{}`", c), Str(s) => write!(formatter, "string {:?}", s), - Bytes(_) => write!(formatter, "byte array"), - Unit => write!(formatter, "unit value"), - Option => write!(formatter, "Option value"), - NewtypeStruct => write!(formatter, "newtype struct"), - Seq => write!(formatter, "sequence"), - Map => write!(formatter, "map"), - Enum => write!(formatter, "enum"), - UnitVariant => write!(formatter, "unit variant"), - NewtypeVariant => write!(formatter, "newtype variant"), - TupleVariant => write!(formatter, "tuple variant"), - StructVariant => write!(formatter, "struct variant"), + Bytes(_) => formatter.write_str("byte array"), + Unit => formatter.write_str("unit value"), + Option => formatter.write_str("Option value"), + NewtypeStruct => formatter.write_str("newtype struct"), + Seq => formatter.write_str("sequence"), + Map => formatter.write_str("map"), + Enum => formatter.write_str("enum"), + UnitVariant => formatter.write_str("unit variant"), + NewtypeVariant => formatter.write_str("newtype variant"), + TupleVariant => formatter.write_str("tuple variant"), + StructVariant => formatter.write_str("struct variant"), Other(other) => formatter.write_str(other), } } @@ -432,10 +434,9 @@ impl<'a> fmt::Display for Unexpected<'a> { /// Within the context of a `Visitor` implementation, the `Visitor` itself /// (`&self`) is an implementation of this trait. /// -/// ```edition2018 -/// # use std::fmt; -/// # +/// ```edition2021 /// # use serde::de::{self, Unexpected, Visitor}; +/// # use std::fmt; /// # /// # struct Example; /// # @@ -457,7 +458,7 @@ impl<'a> fmt::Display for Unexpected<'a> { /// /// Outside of a `Visitor`, `&"..."` can be used. /// -/// ```edition2018 +/// ```edition2021 /// # use serde::de::{self, Unexpected}; /// # /// # fn example() -> Result<(), E> @@ -465,7 +466,10 @@ impl<'a> fmt::Display for Unexpected<'a> { /// # E: de::Error, /// # { /// # let v = true; -/// return Err(de::Error::invalid_type(Unexpected::Bool(v), &"a negative integer")); +/// return Err(de::Error::invalid_type( +/// Unexpected::Bool(v), +/// &"a negative integer", +/// )); /// # } /// ``` pub trait Expected { @@ -501,8 +505,8 @@ impl<'a> Display for Expected + 'a { /// by Serde. /// /// Serde provides `Deserialize` implementations for many Rust primitive and -/// standard library types. The complete list is [here][de]. All of these can -/// be deserialized using Serde out of the box. +/// standard library types. The complete list is [here][crate::de]. All of these +/// can be deserialized using Serde out of the box. /// /// Additionally, Serde provides a procedural macro called `serde_derive` to /// automatically generate `Deserialize` implementations for structs and enums @@ -518,7 +522,6 @@ impl<'a> Display for Expected + 'a { /// `LinkedHashMap` type that is deserializable by Serde because the crate /// provides an implementation of `Deserialize` for it. /// -/// [de]: https://docs.serde.rs/serde/de/index.html /// [derive]: https://serde.rs/derive.html /// [impl-deserialize]: https://serde.rs/impl-deserialize.html /// @@ -565,7 +568,7 @@ pub trait Deserialize<'de>: Sized { D: Deserializer<'de>, { // Default implementation just delegates to `deserialize` impl. - *place = Deserialize::deserialize(deserializer)?; + *place = tri!(Deserialize::deserialize(deserializer)); Ok(()) } } @@ -578,7 +581,7 @@ pub trait Deserialize<'de>: Sized { /// from the input string, but a `from_reader` function may only deserialize /// owned data. /// -/// ```edition2018 +/// ```edition2021 /// # use serde::de::{Deserialize, DeserializeOwned}; /// # use std::io::{Read, Result}; /// # @@ -617,7 +620,7 @@ impl DeserializeOwned for T where T: for<'de> Deserialize<'de> {} /// /// The canonical API for stateless deserialization looks like this: /// -/// ```edition2018 +/// ```edition2021 /// # use serde::Deserialize; /// # /// # enum Error {} @@ -631,7 +634,7 @@ impl DeserializeOwned for T where T: for<'de> Deserialize<'de> {} /// Adjusting an API like this to support stateful deserialization is a matter /// of accepting a seed as input: /// -/// ```edition2018 +/// ```edition2021 /// # use serde::de::DeserializeSeed; /// # /// # enum Error {} @@ -664,12 +667,11 @@ impl DeserializeOwned for T where T: for<'de> Deserialize<'de> {} /// into it. This requires stateful deserialization using the `DeserializeSeed` /// trait. /// -/// ```edition2018 +/// ```edition2021 +/// use serde::de::{Deserialize, DeserializeSeed, Deserializer, SeqAccess, Visitor}; /// use std::fmt; /// use std::marker::PhantomData; /// -/// use serde::de::{Deserialize, DeserializeSeed, Deserializer, SeqAccess, Visitor}; -/// /// // A DeserializeSeed implementation that uses stateful deserialization to /// // append array elements onto the end of an existing vector. The preexisting /// // state ("seed") in this case is the Vec. The `deserialize` method of @@ -708,6 +710,11 @@ impl DeserializeOwned for T where T: for<'de> Deserialize<'de> {} /// where /// A: SeqAccess<'de>, /// { +/// // Decrease the number of reallocations if there are many elements +/// if let Some(size_hint) = seq.size_hint() { +/// self.0.reserve(size_hint); +/// } +/// /// // Visit each element in the inner array and push it onto /// // the existing vector. /// while let Some(elem) = seq.next_element()? { @@ -857,10 +864,10 @@ where /// The `Deserializer` trait supports two entry point styles which enables /// different kinds of deserialization. /// -/// 1. The `deserialize` method. Self-describing data formats like JSON are able -/// to look at the serialized data and tell what it represents. For example -/// the JSON deserializer may see an opening curly brace (`{`) and know that -/// it is seeing a map. If the data format supports +/// 1. The `deserialize_any` method. Self-describing data formats like JSON are +/// able to look at the serialized data and tell what it represents. For +/// example the JSON deserializer may see an opening curly brace (`{`) and +/// know that it is seeing a map. If the data format supports /// `Deserializer::deserialize_any`, it will drive the Visitor using whatever /// type it sees in the input. JSON uses this approach when deserializing /// `serde_json::Value` which is an enum that can represent any JSON @@ -869,7 +876,7 @@ where /// `Deserializer::deserialize_any`. /// /// 2. The various `deserialize_*` methods. Non-self-describing formats like -/// Bincode need to be told what is in the input in order to deserialize it. +/// Postcard need to be told what is in the input in order to deserialize it. /// The `deserialize_*` methods are hints to the deserializer for how to /// interpret the next piece of input. Non-self-describing formats are not /// able to deserialize something like `serde_json::Value` which relies on @@ -879,7 +886,7 @@ where /// `Deserializer::deserialize_any` unless you need to be told by the /// Deserializer what type is in the input. Know that relying on /// `Deserializer::deserialize_any` means your data type will be able to -/// deserialize from self-describing formats only, ruling out Bincode and many +/// deserialize from self-describing formats only, ruling out Postcard and many /// others. /// /// [Serde data model]: https://serde.rs/data-model.html @@ -910,7 +917,7 @@ pub trait Deserializer<'de>: Sized { /// `Deserializer::deserialize_any` unless you need to be told by the /// Deserializer what type is in the input. Know that relying on /// `Deserializer::deserialize_any` means your data type will be able to - /// deserialize from self-describing formats only, ruling out Bincode and + /// deserialize from self-describing formats only, ruling out Postcard and /// many others. fn deserialize_any(self, visitor: V) -> Result where @@ -941,18 +948,15 @@ pub trait Deserializer<'de>: Sized { where V: Visitor<'de>; - serde_if_integer128! { - /// Hint that the `Deserialize` type is expecting an `i128` value. - /// - /// This method is available only on Rust compiler versions >=1.26. The - /// default behavior unconditionally returns an error. - fn deserialize_i128(self, visitor: V) -> Result - where - V: Visitor<'de> - { - let _ = visitor; - Err(Error::custom("i128 is not supported")) - } + /// Hint that the `Deserialize` type is expecting an `i128` value. + /// + /// The default behavior unconditionally returns an error. + fn deserialize_i128(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + let _ = visitor; + Err(Error::custom("i128 is not supported")) } /// Hint that the `Deserialize` type is expecting a `u8` value. @@ -975,18 +979,15 @@ pub trait Deserializer<'de>: Sized { where V: Visitor<'de>; - serde_if_integer128! { - /// Hint that the `Deserialize` type is expecting an `u128` value. - /// - /// This method is available only on Rust compiler versions >=1.26. The - /// default behavior unconditionally returns an error. - fn deserialize_u128(self, visitor: V) -> Result - where - V: Visitor<'de> - { - let _ = visitor; - Err(Error::custom("u128 is not supported")) - } + /// Hint that the `Deserialize` type is expecting an `u128` value. + /// + /// The default behavior unconditionally returns an error. + fn deserialize_u128(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + let _ = visitor; + Err(Error::custom("u128 is not supported")) } /// Hint that the `Deserialize` type is expecting a `f32` value. @@ -1151,10 +1152,10 @@ pub trait Deserializer<'de>: Sized { /// Some types have a human-readable form that may be somewhat expensive to /// construct, as well as a binary form that is compact and efficient. /// Generally text-based formats like JSON and YAML will prefer to use the - /// human-readable one and binary formats like Bincode will prefer the + /// human-readable one and binary formats like Postcard will prefer the /// compact one. /// - /// ```edition2018 + /// ```edition2021 /// # use std::ops::Add; /// # use std::str::FromStr; /// # @@ -1221,11 +1222,11 @@ pub trait Deserializer<'de>: Sized { #[doc(hidden)] fn __deserialize_content( self, - _: ::actually_private::T, + _: crate::actually_private::T, visitor: V, - ) -> Result<::private::de::Content<'de>, Self::Error> + ) -> Result, Self::Error> where - V: Visitor<'de, Value = ::private::de::Content<'de>>, + V: Visitor<'de, Value = crate::__private::de::Content<'de>>, { self.deserialize_any(visitor) } @@ -1245,10 +1246,9 @@ pub trait Deserializer<'de>: Sized { /// /// # Example /// -/// ```edition2018 -/// # use std::fmt; -/// # +/// ```edition2021 /// # use serde::de::{self, Unexpected, Visitor}; +/// # use std::fmt; /// # /// /// A visitor that deserializes a long string - a string containing at least /// /// some minimum number of bytes. @@ -1286,7 +1286,7 @@ pub trait Visitor<'de>: Sized { /// "an integer between 0 and 64". The message should not be capitalized and /// should not end with a period. /// - /// ```edition2018 + /// ```edition2021 /// # use std::fmt; /// # /// # struct S { @@ -1359,20 +1359,20 @@ pub trait Visitor<'de>: Sized { Err(Error::invalid_type(Unexpected::Signed(v), &self)) } - serde_if_integer128! { - /// The input contains a `i128`. - /// - /// This method is available only on Rust compiler versions >=1.26. The - /// default implementation fails with a type error. - fn visit_i128(self, v: i128) -> Result - where - E: Error, - { - let mut buf = [0u8; 58]; - let mut writer = format::Buf::new(&mut buf); - fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as i128", v)).unwrap(); - Err(Error::invalid_type(Unexpected::Other(writer.as_str()), &self)) - } + /// The input contains a `i128`. + /// + /// The default implementation fails with a type error. + fn visit_i128(self, v: i128) -> Result + where + E: Error, + { + let mut buf = [0u8; 58]; + let mut writer = format::Buf::new(&mut buf); + fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as i128", v)).unwrap(); + Err(Error::invalid_type( + Unexpected::Other(writer.as_str()), + &self, + )) } /// The input contains a `u8`. @@ -1421,20 +1421,20 @@ pub trait Visitor<'de>: Sized { Err(Error::invalid_type(Unexpected::Unsigned(v), &self)) } - serde_if_integer128! { - /// The input contains a `u128`. - /// - /// This method is available only on Rust compiler versions >=1.26. The - /// default implementation fails with a type error. - fn visit_u128(self, v: u128) -> Result - where - E: Error, - { - let mut buf = [0u8; 57]; - let mut writer = format::Buf::new(&mut buf); - fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as u128", v)).unwrap(); - Err(Error::invalid_type(Unexpected::Other(writer.as_str()), &self)) - } + /// The input contains a `u128`. + /// + /// The default implementation fails with a type error. + fn visit_u128(self, v: u128) -> Result + where + E: Error, + { + let mut buf = [0u8; 57]; + let mut writer = format::Buf::new(&mut buf); + fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as u128", v)).unwrap(); + Err(Error::invalid_type( + Unexpected::Other(writer.as_str()), + &self, + )) } /// The input contains an `f32`. @@ -1470,7 +1470,7 @@ pub trait Visitor<'de>: Sized { where E: Error, { - self.visit_str(utf8::encode(v).as_str()) + self.visit_str(v.encode_utf8(&mut [0u8; 4])) } /// The input contains a string. The lifetime of the string is ephemeral and @@ -1525,6 +1525,7 @@ pub trait Visitor<'de>: Sized { /// `String`. #[inline] #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] fn visit_string(self, v: String) -> Result where E: Error, @@ -1547,7 +1548,6 @@ pub trait Visitor<'de>: Sized { where E: Error, { - let _ = v; Err(Error::invalid_type(Unexpected::Bytes(v), &self)) } @@ -1555,7 +1555,7 @@ pub trait Visitor<'de>: Sized { /// `Deserializer`. /// /// This enables zero-copy deserialization of bytes in some formats. For - /// example Bincode data containing bytes can be deserialized with zero + /// example Postcard data containing bytes can be deserialized with zero /// copying into a `&'a [u8]` as long as the input data outlives `'a`. /// /// The default implementation forwards to `visit_bytes`. @@ -1584,6 +1584,7 @@ pub trait Visitor<'de>: Sized { /// The default implementation forwards to `visit_bytes` and then drops the /// `Vec`. #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] fn visit_byte_buf(self, v: Vec) -> Result where E: Error, @@ -1827,9 +1828,9 @@ pub trait MapAccess<'de> { K: DeserializeSeed<'de>, V: DeserializeSeed<'de>, { - match try!(self.next_key_seed(kseed)) { + match tri!(self.next_key_seed(kseed)) { Some(key) => { - let value = try!(self.next_value_seed(vseed)); + let value = tri!(self.next_value_seed(vseed)); Ok(Some((key, value))) } None => Ok(None), @@ -2031,7 +2032,7 @@ pub trait VariantAccess<'de>: Sized { /// If the data contains a different type of variant, the following /// `invalid_type` error should be constructed: /// - /// ```edition2018 + /// ```edition2021 /// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected}; /// # /// # struct X; @@ -2071,7 +2072,7 @@ pub trait VariantAccess<'de>: Sized { /// If the data contains a different type of variant, the following /// `invalid_type` error should be constructed: /// - /// ```edition2018 + /// ```edition2021 /// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected}; /// # /// # struct X; @@ -2127,7 +2128,7 @@ pub trait VariantAccess<'de>: Sized { /// If the data contains a different type of variant, the following /// `invalid_type` error should be constructed: /// - /// ```edition2018 + /// ```edition2021 /// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected}; /// # /// # struct X; @@ -2144,11 +2145,7 @@ pub trait VariantAccess<'de>: Sized { /// # T: DeserializeSeed<'de>, /// # { unimplemented!() } /// # - /// fn tuple_variant( - /// self, - /// _len: usize, - /// _visitor: V, - /// ) -> Result + /// fn tuple_variant(self, _len: usize, _visitor: V) -> Result /// where /// V: Visitor<'de>, /// { @@ -2174,7 +2171,7 @@ pub trait VariantAccess<'de>: Sized { /// If the data contains a different type of variant, the following /// `invalid_type` error should be constructed: /// - /// ```edition2018 + /// ```edition2021 /// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected}; /// # /// # struct X; @@ -2234,10 +2231,10 @@ pub trait VariantAccess<'de>: Sized { /// /// # Example /// -/// ```edition2018 +/// ```edition2021 +/// use serde::de::{value, Deserialize, IntoDeserializer}; +/// use serde_derive::Deserialize; /// use std::str::FromStr; -/// use serde::Deserialize; -/// use serde::de::{value, IntoDeserializer}; /// /// #[derive(Deserialize)] /// enum Setting { @@ -2281,15 +2278,48 @@ impl Display for OneOf { 1 => write!(formatter, "`{}`", self.names[0]), 2 => write!(formatter, "`{}` or `{}`", self.names[0], self.names[1]), _ => { - try!(write!(formatter, "one of ")); + tri!(formatter.write_str("one of ")); for (i, alt) in self.names.iter().enumerate() { if i > 0 { - try!(write!(formatter, ", ")); + tri!(formatter.write_str(", ")); } - try!(write!(formatter, "`{}`", alt)); + tri!(write!(formatter, "`{}`", alt)); } Ok(()) } } } } + +struct WithDecimalPoint(f64); + +impl Display for WithDecimalPoint { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + struct LookForDecimalPoint<'f, 'a> { + formatter: &'f mut fmt::Formatter<'a>, + has_decimal_point: bool, + } + + impl<'f, 'a> fmt::Write for LookForDecimalPoint<'f, 'a> { + fn write_str(&mut self, fragment: &str) -> fmt::Result { + self.has_decimal_point |= fragment.contains('.'); + self.formatter.write_str(fragment) + } + + fn write_char(&mut self, ch: char) -> fmt::Result { + self.has_decimal_point |= ch == '.'; + self.formatter.write_char(ch) + } + } + + let mut writer = LookForDecimalPoint { + formatter, + has_decimal_point: false, + }; + tri!(write!(writer, "{}", self.0)); + if !writer.has_decimal_point { + tri!(formatter.write_str(".0")); + } + Ok(()) + } +} diff --git a/serde/src/de/seed.rs b/serde/src/de/seed.rs index 13b7ea46..52fb89d8 100644 --- a/serde/src/de/seed.rs +++ b/serde/src/de/seed.rs @@ -1,4 +1,4 @@ -use de::{Deserialize, DeserializeSeed, Deserializer}; +use crate::de::{Deserialize, DeserializeSeed, Deserializer}; /// A DeserializeSeed helper for implementing deserialize_in_place Visitors. /// diff --git a/serde/src/private/size_hint.rs b/serde/src/de/size_hint.rs similarity index 50% rename from serde/src/private/size_hint.rs rename to serde/src/de/size_hint.rs index ca71e616..4a4fe25d 100644 --- a/serde/src/private/size_hint.rs +++ b/serde/src/de/size_hint.rs @@ -1,4 +1,4 @@ -use lib::*; +use crate::lib::*; pub fn from_bounds(iter: &I) -> Option where @@ -8,9 +8,17 @@ where } #[cfg(any(feature = "std", feature = "alloc"))] -#[inline] -pub fn cautious(hint: Option) -> usize { - cmp::min(hint.unwrap_or(0), 4096) +pub fn cautious(hint: Option) -> usize { + const MAX_PREALLOC_BYTES: usize = 1024 * 1024; + + if mem::size_of::() == 0 { + 0 + } else { + cmp::min( + hint.unwrap_or(0), + MAX_PREALLOC_BYTES / mem::size_of::(), + ) + } } fn helper(bounds: (usize, Option)) -> Option { diff --git a/serde/src/de/utf8.rs b/serde/src/de/utf8.rs deleted file mode 100644 index 576fd03c..00000000 --- a/serde/src/de/utf8.rs +++ /dev/null @@ -1,46 +0,0 @@ -use lib::*; - -const TAG_CONT: u8 = 0b1000_0000; -const TAG_TWO_B: u8 = 0b1100_0000; -const TAG_THREE_B: u8 = 0b1110_0000; -const TAG_FOUR_B: u8 = 0b1111_0000; -const MAX_ONE_B: u32 = 0x80; -const MAX_TWO_B: u32 = 0x800; -const MAX_THREE_B: u32 = 0x10000; - -#[inline] -pub fn encode(c: char) -> Encode { - let code = c as u32; - let mut buf = [0; 4]; - let pos = if code < MAX_ONE_B { - buf[3] = code as u8; - 3 - } else if code < MAX_TWO_B { - buf[2] = (code >> 6 & 0x1F) as u8 | TAG_TWO_B; - buf[3] = (code & 0x3F) as u8 | TAG_CONT; - 2 - } else if code < MAX_THREE_B { - buf[1] = (code >> 12 & 0x0F) as u8 | TAG_THREE_B; - buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT; - buf[3] = (code & 0x3F) as u8 | TAG_CONT; - 1 - } else { - buf[0] = (code >> 18 & 0x07) as u8 | TAG_FOUR_B; - buf[1] = (code >> 12 & 0x3F) as u8 | TAG_CONT; - buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT; - buf[3] = (code & 0x3F) as u8 | TAG_CONT; - 0 - }; - Encode { buf: buf, pos: pos } -} - -pub struct Encode { - buf: [u8; 4], - pos: usize, -} - -impl Encode { - pub fn as_str(&self) -> &str { - str::from_utf8(&self.buf[self.pos..]).unwrap() - } -} diff --git a/serde/src/de/value.rs b/serde/src/de/value.rs index 1b154c3a..3bc0c71c 100644 --- a/serde/src/de/value.rs +++ b/serde/src/de/value.rs @@ -1,10 +1,10 @@ //! Building blocks for deserializing basic values using the `IntoDeserializer` //! trait. //! -//! ```edition2018 +//! ```edition2021 +//! use serde::de::{value, Deserialize, IntoDeserializer}; +//! use serde_derive::Deserialize; //! use std::str::FromStr; -//! use serde::Deserialize; -//! use serde::de::{value, IntoDeserializer}; //! //! #[derive(Deserialize)] //! enum Setting { @@ -21,12 +21,11 @@ //! } //! ``` -use lib::*; +use crate::lib::*; use self::private::{First, Second}; -use __private::size_hint; -use de::{self, Deserializer, Expected, IntoDeserializer, SeqAccess, Visitor}; -use ser; +use crate::de::{self, size_hint, Deserializer, Expected, IntoDeserializer, SeqAccess, Visitor}; +use crate::ser; //////////////////////////////////////////////////////////////////////////////// @@ -113,6 +112,7 @@ impl Debug for Error { } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl error::Error for Error { fn description(&self) -> &str { &self.err @@ -128,9 +128,7 @@ where type Deserializer = UnitDeserializer; fn into_deserializer(self) -> UnitDeserializer { - UnitDeserializer { - marker: PhantomData, - } + UnitDeserializer::new() } } @@ -141,6 +139,15 @@ pub struct UnitDeserializer { impl_copy_clone!(UnitDeserializer); +impl UnitDeserializer { + #[allow(missing_docs)] + pub fn new() -> Self { + UnitDeserializer { + marker: PhantomData, + } + } +} + impl<'de, E> de::Deserializer<'de> for UnitDeserializer where E: de::Error, @@ -178,12 +185,14 @@ impl Debug for UnitDeserializer { /// A deserializer that cannot be instantiated. #[cfg(feature = "unstable")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "unstable")))] pub struct NeverDeserializer { never: !, marker: PhantomData, } #[cfg(feature = "unstable")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "unstable")))] impl<'de, E> IntoDeserializer<'de, E> for ! where E: de::Error, @@ -236,8 +245,15 @@ macro_rules! primitive_deserializer { type Deserializer = $name; fn into_deserializer(self) -> $name { + $name::new(self) + } + } + + impl $name { + #[allow(missing_docs)] + pub fn new(value: $ty) -> Self { $name { - value: self, + value, marker: PhantomData, } } @@ -279,20 +295,17 @@ primitive_deserializer!(i8, "an `i8`.", I8Deserializer, visit_i8); primitive_deserializer!(i16, "an `i16`.", I16Deserializer, visit_i16); primitive_deserializer!(i32, "an `i32`.", I32Deserializer, visit_i32); primitive_deserializer!(i64, "an `i64`.", I64Deserializer, visit_i64); +primitive_deserializer!(i128, "an `i128`.", I128Deserializer, visit_i128); primitive_deserializer!(isize, "an `isize`.", IsizeDeserializer, visit_i64 as i64); primitive_deserializer!(u8, "a `u8`.", U8Deserializer, visit_u8); primitive_deserializer!(u16, "a `u16`.", U16Deserializer, visit_u16); primitive_deserializer!(u64, "a `u64`.", U64Deserializer, visit_u64); +primitive_deserializer!(u128, "a `u128`.", U128Deserializer, visit_u128); primitive_deserializer!(usize, "a `usize`.", UsizeDeserializer, visit_u64 as u64); primitive_deserializer!(f32, "an `f32`.", F32Deserializer, visit_f32); primitive_deserializer!(f64, "an `f64`.", F64Deserializer, visit_f64); primitive_deserializer!(char, "a `char`.", CharDeserializer, visit_char); -serde_if_integer128! { - primitive_deserializer!(i128, "an `i128`.", I128Deserializer, visit_i128); - primitive_deserializer!(u128, "a `u128`.", U128Deserializer, visit_u128); -} - /// A deserializer holding a `u32`. pub struct U32Deserializer { value: u32, @@ -308,8 +321,15 @@ where type Deserializer = U32Deserializer; fn into_deserializer(self) -> U32Deserializer { + U32Deserializer::new(self) + } +} + +impl U32Deserializer { + #[allow(missing_docs)] + pub fn new(value: u32) -> Self { U32Deserializer { - value: self, + value, marker: PhantomData, } } @@ -390,8 +410,15 @@ where type Deserializer = StrDeserializer<'a, E>; fn into_deserializer(self) -> StrDeserializer<'a, E> { + StrDeserializer::new(self) + } +} + +impl<'a, E> StrDeserializer<'a, E> { + #[allow(missing_docs)] + pub fn new(value: &'a str) -> Self { StrDeserializer { - value: self, + value, marker: PhantomData, } } @@ -470,7 +497,7 @@ impl<'de, E> BorrowedStrDeserializer<'de, E> { /// Create a new borrowed deserializer from the given string. pub fn new(value: &'de str) -> BorrowedStrDeserializer<'de, E> { BorrowedStrDeserializer { - value: value, + value, marker: PhantomData, } } @@ -538,6 +565,7 @@ impl<'de, E> Debug for BorrowedStrDeserializer<'de, E> { /// A deserializer holding a `String`. #[cfg(any(feature = "std", feature = "alloc"))] +#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] pub struct StringDeserializer { value: String, marker: PhantomData, @@ -554,6 +582,7 @@ impl Clone for StringDeserializer { } #[cfg(any(feature = "std", feature = "alloc"))] +#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de, E> IntoDeserializer<'de, E> for String where E: de::Error, @@ -561,8 +590,16 @@ where type Deserializer = StringDeserializer; fn into_deserializer(self) -> StringDeserializer { + StringDeserializer::new(self) + } +} + +#[cfg(any(feature = "std", feature = "alloc"))] +impl StringDeserializer { + #[allow(missing_docs)] + pub fn new(value: String) -> Self { StringDeserializer { - value: self, + value, marker: PhantomData, } } @@ -604,7 +641,7 @@ where } #[cfg(any(feature = "std", feature = "alloc"))] -impl<'de, 'a, E> de::EnumAccess<'de> for StringDeserializer +impl<'de, E> de::EnumAccess<'de> for StringDeserializer where E: de::Error, { @@ -633,6 +670,7 @@ impl Debug for StringDeserializer { /// A deserializer holding a `Cow`. #[cfg(any(feature = "std", feature = "alloc"))] +#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] pub struct CowStrDeserializer<'a, E> { value: Cow<'a, str>, marker: PhantomData, @@ -649,6 +687,7 @@ impl<'a, E> Clone for CowStrDeserializer<'a, E> { } #[cfg(any(feature = "std", feature = "alloc"))] +#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de, 'a, E> IntoDeserializer<'de, E> for Cow<'a, str> where E: de::Error, @@ -656,8 +695,16 @@ where type Deserializer = CowStrDeserializer<'a, E>; fn into_deserializer(self) -> CowStrDeserializer<'a, E> { + CowStrDeserializer::new(self) + } +} + +#[cfg(any(feature = "std", feature = "alloc"))] +impl<'a, E> CowStrDeserializer<'a, E> { + #[allow(missing_docs)] + pub fn new(value: Cow<'a, str>) -> Self { CowStrDeserializer { - value: self, + value, marker: PhantomData, } } @@ -739,7 +786,7 @@ impl<'a, E> BytesDeserializer<'a, E> { /// Create a new deserializer from the given bytes. pub fn new(value: &'a [u8]) -> Self { BytesDeserializer { - value: value, + value, marker: PhantomData, } } @@ -798,7 +845,7 @@ impl<'de, E> BorrowedBytesDeserializer<'de, E> { /// Create a new borrowed deserializer from the given borrowed bytes. pub fn new(value: &'de [u8]) -> Self { BorrowedBytesDeserializer { - value: value, + value, marker: PhantomData, } } @@ -893,8 +940,8 @@ where where V: de::Visitor<'de>, { - let v = try!(visitor.visit_seq(&mut self)); - try!(self.end()); + let v = tri!(visitor.visit_seq(&mut self)); + tri!(self.end()); Ok(v) } @@ -936,7 +983,7 @@ struct ExpectedInSeq(usize); impl Expected for ExpectedInSeq { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { if self.0 == 1 { - write!(formatter, "1 element in sequence") + formatter.write_str("1 element in sequence") } else { write!(formatter, "{} elements in sequence", self.0) } @@ -959,6 +1006,7 @@ where //////////////////////////////////////////////////////////////////////////////// #[cfg(any(feature = "std", feature = "alloc"))] +#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de, T, E> IntoDeserializer<'de, E> for Vec where T: IntoDeserializer<'de, E>, @@ -972,6 +1020,7 @@ where } #[cfg(any(feature = "std", feature = "alloc"))] +#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de, T, E> IntoDeserializer<'de, E> for BTreeSet where T: IntoDeserializer<'de, E> + Eq + Ord, @@ -985,6 +1034,7 @@ where } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl<'de, T, S, E> IntoDeserializer<'de, E> for HashSet where T: IntoDeserializer<'de, E> + Eq + Hash, @@ -1009,7 +1059,7 @@ pub struct SeqAccessDeserializer { impl SeqAccessDeserializer { /// Construct a new `SeqAccessDeserializer`. pub fn new(seq: A) -> Self { - SeqAccessDeserializer { seq: seq } + SeqAccessDeserializer { seq } } } @@ -1118,8 +1168,8 @@ where where V: de::Visitor<'de>, { - let value = try!(visitor.visit_map(&mut self)); - try!(self.end()); + let value = tri!(visitor.visit_map(&mut self)); + tri!(self.end()); Ok(value) } @@ -1127,8 +1177,8 @@ where where V: de::Visitor<'de>, { - let value = try!(visitor.visit_seq(&mut self)); - try!(self.end()); + let value = tri!(visitor.visit_seq(&mut self)); + tri!(self.end()); Ok(value) } @@ -1192,8 +1242,8 @@ where { match self.next_pair() { Some((key, value)) => { - let key = try!(kseed.deserialize(key.into_deserializer())); - let value = try!(vseed.deserialize(value.into_deserializer())); + let key = tri!(kseed.deserialize(key.into_deserializer())); + let value = tri!(vseed.deserialize(value.into_deserializer())); Ok(Some((key, value))) } None => Ok(None), @@ -1297,7 +1347,7 @@ where V: de::Visitor<'de>, { let mut pair_visitor = PairVisitor(Some(self.0), Some(self.1), PhantomData); - let pair = try!(visitor.visit_seq(&mut pair_visitor)); + let pair = tri!(visitor.visit_seq(&mut pair_visitor)); if pair_visitor.1.is_none() { Ok(pair) } else { @@ -1361,7 +1411,7 @@ struct ExpectedInMap(usize); impl Expected for ExpectedInMap { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { if self.0 == 1 { - write!(formatter, "1 element in map") + formatter.write_str("1 element in map") } else { write!(formatter, "{} elements in map", self.0) } @@ -1371,6 +1421,7 @@ impl Expected for ExpectedInMap { //////////////////////////////////////////////////////////////////////////////// #[cfg(any(feature = "std", feature = "alloc"))] +#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de, K, V, E> IntoDeserializer<'de, E> for BTreeMap where K: IntoDeserializer<'de, E> + Eq + Ord, @@ -1385,6 +1436,7 @@ where } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl<'de, K, V, S, E> IntoDeserializer<'de, E> for HashMap where K: IntoDeserializer<'de, E> + Eq + Hash, @@ -1410,7 +1462,7 @@ pub struct MapAccessDeserializer { impl MapAccessDeserializer { /// Construct a new `MapAccessDeserializer`. pub fn new(map: A) -> Self { - MapAccessDeserializer { map: map } + MapAccessDeserializer { map } } } @@ -1457,7 +1509,7 @@ where where T: de::DeserializeSeed<'de>, { - match self.map.next_key_seed(seed)? { + match tri!(self.map.next_key_seed(seed)) { Some(key) => Ok((key, private::map_as_enum(self.map))), None => Err(de::Error::invalid_type(de::Unexpected::Map, &"enum")), } @@ -1466,10 +1518,47 @@ where //////////////////////////////////////////////////////////////////////////////// -mod private { - use lib::*; +/// A deserializer holding an `EnumAccess`. +#[derive(Clone, Debug)] +pub struct EnumAccessDeserializer { + access: A, +} - use de::{self, DeserializeSeed, Deserializer, MapAccess, Unexpected, VariantAccess, Visitor}; +impl EnumAccessDeserializer { + /// Construct a new `EnumAccessDeserializer`. + pub fn new(access: A) -> Self { + EnumAccessDeserializer { access } + } +} + +impl<'de, A> de::Deserializer<'de> for EnumAccessDeserializer +where + A: de::EnumAccess<'de>, +{ + type Error = A::Error; + + fn deserialize_any(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + visitor.visit_enum(self.access) + } + + forward_to_deserialize_any! { + bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string + bytes byte_buf option unit unit_struct newtype_struct seq tuple + tuple_struct map struct enum identifier ignored_any + } +} + +//////////////////////////////////////////////////////////////////////////////// + +mod private { + use crate::lib::*; + + use crate::de::{ + self, DeserializeSeed, Deserializer, MapAccess, Unexpected, VariantAccess, Visitor, + }; pub struct UnitOnly { marker: PhantomData, @@ -1534,7 +1623,7 @@ mod private { } pub fn map_as_enum(map: A) -> MapAsEnum { - MapAsEnum { map: map } + MapAsEnum { map } } impl<'de, A> VariantAccess<'de> for MapAsEnum @@ -1558,10 +1647,7 @@ mod private { where V: Visitor<'de>, { - self.map.next_value_seed(SeedTupleVariant { - len: len, - visitor: visitor, - }) + self.map.next_value_seed(SeedTupleVariant { len, visitor }) } fn struct_variant( @@ -1572,8 +1658,7 @@ mod private { where V: Visitor<'de>, { - self.map - .next_value_seed(SeedStructVariant { visitor: visitor }) + self.map.next_value_seed(SeedStructVariant { visitor }) } } diff --git a/serde/src/integer128.rs b/serde/src/integer128.rs index 904c2a23..2f94a644 100644 --- a/serde/src/integer128.rs +++ b/serde/src/integer128.rs @@ -1,82 +1,9 @@ -/// Conditional compilation depending on whether Serde is built with support for -/// 128-bit integers. -/// -/// Data formats that wish to support Rust compiler versions older than 1.26 -/// (or targets that lack 128-bit integers) may place the i128 / u128 methods -/// of their Serializer and Deserializer behind this macro. -/// -/// Data formats that require a minimum Rust compiler version of at least 1.26, -/// or do not target platforms that lack 128-bit integers, do not need to -/// bother with this macro and may assume support for 128-bit integers. -/// -/// ```edition2018 -/// # use serde::__private::doc::Error; -/// # -/// # struct MySerializer; -/// # -/// use serde::{serde_if_integer128, Serializer}; -/// -/// impl Serializer for MySerializer { -/// type Ok = (); -/// type Error = Error; -/// -/// fn serialize_i64(self, v: i64) -> Result { -/// /* ... */ -/// # unimplemented!() -/// } -/// -/// /* ... */ -/// -/// serde_if_integer128! { -/// fn serialize_i128(self, v: i128) -> Result { -/// /* ... */ -/// # unimplemented!() -/// } -/// -/// fn serialize_u128(self, v: u128) -> Result { -/// /* ... */ -/// # unimplemented!() -/// } -/// } -/// # -/// # serde::__serialize_unimplemented! { -/// # bool i8 i16 i32 u8 u16 u32 u64 f32 f64 char str bytes none some -/// # unit unit_struct unit_variant newtype_struct newtype_variant seq -/// # tuple tuple_struct tuple_variant map struct struct_variant -/// # } -/// } -/// ``` -/// -/// When Serde is built with support for 128-bit integers, this macro expands -/// transparently into just the input tokens. -/// -/// ```edition2018 -/// macro_rules! serde_if_integer128 { -/// ($($tt:tt)*) => { -/// $($tt)* -/// }; -/// } -/// ``` -/// -/// When built without support for 128-bit integers, this macro expands to -/// nothing. -/// -/// ```edition2018 -/// macro_rules! serde_if_integer128 { -/// ($($tt:tt)*) => {}; -/// } -/// ``` -#[cfg(not(no_integer128))] +// No longer used. Old versions of serde used this macro for supporting targets +// that did not yet have 128-bit integer support. #[macro_export] +#[doc(hidden)] macro_rules! serde_if_integer128 { ($($tt:tt)*) => { $($tt)* }; } - -#[cfg(no_integer128)] -#[macro_export] -#[doc(hidden)] -macro_rules! serde_if_integer128 { - ($($tt:tt)*) => {}; -} diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 8c97bffb..5cf44c1c 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -31,8 +31,7 @@ //! for Serde by the community. //! //! - [JSON], the ubiquitous JavaScript Object Notation used by many HTTP APIs. -//! - [Bincode], a compact binary format -//! used for IPC within the Servo rendering engine. +//! - [Postcard], a no\_std and embedded-systems friendly compact binary format. //! - [CBOR], a Concise Binary Object Representation designed for small message //! size without the need for version negotiation. //! - [YAML], a self-proclaimed human-friendly configuration language that ain't @@ -45,8 +44,9 @@ //! - [Avro], a binary format used within Apache Hadoop, with support for schema //! definition. //! - [JSON5], a superset of JSON including some productions from ES5. -//! - [Postcard], a no\_std and embedded-systems friendly compact binary format. //! - [URL] query strings, in the x-www-form-urlencoded format. +//! - [Starlark], the format used for describing build targets by the Bazel and +//! Buck build systems. *(serialization only)* //! - [Envy], a way to deserialize environment variables into Rust structs. //! *(deserialization only)* //! - [Envy Store], a way to deserialize [AWS Parameter Store] parameters into @@ -54,91 +54,103 @@ //! - [S-expressions], the textual representation of code and data used by the //! Lisp language family. //! - [D-Bus]'s binary wire format. -//! - [FlexBuffers], the schemaless cousin of Google's FlatBuffers zero-copy serialization format. +//! - [FlexBuffers], the schemaless cousin of Google's FlatBuffers zero-copy +//! serialization format. +//! - [Bencode], a simple binary format used in the BitTorrent protocol. +//! - [Token streams], for processing Rust procedural macro input. +//! *(deserialization only)* //! - [DynamoDB Items], the format used by [rusoto_dynamodb] to transfer data to //! and from DynamoDB. +//! - [Hjson], a syntax extension to JSON designed around human reading and +//! editing. *(deserialization only)* +//! - [CSV], Comma-separated values is a tabular text file format. //! //! [JSON]: https://github.com/serde-rs/json -//! [Bincode]: https://github.com/servo/bincode +//! [Postcard]: https://github.com/jamesmunns/postcard //! [CBOR]: https://github.com/enarx/ciborium //! [YAML]: https://github.com/dtolnay/serde-yaml //! [MessagePack]: https://github.com/3Hren/msgpack-rust -//! [TOML]: https://github.com/alexcrichton/toml-rs +//! [TOML]: https://docs.rs/toml //! [Pickle]: https://github.com/birkenfeld/serde-pickle //! [RON]: https://github.com/ron-rs/ron -//! [BSON]: https://github.com/zonyitoo/bson-rs -//! [Avro]: https://github.com/flavray/avro-rs +//! [BSON]: https://github.com/mongodb/bson-rust +//! [Avro]: https://docs.rs/apache-avro //! [JSON5]: https://github.com/callum-oakley/json5-rs -//! [Postcard]: https://github.com/jamesmunns/postcard //! [URL]: https://docs.rs/serde_qs +//! [Starlark]: https://github.com/dtolnay/serde-starlark //! [Envy]: https://github.com/softprops/envy //! [Envy Store]: https://github.com/softprops/envy-store //! [Cargo]: https://doc.rust-lang.org/cargo/reference/manifest.html -//! [AWS Parameter Store]: https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-paramstore.html +//! [AWS Parameter Store]: https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html //! [S-expressions]: https://github.com/rotty/lexpr-rs //! [D-Bus]: https://docs.rs/zvariant //! [FlexBuffers]: https://github.com/google/flatbuffers/tree/master/rust/flexbuffers +//! [Bencode]: https://github.com/P3KI/bendy +//! [Token streams]: https://github.com/oxidecomputer/serde_tokenstream //! [DynamoDB Items]: https://docs.rs/serde_dynamo //! [rusoto_dynamodb]: https://docs.rs/rusoto_dynamodb +//! [Hjson]: https://github.com/Canop/deser-hjson +//! [CSV]: https://docs.rs/csv //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.136")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.197")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] +// Show which crate feature enables conditionally compiled APIs in documentation. +#![cfg_attr(doc_cfg, feature(doc_cfg))] // Unstable functionality only if the user asks for it. For tracking and // discussion of these features please refer to this issue: // // https://github.com/serde-rs/serde/issues/812 -#![cfg_attr(feature = "unstable", feature(never_type))] +#![cfg_attr(feature = "unstable", feature(error_in_core, never_type))] #![allow(unknown_lints, bare_trait_objects, deprecated)] -#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))] // Ignored clippy and clippy_pedantic lints -#![cfg_attr( - feature = "cargo-clippy", - allow( - // clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704 - unnested_or_patterns, - // clippy bug: https://github.com/rust-lang/rust-clippy/issues/7768 - semicolon_if_nothing_returned, - // not available in our oldest supported compiler - checked_conversions, - empty_enum, - redundant_field_names, - redundant_static_lifetimes, - // integer and float ser/de requires these sorts of casts - cast_possible_truncation, - cast_possible_wrap, - cast_sign_loss, - // things are often more readable this way - cast_lossless, - module_name_repetitions, - option_if_let_else, - single_match_else, - type_complexity, - use_self, - zero_prefixed_literal, - // correctly used - enum_glob_use, - let_underscore_drop, - map_err_ignore, - result_unit_err, - wildcard_imports, - // not practical - needless_pass_by_value, - similar_names, - too_many_lines, - // preference - doc_markdown, - unseparated_literal_suffix, - // false positive - needless_doctest_main, - // noisy - missing_errors_doc, - must_use_candidate, - ) +#![allow( + // clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704 + clippy::unnested_or_patterns, + // clippy bug: https://github.com/rust-lang/rust-clippy/issues/7768 + clippy::semicolon_if_nothing_returned, + // not available in our oldest supported compiler + clippy::empty_enum, + clippy::type_repetition_in_bounds, // https://github.com/rust-lang/rust-clippy/issues/8772 + // integer and float ser/de requires these sorts of casts + clippy::cast_possible_truncation, + clippy::cast_possible_wrap, + clippy::cast_sign_loss, + // things are often more readable this way + clippy::cast_lossless, + clippy::module_name_repetitions, + clippy::single_match_else, + clippy::type_complexity, + clippy::use_self, + clippy::zero_prefixed_literal, + // correctly used + clippy::derive_partial_eq_without_eq, + clippy::enum_glob_use, + clippy::explicit_auto_deref, + clippy::incompatible_msrv, + clippy::let_underscore_untyped, + clippy::map_err_ignore, + clippy::new_without_default, + clippy::result_unit_err, + clippy::wildcard_imports, + // not practical + clippy::needless_pass_by_value, + clippy::similar_names, + clippy::too_many_lines, + // preference + clippy::doc_markdown, + clippy::unseparated_literal_suffix, + // false positive + clippy::needless_doctest_main, + // noisy + clippy::missing_errors_doc, + clippy::must_use_candidate, )] +// Restrictions +#![deny(clippy::question_mark_used)] // Rustc lints. #![deny(missing_docs, unused_imports)] @@ -158,21 +170,26 @@ mod lib { pub use std::*; } - pub use self::core::{cmp, iter, mem, num, ptr, slice, str}; pub use self::core::{f32, f64}; pub use self::core::{i16, i32, i64, i8, isize}; + pub use self::core::{iter, num, ptr, str}; pub use self::core::{u16, u32, u64, u8, usize}; + #[cfg(any(feature = "std", feature = "alloc"))] + pub use self::core::{cmp, mem, slice}; + pub use self::core::cell::{Cell, RefCell}; - pub use self::core::clone::{self, Clone}; - pub use self::core::convert::{self, From, Into}; - pub use self::core::default::{self, Default}; - pub use self::core::fmt::{self, Debug, Display}; + pub use self::core::clone; + pub use self::core::cmp::Reverse; + pub use self::core::convert; + pub use self::core::default; + pub use self::core::fmt::{self, Debug, Display, Write as FmtWrite}; pub use self::core::marker::{self, PhantomData}; pub use self::core::num::Wrapping; - pub use self::core::ops::Range; - pub use self::core::option::{self, Option}; - pub use self::core::result::{self, Result}; + pub use self::core::ops::{Bound, Range, RangeFrom, RangeInclusive, RangeTo}; + pub use self::core::option; + pub use self::core::result; + pub use self::core::time::Duration; #[cfg(all(feature = "alloc", not(feature = "std")))] pub use alloc::borrow::{Cow, ToOwned}; @@ -209,13 +226,23 @@ mod lib { #[cfg(feature = "std")] pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque}; + #[cfg(all(not(no_core_cstr), not(feature = "std")))] + pub use self::core::ffi::CStr; + #[cfg(feature = "std")] + pub use std::ffi::CStr; + + #[cfg(all(not(no_core_cstr), feature = "alloc", not(feature = "std")))] + pub use alloc::ffi::CString; + #[cfg(feature = "std")] + pub use std::ffi::CString; + #[cfg(feature = "std")] pub use std::{error, net}; #[cfg(feature = "std")] pub use std::collections::{HashMap, HashSet}; #[cfg(feature = "std")] - pub use std::ffi::{CStr, CString, OsStr, OsString}; + pub use std::ffi::{OsStr, OsString}; #[cfg(feature = "std")] pub use std::hash::{BuildHasher, Hash}; #[cfg(feature = "std")] @@ -227,28 +254,39 @@ mod lib { #[cfg(feature = "std")] pub use std::time::{SystemTime, UNIX_EPOCH}; - #[cfg(all(feature = "std", not(no_collections_bound), no_ops_bound))] - pub use std::collections::Bound; - - #[cfg(not(no_core_reverse))] - pub use self::core::cmp::Reverse; - - #[cfg(not(no_ops_bound))] - pub use self::core::ops::Bound; - - #[cfg(not(no_range_inclusive))] - pub use self::core::ops::RangeInclusive; - - #[cfg(all(feature = "std", not(no_std_atomic)))] + #[cfg(all(feature = "std", no_target_has_atomic, not(no_std_atomic)))] pub use std::sync::atomic::{ AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8, AtomicUsize, Ordering, }; - #[cfg(all(feature = "std", not(no_std_atomic64)))] + #[cfg(all(feature = "std", no_target_has_atomic, not(no_std_atomic64)))] pub use std::sync::atomic::{AtomicI64, AtomicU64}; - #[cfg(any(feature = "std", not(no_core_duration)))] - pub use self::core::time::Duration; + #[cfg(all(feature = "std", not(no_target_has_atomic)))] + pub use std::sync::atomic::Ordering; + #[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "8"))] + pub use std::sync::atomic::{AtomicBool, AtomicI8, AtomicU8}; + #[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "16"))] + pub use std::sync::atomic::{AtomicI16, AtomicU16}; + #[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "32"))] + pub use std::sync::atomic::{AtomicI32, AtomicU32}; + #[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "64"))] + pub use std::sync::atomic::{AtomicI64, AtomicU64}; + #[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "ptr"))] + pub use std::sync::atomic::{AtomicIsize, AtomicUsize}; +} + +// None of this crate's error handling needs the `From::from` error conversion +// performed implicitly by the `?` operator or the standard library's `try!` +// macro. This simplified macro gives a 5.5% improvement in compile time +// compared to standard `try!`, and 9% improvement compared to `?`. +macro_rules! tri { + ($expr:expr) => { + match $expr { + Ok(val) => val, + Err(err) => return Err(err), + } + }; } //////////////////////////////////////////////////////////////////////////////// @@ -263,24 +301,19 @@ pub mod de; pub mod ser; #[doc(inline)] -pub use de::{Deserialize, Deserializer}; +pub use crate::de::{Deserialize, Deserializer}; #[doc(inline)] -pub use ser::{Serialize, Serializer}; +pub use crate::ser::{Serialize, Serializer}; // Used by generated code and doc tests. Not public API. #[doc(hidden)] #[path = "private/mod.rs"] pub mod __private; -#[allow(unused_imports)] -use self::__private as export; -#[allow(unused_imports)] -use self::__private as private; - #[path = "de/seed.rs"] mod seed; -#[cfg(not(feature = "std"))] +#[cfg(not(any(feature = "std", feature = "unstable")))] mod std_error; // Re-export #[derive(Serialize, Deserialize)]. @@ -289,12 +322,12 @@ mod std_error; // be annoying for crates that provide handwritten impls or data formats. They // would need to disable default features and then explicitly re-enable std. #[cfg(feature = "serde_derive")] -#[allow(unused_imports)] -#[macro_use] extern crate serde_derive; + +/// Derive macro available if serde is built with `features = ["derive"]`. #[cfg(feature = "serde_derive")] -#[doc(hidden)] -pub use serde_derive::*; +#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))] +pub use serde_derive::{Deserialize, Serialize}; #[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))] mod actually_private { diff --git a/serde/src/macros.rs b/serde/src/macros.rs index 6502a23a..a8fd85a3 100644 --- a/serde/src/macros.rs +++ b/serde/src/macros.rs @@ -11,7 +11,7 @@ /// input. This requires repetitive implementations of all the [`Deserializer`] /// trait methods. /// -/// ```edition2018 +/// ```edition2021 /// # use serde::forward_to_deserialize_any; /// # use serde::de::{value, Deserializer, Visitor}; /// # @@ -47,7 +47,7 @@ /// methods so that they forward directly to [`Deserializer::deserialize_any`]. /// You can choose which methods to forward. /// -/// ```edition2018 +/// ```edition2021 /// # use serde::forward_to_deserialize_any; /// # use serde::de::{value, Deserializer, Visitor}; /// # @@ -78,11 +78,10 @@ /// called `V`. A different type parameter and a different lifetime can be /// specified explicitly if necessary. /// -/// ```edition2018 -/// # use std::marker::PhantomData; -/// # +/// ```edition2021 /// # use serde::forward_to_deserialize_any; /// # use serde::de::{value, Deserializer, Visitor}; +/// # use std::marker::PhantomData; /// # /// # struct MyDeserializer(PhantomData); /// # @@ -155,9 +154,7 @@ macro_rules! forward_to_deserialize_any_helper { forward_to_deserialize_any_method!{deserialize_i64<$l, $v>()} }; (i128<$l:tt, $v:ident>) => { - serde_if_integer128! { - forward_to_deserialize_any_method!{deserialize_i128<$l, $v>()} - } + forward_to_deserialize_any_method!{deserialize_i128<$l, $v>()} }; (u8<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_u8<$l, $v>()} @@ -172,9 +169,7 @@ macro_rules! forward_to_deserialize_any_helper { forward_to_deserialize_any_method!{deserialize_u64<$l, $v>()} }; (u128<$l:tt, $v:ident>) => { - serde_if_integer128! { - forward_to_deserialize_any_method!{deserialize_u128<$l, $v>()} - } + forward_to_deserialize_any_method!{deserialize_u128<$l, $v>()} }; (f32<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_f32<$l, $v>()} diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index f0697d64..883e6909 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -1,10 +1,13 @@ -use lib::*; +use crate::lib::*; -use de::value::{BorrowedBytesDeserializer, BytesDeserializer}; -use de::{Deserialize, Deserializer, Error, IntoDeserializer, Visitor}; +use crate::de::value::{BorrowedBytesDeserializer, BytesDeserializer}; +use crate::de::{ + Deserialize, DeserializeSeed, Deserializer, EnumAccess, Error, IntoDeserializer, VariantAccess, + Visitor, +}; #[cfg(any(feature = "std", feature = "alloc"))] -use de::{DeserializeSeed, MapAccess, Unexpected}; +use crate::de::{MapAccess, Unexpected}; #[cfg(any(feature = "std", feature = "alloc"))] pub use self::content::{ @@ -13,7 +16,7 @@ pub use self::content::{ TagOrContentField, TagOrContentFieldVisitor, TaggedContentVisitor, UntaggedUnitVisitor, }; -pub use seed::InPlaceSeed; +pub use crate::seed::InPlaceSeed; /// If the missing field is of type `Option` then treat is as `None`, /// otherwise it is an error. @@ -203,13 +206,13 @@ mod content { // This issue is tracking making some of this stuff public: // https://github.com/serde-rs/serde/issues/741 - use lib::*; + use crate::lib::*; - use __private::size_hint; - use actually_private; - use de::{ - self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, IgnoredAny, - MapAccess, SeqAccess, Unexpected, Visitor, + use crate::actually_private; + use crate::de::value::{MapDeserializer, SeqDeserializer}; + use crate::de::{ + self, size_hint, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, + IgnoredAny, MapAccess, SeqAccess, Unexpected, Visitor, }; /// Used from generated code to buffer the contents of the Deserializer when @@ -299,6 +302,17 @@ mod content { } } + impl<'de, E> de::IntoDeserializer<'de, E> for Content<'de> + where + E: de::Error, + { + type Deserializer = ContentDeserializer<'de, E>; + + fn into_deserializer(self) -> Self::Deserializer { + ContentDeserializer::new(self) + } + } + struct ContentVisitor<'de> { value: PhantomData>, } @@ -474,8 +488,9 @@ mod content { where V: SeqAccess<'de>, { - let mut vec = Vec::with_capacity(size_hint::cautious(visitor.size_hint())); - while let Some(e) = try!(visitor.next_element()) { + let mut vec = + Vec::::with_capacity(size_hint::cautious::(visitor.size_hint())); + while let Some(e) = tri!(visitor.next_element()) { vec.push(e); } Ok(Content::Seq(vec)) @@ -485,8 +500,11 @@ mod content { where V: MapAccess<'de>, { - let mut vec = Vec::with_capacity(size_hint::cautious(visitor.size_hint())); - while let Some(kv) = try!(visitor.next_entry()) { + let mut vec = + Vec::<(Content, Content)>::with_capacity( + size_hint::cautious::<(Content, Content)>(visitor.size_hint()), + ); + while let Some(kv) = tri!(visitor.next_entry()) { vec.push(kv); } Ok(Content::Map(vec)) @@ -518,7 +536,7 @@ mod content { impl<'de> TagOrContentVisitor<'de> { fn new(name: &'static str) -> Self { TagOrContentVisitor { - name: name, + name, value: PhantomData, } } @@ -797,51 +815,29 @@ mod content { /// Used by generated code to deserialize an internally tagged enum. /// /// Not public API. - pub struct TaggedContent<'de, T> { - pub tag: T, - pub content: Content<'de>, - } - - /// Not public API. - pub struct TaggedContentVisitor<'de, T> { + pub struct TaggedContentVisitor { tag_name: &'static str, expecting: &'static str, - value: PhantomData>, + value: PhantomData, } - impl<'de, T> TaggedContentVisitor<'de, T> { + impl TaggedContentVisitor { /// Visitor for the content of an internally tagged enum with the given /// tag name. pub fn new(name: &'static str, expecting: &'static str) -> Self { TaggedContentVisitor { tag_name: name, - expecting: expecting, + expecting, value: PhantomData, } } } - impl<'de, T> DeserializeSeed<'de> for TaggedContentVisitor<'de, T> + impl<'de, T> Visitor<'de> for TaggedContentVisitor where T: Deserialize<'de>, { - type Value = TaggedContent<'de, T>; - - fn deserialize(self, deserializer: D) -> Result - where - D: Deserializer<'de>, - { - // Internally tagged enums are only supported in self-describing - // formats. - deserializer.deserialize_any(self) - } - } - - impl<'de, T> Visitor<'de> for TaggedContentVisitor<'de, T> - where - T: Deserialize<'de>, - { - type Value = TaggedContent<'de, T>; + type Value = (T, Content<'de>); fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.write_str(self.expecting) @@ -851,17 +847,14 @@ mod content { where S: SeqAccess<'de>, { - let tag = match try!(seq.next_element()) { + let tag = match tri!(seq.next_element()) { Some(tag) => tag, None => { return Err(de::Error::missing_field(self.tag_name)); } }; let rest = de::value::SeqAccessDeserializer::new(seq); - Ok(TaggedContent { - tag: tag, - content: try!(Content::deserialize(rest)), - }) + Ok((tag, tri!(Content::deserialize(rest)))) } fn visit_map(self, mut map: M) -> Result @@ -869,27 +862,27 @@ mod content { M: MapAccess<'de>, { let mut tag = None; - let mut vec = Vec::with_capacity(size_hint::cautious(map.size_hint())); - while let Some(k) = try!(map.next_key_seed(TagOrContentVisitor::new(self.tag_name))) { + let mut vec = Vec::<(Content, Content)>::with_capacity(size_hint::cautious::<( + Content, + Content, + )>(map.size_hint())); + while let Some(k) = tri!(map.next_key_seed(TagOrContentVisitor::new(self.tag_name))) { match k { TagOrContent::Tag => { if tag.is_some() { return Err(de::Error::duplicate_field(self.tag_name)); } - tag = Some(try!(map.next_value())); + tag = Some(tri!(map.next_value())); } TagOrContent::Content(k) => { - let v = try!(map.next_value()); + let v = tri!(map.next_value()); vec.push((k, v)); } } } match tag { None => Err(de::Error::missing_field(self.tag_name)), - Some(tag) => Ok(TaggedContent { - tag: tag, - content: Content::Map(vec), - }), + Some(tag) => Ok((tag, Content::Map(vec))), } } } @@ -915,7 +908,7 @@ mod content { where D: Deserializer<'de>, { - deserializer.deserialize_str(self) + deserializer.deserialize_identifier(self) } } @@ -926,6 +919,20 @@ mod content { write!(formatter, "{:?} or {:?}", self.tag, self.content) } + fn visit_u64(self, field_index: u64) -> Result + where + E: de::Error, + { + match field_index { + 0 => Ok(TagOrContentField::Tag), + 1 => Ok(TagOrContentField::Content), + _ => Err(de::Error::invalid_value( + Unexpected::Unsigned(field_index), + &self, + )), + } + } + fn visit_str(self, field: &str) -> Result where E: de::Error, @@ -938,6 +945,19 @@ mod content { Err(de::Error::invalid_value(Unexpected::Str(field), &self)) } } + + fn visit_bytes(self, field: &[u8]) -> Result + where + E: de::Error, + { + if field == self.tag.as_bytes() { + Ok(TagOrContentField::Tag) + } else if field == self.content.as_bytes() { + Ok(TagOrContentField::Content) + } else { + Err(de::Error::invalid_value(Unexpected::Bytes(field), &self)) + } + } } /// Used by generated code to deserialize an adjacently tagged enum when @@ -963,7 +983,7 @@ mod content { where D: Deserializer<'de>, { - deserializer.deserialize_str(self) + deserializer.deserialize_identifier(self) } } @@ -978,13 +998,31 @@ mod content { ) } + fn visit_u64(self, field_index: u64) -> Result + where + E: de::Error, + { + match field_index { + 0 => Ok(TagContentOtherField::Tag), + 1 => Ok(TagContentOtherField::Content), + _ => Ok(TagContentOtherField::Other), + } + } + fn visit_str(self, field: &str) -> Result where E: de::Error, { - if field == self.tag { + self.visit_bytes(field.as_bytes()) + } + + fn visit_bytes(self, field: &[u8]) -> Result + where + E: de::Error, + { + if field == self.tag.as_bytes() { Ok(TagContentOtherField::Tag) - } else if field == self.content { + } else if field == self.content.as_bytes() { Ok(TagContentOtherField::Content) } else { Ok(TagContentOtherField::Other) @@ -1050,9 +1088,9 @@ mod content { E: de::Error, { let seq = content.into_iter().map(ContentDeserializer::new); - let mut seq_visitor = de::value::SeqDeserializer::new(seq); - let value = try!(visitor.visit_seq(&mut seq_visitor)); - try!(seq_visitor.end()); + let mut seq_visitor = SeqDeserializer::new(seq); + let value = tri!(visitor.visit_seq(&mut seq_visitor)); + tri!(seq_visitor.end()); Ok(value) } @@ -1067,9 +1105,9 @@ mod content { let map = content .into_iter() .map(|(k, v)| (ContentDeserializer::new(k), ContentDeserializer::new(v))); - let mut map_visitor = de::value::MapDeserializer::new(map); - let value = try!(visitor.visit_map(&mut map_visitor)); - try!(map_visitor.end()); + let mut map_visitor = MapDeserializer::new(map); + let value = tri!(visitor.visit_map(&mut map_visitor)); + tri!(map_visitor.end()); Ok(value) } @@ -1262,6 +1300,17 @@ mod content { { match self.content { Content::Unit => visitor.visit_unit(), + + // Allow deserializing newtype variant containing unit. + // + // #[derive(Deserialize)] + // #[serde(tag = "result")] + // enum Response { + // Success(T), + // } + // + // We want {"result":"Success"} to deserialize into Response<()>. + Content::Map(ref v) if v.is_empty() => visitor.visit_unit(), _ => Err(self.invalid_type(&visitor)), } } @@ -1446,7 +1495,7 @@ mod content { /// private API, don't use pub fn new(content: Content<'de>) -> Self { ContentDeserializer { - content: content, + content, err: PhantomData, } } @@ -1467,8 +1516,8 @@ mod content { { pub fn new(variant: Content<'de>, value: Option>) -> EnumDeserializer<'de, E> { EnumDeserializer { - variant: variant, - value: value, + variant, + value, err: PhantomData, } } @@ -1534,7 +1583,7 @@ mod content { { match self.value { Some(Content::Seq(v)) => { - de::Deserializer::deserialize_any(SeqDeserializer::new(v), visitor) + de::Deserializer::deserialize_any(SeqDeserializer::new(v.into_iter()), visitor) } Some(other) => Err(de::Error::invalid_type( other.unexpected(), @@ -1557,10 +1606,10 @@ mod content { { match self.value { Some(Content::Map(v)) => { - de::Deserializer::deserialize_any(MapDeserializer::new(v), visitor) + de::Deserializer::deserialize_any(MapDeserializer::new(v.into_iter()), visitor) } Some(Content::Seq(v)) => { - de::Deserializer::deserialize_any(SeqDeserializer::new(v), visitor) + de::Deserializer::deserialize_any(SeqDeserializer::new(v.into_iter()), visitor) } Some(other) => Err(de::Error::invalid_type( other.unexpected(), @@ -1574,156 +1623,6 @@ mod content { } } - struct SeqDeserializer<'de, E> - where - E: de::Error, - { - iter: > as IntoIterator>::IntoIter, - err: PhantomData, - } - - impl<'de, E> SeqDeserializer<'de, E> - where - E: de::Error, - { - fn new(vec: Vec>) -> Self { - SeqDeserializer { - iter: vec.into_iter(), - err: PhantomData, - } - } - } - - impl<'de, E> de::Deserializer<'de> for SeqDeserializer<'de, E> - where - E: de::Error, - { - type Error = E; - - #[inline] - fn deserialize_any(mut self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - let len = self.iter.len(); - if len == 0 { - visitor.visit_unit() - } else { - let ret = try!(visitor.visit_seq(&mut self)); - let remaining = self.iter.len(); - if remaining == 0 { - Ok(ret) - } else { - Err(de::Error::invalid_length(len, &"fewer elements in array")) - } - } - } - - forward_to_deserialize_any! { - bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string - bytes byte_buf option unit unit_struct newtype_struct seq tuple - tuple_struct map struct enum identifier ignored_any - } - } - - impl<'de, E> de::SeqAccess<'de> for SeqDeserializer<'de, E> - where - E: de::Error, - { - type Error = E; - - fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> - where - T: de::DeserializeSeed<'de>, - { - match self.iter.next() { - Some(value) => seed.deserialize(ContentDeserializer::new(value)).map(Some), - None => Ok(None), - } - } - - fn size_hint(&self) -> Option { - size_hint::from_bounds(&self.iter) - } - } - - struct MapDeserializer<'de, E> - where - E: de::Error, - { - iter: , Content<'de>)> as IntoIterator>::IntoIter, - value: Option>, - err: PhantomData, - } - - impl<'de, E> MapDeserializer<'de, E> - where - E: de::Error, - { - fn new(map: Vec<(Content<'de>, Content<'de>)>) -> Self { - MapDeserializer { - iter: map.into_iter(), - value: None, - err: PhantomData, - } - } - } - - impl<'de, E> de::MapAccess<'de> for MapDeserializer<'de, E> - where - E: de::Error, - { - type Error = E; - - fn next_key_seed(&mut self, seed: T) -> Result, Self::Error> - where - T: de::DeserializeSeed<'de>, - { - match self.iter.next() { - Some((key, value)) => { - self.value = Some(value); - seed.deserialize(ContentDeserializer::new(key)).map(Some) - } - None => Ok(None), - } - } - - fn next_value_seed(&mut self, seed: T) -> Result - where - T: de::DeserializeSeed<'de>, - { - match self.value.take() { - Some(value) => seed.deserialize(ContentDeserializer::new(value)), - None => Err(de::Error::custom("value is missing")), - } - } - - fn size_hint(&self) -> Option { - size_hint::from_bounds(&self.iter) - } - } - - impl<'de, E> de::Deserializer<'de> for MapDeserializer<'de, E> - where - E: de::Error, - { - type Error = E; - - #[inline] - fn deserialize_any(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - visitor.visit_map(self) - } - - forward_to_deserialize_any! { - bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string - bytes byte_buf option unit unit_struct newtype_struct seq tuple - tuple_struct map struct enum identifier ignored_any - } - } - /// Not public API. pub struct ContentRefDeserializer<'a, 'de: 'a, E> { content: &'a Content<'de>, @@ -1785,9 +1684,9 @@ mod content { E: de::Error, { let seq = content.iter().map(ContentRefDeserializer::new); - let mut seq_visitor = de::value::SeqDeserializer::new(seq); - let value = try!(visitor.visit_seq(&mut seq_visitor)); - try!(seq_visitor.end()); + let mut seq_visitor = SeqDeserializer::new(seq); + let value = tri!(visitor.visit_seq(&mut seq_visitor)); + tri!(seq_visitor.end()); Ok(value) } @@ -1799,15 +1698,15 @@ mod content { V: Visitor<'de>, E: de::Error, { - let map = content.iter().map(|&(ref k, ref v)| { + let map = content.iter().map(|(k, v)| { ( ContentRefDeserializer::new(k), ContentRefDeserializer::new(v), ) }); - let mut map_visitor = de::value::MapDeserializer::new(map); - let value = try!(visitor.visit_map(&mut map_visitor)); - try!(map_visitor.end()); + let mut map_visitor = MapDeserializer::new(map); + let value = tri!(visitor.visit_map(&mut map_visitor)); + tri!(map_visitor.end()); Ok(value) } @@ -2096,7 +1995,7 @@ mod content { let (variant, value) = match *self.content { Content::Map(ref value) => { let mut iter = value.iter(); - let &(ref variant, ref value) = match iter.next() { + let (variant, value) = match iter.next() { Some(v) => v, None => { return Err(de::Error::invalid_value( @@ -2124,8 +2023,8 @@ mod content { }; visitor.visit_enum(EnumRefDeserializer { - variant: variant, - value: value, + variant, + value, err: PhantomData, }) } @@ -2169,12 +2068,20 @@ mod content { /// private API, don't use pub fn new(content: &'a Content<'de>) -> Self { ContentRefDeserializer { - content: content, + content, err: PhantomData, } } } + impl<'a, 'de: 'a, E> Copy for ContentRefDeserializer<'a, 'de, E> {} + + impl<'a, 'de: 'a, E> Clone for ContentRefDeserializer<'a, 'de, E> { + fn clone(&self) -> Self { + *self + } + } + struct EnumRefDeserializer<'a, 'de: 'a, E> where E: de::Error, @@ -2243,7 +2150,7 @@ mod content { V: de::Visitor<'de>, { match self.value { - Some(&Content::Seq(ref v)) => { + Some(Content::Seq(v)) => { de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor) } Some(other) => Err(de::Error::invalid_type( @@ -2266,10 +2173,10 @@ mod content { V: de::Visitor<'de>, { match self.value { - Some(&Content::Map(ref v)) => { + Some(Content::Map(v)) => { de::Deserializer::deserialize_any(MapRefDeserializer::new(v), visitor) } - Some(&Content::Seq(ref v)) => { + Some(Content::Seq(v)) => { de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor) } Some(other) => Err(de::Error::invalid_type( @@ -2319,7 +2226,7 @@ mod content { if len == 0 { visitor.visit_unit() } else { - let ret = try!(visitor.visit_seq(&mut self)); + let ret = tri!(visitor.visit_seq(&mut self)); let remaining = self.iter.len(); if remaining == 0 { Ok(ret) @@ -2392,7 +2299,7 @@ mod content { T: de::DeserializeSeed<'de>, { match self.iter.next() { - Some(&(ref key, ref value)) => { + Some((key, value)) => { self.value = Some(value); seed.deserialize(ContentRefDeserializer::new(key)).map(Some) } @@ -2470,8 +2377,8 @@ mod content { /// Not public API. pub fn new(type_name: &'a str, variant_name: &'a str) -> Self { InternallyTaggedUnitVisitor { - type_name: type_name, - variant_name: variant_name, + type_name, + variant_name, } } } @@ -2498,7 +2405,7 @@ mod content { where M: MapAccess<'de>, { - while try!(access.next_entry::()).is_some() {} + while tri!(access.next_entry::()).is_some() {} Ok(()) } } @@ -2515,8 +2422,8 @@ mod content { /// Not public API. pub fn new(type_name: &'a str, variant_name: &'a str) -> Self { UntaggedUnitVisitor { - type_name: type_name, - variant_name: variant_name, + type_name, + variant_name, } } } @@ -2697,7 +2604,7 @@ where #[cfg(any(feature = "std", feature = "alloc"))] macro_rules! forward_to_deserialize_other { - ($($func:ident ( $($arg:ty),* ))*) => { + ($($func:ident ($($arg:ty),*))*) => { $( fn $func(self, $(_: $arg,)* _visitor: V) -> Result where @@ -2720,11 +2627,7 @@ where where V: Visitor<'de>, { - visitor.visit_map(FlatInternallyTaggedAccess { - iter: self.0.iter_mut(), - pending: None, - _marker: PhantomData, - }) + self.deserialize_map(visitor) } fn deserialize_enum( @@ -2736,17 +2639,8 @@ where where V: Visitor<'de>, { - for item in self.0.iter_mut() { - // items in the vector are nulled out when used. So we can only use - // an item if it's still filled in and if the field is one we care - // about. - let use_item = match *item { - None => false, - Some((ref c, _)) => c.as_str().map_or(false, |x| variants.contains(&x)), - }; - - if use_item { - let (key, value) = item.take().unwrap(); + for entry in self.0 { + if let Some((key, value)) = flat_map_take_entry(entry, variants) { return visitor.visit_enum(EnumDeserializer::new(key, Some(value))); } } @@ -2761,7 +2655,11 @@ where where V: Visitor<'de>, { - visitor.visit_map(FlatMapAccess::new(self.0.iter())) + visitor.visit_map(FlatMapAccess { + iter: self.0.iter(), + pending_content: None, + _marker: PhantomData, + }) } fn deserialize_struct( @@ -2773,7 +2671,12 @@ where where V: Visitor<'de>, { - visitor.visit_map(FlatStructAccess::new(self.0.iter_mut(), fields)) + visitor.visit_map(FlatStructAccess { + iter: self.0.iter_mut(), + pending_content: None, + fields, + _marker: PhantomData, + }) } fn deserialize_newtype_struct(self, _name: &str, visitor: V) -> Result @@ -2800,6 +2703,13 @@ where visitor.visit_unit() } + fn deserialize_ignored_any(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_unit() + } + forward_to_deserialize_other! { deserialize_bool() deserialize_i8() @@ -2822,30 +2732,16 @@ where deserialize_tuple(usize) deserialize_tuple_struct(&'static str, usize) deserialize_identifier() - deserialize_ignored_any() } } #[cfg(any(feature = "std", feature = "alloc"))] -pub struct FlatMapAccess<'a, 'de: 'a, E> { +struct FlatMapAccess<'a, 'de: 'a, E> { iter: slice::Iter<'a, Option<(Content<'de>, Content<'de>)>>, pending_content: Option<&'a Content<'de>>, _marker: PhantomData, } -#[cfg(any(feature = "std", feature = "alloc"))] -impl<'a, 'de, E> FlatMapAccess<'a, 'de, E> { - fn new( - iter: slice::Iter<'a, Option<(Content<'de>, Content<'de>)>>, - ) -> FlatMapAccess<'a, 'de, E> { - FlatMapAccess { - iter: iter, - pending_content: None, - _marker: PhantomData, - } - } -} - #[cfg(any(feature = "std", feature = "alloc"))] impl<'a, 'de, E> MapAccess<'de> for FlatMapAccess<'a, 'de, E> where @@ -2860,6 +2756,10 @@ where for item in &mut self.iter { // Items in the vector are nulled out when used by a struct. if let Some((ref key, ref content)) = *item { + // Do not take(), instead borrow this entry. The internally tagged + // enum does its own buffering so we can't tell whether this entry + // is going to be consumed. Borrowing here leaves the entry + // available for later flattened fields. self.pending_content = Some(content); return seed.deserialize(ContentRefDeserializer::new(key)).map(Some); } @@ -2879,28 +2779,13 @@ where } #[cfg(any(feature = "std", feature = "alloc"))] -pub struct FlatStructAccess<'a, 'de: 'a, E> { +struct FlatStructAccess<'a, 'de: 'a, E> { iter: slice::IterMut<'a, Option<(Content<'de>, Content<'de>)>>, pending_content: Option>, fields: &'static [&'static str], _marker: PhantomData, } -#[cfg(any(feature = "std", feature = "alloc"))] -impl<'a, 'de, E> FlatStructAccess<'a, 'de, E> { - fn new( - iter: slice::IterMut<'a, Option<(Content<'de>, Content<'de>)>>, - fields: &'static [&'static str], - ) -> FlatStructAccess<'a, 'de, E> { - FlatStructAccess { - iter: iter, - pending_content: None, - fields: fields, - _marker: PhantomData, - } - } -} - #[cfg(any(feature = "std", feature = "alloc"))] impl<'a, 'de, E> MapAccess<'de> for FlatStructAccess<'a, 'de, E> where @@ -2912,17 +2797,8 @@ where where T: DeserializeSeed<'de>, { - while let Some(item) = self.iter.next() { - // items in the vector are nulled out when used. So we can only use - // an item if it's still filled in and if the field is one we care - // about. In case we do not know which fields we want, we take them all. - let use_item = match *item { - None => false, - Some((ref c, _)) => c.as_str().map_or(false, |key| self.fields.contains(&key)), - }; - - if use_item { - let (key, content) = item.take().unwrap(); + for entry in self.iter.by_ref() { + if let Some((key, content)) = flat_map_take_entry(entry, self.fields) { self.pending_content = Some(content); return seed.deserialize(ContentDeserializer::new(key)).map(Some); } @@ -2941,44 +2817,76 @@ where } } +/// Claims one key-value pair from a FlatMapDeserializer's field buffer if the +/// field name matches any of the recognized ones. #[cfg(any(feature = "std", feature = "alloc"))] -pub struct FlatInternallyTaggedAccess<'a, 'de: 'a, E> { - iter: slice::IterMut<'a, Option<(Content<'de>, Content<'de>)>>, - pending: Option<&'a Content<'de>>, - _marker: PhantomData, +fn flat_map_take_entry<'de>( + entry: &mut Option<(Content<'de>, Content<'de>)>, + recognized: &[&str], +) -> Option<(Content<'de>, Content<'de>)> { + // Entries in the FlatMapDeserializer buffer are nulled out as they get + // claimed for deserialization. We only use an entry if it is still present + // and if the field is one recognized by the current data structure. + let is_recognized = match entry { + None => false, + Some((k, _v)) => k.as_str().map_or(false, |name| recognized.contains(&name)), + }; + + if is_recognized { + entry.take() + } else { + None + } } -#[cfg(any(feature = "std", feature = "alloc"))] -impl<'a, 'de, E> MapAccess<'de> for FlatInternallyTaggedAccess<'a, 'de, E> +pub struct AdjacentlyTaggedEnumVariantSeed { + pub enum_name: &'static str, + pub variants: &'static [&'static str], + pub fields_enum: PhantomData, +} + +pub struct AdjacentlyTaggedEnumVariantVisitor { + enum_name: &'static str, + fields_enum: PhantomData, +} + +impl<'de, F> Visitor<'de> for AdjacentlyTaggedEnumVariantVisitor where - E: Error, + F: Deserialize<'de>, { - type Error = E; + type Value = F; - fn next_key_seed(&mut self, seed: T) -> Result, Self::Error> - where - T: DeserializeSeed<'de>, - { - for item in &mut self.iter { - if let Some((ref key, ref content)) = *item { - // Do not take(), instead borrow this entry. The internally tagged - // enum does its own buffering so we can't tell whether this entry - // is going to be consumed. Borrowing here leaves the entry - // available for later flattened fields. - self.pending = Some(content); - return seed.deserialize(ContentRefDeserializer::new(key)).map(Some); - } - } - Ok(None) + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "variant of enum {}", self.enum_name) } - fn next_value_seed(&mut self, seed: T) -> Result + fn visit_enum(self, data: A) -> Result where - T: DeserializeSeed<'de>, + A: EnumAccess<'de>, { - match self.pending.take() { - Some(value) => seed.deserialize(ContentRefDeserializer::new(value)), - None => panic!("value is missing"), - } + let (variant, variant_access) = tri!(data.variant()); + tri!(variant_access.unit_variant()); + Ok(variant) + } +} + +impl<'de, F> DeserializeSeed<'de> for AdjacentlyTaggedEnumVariantSeed +where + F: Deserialize<'de>, +{ + type Value = F; + + fn deserialize(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_enum( + self.enum_name, + self.variants, + AdjacentlyTaggedEnumVariantVisitor { + enum_name: self.enum_name, + fields_enum: PhantomData, + }, + ) } } diff --git a/serde/src/private/doc.rs b/serde/src/private/doc.rs index f597af84..1b18fe6b 100644 --- a/serde/src/private/doc.rs +++ b/serde/src/private/doc.rs @@ -1,8 +1,8 @@ // Used only by Serde doc tests. Not public API. -use lib::*; +use crate::lib::*; -use ser; +use crate::ser; #[doc(hidden)] #[derive(Debug)] diff --git a/serde/src/private/mod.rs b/serde/src/private/mod.rs index e8969023..177f8501 100644 --- a/serde/src/private/mod.rs +++ b/serde/src/private/mod.rs @@ -3,30 +3,28 @@ pub mod de; #[cfg(not(no_serde_derive))] pub mod ser; -pub mod size_hint; - // FIXME: #[cfg(doctest)] once https://github.com/rust-lang/rust/issues/67295 is fixed. pub mod doc; -pub use lib::clone::Clone; -pub use lib::convert::{From, Into}; -pub use lib::default::Default; -pub use lib::fmt::{self, Formatter}; -pub use lib::marker::PhantomData; -pub use lib::option::Option::{self, None, Some}; -pub use lib::ptr; -pub use lib::result::Result::{self, Err, Ok}; +pub use crate::lib::clone::Clone; +pub use crate::lib::convert::{From, Into}; +pub use crate::lib::default::Default; +pub use crate::lib::fmt::{self, Formatter}; +pub use crate::lib::marker::PhantomData; +pub use crate::lib::option::Option::{self, None, Some}; +pub use crate::lib::ptr; +pub use crate::lib::result::Result::{self, Err, Ok}; pub use self::string::from_utf8_lossy; #[cfg(any(feature = "alloc", feature = "std"))] -pub use lib::{ToString, Vec}; +pub use crate::lib::{ToString, Vec}; #[cfg(not(no_core_try_from))] -pub use lib::convert::TryFrom; +pub use crate::lib::convert::TryFrom; mod string { - use lib::*; + use crate::lib::*; #[cfg(any(feature = "std", feature = "alloc"))] pub fn from_utf8_lossy(bytes: &[u8]) -> Cow { diff --git a/serde/src/private/ser.rs b/serde/src/private/ser.rs index 6ee99938..50bcb251 100644 --- a/serde/src/private/ser.rs +++ b/serde/src/private/ser.rs @@ -1,6 +1,6 @@ -use lib::*; +use crate::lib::*; -use ser::{self, Impossible, Serialize, SerializeMap, SerializeStruct, Serializer}; +use crate::ser::{self, Impossible, Serialize, SerializeMap, SerializeStruct, Serializer}; #[cfg(any(feature = "std", feature = "alloc"))] use self::content::{ @@ -27,10 +27,10 @@ where T: Serialize, { value.serialize(TaggedSerializer { - type_ident: type_ident, - variant_ident: variant_ident, - tag: tag, - variant_name: variant_name, + type_ident, + variant_ident, + tag, + variant_name, delegate: serializer, }) } @@ -51,7 +51,6 @@ enum Unsupported { String, ByteArray, Optional, - Unit, #[cfg(any(feature = "std", feature = "alloc"))] UnitStruct, Sequence, @@ -70,7 +69,6 @@ impl Display for Unsupported { Unsupported::String => formatter.write_str("a string"), Unsupported::ByteArray => formatter.write_str("a byte array"), Unsupported::Optional => formatter.write_str("an optional"), - Unsupported::Unit => formatter.write_str("unit"), #[cfg(any(feature = "std", feature = "alloc"))] Unsupported::UnitStruct => formatter.write_str("unit struct"), Unsupported::Sequence => formatter.write_str("a sequence"), @@ -184,12 +182,14 @@ where } fn serialize_unit(self) -> Result { - Err(self.bad_type(Unsupported::Unit)) + let mut map = tri!(self.delegate.serialize_map(Some(1))); + tri!(map.serialize_entry(self.tag, self.variant_name)); + map.end() } fn serialize_unit_struct(self, _: &'static str) -> Result { - let mut map = try!(self.delegate.serialize_map(Some(1))); - try!(map.serialize_entry(self.tag, self.variant_name)); + let mut map = tri!(self.delegate.serialize_map(Some(1))); + tri!(map.serialize_entry(self.tag, self.variant_name)); map.end() } @@ -199,9 +199,9 @@ where _: u32, inner_variant: &'static str, ) -> Result { - let mut map = try!(self.delegate.serialize_map(Some(2))); - try!(map.serialize_entry(self.tag, self.variant_name)); - try!(map.serialize_entry(inner_variant, &())); + let mut map = tri!(self.delegate.serialize_map(Some(2))); + tri!(map.serialize_entry(self.tag, self.variant_name)); + tri!(map.serialize_entry(inner_variant, &())); map.end() } @@ -226,9 +226,9 @@ where where T: Serialize, { - let mut map = try!(self.delegate.serialize_map(Some(2))); - try!(map.serialize_entry(self.tag, self.variant_name)); - try!(map.serialize_entry(inner_variant, inner_value)); + let mut map = tri!(self.delegate.serialize_map(Some(2))); + tri!(map.serialize_entry(self.tag, self.variant_name)); + tri!(map.serialize_entry(inner_variant, inner_value)); map.end() } @@ -269,9 +269,9 @@ where inner_variant: &'static str, len: usize, ) -> Result { - let mut map = try!(self.delegate.serialize_map(Some(2))); - try!(map.serialize_entry(self.tag, self.variant_name)); - try!(map.serialize_key(inner_variant)); + let mut map = tri!(self.delegate.serialize_map(Some(2))); + tri!(map.serialize_entry(self.tag, self.variant_name)); + tri!(map.serialize_key(inner_variant)); Ok(SerializeTupleVariantAsMapValue::new( map, inner_variant, @@ -280,8 +280,8 @@ where } fn serialize_map(self, len: Option) -> Result { - let mut map = try!(self.delegate.serialize_map(len.map(|len| len + 1))); - try!(map.serialize_entry(self.tag, self.variant_name)); + let mut map = tri!(self.delegate.serialize_map(len.map(|len| len + 1))); + tri!(map.serialize_entry(self.tag, self.variant_name)); Ok(map) } @@ -290,8 +290,8 @@ where name: &'static str, len: usize, ) -> Result { - let mut state = try!(self.delegate.serialize_struct(name, len + 1)); - try!(state.serialize_field(self.tag, self.variant_name)); + let mut state = tri!(self.delegate.serialize_struct(name, len + 1)); + tri!(state.serialize_field(self.tag, self.variant_name)); Ok(state) } @@ -316,9 +316,9 @@ where inner_variant: &'static str, len: usize, ) -> Result { - let mut map = try!(self.delegate.serialize_map(Some(2))); - try!(map.serialize_entry(self.tag, self.variant_name)); - try!(map.serialize_key(inner_variant)); + let mut map = tri!(self.delegate.serialize_map(Some(2))); + tri!(map.serialize_entry(self.tag, self.variant_name)); + tri!(map.serialize_key(inner_variant)); Ok(SerializeStructVariantAsMapValue::new( map, inner_variant, @@ -337,9 +337,9 @@ where #[cfg(any(feature = "std", feature = "alloc"))] mod content { - use lib::*; + use crate::lib::*; - use ser::{self, Serialize, Serializer}; + use crate::ser::{self, Serialize, Serializer}; pub struct SerializeTupleVariantAsMapValue { map: M, @@ -350,8 +350,8 @@ mod content { impl SerializeTupleVariantAsMapValue { pub fn new(map: M, name: &'static str, len: usize) -> Self { SerializeTupleVariantAsMapValue { - map: map, - name: name, + map, + name, fields: Vec::with_capacity(len), } } @@ -368,13 +368,13 @@ mod content { where T: Serialize, { - let value = try!(value.serialize(ContentSerializer::::new())); + let value = tri!(value.serialize(ContentSerializer::::new())); self.fields.push(value); Ok(()) } fn end(mut self) -> Result { - try!(self + tri!(self .map .serialize_value(&Content::TupleStruct(self.name, self.fields))); self.map.end() @@ -390,8 +390,8 @@ mod content { impl SerializeStructVariantAsMapValue { pub fn new(map: M, name: &'static str, len: usize) -> Self { SerializeStructVariantAsMapValue { - map: map, - name: name, + map, + name, fields: Vec::with_capacity(len), } } @@ -412,13 +412,13 @@ mod content { where T: Serialize, { - let value = try!(value.serialize(ContentSerializer::::new())); + let value = tri!(value.serialize(ContentSerializer::::new())); self.fields.push((key, value)); Ok(()) } fn end(mut self) -> Result { - try!(self + tri!(self .map .serialize_value(&Content::Struct(self.name, self.fields))); self.map.end() @@ -499,50 +499,50 @@ mod content { } Content::Seq(ref elements) => elements.serialize(serializer), Content::Tuple(ref elements) => { - use ser::SerializeTuple; - let mut tuple = try!(serializer.serialize_tuple(elements.len())); + use crate::ser::SerializeTuple; + let mut tuple = tri!(serializer.serialize_tuple(elements.len())); for e in elements { - try!(tuple.serialize_element(e)); + tri!(tuple.serialize_element(e)); } tuple.end() } Content::TupleStruct(n, ref fields) => { - use ser::SerializeTupleStruct; - let mut ts = try!(serializer.serialize_tuple_struct(n, fields.len())); + use crate::ser::SerializeTupleStruct; + let mut ts = tri!(serializer.serialize_tuple_struct(n, fields.len())); for f in fields { - try!(ts.serialize_field(f)); + tri!(ts.serialize_field(f)); } ts.end() } Content::TupleVariant(n, i, v, ref fields) => { - use ser::SerializeTupleVariant; - let mut tv = try!(serializer.serialize_tuple_variant(n, i, v, fields.len())); + use crate::ser::SerializeTupleVariant; + let mut tv = tri!(serializer.serialize_tuple_variant(n, i, v, fields.len())); for f in fields { - try!(tv.serialize_field(f)); + tri!(tv.serialize_field(f)); } tv.end() } Content::Map(ref entries) => { - use ser::SerializeMap; - let mut map = try!(serializer.serialize_map(Some(entries.len()))); - for &(ref k, ref v) in entries { - try!(map.serialize_entry(k, v)); + use crate::ser::SerializeMap; + let mut map = tri!(serializer.serialize_map(Some(entries.len()))); + for (k, v) in entries { + tri!(map.serialize_entry(k, v)); } map.end() } Content::Struct(n, ref fields) => { - use ser::SerializeStruct; - let mut s = try!(serializer.serialize_struct(n, fields.len())); + use crate::ser::SerializeStruct; + let mut s = tri!(serializer.serialize_struct(n, fields.len())); for &(k, ref v) in fields { - try!(s.serialize_field(k, v)); + tri!(s.serialize_field(k, v)); } s.end() } Content::StructVariant(n, i, v, ref fields) => { - use ser::SerializeStructVariant; - let mut sv = try!(serializer.serialize_struct_variant(n, i, v, fields.len())); + use crate::ser::SerializeStructVariant; + let mut sv = tri!(serializer.serialize_struct_variant(n, i, v, fields.len())); for &(k, ref v) in fields { - try!(sv.serialize_field(k, v)); + tri!(sv.serialize_field(k, v)); } sv.end() } @@ -639,7 +639,7 @@ mod content { where T: Serialize, { - Ok(Content::Some(Box::new(try!(value.serialize(self))))) + Ok(Content::Some(Box::new(tri!(value.serialize(self))))) } fn serialize_unit(self) -> Result { @@ -669,7 +669,7 @@ mod content { { Ok(Content::NewtypeStruct( name, - Box::new(try!(value.serialize(self))), + Box::new(tri!(value.serialize(self))), )) } @@ -687,7 +687,7 @@ mod content { name, variant_index, variant, - Box::new(try!(value.serialize(self))), + Box::new(tri!(value.serialize(self))), )) } @@ -711,7 +711,7 @@ mod content { len: usize, ) -> Result { Ok(SerializeTupleStruct { - name: name, + name, fields: Vec::with_capacity(len), error: PhantomData, }) @@ -725,9 +725,9 @@ mod content { len: usize, ) -> Result { Ok(SerializeTupleVariant { - name: name, - variant_index: variant_index, - variant: variant, + name, + variant_index, + variant, fields: Vec::with_capacity(len), error: PhantomData, }) @@ -747,7 +747,7 @@ mod content { len: usize, ) -> Result { Ok(SerializeStruct { - name: name, + name, fields: Vec::with_capacity(len), error: PhantomData, }) @@ -761,9 +761,9 @@ mod content { len: usize, ) -> Result { Ok(SerializeStructVariant { - name: name, - variant_index: variant_index, - variant: variant, + name, + variant_index, + variant, fields: Vec::with_capacity(len), error: PhantomData, }) @@ -786,7 +786,7 @@ mod content { where T: Serialize, { - let value = try!(value.serialize(ContentSerializer::::new())); + let value = tri!(value.serialize(ContentSerializer::::new())); self.elements.push(value); Ok(()) } @@ -812,7 +812,7 @@ mod content { where T: Serialize, { - let value = try!(value.serialize(ContentSerializer::::new())); + let value = tri!(value.serialize(ContentSerializer::::new())); self.elements.push(value); Ok(()) } @@ -839,7 +839,7 @@ mod content { where T: Serialize, { - let value = try!(value.serialize(ContentSerializer::::new())); + let value = tri!(value.serialize(ContentSerializer::::new())); self.fields.push(value); Ok(()) } @@ -868,7 +868,7 @@ mod content { where T: Serialize, { - let value = try!(value.serialize(ContentSerializer::::new())); + let value = tri!(value.serialize(ContentSerializer::::new())); self.fields.push(value); Ok(()) } @@ -900,7 +900,7 @@ mod content { where T: Serialize, { - let key = try!(key.serialize(ContentSerializer::::new())); + let key = tri!(key.serialize(ContentSerializer::::new())); self.key = Some(key); Ok(()) } @@ -913,7 +913,7 @@ mod content { .key .take() .expect("serialize_value called before serialize_key"); - let value = try!(value.serialize(ContentSerializer::::new())); + let value = tri!(value.serialize(ContentSerializer::::new())); self.entries.push((key, value)); Ok(()) } @@ -927,8 +927,8 @@ mod content { K: Serialize, V: Serialize, { - let key = try!(key.serialize(ContentSerializer::::new())); - let value = try!(value.serialize(ContentSerializer::::new())); + let key = tri!(key.serialize(ContentSerializer::::new())); + let value = tri!(value.serialize(ContentSerializer::::new())); self.entries.push((key, value)); Ok(()) } @@ -951,7 +951,7 @@ mod content { where T: Serialize, { - let value = try!(value.serialize(ContentSerializer::::new())); + let value = tri!(value.serialize(ContentSerializer::::new())); self.fields.push((key, value)); Ok(()) } @@ -980,7 +980,7 @@ mod content { where T: Serialize, { - let value = try!(value.serialize(ContentSerializer::::new())); + let value = tri!(value.serialize(ContentSerializer::::new())); self.fields.push((key, value)); Ok(()) } @@ -1025,7 +1025,7 @@ where type SerializeTupleStruct = Impossible; type SerializeMap = FlatMapSerializeMap<'a, M>; type SerializeStruct = FlatMapSerializeStruct<'a, M>; - type SerializeTupleVariant = Impossible; + type SerializeTupleVariant = FlatMapSerializeTupleVariantAsMapValue<'a, M>; type SerializeStructVariant = FlatMapSerializeStructVariantAsMapValue<'a, M>; fn serialize_bool(self, _: bool) -> Result { @@ -1133,7 +1133,7 @@ where where T: Serialize, { - try!(self.0.serialize_key(variant)); + tri!(self.0.serialize_key(variant)); self.0.serialize_value(value) } @@ -1157,10 +1157,11 @@ where self, _: &'static str, _: u32, - _: &'static str, + variant: &'static str, _: usize, ) -> Result { - Err(Self::bad_type(Unsupported::Enum)) + tri!(self.0.serialize_key(variant)); + Ok(FlatMapSerializeTupleVariantAsMapValue::new(self.0)) } fn serialize_map(self, _: Option) -> Result { @@ -1182,7 +1183,7 @@ where inner_variant: &'static str, _: usize, ) -> Result { - try!(self.0.serialize_key(inner_variant)); + tri!(self.0.serialize_key(inner_variant)); Ok(FlatMapSerializeStructVariantAsMapValue::new( self.0, inner_variant, @@ -1259,6 +1260,52 @@ where } } +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#[cfg(any(feature = "std", feature = "alloc"))] +pub struct FlatMapSerializeTupleVariantAsMapValue<'a, M: 'a> { + map: &'a mut M, + fields: Vec, +} + +#[cfg(any(feature = "std", feature = "alloc"))] +impl<'a, M> FlatMapSerializeTupleVariantAsMapValue<'a, M> +where + M: SerializeMap + 'a, +{ + fn new(map: &'a mut M) -> Self { + FlatMapSerializeTupleVariantAsMapValue { + map, + fields: Vec::new(), + } + } +} + +#[cfg(any(feature = "std", feature = "alloc"))] +impl<'a, M> ser::SerializeTupleVariant for FlatMapSerializeTupleVariantAsMapValue<'a, M> +where + M: SerializeMap + 'a, +{ + type Ok = (); + type Error = M::Error; + + fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> + where + T: Serialize, + { + let value = tri!(value.serialize(ContentSerializer::::new())); + self.fields.push(value); + Ok(()) + } + + fn end(self) -> Result<(), Self::Error> { + tri!(self.map.serialize_value(&Content::Seq(self.fields))); + Ok(()) + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + #[cfg(any(feature = "std", feature = "alloc"))] pub struct FlatMapSerializeStructVariantAsMapValue<'a, M: 'a> { map: &'a mut M, @@ -1273,8 +1320,8 @@ where { fn new(map: &'a mut M, name: &'static str) -> FlatMapSerializeStructVariantAsMapValue<'a, M> { FlatMapSerializeStructVariantAsMapValue { - map: map, - name: name, + map, + name, fields: Vec::new(), } } @@ -1296,15 +1343,43 @@ where where T: Serialize, { - let value = try!(value.serialize(ContentSerializer::::new())); + let value = tri!(value.serialize(ContentSerializer::::new())); self.fields.push((key, value)); Ok(()) } fn end(self) -> Result<(), Self::Error> { - try!(self + tri!(self .map .serialize_value(&Content::Struct(self.name, self.fields))); Ok(()) } } + +pub struct AdjacentlyTaggedEnumVariant { + pub enum_name: &'static str, + pub variant_index: u32, + pub variant_name: &'static str, +} + +impl Serialize for AdjacentlyTaggedEnumVariant { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_unit_variant(self.enum_name, self.variant_index, self.variant_name) + } +} + +// Error when Serialize for a non_exhaustive remote enum encounters a variant +// that is not recognized. +pub struct CannotSerializeVariant(pub T); + +impl Display for CannotSerializeVariant +where + T: Debug, +{ + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "enum variant cannot be serialized: {:?}", self.0) + } +} diff --git a/serde/src/ser/fmt.rs b/serde/src/ser/fmt.rs index e7e09a1b..0650ab6f 100644 --- a/serde/src/ser/fmt.rs +++ b/serde/src/ser/fmt.rs @@ -1,5 +1,5 @@ -use lib::*; -use ser::{Error, Impossible, Serialize, Serializer}; +use crate::lib::*; +use crate::ser::{Error, Impossible, Serialize, Serializer}; impl Error for fmt::Error { fn custom(_msg: T) -> Self { @@ -17,8 +17,9 @@ macro_rules! fmt_primitives { }; } -/// ```edition2018 -/// use serde::Serialize; +/// ```edition2021 +/// use serde::ser::Serialize; +/// use serde_derive::Serialize; /// use std::fmt::{self, Display}; /// /// #[derive(Serialize)] @@ -51,10 +52,12 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> { serialize_i16: i16, serialize_i32: i32, serialize_i64: i64, + serialize_i128: i128, serialize_u8: u8, serialize_u16: u16, serialize_u32: u32, serialize_u64: u64, + serialize_u128: u128, serialize_f32: f32, serialize_f64: f64, serialize_char: char, @@ -62,13 +65,6 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> { serialize_unit_struct: &'static str, } - serde_if_integer128! { - fmt_primitives! { - serialize_i128: i128, - serialize_u128: u128, - } - } - fn serialize_unit_variant( self, _name: &'static str, diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index 7219f51b..8c70634a 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -1,6 +1,6 @@ -use lib::*; +use crate::lib::*; -use ser::{Error, Serialize, SerializeTuple, Serializer}; +use crate::ser::{Error, Serialize, SerializeTuple, Serializer}; //////////////////////////////////////////////////////////////////////////////// @@ -24,20 +24,17 @@ primitive_impl!(i8, serialize_i8); primitive_impl!(i16, serialize_i16); primitive_impl!(i32, serialize_i32); primitive_impl!(i64, serialize_i64); +primitive_impl!(i128, serialize_i128); primitive_impl!(usize, serialize_u64 as u64); primitive_impl!(u8, serialize_u8); primitive_impl!(u16, serialize_u16); primitive_impl!(u32, serialize_u32); primitive_impl!(u64, serialize_u64); +primitive_impl!(u128, serialize_u128); primitive_impl!(f32, serialize_f32); primitive_impl!(f64, serialize_f64); primitive_impl!(char, serialize_char); -serde_if_integer128! { - primitive_impl!(i128, serialize_i128); - primitive_impl!(u128, serialize_u128); -} - //////////////////////////////////////////////////////////////////////////////// impl Serialize for str { @@ -51,6 +48,7 @@ impl Serialize for str { } #[cfg(any(feature = "std", feature = "alloc"))] +#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] impl Serialize for String { #[inline] fn serialize(&self, serializer: S) -> Result @@ -72,7 +70,8 @@ impl<'a> Serialize for fmt::Arguments<'a> { //////////////////////////////////////////////////////////////////////////////// -#[cfg(feature = "std")] +#[cfg(any(feature = "std", not(no_core_cstr)))] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl Serialize for CStr { #[inline] fn serialize(&self, serializer: S) -> Result @@ -83,7 +82,8 @@ impl Serialize for CStr { } } -#[cfg(feature = "std")] +#[cfg(any(feature = "std", all(not(no_core_cstr), feature = "alloc")))] +#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] impl Serialize for CString { #[inline] fn serialize(&self, serializer: S) -> Result @@ -133,7 +133,7 @@ impl Serialize for [T; 0] { where S: Serializer, { - try!(serializer.serialize_tuple(0)).end() + tri!(serializer.serialize_tuple(0)).end() } } @@ -149,9 +149,9 @@ macro_rules! array_impls { where S: Serializer, { - let mut seq = try!(serializer.serialize_tuple($len)); + let mut seq = tri!(serializer.serialize_tuple($len)); for e in self { - try!(seq.serialize_element(e)); + tri!(seq.serialize_element(e)); } seq.end() } @@ -182,9 +182,35 @@ where } } -#[cfg(any(feature = "std", feature = "alloc"))] +#[cfg(not(no_relaxed_trait_bounds))] macro_rules! seq_impl { - ($ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)* >) => { + ( + $(#[$attr:meta])* + $ty:ident + ) => { + $(#[$attr])* + impl Serialize for $ty + where + T: Serialize, + { + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.collect_seq(self) + } + } + } +} + +#[cfg(no_relaxed_trait_bounds)] +macro_rules! seq_impl { + ( + $(#[$attr:meta])* + $ty:ident + ) => { + $(#[$attr])* impl Serialize for $ty where T: Serialize $(+ $tbound1 $(+ $tbound2)*)*, @@ -201,23 +227,41 @@ macro_rules! seq_impl { } } -#[cfg(any(feature = "std", feature = "alloc"))] -seq_impl!(BinaryHeap); +seq_impl! { + #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + BinaryHeap +} -#[cfg(any(feature = "std", feature = "alloc"))] -seq_impl!(BTreeSet); +seq_impl! { + #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + BTreeSet +} -#[cfg(feature = "std")] -seq_impl!(HashSet); +seq_impl! { + #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] + HashSet +} -#[cfg(any(feature = "std", feature = "alloc"))] -seq_impl!(LinkedList); +seq_impl! { + #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + LinkedList +} -#[cfg(any(feature = "std", feature = "alloc"))] -seq_impl!(Vec); +seq_impl! { + #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + Vec +} -#[cfg(any(feature = "std", feature = "alloc"))] -seq_impl!(VecDeque); +seq_impl! { + #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + VecDeque +} //////////////////////////////////////////////////////////////////////////////// @@ -230,16 +274,32 @@ where S: Serializer, { use super::SerializeStruct; - let mut state = try!(serializer.serialize_struct("Range", 2)); - try!(state.serialize_field("start", &self.start)); - try!(state.serialize_field("end", &self.end)); + let mut state = tri!(serializer.serialize_struct("Range", 2)); + tri!(state.serialize_field("start", &self.start)); + tri!(state.serialize_field("end", &self.end)); + state.end() + } +} + +//////////////////////////////////////////////////////////////////////////////// + +impl Serialize for RangeFrom +where + Idx: Serialize, +{ + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + use super::SerializeStruct; + let mut state = tri!(serializer.serialize_struct("RangeFrom", 1)); + tri!(state.serialize_field("start", &self.start)); state.end() } } //////////////////////////////////////////////////////////////////////////////// -#[cfg(not(no_range_inclusive))] impl Serialize for RangeInclusive where Idx: Serialize, @@ -249,16 +309,32 @@ where S: Serializer, { use super::SerializeStruct; - let mut state = try!(serializer.serialize_struct("RangeInclusive", 2)); - try!(state.serialize_field("start", &self.start())); - try!(state.serialize_field("end", &self.end())); + let mut state = tri!(serializer.serialize_struct("RangeInclusive", 2)); + tri!(state.serialize_field("start", &self.start())); + tri!(state.serialize_field("end", &self.end())); + state.end() + } +} + +//////////////////////////////////////////////////////////////////////////////// + +impl Serialize for RangeTo +where + Idx: Serialize, +{ + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + use super::SerializeStruct; + let mut state = tri!(serializer.serialize_struct("RangeTo", 1)); + tri!(state.serialize_field("end", &self.end)); state.end() } } //////////////////////////////////////////////////////////////////////////////// -#[cfg(any(not(no_ops_bound), all(feature = "std", not(no_collections_bound))))] impl Serialize for Bound where T: Serialize, @@ -292,6 +368,7 @@ impl Serialize for () { } #[cfg(feature = "unstable")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "unstable")))] impl Serialize for ! { fn serialize(&self, _serializer: S) -> Result where @@ -315,9 +392,9 @@ macro_rules! tuple_impls { where S: Serializer, { - let mut tuple = try!(serializer.serialize_tuple($len)); + let mut tuple = tri!(serializer.serialize_tuple($len)); $( - try!(tuple.serialize_element(&self.$n)); + tri!(tuple.serialize_element(&self.$n)); )+ tuple.end() } @@ -347,9 +424,36 @@ tuple_impls! { //////////////////////////////////////////////////////////////////////////////// -#[cfg(any(feature = "std", feature = "alloc"))] +#[cfg(not(no_relaxed_trait_bounds))] macro_rules! map_impl { - ($ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)* >) => { + ( + $(#[$attr:meta])* + $ty:ident + ) => { + $(#[$attr])* + impl Serialize for $ty + where + K: Serialize, + V: Serialize, + { + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.collect_map(self) + } + } + } +} + +#[cfg(no_relaxed_trait_bounds)] +macro_rules! map_impl { + ( + $(#[$attr:meta])* + $ty:ident + ) => { + $(#[$attr])* impl Serialize for $ty where K: Serialize $(+ $kbound1 $(+ $kbound2)*)*, @@ -367,20 +471,26 @@ macro_rules! map_impl { } } -#[cfg(any(feature = "std", feature = "alloc"))] -map_impl!(BTreeMap); +map_impl! { + #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + BTreeMap +} -#[cfg(feature = "std")] -map_impl!(HashMap); +map_impl! { + #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] + HashMap +} //////////////////////////////////////////////////////////////////////////////// macro_rules! deref_impl { ( - $(#[doc = $doc:tt])* + $(#[$attr:meta])* <$($desc:tt)+ ) => { - $(#[doc = $doc])* + $(#[$attr])* impl <$($desc)+ { #[inline] fn serialize(&self, serializer: S) -> Result @@ -393,13 +503,20 @@ macro_rules! deref_impl { }; } -deref_impl!(<'a, T: ?Sized> Serialize for &'a T where T: Serialize); -deref_impl!(<'a, T: ?Sized> Serialize for &'a mut T where T: Serialize); +deref_impl! { + <'a, T: ?Sized> Serialize for &'a T where T: Serialize +} -#[cfg(any(feature = "std", feature = "alloc"))] -deref_impl!( Serialize for Box where T: Serialize); +deref_impl! { + <'a, T: ?Sized> Serialize for &'a mut T where T: Serialize +} + +deref_impl! { + #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + Serialize for Box where T: Serialize +} -#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] deref_impl! { /// This impl requires the [`"rc"`] Cargo feature of Serde. /// @@ -409,10 +526,11 @@ deref_impl! { /// repeated data. /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc + #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] + #[cfg_attr(doc_cfg, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))] Serialize for Rc where T: Serialize } -#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] deref_impl! { /// This impl requires the [`"rc"`] Cargo feature of Serde. /// @@ -422,11 +540,16 @@ deref_impl! { /// repeated data. /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc + #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] + #[cfg_attr(doc_cfg, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))] Serialize for Arc where T: Serialize } -#[cfg(any(feature = "std", feature = "alloc"))] -deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned); +deref_impl! { + #[cfg(any(feature = "std", feature = "alloc"))] + #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] + <'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned +} //////////////////////////////////////////////////////////////////////////////// @@ -434,6 +557,10 @@ deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwne /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] +#[cfg_attr( + doc_cfg, + doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))) +)] impl Serialize for RcWeak where T: Serialize, @@ -450,6 +577,10 @@ where /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] +#[cfg_attr( + doc_cfg, + doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))) +)] impl Serialize for ArcWeak where T: Serialize, @@ -465,9 +596,8 @@ where //////////////////////////////////////////////////////////////////////////////// macro_rules! nonzero_integers { - ( $( $T: ident, )+ ) => { + ($($T:ident,)+) => { $( - #[cfg(not(no_num_nonzero))] impl Serialize for num::$T { fn serialize(&self, serializer: S) -> Result where @@ -485,6 +615,7 @@ nonzero_integers! { NonZeroU16, NonZeroU32, NonZeroU64, + NonZeroU128, NonZeroUsize, } @@ -494,22 +625,10 @@ nonzero_integers! { NonZeroI16, NonZeroI32, NonZeroI64, + NonZeroI128, NonZeroIsize, } -// Currently 128-bit integers do not work on Emscripten targets so we need an -// additional `#[cfg]` -serde_if_integer128! { - nonzero_integers! { - NonZeroU128, - } - - #[cfg(not(no_num_nonzero_signed))] - nonzero_integers! { - NonZeroI128, - } -} - impl Serialize for Cell where T: Serialize + Copy, @@ -522,7 +641,7 @@ where } } -impl Serialize for RefCell +impl Serialize for RefCell where T: Serialize, { @@ -538,7 +657,8 @@ where } #[cfg(feature = "std")] -impl Serialize for Mutex +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +impl Serialize for Mutex where T: Serialize, { @@ -554,7 +674,8 @@ where } #[cfg(feature = "std")] -impl Serialize for RwLock +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +impl Serialize for RwLock where T: Serialize, { @@ -591,16 +712,15 @@ where //////////////////////////////////////////////////////////////////////////////// -#[cfg(any(feature = "std", not(no_core_duration)))] impl Serialize for Duration { fn serialize(&self, serializer: S) -> Result where S: Serializer, { use super::SerializeStruct; - let mut state = try!(serializer.serialize_struct("Duration", 2)); - try!(state.serialize_field("secs", &self.as_secs())); - try!(state.serialize_field("nanos", &self.subsec_nanos())); + let mut state = tri!(serializer.serialize_struct("Duration", 2)); + tri!(state.serialize_field("secs", &self.as_secs())); + tri!(state.serialize_field("nanos", &self.subsec_nanos())); state.end() } } @@ -608,18 +728,20 @@ impl Serialize for Duration { //////////////////////////////////////////////////////////////////////////////// #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl Serialize for SystemTime { fn serialize(&self, serializer: S) -> Result where S: Serializer, { use super::SerializeStruct; - let duration_since_epoch = self - .duration_since(UNIX_EPOCH) - .map_err(|_| S::Error::custom("SystemTime must be later than UNIX_EPOCH"))?; - let mut state = try!(serializer.serialize_struct("SystemTime", 2)); - try!(state.serialize_field("secs_since_epoch", &duration_since_epoch.as_secs())); - try!(state.serialize_field("nanos_since_epoch", &duration_since_epoch.subsec_nanos())); + let duration_since_epoch = match self.duration_since(UNIX_EPOCH) { + Ok(duration_since_epoch) => duration_since_epoch, + Err(_) => return Err(S::Error::custom("SystemTime must be later than UNIX_EPOCH")), + }; + let mut state = tri!(serializer.serialize_struct("SystemTime", 2)); + tri!(state.serialize_field("secs_since_epoch", &duration_since_epoch.as_secs())); + tri!(state.serialize_field("nanos_since_epoch", &duration_since_epoch.subsec_nanos())); state.end() } } @@ -651,6 +773,7 @@ macro_rules! serialize_display_bounded_length { } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl Serialize for net::IpAddr { fn serialize(&self, serializer: S) -> Result where @@ -675,7 +798,7 @@ impl Serialize for net::IpAddr { } #[cfg(feature = "std")] -const DEC_DIGITS_LUT: &'static [u8] = b"\ +const DEC_DIGITS_LUT: &[u8] = b"\ 0001020304050607080910111213141516171819\ 2021222324252627282930313233343536373839\ 4041424344454647484950515253545556575859\ @@ -721,6 +844,7 @@ fn test_format_u8() { } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl Serialize for net::Ipv4Addr { fn serialize(&self, serializer: S) -> Result where @@ -735,8 +859,9 @@ impl Serialize for net::Ipv4Addr { // 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]) }) + // Safety: We've only written ASCII bytes to the buffer, so it is valid UTF-8 + let buf = unsafe { str::from_utf8_unchecked(&buf[..written]) }; + serializer.serialize_str(buf) } else { self.octets().serialize(serializer) } @@ -744,6 +869,7 @@ impl Serialize for net::Ipv4Addr { } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl Serialize for net::Ipv6Addr { fn serialize(&self, serializer: S) -> Result where @@ -760,6 +886,7 @@ impl Serialize for net::Ipv6Addr { } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl Serialize for net::SocketAddr { fn serialize(&self, serializer: S) -> Result where @@ -784,6 +911,7 @@ impl Serialize for net::SocketAddr { } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl Serialize for net::SocketAddrV4 { fn serialize(&self, serializer: S) -> Result where @@ -800,6 +928,7 @@ impl Serialize for net::SocketAddrV4 { } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl Serialize for net::SocketAddrV6 { fn serialize(&self, serializer: S) -> Result where @@ -821,6 +950,7 @@ impl Serialize for net::SocketAddrV6 { //////////////////////////////////////////////////////////////////////////////// #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl Serialize for Path { fn serialize(&self, serializer: S) -> Result where @@ -834,6 +964,7 @@ impl Serialize for Path { } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl Serialize for PathBuf { fn serialize(&self, serializer: S) -> Result where @@ -844,6 +975,7 @@ impl Serialize for PathBuf { } #[cfg(all(feature = "std", any(unix, windows)))] +#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", any(unix, windows)))))] impl Serialize for OsStr { #[cfg(unix)] fn serialize(&self, serializer: S) -> Result @@ -866,6 +998,7 @@ impl Serialize for OsStr { } #[cfg(all(feature = "std", any(unix, windows)))] +#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", any(unix, windows)))))] impl Serialize for OsString { fn serialize(&self, serializer: S) -> Result where @@ -890,7 +1023,6 @@ where } } -#[cfg(not(no_core_reverse))] impl Serialize for Reverse where T: Serialize, @@ -908,15 +1040,17 @@ where #[cfg(all(feature = "std", not(no_std_atomic)))] macro_rules! atomic_impl { - ($($ty:ident)*) => { + ($($ty:ident $size:expr)*) => { $( + #[cfg(any(no_target_has_atomic, target_has_atomic = $size))] + #[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", target_has_atomic = $size))))] impl Serialize for $ty { fn serialize(&self, serializer: S) -> Result where S: Serializer, { // Matches the atomic ordering used in libcore for the Debug impl - self.load(Ordering::SeqCst).serialize(serializer) + self.load(Ordering::Relaxed).serialize(serializer) } } )* @@ -925,12 +1059,19 @@ macro_rules! atomic_impl { #[cfg(all(feature = "std", not(no_std_atomic)))] atomic_impl! { - AtomicBool - AtomicI8 AtomicI16 AtomicI32 AtomicIsize - AtomicU8 AtomicU16 AtomicU32 AtomicUsize + AtomicBool "8" + AtomicI8 "8" + AtomicI16 "16" + AtomicI32 "32" + AtomicIsize "ptr" + AtomicU8 "8" + AtomicU16 "16" + AtomicU32 "32" + AtomicUsize "ptr" } #[cfg(all(feature = "std", not(no_std_atomic64)))] atomic_impl! { - AtomicI64 AtomicU64 + AtomicI64 "64" + AtomicU64 "64" } diff --git a/serde/src/ser/impossible.rs b/serde/src/ser/impossible.rs index e8df9ca7..479be940 100644 --- a/serde/src/ser/impossible.rs +++ b/serde/src/ser/impossible.rs @@ -1,8 +1,8 @@ //! This module contains `Impossible` serializer and its implementations. -use lib::*; +use crate::lib::*; -use ser::{ +use crate::ser::{ self, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeTuple, SerializeTupleStruct, SerializeTupleVariant, }; @@ -15,7 +15,7 @@ use ser::{ /// [`SerializeTuple`], [`SerializeTupleStruct`], [`SerializeTupleVariant`], /// [`SerializeMap`], [`SerializeStruct`], and [`SerializeStructVariant`]. /// -/// ```edition2018 +/// ```edition2021 /// # use serde::ser::{Serializer, Impossible}; /// # use serde::__private::doc::Error; /// # diff --git a/serde/src/ser/mod.rs b/serde/src/ser/mod.rs index dcf836b0..75c45140 100644 --- a/serde/src/ser/mod.rs +++ b/serde/src/ser/mod.rs @@ -30,7 +30,7 @@ //! # The Serializer trait //! //! [`Serializer`] implementations are provided by third-party crates, for -//! example [`serde_json`], [`serde_yaml`] and [`bincode`]. +//! example [`serde_json`], [`serde_yaml`] and [`postcard`]. //! //! A partial list of well-maintained formats is given on the [Serde //! website][data formats]. @@ -61,8 +61,8 @@ //! - RefCell\ //! - Mutex\ //! - RwLock\ -//! - Rc\ *(if* features = ["rc"] *is enabled)* -//! - Arc\ *(if* features = ["rc"] *is enabled)* +//! - Rc\ *(if* features = \["rc"\] *is enabled)* +//! - Arc\ *(if* features = \["rc"\] *is enabled)* //! - **Collection types**: //! - BTreeMap\ //! - BTreeSet\ @@ -99,7 +99,7 @@ //! [`LinkedHashMap`]: https://docs.rs/linked-hash-map/*/linked_hash_map/struct.LinkedHashMap.html //! [`Serialize`]: ../trait.Serialize.html //! [`Serializer`]: ../trait.Serializer.html -//! [`bincode`]: https://github.com/servo/bincode +//! [`postcard`]: https://github.com/jamesmunns/postcard //! [`linked-hash-map`]: https://crates.io/crates/linked-hash-map //! [`serde_derive`]: https://crates.io/crates/serde_derive //! [`serde_json`]: https://github.com/serde-rs/json @@ -107,7 +107,7 @@ //! [derive section of the manual]: https://serde.rs/derive.html //! [data formats]: https://serde.rs/#data-formats -use lib::*; +use crate::lib::*; mod fmt; mod impls; @@ -115,12 +115,15 @@ mod impossible; pub use self::impossible::Impossible; +#[cfg(not(any(feature = "std", feature = "unstable")))] +#[doc(no_inline)] +pub use crate::std_error::Error as StdError; +#[cfg(all(feature = "unstable", not(feature = "std")))] +#[doc(no_inline)] +pub use core::error::Error as StdError; #[cfg(feature = "std")] #[doc(no_inline)] pub use std::error::Error as StdError; -#[cfg(not(feature = "std"))] -#[doc(no_inline)] -pub use std_error::Error as StdError; //////////////////////////////////////////////////////////////////////////////// @@ -146,7 +149,7 @@ macro_rules! declare_error_trait { /// For example, a filesystem [`Path`] may refuse to serialize /// itself if it contains invalid UTF-8 data. /// - /// ```edition2018 + /// ```edition2021 /// # struct Path; /// # /// # impl Path { @@ -191,8 +194,8 @@ declare_error_trait!(Error: Sized + Debug + Display); /// by Serde. /// /// Serde provides `Serialize` implementations for many Rust primitive and -/// standard library types. The complete list is [here][ser]. All of these can -/// be serialized using Serde out of the box. +/// standard library types. The complete list is [here][crate::ser]. All of +/// these can be serialized using Serde out of the box. /// /// Additionally, Serde provides a procedural macro called [`serde_derive`] to /// automatically generate `Serialize` implementations for structs and enums in @@ -212,14 +215,13 @@ declare_error_trait!(Error: Sized + Debug + Display); /// [`linked-hash-map`]: https://crates.io/crates/linked-hash-map /// [`serde_derive`]: https://crates.io/crates/serde_derive /// [derive section of the manual]: https://serde.rs/derive.html -/// [ser]: https://docs.serde.rs/serde/ser/index.html pub trait Serialize { /// Serialize this value into the given Serde serializer. /// /// See the [Implementing `Serialize`] section of the manual for more /// information about how to implement this method. /// - /// ```edition2018 + /// ```edition2021 /// use serde::ser::{Serialize, SerializeStruct, Serializer}; /// /// struct Person { @@ -314,7 +316,7 @@ pub trait Serialize { /// - For example the `E::S` in `enum E { S { r: u8, g: u8, b: u8 } }`. /// /// Many Serde serializers produce text or binary data as output, for example -/// JSON or Bincode. This is not a requirement of the `Serializer` trait, and +/// JSON or Postcard. This is not a requirement of the `Serializer` trait, and /// there are serializers that do not produce text or binary output. One example /// is the `serde_json::value::Serializer` (distinct from the main `serde_json` /// serializer) that produces a `serde_json::Value` data structure in memory as @@ -386,7 +388,7 @@ pub trait Serializer: Sized { /// Serialize a `bool` value. /// - /// ```edition2018 + /// ```edition2021 /// # use serde::Serializer; /// # /// # serde::__private_serialize!(); @@ -408,7 +410,7 @@ pub trait Serializer: Sized { /// reasonable implementation would be to cast the value to `i64` and /// forward to `serialize_i64`. /// - /// ```edition2018 + /// ```edition2021 /// # use serde::Serializer; /// # /// # serde::__private_serialize!(); @@ -430,7 +432,7 @@ pub trait Serializer: Sized { /// reasonable implementation would be to cast the value to `i64` and /// forward to `serialize_i64`. /// - /// ```edition2018 + /// ```edition2021 /// # use serde::Serializer; /// # /// # serde::__private_serialize!(); @@ -452,7 +454,7 @@ pub trait Serializer: Sized { /// reasonable implementation would be to cast the value to `i64` and /// forward to `serialize_i64`. /// - /// ```edition2018 + /// ```edition2021 /// # use serde::Serializer; /// # /// # serde::__private_serialize!(); @@ -470,7 +472,7 @@ pub trait Serializer: Sized { /// Serialize an `i64` value. /// - /// ```edition2018 + /// ```edition2021 /// # use serde::Serializer; /// # /// # serde::__private_serialize!(); @@ -486,30 +488,27 @@ pub trait Serializer: Sized { /// ``` fn serialize_i64(self, v: i64) -> Result; - serde_if_integer128! { - /// Serialize an `i128` value. - /// - /// ```edition2018 - /// # use serde::Serializer; - /// # - /// # serde::__private_serialize!(); - /// # - /// impl Serialize for i128 { - /// fn serialize(&self, serializer: S) -> Result - /// where - /// S: Serializer, - /// { - /// serializer.serialize_i128(*self) - /// } - /// } - /// ``` - /// - /// This method is available only on Rust compiler versions >=1.26. The - /// default behavior unconditionally returns an error. - fn serialize_i128(self, v: i128) -> Result { - let _ = v; - Err(Error::custom("i128 is not supported")) - } + /// Serialize an `i128` value. + /// + /// ```edition2021 + /// # use serde::Serializer; + /// # + /// # serde::__private_serialize!(); + /// # + /// impl Serialize for i128 { + /// fn serialize(&self, serializer: S) -> Result + /// where + /// S: Serializer, + /// { + /// serializer.serialize_i128(*self) + /// } + /// } + /// ``` + /// + /// The default behavior unconditionally returns an error. + fn serialize_i128(self, v: i128) -> Result { + let _ = v; + Err(Error::custom("i128 is not supported")) } /// Serialize a `u8` value. @@ -518,7 +517,7 @@ pub trait Serializer: Sized { /// reasonable implementation would be to cast the value to `u64` and /// forward to `serialize_u64`. /// - /// ```edition2018 + /// ```edition2021 /// # use serde::Serializer; /// # /// # serde::__private_serialize!(); @@ -540,7 +539,7 @@ pub trait Serializer: Sized { /// reasonable implementation would be to cast the value to `u64` and /// forward to `serialize_u64`. /// - /// ```edition2018 + /// ```edition2021 /// # use serde::Serializer; /// # /// # serde::__private_serialize!(); @@ -562,7 +561,7 @@ pub trait Serializer: Sized { /// reasonable implementation would be to cast the value to `u64` and /// forward to `serialize_u64`. /// - /// ```edition2018 + /// ```edition2021 /// # use serde::Serializer; /// # /// # serde::__private_serialize!(); @@ -580,7 +579,7 @@ pub trait Serializer: Sized { /// Serialize a `u64` value. /// - /// ```edition2018 + /// ```edition2021 /// # use serde::Serializer; /// # /// # serde::__private_serialize!(); @@ -596,30 +595,27 @@ pub trait Serializer: Sized { /// ``` fn serialize_u64(self, v: u64) -> Result; - serde_if_integer128! { - /// Serialize a `u128` value. - /// - /// ```edition2018 - /// # use serde::Serializer; - /// # - /// # serde::__private_serialize!(); - /// # - /// impl Serialize for u128 { - /// fn serialize(&self, serializer: S) -> Result - /// where - /// S: Serializer, - /// { - /// serializer.serialize_u128(*self) - /// } - /// } - /// ``` - /// - /// This method is available only on Rust compiler versions >=1.26. The - /// default behavior unconditionally returns an error. - fn serialize_u128(self, v: u128) -> Result { - let _ = v; - Err(Error::custom("u128 is not supported")) - } + /// Serialize a `u128` value. + /// + /// ```edition2021 + /// # use serde::Serializer; + /// # + /// # serde::__private_serialize!(); + /// # + /// impl Serialize for u128 { + /// fn serialize(&self, serializer: S) -> Result + /// where + /// S: Serializer, + /// { + /// serializer.serialize_u128(*self) + /// } + /// } + /// ``` + /// + /// The default behavior unconditionally returns an error. + fn serialize_u128(self, v: u128) -> Result { + let _ = v; + Err(Error::custom("u128 is not supported")) } /// Serialize an `f32` value. @@ -628,7 +624,7 @@ pub trait Serializer: Sized { /// reasonable implementation would be to cast the value to `f64` and /// forward to `serialize_f64`. /// - /// ```edition2018 + /// ```edition2021 /// # use serde::Serializer; /// # /// # serde::__private_serialize!(); @@ -646,7 +642,7 @@ pub trait Serializer: Sized { /// Serialize an `f64` value. /// - /// ```edition2018 + /// ```edition2021 /// # use serde::Serializer; /// # /// # serde::__private_serialize!(); @@ -667,7 +663,7 @@ pub trait Serializer: Sized { /// If the format does not support characters, it is reasonable to serialize /// it as a single element `str` or a `u32`. /// - /// ```edition2018 + /// ```edition2021 /// # use serde::Serializer; /// # /// # serde::__private_serialize!(); @@ -685,7 +681,7 @@ pub trait Serializer: Sized { /// Serialize a `&str`. /// - /// ```edition2018 + /// ```edition2021 /// # use serde::Serializer; /// # /// # serde::__private_serialize!(); @@ -709,7 +705,7 @@ pub trait Serializer: Sized { /// `serialize_seq`. If forwarded, the implementation looks usually just /// like this: /// - /// ```edition2018 + /// ```edition2021 /// # use serde::ser::{Serializer, SerializeSeq}; /// # use serde::__private::doc::Error; /// # @@ -738,7 +734,7 @@ pub trait Serializer: Sized { /// Serialize a [`None`] value. /// - /// ```edition2018 + /// ```edition2021 /// # use serde::{Serialize, Serializer}; /// # /// # enum Option { @@ -771,7 +767,7 @@ pub trait Serializer: Sized { /// Serialize a [`Some(T)`] value. /// - /// ```edition2018 + /// ```edition2021 /// # use serde::{Serialize, Serializer}; /// # /// # enum Option { @@ -806,7 +802,7 @@ pub trait Serializer: Sized { /// Serialize a `()` value. /// - /// ```edition2018 + /// ```edition2021 /// # use serde::Serializer; /// # /// # serde::__private_serialize!(); @@ -826,7 +822,7 @@ pub trait Serializer: Sized { /// /// A reasonable implementation would be to forward to `serialize_unit`. /// - /// ```edition2018 + /// ```edition2021 /// use serde::{Serialize, Serializer}; /// /// struct Nothing; @@ -848,7 +844,7 @@ pub trait Serializer: Sized { /// this variant within the enum, and the `variant` is the name of the /// variant. /// - /// ```edition2018 + /// ```edition2021 /// use serde::{Serialize, Serializer}; /// /// enum E { @@ -881,7 +877,7 @@ pub trait Serializer: Sized { /// wrappers around the data they contain. A reasonable implementation would /// be to forward to `value.serialize(self)`. /// - /// ```edition2018 + /// ```edition2021 /// use serde::{Serialize, Serializer}; /// /// struct Millimeters(u8); @@ -909,7 +905,7 @@ pub trait Serializer: Sized { /// this variant within the enum, and the `variant` is the name of the /// variant. The `value` is the data contained within this newtype variant. /// - /// ```edition2018 + /// ```edition2021 /// use serde::{Serialize, Serializer}; /// /// enum E { @@ -947,7 +943,7 @@ pub trait Serializer: Sized { /// not be computable before the sequence is iterated. Some serializers only /// support sequences whose length is known up front. /// - /// ```edition2018 + /// ```edition2021 /// # use std::marker::PhantomData; /// # /// # struct Vec(PhantomData); @@ -960,14 +956,14 @@ pub trait Serializer: Sized { /// # /// # impl<'a, T> IntoIterator for &'a Vec { /// # type Item = &'a T; - /// # type IntoIter = Box>; + /// # type IntoIter = Box>; /// # /// # fn into_iter(self) -> Self::IntoIter { /// # unimplemented!() /// # } /// # } /// # - /// use serde::ser::{Serialize, Serializer, SerializeSeq}; + /// use serde::ser::{Serialize, SerializeSeq, Serializer}; /// /// impl Serialize for Vec /// where @@ -992,8 +988,8 @@ pub trait Serializer: Sized { /// This call must be followed by zero or more calls to `serialize_element`, /// then a call to `end`. /// - /// ```edition2018 - /// use serde::ser::{Serialize, Serializer, SerializeTuple}; + /// ```edition2021 + /// use serde::ser::{Serialize, SerializeTuple, Serializer}; /// /// # mod fool { /// # trait Serialize {} @@ -1022,7 +1018,7 @@ pub trait Serializer: Sized { /// } /// ``` /// - /// ```edition2018 + /// ```edition2021 /// use serde::ser::{Serialize, SerializeTuple, Serializer}; /// /// const VRAM_SIZE: usize = 386; @@ -1050,7 +1046,7 @@ pub trait Serializer: Sized { /// The `name` is the name of the tuple struct and the `len` is the number /// of data fields that will be serialized. /// - /// ```edition2018 + /// ```edition2021 /// use serde::ser::{Serialize, SerializeTupleStruct, Serializer}; /// /// struct Rgb(u8, u8, u8); @@ -1082,7 +1078,7 @@ pub trait Serializer: Sized { /// this variant within the enum, the `variant` is the name of the variant, /// and the `len` is the number of data fields that will be serialized. /// - /// ```edition2018 + /// ```edition2021 /// use serde::ser::{Serialize, SerializeTupleVariant, Serializer}; /// /// enum E { @@ -1128,7 +1124,7 @@ pub trait Serializer: Sized { /// be computable before the map is iterated. Some serializers only support /// maps whose length is known up front. /// - /// ```edition2018 + /// ```edition2021 /// # use std::marker::PhantomData; /// # /// # struct HashMap(PhantomData, PhantomData); @@ -1141,14 +1137,14 @@ pub trait Serializer: Sized { /// # /// # impl<'a, K, V> IntoIterator for &'a HashMap { /// # type Item = (&'a K, &'a V); - /// # type IntoIter = Box>; + /// # type IntoIter = Box>; /// # /// # fn into_iter(self) -> Self::IntoIter { /// # unimplemented!() /// # } /// # } /// # - /// use serde::ser::{Serialize, Serializer, SerializeMap}; + /// use serde::ser::{Serialize, SerializeMap, Serializer}; /// /// impl Serialize for HashMap /// where @@ -1176,7 +1172,7 @@ pub trait Serializer: Sized { /// The `name` is the name of the struct and the `len` is the number of /// data fields that will be serialized. /// - /// ```edition2018 + /// ```edition2021 /// use serde::ser::{Serialize, SerializeStruct, Serializer}; /// /// struct Rgb { @@ -1212,7 +1208,7 @@ pub trait Serializer: Sized { /// this variant within the enum, the `variant` is the name of the variant, /// and the `len` is the number of data fields that will be serialized. /// - /// ```edition2018 + /// ```edition2021 /// use serde::ser::{Serialize, SerializeStructVariant, Serializer}; /// /// enum E { @@ -1254,7 +1250,7 @@ pub trait Serializer: Sized { /// using [`serialize_seq`]. Implementors should not need to override this /// method. /// - /// ```edition2018 + /// ```edition2021 /// use serde::{Serialize, Serializer}; /// /// struct SecretlyOneHigher { @@ -1277,22 +1273,9 @@ pub trait Serializer: Sized { I: IntoIterator, ::Item: Serialize, { - let iter = iter.into_iter(); - let mut serializer = try!(self.serialize_seq(iterator_len_hint(&iter))); - - #[cfg(not(no_iterator_try_fold))] - { - let mut iter = iter; - try!(iter.try_for_each(|item| serializer.serialize_element(&item))); - } - - #[cfg(no_iterator_try_fold)] - { - for item in iter { - try!(serializer.serialize_element(&item)); - } - } - + let mut iter = iter.into_iter(); + let mut serializer = tri!(self.serialize_seq(iterator_len_hint(&iter))); + tri!(iter.try_for_each(|item| serializer.serialize_element(&item))); serializer.end() } @@ -1302,7 +1285,7 @@ pub trait Serializer: Sized { /// using [`serialize_map`]. Implementors should not need to override this /// method. /// - /// ```edition2018 + /// ```edition2021 /// use serde::{Serialize, Serializer}; /// use std::collections::BTreeSet; /// @@ -1328,22 +1311,9 @@ pub trait Serializer: Sized { V: Serialize, I: IntoIterator, { - let iter = iter.into_iter(); - let mut serializer = try!(self.serialize_map(iterator_len_hint(&iter))); - - #[cfg(not(no_iterator_try_fold))] - { - let mut iter = iter; - try!(iter.try_for_each(|(key, value)| serializer.serialize_entry(&key, &value))); - } - - #[cfg(no_iterator_try_fold)] - { - for (key, value) in iter { - try!(serializer.serialize_entry(&key, &value)); - } - } - + let mut iter = iter.into_iter(); + let mut serializer = tri!(self.serialize_map(iterator_len_hint(&iter))); + tri!(iter.try_for_each(|(key, value)| serializer.serialize_entry(&key, &value))); serializer.end() } @@ -1353,7 +1323,7 @@ pub trait Serializer: Sized { /// delegates to [`serialize_str`]. Serializers are encouraged to provide a /// more efficient implementation if possible. /// - /// ```edition2018 + /// ```edition2021 /// # struct DateTime; /// # /// # impl DateTime { @@ -1368,9 +1338,7 @@ pub trait Serializer: Sized { /// where /// S: Serializer, /// { - /// serializer.collect_str(&format_args!("{:?}{:?}", - /// self.naive_local(), - /// self.offset())) + /// serializer.collect_str(&format_args!("{:?}{:?}", self.naive_local(), self.offset())) /// } /// } /// ``` @@ -1391,7 +1359,7 @@ pub trait Serializer: Sized { /// of this method. If no more sensible behavior is possible, the /// implementation is expected to return an error. /// - /// ```edition2018 + /// ```edition2021 /// # struct DateTime; /// # /// # impl DateTime { @@ -1406,9 +1374,7 @@ pub trait Serializer: Sized { /// where /// S: Serializer, /// { - /// serializer.collect_str(&format_args!("{:?}{:?}", - /// self.naive_local(), - /// self.offset())) + /// serializer.collect_str(&format_args!("{:?}{:?}", self.naive_local(), self.offset())) /// } /// } /// ``` @@ -1423,10 +1389,10 @@ pub trait Serializer: Sized { /// Some types have a human-readable form that may be somewhat expensive to /// construct, as well as a binary form that is compact and efficient. /// Generally text-based formats like JSON and YAML will prefer to use the - /// human-readable one and binary formats like Bincode will prefer the + /// human-readable one and binary formats like Postcard will prefer the /// compact one. /// - /// ```edition2018 + /// ```edition2021 /// # use std::fmt::{self, Display}; /// # /// # struct Timestamp; @@ -1475,7 +1441,7 @@ pub trait Serializer: Sized { /// /// # Example use /// -/// ```edition2018 +/// ```edition2021 /// # use std::marker::PhantomData; /// # /// # struct Vec(PhantomData); @@ -1488,13 +1454,13 @@ pub trait Serializer: Sized { /// # /// # impl<'a, T> IntoIterator for &'a Vec { /// # type Item = &'a T; -/// # type IntoIter = Box>; +/// # type IntoIter = Box>; /// # fn into_iter(self) -> Self::IntoIter { /// # unimplemented!() /// # } /// # } /// # -/// use serde::ser::{Serialize, Serializer, SerializeSeq}; +/// use serde::ser::{Serialize, SerializeSeq, Serializer}; /// /// impl Serialize for Vec /// where @@ -1539,8 +1505,8 @@ pub trait SerializeSeq { /// /// # Example use /// -/// ```edition2018 -/// use serde::ser::{Serialize, Serializer, SerializeTuple}; +/// ```edition2021 +/// use serde::ser::{Serialize, SerializeTuple, Serializer}; /// /// # mod fool { /// # trait Serialize {} @@ -1569,7 +1535,7 @@ pub trait SerializeSeq { /// } /// ``` /// -/// ```edition2018 +/// ```edition2021 /// # use std::marker::PhantomData; /// # /// # struct Array(PhantomData); @@ -1582,13 +1548,13 @@ pub trait SerializeSeq { /// # /// # impl<'a, T> IntoIterator for &'a Array { /// # type Item = &'a T; -/// # type IntoIter = Box>; +/// # type IntoIter = Box>; /// # fn into_iter(self) -> Self::IntoIter { /// # unimplemented!() /// # } /// # } /// # -/// use serde::ser::{Serialize, Serializer, SerializeTuple}; +/// use serde::ser::{Serialize, SerializeTuple, Serializer}; /// /// # mod fool { /// # trait Serialize {} @@ -1639,7 +1605,7 @@ pub trait SerializeTuple { /// /// # Example use /// -/// ```edition2018 +/// ```edition2021 /// use serde::ser::{Serialize, SerializeTupleStruct, Serializer}; /// /// struct Rgb(u8, u8, u8); @@ -1684,7 +1650,7 @@ pub trait SerializeTupleStruct { /// /// # Example use /// -/// ```edition2018 +/// ```edition2021 /// use serde::ser::{Serialize, SerializeTupleVariant, Serializer}; /// /// enum E { @@ -1742,7 +1708,7 @@ pub trait SerializeTupleVariant { /// /// # Example use /// -/// ```edition2018 +/// ```edition2021 /// # use std::marker::PhantomData; /// # /// # struct HashMap(PhantomData, PhantomData); @@ -1755,14 +1721,14 @@ pub trait SerializeTupleVariant { /// # /// # impl<'a, K, V> IntoIterator for &'a HashMap { /// # type Item = (&'a K, &'a V); -/// # type IntoIter = Box>; +/// # type IntoIter = Box>; /// # /// # fn into_iter(self) -> Self::IntoIter { /// # unimplemented!() /// # } /// # } /// # -/// use serde::ser::{Serialize, Serializer, SerializeMap}; +/// use serde::ser::{Serialize, SerializeMap, Serializer}; /// /// impl Serialize for HashMap /// where @@ -1841,7 +1807,7 @@ pub trait SerializeMap { K: Serialize, V: Serialize, { - try!(self.serialize_key(key)); + tri!(self.serialize_key(key)); self.serialize_value(value) } @@ -1853,7 +1819,7 @@ pub trait SerializeMap { /// /// # Example use /// -/// ```edition2018 +/// ```edition2021 /// use serde::ser::{Serialize, SerializeStruct, Serializer}; /// /// struct Rgb { @@ -1913,7 +1879,7 @@ pub trait SerializeStruct { /// /// # Example use /// -/// ```edition2018 +/// ```edition2021 /// use serde::ser::{Serialize, SerializeStructVariant, Serializer}; /// /// enum E { diff --git a/serde/src/std_error.rs b/serde/src/std_error.rs index 1055e0ff..f15a4d74 100644 --- a/serde/src/std_error.rs +++ b/serde/src/std_error.rs @@ -1,4 +1,4 @@ -use lib::{Debug, Display}; +use crate::lib::{Debug, Display}; /// Either a re-export of std::error::Error or a new identical trait, depending /// on whether Serde's "std" feature is enabled. @@ -9,7 +9,7 @@ use lib::{Debug, Display}; /// generally provide their error types with a `std::error::Error` impl /// directly: /// -/// ```edition2018 +/// ```edition2021 /// #[derive(Debug)] /// struct MySerError {...} /// @@ -29,7 +29,7 @@ use lib::{Debug, Display}; /// std = ["serde/std"] /// ``` /// -/// ```edition2018 +/// ```edition2021 /// #[cfg(feature = "std")] /// impl std::error::Error for MySerError {} /// ``` @@ -37,7 +37,7 @@ use lib::{Debug, Display}; /// ... or else provide the std Error impl unconditionally via Serde's /// re-export: /// -/// ```edition2018 +/// ```edition2021 /// impl serde::ser::StdError for MySerError {} /// ``` pub trait Error: Debug + Display { diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 47fda7ff..cd3c4b79 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,16 +1,16 @@ [package] name = "serde_derive" -version = "1.0.136" # remember to update html_root_url +version = "1.0.197" authors = ["Erick Tryzelaar ", "David Tolnay "] -rust-version = "1.31" -license = "MIT OR Apache-2.0" +categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" -homepage = "https://serde.rs" -repository = "https://github.com/serde-rs/serde" documentation = "https://serde.rs/derive.html" -keywords = ["serde", "serialization", "no_std"] +homepage = "https://serde.rs" +keywords = ["serde", "serialization", "no_std", "derive"] +license = "MIT OR Apache-2.0" readme = "crates-io.md" -include = ["build.rs", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] +repository = "https://github.com/serde-rs/serde" +rust-version = "1.56" [features] default = [] @@ -21,12 +21,13 @@ name = "serde_derive" proc-macro = true [dependencies] -proc-macro2 = "1.0" -quote = "1.0" -syn = "1.0.60" +proc-macro2 = { workspace = true, features = ["proc-macro"] } +quote = { workspace = true, features = ["proc-macro"] } +syn = { workspace = true, features = ["clone-impls", "derive", "parsing", "printing", "proc-macro"] } [dev-dependencies] -serde = { version = "1.0", path = "../serde" } +serde = { version = "1", path = "../serde" } [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = ["--generate-link-to-definition"] diff --git a/serde_derive/build.rs b/serde_derive/build.rs deleted file mode 100644 index d0c827a6..00000000 --- a/serde_derive/build.rs +++ /dev/null @@ -1,36 +0,0 @@ -use std::env; -use std::process::Command; -use std::str; - -// The rustc-cfg strings below are *not* public API. Please let us know by -// opening a GitHub issue if your build environment requires some way to enable -// these cfgs other than by executing our build script. -fn main() { - let minor = match rustc_minor_version() { - Some(minor) => minor, - None => return, - }; - - // Underscore const names stabilized in Rust 1.37: - // https://blog.rust-lang.org/2019/08/15/Rust-1.37.0.html#using-unnamed-const-items-for-macros - if minor >= 37 { - println!("cargo:rustc-cfg=underscore_consts"); - } - - // The ptr::addr_of! macro stabilized in Rust 1.51: - // https://blog.rust-lang.org/2021/03/25/Rust-1.51.0.html#stabilized-apis - if minor >= 51 { - println!("cargo:rustc-cfg=ptr_addr_of"); - } -} - -fn rustc_minor_version() -> Option { - let rustc = env::var_os("RUSTC")?; - let output = Command::new(rustc).arg("--version").output().ok()?; - let version = str::from_utf8(&output.stdout).ok()?; - let mut pieces = version.split('.'); - if pieces.next() != Some("rustc 1") { - return None; - } - pieces.next()?.parse().ok() -} diff --git a/serde_derive/src/bound.rs b/serde_derive/src/bound.rs index abca467b..fe8ccfff 100644 --- a/serde_derive/src/bound.rs +++ b/serde_derive/src/bound.rs @@ -1,12 +1,9 @@ -use std::collections::HashSet; - -use syn; -use syn::punctuated::{Pair, Punctuated}; - -use internals::ast::{Container, Data}; -use internals::{attr, ungroup}; - +use crate::internals::ast::{Container, Data}; +use crate::internals::{attr, ungroup}; use proc_macro2::Span; +use std::collections::HashSet; +use syn::punctuated::{Pair, Punctuated}; +use syn::Token; // Remove the default from every type parameter because in the generated impls // they look like associated types: "error: associated type bindings are not @@ -147,6 +144,7 @@ pub fn with_bound( fn visit_type(&mut self, ty: &'ast syn::Type) { match ty { + #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] syn::Type::Array(ty) => self.visit_type(&ty.elem), syn::Type::BareFn(ty) => { for arg in &ty.inputs { @@ -184,9 +182,6 @@ pub fn with_bound( syn::Type::Infer(_) | syn::Type::Never(_) | syn::Type::Verbatim(_) => {} - #[cfg(test)] - syn::Type::__TestExhaustive(_) => unimplemented!(), - #[cfg(not(test))] _ => {} } } @@ -201,11 +196,14 @@ pub fn with_bound( syn::PathArguments::AngleBracketed(arguments) => { for arg in &arguments.args { match arg { + #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] syn::GenericArgument::Type(arg) => self.visit_type(arg), - syn::GenericArgument::Binding(arg) => self.visit_type(&arg.ty), + syn::GenericArgument::AssocType(arg) => self.visit_type(&arg.ty), syn::GenericArgument::Lifetime(_) - | syn::GenericArgument::Constraint(_) - | syn::GenericArgument::Const(_) => {} + | syn::GenericArgument::Const(_) + | syn::GenericArgument::AssocConst(_) + | syn::GenericArgument::Constraint(_) => {} + _ => {} } } } @@ -227,8 +225,10 @@ pub fn with_bound( fn visit_type_param_bound(&mut self, bound: &'ast syn::TypeParamBound) { match bound { + #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] syn::TypeParamBound::Trait(bound) => self.visit_path(&bound.path), - syn::TypeParamBound::Lifetime(_) => {} + syn::TypeParamBound::Lifetime(_) | syn::TypeParamBound::Verbatim(_) => {} + _ => {} } } @@ -253,7 +253,7 @@ pub fn with_bound( }; match &cont.data { Data::Enum(variants) => { - for variant in variants.iter() { + for variant in variants { let relevant_fields = variant .fields .iter() @@ -336,7 +336,7 @@ pub fn with_self_bound( pub fn with_lifetime_bound(generics: &syn::Generics, lifetime: &str) -> syn::Generics { let bound = syn::Lifetime::new(lifetime, Span::call_site()); - let def = syn::LifetimeDef { + let def = syn::LifetimeParam { attrs: Vec::new(), lifetime: bound.clone(), colon_token: None, diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index ff7bc42f..e3b737c6 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -1,22 +1,16 @@ +use crate::fragment::{Expr, Fragment, Match, Stmts}; +use crate::internals::ast::{Container, Data, Field, Style, Variant}; +use crate::internals::{attr, replace_receiver, ungroup, Ctxt, Derive}; +use crate::{bound, dummy, pretend, this}; use proc_macro2::{Literal, Span, TokenStream}; -use quote::ToTokens; -use syn::punctuated::Punctuated; -use syn::spanned::Spanned; -use syn::{self, Ident, Index, Member}; - -use bound; -use dummy; -use fragment::{Expr, Fragment, Match, Stmts}; -use internals::ast::{Container, Data, Field, Style, Variant}; -use internals::{attr, replace_receiver, ungroup, Ctxt, Derive}; -use pretend; - +use quote::{quote, quote_spanned, ToTokens}; use std::collections::BTreeSet; use std::ptr; +use syn::punctuated::Punctuated; +use syn::spanned::Spanned; +use syn::{parse_quote, Ident, Index, Member}; -pub fn expand_derive_deserialize( - input: &mut syn::DeriveInput, -) -> Result> { +pub fn expand_derive_deserialize(input: &mut syn::DeriveInput) -> syn::Result { replace_receiver(input); let ctxt = Ctxt::new(); @@ -68,8 +62,6 @@ pub fn expand_derive_deserialize( Ok(dummy::wrap_in_const( cont.attrs.custom_serde_path(), - "DESERIALIZE", - ident, impl_block, )) } @@ -111,9 +103,13 @@ struct Parameters { local: syn::Ident, /// Path to the type the impl is for. Either a single `Ident` for local - /// types or `some::remote::Ident` for remote types. Does not include - /// generic parameters. - this: syn::Path, + /// types (does not include generic parameters) or `some::remote::Path` for + /// remote types. + this_type: syn::Path, + + /// Same as `this_type` but using `::` for generic parameters for use in + /// expression position. + this_value: syn::Path, /// Generics including any explicit and inferred bounds for the impl. generics: syn::Generics, @@ -133,10 +129,8 @@ struct Parameters { impl Parameters { fn new(cont: &Container) -> Self { let local = cont.ident.clone(); - let this = match cont.attrs.remote() { - Some(remote) => remote.clone(), - None => cont.ident.clone().into(), - }; + let this_type = this::this_type(cont); + let this_value = this::this_value(cont); let borrowed = borrowed_lifetimes(cont); let generics = build_generics(cont, &borrowed); let has_getter = cont.data.has_getter(); @@ -144,7 +138,8 @@ impl Parameters { Parameters { local, - this, + this_type, + this_value, generics, borrowed, has_getter, @@ -155,7 +150,7 @@ impl Parameters { /// Type name to use in error messages and `&'static str` arguments to /// various Deserializer methods. fn type_name(&self) -> String { - self.this.segments.last().unwrap().ident.to_string() + self.this_type.segments.last().unwrap().ident.to_string() } } @@ -240,9 +235,9 @@ impl BorrowedLifetimes { } } - fn de_lifetime_def(&self) -> Option { + fn de_lifetime_param(&self) -> Option { match self { - BorrowedLifetimes::Borrowed(bounds) => Some(syn::LifetimeDef { + BorrowedLifetimes::Borrowed(bounds) => Some(syn::LifetimeParam { attrs: Vec::new(), lifetime: syn::Lifetime::new("'de", Span::call_site()), colon_token: None, @@ -287,10 +282,10 @@ fn deserialize_body(cont: &Container, params: &Parameters) -> Fragment { match &cont.data { Data::Enum(variants) => deserialize_enum(params, variants, &cont.attrs), Data::Struct(Style::Struct, fields) => { - deserialize_struct(None, params, fields, &cont.attrs, None, &Untagged::No) + deserialize_struct(params, fields, &cont.attrs, StructForm::Struct) } Data::Struct(Style::Tuple, fields) | Data::Struct(Style::Newtype, fields) => { - deserialize_tuple(None, params, fields, &cont.attrs, None) + deserialize_tuple(params, fields, &cont.attrs, TupleForm::Tuple) } Data::Struct(Style::Unit, _) => deserialize_unit_struct(params, &cont.attrs), } @@ -322,10 +317,10 @@ fn deserialize_in_place_body(cont: &Container, params: &Parameters) -> Option { - deserialize_struct_in_place(None, params, fields, &cont.attrs, None)? + deserialize_struct_in_place(params, fields, &cont.attrs)? } Data::Struct(Style::Tuple, fields) | Data::Struct(Style::Newtype, fields) => { - deserialize_tuple_in_place(None, params, fields, &cont.attrs, None) + deserialize_tuple_in_place(params, fields, &cont.attrs) } Data::Enum(_) | Data::Struct(Style::Unit, _) => { return None; @@ -358,7 +353,7 @@ fn deserialize_transparent(cont: &Container, params: &Parameters) -> Fragment { Data::Enum(_) => unreachable!(), }; - let this = ¶ms.this; + let this_value = ¶ms.this_value; let transparent_field = fields.iter().find(|f| f.attrs.transparent()).unwrap(); let path = match transparent_field.attrs.deserialize_with() { @@ -386,7 +381,7 @@ fn deserialize_transparent(cont: &Container, params: &Parameters) -> Fragment { quote_block! { _serde::__private::Result::map( #path(__deserializer), - |__transparent| #this { #(#assign),* }) + |__transparent| #this_value { #(#assign),* }) } } @@ -407,17 +402,25 @@ fn deserialize_try_from(type_try_from: &syn::Type) -> Fragment { } fn deserialize_unit_struct(params: &Parameters, cattrs: &attr::Container) -> Fragment { - let this = ¶ms.this; + let this_type = ¶ms.this_type; + let this_value = ¶ms.this_value; let type_name = cattrs.name().deserialize_name(); + let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = + split_with_de_lifetime(params); + let delife = params.borrowed.de_lifetime(); let expecting = format!("unit struct {}", params.type_name()); let expecting = cattrs.expecting().unwrap_or(&expecting); quote_block! { - struct __Visitor; + #[doc(hidden)] + struct __Visitor #de_impl_generics #where_clause { + marker: _serde::__private::PhantomData<#this_type #ty_generics>, + lifetime: _serde::__private::PhantomData<&#delife ()>, + } - impl<'de> _serde::de::Visitor<'de> for __Visitor { - type Value = #this; + impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause { + type Value = #this_type #ty_generics; fn expecting(&self, __formatter: &mut _serde::__private::Formatter) -> _serde::__private::fmt::Result { _serde::__private::Formatter::write_str(__formatter, #expecting) @@ -428,28 +431,49 @@ fn deserialize_unit_struct(params: &Parameters, cattrs: &attr::Container) -> Fra where __E: _serde::de::Error, { - _serde::__private::Ok(#this) + _serde::__private::Ok(#this_value) } } - _serde::Deserializer::deserialize_unit_struct(__deserializer, #type_name, __Visitor) + _serde::Deserializer::deserialize_unit_struct( + __deserializer, + #type_name, + __Visitor { + marker: _serde::__private::PhantomData::<#this_type #ty_generics>, + lifetime: _serde::__private::PhantomData, + }, + ) } } +enum TupleForm<'a> { + Tuple, + /// Contains a variant name + ExternallyTagged(&'a syn::Ident), + /// Contains a variant name and an intermediate deserializer from which actual + /// deserialization will be performed + Untagged(&'a syn::Ident, TokenStream), +} + fn deserialize_tuple( - variant_ident: Option<&syn::Ident>, params: &Parameters, fields: &[Field], cattrs: &attr::Container, - deserializer: Option, + form: TupleForm, ) -> Fragment { - let this = ¶ms.this; + assert!(!cattrs.has_flatten()); + + let field_count = fields + .iter() + .filter(|field| !field.attrs.skip_deserializing()) + .count(); + + let this_type = ¶ms.this_type; + let this_value = ¶ms.this_value; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params); let delife = params.borrowed.de_lifetime(); - assert!(!cattrs.has_flatten()); - // If there are getters (implying private fields), construct the local type // and use an `Into` conversion to get the remote type. If there are no // getters then construct the target type directly. @@ -457,26 +481,30 @@ fn deserialize_tuple( let local = ¶ms.local; quote!(#local) } else { - quote!(#this) + quote!(#this_value) }; - let is_enum = variant_ident.is_some(); - let type_path = match variant_ident { - Some(variant_ident) => quote!(#construct::#variant_ident), - None => construct, + let type_path = match form { + TupleForm::Tuple => construct, + TupleForm::ExternallyTagged(variant_ident) | TupleForm::Untagged(variant_ident, _) => { + quote!(#construct::#variant_ident) + } }; - let expecting = match variant_ident { - Some(variant_ident) => format!("tuple variant {}::{}", params.type_name(), variant_ident), - None => format!("tuple struct {}", params.type_name()), + let expecting = match form { + TupleForm::Tuple => format!("tuple struct {}", params.type_name()), + TupleForm::ExternallyTagged(variant_ident) | TupleForm::Untagged(variant_ident, _) => { + format!("tuple variant {}::{}", params.type_name(), variant_ident) + } }; let expecting = cattrs.expecting().unwrap_or(&expecting); let nfields = fields.len(); - let visit_newtype_struct = if !is_enum && nfields == 1 { - Some(deserialize_newtype_struct(&type_path, params, &fields[0])) - } else { - None + let visit_newtype_struct = match form { + TupleForm::Tuple if nfields == 1 => { + Some(deserialize_newtype_struct(&type_path, params, &fields[0])) + } + _ => None, }; let visit_seq = Stmts(deserialize_seq( @@ -485,37 +513,46 @@ fn deserialize_tuple( let visitor_expr = quote! { __Visitor { - marker: _serde::__private::PhantomData::<#this #ty_generics>, + marker: _serde::__private::PhantomData::<#this_type #ty_generics>, lifetime: _serde::__private::PhantomData, } }; - let dispatch = if let Some(deserializer) = deserializer { - quote!(_serde::Deserializer::deserialize_tuple(#deserializer, #nfields, #visitor_expr)) - } else if is_enum { - quote!(_serde::de::VariantAccess::tuple_variant(__variant, #nfields, #visitor_expr)) - } else if nfields == 1 { - let type_name = cattrs.name().deserialize_name(); - quote!(_serde::Deserializer::deserialize_newtype_struct(__deserializer, #type_name, #visitor_expr)) - } else { - let type_name = cattrs.name().deserialize_name(); - quote!(_serde::Deserializer::deserialize_tuple_struct(__deserializer, #type_name, #nfields, #visitor_expr)) + let dispatch = match form { + TupleForm::Tuple if nfields == 1 => { + let type_name = cattrs.name().deserialize_name(); + quote! { + _serde::Deserializer::deserialize_newtype_struct(__deserializer, #type_name, #visitor_expr) + } + } + TupleForm::Tuple => { + let type_name = cattrs.name().deserialize_name(); + quote! { + _serde::Deserializer::deserialize_tuple_struct(__deserializer, #type_name, #field_count, #visitor_expr) + } + } + TupleForm::ExternallyTagged(_) => quote! { + _serde::de::VariantAccess::tuple_variant(__variant, #field_count, #visitor_expr) + }, + TupleForm::Untagged(_, deserializer) => quote! { + _serde::Deserializer::deserialize_tuple(#deserializer, #field_count, #visitor_expr) + }, }; - let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing()); - let visitor_var = if all_skipped { + let visitor_var = if field_count == 0 { quote!(_) } else { quote!(mut __seq) }; quote_block! { + #[doc(hidden)] struct __Visitor #de_impl_generics #where_clause { - marker: _serde::__private::PhantomData<#this #ty_generics>, + marker: _serde::__private::PhantomData<#this_type #ty_generics>, lifetime: _serde::__private::PhantomData<&#delife ()>, } impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause { - type Value = #this #ty_generics; + type Value = #this_type #ty_generics; fn expecting(&self, __formatter: &mut _serde::__private::Formatter) -> _serde::__private::fmt::Result { _serde::__private::Formatter::write_str(__formatter, #expecting) @@ -538,30 +575,41 @@ fn deserialize_tuple( #[cfg(feature = "deserialize_in_place")] fn deserialize_tuple_in_place( - variant_ident: Option, params: &Parameters, fields: &[Field], cattrs: &attr::Container, - deserializer: Option, ) -> Fragment { - let this = ¶ms.this; + assert!(!cattrs.has_flatten()); + + let field_count = fields + .iter() + .filter(|field| !field.attrs.skip_deserializing()) + .count(); + + let this_type = ¶ms.this_type; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params); let delife = params.borrowed.de_lifetime(); - assert!(!cattrs.has_flatten()); - - let is_enum = variant_ident.is_some(); - let expecting = match variant_ident { - Some(variant_ident) => format!("tuple variant {}::{}", params.type_name(), variant_ident), - None => format!("tuple struct {}", params.type_name()), - }; + let expecting = format!("tuple struct {}", params.type_name()); let expecting = cattrs.expecting().unwrap_or(&expecting); let nfields = fields.len(); - let visit_newtype_struct = if !is_enum && nfields == 1 { - Some(deserialize_newtype_struct_in_place(params, &fields[0])) + let visit_newtype_struct = if nfields == 1 { + // We do not generate deserialize_in_place if every field has a + // deserialize_with. + assert!(fields[0].attrs.deserialize_with().is_none()); + + Some(quote! { + #[inline] + fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::__private::Result + where + __E: _serde::Deserializer<#delife>, + { + _serde::Deserialize::deserialize_in_place(__e, &mut self.place.0) + } + }) } else { None }; @@ -575,20 +623,14 @@ fn deserialize_tuple_in_place( } }; - let dispatch = if let Some(deserializer) = deserializer { - quote!(_serde::Deserializer::deserialize_tuple(#deserializer, #nfields, #visitor_expr)) - } else if is_enum { - quote!(_serde::de::VariantAccess::tuple_variant(__variant, #nfields, #visitor_expr)) - } else if nfields == 1 { - let type_name = cattrs.name().deserialize_name(); + let type_name = cattrs.name().deserialize_name(); + let dispatch = if nfields == 1 { quote!(_serde::Deserializer::deserialize_newtype_struct(__deserializer, #type_name, #visitor_expr)) } else { - let type_name = cattrs.name().deserialize_name(); - quote!(_serde::Deserializer::deserialize_tuple_struct(__deserializer, #type_name, #nfields, #visitor_expr)) + quote!(_serde::Deserializer::deserialize_tuple_struct(__deserializer, #type_name, #field_count, #visitor_expr)) }; - let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing()); - let visitor_var = if all_skipped { + let visitor_var = if field_count == 0 { quote!(_) } else { quote!(mut __seq) @@ -599,8 +641,9 @@ fn deserialize_tuple_in_place( let place_life = place_lifetime(); quote_block! { + #[doc(hidden)] struct __Visitor #in_place_impl_generics #where_clause { - place: &#place_life mut #this #ty_generics, + place: &#place_life mut #this_type #ty_generics, lifetime: _serde::__private::PhantomData<&#delife ()>, } @@ -661,31 +704,23 @@ fn deserialize_seq( let span = field.original.span(); let func = quote_spanned!(span=> _serde::de::SeqAccess::next_element::<#field_ty>); - quote!(try!(#func(&mut __seq))) + quote!(#func(&mut __seq)?) } Some(path) => { let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path); quote!({ #wrapper _serde::__private::Option::map( - try!(_serde::de::SeqAccess::next_element::<#wrapper_ty>(&mut __seq)), + _serde::de::SeqAccess::next_element::<#wrapper_ty>(&mut __seq)?, |__wrap| __wrap.value) }) } }; - let value_if_none = match field.attrs.default() { - attr::Default::Default => quote!(_serde::__private::Default::default()), - attr::Default::Path(path) => quote!(#path()), - attr::Default::None => quote!( - return _serde::__private::Err(_serde::de::Error::invalid_length(#index_in_seq, &#expecting)); - ), - }; + let value_if_none = expr_is_missing_seq(None, index_in_seq, field, cattrs, expecting); let assign = quote! { let #var = match #visit { _serde::__private::Some(__value) => __value, - _serde::__private::None => { - #value_if_none - } + _serde::__private::None => #value_if_none, }; }; index_in_seq += 1; @@ -705,9 +740,10 @@ fn deserialize_seq( }; if params.has_getter { - let this = ¶ms.this; + let this_type = ¶ms.this_type; + let (_, ty_generics, _) = params.generics.split_for_impl(); result = quote! { - _serde::__private::Into::<#this>::into(#result) + _serde::__private::Into::<#this_type #ty_generics>::into(#result) }; } @@ -760,24 +796,14 @@ fn deserialize_seq_in_place( self.place.#member = #default; } } else { - let value_if_none = match field.attrs.default() { - attr::Default::Default => quote!( - self.place.#member = _serde::__private::Default::default(); - ), - attr::Default::Path(path) => quote!( - self.place.#member = #path(); - ), - attr::Default::None => quote!( - return _serde::__private::Err(_serde::de::Error::invalid_length(#index_in_seq, &#expecting)); - ), - }; + let value_if_none = expr_is_missing_seq(Some(quote!(self.place.#member = )), index_in_seq, field, cattrs, expecting); let write = match field.attrs.deserialize_with() { None => { quote! { - if let _serde::__private::None = try!(_serde::de::SeqAccess::next_element_seed(&mut __seq, - _serde::__private::de::InPlaceSeed(&mut self.place.#member))) + if let _serde::__private::None = _serde::de::SeqAccess::next_element_seed(&mut __seq, + _serde::__private::de::InPlaceSeed(&mut self.place.#member))? { - #value_if_none + #value_if_none; } } } @@ -785,12 +811,12 @@ fn deserialize_seq_in_place( let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path); quote!({ #wrapper - match try!(_serde::de::SeqAccess::next_element::<#wrapper_ty>(&mut __seq)) { + match _serde::de::SeqAccess::next_element::<#wrapper_ty>(&mut __seq)? { _serde::__private::Some(__wrap) => { self.place.#member = __wrap.value; } _serde::__private::None => { - #value_if_none + #value_if_none; } } }) @@ -801,14 +827,14 @@ fn deserialize_seq_in_place( } }); - let this = ¶ms.this; + let this_type = ¶ms.this_type; let (_, ty_generics, _) = params.generics.split_for_impl(); let let_default = match cattrs.default() { attr::Default::Default => Some(quote!( - let __default: #this #ty_generics = _serde::__private::Default::default(); + let __default: #this_type #ty_generics = _serde::__private::Default::default(); )), attr::Default::Path(path) => Some(quote!( - let __default: #this #ty_generics = #path(); + let __default: #this_type #ty_generics = #path(); )), attr::Default::None => { // We don't need the default value, to prevent an unused variable warning @@ -837,21 +863,22 @@ fn deserialize_newtype_struct( let span = field.original.span(); let func = quote_spanned!(span=> <#field_ty as _serde::Deserialize>::deserialize); quote! { - try!(#func(__e)) + #func(__e)? } } Some(path) => { quote! { - try!(#path(__e)) + #path(__e)? } } }; let mut result = quote!(#type_path(__field0)); if params.has_getter { - let this = ¶ms.this; + let this_type = ¶ms.this_type; + let (_, ty_generics, _) = params.generics.split_for_impl(); result = quote! { - _serde::__private::Into::<#this>::into(#result) + _serde::__private::Into::<#this_type #ty_generics>::into(#result) }; } @@ -867,41 +894,26 @@ fn deserialize_newtype_struct( } } -#[cfg(feature = "deserialize_in_place")] -fn deserialize_newtype_struct_in_place(params: &Parameters, field: &Field) -> TokenStream { - // We do not generate deserialize_in_place if every field has a - // deserialize_with. - assert!(field.attrs.deserialize_with().is_none()); - - let delife = params.borrowed.de_lifetime(); - - quote! { - #[inline] - fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::__private::Result - where - __E: _serde::Deserializer<#delife>, - { - _serde::Deserialize::deserialize_in_place(__e, &mut self.place.0) - } - } -} - -enum Untagged { - Yes, - No, +enum StructForm<'a> { + Struct, + /// Contains a variant name + ExternallyTagged(&'a syn::Ident), + /// Contains a variant name and an intermediate deserializer from which actual + /// deserialization will be performed + InternallyTagged(&'a syn::Ident, TokenStream), + /// Contains a variant name and an intermediate deserializer from which actual + /// deserialization will be performed + Untagged(&'a syn::Ident, TokenStream), } fn deserialize_struct( - variant_ident: Option<&syn::Ident>, params: &Parameters, fields: &[Field], cattrs: &attr::Container, - deserializer: Option, - untagged: &Untagged, + form: StructForm, ) -> Fragment { - let is_enum = variant_ident.is_some(); - - let this = ¶ms.this; + let this_type = ¶ms.this_type; + let this_value = ¶ms.this_value; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params); let delife = params.borrowed.de_lifetime(); @@ -913,110 +925,140 @@ fn deserialize_struct( let local = ¶ms.local; quote!(#local) } else { - quote!(#this) + quote!(#this_value) }; - let type_path = match variant_ident { - Some(variant_ident) => quote!(#construct::#variant_ident), - None => construct, + let type_path = match form { + StructForm::Struct => construct, + StructForm::ExternallyTagged(variant_ident) + | StructForm::InternallyTagged(variant_ident, _) + | StructForm::Untagged(variant_ident, _) => quote!(#construct::#variant_ident), }; - let expecting = match variant_ident { - Some(variant_ident) => format!("struct variant {}::{}", params.type_name(), variant_ident), - None => format!("struct {}", params.type_name()), + let expecting = match form { + StructForm::Struct => format!("struct {}", params.type_name()), + StructForm::ExternallyTagged(variant_ident) + | StructForm::InternallyTagged(variant_ident, _) + | StructForm::Untagged(variant_ident, _) => { + format!("struct variant {}::{}", params.type_name(), variant_ident) + } }; let expecting = cattrs.expecting().unwrap_or(&expecting); - let visit_seq = Stmts(deserialize_seq( - &type_path, params, fields, true, cattrs, expecting, - )); - - let (field_visitor, fields_stmt, visit_map) = if cattrs.has_flatten() { - deserialize_struct_as_map_visitor(&type_path, params, fields, cattrs) - } else { - deserialize_struct_as_struct_visitor(&type_path, params, fields, cattrs) - }; - let field_visitor = Stmts(field_visitor); - let fields_stmt = fields_stmt.map(Stmts); - let visit_map = Stmts(visit_map); - - let visitor_expr = quote! { - __Visitor { - marker: _serde::__private::PhantomData::<#this #ty_generics>, - lifetime: _serde::__private::PhantomData, - } - }; - let dispatch = if let Some(deserializer) = deserializer { - quote! { - _serde::Deserializer::deserialize_any(#deserializer, #visitor_expr) - } - } else if is_enum && cattrs.has_flatten() { - quote! { - _serde::de::VariantAccess::newtype_variant_seed(__variant, #visitor_expr) - } - } else if is_enum { - quote! { - _serde::de::VariantAccess::struct_variant(__variant, FIELDS, #visitor_expr) - } - } else if cattrs.has_flatten() { - quote! { - _serde::Deserializer::deserialize_map(__deserializer, #visitor_expr) - } - } else { - let type_name = cattrs.name().deserialize_name(); - quote! { - _serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, #visitor_expr) - } - }; - - let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing()); - let visitor_var = if all_skipped { - quote!(_) - } else { - quote!(mut __seq) - }; + let field_names_idents: Vec<_> = fields + .iter() + .enumerate() + // Skip fields that shouldn't be deserialized or that were flattened, + // so they don't appear in the storage in their literal form + .filter(|&(_, field)| !field.attrs.skip_deserializing() && !field.attrs.flatten()) + .map(|(i, field)| { + ( + field.attrs.name().deserialize_name(), + field_i(i), + field.attrs.aliases(), + ) + }) + .collect(); + let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs); // untagged struct variants do not get a visit_seq method. The same applies to // structs that only have a map representation. - let visit_seq = match *untagged { - Untagged::No if !cattrs.has_flatten() => Some(quote! { - #[inline] - fn visit_seq<__A>(self, #visitor_var: __A) -> _serde::__private::Result - where - __A: _serde::de::SeqAccess<#delife>, - { - #visit_seq + let visit_seq = match form { + StructForm::Untagged(..) => None, + _ if cattrs.has_flatten() => None, + _ => { + let mut_seq = if field_names_idents.is_empty() { + quote!(_) + } else { + quote!(mut __seq) + }; + + let visit_seq = Stmts(deserialize_seq( + &type_path, params, fields, true, cattrs, expecting, + )); + + Some(quote! { + #[inline] + fn visit_seq<__A>(self, #mut_seq: __A) -> _serde::__private::Result + where + __A: _serde::de::SeqAccess<#delife>, + { + #visit_seq + } + }) + } + }; + let visit_map = Stmts(deserialize_map(&type_path, params, fields, cattrs)); + + let visitor_seed = match form { + StructForm::ExternallyTagged(..) if cattrs.has_flatten() => Some(quote! { + impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Visitor #de_ty_generics #where_clause { + type Value = #this_type #ty_generics; + + fn deserialize<__D>(self, __deserializer: __D) -> _serde::__private::Result + where + __D: _serde::Deserializer<#delife>, + { + _serde::Deserializer::deserialize_map(__deserializer, self) + } } }), _ => None, }; - let visitor_seed = if is_enum && cattrs.has_flatten() { - Some(quote! { - impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Visitor #de_ty_generics #where_clause { - type Value = #this #ty_generics; - - fn deserialize<__D>(self, __deserializer: __D) -> _serde::__private::Result - where - __D: _serde::Deserializer<'de>, - { - _serde::Deserializer::deserialize_map(__deserializer, self) - } - } - }) - } else { + let fields_stmt = if cattrs.has_flatten() { None + } else { + let field_names = field_names_idents + .iter() + .flat_map(|&(_, _, aliases)| aliases); + + Some(quote! { + #[doc(hidden)] + const FIELDS: &'static [&'static str] = &[ #(#field_names),* ]; + }) + }; + + let visitor_expr = quote! { + __Visitor { + marker: _serde::__private::PhantomData::<#this_type #ty_generics>, + lifetime: _serde::__private::PhantomData, + } + }; + let dispatch = match form { + StructForm::Struct if cattrs.has_flatten() => quote! { + _serde::Deserializer::deserialize_map(__deserializer, #visitor_expr) + }, + StructForm::Struct => { + let type_name = cattrs.name().deserialize_name(); + quote! { + _serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, #visitor_expr) + } + } + StructForm::ExternallyTagged(_) if cattrs.has_flatten() => quote! { + _serde::de::VariantAccess::newtype_variant_seed(__variant, #visitor_expr) + }, + StructForm::ExternallyTagged(_) => quote! { + _serde::de::VariantAccess::struct_variant(__variant, FIELDS, #visitor_expr) + }, + StructForm::InternallyTagged(_, deserializer) => quote! { + _serde::Deserializer::deserialize_any(#deserializer, #visitor_expr) + }, + StructForm::Untagged(_, deserializer) => quote! { + _serde::Deserializer::deserialize_any(#deserializer, #visitor_expr) + }, }; quote_block! { #field_visitor + #[doc(hidden)] struct __Visitor #de_impl_generics #where_clause { - marker: _serde::__private::PhantomData<#this #ty_generics>, + marker: _serde::__private::PhantomData<#this_type #ty_generics>, lifetime: _serde::__private::PhantomData<&#delife ()>, } impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause { - type Value = #this #ty_generics; + type Value = #this_type #ty_generics; fn expecting(&self, __formatter: &mut _serde::__private::Formatter) -> _serde::__private::fmt::Result { _serde::__private::Formatter::write_str(__formatter, #expecting) @@ -1043,77 +1085,50 @@ fn deserialize_struct( #[cfg(feature = "deserialize_in_place")] fn deserialize_struct_in_place( - variant_ident: Option, params: &Parameters, fields: &[Field], cattrs: &attr::Container, - deserializer: Option, ) -> Option { - let is_enum = variant_ident.is_some(); - // for now we do not support in_place deserialization for structs that // are represented as map. if cattrs.has_flatten() { return None; } - let this = ¶ms.this; + let this_type = ¶ms.this_type; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params); let delife = params.borrowed.de_lifetime(); - let expecting = match variant_ident { - Some(variant_ident) => format!("struct variant {}::{}", params.type_name(), variant_ident), - None => format!("struct {}", params.type_name()), - }; + let expecting = format!("struct {}", params.type_name()); let expecting = cattrs.expecting().unwrap_or(&expecting); - let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, expecting)); + let field_names_idents: Vec<_> = fields + .iter() + .enumerate() + .filter(|&(_, field)| !field.attrs.skip_deserializing()) + .map(|(i, field)| { + ( + field.attrs.name().deserialize_name(), + field_i(i), + field.attrs.aliases(), + ) + }) + .collect(); - let (field_visitor, fields_stmt, visit_map) = - deserialize_struct_as_struct_in_place_visitor(params, fields, cattrs); + let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs); - let field_visitor = Stmts(field_visitor); - let fields_stmt = Stmts(fields_stmt); - let visit_map = Stmts(visit_map); - - let visitor_expr = quote! { - __Visitor { - place: __place, - lifetime: _serde::__private::PhantomData, - } - }; - let dispatch = if let Some(deserializer) = deserializer { - quote! { - _serde::Deserializer::deserialize_any(#deserializer, #visitor_expr) - } - } else if is_enum { - quote! { - _serde::de::VariantAccess::struct_variant(__variant, FIELDS, #visitor_expr) - } - } else { - let type_name = cattrs.name().deserialize_name(); - quote! { - _serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, #visitor_expr) - } - }; - - let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing()); - let visitor_var = if all_skipped { + let mut_seq = if field_names_idents.is_empty() { quote!(_) } else { quote!(mut __seq) }; - - let visit_seq = quote! { - #[inline] - fn visit_seq<__A>(self, #visitor_var: __A) -> _serde::__private::Result - where - __A: _serde::de::SeqAccess<#delife>, - { - #visit_seq - } - }; + let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, expecting)); + let visit_map = Stmts(deserialize_map_in_place(params, fields, cattrs)); + let field_names = field_names_idents + .iter() + .flat_map(|&(_, _, aliases)| aliases); + let type_name = cattrs.name().deserialize_name(); let in_place_impl_generics = de_impl_generics.in_place(); let in_place_ty_generics = de_ty_generics.in_place(); @@ -1122,8 +1137,9 @@ fn deserialize_struct_in_place( Some(quote_block! { #field_visitor + #[doc(hidden)] struct __Visitor #in_place_impl_generics #where_clause { - place: &#place_life mut #this #ty_generics, + place: &#place_life mut #this_type #ty_generics, lifetime: _serde::__private::PhantomData<&#delife ()>, } @@ -1134,7 +1150,13 @@ fn deserialize_struct_in_place( _serde::__private::Formatter::write_str(__formatter, #expecting) } - #visit_seq + #[inline] + fn visit_seq<__A>(self, #mut_seq: __A) -> _serde::__private::Result + where + __A: _serde::de::SeqAccess<#delife>, + { + #visit_seq + } #[inline] fn visit_map<__A>(self, mut __map: __A) -> _serde::__private::Result @@ -1145,9 +1167,13 @@ fn deserialize_struct_in_place( } } - #fields_stmt + #[doc(hidden)] + const FIELDS: &'static [&'static str] = &[ #(#field_names),* ]; - #dispatch + _serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, __Visitor { + place: __place, + lifetime: _serde::__private::PhantomData, + }) }) } @@ -1155,6 +1181,22 @@ fn deserialize_enum( params: &Parameters, variants: &[Variant], cattrs: &attr::Container, +) -> Fragment { + // The variants have already been checked (in ast.rs) that all untagged variants appear at the end + match variants.iter().position(|var| var.attrs.untagged()) { + Some(variant_idx) => { + let (tagged, untagged) = variants.split_at(variant_idx); + let tagged_frag = Expr(deserialize_homogeneous_enum(params, tagged, cattrs)); + deserialize_untagged_enum_after(params, untagged, cattrs, Some(tagged_frag)) + } + None => deserialize_homogeneous_enum(params, variants, cattrs), + } +} + +fn deserialize_homogeneous_enum( + params: &Parameters, + variants: &[Variant], + cattrs: &attr::Container, ) -> Fragment { match cattrs.tag() { attr::TagType::External => deserialize_externally_tagged_enum(params, variants, cattrs), @@ -1188,11 +1230,17 @@ fn prepare_enum_variant_enum( }) .collect(); - let other_idx = deserialized_variants.position(|(_, variant)| variant.attrs.other()); + let fallthrough = deserialized_variants + .position(|(_, variant)| variant.attrs.other()) + .map(|other_idx| { + let ignore_variant = variant_names_idents[other_idx].1.clone(); + quote!(_serde::__private::Ok(__Field::#ignore_variant)) + }); let variants_stmt = { let variant_names = variant_names_idents.iter().map(|(name, _, _)| name); quote! { + #[doc(hidden)] const VARIANTS: &'static [&'static str] = &[ #(#variant_names),* ]; } }; @@ -1201,7 +1249,8 @@ fn prepare_enum_variant_enum( &variant_names_idents, cattrs, true, - other_idx, + None, + fallthrough, )); (variants_stmt, variant_visitor) @@ -1212,7 +1261,7 @@ fn deserialize_externally_tagged_enum( variants: &[Variant], cattrs: &attr::Container, ) -> Fragment { - let this = ¶ms.this; + let this_type = ¶ms.this_type; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params); let delife = params.borrowed.de_lifetime(); @@ -1247,7 +1296,7 @@ fn deserialize_externally_tagged_enum( // This is an empty enum like `enum Impossible {}` or an enum in which // all variants have `#[serde(skip_deserializing)]`. quote! { - // FIXME: Once we drop support for Rust 1.15: + // FIXME: Once feature(exhaustive_patterns) is stable: // let _serde::__private::Err(__err) = _serde::de::EnumAccess::variant::<__Field>(__data); // _serde::__private::Err(__err) _serde::__private::Result::map( @@ -1256,7 +1305,7 @@ fn deserialize_externally_tagged_enum( } } else { quote! { - match try!(_serde::de::EnumAccess::variant(__data)) { + match _serde::de::EnumAccess::variant(__data)? { #(#variant_arms)* } } @@ -1265,13 +1314,14 @@ fn deserialize_externally_tagged_enum( quote_block! { #variant_visitor + #[doc(hidden)] struct __Visitor #de_impl_generics #where_clause { - marker: _serde::__private::PhantomData<#this #ty_generics>, + marker: _serde::__private::PhantomData<#this_type #ty_generics>, lifetime: _serde::__private::PhantomData<&#delife ()>, } impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause { - type Value = #this #ty_generics; + type Value = #this_type #ty_generics; fn expecting(&self, __formatter: &mut _serde::__private::Formatter) -> _serde::__private::fmt::Result { _serde::__private::Formatter::write_str(__formatter, #expecting) @@ -1292,7 +1342,7 @@ fn deserialize_externally_tagged_enum( #type_name, VARIANTS, __Visitor { - marker: _serde::__private::PhantomData::<#this #ty_generics>, + marker: _serde::__private::PhantomData::<#this_type #ty_generics>, lifetime: _serde::__private::PhantomData, }, ) @@ -1319,9 +1369,7 @@ fn deserialize_internally_tagged_enum( params, variant, cattrs, - quote! { - _serde::__private::de::ContentDeserializer::<__D::Error>::new(__tagged.content) - }, + quote!(__deserializer), )); quote! { @@ -1337,11 +1385,12 @@ fn deserialize_internally_tagged_enum( #variants_stmt - let __tagged = try!(_serde::Deserializer::deserialize_any( + let (__tag, __content) = _serde::Deserializer::deserialize_any( __deserializer, - _serde::__private::de::TaggedContentVisitor::<__Field>::new(#tag, #expecting))); + _serde::__private::de::TaggedContentVisitor::<__Field>::new(#tag, #expecting))?; + let __deserializer = _serde::__private::de::ContentDeserializer::<__D::Error>::new(__content); - match __tagged.tag { + match __tag { #(#variant_arms)* } } @@ -1354,7 +1403,8 @@ fn deserialize_adjacently_tagged_enum( tag: &str, content: &str, ) -> Fragment { - let this = ¶ms.this; + let this_type = ¶ms.this_type; + let this_value = ¶ms.this_value; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params); let delife = params.borrowed.de_lifetime(); @@ -1381,7 +1431,8 @@ fn deserialize_adjacently_tagged_enum( }) .collect(); - let expecting = format!("adjacently tagged enum {}", params.type_name()); + let rust_name = params.type_name(); + let expecting = format!("adjacently tagged enum {}", rust_name); let expecting = cattrs.expecting().unwrap_or(&expecting); let type_name = cattrs.name().deserialize_name(); let deny_unknown_fields = cattrs.deny_unknown_fields(); @@ -1401,6 +1452,14 @@ fn deserialize_adjacently_tagged_enum( } }; + let variant_seed = quote! { + _serde::__private::de::AdjacentlyTaggedEnumVariantSeed::<__Field> { + enum_name: #rust_name, + variants: VARIANTS, + fields_enum: _serde::__private::PhantomData + } + }; + let mut missing_content = quote! { _serde::__private::Err(<__A::Error as _serde::de::Error>::missing_field(#content)) }; @@ -1415,13 +1474,13 @@ fn deserialize_adjacently_tagged_enum( let arm = match variant.style { Style::Unit => quote! { - _serde::__private::Ok(#this::#variant_ident) + _serde::__private::Ok(#this_value::#variant_ident) }, Style::Newtype if variant.attrs.deserialize_with().is_none() => { let span = variant.original.span(); let func = quote_spanned!(span=> _serde::__private::de::missing_field); quote! { - #func(#content).map(#this::#variant_ident) + #func(#content).map(#this_value::#variant_ident) } } _ => { @@ -1445,7 +1504,11 @@ fn deserialize_adjacently_tagged_enum( // Advance the map by one key, returning early in case of error. let next_key = quote! { - try!(_serde::de::MapAccess::next_key_seed(&mut __map, #tag_or_content)) + _serde::de::MapAccess::next_key_seed(&mut __map, #tag_or_content)? + }; + + let variant_from_map = quote! { + _serde::de::MapAccess::next_value_seed(&mut __map, #variant_seed)? }; // When allowing unknown fields, we want to transparently step through keys @@ -1458,7 +1521,7 @@ fn deserialize_adjacently_tagged_enum( while let _serde::__private::Some(__k) = #next_key { match __k { _serde::__private::de::TagContentOtherField::Other => { - let _ = try!(_serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)); + let _ = _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?; continue; }, _serde::__private::de::TagContentOtherField::Tag => { @@ -1493,14 +1556,14 @@ fn deserialize_adjacently_tagged_enum( let finish_content_then_tag = if variant_arms.is_empty() { quote! { - match try!(_serde::de::MapAccess::next_value::<__Field>(&mut __map)) {} + match #variant_from_map {} } } else { quote! { - let __ret = try!(match try!(_serde::de::MapAccess::next_value(&mut __map)) { + let __ret = match #variant_from_map { // Deserialize the buffered content now that we know the variant. #(#variant_arms)* - }); + }?; // Visit remaining keys, looking for duplicates. #visit_remaining_keys } @@ -1511,14 +1574,15 @@ fn deserialize_adjacently_tagged_enum( #variants_stmt + #[doc(hidden)] struct __Seed #de_impl_generics #where_clause { field: __Field, - marker: _serde::__private::PhantomData<#this #ty_generics>, + marker: _serde::__private::PhantomData<#this_type #ty_generics>, lifetime: _serde::__private::PhantomData<&#delife ()>, } impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Seed #de_ty_generics #where_clause { - type Value = #this #ty_generics; + type Value = #this_type #ty_generics; fn deserialize<__D>(self, __deserializer: __D) -> _serde::__private::Result where @@ -1530,13 +1594,14 @@ fn deserialize_adjacently_tagged_enum( } } + #[doc(hidden)] struct __Visitor #de_impl_generics #where_clause { - marker: _serde::__private::PhantomData<#this #ty_generics>, + marker: _serde::__private::PhantomData<#this_type #ty_generics>, lifetime: _serde::__private::PhantomData<&#delife ()>, } impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause { - type Value = #this #ty_generics; + type Value = #this_type #ty_generics; fn expecting(&self, __formatter: &mut _serde::__private::Formatter) -> _serde::__private::fmt::Result { _serde::__private::Formatter::write_str(__formatter, #expecting) @@ -1551,7 +1616,7 @@ fn deserialize_adjacently_tagged_enum( // First key is the tag. _serde::__private::Some(_serde::__private::de::TagOrContentField::Tag) => { // Parse the tag. - let __field = try!(_serde::de::MapAccess::next_value(&mut __map)); + let __field = #variant_from_map; // Visit the second key. match #next_relevant_key { // Second key is a duplicate of the tag. @@ -1560,12 +1625,12 @@ fn deserialize_adjacently_tagged_enum( } // Second key is the content. _serde::__private::Some(_serde::__private::de::TagOrContentField::Content) => { - let __ret = try!(_serde::de::MapAccess::next_value_seed(&mut __map, + let __ret = _serde::de::MapAccess::next_value_seed(&mut __map, __Seed { field: __field, marker: _serde::__private::PhantomData, lifetime: _serde::__private::PhantomData, - })); + })?; // Visit remaining keys, looking for duplicates. #visit_remaining_keys } @@ -1576,7 +1641,7 @@ fn deserialize_adjacently_tagged_enum( // First key is the content. _serde::__private::Some(_serde::__private::de::TagOrContentField::Content) => { // Buffer up the content. - let __content = try!(_serde::de::MapAccess::next_value::<_serde::__private::de::Content>(&mut __map)); + let __content = _serde::de::MapAccess::next_value::<_serde::__private::de::Content>(&mut __map)?; // Visit the second key. match #next_relevant_key { // Second key is the tag. @@ -1606,17 +1671,17 @@ fn deserialize_adjacently_tagged_enum( __A: _serde::de::SeqAccess<#delife>, { // Visit the first element - the tag. - match try!(_serde::de::SeqAccess::next_element(&mut __seq)) { + match _serde::de::SeqAccess::next_element(&mut __seq)? { _serde::__private::Some(__field) => { // Visit the second element - the content. - match try!(_serde::de::SeqAccess::next_element_seed( + match _serde::de::SeqAccess::next_element_seed( &mut __seq, __Seed { field: __field, marker: _serde::__private::PhantomData, lifetime: _serde::__private::PhantomData, }, - )) { + )? { _serde::__private::Some(__ret) => _serde::__private::Ok(__ret), // There is no second element. _serde::__private::None => { @@ -1632,13 +1697,14 @@ fn deserialize_adjacently_tagged_enum( } } + #[doc(hidden)] const FIELDS: &'static [&'static str] = &[#tag, #content]; _serde::Deserializer::deserialize_struct( __deserializer, #type_name, FIELDS, __Visitor { - marker: _serde::__private::PhantomData::<#this #ty_generics>, + marker: _serde::__private::PhantomData::<#this_type #ty_generics>, lifetime: _serde::__private::PhantomData, }, ) @@ -1649,6 +1715,16 @@ fn deserialize_untagged_enum( params: &Parameters, variants: &[Variant], cattrs: &attr::Container, +) -> Fragment { + let first_attempt = None; + deserialize_untagged_enum_after(params, variants, cattrs, first_attempt) +} + +fn deserialize_untagged_enum_after( + params: &Parameters, + variants: &[Variant], + cattrs: &attr::Container, + first_attempt: Option, ) -> Fragment { let attempts = variants .iter() @@ -1658,12 +1734,9 @@ fn deserialize_untagged_enum( params, variant, cattrs, - quote!( - _serde::__private::de::ContentRefDeserializer::<__D::Error>::new(&__content) - ), + quote!(__deserializer), )) }); - // TODO this message could be better by saving the errors from the failed // attempts. The heuristic used by TOML was to count the number of fields // processed before an error, and use the error that happened after the @@ -1676,8 +1749,22 @@ fn deserialize_untagged_enum( ); let fallthrough_msg = cattrs.expecting().unwrap_or(&fallthrough_msg); + // Ignore any error associated with non-untagged deserialization so that we + // can fall through to the untagged variants. This may be infallible so we + // need to provide the error type. + let first_attempt = first_attempt.map(|expr| { + quote! { + if let _serde::__private::Result::<_, __D::Error>::Ok(__ok) = (|| #expr)() { + return _serde::__private::Ok(__ok); + } + } + }); + quote_block! { - let __content = try!(<_serde::__private::de::Content as _serde::Deserialize>::deserialize(__deserializer)); + let __content = <_serde::__private::de::Content as _serde::Deserialize>::deserialize(__deserializer)?; + let __deserializer = _serde::__private::de::ContentRefDeserializer::<__D::Error>::new(&__content); + + #first_attempt #( if let _serde::__private::Ok(__ok) = #attempts { @@ -1707,10 +1794,10 @@ fn deserialize_externally_tagged_variant( match variant.style { Style::Unit => { - let this = ¶ms.this; + let this_value = ¶ms.this_value; quote_block! { - try!(_serde::de::VariantAccess::unit_variant(__variant)); - _serde::__private::Ok(#this::#variant_ident) + _serde::de::VariantAccess::unit_variant(__variant)?; + _serde::__private::Ok(#this_value::#variant_ident) } } Style::Newtype => deserialize_externally_tagged_newtype_variant( @@ -1719,16 +1806,17 @@ fn deserialize_externally_tagged_variant( &variant.fields[0], cattrs, ), - Style::Tuple => { - deserialize_tuple(Some(variant_ident), params, &variant.fields, cattrs, None) - } - Style::Struct => deserialize_struct( - Some(variant_ident), + Style::Tuple => deserialize_tuple( params, &variant.fields, cattrs, - None, - &Untagged::No, + TupleForm::ExternallyTagged(variant_ident), + ), + Style::Struct => deserialize_struct( + params, + &variant.fields, + cattrs, + StructForm::ExternallyTagged(variant_ident), ), } } @@ -1749,16 +1837,16 @@ fn deserialize_internally_tagged_variant( match effective_style(variant) { Style::Unit => { - let this = ¶ms.this; + let this_value = ¶ms.this_value; let type_name = params.type_name(); let variant_name = variant.ident.to_string(); - let default = variant.fields.get(0).map(|field| { + let default = variant.fields.first().map(|field| { let default = Expr(expr_is_missing(field, cattrs)); quote!((#default)) }); quote_block! { - try!(_serde::Deserializer::deserialize_any(#deserializer, _serde::__private::de::InternallyTaggedUnitVisitor::new(#type_name, #variant_name))); - _serde::__private::Ok(#this::#variant_ident #default) + _serde::Deserializer::deserialize_any(#deserializer, _serde::__private::de::InternallyTaggedUnitVisitor::new(#type_name, #variant_name))?; + _serde::__private::Ok(#this_value::#variant_ident #default) } } Style::Newtype => deserialize_untagged_newtype_variant( @@ -1768,12 +1856,10 @@ fn deserialize_internally_tagged_variant( &deserializer, ), Style::Struct => deserialize_struct( - Some(variant_ident), params, &variant.fields, cattrs, - Some(deserializer), - &Untagged::No, + StructForm::InternallyTagged(variant_ident, deserializer), ), Style::Tuple => unreachable!("checked in serde_derive_internals"), } @@ -1796,10 +1882,10 @@ fn deserialize_untagged_variant( match effective_style(variant) { Style::Unit => { - let this = ¶ms.this; + let this_value = ¶ms.this_value; let type_name = params.type_name(); let variant_name = variant.ident.to_string(); - let default = variant.fields.get(0).map(|field| { + let default = variant.fields.first().map(|field| { let default = Expr(expr_is_missing(field, cattrs)); quote!((#default)) }); @@ -1808,7 +1894,7 @@ fn deserialize_untagged_variant( #deserializer, _serde::__private::de::UntaggedUnitVisitor::new(#type_name, #variant_name) ) { - _serde::__private::Ok(()) => _serde::__private::Ok(#this::#variant_ident #default), + _serde::__private::Ok(()) => _serde::__private::Ok(#this_value::#variant_ident #default), _serde::__private::Err(__err) => _serde::__private::Err(__err), } } @@ -1820,19 +1906,16 @@ fn deserialize_untagged_variant( &deserializer, ), Style::Tuple => deserialize_tuple( - Some(variant_ident), params, &variant.fields, cattrs, - Some(deserializer), + TupleForm::Untagged(variant_ident, deserializer), ), Style::Struct => deserialize_struct( - Some(variant_ident), params, &variant.fields, cattrs, - Some(deserializer), - &Untagged::Yes, + StructForm::Untagged(variant_ident, deserializer), ), } } @@ -1843,14 +1926,13 @@ fn deserialize_externally_tagged_newtype_variant( field: &Field, cattrs: &attr::Container, ) -> Fragment { - let this = ¶ms.this; + let this_value = ¶ms.this_value; if field.attrs.skip_deserializing() { - let this = ¶ms.this; let default = Expr(expr_is_missing(field, cattrs)); return quote_block! { - try!(_serde::de::VariantAccess::unit_variant(__variant)); - _serde::__private::Ok(#this::#variant_ident(#default)) + _serde::de::VariantAccess::unit_variant(__variant)?; + _serde::__private::Ok(#this_value::#variant_ident(#default)) }; } @@ -1861,7 +1943,7 @@ fn deserialize_externally_tagged_newtype_variant( let func = quote_spanned!(span=> _serde::de::VariantAccess::newtype_variant::<#field_ty>); quote_expr! { - _serde::__private::Result::map(#func(__variant), #this::#variant_ident) + _serde::__private::Result::map(#func(__variant), #this_value::#variant_ident) } } Some(path) => { @@ -1870,7 +1952,7 @@ fn deserialize_externally_tagged_newtype_variant( #wrapper _serde::__private::Result::map( _serde::de::VariantAccess::newtype_variant::<#wrapper_ty>(__variant), - |__wrapper| #this::#variant_ident(__wrapper.value)) + |__wrapper| #this_value::#variant_ident(__wrapper.value)) } } } @@ -1882,52 +1964,37 @@ fn deserialize_untagged_newtype_variant( field: &Field, deserializer: &TokenStream, ) -> Fragment { - let this = ¶ms.this; + let this_value = ¶ms.this_value; let field_ty = field.ty; match field.attrs.deserialize_with() { None => { let span = field.original.span(); let func = quote_spanned!(span=> <#field_ty as _serde::Deserialize>::deserialize); quote_expr! { - _serde::__private::Result::map(#func(#deserializer), #this::#variant_ident) + _serde::__private::Result::map(#func(#deserializer), #this_value::#variant_ident) } } Some(path) => { quote_block! { let __value: _serde::__private::Result<#field_ty, _> = #path(#deserializer); - _serde::__private::Result::map(__value, #this::#variant_ident) + _serde::__private::Result::map(__value, #this_value::#variant_ident) } } } } fn deserialize_generated_identifier( - fields: &[(String, Ident, Vec)], + fields: &[(&str, Ident, &BTreeSet)], cattrs: &attr::Container, is_variant: bool, - other_idx: Option, + ignore_variant: Option, + fallthrough: Option, ) -> Fragment { - let this = quote!(__Field); + let this_value = quote!(__Field); let field_idents: &Vec<_> = &fields.iter().map(|(_, ident, _)| ident).collect(); - let (ignore_variant, fallthrough) = if !is_variant && cattrs.has_flatten() { - let ignore_variant = quote!(__other(_serde::__private::de::Content<'de>),); - let fallthrough = quote!(_serde::__private::Ok(__Field::__other(__value))); - (Some(ignore_variant), Some(fallthrough)) - } else if let Some(other_idx) = other_idx { - let ignore_variant = fields[other_idx].1.clone(); - let fallthrough = quote!(_serde::__private::Ok(__Field::#ignore_variant)); - (None, Some(fallthrough)) - } else if is_variant || cattrs.deny_unknown_fields() { - (None, None) - } else { - let ignore_variant = quote!(__ignore,); - let fallthrough = quote!(_serde::__private::Ok(__Field::__ignore)); - (Some(ignore_variant), Some(fallthrough)) - }; - let visitor_impl = Stmts(deserialize_identifier( - &this, + &this_value, fields, is_variant, fallthrough, @@ -1944,11 +2011,13 @@ fn deserialize_generated_identifier( quote_block! { #[allow(non_camel_case_types)] + #[doc(hidden)] enum __Field #lifetime { #(#field_idents,)* #ignore_variant } + #[doc(hidden)] struct __FieldVisitor; impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { @@ -1969,6 +2038,33 @@ fn deserialize_generated_identifier( } } +/// Generates enum and its `Deserialize` implementation that represents each +/// non-skipped field of the struct +fn deserialize_field_identifier( + fields: &[(&str, Ident, &BTreeSet)], + cattrs: &attr::Container, +) -> Stmts { + let (ignore_variant, fallthrough) = if cattrs.has_flatten() { + let ignore_variant = quote!(__other(_serde::__private::de::Content<'de>),); + let fallthrough = quote!(_serde::__private::Ok(__Field::__other(__value))); + (Some(ignore_variant), Some(fallthrough)) + } else if cattrs.deny_unknown_fields() { + (None, None) + } else { + let ignore_variant = quote!(__ignore,); + let fallthrough = quote!(_serde::__private::Ok(__Field::__ignore)); + (Some(ignore_variant), Some(fallthrough)) + }; + + Stmts(deserialize_generated_identifier( + fields, + cattrs, + false, + ignore_variant, + fallthrough, + )) +} + // Generates `Deserialize::deserialize` body for an enum with // `serde(field_identifier)` or `serde(variant_identifier)` attribute. fn deserialize_custom_identifier( @@ -1982,8 +2078,8 @@ fn deserialize_custom_identifier( attr::Identifier::No => unreachable!(), }; - let this = ¶ms.this; - let this = quote!(#this); + let this_type = params.this_type.to_token_stream(); + let this_value = params.this_value.to_token_stream(); let (ordinary, fallthrough, fallthrough_borrowed) = if let Some(last) = variants.last() { let last_ident = &last.ident; @@ -1992,7 +2088,7 @@ fn deserialize_custom_identifier( // last variant (checked in `check_identifier`), so all preceding // are ordinary variants. let ordinary = &variants[..variants.len() - 1]; - let fallthrough = quote!(_serde::__private::Ok(#this::#last_ident)); + let fallthrough = quote!(_serde::__private::Ok(#this_value::#last_ident)); (ordinary, Some(fallthrough), None) } else if let Style::Newtype = last.style { let ordinary = &variants[..variants.len() - 1]; @@ -2002,7 +2098,7 @@ fn deserialize_custom_identifier( _serde::Deserialize::deserialize( _serde::__private::de::IdentifierDeserializer::from(#value) ), - #this::#last_ident) + #this_value::#last_ident) } }; ( @@ -2030,17 +2126,19 @@ fn deserialize_custom_identifier( }) .collect(); - let names = names_idents.iter().map(|(name, _, _)| name); + let names = names_idents.iter().flat_map(|&(_, _, aliases)| aliases); let names_const = if fallthrough.is_some() { None } else if is_variant { let variants = quote! { + #[doc(hidden)] const VARIANTS: &'static [&'static str] = &[ #(#names),* ]; }; Some(variants) } else { let fields = quote! { + #[doc(hidden)] const FIELDS: &'static [&'static str] = &[ #(#names),* ]; }; Some(fields) @@ -2050,7 +2148,7 @@ fn deserialize_custom_identifier( split_with_de_lifetime(params); let delife = params.borrowed.de_lifetime(); let visitor_impl = Stmts(deserialize_identifier( - &this, + &this_value, &names_idents, is_variant, fallthrough, @@ -2062,19 +2160,20 @@ fn deserialize_custom_identifier( quote_block! { #names_const + #[doc(hidden)] struct __FieldVisitor #de_impl_generics #where_clause { - marker: _serde::__private::PhantomData<#this #ty_generics>, + marker: _serde::__private::PhantomData<#this_type #ty_generics>, lifetime: _serde::__private::PhantomData<&#delife ()>, } impl #de_impl_generics _serde::de::Visitor<#delife> for __FieldVisitor #de_ty_generics #where_clause { - type Value = #this #ty_generics; + type Value = #this_type #ty_generics; #visitor_impl } let __visitor = __FieldVisitor { - marker: _serde::__private::PhantomData::<#this #ty_generics>, + marker: _serde::__private::PhantomData::<#this_type #ty_generics>, lifetime: _serde::__private::PhantomData, }; _serde::Deserializer::deserialize_identifier(__deserializer, __visitor) @@ -2082,33 +2181,25 @@ fn deserialize_custom_identifier( } fn deserialize_identifier( - this: &TokenStream, - fields: &[(String, Ident, Vec)], + this_value: &TokenStream, + fields: &[(&str, Ident, &BTreeSet)], is_variant: bool, fallthrough: Option, fallthrough_borrowed: Option, collect_other_fields: bool, expecting: Option<&str>, ) -> Fragment { - let mut flat_fields = Vec::new(); - for (_, ident, aliases) in fields { - flat_fields.extend(aliases.iter().map(|alias| (alias, ident))); - } - - let field_strs: &Vec<_> = &flat_fields.iter().map(|(name, _)| name).collect(); - let field_bytes: &Vec<_> = &flat_fields - .iter() - .map(|(name, _)| Literal::byte_string(name.as_bytes())) - .collect(); - - let constructors: &Vec<_> = &flat_fields - .iter() - .map(|(_, ident)| quote!(#this::#ident)) - .collect(); - let main_constructors: &Vec<_> = &fields - .iter() - .map(|(_, ident, _)| quote!(#this::#ident)) - .collect(); + let str_mapping = fields.iter().map(|(_, ident, aliases)| { + // `aliases` also contains a main name + quote!(#(#aliases)|* => _serde::__private::Ok(#this_value::#ident)) + }); + let bytes_mapping = fields.iter().map(|(_, ident, aliases)| { + // `aliases` also contains a main name + let aliases = aliases + .iter() + .map(|alias| Literal::byte_string(alias.as_bytes())); + quote!(#(#aliases)|* => _serde::__private::Ok(#this_value::#ident)) + }); let expecting = expecting.unwrap_or(if is_variant { "variant identifier" @@ -2116,8 +2207,6 @@ fn deserialize_identifier( "field identifier" }); - let index_expecting = if is_variant { "variant" } else { "field" }; - let bytes_to_str = if fallthrough.is_some() || collect_other_fields { None } else { @@ -2165,21 +2254,6 @@ fn deserialize_identifier( &fallthrough_arm_tokens }; - let u64_fallthrough_arm_tokens; - let u64_fallthrough_arm = if let Some(fallthrough) = &fallthrough { - fallthrough - } else { - let fallthrough_msg = format!("{} index 0 <= i < {}", index_expecting, fields.len()); - u64_fallthrough_arm_tokens = quote! { - _serde::__private::Err(_serde::de::Error::invalid_value( - _serde::de::Unexpected::Unsigned(__value), - &#fallthrough_msg, - )) - }; - &u64_fallthrough_arm_tokens - }; - - let variant_indices = 0_u64..; let visit_other = if collect_other_fields { quote! { fn visit_bool<__E>(self, __value: bool) -> _serde::__private::Result @@ -2274,15 +2348,33 @@ fn deserialize_identifier( } } } else { + let u64_mapping = fields.iter().enumerate().map(|(i, (_, ident, _))| { + let i = i as u64; + quote!(#i => _serde::__private::Ok(#this_value::#ident)) + }); + + let u64_fallthrough_arm_tokens; + let u64_fallthrough_arm = if let Some(fallthrough) = &fallthrough { + fallthrough + } else { + let index_expecting = if is_variant { "variant" } else { "field" }; + let fallthrough_msg = format!("{} index 0 <= i < {}", index_expecting, fields.len()); + u64_fallthrough_arm_tokens = quote! { + _serde::__private::Err(_serde::de::Error::invalid_value( + _serde::de::Unexpected::Unsigned(__value), + &#fallthrough_msg, + )) + }; + &u64_fallthrough_arm_tokens + }; + quote! { fn visit_u64<__E>(self, __value: u64) -> _serde::__private::Result where __E: _serde::de::Error, { match __value { - #( - #variant_indices => _serde::__private::Ok(#main_constructors), - )* + #(#u64_mapping,)* _ => #u64_fallthrough_arm, } } @@ -2290,6 +2382,8 @@ fn deserialize_identifier( }; let visit_borrowed = if fallthrough_borrowed.is_some() || collect_other_fields { + let str_mapping = str_mapping.clone(); + let bytes_mapping = bytes_mapping.clone(); let fallthrough_borrowed_arm = fallthrough_borrowed.as_ref().unwrap_or(fallthrough_arm); Some(quote! { fn visit_borrowed_str<__E>(self, __value: &'de str) -> _serde::__private::Result @@ -2297,9 +2391,7 @@ fn deserialize_identifier( __E: _serde::de::Error, { match __value { - #( - #field_strs => _serde::__private::Ok(#constructors), - )* + #(#str_mapping,)* _ => { #value_as_borrowed_str_content #fallthrough_borrowed_arm @@ -2312,9 +2404,7 @@ fn deserialize_identifier( __E: _serde::de::Error, { match __value { - #( - #field_bytes => _serde::__private::Ok(#constructors), - )* + #(#bytes_mapping,)* _ => { #bytes_to_str #value_as_borrowed_bytes_content @@ -2339,9 +2429,7 @@ fn deserialize_identifier( __E: _serde::de::Error, { match __value { - #( - #field_strs => _serde::__private::Ok(#constructors), - )* + #(#str_mapping,)* _ => { #value_as_str_content #fallthrough_arm @@ -2354,9 +2442,7 @@ fn deserialize_identifier( __E: _serde::de::Error, { match __value { - #( - #field_bytes => _serde::__private::Ok(#constructors), - )* + #(#bytes_mapping,)* _ => { #bytes_to_str #value_as_bytes_content @@ -2369,67 +2455,6 @@ fn deserialize_identifier( } } -fn deserialize_struct_as_struct_visitor( - struct_path: &TokenStream, - params: &Parameters, - fields: &[Field], - cattrs: &attr::Container, -) -> (Fragment, Option, Fragment) { - assert!(!cattrs.has_flatten()); - - let field_names_idents: Vec<_> = fields - .iter() - .enumerate() - .filter(|&(_, field)| !field.attrs.skip_deserializing()) - .map(|(i, field)| { - ( - field.attrs.name().deserialize_name(), - field_i(i), - field.attrs.aliases(), - ) - }) - .collect(); - - let fields_stmt = { - let field_names = field_names_idents.iter().map(|(name, _, _)| name); - quote_block! { - const FIELDS: &'static [&'static str] = &[ #(#field_names),* ]; - } - }; - - let field_visitor = deserialize_generated_identifier(&field_names_idents, cattrs, false, None); - - let visit_map = deserialize_map(struct_path, params, fields, cattrs); - - (field_visitor, Some(fields_stmt), visit_map) -} - -fn deserialize_struct_as_map_visitor( - struct_path: &TokenStream, - params: &Parameters, - fields: &[Field], - cattrs: &attr::Container, -) -> (Fragment, Option, Fragment) { - let field_names_idents: Vec<_> = fields - .iter() - .enumerate() - .filter(|&(_, field)| !field.attrs.skip_deserializing() && !field.attrs.flatten()) - .map(|(i, field)| { - ( - field.attrs.name().deserialize_name(), - field_i(i), - field.attrs.aliases(), - ) - }) - .collect(); - - let field_visitor = deserialize_generated_identifier(&field_names_idents, cattrs, false, None); - - let visit_map = deserialize_map(struct_path, params, fields, cattrs); - - (field_visitor, None, visit_map) -} - fn deserialize_map( struct_path: &TokenStream, params: &Parameters, @@ -2480,7 +2505,7 @@ fn deserialize_map( let func = quote_spanned!(span=> _serde::de::MapAccess::next_value::<#field_ty>); quote! { - try!(#func(&mut __map)) + #func(&mut __map)? } } Some(path) => { @@ -2512,29 +2537,29 @@ fn deserialize_map( __Field::__other(__name) => { __collect.push(_serde::__private::Some(( __name, - try!(_serde::de::MapAccess::next_value(&mut __map))))); + _serde::de::MapAccess::next_value(&mut __map)?))); } }) } else if cattrs.deny_unknown_fields() { None } else { Some(quote! { - _ => { let _ = try!(_serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)); } + _ => { let _ = _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?; } }) }; let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing()); let match_keys = if cattrs.deny_unknown_fields() && all_skipped { quote! { - // FIXME: Once we drop support for Rust 1.15: - // let _serde::__private::None::<__Field> = try!(_serde::de::MapAccess::next_key(&mut __map)); + // FIXME: Once feature(exhaustive_patterns) is stable: + // let _serde::__private::None::<__Field> = _serde::de::MapAccess::next_key(&mut __map)?; _serde::__private::Option::map( - try!(_serde::de::MapAccess::next_key::<__Field>(&mut __map)), + _serde::de::MapAccess::next_key::<__Field>(&mut __map)?, |__impossible| match __impossible {}); } } else { quote! { - while let _serde::__private::Some(__key) = try!(_serde::de::MapAccess::next_key::<__Field>(&mut __map)) { + while let _serde::__private::Some(__key) = _serde::de::MapAccess::next_key::<__Field>(&mut __map)? { match __key { #(#value_arms)* #ignored_arm @@ -2570,10 +2595,10 @@ fn deserialize_map( Some(path) => quote!(#path), }; quote! { - let #name: #field_ty = try!(#func( + let #name: #field_ty = #func( _serde::__private::de::FlatMapDeserializer( &mut __collect, - _serde::__private::PhantomData))); + _serde::__private::PhantomData))?; } }); @@ -2621,9 +2646,10 @@ fn deserialize_map( let mut result = quote!(#struct_path { #(#result),* }); if params.has_getter { - let this = ¶ms.this; + let this_type = ¶ms.this_type; + let (_, ty_generics, _) = params.generics.split_for_impl(); result = quote! { - _serde::__private::Into::<#this>::into(#result) + _serde::__private::Into::<#this_type #ty_generics>::into(#result) }; } @@ -2646,41 +2672,6 @@ fn deserialize_map( } } -#[cfg(feature = "deserialize_in_place")] -fn deserialize_struct_as_struct_in_place_visitor( - params: &Parameters, - fields: &[Field], - cattrs: &attr::Container, -) -> (Fragment, Fragment, Fragment) { - assert!(!cattrs.has_flatten()); - - let field_names_idents: Vec<_> = fields - .iter() - .enumerate() - .filter(|&(_, field)| !field.attrs.skip_deserializing()) - .map(|(i, field)| { - ( - field.attrs.name().deserialize_name(), - field_i(i), - field.attrs.aliases(), - ) - }) - .collect(); - - let fields_stmt = { - let field_names = field_names_idents.iter().map(|(name, _, _)| name); - quote_block! { - const FIELDS: &'static [&'static str] = &[ #(#field_names),* ]; - } - }; - - let field_visitor = deserialize_generated_identifier(&field_names_idents, cattrs, false, None); - - let visit_map = deserialize_map_in_place(params, fields, cattrs); - - (field_visitor, fields_stmt, visit_map) -} - #[cfg(feature = "deserialize_in_place")] fn deserialize_map_in_place( params: &Parameters, @@ -2718,7 +2709,7 @@ fn deserialize_map_in_place( let visit = match field.attrs.deserialize_with() { None => { quote! { - try!(_serde::de::MapAccess::next_value_seed(&mut __map, _serde::__private::de::InPlaceSeed(&mut self.place.#member))) + _serde::de::MapAccess::next_value_seed(&mut __map, _serde::__private::de::InPlaceSeed(&mut self.place.#member))? } } Some(path) => { @@ -2750,7 +2741,7 @@ fn deserialize_map_in_place( None } else { Some(quote! { - _ => { let _ = try!(_serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)); } + _ => { let _ = _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?; } }) }; @@ -2758,15 +2749,15 @@ fn deserialize_map_in_place( let match_keys = if cattrs.deny_unknown_fields() && all_skipped { quote! { - // FIXME: Once we drop support for Rust 1.15: - // let _serde::__private::None::<__Field> = try!(_serde::de::MapAccess::next_key(&mut __map)); + // FIXME: Once feature(exhaustive_patterns) is stable: + // let _serde::__private::None::<__Field> = _serde::de::MapAccess::next_key(&mut __map)?; _serde::__private::Option::map( - try!(_serde::de::MapAccess::next_key::<__Field>(&mut __map)), + _serde::de::MapAccess::next_key::<__Field>(&mut __map)?, |__impossible| match __impossible {}); } } else { quote! { - while let _serde::__private::Some(__key) = try!(_serde::de::MapAccess::next_key::<__Field>(&mut __map)) { + while let _serde::__private::Some(__key) = _serde::de::MapAccess::next_key::<__Field>(&mut __map)? { match __key { #(#value_arms_from)* #ignored_arm @@ -2803,15 +2794,15 @@ fn deserialize_map_in_place( } }); - let this = ¶ms.this; + let this_type = ¶ms.this_type; let (_, _, ty_generics, _) = split_with_de_lifetime(params); let let_default = match cattrs.default() { attr::Default::Default => Some(quote!( - let __default: #this #ty_generics = _serde::__private::Default::default(); + let __default: #this_type #ty_generics = _serde::__private::Default::default(); )), attr::Default::Path(path) => Some(quote!( - let __default: #this #ty_generics = #path(); + let __default: #this_type #ty_generics = #path(); )), attr::Default::None => { // We don't need the default value, to prevent an unused variable warning @@ -2844,15 +2835,16 @@ fn wrap_deserialize_with( value_ty: &TokenStream, deserialize_with: &syn::ExprPath, ) -> (TokenStream, TokenStream) { - let this = ¶ms.this; + let this_type = ¶ms.this_type; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params); let delife = params.borrowed.de_lifetime(); let wrapper = quote! { + #[doc(hidden)] struct __DeserializeWith #de_impl_generics #where_clause { value: #value_ty, - phantom: _serde::__private::PhantomData<#this #ty_generics>, + phantom: _serde::__private::PhantomData<#this_type #ty_generics>, lifetime: _serde::__private::PhantomData<&#delife ()>, } @@ -2862,7 +2854,7 @@ fn wrap_deserialize_with( __D: _serde::Deserializer<#delife>, { _serde::__private::Ok(__DeserializeWith { - value: try!(#deserialize_with(__deserializer)), + value: #deserialize_with(__deserializer)?, phantom: _serde::__private::PhantomData, lifetime: _serde::__private::PhantomData, }) @@ -2903,7 +2895,7 @@ fn unwrap_to_variant_closure( variant: &Variant, with_wrapper: bool, ) -> TokenStream { - let this = ¶ms.this; + let this_value = ¶ms.this_value; let variant_ident = &variant.ident; let (arg, wrapper) = if with_wrapper { @@ -2924,23 +2916,23 @@ fn unwrap_to_variant_closure( Style::Struct if variant.fields.len() == 1 => { let member = &variant.fields[0].member; quote! { - |#arg| #this::#variant_ident { #member: #wrapper } + |#arg| #this_value::#variant_ident { #member: #wrapper } } } Style::Struct => { let members = variant.fields.iter().map(|field| &field.member); quote! { - |#arg| #this::#variant_ident { #(#members: #wrapper.#field_access),* } + |#arg| #this_value::#variant_ident { #(#members: #wrapper.#field_access),* } } } Style::Tuple => quote! { - |#arg| #this::#variant_ident(#(#wrapper.#field_access),*) + |#arg| #this_value::#variant_ident(#(#wrapper.#field_access),*) }, Style::Newtype => quote! { - |#arg| #this::#variant_ident(#wrapper) + |#arg| #this_value::#variant_ident(#wrapper) }, Style::Unit => quote! { - |#arg| #this::#variant_ident + |#arg| #this_value::#variant_ident }, } } @@ -2972,7 +2964,7 @@ fn expr_is_missing(field: &Field, cattrs: &attr::Container) -> Fragment { let span = field.original.span(); let func = quote_spanned!(span=> _serde::__private::de::missing_field); quote_expr! { - try!(#func(#name)) + #func(#name)? } } Some(_) => { @@ -2983,6 +2975,35 @@ fn expr_is_missing(field: &Field, cattrs: &attr::Container) -> Fragment { } } +fn expr_is_missing_seq( + assign_to: Option, + index: usize, + field: &Field, + cattrs: &attr::Container, + expecting: &str, +) -> TokenStream { + match field.attrs.default() { + attr::Default::Default => { + let span = field.original.span(); + return quote_spanned!(span=> #assign_to _serde::__private::Default::default()); + } + attr::Default::Path(path) => { + return quote_spanned!(path.span()=> #assign_to #path()); + } + attr::Default::None => { /* below */ } + } + + match *cattrs.default() { + attr::Default::Default | attr::Default::Path(_) => { + let member = &field.member; + quote!(#assign_to __default.#member) + } + attr::Default::None => quote!( + return _serde::__private::Err(_serde::de::Error::invalid_length(#index, &#expecting)) + ), + } +} + fn effective_style(variant: &Variant) -> Style { match variant.style { Style::Newtype if variant.fields[0].attrs.skip_deserializing() => Style::Unit, @@ -2997,7 +3018,7 @@ struct InPlaceImplGenerics<'a>(&'a Parameters); impl<'a> ToTokens for DeImplGenerics<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { let mut generics = self.0.generics.clone(); - if let Some(de_lifetime) = self.0.borrowed.de_lifetime_def() { + if let Some(de_lifetime) = self.0.borrowed.de_lifetime_param() { generics.params = Some(syn::GenericParam::Lifetime(de_lifetime)) .into_iter() .chain(generics.params) @@ -3032,7 +3053,7 @@ impl<'a> ToTokens for InPlaceImplGenerics<'a> { .into_iter() .chain(generics.params) .collect(); - if let Some(de_lifetime) = self.0.borrowed.de_lifetime_def() { + if let Some(de_lifetime) = self.0.borrowed.de_lifetime_param() { generics.params = Some(syn::GenericParam::Lifetime(de_lifetime)) .into_iter() .chain(generics.params) @@ -3054,23 +3075,31 @@ struct DeTypeGenerics<'a>(&'a Parameters); #[cfg(feature = "deserialize_in_place")] struct InPlaceTypeGenerics<'a>(&'a Parameters); +fn de_type_generics_to_tokens( + mut generics: syn::Generics, + borrowed: &BorrowedLifetimes, + tokens: &mut TokenStream, +) { + if borrowed.de_lifetime_param().is_some() { + let def = syn::LifetimeParam { + attrs: Vec::new(), + lifetime: syn::Lifetime::new("'de", Span::call_site()), + colon_token: None, + bounds: Punctuated::new(), + }; + // Prepend 'de lifetime to list of generics + generics.params = Some(syn::GenericParam::Lifetime(def)) + .into_iter() + .chain(generics.params) + .collect(); + } + let (_, ty_generics, _) = generics.split_for_impl(); + ty_generics.to_tokens(tokens); +} + impl<'a> ToTokens for DeTypeGenerics<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { - let mut generics = self.0.generics.clone(); - if self.0.borrowed.de_lifetime_def().is_some() { - let def = syn::LifetimeDef { - attrs: Vec::new(), - lifetime: syn::Lifetime::new("'de", Span::call_site()), - colon_token: None, - bounds: Punctuated::new(), - }; - generics.params = Some(syn::GenericParam::Lifetime(def)) - .into_iter() - .chain(generics.params) - .collect(); - } - let (_, ty_generics, _) = generics.split_for_impl(); - ty_generics.to_tokens(tokens); + de_type_generics_to_tokens(self.0.generics.clone(), &self.0.borrowed, tokens); } } @@ -3083,20 +3112,7 @@ impl<'a> ToTokens for InPlaceTypeGenerics<'a> { .chain(generics.params) .collect(); - if self.0.borrowed.de_lifetime_def().is_some() { - let def = syn::LifetimeDef { - attrs: Vec::new(), - lifetime: syn::Lifetime::new("'de", Span::call_site()), - colon_token: None, - bounds: Punctuated::new(), - }; - generics.params = Some(syn::GenericParam::Lifetime(def)) - .into_iter() - .chain(generics.params) - .collect(); - } - let (_, ty_generics, _) = generics.split_for_impl(); - ty_generics.to_tokens(tokens); + de_type_generics_to_tokens(generics, &self.0.borrowed, tokens); } } @@ -3108,8 +3124,8 @@ impl<'a> DeTypeGenerics<'a> { } #[cfg(feature = "deserialize_in_place")] -fn place_lifetime() -> syn::LifetimeDef { - syn::LifetimeDef { +fn place_lifetime() -> syn::LifetimeParam { + syn::LifetimeParam { attrs: Vec::new(), lifetime: syn::Lifetime::new("'place", Span::call_site()), colon_token: None, diff --git a/serde_derive/src/dummy.rs b/serde_derive/src/dummy.rs index 29de2601..095f950f 100644 --- a/serde_derive/src/dummy.rs +++ b/serde_derive/src/dummy.rs @@ -1,23 +1,7 @@ -use proc_macro2::{Ident, TokenStream}; -use quote::format_ident; - -use syn; -use try; - -pub fn wrap_in_const( - serde_path: Option<&syn::Path>, - trait_: &str, - ty: &Ident, - code: TokenStream, -) -> TokenStream { - let try_replacement = try::replacement(); - - let dummy_const = if cfg!(underscore_consts) { - format_ident!("_") - } else { - format_ident!("_IMPL_{}_FOR_{}", trait_, unraw(ty)) - }; +use proc_macro2::TokenStream; +use quote::quote; +pub fn wrap_in_const(serde_path: Option<&syn::Path>, code: TokenStream) -> TokenStream { let use_serde = match serde_path { Some(path) => quote! { use #path as _serde; @@ -31,18 +15,9 @@ pub fn wrap_in_const( quote! { #[doc(hidden)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] - const #dummy_const: () = { + const _: () = { #use_serde - #try_replacement #code }; } } - -#[allow(deprecated)] -fn unraw(ident: &Ident) -> String { - // str::trim_start_matches was added in 1.30, trim_left_matches deprecated - // in 1.33. We currently support rustc back to 1.15 so we need to continue - // to use the deprecated one. - ident.to_string().trim_left_matches("r#").to_owned() -} diff --git a/serde_derive/src/fragment.rs b/serde_derive/src/fragment.rs index 324504aa..6627c266 100644 --- a/serde_derive/src/fragment.rs +++ b/serde_derive/src/fragment.rs @@ -1,6 +1,6 @@ use proc_macro2::TokenStream; use quote::ToTokens; -use syn::token; +use syn::{token, Token}; pub enum Fragment { /// Tokens that can be used as an expression. diff --git a/serde_derive/src/internals/ast.rs b/serde_derive/src/internals/ast.rs index 2a6950b2..a28d3ae7 100644 --- a/serde_derive/src/internals/ast.rs +++ b/serde_derive/src/internals/ast.rs @@ -1,10 +1,8 @@ //! A Serde ast, parsed from the Syn ast and ready to generate Rust code. -use internals::attr; -use internals::check; -use internals::{Ctxt, Derive}; -use syn; +use crate::internals::{attr, check, Ctxt, Derive}; use syn::punctuated::Punctuated; +use syn::Token; /// A source data structure annotated with `#[derive(Serialize)]` and/or `#[derive(Deserialize)]`, /// parsed into an internal representation. @@ -88,9 +86,12 @@ impl<'a> Container<'a> { if field.attrs.flatten() { has_flatten = true; } - field - .attrs - .rename_by_rules(variant.attrs.rename_all_rules()); + field.attrs.rename_by_rules( + variant + .attrs + .rename_all_rules() + .or(attrs.rename_all_fields_rules()), + ); } } } @@ -121,7 +122,7 @@ impl<'a> Container<'a> { } impl<'a> Data<'a> { - pub fn all_fields(&'a self) -> Box> + 'a> { + pub fn all_fields(&'a self) -> Box> + 'a> { match self { Data::Enum(variants) => { Box::new(variants.iter().flat_map(|variant| variant.fields.iter())) @@ -140,7 +141,7 @@ fn enum_from_ast<'a>( variants: &'a Punctuated, container_default: &attr::Default, ) -> Vec> { - variants + let variants: Vec = variants .iter() .map(|variant| { let attrs = attr::Variant::from_ast(cx, variant); @@ -154,7 +155,20 @@ fn enum_from_ast<'a>( original: variant, } }) - .collect() + .collect(); + + let index_of_last_tagged_variant = variants + .iter() + .rposition(|variant| !variant.attrs.untagged()); + if let Some(index_of_last_tagged_variant) = index_of_last_tagged_variant { + for variant in &variants[..index_of_last_tagged_variant] { + if variant.attrs.untagged() { + cx.error_spanned_by(&variant.ident, "all variants with the #[serde(untagged)] attribute must be placed at the end of the enum"); + } + } + } + + variants } fn struct_from_ast<'a>( diff --git a/serde_derive/src/internals/attr.rs b/serde_derive/src/internals/attr.rs index 13f55250..bb9de328 100644 --- a/serde_derive/src/internals/attr.rs +++ b/serde_derive/src/internals/attr.rs @@ -1,16 +1,14 @@ -use internals::respan::respan; -use internals::symbol::*; -use internals::{ungroup, Ctxt}; +use crate::internals::symbol::*; +use crate::internals::{ungroup, Ctxt}; use proc_macro2::{Spacing, Span, TokenStream, TokenTree}; use quote::ToTokens; use std::borrow::Cow; use std::collections::BTreeSet; -use syn; -use syn::parse::{self, Parse, ParseStream}; +use std::iter::FromIterator; +use syn::meta::ParseNestedMeta; +use syn::parse::ParseStream; use syn::punctuated::Punctuated; -use syn::Ident; -use syn::Meta::{List, NameValue, Path}; -use syn::NestedMeta::{Lit, Meta}; +use syn::{parse_quote, token, Ident, Lifetime, Token}; // This module handles parsing of `#[serde(...)]` attributes. The entrypoints // are `attr::Container::from_ast`, `attr::Variant::from_ast`, and @@ -20,7 +18,7 @@ use syn::NestedMeta::{Lit, Meta}; // user will see errors simultaneously for all bad attributes in the crate // rather than just the first. -pub use internals::case::RenameRule; +pub use crate::internals::case::RenameRule; struct Attr<'c, T> { cx: &'c Ctxt, @@ -43,8 +41,8 @@ impl<'c, T> Attr<'c, T> { let tokens = obj.into_token_stream(); if self.value.is_some() { - self.cx - .error_spanned_by(tokens, format!("duplicate serde attribute `{}`", self.name)); + let msg = format!("duplicate serde attribute `{}`", self.name); + self.cx.error_spanned_by(tokens, msg); } else { self.tokens = tokens; self.value = Some(value); @@ -115,16 +113,14 @@ impl<'c, T> VecAttr<'c, T> { self.values.push(value); } - fn at_most_one(mut self) -> Result, ()> { + fn at_most_one(mut self) -> Option { if self.values.len() > 1 { let dup_token = self.first_dup_tokens; - self.cx.error_spanned_by( - dup_token, - format!("duplicate serde attribute `{}`", self.name), - ); - Err(()) + let msg = format!("duplicate serde attribute `{}`", self.name); + self.cx.error_spanned_by(dup_token, msg); + None } else { - Ok(self.values.pop()) + self.values.pop() } } @@ -138,15 +134,11 @@ pub struct Name { serialize_renamed: bool, deserialize: String, deserialize_renamed: bool, - deserialize_aliases: Vec, + deserialize_aliases: BTreeSet, } -#[allow(deprecated)] fn unraw(ident: &Ident) -> String { - // str::trim_start_matches was added in 1.30, trim_left_matches deprecated - // in 1.33. We currently support rustc back to 1.15 so we need to continue - // to use the deprecated one. - ident.to_string().trim_left_matches("r#").to_owned() + ident.to_string().trim_start_matches("r#").to_owned() } impl Name { @@ -156,16 +148,12 @@ impl Name { de_name: Attr, de_aliases: Option>, ) -> Name { - let deserialize_aliases = match de_aliases { - Some(de_aliases) => { - let mut alias_list = BTreeSet::new(); - for alias_name in de_aliases.get() { - alias_list.insert(alias_name); - } - alias_list.into_iter().collect() + let mut alias_set = BTreeSet::new(); + if let Some(de_aliases) = de_aliases { + for alias_name in de_aliases.get() { + alias_set.insert(alias_name); } - None => Vec::new(), - }; + } let ser_name = ser_name.get(); let ser_renamed = ser_name.is_some(); @@ -176,35 +164,42 @@ impl Name { serialize_renamed: ser_renamed, deserialize: de_name.unwrap_or(source_name), deserialize_renamed: de_renamed, - deserialize_aliases, + deserialize_aliases: alias_set, } } /// Return the container name for the container when serializing. - pub fn serialize_name(&self) -> String { - self.serialize.clone() + pub fn serialize_name(&self) -> &str { + &self.serialize } /// Return the container name for the container when deserializing. - pub fn deserialize_name(&self) -> String { - self.deserialize.clone() + pub fn deserialize_name(&self) -> &str { + &self.deserialize } - fn deserialize_aliases(&self) -> Vec { - let mut aliases = self.deserialize_aliases.clone(); - let main_name = self.deserialize_name(); - if !aliases.contains(&main_name) { - aliases.push(main_name); - } - aliases + fn deserialize_aliases(&self) -> &BTreeSet { + &self.deserialize_aliases } } +#[derive(Copy, Clone)] pub struct RenameAllRules { serialize: RenameRule, deserialize: RenameRule, } +impl RenameAllRules { + /// Returns a new `RenameAllRules` with the individual rules of `self` and + /// `other_rules` joined by `RenameRules::or`. + pub fn or(self, other_rules: Self) -> Self { + Self { + serialize: self.serialize.or(other_rules.serialize), + deserialize: self.deserialize.or(other_rules.deserialize), + } + } +} + /// Represents struct or enum attribute information. pub struct Container { name: Name, @@ -212,6 +207,7 @@ pub struct Container { deny_unknown_fields: bool, default: Default, rename_all_rules: RenameAllRules, + rename_all_fields_rules: RenameAllRules, ser_bound: Option>, de_bound: Option>, tag: TagType, @@ -225,6 +221,7 @@ pub struct Container { is_packed: bool, /// Error message generated when type can't be deserialized expecting: Option, + non_exhaustive: bool, } /// Styles of representing an enum. @@ -295,6 +292,8 @@ impl Container { let mut default = Attr::none(cx, DEFAULT); let mut rename_all_ser_rule = Attr::none(cx, RENAME_ALL); let mut rename_all_de_rule = Attr::none(cx, RENAME_ALL); + let mut rename_all_fields_ser_rule = Attr::none(cx, RENAME_ALL_FIELDS); + let mut rename_all_fields_de_rule = Attr::none(cx, RENAME_ALL_FIELDS); let mut ser_bound = Attr::none(cx, BOUND); let mut de_bound = Attr::none(cx, BOUND); let mut untagged = BoolAttr::none(cx, UNTAGGED); @@ -308,286 +307,254 @@ impl Container { let mut variant_identifier = BoolAttr::none(cx, VARIANT_IDENTIFIER); let mut serde_path = Attr::none(cx, CRATE); let mut expecting = Attr::none(cx, EXPECTING); + let mut non_exhaustive = false; - for meta_item in item - .attrs - .iter() - .flat_map(|attr| get_serde_meta_items(cx, attr)) - .flatten() - { - match &meta_item { - // Parse `#[serde(rename = "foo")]` - Meta(NameValue(m)) if m.path == RENAME => { - if let Ok(s) = get_lit_str(cx, RENAME, &m.lit) { - ser_name.set(&m.path, s.value()); - de_name.set(&m.path, s.value()); - } + for attr in &item.attrs { + if attr.path() != SERDE { + non_exhaustive |= + matches!(&attr.meta, syn::Meta::Path(path) if path == NON_EXHAUSTIVE); + continue; + } + + if let syn::Meta::List(meta) = &attr.meta { + if meta.tokens.is_empty() { + continue; } + } - // Parse `#[serde(rename(serialize = "foo", deserialize = "bar"))]` - Meta(List(m)) if m.path == RENAME => { - if let Ok((ser, de)) = get_renames(cx, &m.nested) { - ser_name.set_opt(&m.path, ser.map(syn::LitStr::value)); - de_name.set_opt(&m.path, de.map(syn::LitStr::value)); - } - } - - // Parse `#[serde(rename_all = "foo")]` - Meta(NameValue(m)) if m.path == RENAME_ALL => { - if let Ok(s) = get_lit_str(cx, RENAME_ALL, &m.lit) { - match RenameRule::from_str(&s.value()) { - Ok(rename_rule) => { - rename_all_ser_rule.set(&m.path, rename_rule); - rename_all_de_rule.set(&m.path, rename_rule); - } - Err(err) => cx.error_spanned_by(s, err), + if let Err(err) = attr.parse_nested_meta(|meta| { + if meta.path == RENAME { + // #[serde(rename = "foo")] + // #[serde(rename(serialize = "foo", deserialize = "bar"))] + let (ser, de) = get_renames(cx, RENAME, &meta)?; + ser_name.set_opt(&meta.path, ser.as_ref().map(syn::LitStr::value)); + de_name.set_opt(&meta.path, de.as_ref().map(syn::LitStr::value)); + } else if meta.path == RENAME_ALL { + // #[serde(rename_all = "foo")] + // #[serde(rename_all(serialize = "foo", deserialize = "bar"))] + let one_name = meta.input.peek(Token![=]); + let (ser, de) = get_renames(cx, RENAME_ALL, &meta)?; + if let Some(ser) = ser { + match RenameRule::from_str(&ser.value()) { + Ok(rename_rule) => rename_all_ser_rule.set(&meta.path, rename_rule), + Err(err) => cx.error_spanned_by(ser, err), } } - } - - // Parse `#[serde(rename_all(serialize = "foo", deserialize = "bar"))]` - Meta(List(m)) if m.path == RENAME_ALL => { - if let Ok((ser, de)) = get_renames(cx, &m.nested) { - if let Some(ser) = ser { - match RenameRule::from_str(&ser.value()) { - Ok(rename_rule) => rename_all_ser_rule.set(&m.path, rename_rule), - Err(err) => cx.error_spanned_by(ser, err), - } - } - if let Some(de) = de { - match RenameRule::from_str(&de.value()) { - Ok(rename_rule) => rename_all_de_rule.set(&m.path, rename_rule), - Err(err) => cx.error_spanned_by(de, err), - } - } - } - } - - // Parse `#[serde(transparent)]` - Meta(Path(word)) if word == TRANSPARENT => { - transparent.set_true(word); - } - - // Parse `#[serde(deny_unknown_fields)]` - Meta(Path(word)) if word == DENY_UNKNOWN_FIELDS => { - deny_unknown_fields.set_true(word); - } - - // Parse `#[serde(default)]` - Meta(Path(word)) if word == DEFAULT => match &item.data { - syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields { - syn::Fields::Named(_) => { - default.set(word, Default::Default); - } - syn::Fields::Unnamed(_) | syn::Fields::Unit => cx.error_spanned_by( - fields, - "#[serde(default)] can only be used on structs with named fields", - ), - }, - syn::Data::Enum(syn::DataEnum { enum_token, .. }) => cx.error_spanned_by( - enum_token, - "#[serde(default)] can only be used on structs with named fields", - ), - syn::Data::Union(syn::DataUnion { union_token, .. }) => cx.error_spanned_by( - union_token, - "#[serde(default)] can only be used on structs with named fields", - ), - }, - - // Parse `#[serde(default = "...")]` - Meta(NameValue(m)) if m.path == DEFAULT => { - if let Ok(path) = parse_lit_into_expr_path(cx, DEFAULT, &m.lit) { - match &item.data { - syn::Data::Struct(syn::DataStruct { fields, .. }) => { - match fields { - syn::Fields::Named(_) => { - default.set(&m.path, Default::Path(path)); - } - syn::Fields::Unnamed(_) | syn::Fields::Unit => cx - .error_spanned_by( - fields, - "#[serde(default = \"...\")] can only be used on structs with named fields", - ), + if let Some(de) = de { + match RenameRule::from_str(&de.value()) { + Ok(rename_rule) => rename_all_de_rule.set(&meta.path, rename_rule), + Err(err) => { + if !one_name { + cx.error_spanned_by(de, err); } } - syn::Data::Enum(syn::DataEnum { enum_token, .. }) => cx - .error_spanned_by( - enum_token, - "#[serde(default = \"...\")] can only be used on structs with named fields", - ), - syn::Data::Union(syn::DataUnion { - union_token, .. - }) => cx.error_spanned_by( - union_token, - "#[serde(default = \"...\")] can only be used on structs with named fields", - ), } } - } + } else if meta.path == RENAME_ALL_FIELDS { + // #[serde(rename_all_fields = "foo")] + // #[serde(rename_all_fields(serialize = "foo", deserialize = "bar"))] + let one_name = meta.input.peek(Token![=]); + let (ser, de) = get_renames(cx, RENAME_ALL_FIELDS, &meta)?; - // Parse `#[serde(bound = "T: SomeBound")]` - Meta(NameValue(m)) if m.path == BOUND => { - if let Ok(where_predicates) = parse_lit_into_where(cx, BOUND, BOUND, &m.lit) { - ser_bound.set(&m.path, where_predicates.clone()); - de_bound.set(&m.path, where_predicates); + match item.data { + syn::Data::Enum(_) => { + if let Some(ser) = ser { + match RenameRule::from_str(&ser.value()) { + Ok(rename_rule) => { + rename_all_fields_ser_rule.set(&meta.path, rename_rule); + } + Err(err) => cx.error_spanned_by(ser, err), + } + } + if let Some(de) = de { + match RenameRule::from_str(&de.value()) { + Ok(rename_rule) => { + rename_all_fields_de_rule.set(&meta.path, rename_rule); + } + Err(err) => { + if !one_name { + cx.error_spanned_by(de, err); + } + } + } + } + } + syn::Data::Struct(_) => { + let msg = "#[serde(rename_all_fields)] can only be used on enums"; + cx.syn_error(meta.error(msg)); + } + syn::Data::Union(_) => { + let msg = "#[serde(rename_all_fields)] can only be used on enums"; + cx.syn_error(meta.error(msg)); + } } - } - - // Parse `#[serde(bound(serialize = "...", deserialize = "..."))]` - Meta(List(m)) if m.path == BOUND => { - if let Ok((ser, de)) = get_where_predicates(cx, &m.nested) { - ser_bound.set_opt(&m.path, ser); - de_bound.set_opt(&m.path, de); + } else if meta.path == TRANSPARENT { + // #[serde(transparent)] + transparent.set_true(meta.path); + } else if meta.path == DENY_UNKNOWN_FIELDS { + // #[serde(deny_unknown_fields)] + deny_unknown_fields.set_true(meta.path); + } else if meta.path == DEFAULT { + if meta.input.peek(Token![=]) { + // #[serde(default = "...")] + if let Some(path) = parse_lit_into_expr_path(cx, DEFAULT, &meta)? { + match &item.data { + syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields { + syn::Fields::Named(_) | syn::Fields::Unnamed(_) => { + default.set(&meta.path, Default::Path(path)); + } + syn::Fields::Unit => { + let msg = "#[serde(default = \"...\")] can only be used on structs that have fields"; + cx.syn_error(meta.error(msg)); + } + }, + syn::Data::Enum(_) => { + let msg = "#[serde(default = \"...\")] can only be used on structs"; + cx.syn_error(meta.error(msg)); + } + syn::Data::Union(_) => { + let msg = "#[serde(default = \"...\")] can only be used on structs"; + cx.syn_error(meta.error(msg)); + } + } + } + } else { + // #[serde(default)] + match &item.data { + syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields { + syn::Fields::Named(_) | syn::Fields::Unnamed(_) => { + default.set(meta.path, Default::Default); + } + syn::Fields::Unit => { + let msg = "#[serde(default)] can only be used on structs that have fields"; + cx.error_spanned_by(fields, msg); + } + }, + syn::Data::Enum(_) => { + let msg = "#[serde(default)] can only be used on structs"; + cx.syn_error(meta.error(msg)); + } + syn::Data::Union(_) => { + let msg = "#[serde(default)] can only be used on structs"; + cx.syn_error(meta.error(msg)); + } + } } - } - - // Parse `#[serde(untagged)]` - Meta(Path(word)) if word == UNTAGGED => match item.data { - syn::Data::Enum(_) => { - untagged.set_true(word); + } else if meta.path == BOUND { + // #[serde(bound = "T: SomeBound")] + // #[serde(bound(serialize = "...", deserialize = "..."))] + let (ser, de) = get_where_predicates(cx, &meta)?; + ser_bound.set_opt(&meta.path, ser); + de_bound.set_opt(&meta.path, de); + } else if meta.path == UNTAGGED { + // #[serde(untagged)] + match item.data { + syn::Data::Enum(_) => { + untagged.set_true(&meta.path); + } + syn::Data::Struct(_) => { + let msg = "#[serde(untagged)] can only be used on enums"; + cx.syn_error(meta.error(msg)); + } + syn::Data::Union(_) => { + let msg = "#[serde(untagged)] can only be used on enums"; + cx.syn_error(meta.error(msg)); + } } - syn::Data::Struct(syn::DataStruct { struct_token, .. }) => { - cx.error_spanned_by( - struct_token, - "#[serde(untagged)] can only be used on enums", - ); - } - syn::Data::Union(syn::DataUnion { union_token, .. }) => { - cx.error_spanned_by( - union_token, - "#[serde(untagged)] can only be used on enums", - ); - } - }, - - // Parse `#[serde(tag = "type")]` - Meta(NameValue(m)) if m.path == TAG => { - if let Ok(s) = get_lit_str(cx, TAG, &m.lit) { + } else if meta.path == TAG { + // #[serde(tag = "type")] + if let Some(s) = get_lit_str(cx, TAG, &meta)? { match &item.data { syn::Data::Enum(_) => { - internal_tag.set(&m.path, s.value()); + internal_tag.set(&meta.path, s.value()); } syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields { syn::Fields::Named(_) => { - internal_tag.set(&m.path, s.value()); + internal_tag.set(&meta.path, s.value()); } syn::Fields::Unnamed(_) | syn::Fields::Unit => { - cx.error_spanned_by( - fields, - "#[serde(tag = \"...\")] can only be used on enums and structs with named fields", - ); + let msg = "#[serde(tag = \"...\")] can only be used on enums and structs with named fields"; + cx.syn_error(meta.error(msg)); } }, - syn::Data::Union(syn::DataUnion { union_token, .. }) => { - cx.error_spanned_by( - union_token, - "#[serde(tag = \"...\")] can only be used on enums and structs with named fields", - ); + syn::Data::Union(_) => { + let msg = "#[serde(tag = \"...\")] can only be used on enums and structs with named fields"; + cx.syn_error(meta.error(msg)); } } } - } - - // Parse `#[serde(content = "c")]` - Meta(NameValue(m)) if m.path == CONTENT => { - if let Ok(s) = get_lit_str(cx, CONTENT, &m.lit) { + } else if meta.path == CONTENT { + // #[serde(content = "c")] + if let Some(s) = get_lit_str(cx, CONTENT, &meta)? { match &item.data { syn::Data::Enum(_) => { - content.set(&m.path, s.value()); + content.set(&meta.path, s.value()); } - syn::Data::Struct(syn::DataStruct { struct_token, .. }) => { - cx.error_spanned_by( - struct_token, - "#[serde(content = \"...\")] can only be used on enums", - ); + syn::Data::Struct(_) => { + let msg = "#[serde(content = \"...\")] can only be used on enums"; + cx.syn_error(meta.error(msg)); } - syn::Data::Union(syn::DataUnion { union_token, .. }) => { - cx.error_spanned_by( - union_token, - "#[serde(content = \"...\")] can only be used on enums", - ); + syn::Data::Union(_) => { + let msg = "#[serde(content = \"...\")] can only be used on enums"; + cx.syn_error(meta.error(msg)); } } } - } - - // Parse `#[serde(from = "Type")] - Meta(NameValue(m)) if m.path == FROM => { - if let Ok(from_ty) = parse_lit_into_ty(cx, FROM, &m.lit) { - type_from.set_opt(&m.path, Some(from_ty)); + } else if meta.path == FROM { + // #[serde(from = "Type")] + if let Some(from_ty) = parse_lit_into_ty(cx, FROM, &meta)? { + type_from.set_opt(&meta.path, Some(from_ty)); } - } - - // Parse `#[serde(try_from = "Type")] - Meta(NameValue(m)) if m.path == TRY_FROM => { - if let Ok(try_from_ty) = parse_lit_into_ty(cx, TRY_FROM, &m.lit) { - type_try_from.set_opt(&m.path, Some(try_from_ty)); + } else if meta.path == TRY_FROM { + // #[serde(try_from = "Type")] + if let Some(try_from_ty) = parse_lit_into_ty(cx, TRY_FROM, &meta)? { + type_try_from.set_opt(&meta.path, Some(try_from_ty)); } - } - - // Parse `#[serde(into = "Type")] - Meta(NameValue(m)) if m.path == INTO => { - if let Ok(into_ty) = parse_lit_into_ty(cx, INTO, &m.lit) { - type_into.set_opt(&m.path, Some(into_ty)); + } else if meta.path == INTO { + // #[serde(into = "Type")] + if let Some(into_ty) = parse_lit_into_ty(cx, INTO, &meta)? { + type_into.set_opt(&meta.path, Some(into_ty)); } - } - - // Parse `#[serde(remote = "...")]` - Meta(NameValue(m)) if m.path == REMOTE => { - if let Ok(path) = parse_lit_into_path(cx, REMOTE, &m.lit) { + } else if meta.path == REMOTE { + // #[serde(remote = "...")] + if let Some(path) = parse_lit_into_path(cx, REMOTE, &meta)? { if is_primitive_path(&path, "Self") { - remote.set(&m.path, item.ident.clone().into()); + remote.set(&meta.path, item.ident.clone().into()); } else { - remote.set(&m.path, path); + remote.set(&meta.path, path); } } - } - - // Parse `#[serde(field_identifier)]` - Meta(Path(word)) if word == FIELD_IDENTIFIER => { - field_identifier.set_true(word); - } - - // Parse `#[serde(variant_identifier)]` - Meta(Path(word)) if word == VARIANT_IDENTIFIER => { - variant_identifier.set_true(word); - } - - // Parse `#[serde(crate = "foo")]` - Meta(NameValue(m)) if m.path == CRATE => { - if let Ok(path) = parse_lit_into_path(cx, CRATE, &m.lit) { - serde_path.set(&m.path, path); + } else if meta.path == FIELD_IDENTIFIER { + // #[serde(field_identifier)] + field_identifier.set_true(&meta.path); + } else if meta.path == VARIANT_IDENTIFIER { + // #[serde(variant_identifier)] + variant_identifier.set_true(&meta.path); + } else if meta.path == CRATE { + // #[serde(crate = "foo")] + if let Some(path) = parse_lit_into_path(cx, CRATE, &meta)? { + serde_path.set(&meta.path, path); } - } - - // Parse `#[serde(expecting = "a message")]` - Meta(NameValue(m)) if m.path == EXPECTING => { - if let Ok(s) = get_lit_str(cx, EXPECTING, &m.lit) { - expecting.set(&m.path, s.value()); + } else if meta.path == EXPECTING { + // #[serde(expecting = "a message")] + if let Some(s) = get_lit_str(cx, EXPECTING, &meta)? { + expecting.set(&meta.path, s.value()); } - } - - Meta(meta_item) => { - let path = meta_item - .path() - .into_token_stream() - .to_string() - .replace(' ', ""); - cx.error_spanned_by( - meta_item.path(), - format!("unknown serde container attribute `{}`", path), + } else { + let path = meta.path.to_token_stream().to_string().replace(' ', ""); + return Err( + meta.error(format_args!("unknown serde container attribute `{}`", path)) ); } - - Lit(lit) => { - cx.error_spanned_by(lit, "unexpected literal in serde container attribute"); - } + Ok(()) + }) { + cx.syn_error(err); } } let mut is_packed = false; for attr in &item.attrs { - if attr.path.is_ident("repr") { + if attr.path() == REPR { let _ = attr.parse_args_with(|input: ParseStream| { while let Some(token) = input.parse()? { if let TokenTree::Ident(ident) = token { @@ -608,6 +575,10 @@ impl Container { serialize: rename_all_ser_rule.get().unwrap_or(RenameRule::None), deserialize: rename_all_de_rule.get().unwrap_or(RenameRule::None), }, + rename_all_fields_rules: RenameAllRules { + serialize: rename_all_fields_ser_rule.get().unwrap_or(RenameRule::None), + deserialize: rename_all_fields_de_rule.get().unwrap_or(RenameRule::None), + }, ser_bound: ser_bound.get(), de_bound: de_bound.get(), tag: decide_tag(cx, item, untagged, internal_tag, content), @@ -620,6 +591,7 @@ impl Container { serde_path: serde_path.get(), is_packed, expecting: expecting.get(), + non_exhaustive, } } @@ -627,8 +599,12 @@ impl Container { &self.name } - pub fn rename_all_rules(&self) -> &RenameAllRules { - &self.rename_all_rules + pub fn rename_all_rules(&self) -> RenameAllRules { + self.rename_all_rules + } + + pub fn rename_all_fields_rules(&self) -> RenameAllRules { + self.rename_all_fields_rules } pub fn transparent(&self) -> bool { @@ -701,6 +677,10 @@ impl Container { pub fn expecting(&self) -> Option<&str> { self.expecting.as_ref().map(String::as_ref) } + + pub fn non_exhaustive(&self) -> bool { + self.non_exhaustive + } } fn decide_tag( @@ -725,10 +705,9 @@ fn decide_tag( syn::Fields::Named(_) | syn::Fields::Unit => {} syn::Fields::Unnamed(fields) => { if fields.unnamed.len() != 1 { - cx.error_spanned_by( - variant, - "#[serde(tag = \"...\")] cannot be used with tuple variants", - ); + let msg = + "#[serde(tag = \"...\")] cannot be used with tuple variants"; + cx.error_spanned_by(variant, msg); break; } } @@ -737,49 +716,29 @@ fn decide_tag( } TagType::Internal { tag } } - (Some((untagged_tokens, _)), Some((tag_tokens, _)), None) => { - cx.error_spanned_by( - untagged_tokens, - "enum cannot be both untagged and internally tagged", - ); - cx.error_spanned_by( - tag_tokens, - "enum cannot be both untagged and internally tagged", - ); + (Some((untagged_tokens, ())), Some((tag_tokens, _)), None) => { + let msg = "enum cannot be both untagged and internally tagged"; + cx.error_spanned_by(untagged_tokens, msg); + cx.error_spanned_by(tag_tokens, msg); TagType::External // doesn't matter, will error } (None, None, Some((content_tokens, _))) => { - cx.error_spanned_by( - content_tokens, - "#[serde(tag = \"...\", content = \"...\")] must be used together", - ); + let msg = "#[serde(tag = \"...\", content = \"...\")] must be used together"; + cx.error_spanned_by(content_tokens, msg); TagType::External } - (Some((untagged_tokens, _)), None, Some((content_tokens, _))) => { - cx.error_spanned_by( - untagged_tokens, - "untagged enum cannot have #[serde(content = \"...\")]", - ); - cx.error_spanned_by( - content_tokens, - "untagged enum cannot have #[serde(content = \"...\")]", - ); + (Some((untagged_tokens, ())), None, Some((content_tokens, _))) => { + let msg = "untagged enum cannot have #[serde(content = \"...\")]"; + cx.error_spanned_by(untagged_tokens, msg); + cx.error_spanned_by(content_tokens, msg); TagType::External } (None, Some((_, tag)), Some((_, content))) => TagType::Adjacent { tag, content }, - (Some((untagged_tokens, _)), Some((tag_tokens, _)), Some((content_tokens, _))) => { - cx.error_spanned_by( - untagged_tokens, - "untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]", - ); - cx.error_spanned_by( - tag_tokens, - "untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]", - ); - cx.error_spanned_by( - content_tokens, - "untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]", - ); + (Some((untagged_tokens, ())), Some((tag_tokens, _)), Some((content_tokens, _))) => { + let msg = "untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]"; + cx.error_spanned_by(untagged_tokens, msg); + cx.error_spanned_by(tag_tokens, msg); + cx.error_spanned_by(content_tokens, msg); TagType::External } } @@ -797,45 +756,33 @@ fn decide_identifier( variant_identifier.0.get_with_tokens(), ) { (_, None, None) => Identifier::No, - (_, Some((field_identifier_tokens, _)), Some((variant_identifier_tokens, _))) => { - cx.error_spanned_by( - field_identifier_tokens, - "#[serde(field_identifier)] and #[serde(variant_identifier)] cannot both be set", - ); - cx.error_spanned_by( - variant_identifier_tokens, - "#[serde(field_identifier)] and #[serde(variant_identifier)] cannot both be set", - ); + (_, Some((field_identifier_tokens, ())), Some((variant_identifier_tokens, ()))) => { + let msg = + "#[serde(field_identifier)] and #[serde(variant_identifier)] cannot both be set"; + cx.error_spanned_by(field_identifier_tokens, msg); + cx.error_spanned_by(variant_identifier_tokens, msg); Identifier::No } (syn::Data::Enum(_), Some(_), None) => Identifier::Field, (syn::Data::Enum(_), None, Some(_)) => Identifier::Variant, (syn::Data::Struct(syn::DataStruct { struct_token, .. }), Some(_), None) => { - cx.error_spanned_by( - struct_token, - "#[serde(field_identifier)] can only be used on an enum", - ); + let msg = "#[serde(field_identifier)] can only be used on an enum"; + cx.error_spanned_by(struct_token, msg); Identifier::No } (syn::Data::Union(syn::DataUnion { union_token, .. }), Some(_), None) => { - cx.error_spanned_by( - union_token, - "#[serde(field_identifier)] can only be used on an enum", - ); + let msg = "#[serde(field_identifier)] can only be used on an enum"; + cx.error_spanned_by(union_token, msg); Identifier::No } (syn::Data::Struct(syn::DataStruct { struct_token, .. }), None, Some(_)) => { - cx.error_spanned_by( - struct_token, - "#[serde(variant_identifier)] can only be used on an enum", - ); + let msg = "#[serde(variant_identifier)] can only be used on an enum"; + cx.error_spanned_by(struct_token, msg); Identifier::No } (syn::Data::Union(syn::DataUnion { union_token, .. }), None, Some(_)) => { - cx.error_spanned_by( - union_token, - "#[serde(variant_identifier)] can only be used on an enum", - ); + let msg = "#[serde(variant_identifier)] can only be used on an enum"; + cx.error_spanned_by(union_token, msg); Identifier::No } } @@ -852,7 +799,13 @@ pub struct Variant { other: bool, serialize_with: Option, deserialize_with: Option, - borrow: Option, + borrow: Option, + untagged: bool, +} + +struct BorrowAttribute { + path: syn::Path, + lifetimes: Option>, } impl Variant { @@ -870,169 +823,135 @@ impl Variant { let mut serialize_with = Attr::none(cx, SERIALIZE_WITH); let mut deserialize_with = Attr::none(cx, DESERIALIZE_WITH); let mut borrow = Attr::none(cx, BORROW); + let mut untagged = BoolAttr::none(cx, UNTAGGED); - for meta_item in variant - .attrs - .iter() - .flat_map(|attr| get_serde_meta_items(cx, attr)) - .flatten() - { - match &meta_item { - // Parse `#[serde(rename = "foo")]` - Meta(NameValue(m)) if m.path == RENAME => { - if let Ok(s) = get_lit_str(cx, RENAME, &m.lit) { - ser_name.set(&m.path, s.value()); - de_name.set_if_none(s.value()); - de_aliases.insert(&m.path, s.value()); - } + for attr in &variant.attrs { + if attr.path() != SERDE { + continue; + } + + if let syn::Meta::List(meta) = &attr.meta { + if meta.tokens.is_empty() { + continue; } + } - // Parse `#[serde(rename(serialize = "foo", deserialize = "bar"))]` - Meta(List(m)) if m.path == RENAME => { - if let Ok((ser, de)) = get_multiple_renames(cx, &m.nested) { - ser_name.set_opt(&m.path, ser.map(syn::LitStr::value)); - for de_value in de { - de_name.set_if_none(de_value.value()); - de_aliases.insert(&m.path, de_value.value()); + if let Err(err) = attr.parse_nested_meta(|meta| { + if meta.path == RENAME { + // #[serde(rename = "foo")] + // #[serde(rename(serialize = "foo", deserialize = "bar"))] + let (ser, de) = get_multiple_renames(cx, &meta)?; + ser_name.set_opt(&meta.path, ser.as_ref().map(syn::LitStr::value)); + for de_value in de { + de_name.set_if_none(de_value.value()); + de_aliases.insert(&meta.path, de_value.value()); + } + } else if meta.path == ALIAS { + // #[serde(alias = "foo")] + if let Some(s) = get_lit_str(cx, ALIAS, &meta)? { + de_aliases.insert(&meta.path, s.value()); + } + } else if meta.path == RENAME_ALL { + // #[serde(rename_all = "foo")] + // #[serde(rename_all(serialize = "foo", deserialize = "bar"))] + let one_name = meta.input.peek(Token![=]); + let (ser, de) = get_renames(cx, RENAME_ALL, &meta)?; + if let Some(ser) = ser { + match RenameRule::from_str(&ser.value()) { + Ok(rename_rule) => rename_all_ser_rule.set(&meta.path, rename_rule), + Err(err) => cx.error_spanned_by(ser, err), } } - } - - // Parse `#[serde(alias = "foo")]` - Meta(NameValue(m)) if m.path == ALIAS => { - if let Ok(s) = get_lit_str(cx, ALIAS, &m.lit) { - de_aliases.insert(&m.path, s.value()); - } - } - - // Parse `#[serde(rename_all = "foo")]` - Meta(NameValue(m)) if m.path == RENAME_ALL => { - if let Ok(s) = get_lit_str(cx, RENAME_ALL, &m.lit) { - match RenameRule::from_str(&s.value()) { - Ok(rename_rule) => { - rename_all_ser_rule.set(&m.path, rename_rule); - rename_all_de_rule.set(&m.path, rename_rule); - } - Err(err) => cx.error_spanned_by(s, err), - } - } - } - - // Parse `#[serde(rename_all(serialize = "foo", deserialize = "bar"))]` - Meta(List(m)) if m.path == RENAME_ALL => { - if let Ok((ser, de)) = get_renames(cx, &m.nested) { - if let Some(ser) = ser { - match RenameRule::from_str(&ser.value()) { - Ok(rename_rule) => rename_all_ser_rule.set(&m.path, rename_rule), - Err(err) => cx.error_spanned_by(ser, err), - } - } - if let Some(de) = de { - match RenameRule::from_str(&de.value()) { - Ok(rename_rule) => rename_all_de_rule.set(&m.path, rename_rule), - Err(err) => cx.error_spanned_by(de, err), + if let Some(de) = de { + match RenameRule::from_str(&de.value()) { + Ok(rename_rule) => rename_all_de_rule.set(&meta.path, rename_rule), + Err(err) => { + if !one_name { + cx.error_spanned_by(de, err); + } } } } - } - - // Parse `#[serde(skip)]` - Meta(Path(word)) if word == SKIP => { - skip_serializing.set_true(word); - skip_deserializing.set_true(word); - } - - // Parse `#[serde(skip_deserializing)]` - Meta(Path(word)) if word == SKIP_DESERIALIZING => { - skip_deserializing.set_true(word); - } - - // Parse `#[serde(skip_serializing)]` - Meta(Path(word)) if word == SKIP_SERIALIZING => { - skip_serializing.set_true(word); - } - - // Parse `#[serde(other)]` - Meta(Path(word)) if word == OTHER => { - other.set_true(word); - } - - // Parse `#[serde(bound = "T: SomeBound")]` - Meta(NameValue(m)) if m.path == BOUND => { - if let Ok(where_predicates) = parse_lit_into_where(cx, BOUND, BOUND, &m.lit) { - ser_bound.set(&m.path, where_predicates.clone()); - de_bound.set(&m.path, where_predicates); - } - } - - // Parse `#[serde(bound(serialize = "...", deserialize = "..."))]` - Meta(List(m)) if m.path == BOUND => { - if let Ok((ser, de)) = get_where_predicates(cx, &m.nested) { - ser_bound.set_opt(&m.path, ser); - de_bound.set_opt(&m.path, de); - } - } - - // Parse `#[serde(with = "...")]` - Meta(NameValue(m)) if m.path == WITH => { - if let Ok(path) = parse_lit_into_expr_path(cx, WITH, &m.lit) { + } else if meta.path == SKIP { + // #[serde(skip)] + skip_serializing.set_true(&meta.path); + skip_deserializing.set_true(&meta.path); + } else if meta.path == SKIP_DESERIALIZING { + // #[serde(skip_deserializing)] + skip_deserializing.set_true(&meta.path); + } else if meta.path == SKIP_SERIALIZING { + // #[serde(skip_serializing)] + skip_serializing.set_true(&meta.path); + } else if meta.path == OTHER { + // #[serde(other)] + other.set_true(&meta.path); + } else if meta.path == BOUND { + // #[serde(bound = "T: SomeBound")] + // #[serde(bound(serialize = "...", deserialize = "..."))] + let (ser, de) = get_where_predicates(cx, &meta)?; + ser_bound.set_opt(&meta.path, ser); + de_bound.set_opt(&meta.path, de); + } else if meta.path == WITH { + // #[serde(with = "...")] + if let Some(path) = parse_lit_into_expr_path(cx, WITH, &meta)? { let mut ser_path = path.clone(); ser_path .path .segments .push(Ident::new("serialize", Span::call_site()).into()); - serialize_with.set(&m.path, ser_path); + serialize_with.set(&meta.path, ser_path); let mut de_path = path; de_path .path .segments .push(Ident::new("deserialize", Span::call_site()).into()); - deserialize_with.set(&m.path, de_path); + deserialize_with.set(&meta.path, de_path); } - } - - // Parse `#[serde(serialize_with = "...")]` - Meta(NameValue(m)) if m.path == SERIALIZE_WITH => { - if let Ok(path) = parse_lit_into_expr_path(cx, SERIALIZE_WITH, &m.lit) { - serialize_with.set(&m.path, path); + } else if meta.path == SERIALIZE_WITH { + // #[serde(serialize_with = "...")] + if let Some(path) = parse_lit_into_expr_path(cx, SERIALIZE_WITH, &meta)? { + serialize_with.set(&meta.path, path); } - } - - // Parse `#[serde(deserialize_with = "...")]` - Meta(NameValue(m)) if m.path == DESERIALIZE_WITH => { - if let Ok(path) = parse_lit_into_expr_path(cx, DESERIALIZE_WITH, &m.lit) { - deserialize_with.set(&m.path, path); + } else if meta.path == DESERIALIZE_WITH { + // #[serde(deserialize_with = "...")] + if let Some(path) = parse_lit_into_expr_path(cx, DESERIALIZE_WITH, &meta)? { + deserialize_with.set(&meta.path, path); } - } - - // Defer `#[serde(borrow)]` and `#[serde(borrow = "'a + 'b")]` - Meta(m) if m.path() == BORROW => match &variant.fields { - syn::Fields::Unnamed(fields) if fields.unnamed.len() == 1 => { - borrow.set(m.path(), m.clone()); + } else if meta.path == BORROW { + let borrow_attribute = if meta.input.peek(Token![=]) { + // #[serde(borrow = "'a + 'b")] + let lifetimes = parse_lit_into_lifetimes(cx, &meta)?; + BorrowAttribute { + path: meta.path.clone(), + lifetimes: Some(lifetimes), + } + } else { + // #[serde(borrow)] + BorrowAttribute { + path: meta.path.clone(), + lifetimes: None, + } + }; + match &variant.fields { + syn::Fields::Unnamed(fields) if fields.unnamed.len() == 1 => { + borrow.set(&meta.path, borrow_attribute); + } + _ => { + let msg = "#[serde(borrow)] may only be used on newtype variants"; + cx.error_spanned_by(variant, msg); + } } - _ => { - cx.error_spanned_by( - variant, - "#[serde(borrow)] may only be used on newtype variants", - ); - } - }, - - Meta(meta_item) => { - let path = meta_item - .path() - .into_token_stream() - .to_string() - .replace(' ', ""); - cx.error_spanned_by( - meta_item.path(), - format!("unknown serde variant attribute `{}`", path), + } else if meta.path == UNTAGGED { + untagged.set_true(&meta.path); + } else { + let path = meta.path.to_token_stream().to_string().replace(' ', ""); + return Err( + meta.error(format_args!("unknown serde variant attribute `{}`", path)) ); } - - Lit(lit) => { - cx.error_spanned_by(lit, "unexpected literal in serde variant attribute"); - } + Ok(()) + }) { + cx.syn_error(err); } } @@ -1050,6 +969,7 @@ impl Variant { serialize_with: serialize_with.get(), deserialize_with: deserialize_with.get(), borrow: borrow.get(), + untagged: untagged.get(), } } @@ -1057,21 +977,24 @@ impl Variant { &self.name } - pub fn aliases(&self) -> Vec { + pub fn aliases(&self) -> &BTreeSet { self.name.deserialize_aliases() } - pub fn rename_by_rules(&mut self, rules: &RenameAllRules) { + pub fn rename_by_rules(&mut self, rules: RenameAllRules) { if !self.name.serialize_renamed { self.name.serialize = rules.serialize.apply_to_variant(&self.name.serialize); } if !self.name.deserialize_renamed { self.name.deserialize = rules.deserialize.apply_to_variant(&self.name.deserialize); } + self.name + .deserialize_aliases + .insert(self.name.deserialize.clone()); } - pub fn rename_all_rules(&self) -> &RenameAllRules { - &self.rename_all_rules + pub fn rename_all_rules(&self) -> RenameAllRules { + self.rename_all_rules } pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> { @@ -1101,6 +1024,10 @@ impl Variant { pub fn deserialize_with(&self) -> Option<&syn::ExprPath> { self.deserialize_with.as_ref() } + + pub fn untagged(&self) -> bool { + self.untagged + } } /// Represents field attribute information @@ -1168,182 +1095,145 @@ impl Field { None => index.to_string(), }; - let variant_borrow = attrs - .and_then(|variant| variant.borrow.as_ref()) - .map(|borrow| Meta(borrow.clone())); - - for meta_item in field - .attrs - .iter() - .flat_map(|attr| get_serde_meta_items(cx, attr)) - .flatten() - .chain(variant_borrow) - { - match &meta_item { - // Parse `#[serde(rename = "foo")]` - Meta(NameValue(m)) if m.path == RENAME => { - if let Ok(s) = get_lit_str(cx, RENAME, &m.lit) { - ser_name.set(&m.path, s.value()); - de_name.set_if_none(s.value()); - de_aliases.insert(&m.path, s.value()); - } - } - - // Parse `#[serde(rename(serialize = "foo", deserialize = "bar"))]` - Meta(List(m)) if m.path == RENAME => { - if let Ok((ser, de)) = get_multiple_renames(cx, &m.nested) { - ser_name.set_opt(&m.path, ser.map(syn::LitStr::value)); - for de_value in de { - de_name.set_if_none(de_value.value()); - de_aliases.insert(&m.path, de_value.value()); + if let Some(borrow_attribute) = attrs.and_then(|variant| variant.borrow.as_ref()) { + if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, field) { + if let Some(lifetimes) = &borrow_attribute.lifetimes { + for lifetime in lifetimes { + if !borrowable.contains(lifetime) { + let msg = + format!("field `{}` does not have lifetime {}", ident, lifetime); + cx.error_spanned_by(field, msg); } } + borrowed_lifetimes.set(&borrow_attribute.path, lifetimes.clone()); + } else { + borrowed_lifetimes.set(&borrow_attribute.path, borrowable); } + } + } - // Parse `#[serde(alias = "foo")]` - Meta(NameValue(m)) if m.path == ALIAS => { - if let Ok(s) = get_lit_str(cx, ALIAS, &m.lit) { - de_aliases.insert(&m.path, s.value()); + for attr in &field.attrs { + if attr.path() != SERDE { + continue; + } + + if let syn::Meta::List(meta) = &attr.meta { + if meta.tokens.is_empty() { + continue; + } + } + + if let Err(err) = attr.parse_nested_meta(|meta| { + if meta.path == RENAME { + // #[serde(rename = "foo")] + // #[serde(rename(serialize = "foo", deserialize = "bar"))] + let (ser, de) = get_multiple_renames(cx, &meta)?; + ser_name.set_opt(&meta.path, ser.as_ref().map(syn::LitStr::value)); + for de_value in de { + de_name.set_if_none(de_value.value()); + de_aliases.insert(&meta.path, de_value.value()); } - } - - // Parse `#[serde(default)]` - Meta(Path(word)) if word == DEFAULT => { - default.set(word, Default::Default); - } - - // Parse `#[serde(default = "...")]` - Meta(NameValue(m)) if m.path == DEFAULT => { - if let Ok(path) = parse_lit_into_expr_path(cx, DEFAULT, &m.lit) { - default.set(&m.path, Default::Path(path)); + } else if meta.path == ALIAS { + // #[serde(alias = "foo")] + if let Some(s) = get_lit_str(cx, ALIAS, &meta)? { + de_aliases.insert(&meta.path, s.value()); } - } - - // Parse `#[serde(skip_serializing)]` - Meta(Path(word)) if word == SKIP_SERIALIZING => { - skip_serializing.set_true(word); - } - - // Parse `#[serde(skip_deserializing)]` - Meta(Path(word)) if word == SKIP_DESERIALIZING => { - skip_deserializing.set_true(word); - } - - // Parse `#[serde(skip)]` - Meta(Path(word)) if word == SKIP => { - skip_serializing.set_true(word); - skip_deserializing.set_true(word); - } - - // Parse `#[serde(skip_serializing_if = "...")]` - Meta(NameValue(m)) if m.path == SKIP_SERIALIZING_IF => { - if let Ok(path) = parse_lit_into_expr_path(cx, SKIP_SERIALIZING_IF, &m.lit) { - skip_serializing_if.set(&m.path, path); + } else if meta.path == DEFAULT { + if meta.input.peek(Token![=]) { + // #[serde(default = "...")] + if let Some(path) = parse_lit_into_expr_path(cx, DEFAULT, &meta)? { + default.set(&meta.path, Default::Path(path)); + } + } else { + // #[serde(default)] + default.set(&meta.path, Default::Default); } - } - - // Parse `#[serde(serialize_with = "...")]` - Meta(NameValue(m)) if m.path == SERIALIZE_WITH => { - if let Ok(path) = parse_lit_into_expr_path(cx, SERIALIZE_WITH, &m.lit) { - serialize_with.set(&m.path, path); + } else if meta.path == SKIP_SERIALIZING { + // #[serde(skip_serializing)] + skip_serializing.set_true(&meta.path); + } else if meta.path == SKIP_DESERIALIZING { + // #[serde(skip_deserializing)] + skip_deserializing.set_true(&meta.path); + } else if meta.path == SKIP { + // #[serde(skip)] + skip_serializing.set_true(&meta.path); + skip_deserializing.set_true(&meta.path); + } else if meta.path == SKIP_SERIALIZING_IF { + // #[serde(skip_serializing_if = "...")] + if let Some(path) = parse_lit_into_expr_path(cx, SKIP_SERIALIZING_IF, &meta)? { + skip_serializing_if.set(&meta.path, path); } - } - - // Parse `#[serde(deserialize_with = "...")]` - Meta(NameValue(m)) if m.path == DESERIALIZE_WITH => { - if let Ok(path) = parse_lit_into_expr_path(cx, DESERIALIZE_WITH, &m.lit) { - deserialize_with.set(&m.path, path); + } else if meta.path == SERIALIZE_WITH { + // #[serde(serialize_with = "...")] + if let Some(path) = parse_lit_into_expr_path(cx, SERIALIZE_WITH, &meta)? { + serialize_with.set(&meta.path, path); } - } - - // Parse `#[serde(with = "...")]` - Meta(NameValue(m)) if m.path == WITH => { - if let Ok(path) = parse_lit_into_expr_path(cx, WITH, &m.lit) { + } else if meta.path == DESERIALIZE_WITH { + // #[serde(deserialize_with = "...")] + if let Some(path) = parse_lit_into_expr_path(cx, DESERIALIZE_WITH, &meta)? { + deserialize_with.set(&meta.path, path); + } + } else if meta.path == WITH { + // #[serde(with = "...")] + if let Some(path) = parse_lit_into_expr_path(cx, WITH, &meta)? { let mut ser_path = path.clone(); ser_path .path .segments .push(Ident::new("serialize", Span::call_site()).into()); - serialize_with.set(&m.path, ser_path); + serialize_with.set(&meta.path, ser_path); let mut de_path = path; de_path .path .segments .push(Ident::new("deserialize", Span::call_site()).into()); - deserialize_with.set(&m.path, de_path); + deserialize_with.set(&meta.path, de_path); } - } - - // Parse `#[serde(bound = "T: SomeBound")]` - Meta(NameValue(m)) if m.path == BOUND => { - if let Ok(where_predicates) = parse_lit_into_where(cx, BOUND, BOUND, &m.lit) { - ser_bound.set(&m.path, where_predicates.clone()); - de_bound.set(&m.path, where_predicates); - } - } - - // Parse `#[serde(bound(serialize = "...", deserialize = "..."))]` - Meta(List(m)) if m.path == BOUND => { - if let Ok((ser, de)) = get_where_predicates(cx, &m.nested) { - ser_bound.set_opt(&m.path, ser); - de_bound.set_opt(&m.path, de); - } - } - - // Parse `#[serde(borrow)]` - Meta(Path(word)) if word == BORROW => { - if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, field) { - borrowed_lifetimes.set(word, borrowable); - } - } - - // Parse `#[serde(borrow = "'a + 'b")]` - Meta(NameValue(m)) if m.path == BORROW => { - if let Ok(lifetimes) = parse_lit_into_lifetimes(cx, BORROW, &m.lit) { + } else if meta.path == BOUND { + // #[serde(bound = "T: SomeBound")] + // #[serde(bound(serialize = "...", deserialize = "..."))] + let (ser, de) = get_where_predicates(cx, &meta)?; + ser_bound.set_opt(&meta.path, ser); + de_bound.set_opt(&meta.path, de); + } else if meta.path == BORROW { + if meta.input.peek(Token![=]) { + // #[serde(borrow = "'a + 'b")] + let lifetimes = parse_lit_into_lifetimes(cx, &meta)?; if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, field) { for lifetime in &lifetimes { if !borrowable.contains(lifetime) { - cx.error_spanned_by( - field, - format!( - "field `{}` does not have lifetime {}", - ident, lifetime - ), + let msg = format!( + "field `{}` does not have lifetime {}", + ident, lifetime, ); + cx.error_spanned_by(field, msg); } } - borrowed_lifetimes.set(&m.path, lifetimes); + borrowed_lifetimes.set(&meta.path, lifetimes); + } + } else { + // #[serde(borrow)] + if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, field) { + borrowed_lifetimes.set(&meta.path, borrowable); } } - } - - // Parse `#[serde(getter = "...")]` - Meta(NameValue(m)) if m.path == GETTER => { - if let Ok(path) = parse_lit_into_expr_path(cx, GETTER, &m.lit) { - getter.set(&m.path, path); + } else if meta.path == GETTER { + // #[serde(getter = "...")] + if let Some(path) = parse_lit_into_expr_path(cx, GETTER, &meta)? { + getter.set(&meta.path, path); } - } - - // Parse `#[serde(flatten)]` - Meta(Path(word)) if word == FLATTEN => { - flatten.set_true(word); - } - - Meta(meta_item) => { - let path = meta_item - .path() - .into_token_stream() - .to_string() - .replace(' ', ""); - cx.error_spanned_by( - meta_item.path(), - format!("unknown serde field attribute `{}`", path), + } else if meta.path == FLATTEN { + // #[serde(flatten)] + flatten.set_true(&meta.path); + } else { + let path = meta.path.to_token_stream().to_string().replace(' ', ""); + return Err( + meta.error(format_args!("unknown serde field attribute `{}`", path)) ); } - - Lit(lit) => { - cx.error_spanned_by(lit, "unexpected literal in serde field attribute"); - } + Ok(()) + }) { + cx.syn_error(err); } } @@ -1429,17 +1319,20 @@ impl Field { &self.name } - pub fn aliases(&self) -> Vec { + pub fn aliases(&self) -> &BTreeSet { self.name.deserialize_aliases() } - pub fn rename_by_rules(&mut self, rules: &RenameAllRules) { + pub fn rename_by_rules(&mut self, rules: RenameAllRules) { if !self.name.serialize_renamed { self.name.serialize = rules.serialize.apply_to_field(&self.name.serialize); } if !self.name.deserialize_renamed { self.name.deserialize = rules.deserialize.apply_to_field(&self.name.deserialize); } + self.name + .deserialize_aliases + .insert(self.name.deserialize.clone()); } pub fn skip_serializing(&self) -> bool { @@ -1497,130 +1390,161 @@ impl Field { type SerAndDe = (Option, Option); -fn get_ser_and_de<'a, 'b, T, F>( - cx: &'b Ctxt, +fn get_ser_and_de<'c, T, F, R>( + cx: &'c Ctxt, attr_name: Symbol, - metas: &'a Punctuated, + meta: &ParseNestedMeta, f: F, -) -> Result<(VecAttr<'b, T>, VecAttr<'b, T>), ()> +) -> syn::Result<(VecAttr<'c, T>, VecAttr<'c, T>)> where - T: 'a, - F: Fn(&Ctxt, Symbol, Symbol, &'a syn::Lit) -> Result, + T: Clone, + F: Fn(&Ctxt, Symbol, Symbol, &ParseNestedMeta) -> syn::Result, + R: Into>, { let mut ser_meta = VecAttr::none(cx, attr_name); let mut de_meta = VecAttr::none(cx, attr_name); - for meta in metas { - match meta { - Meta(NameValue(meta)) if meta.path == SERIALIZE => { - if let Ok(v) = f(cx, attr_name, SERIALIZE, &meta.lit) { + let lookahead = meta.input.lookahead1(); + if lookahead.peek(Token![=]) { + if let Some(both) = f(cx, attr_name, attr_name, meta)?.into() { + ser_meta.insert(&meta.path, both.clone()); + de_meta.insert(&meta.path, both); + } + } else if lookahead.peek(token::Paren) { + meta.parse_nested_meta(|meta| { + if meta.path == SERIALIZE { + if let Some(v) = f(cx, attr_name, SERIALIZE, &meta)?.into() { ser_meta.insert(&meta.path, v); } - } - - Meta(NameValue(meta)) if meta.path == DESERIALIZE => { - if let Ok(v) = f(cx, attr_name, DESERIALIZE, &meta.lit) { + } else if meta.path == DESERIALIZE { + if let Some(v) = f(cx, attr_name, DESERIALIZE, &meta)?.into() { de_meta.insert(&meta.path, v); } + } else { + return Err(meta.error(format_args!( + "malformed {0} attribute, expected `{0}(serialize = ..., deserialize = ...)`", + attr_name, + ))); } - - _ => { - cx.error_spanned_by( - meta, - format!( - "malformed {0} attribute, expected `{0}(serialize = ..., deserialize = ...)`", - attr_name - ), - ); - return Err(()); - } - } + Ok(()) + })?; + } else { + return Err(lookahead.error()); } Ok((ser_meta, de_meta)) } -fn get_renames<'a>( +fn get_renames( cx: &Ctxt, - items: &'a Punctuated, -) -> Result, ()> { - let (ser, de) = get_ser_and_de(cx, RENAME, items, get_lit_str2)?; - Ok((ser.at_most_one()?, de.at_most_one()?)) + attr_name: Symbol, + meta: &ParseNestedMeta, +) -> syn::Result> { + let (ser, de) = get_ser_and_de(cx, attr_name, meta, get_lit_str2)?; + Ok((ser.at_most_one(), de.at_most_one())) } -fn get_multiple_renames<'a>( +fn get_multiple_renames( cx: &Ctxt, - items: &'a Punctuated, -) -> Result<(Option<&'a syn::LitStr>, Vec<&'a syn::LitStr>), ()> { - let (ser, de) = get_ser_and_de(cx, RENAME, items, get_lit_str2)?; - Ok((ser.at_most_one()?, de.get())) + meta: &ParseNestedMeta, +) -> syn::Result<(Option, Vec)> { + let (ser, de) = get_ser_and_de(cx, RENAME, meta, get_lit_str2)?; + Ok((ser.at_most_one(), de.get())) } fn get_where_predicates( cx: &Ctxt, - items: &Punctuated, -) -> Result>, ()> { - let (ser, de) = get_ser_and_de(cx, BOUND, items, parse_lit_into_where)?; - Ok((ser.at_most_one()?, de.at_most_one()?)) + meta: &ParseNestedMeta, +) -> syn::Result>> { + let (ser, de) = get_ser_and_de(cx, BOUND, meta, parse_lit_into_where)?; + Ok((ser.at_most_one(), de.at_most_one())) } -pub fn get_serde_meta_items(cx: &Ctxt, attr: &syn::Attribute) -> Result, ()> { - if attr.path != SERDE { - return Ok(Vec::new()); - } - - match attr.parse_meta() { - Ok(List(meta)) => Ok(meta.nested.into_iter().collect()), - Ok(other) => { - cx.error_spanned_by(other, "expected #[serde(...)]"); - Err(()) - } - Err(err) => { - cx.syn_error(err); - Err(()) - } - } +fn get_lit_str( + cx: &Ctxt, + attr_name: Symbol, + meta: &ParseNestedMeta, +) -> syn::Result> { + get_lit_str2(cx, attr_name, attr_name, meta) } -fn get_lit_str<'a>(cx: &Ctxt, attr_name: Symbol, lit: &'a syn::Lit) -> Result<&'a syn::LitStr, ()> { - get_lit_str2(cx, attr_name, attr_name, lit) -} - -fn get_lit_str2<'a>( +fn get_lit_str2( cx: &Ctxt, attr_name: Symbol, meta_item_name: Symbol, - lit: &'a syn::Lit, -) -> Result<&'a syn::LitStr, ()> { - if let syn::Lit::Str(lit) = lit { - Ok(lit) + meta: &ParseNestedMeta, +) -> syn::Result> { + let expr: syn::Expr = meta.value()?.parse()?; + let mut value = &expr; + while let syn::Expr::Group(e) = value { + value = &e.expr; + } + if let syn::Expr::Lit(syn::ExprLit { + lit: syn::Lit::Str(lit), + .. + }) = value + { + let suffix = lit.suffix(); + if !suffix.is_empty() { + cx.error_spanned_by( + lit, + format!("unexpected suffix `{}` on string literal", suffix), + ); + } + Ok(Some(lit.clone())) } else { cx.error_spanned_by( - lit, + expr, format!( "expected serde {} attribute to be a string: `{} = \"...\"`", attr_name, meta_item_name ), ); - Err(()) + Ok(None) } } -fn parse_lit_into_path(cx: &Ctxt, attr_name: Symbol, lit: &syn::Lit) -> Result { - let string = get_lit_str(cx, attr_name, lit)?; - parse_lit_str(string).map_err(|_| { - cx.error_spanned_by(lit, format!("failed to parse path: {:?}", string.value())); +fn parse_lit_into_path( + cx: &Ctxt, + attr_name: Symbol, + meta: &ParseNestedMeta, +) -> syn::Result> { + let string = match get_lit_str(cx, attr_name, meta)? { + Some(string) => string, + None => return Ok(None), + }; + + Ok(match string.parse() { + Ok(path) => Some(path), + Err(_) => { + cx.error_spanned_by( + &string, + format!("failed to parse path: {:?}", string.value()), + ); + None + } }) } fn parse_lit_into_expr_path( cx: &Ctxt, attr_name: Symbol, - lit: &syn::Lit, -) -> Result { - let string = get_lit_str(cx, attr_name, lit)?; - parse_lit_str(string).map_err(|_| { - cx.error_spanned_by(lit, format!("failed to parse path: {:?}", string.value())); + meta: &ParseNestedMeta, +) -> syn::Result> { + let string = match get_lit_str(cx, attr_name, meta)? { + Some(string) => string, + None => return Ok(None), + }; + + Ok(match string.parse() { + Ok(expr) => Some(expr), + Err(_) => { + cx.error_spanned_by( + &string, + format!("failed to parse path: {:?}", string.value()), + ); + None + } }) } @@ -1628,28 +1552,43 @@ fn parse_lit_into_where( cx: &Ctxt, attr_name: Symbol, meta_item_name: Symbol, - lit: &syn::Lit, -) -> Result, ()> { - let string = get_lit_str2(cx, attr_name, meta_item_name, lit)?; - if string.value().is_empty() { - return Ok(Vec::new()); - } + meta: &ParseNestedMeta, +) -> syn::Result> { + let string = match get_lit_str2(cx, attr_name, meta_item_name, meta)? { + Some(string) => string, + None => return Ok(Vec::new()), + }; - let where_string = syn::LitStr::new(&format!("where {}", string.value()), string.span()); - - parse_lit_str::(&where_string) - .map(|wh| wh.predicates.into_iter().collect()) - .map_err(|err| cx.error_spanned_by(lit, err)) + Ok( + match string.parse_with(Punctuated::::parse_terminated) { + Ok(predicates) => Vec::from_iter(predicates), + Err(err) => { + cx.error_spanned_by(string, err); + Vec::new() + } + }, + ) } -fn parse_lit_into_ty(cx: &Ctxt, attr_name: Symbol, lit: &syn::Lit) -> Result { - let string = get_lit_str(cx, attr_name, lit)?; +fn parse_lit_into_ty( + cx: &Ctxt, + attr_name: Symbol, + meta: &ParseNestedMeta, +) -> syn::Result> { + let string = match get_lit_str(cx, attr_name, meta)? { + Some(string) => string, + None => return Ok(None), + }; - parse_lit_str(string).map_err(|_| { - cx.error_spanned_by( - lit, - format!("failed to parse type: {} = {:?}", attr_name, string.value()), - ); + Ok(match string.parse() { + Ok(ty) => Some(ty), + Err(_) => { + cx.error_spanned_by( + &string, + format!("failed to parse type: {} = {:?}", attr_name, string.value()), + ); + None + } }) } @@ -1657,38 +1596,41 @@ fn parse_lit_into_ty(cx: &Ctxt, attr_name: Symbol, lit: &syn::Lit) -> Result Result, ()> { - let string = get_lit_str(cx, attr_name, lit)?; - if string.value().is_empty() { - cx.error_spanned_by(lit, "at least one lifetime must be borrowed"); - return Err(()); - } + meta: &ParseNestedMeta, +) -> syn::Result> { + let string = match get_lit_str(cx, BORROW, meta)? { + Some(string) => string, + None => return Ok(BTreeSet::new()), + }; - struct BorrowedLifetimes(Punctuated); - - impl Parse for BorrowedLifetimes { - fn parse(input: ParseStream) -> parse::Result { - Punctuated::parse_separated_nonempty(input).map(BorrowedLifetimes) - } - } - - if let Ok(BorrowedLifetimes(lifetimes)) = parse_lit_str(string) { + if let Ok(lifetimes) = string.parse_with(|input: ParseStream| { let mut set = BTreeSet::new(); - for lifetime in lifetimes { + while !input.is_empty() { + let lifetime: Lifetime = input.parse()?; if !set.insert(lifetime.clone()) { - cx.error_spanned_by(lit, format!("duplicate borrowed lifetime `{}`", lifetime)); + cx.error_spanned_by( + &string, + format!("duplicate borrowed lifetime `{}`", lifetime), + ); } + if input.is_empty() { + break; + } + input.parse::()?; } - return Ok(set); + Ok(set) + }) { + if lifetimes.is_empty() { + cx.error_spanned_by(string, "at least one lifetime must be borrowed"); + } + return Ok(lifetimes); } cx.error_spanned_by( - lit, + &string, format!("failed to parse borrowed lifetimes: {:?}", string.value()), ); - Err(()) + Ok(BTreeSet::new()) } fn is_implicitly_borrowed(ty: &syn::Type) -> bool { @@ -1842,10 +1784,8 @@ fn borrowable_lifetimes( let mut lifetimes = BTreeSet::new(); collect_lifetimes(&field.ty, &mut lifetimes); if lifetimes.is_empty() { - cx.error_spanned_by( - field, - format!("field `{}` has no lifetimes to borrow", name), - ); + let msg = format!("field `{}` has no lifetimes to borrow", name); + cx.error_spanned_by(field, msg); Err(()) } else { Ok(lifetimes) @@ -1854,6 +1794,7 @@ fn borrowable_lifetimes( fn collect_lifetimes(ty: &syn::Type, out: &mut BTreeSet) { match ty { + #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] syn::Type::Slice(ty) => { collect_lifetimes(&ty.elem, out); } @@ -1886,11 +1827,13 @@ fn collect_lifetimes(ty: &syn::Type, out: &mut BTreeSet) { syn::GenericArgument::Type(ty) => { collect_lifetimes(ty, out); } - syn::GenericArgument::Binding(binding) => { + syn::GenericArgument::AssocType(binding) => { collect_lifetimes(&binding.ty, out); } - syn::GenericArgument::Constraint(_) - | syn::GenericArgument::Const(_) => {} + syn::GenericArgument::Const(_) + | syn::GenericArgument::AssocConst(_) + | syn::GenericArgument::Constraint(_) + | _ => {} } } } @@ -1912,9 +1855,6 @@ fn collect_lifetimes(ty: &syn::Type, out: &mut BTreeSet) { | syn::Type::Infer(_) | syn::Type::Verbatim(_) => {} - #[cfg(test)] - syn::Type::__TestExhaustive(_) => unimplemented!(), - #[cfg(not(test))] _ => {} } } @@ -1939,16 +1879,3 @@ fn collect_lifetimes_from_tokens(tokens: TokenStream, out: &mut BTreeSet(s: &syn::LitStr) -> parse::Result -where - T: Parse, -{ - let tokens = spanned_tokens(s)?; - syn::parse2(tokens) -} - -fn spanned_tokens(s: &syn::LitStr) -> parse::Result { - let stream = syn::parse_str(&s.value())?; - Ok(respan(stream, s.span())) -} diff --git a/serde_derive/src/internals/case.rs b/serde_derive/src/internals/case.rs index 55450516..8c8c02e7 100644 --- a/serde_derive/src/internals/case.rs +++ b/serde_derive/src/internals/case.rs @@ -1,13 +1,8 @@ //! Code to convert the Rust-styled field/variant (e.g. `my_field`, `MyType`) to the //! case of the source (e.g. `my-field`, `MY_FIELD`). -// See https://users.rust-lang.org/t/psa-dealing-with-warning-unused-import-std-ascii-asciiext-in-today-s-nightly/13726 -#[allow(deprecated, unused_imports)] -use std::ascii::AsciiExt; - -use std::fmt::{self, Debug, Display}; - use self::RenameRule::*; +use std::fmt::{self, Debug, Display}; /// The different possible ways to change case of fields in a struct, or variants in an enum. #[derive(Copy, Clone, PartialEq)] @@ -59,8 +54,8 @@ impl RenameRule { } /// Apply a renaming rule to an enum variant, returning the version expected in the source. - pub fn apply_to_variant(&self, variant: &str) -> String { - match *self { + pub fn apply_to_variant(self, variant: &str) -> String { + match self { None | PascalCase => variant.to_owned(), LowerCase => variant.to_ascii_lowercase(), UpperCase => variant.to_ascii_uppercase(), @@ -84,8 +79,8 @@ impl RenameRule { } /// Apply a renaming rule to a struct field, returning the version expected in the source. - pub fn apply_to_field(&self, field: &str) -> String { - match *self { + pub fn apply_to_field(self, field: &str) -> String { + match self { None | LowerCase | SnakeCase => field.to_owned(), UpperCase => field.to_ascii_uppercase(), PascalCase => { @@ -112,6 +107,14 @@ impl RenameRule { ScreamingKebabCase => ScreamingSnakeCase.apply_to_field(field).replace('_', "-"), } } + + /// Returns the `RenameRule` if it is not `None`, `rule_b` otherwise. + pub fn or(self, rule_b: Self) -> Self { + match self { + None => rule_b, + _ => self, + } + } } pub struct ParseError<'a> { diff --git a/serde_derive/src/internals/check.rs b/serde_derive/src/internals/check.rs index 0e2484a7..52b0f379 100644 --- a/serde_derive/src/internals/check.rs +++ b/serde_derive/src/internals/check.rs @@ -1,11 +1,13 @@ -use internals::ast::{Container, Data, Field, Style}; -use internals::attr::{Identifier, TagType}; -use internals::{ungroup, Ctxt, Derive}; +use crate::internals::ast::{Container, Data, Field, Style}; +use crate::internals::attr::{Default, Identifier, TagType}; +use crate::internals::{ungroup, Ctxt, Derive}; use syn::{Member, Type}; -/// Cross-cutting checks that require looking at more than a single attrs -/// object. Simpler checks should happen when parsing and building the attrs. +// Cross-cutting checks that require looking at more than a single attrs object. +// Simpler checks should happen when parsing and building the attrs. pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) { + check_default_on_tuple(cx, cont); + check_remote_generic(cx, cont); check_getter(cx, cont); check_flatten(cx, cont); check_identifier(cx, cont); @@ -16,8 +18,63 @@ pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) { check_from_and_try_from(cx, cont); } -/// Getters are only allowed inside structs (not enums) with the `remote` -/// attribute. +// If some field of a tuple struct is marked #[serde(default)] then all fields +// after it must also be marked with that attribute, or the struct must have a +// container-level serde(default) attribute. A field's default value is only +// used for tuple fields if the sequence is exhausted at that point; that means +// all subsequent fields will fail to deserialize if they don't have their own +// default. +fn check_default_on_tuple(cx: &Ctxt, cont: &Container) { + if let Default::None = cont.attrs.default() { + if let Data::Struct(Style::Tuple, fields) = &cont.data { + let mut first_default_index = None; + for (i, field) in fields.iter().enumerate() { + // Skipped fields automatically get the #[serde(default)] + // attribute. We are interested only on non-skipped fields here. + if field.attrs.skip_deserializing() { + continue; + } + if let Default::None = field.attrs.default() { + if let Some(first) = first_default_index { + cx.error_spanned_by( + field.ty, + format!("field must have #[serde(default)] because previous field {} has #[serde(default)]", first), + ); + } + continue; + } + if first_default_index.is_none() { + first_default_index = Some(i); + } + } + } + } +} + +// Remote derive definition type must have either all of the generics of the +// remote type: +// +// #[serde(remote = "Generic")] +// struct Generic {…} +// +// or none of them, i.e. defining impls for one concrete instantiation of the +// remote type only: +// +// #[serde(remote = "Generic")] +// struct ConcreteDef {…} +// +fn check_remote_generic(cx: &Ctxt, cont: &Container) { + if let Some(remote) = cont.attrs.remote() { + let local_has_generic = !cont.generics.params.is_empty(); + let remote_has_generic = !remote.segments.last().unwrap().arguments.is_none(); + if local_has_generic && remote_has_generic { + cx.error_spanned_by(remote, "remove generic parameters from this path"); + } + } +} + +// Getters are only allowed inside structs (not enums) with the `remote` +// attribute. fn check_getter(cx: &Ctxt, cont: &Container) { match cont.data { Data::Enum(_) => { @@ -39,7 +96,7 @@ fn check_getter(cx: &Ctxt, cont: &Container) { } } -/// Flattening has some restrictions we can test. +// Flattening has some restrictions we can test. fn check_flatten(cx: &Ctxt, cont: &Container) { match &cont.data { Data::Enum(variants) => { @@ -78,18 +135,16 @@ fn check_flatten_field(cx: &Ctxt, style: Style, field: &Field) { } } -/// The `other` attribute must be used at most once and it must be the last -/// variant of an enum. -/// -/// Inside a `variant_identifier` all variants must be unit variants. Inside a -/// `field_identifier` all but possibly one variant must be unit variants. The -/// last variant may be a newtype variant which is an implicit "other" case. +// The `other` attribute must be used at most once and it must be the last +// variant of an enum. +// +// Inside a `variant_identifier` all variants must be unit variants. Inside a +// `field_identifier` all but possibly one variant must be unit variants. The +// last variant may be a newtype variant which is an implicit "other" case. fn check_identifier(cx: &Ctxt, cont: &Container) { let variants = match &cont.data { Data::Enum(variants) => variants, - Data::Struct(_, _) => { - return; - } + Data::Struct(_, _) => return, }; for (i, variant) in variants.iter().enumerate() { @@ -166,17 +221,15 @@ fn check_identifier(cx: &Ctxt, cont: &Container) { } } -/// Skip-(de)serializing attributes are not allowed on variants marked -/// (de)serialize_with. +// Skip-(de)serializing attributes are not allowed on variants marked +// (de)serialize_with. fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) { let variants = match &cont.data { Data::Enum(variants) => variants, - Data::Struct(_, _) => { - return; - } + Data::Struct(_, _) => return, }; - for variant in variants.iter() { + for variant in variants { if variant.attrs.serialize_with().is_some() { if variant.attrs.skip_serializing() { cx.error_spanned_by( @@ -241,10 +294,9 @@ fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) { } } -/// The tag of an internally-tagged struct variant must not be -/// the same as either one of its fields, as this would result in -/// duplicate keys in the serialized output and/or ambiguity in -/// the to-be-deserialized input. +// The tag of an internally-tagged struct variant must not be the same as either +// one of its fields, as this would result in duplicate keys in the serialized +// output and/or ambiguity in the to-be-deserialized input. fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) { let variants = match &cont.data { Data::Enum(variants) => variants, @@ -266,9 +318,14 @@ fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) { for variant in variants { match variant.style { Style::Struct => { + if variant.attrs.untagged() { + continue; + } for field in &variant.fields { - let check_ser = !field.attrs.skip_serializing(); - let check_de = !field.attrs.skip_deserializing(); + let check_ser = + !(field.attrs.skip_serializing() || variant.attrs.skip_serializing()); + let check_de = + !(field.attrs.skip_deserializing() || variant.attrs.skip_deserializing()); let name = field.attrs.name(); let ser_name = name.serialize_name(); @@ -290,8 +347,8 @@ fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) { } } -/// In the case of adjacently-tagged enums, the type and the -/// contents tag must differ, for the same reason. +// In the case of adjacently-tagged enums, the type and the contents tag must +// differ, for the same reason. fn check_adjacent_tag_conflict(cx: &Ctxt, cont: &Container) { let (type_tag, content_tag) = match cont.attrs.tag() { TagType::Adjacent { tag, content } => (tag, content), @@ -309,7 +366,7 @@ fn check_adjacent_tag_conflict(cx: &Ctxt, cont: &Container) { } } -/// Enums and unit structs cannot be transparent. +// Enums and unit structs cannot be transparent. fn check_transparent(cx: &Ctxt, cont: &mut Container, derive: Derive) { if !cont.attrs.transparent() { return; diff --git a/serde_derive/src/internals/ctxt.rs b/serde_derive/src/internals/ctxt.rs index d692c2a4..a47bfa41 100644 --- a/serde_derive/src/internals/ctxt.rs +++ b/serde_derive/src/internals/ctxt.rs @@ -2,7 +2,6 @@ use quote::ToTokens; use std::cell::RefCell; use std::fmt::Display; use std::thread; -use syn; /// A type to collect errors together and format them. /// @@ -44,12 +43,19 @@ impl Ctxt { } /// Consume this object, producing a formatted error string if there are errors. - pub fn check(self) -> Result<(), Vec> { - let errors = self.errors.borrow_mut().take().unwrap(); - match errors.len() { - 0 => Ok(()), - _ => Err(errors), + pub fn check(self) -> syn::Result<()> { + let mut errors = self.errors.borrow_mut().take().unwrap().into_iter(); + + let mut combined = match errors.next() { + Some(first) => first, + None => return Ok(()), + }; + + for rest in errors { + combined.combine(rest); } + + Err(combined) } } diff --git a/serde_derive/src/internals/mod.rs b/serde_derive/src/internals/mod.rs index 5e9f416c..f98ef08e 100644 --- a/serde_derive/src/internals/mod.rs +++ b/serde_derive/src/internals/mod.rs @@ -1,19 +1,18 @@ pub mod ast; pub mod attr; -mod ctxt; -pub use self::ctxt::Ctxt; - -mod receiver; -pub use self::receiver::replace_receiver; - mod case; mod check; +mod ctxt; +mod receiver; mod respan; mod symbol; use syn::Type; +pub use self::ctxt::Ctxt; +pub use self::receiver::replace_receiver; + #[derive(Copy, Clone)] pub enum Derive { Serialize, diff --git a/serde_derive/src/internals/receiver.rs b/serde_derive/src/internals/receiver.rs index 2b722d8f..fa2a77d2 100644 --- a/serde_derive/src/internals/receiver.rs +++ b/serde_derive/src/internals/receiver.rs @@ -1,11 +1,11 @@ -use internals::respan::respan; +use crate::internals::respan::respan; use proc_macro2::Span; use quote::ToTokens; use std::mem; use syn::punctuated::Punctuated; use syn::{ parse_quote, Data, DeriveInput, Expr, ExprPath, GenericArgument, GenericParam, Generics, Macro, - Path, PathArguments, QSelf, ReturnType, Type, TypeParamBound, TypePath, WherePredicate, + Path, PathArguments, QSelf, ReturnType, Token, Type, TypeParamBound, TypePath, WherePredicate, }; pub fn replace_receiver(input: &mut DeriveInput) { @@ -107,6 +107,7 @@ impl ReplaceReceiver<'_> { fn visit_type_mut_impl(&mut self, ty: &mut Type) { match ty { + #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] Type::Array(ty) => { self.visit_type_mut(&mut ty.elem); self.visit_expr_mut(&mut ty.len); @@ -147,9 +148,6 @@ impl ReplaceReceiver<'_> { Type::Infer(_) | Type::Never(_) | Type::Verbatim(_) => {} - #[cfg(test)] - Type::__TestExhaustive(_) => unimplemented!(), - #[cfg(not(test))] _ => {} } } @@ -180,11 +178,14 @@ impl ReplaceReceiver<'_> { PathArguments::AngleBracketed(arguments) => { for arg in &mut arguments.args { match arg { + #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] GenericArgument::Type(arg) => self.visit_type_mut(arg), - GenericArgument::Binding(arg) => self.visit_type_mut(&mut arg.ty), + GenericArgument::AssocType(arg) => self.visit_type_mut(&mut arg.ty), GenericArgument::Lifetime(_) - | GenericArgument::Constraint(_) - | GenericArgument::Const(_) => {} + | GenericArgument::Const(_) + | GenericArgument::AssocConst(_) + | GenericArgument::Constraint(_) => {} + _ => {} } } } @@ -206,8 +207,10 @@ impl ReplaceReceiver<'_> { fn visit_type_param_bound_mut(&mut self, bound: &mut TypeParamBound) { match bound { + #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] TypeParamBound::Trait(bound) => self.visit_path_mut(&mut bound.path), - TypeParamBound::Lifetime(_) => {} + TypeParamBound::Lifetime(_) | TypeParamBound::Verbatim(_) => {} + _ => {} } } @@ -225,13 +228,15 @@ impl ReplaceReceiver<'_> { if let Some(where_clause) = &mut generics.where_clause { for predicate in &mut where_clause.predicates { match predicate { + #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] WherePredicate::Type(predicate) => { self.visit_type_mut(&mut predicate.bounded_ty); for bound in &mut predicate.bounds { self.visit_type_param_bound_mut(bound); } } - WherePredicate::Lifetime(_) | WherePredicate::Eq(_) => {} + WherePredicate::Lifetime(_) => {} + _ => {} } } } diff --git a/serde_derive/src/internals/symbol.rs b/serde_derive/src/internals/symbol.rs index 1fedd275..572391a8 100644 --- a/serde_derive/src/internals/symbol.rs +++ b/serde_derive/src/internals/symbol.rs @@ -13,15 +13,19 @@ pub const DEFAULT: Symbol = Symbol("default"); pub const DENY_UNKNOWN_FIELDS: Symbol = Symbol("deny_unknown_fields"); pub const DESERIALIZE: Symbol = Symbol("deserialize"); pub const DESERIALIZE_WITH: Symbol = Symbol("deserialize_with"); +pub const EXPECTING: Symbol = Symbol("expecting"); pub const FIELD_IDENTIFIER: Symbol = Symbol("field_identifier"); pub const FLATTEN: Symbol = Symbol("flatten"); pub const FROM: Symbol = Symbol("from"); pub const GETTER: Symbol = Symbol("getter"); pub const INTO: Symbol = Symbol("into"); +pub const NON_EXHAUSTIVE: Symbol = Symbol("non_exhaustive"); pub const OTHER: Symbol = Symbol("other"); pub const REMOTE: Symbol = Symbol("remote"); pub const RENAME: Symbol = Symbol("rename"); pub const RENAME_ALL: Symbol = Symbol("rename_all"); +pub const RENAME_ALL_FIELDS: Symbol = Symbol("rename_all_fields"); +pub const REPR: Symbol = Symbol("repr"); pub const SERDE: Symbol = Symbol("serde"); pub const SERIALIZE: Symbol = Symbol("serialize"); pub const SERIALIZE_WITH: Symbol = Symbol("serialize_with"); @@ -35,7 +39,6 @@ pub const TRY_FROM: Symbol = Symbol("try_from"); pub const UNTAGGED: Symbol = Symbol("untagged"); pub const VARIANT_IDENTIFIER: Symbol = Symbol("variant_identifier"); pub const WITH: Symbol = Symbol("with"); -pub const EXPECTING: Symbol = Symbol("expecting"); impl PartialEq for Ident { fn eq(&self, word: &Symbol) -> bool { diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index 8079bb6c..b91f17b1 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -1,7 +1,7 @@ //! This crate provides Serde's two derive macros. //! -//! ```edition2018 -//! # use serde_derive::{Serialize, Deserialize}; +//! ```edition2021 +//! # use serde_derive::{Deserialize, Serialize}; //! # //! #[derive(Serialize, Deserialize)] //! # struct S; @@ -13,8 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.136")] -#![allow(unknown_lints, bare_trait_objects)] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.197")] // Ignored clippy lints #![allow( // clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054 @@ -22,6 +21,7 @@ clippy::cognitive_complexity, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/7575 clippy::collapsible_match, + clippy::derive_partial_eq_without_eq, clippy::enum_variant_names, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6797 clippy::manual_map, @@ -42,7 +42,7 @@ clippy::enum_glob_use, clippy::indexing_slicing, clippy::items_after_statements, - clippy::let_underscore_drop, + clippy::let_underscore_untyped, clippy::manual_assert, clippy::map_err_ignore, clippy::match_same_arms, @@ -50,7 +50,6 @@ clippy::match_wildcard_for_single_variants, clippy::module_name_repetitions, clippy::must_use_candidate, - clippy::option_if_let_else, clippy::similar_names, clippy::single_match_else, clippy::struct_excessive_bools, @@ -60,18 +59,18 @@ clippy::use_self, clippy::wildcard_imports )] +#![cfg_attr(all(test, exhaustive), feature(non_exhaustive_omitted_patterns_lint))] -#[macro_use] +extern crate proc_macro2; extern crate quote; -#[macro_use] extern crate syn; extern crate proc_macro; -extern crate proc_macro2; mod internals; use proc_macro::TokenStream; +use syn::parse_macro_input; use syn::DeriveInput; #[macro_use] @@ -83,13 +82,13 @@ mod de; mod dummy; mod pretend; mod ser; -mod try; +mod this; #[proc_macro_derive(Serialize, attributes(serde))] pub fn derive_serialize(input: TokenStream) -> TokenStream { let mut input = parse_macro_input!(input as DeriveInput); ser::expand_derive_serialize(&mut input) - .unwrap_or_else(to_compile_errors) + .unwrap_or_else(syn::Error::into_compile_error) .into() } @@ -97,11 +96,6 @@ pub fn derive_serialize(input: TokenStream) -> TokenStream { pub fn derive_deserialize(input: TokenStream) -> TokenStream { let mut input = parse_macro_input!(input as DeriveInput); de::expand_derive_deserialize(&mut input) - .unwrap_or_else(to_compile_errors) + .unwrap_or_else(syn::Error::into_compile_error) .into() } - -fn to_compile_errors(errors: Vec) -> proc_macro2::TokenStream { - let compile_errors = errors.iter().map(syn::Error::to_compile_error); - quote!(#(#compile_errors)*) -} diff --git a/serde_derive/src/pretend.rs b/serde_derive/src/pretend.rs index 3af6a66f..2c9e7793 100644 --- a/serde_derive/src/pretend.rs +++ b/serde_derive/src/pretend.rs @@ -1,7 +1,6 @@ +use crate::internals::ast::{Container, Data, Field, Style, Variant}; use proc_macro2::TokenStream; -use quote::format_ident; - -use internals::ast::{Container, Data, Field, Style, Variant}; +use quote::{format_ident, quote}; // Suppress dead_code warnings that would otherwise appear when using a remote // derive. Other than this pretend code, a struct annotated with remote derive @@ -65,14 +64,14 @@ pub fn pretend_used(cont: &Container, is_packed: bool) -> TokenStream { fn pretend_fields_used(cont: &Container, is_packed: bool) -> TokenStream { match &cont.data { Data::Enum(variants) => pretend_fields_used_enum(cont, variants), - Data::Struct(Style::Struct, fields) => { + Data::Struct(Style::Struct | Style::Tuple | Style::Newtype, fields) => { if is_packed { pretend_fields_used_struct_packed(cont, fields) } else { pretend_fields_used_struct(cont, fields) } } - Data::Struct(_, _) => quote!(), + Data::Struct(Style::Unit, _) => quote!(), } } @@ -97,29 +96,14 @@ fn pretend_fields_used_struct_packed(cont: &Container, fields: &[Field]) -> Toke let members = fields.iter().map(|field| &field.member).collect::>(); - #[cfg(ptr_addr_of)] - { - quote! { - match _serde::__private::None::<&#type_ident #ty_generics> { - _serde::__private::Some(__v @ #type_ident { #(#members: _),* }) => { - #( - let _ = _serde::__private::ptr::addr_of!(__v.#members); - )* - } - _ => {} - } - } - } - - #[cfg(not(ptr_addr_of))] - { - let placeholders = (0usize..).map(|i| format_ident!("__v{}", i)); - - quote! { - match _serde::__private::None::<#type_ident #ty_generics> { - _serde::__private::Some(#type_ident { #(#members: #placeholders),* }) => {} - _ => {} + quote! { + match _serde::__private::None::<&#type_ident #ty_generics> { + _serde::__private::Some(__v @ #type_ident { #(#members: _),* }) => { + #( + let _ = _serde::__private::ptr::addr_of!(__v.#members); + )* } + _ => {} } } } @@ -131,13 +115,13 @@ fn pretend_fields_used_enum(cont: &Container, variants: &[Variant]) -> TokenStre let patterns = variants .iter() .filter_map(|variant| match variant.style { - Style::Struct => { + Style::Struct | Style::Tuple | Style::Newtype => { let variant_ident = &variant.ident; let members = variant.fields.iter().map(|field| &field.member); let placeholders = (0usize..).map(|i| format_ident!("__v{}", i)); Some(quote!(#type_ident::#variant_ident { #(#members: #placeholders),* })) } - _ => None, + Style::Unit => None, }) .collect::>(); diff --git a/serde_derive/src/ser.rs b/serde_derive/src/ser.rs index 529a20d7..3be51ee5 100644 --- a/serde_derive/src/ser.rs +++ b/serde_derive/src/ser.rs @@ -1,17 +1,13 @@ +use crate::fragment::{Fragment, Match, Stmts}; +use crate::internals::ast::{Container, Data, Field, Style, Variant}; +use crate::internals::{attr, replace_receiver, Ctxt, Derive}; +use crate::{bound, dummy, pretend, this}; use proc_macro2::{Span, TokenStream}; +use quote::{quote, quote_spanned}; use syn::spanned::Spanned; -use syn::{self, Ident, Index, Member}; +use syn::{parse_quote, Ident, Index, Member}; -use bound; -use dummy; -use fragment::{Fragment, Match, Stmts}; -use internals::ast::{Container, Data, Field, Style, Variant}; -use internals::{attr, replace_receiver, Ctxt, Derive}; -use pretend; - -pub fn expand_derive_serialize( - input: &mut syn::DeriveInput, -) -> Result> { +pub fn expand_derive_serialize(input: &mut syn::DeriveInput) -> syn::Result { replace_receiver(input); let ctxt = Ctxt::new(); @@ -58,8 +54,6 @@ pub fn expand_derive_serialize( Ok(dummy::wrap_in_const( cont.attrs.custom_serde_path(), - "SERIALIZE", - ident, impl_block, )) } @@ -82,9 +76,13 @@ struct Parameters { self_var: Ident, /// Path to the type the impl is for. Either a single `Ident` for local - /// types or `some::remote::Ident` for remote types. Does not include - /// generic parameters. - this: syn::Path, + /// types (does not include generic parameters) or `some::remote::Path` for + /// remote types. + this_type: syn::Path, + + /// Same as `this_type` but using `::` for generic parameters for use in + /// expression position. + this_value: syn::Path, /// Generics including any explicit and inferred bounds for the impl. generics: syn::Generics, @@ -105,18 +103,15 @@ impl Parameters { Ident::new("self", Span::call_site()) }; - let this = match cont.attrs.remote() { - Some(remote) => remote.clone(), - None => cont.ident.clone().into(), - }; - + let this_type = this::this_type(cont); + let this_value = this::this_value(cont); let is_packed = cont.attrs.is_packed(); - let generics = build_generics(cont); Parameters { self_var, - this, + this_type, + this_value, generics, is_remote, is_packed, @@ -126,7 +121,7 @@ impl Parameters { /// Type name to use in error messages and `&'static str` arguments to /// various Serializer methods. fn type_name(&self) -> String { - self.this.segments.last().unwrap().ident.to_string() + self.this_type.segments.last().unwrap().ident.to_string() } } @@ -287,7 +282,7 @@ fn serialize_tuple_struct( .fold(quote!(0), |sum, expr| quote!(#sum + #expr)); quote_block! { - let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_struct(__serializer, #type_name, #len)); + let #let_mut __serde_state = _serde::Serializer::serialize_tuple_struct(__serializer, #type_name, #len)?; #(#serialize_stmts)* _serde::ser::SerializeTupleStruct::end(__serde_state) } @@ -309,7 +304,7 @@ fn serialize_struct_tag_field(cattrs: &attr::Container, struct_trait: &StructTra let type_name = cattrs.name().serialize_name(); let func = struct_trait.serialize_field(Span::call_site()); quote! { - try!(#func(&mut __serde_state, #tag, #type_name)); + #func(&mut __serde_state, #tag, #type_name)?; } } _ => quote! {}, @@ -350,7 +345,7 @@ fn serialize_struct_as_struct( ); quote_block! { - let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct(__serializer, #type_name, #len)); + let #let_mut __serde_state = _serde::Serializer::serialize_struct(__serializer, #type_name, #len)?; #tag_field #(#serialize_fields)* _serde::ser::SerializeStruct::end(__serde_state) @@ -394,7 +389,7 @@ fn serialize_struct_as_map( }; quote_block! { - let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(__serializer, #len)); + let #let_mut __serde_state = _serde::Serializer::serialize_map(__serializer, #len)?; #tag_field #(#serialize_fields)* _serde::ser::SerializeMap::end(__serde_state) @@ -406,7 +401,7 @@ fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Cont let self_var = ¶ms.self_var; - let arms: Vec<_> = variants + let mut arms: Vec<_> = variants .iter() .enumerate() .map(|(variant_index, variant)| { @@ -414,6 +409,12 @@ fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Cont }) .collect(); + if cattrs.remote().is_some() && cattrs.non_exhaustive() { + arms.push(quote! { + ref unrecognized => _serde::__private::Err(_serde::ser::Error::custom(_serde::__private::ser::CannotSerializeVariant(unrecognized))), + }); + } + quote_expr! { match *#self_var { #(#arms)* @@ -427,7 +428,7 @@ fn serialize_variant( variant_index: u32, cattrs: &attr::Container, ) -> TokenStream { - let this = ¶ms.this; + let this_value = ¶ms.this_value; let variant_ident = &variant.ident; if variant.attrs.skip_serializing() { @@ -445,47 +446,56 @@ fn serialize_variant( Style::Struct => quote!({ .. }), }; quote! { - #this::#variant_ident #fields_pat => #skipped_err, + #this_value::#variant_ident #fields_pat => #skipped_err, } } else { // variant wasn't skipped let case = match variant.style { Style::Unit => { quote! { - #this::#variant_ident + #this_value::#variant_ident } } Style::Newtype => { quote! { - #this::#variant_ident(ref __field0) + #this_value::#variant_ident(ref __field0) } } Style::Tuple => { let field_names = (0..variant.fields.len()) .map(|i| Ident::new(&format!("__field{}", i), Span::call_site())); quote! { - #this::#variant_ident(#(ref #field_names),*) + #this_value::#variant_ident(#(ref #field_names),*) } } Style::Struct => { let members = variant.fields.iter().map(|f| &f.member); quote! { - #this::#variant_ident { #(ref #members),* } + #this_value::#variant_ident { #(ref #members),* } } } }; - let body = Match(match cattrs.tag() { - attr::TagType::External => { + let body = Match(match (cattrs.tag(), variant.attrs.untagged()) { + (attr::TagType::External, false) => { serialize_externally_tagged_variant(params, variant, variant_index, cattrs) } - attr::TagType::Internal { tag } => { + (attr::TagType::Internal { tag }, false) => { serialize_internally_tagged_variant(params, variant, cattrs, tag) } - attr::TagType::Adjacent { tag, content } => { - serialize_adjacently_tagged_variant(params, variant, cattrs, tag, content) + (attr::TagType::Adjacent { tag, content }, false) => { + serialize_adjacently_tagged_variant( + params, + variant, + cattrs, + variant_index, + tag, + content, + ) + } + (attr::TagType::None, _) | (_, true) => { + serialize_untagged_variant(params, variant, cattrs) } - attr::TagType::None => serialize_untagged_variant(params, variant, cattrs), }); quote! { @@ -562,7 +572,7 @@ fn serialize_externally_tagged_variant( }, params, &variant.fields, - &type_name, + type_name, ), } } @@ -596,10 +606,10 @@ fn serialize_internally_tagged_variant( match effective_style(variant) { Style::Unit => { quote_block! { - let mut __struct = try!(_serde::Serializer::serialize_struct( - __serializer, #type_name, 1)); - try!(_serde::ser::SerializeStruct::serialize_field( - &mut __struct, #tag, #variant_name)); + let mut __struct = _serde::Serializer::serialize_struct( + __serializer, #type_name, 1)?; + _serde::ser::SerializeStruct::serialize_field( + &mut __struct, #tag, #variant_name)?; _serde::ser::SerializeStruct::end(__struct) } } @@ -627,7 +637,7 @@ fn serialize_internally_tagged_variant( StructVariant::InternallyTagged { tag, variant_name }, params, &variant.fields, - &type_name, + type_name, ), Style::Tuple => unreachable!("checked in serde_derive_internals"), } @@ -637,12 +647,20 @@ fn serialize_adjacently_tagged_variant( params: &Parameters, variant: &Variant, cattrs: &attr::Container, + variant_index: u32, tag: &str, content: &str, ) -> Fragment { - let this = ¶ms.this; + let this_type = ¶ms.this_type; let type_name = cattrs.name().serialize_name(); let variant_name = variant.attrs.name().serialize_name(); + let serialize_variant = quote! { + &_serde::__private::ser::AdjacentlyTaggedEnumVariant { + enum_name: #type_name, + variant_index: #variant_index, + variant_name: #variant_name, + } + }; let inner = Stmts(if let Some(path) = variant.attrs.serialize_with() { let ser = wrap_serialize_variant_with(params, path, variant); @@ -653,10 +671,10 @@ fn serialize_adjacently_tagged_variant( match effective_style(variant) { Style::Unit => { return quote_block! { - let mut __struct = try!(_serde::Serializer::serialize_struct( - __serializer, #type_name, 1)); - try!(_serde::ser::SerializeStruct::serialize_field( - &mut __struct, #tag, #variant_name)); + let mut __struct = _serde::Serializer::serialize_struct( + __serializer, #type_name, 1)?; + _serde::ser::SerializeStruct::serialize_field( + &mut __struct, #tag, #serialize_variant)?; _serde::ser::SerializeStruct::end(__struct) }; } @@ -670,12 +688,12 @@ fn serialize_adjacently_tagged_variant( let span = field.original.span(); let func = quote_spanned!(span=> _serde::ser::SerializeStruct::serialize_field); return quote_block! { - let mut __struct = try!(_serde::Serializer::serialize_struct( - __serializer, #type_name, 2)); - try!(_serde::ser::SerializeStruct::serialize_field( - &mut __struct, #tag, #variant_name)); - try!(#func( - &mut __struct, #content, #field_expr)); + let mut __struct = _serde::Serializer::serialize_struct( + __serializer, #type_name, 2)?; + _serde::ser::SerializeStruct::serialize_field( + &mut __struct, #tag, #serialize_variant)?; + #func( + &mut __struct, #content, #field_expr)?; _serde::ser::SerializeStruct::end(__struct) }; } @@ -686,13 +704,13 @@ fn serialize_adjacently_tagged_variant( StructVariant::Untagged, params, &variant.fields, - &variant_name, + variant_name, ), } }); let fields_ty = variant.fields.iter().map(|f| &f.ty); - let fields_ident: &Vec<_> = &match variant.style { + let fields_ident: &[_] = &match variant.style { Style::Unit => { if variant.attrs.serialize_with().is_some() { vec![] @@ -717,9 +735,10 @@ fn serialize_adjacently_tagged_variant( let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl(); quote_block! { + #[doc(hidden)] struct __AdjacentlyTagged #wrapper_generics #where_clause { data: (#(&'__a #fields_ty,)*), - phantom: _serde::__private::PhantomData<#this #ty_generics>, + phantom: _serde::__private::PhantomData<#this_type #ty_generics>, } impl #wrapper_impl_generics _serde::Serialize for __AdjacentlyTagged #wrapper_ty_generics #where_clause { @@ -734,15 +753,15 @@ fn serialize_adjacently_tagged_variant( } } - let mut __struct = try!(_serde::Serializer::serialize_struct( - __serializer, #type_name, 2)); - try!(_serde::ser::SerializeStruct::serialize_field( - &mut __struct, #tag, #variant_name)); - try!(_serde::ser::SerializeStruct::serialize_field( + let mut __struct = _serde::Serializer::serialize_struct( + __serializer, #type_name, 2)?; + _serde::ser::SerializeStruct::serialize_field( + &mut __struct, #tag, #serialize_variant)?; + _serde::ser::SerializeStruct::serialize_field( &mut __struct, #content, &__AdjacentlyTagged { data: (#(#fields_ident,)*), - phantom: _serde::__private::PhantomData::<#this #ty_generics>, - })); + phantom: _serde::__private::PhantomData::<#this_type #ty_generics>, + })?; _serde::ser::SerializeStruct::end(__struct) } } @@ -781,16 +800,16 @@ fn serialize_untagged_variant( Style::Tuple => serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields), Style::Struct => { let type_name = cattrs.name().serialize_name(); - serialize_struct_variant(StructVariant::Untagged, params, &variant.fields, &type_name) + serialize_struct_variant(StructVariant::Untagged, params, &variant.fields, type_name) } } } -enum TupleVariant { +enum TupleVariant<'a> { ExternallyTagged { - type_name: String, + type_name: &'a str, variant_index: u32, - variant_name: String, + variant_name: &'a str, }, Untagged, } @@ -832,21 +851,21 @@ fn serialize_tuple_variant( variant_name, } => { quote_block! { - let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_variant( + let #let_mut __serde_state = _serde::Serializer::serialize_tuple_variant( __serializer, #type_name, #variant_index, #variant_name, - #len)); + #len)?; #(#serialize_stmts)* _serde::ser::SerializeTupleVariant::end(__serde_state) } } TupleVariant::Untagged => { quote_block! { - let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple( + let #let_mut __serde_state = _serde::Serializer::serialize_tuple( __serializer, - #len)); + #len)?; #(#serialize_stmts)* _serde::ser::SerializeTuple::end(__serde_state) } @@ -857,17 +876,17 @@ fn serialize_tuple_variant( enum StructVariant<'a> { ExternallyTagged { variant_index: u32, - variant_name: String, + variant_name: &'a str, }, InternallyTagged { tag: &'a str, - variant_name: String, + variant_name: &'a str, }, Untagged, } -fn serialize_struct_variant<'a>( - context: StructVariant<'a>, +fn serialize_struct_variant( + context: StructVariant, params: &Parameters, fields: &[Field], name: &str, @@ -909,40 +928,40 @@ fn serialize_struct_variant<'a>( variant_name, } => { quote_block! { - let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct_variant( + let #let_mut __serde_state = _serde::Serializer::serialize_struct_variant( __serializer, #name, #variant_index, #variant_name, #len, - )); + )?; #(#serialize_fields)* _serde::ser::SerializeStructVariant::end(__serde_state) } } StructVariant::InternallyTagged { tag, variant_name } => { quote_block! { - let mut __serde_state = try!(_serde::Serializer::serialize_struct( + let mut __serde_state = _serde::Serializer::serialize_struct( __serializer, #name, #len + 1, - )); - try!(_serde::ser::SerializeStruct::serialize_field( + )?; + _serde::ser::SerializeStruct::serialize_field( &mut __serde_state, #tag, #variant_name, - )); + )?; #(#serialize_fields)* _serde::ser::SerializeStruct::end(__serde_state) } } StructVariant::Untagged => { quote_block! { - let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct( + let #let_mut __serde_state = _serde::Serializer::serialize_struct( __serializer, #name, #len, - )); + )?; #(#serialize_fields)* _serde::ser::SerializeStruct::end(__serde_state) } @@ -950,8 +969,8 @@ fn serialize_struct_variant<'a>( } } -fn serialize_struct_variant_with_flatten<'a>( - context: StructVariant<'a>, +fn serialize_struct_variant_with_flatten( + context: StructVariant, params: &Parameters, fields: &[Field], name: &str, @@ -971,7 +990,7 @@ fn serialize_struct_variant_with_flatten<'a>( variant_index, variant_name, } => { - let this = ¶ms.this; + let this_type = ¶ms.this_type; let fields_ty = fields.iter().map(|f| &f.ty); let members = &fields.iter().map(|f| &f.member).collect::>(); @@ -980,9 +999,10 @@ fn serialize_struct_variant_with_flatten<'a>( let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl(); quote_block! { + #[doc(hidden)] struct __EnumFlatten #wrapper_generics #where_clause { data: (#(&'__a #fields_ty,)*), - phantom: _serde::__private::PhantomData<#this #ty_generics>, + phantom: _serde::__private::PhantomData<#this_type #ty_generics>, } impl #wrapper_impl_generics _serde::Serialize for __EnumFlatten #wrapper_ty_generics #where_clause { @@ -991,9 +1011,9 @@ fn serialize_struct_variant_with_flatten<'a>( __S: _serde::Serializer, { let (#(#members,)*) = self.data; - let #let_mut __serde_state = try!(_serde::Serializer::serialize_map( + let #let_mut __serde_state = _serde::Serializer::serialize_map( __serializer, - _serde::__private::None)); + _serde::__private::None)?; #(#serialize_fields)* _serde::ser::SerializeMap::end(__serde_state) } @@ -1006,29 +1026,29 @@ fn serialize_struct_variant_with_flatten<'a>( #variant_name, &__EnumFlatten { data: (#(#members,)*), - phantom: _serde::__private::PhantomData::<#this #ty_generics>, + phantom: _serde::__private::PhantomData::<#this_type #ty_generics>, }) } } StructVariant::InternallyTagged { tag, variant_name } => { quote_block! { - let #let_mut __serde_state = try!(_serde::Serializer::serialize_map( + let #let_mut __serde_state = _serde::Serializer::serialize_map( __serializer, - _serde::__private::None)); - try!(_serde::ser::SerializeMap::serialize_entry( + _serde::__private::None)?; + _serde::ser::SerializeMap::serialize_entry( &mut __serde_state, #tag, #variant_name, - )); + )?; #(#serialize_fields)* _serde::ser::SerializeMap::end(__serde_state) } } StructVariant::Untagged => { quote_block! { - let #let_mut __serde_state = try!(_serde::Serializer::serialize_map( + let #let_mut __serde_state = _serde::Serializer::serialize_map( __serializer, - _serde::__private::None)); + _serde::__private::None)?; #(#serialize_fields)* _serde::ser::SerializeMap::end(__serde_state) } @@ -1073,7 +1093,7 @@ fn serialize_tuple_struct_visitor( let span = field.original.span(); let func = tuple_trait.serialize_element(span); let ser = quote! { - try!(#func(&mut __serde_state, #field_expr)); + #func(&mut __serde_state, #field_expr)?; }; match skip { @@ -1117,12 +1137,12 @@ fn serialize_struct_visitor( let ser = if field.attrs.flatten() { let func = quote_spanned!(span=> _serde::Serialize::serialize); quote! { - try!(#func(&#field_expr, _serde::__private::ser::FlatMapSerializer(&mut __serde_state))); + #func(&#field_expr, _serde::__private::ser::FlatMapSerializer(&mut __serde_state))?; } } else { let func = struct_trait.serialize_field(span); quote! { - try!(#func(&mut __serde_state, #key_expr, #field_expr)); + #func(&mut __serde_state, #key_expr, #field_expr)?; } }; @@ -1134,7 +1154,7 @@ fn serialize_struct_visitor( if !#skip { #ser } else { - try!(#skip_func(&mut __serde_state, #key_expr)); + #skip_func(&mut __serde_state, #key_expr)?; } } } else { @@ -1192,7 +1212,7 @@ fn wrap_serialize_with( field_tys: &[&syn::Type], field_exprs: &[TokenStream], ) -> TokenStream { - let this = ¶ms.this; + let this_type = ¶ms.this_type; let (_, ty_generics, where_clause) = params.generics.split_for_impl(); let wrapper_generics = if field_exprs.is_empty() { @@ -1210,9 +1230,10 @@ fn wrap_serialize_with( }); quote!({ + #[doc(hidden)] struct __SerializeWith #wrapper_impl_generics #where_clause { values: (#(&'__a #field_tys, )*), - phantom: _serde::__private::PhantomData<#this #ty_generics>, + phantom: _serde::__private::PhantomData<#this_type #ty_generics>, } impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause { @@ -1226,14 +1247,14 @@ fn wrap_serialize_with( &__SerializeWith { values: (#(#field_exprs, )*), - phantom: _serde::__private::PhantomData::<#this #ty_generics>, + phantom: _serde::__private::PhantomData::<#this_type #ty_generics>, } }) } // Serialization of an empty struct results in code like: // -// let mut __serde_state = try!(serializer.serialize_struct("S", 0)); +// let mut __serde_state = serializer.serialize_struct("S", 0)?; // _serde::ser::SerializeStruct::end(__serde_state) // // where we want to omit the `mut` to avoid a warning. diff --git a/serde_derive/src/this.rs b/serde_derive/src/this.rs new file mode 100644 index 00000000..941cea40 --- /dev/null +++ b/serde_derive/src/this.rs @@ -0,0 +1,32 @@ +use crate::internals::ast::Container; +use syn::{Path, PathArguments, Token}; + +pub fn this_type(cont: &Container) -> Path { + if let Some(remote) = cont.attrs.remote() { + let mut this = remote.clone(); + for segment in &mut this.segments { + if let PathArguments::AngleBracketed(arguments) = &mut segment.arguments { + arguments.colon2_token = None; + } + } + this + } else { + Path::from(cont.ident.clone()) + } +} + +pub fn this_value(cont: &Container) -> Path { + if let Some(remote) = cont.attrs.remote() { + let mut this = remote.clone(); + for segment in &mut this.segments { + if let PathArguments::AngleBracketed(arguments) = &mut segment.arguments { + if arguments.colon2_token.is_none() { + arguments.colon2_token = Some(Token![::](arguments.lt_token.span)); + } + } + } + this + } else { + Path::from(cont.ident.clone()) + } +} diff --git a/serde_derive/src/try.rs b/serde_derive/src/try.rs deleted file mode 100644 index 48cceeba..00000000 --- a/serde_derive/src/try.rs +++ /dev/null @@ -1,24 +0,0 @@ -use proc_macro2::{Punct, Spacing, TokenStream}; - -// None of our generated code requires the `From::from` error conversion -// performed by the standard library's `try!` macro. With this simplified macro -// we see a significant improvement in type checking and borrow checking time of -// the generated code and a slight improvement in binary size. -pub fn replacement() -> TokenStream { - // Cannot pass `$expr` to `quote!` prior to Rust 1.17.0 so interpolate it. - let dollar = Punct::new('$', Spacing::Alone); - - quote! { - #[allow(unused_macros)] - macro_rules! try { - (#dollar __expr:expr) => { - match #dollar __expr { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } - } - } - } -} diff --git a/serde_derive_internals/Cargo.toml b/serde_derive_internals/Cargo.toml index b57b5a1d..6ce27797 100644 --- a/serde_derive_internals/Cargo.toml +++ b/serde_derive_internals/Cargo.toml @@ -1,23 +1,24 @@ [package] name = "serde_derive_internals" -version = "0.26.0" # remember to update html_root_url +version = "0.29.0" authors = ["Erick Tryzelaar ", "David Tolnay "] -rust-version = "1.31" -license = "MIT OR Apache-2.0" description = "AST representation used by Serde derive macros. Unstable." -homepage = "https://serde.rs" -repository = "https://github.com/serde-rs/serde" documentation = "https://docs.rs/serde_derive_internals" +exclude = ["build.rs"] +homepage = "https://serde.rs" keywords = ["serde", "serialization"] -include = ["lib.rs", "src/**/*.rs", "LICENSE-APACHE", "LICENSE-MIT"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/serde-rs/serde" +rust-version = "1.56" [lib] path = "lib.rs" [dependencies] -proc-macro2 = "1.0" -quote = "1.0" -syn = { version = "1.0.60", default-features = false, features = ["derive", "parsing", "printing", "clone-impls"] } +proc-macro2 = { workspace = true } +quote = { workspace = true } +syn = { workspace = true, features = ["clone-impls", "derive", "parsing", "printing"] } [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] +rustdoc-args = ["--generate-link-to-definition"] diff --git a/serde_derive_internals/build.rs b/serde_derive_internals/build.rs index b2a2d04a..25b5ef31 100644 --- a/serde_derive_internals/build.rs +++ b/serde_derive_internals/build.rs @@ -1,6 +1,9 @@ use std::path::Path; fn main() { + println!("cargo:rerun-if-changed=build.rs"); + println!("cargo:rerun-if-changed=src/mod.rs"); + // 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 diff --git a/serde_derive_internals/lib.rs b/serde_derive_internals/lib.rs index e0a14324..1053b009 100644 --- a/serde_derive_internals/lib.rs +++ b/serde_derive_internals/lib.rs @@ -1,10 +1,10 @@ -#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.26.0")] -#![allow(unknown_lints, bare_trait_objects)] +#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.29.0")] // Ignored clippy lints #![allow( clippy::cognitive_complexity, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/7575 clippy::collapsible_match, + clippy::derive_partial_eq_without_eq, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6797 clippy::manual_map, clippy::missing_panics_doc, @@ -21,7 +21,7 @@ clippy::doc_markdown, clippy::enum_glob_use, clippy::items_after_statements, - clippy::let_underscore_drop, + clippy::let_underscore_untyped, clippy::manual_assert, clippy::match_same_arms, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6984 @@ -29,18 +29,18 @@ clippy::missing_errors_doc, clippy::module_name_repetitions, clippy::must_use_candidate, + clippy::return_self_not_must_use, clippy::similar_names, + clippy::single_match_else, clippy::struct_excessive_bools, clippy::too_many_lines, clippy::unused_self, clippy::wildcard_imports )] -#[macro_use] -extern crate syn; - extern crate proc_macro2; extern crate quote; +extern crate syn; #[cfg_attr(serde_build_from_git, path = "../serde_derive/src/internals/mod.rs")] #[cfg_attr(not(serde_build_from_git), path = "src/mod.rs")] diff --git a/serde_test/Cargo.toml b/serde_test/Cargo.toml deleted file mode 100644 index 848e7d49..00000000 --- a/serde_test/Cargo.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -name = "serde_test" -version = "1.0.136" # remember to update html_root_url -authors = ["Erick Tryzelaar ", "David Tolnay "] -rust-version = "1.15" -license = "MIT OR Apache-2.0" -description = "Token De/Serializer for testing De/Serialize implementations" -homepage = "https://serde.rs" -repository = "https://github.com/serde-rs/serde" -documentation = "https://docs.serde.rs/serde_test/" -keywords = ["serde", "serialization"] -readme = "crates-io.md" -include = ["build.rs", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] -build = "build.rs" - -[dependencies] -serde = { version = "1.0.60", path = "../serde" } - -[dev-dependencies] -serde = { version = "1.0", path = "../serde" } -serde_derive = { version = "1.0", path = "../serde_derive" } - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] diff --git a/serde_test/LICENSE-APACHE b/serde_test/LICENSE-APACHE deleted file mode 120000 index 965b606f..00000000 --- a/serde_test/LICENSE-APACHE +++ /dev/null @@ -1 +0,0 @@ -../LICENSE-APACHE \ No newline at end of file diff --git a/serde_test/LICENSE-MIT b/serde_test/LICENSE-MIT deleted file mode 120000 index 76219eb7..00000000 --- a/serde_test/LICENSE-MIT +++ /dev/null @@ -1 +0,0 @@ -../LICENSE-MIT \ No newline at end of file diff --git a/serde_test/README.md b/serde_test/README.md deleted file mode 120000 index 32d46ee8..00000000 --- a/serde_test/README.md +++ /dev/null @@ -1 +0,0 @@ -../README.md \ No newline at end of file diff --git a/serde_test/build.rs b/serde_test/build.rs deleted file mode 100644 index 15870655..00000000 --- a/serde_test/build.rs +++ /dev/null @@ -1,48 +0,0 @@ -use std::env; -use std::process::Command; -use std::str::{self, FromStr}; - -// The rustc-cfg strings below are *not* public API. Please let us know by -// opening a GitHub issue if your build environment requires some way to enable -// these cfgs other than by executing our build script. -fn main() { - let minor = match rustc_minor_version() { - Some(minor) => minor, - None => return, - }; - - // #[track_caller] stabilized in Rust 1.46: - // https://blog.rust-lang.org/2020/08/27/Rust-1.46.0.html#track_caller - if minor >= 46 { - println!("cargo:rustc-cfg=track_caller"); - } -} - -fn rustc_minor_version() -> Option { - let rustc = match env::var_os("RUSTC") { - Some(rustc) => rustc, - None => return None, - }; - - let output = match Command::new(rustc).arg("--version").output() { - Ok(output) => output, - Err(_) => return None, - }; - - let version = match str::from_utf8(&output.stdout) { - Ok(version) => version, - Err(_) => return None, - }; - - let mut pieces = version.split('.'); - if pieces.next() != Some("rustc 1") { - return None; - } - - let next = match pieces.next() { - Some(next) => next, - None => return None, - }; - - u32::from_str(next).ok() -} diff --git a/serde_test/crates-io.md b/serde_test/crates-io.md deleted file mode 120000 index ae66dc9c..00000000 --- a/serde_test/crates-io.md +++ /dev/null @@ -1 +0,0 @@ -../crates-io.md \ No newline at end of file diff --git a/serde_test/src/assert.rs b/serde_test/src/assert.rs deleted file mode 100644 index b34b1f55..00000000 --- a/serde_test/src/assert.rs +++ /dev/null @@ -1,223 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use de::Deserializer; -use ser::Serializer; -use token::Token; - -use std::fmt::Debug; - -/// Runs both `assert_ser_tokens` and `assert_de_tokens`. -/// -/// ```edition2018 -/// # use serde::{Serialize, Deserialize}; -/// # use serde_test::{assert_tokens, Token}; -/// # -/// #[derive(Serialize, Deserialize, PartialEq, Debug)] -/// struct S { -/// a: u8, -/// b: u8, -/// } -/// -/// let s = S { a: 0, b: 0 }; -/// assert_tokens(&s, &[ -/// Token::Struct { name: "S", len: 2 }, -/// Token::Str("a"), -/// Token::U8(0), -/// Token::Str("b"), -/// Token::U8(0), -/// Token::StructEnd, -/// ]); -/// ``` -#[cfg_attr(track_caller, track_caller)] -pub fn assert_tokens<'de, T>(value: &T, tokens: &'de [Token]) -where - T: Serialize + Deserialize<'de> + PartialEq + Debug, -{ - assert_ser_tokens(value, tokens); - assert_de_tokens(value, tokens); -} - -/// Asserts that `value` serializes to the given `tokens`. -/// -/// ```edition2018 -/// # use serde::{Serialize, Deserialize}; -/// # use serde_test::{assert_ser_tokens, Token}; -/// # -/// #[derive(Serialize, Deserialize, PartialEq, Debug)] -/// struct S { -/// a: u8, -/// b: u8, -/// } -/// -/// let s = S { a: 0, b: 0 }; -/// assert_ser_tokens(&s, &[ -/// Token::Struct { name: "S", len: 2 }, -/// Token::Str("a"), -/// Token::U8(0), -/// Token::Str("b"), -/// Token::U8(0), -/// Token::StructEnd, -/// ]); -/// ``` -#[cfg_attr(track_caller, track_caller)] -pub fn assert_ser_tokens(value: &T, tokens: &[Token]) -where - T: Serialize, -{ - let mut ser = Serializer::new(tokens); - match value.serialize(&mut ser) { - Ok(_) => {} - Err(err) => panic!("value failed to serialize: {}", err), - } - - if ser.remaining() > 0 { - panic!("{} remaining tokens", ser.remaining()); - } -} - -/// Asserts that `value` serializes to the given `tokens`, and then yields -/// `error`. -/// -/// ```edition2018 -/// use std::sync::{Arc, Mutex}; -/// use std::thread; -/// -/// use serde::Serialize; -/// use serde_test::{assert_ser_tokens_error, Token}; -/// -/// #[derive(Serialize)] -/// struct Example { -/// lock: Arc>, -/// } -/// -/// fn main() { -/// let example = Example { lock: Arc::new(Mutex::new(0)) }; -/// let lock = example.lock.clone(); -/// -/// let _ = thread::spawn(move || { -/// // This thread will acquire the mutex first, unwrapping the result -/// // of `lock` because the lock has not been poisoned. -/// let _guard = lock.lock().unwrap(); -/// -/// // This panic while holding the lock (`_guard` is in scope) will -/// // poison the mutex. -/// panic!() -/// }).join(); -/// -/// let expected = &[ -/// Token::Struct { name: "Example", len: 1 }, -/// Token::Str("lock"), -/// ]; -/// let error = "lock poison error while serializing"; -/// assert_ser_tokens_error(&example, expected, error); -/// } -/// ``` -#[cfg_attr(track_caller, track_caller)] -pub fn assert_ser_tokens_error(value: &T, tokens: &[Token], error: &str) -where - T: Serialize, -{ - let mut ser = Serializer::new(tokens); - match value.serialize(&mut ser) { - Ok(_) => panic!("value serialized successfully"), - Err(e) => assert_eq!(e, *error), - } - - if ser.remaining() > 0 { - panic!("{} remaining tokens", ser.remaining()); - } -} - -/// Asserts that the given `tokens` deserialize into `value`. -/// -/// ```edition2018 -/// # use serde::{Serialize, Deserialize}; -/// # use serde_test::{assert_de_tokens, Token}; -/// # -/// #[derive(Serialize, Deserialize, PartialEq, Debug)] -/// struct S { -/// a: u8, -/// b: u8, -/// } -/// -/// let s = S { a: 0, b: 0 }; -/// assert_de_tokens(&s, &[ -/// Token::Struct { name: "S", len: 2 }, -/// Token::Str("a"), -/// Token::U8(0), -/// Token::Str("b"), -/// Token::U8(0), -/// Token::StructEnd, -/// ]); -/// ``` -#[cfg_attr(track_caller, track_caller)] -pub fn assert_de_tokens<'de, T>(value: &T, tokens: &'de [Token]) -where - T: Deserialize<'de> + PartialEq + Debug, -{ - let mut de = Deserializer::new(tokens); - let mut deserialized_val = match T::deserialize(&mut de) { - Ok(v) => { - assert_eq!(v, *value); - v - } - Err(e) => panic!("tokens failed to deserialize: {}", e), - }; - if de.remaining() > 0 { - panic!("{} remaining tokens", de.remaining()); - } - - // Do the same thing for deserialize_in_place. This isn't *great* because a - // no-op impl of deserialize_in_place can technically succeed here. Still, - // this should catch a lot of junk. - let mut de = Deserializer::new(tokens); - match T::deserialize_in_place(&mut de, &mut deserialized_val) { - Ok(()) => { - assert_eq!(deserialized_val, *value); - } - Err(e) => panic!("tokens failed to deserialize_in_place: {}", e), - } - if de.remaining() > 0 { - panic!("{} remaining tokens", de.remaining()); - } -} - -/// Asserts that the given `tokens` yield `error` when deserializing. -/// -/// ```edition2018 -/// # use serde::{Serialize, Deserialize}; -/// # use serde_test::{assert_de_tokens_error, Token}; -/// # -/// #[derive(Serialize, Deserialize, PartialEq, Debug)] -/// #[serde(deny_unknown_fields)] -/// struct S { -/// a: u8, -/// b: u8, -/// } -/// -/// assert_de_tokens_error::( -/// &[ -/// Token::Struct { name: "S", len: 2 }, -/// Token::Str("x"), -/// ], -/// "unknown field `x`, expected `a` or `b`", -/// ); -/// ``` -#[cfg_attr(track_caller, track_caller)] -pub fn assert_de_tokens_error<'de, T>(tokens: &'de [Token], error: &str) -where - T: Deserialize<'de>, -{ - let mut de = Deserializer::new(tokens); - match T::deserialize(&mut de) { - Ok(_) => panic!("tokens deserialized successfully"), - Err(e) => assert_eq!(e, *error), - } - - // There may be one token left if a peek caused the error - de.next_token_opt(); - - if de.remaining() > 0 { - panic!("{} remaining tokens", de.remaining()); - } -} diff --git a/serde_test/src/configure.rs b/serde_test/src/configure.rs deleted file mode 100644 index d34ad906..00000000 --- a/serde_test/src/configure.rs +++ /dev/null @@ -1,847 +0,0 @@ -use std::fmt; - -use serde::ser::{ - SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeTuple, - SerializeTupleStruct, SerializeTupleVariant, -}; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; - -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] -pub struct Readable(T); -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] -pub struct Compact(T); - -/// Trait to determine whether a value is represented in human-readable or -/// compact form. -/// -/// ```edition2018 -/// use serde::{Deserialize, Deserializer, Serialize, Serializer}; -/// use serde_test::{assert_tokens, Configure, Token}; -/// -/// #[derive(Debug, PartialEq)] -/// struct Example(u8, u8); -/// -/// impl Serialize for Example { -/// fn serialize(&self, serializer: S) -> Result -/// where -/// S: Serializer, -/// { -/// if serializer.is_human_readable() { -/// format!("{}.{}", self.0, self.1).serialize(serializer) -/// } else { -/// (self.0, self.1).serialize(serializer) -/// } -/// } -/// } -/// -/// impl<'de> Deserialize<'de> for Example { -/// fn deserialize(deserializer: D) -> Result -/// where -/// D: Deserializer<'de>, -/// { -/// use serde::de::Error; -/// if deserializer.is_human_readable() { -/// let s = String::deserialize(deserializer)?; -/// let parts: Vec<_> = s.split('.').collect(); -/// Ok(Example( -/// parts[0].parse().map_err(D::Error::custom)?, -/// parts[1].parse().map_err(D::Error::custom)?, -/// )) -/// } else { -/// let (x, y) = Deserialize::deserialize(deserializer)?; -/// Ok(Example(x, y)) -/// } -/// } -/// } -/// -/// fn main() { -/// assert_tokens( -/// &Example(1, 0).compact(), -/// &[ -/// Token::Tuple { len: 2 }, -/// Token::U8(1), -/// Token::U8(0), -/// Token::TupleEnd, -/// ], -/// ); -/// assert_tokens(&Example(1, 0).readable(), &[Token::Str("1.0")]); -/// } -/// ``` -pub trait Configure { - /// Marks `self` as using `is_human_readable == true` - fn readable(self) -> Readable - where - Self: Sized, - { - Readable(self) - } - /// Marks `self` as using `is_human_readable == false` - fn compact(self) -> Compact - where - Self: Sized, - { - Compact(self) - } -} - -impl Configure for T {} - -impl Serialize for Readable -where - T: Serialize, -{ - #[inline] - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - self.0.serialize(Readable(serializer)) - } -} -impl Serialize for Compact -where - T: Serialize, -{ - #[inline] - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - self.0.serialize(Compact(serializer)) - } -} -impl<'de, T> Deserialize<'de> for Readable -where - T: Deserialize<'de>, -{ - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - T::deserialize(Readable(deserializer)).map(Readable) - } -} -impl<'de, T> Deserialize<'de> for Compact -where - T: Deserialize<'de>, -{ - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - T::deserialize(Compact(deserializer)).map(Compact) - } -} - -impl<'de, T> DeserializeSeed<'de> for Readable -where - T: DeserializeSeed<'de>, -{ - type Value = T::Value; - - fn deserialize(self, deserializer: D) -> Result - where - D: Deserializer<'de>, - { - self.0.deserialize(Readable(deserializer)) - } -} -impl<'de, T> DeserializeSeed<'de> for Compact -where - T: DeserializeSeed<'de>, -{ - type Value = T::Value; - - fn deserialize(self, deserializer: D) -> Result - where - D: Deserializer<'de>, - { - self.0.deserialize(Compact(deserializer)) - } -} - -macro_rules! forward_method { - ($name: ident (self $(, $arg: ident : $arg_type: ty)* ) -> $return_type: ty) => { - fn $name (self $(, $arg : $arg_type)* ) -> $return_type { - (self.0).$name( $($arg),* ) - } - }; -} - -macro_rules! forward_serialize_methods { - ( $( $name: ident $arg_type: ty ),* ) => { - $( - forward_method!($name(self, v : $arg_type) -> Result); - )* - }; -} - -macro_rules! impl_serializer { - ($wrapper:ident, $is_human_readable:expr) => { - impl Serializer for $wrapper - where - S: Serializer, - { - type Ok = S::Ok; - type Error = S::Error; - - type SerializeSeq = $wrapper; - type SerializeTuple = $wrapper; - type SerializeTupleStruct = $wrapper; - type SerializeTupleVariant = $wrapper; - type SerializeMap = $wrapper; - type SerializeStruct = $wrapper; - type SerializeStructVariant = $wrapper; - - fn is_human_readable(&self) -> bool { - $is_human_readable - } - - forward_serialize_methods! { - serialize_bool bool, - serialize_i8 i8, - serialize_i16 i16, - serialize_i32 i32, - serialize_i64 i64, - serialize_u8 u8, - serialize_u16 u16, - serialize_u32 u32, - serialize_u64 u64, - serialize_f32 f32, - serialize_f64 f64, - serialize_char char, - serialize_str &str, - serialize_bytes &[u8], - serialize_unit_struct &'static str - - } - - fn serialize_unit(self) -> Result { - self.0.serialize_unit() - } - - fn serialize_unit_variant( - self, - name: &'static str, - variant_index: u32, - variant: &'static str, - ) -> Result { - self.0.serialize_unit_variant(name, variant_index, variant) - } - - fn serialize_newtype_struct( - self, - name: &'static str, - value: &T, - ) -> Result - where - T: Serialize, - { - self.0.serialize_newtype_struct(name, &$wrapper(value)) - } - - fn serialize_newtype_variant( - self, - name: &'static str, - variant_index: u32, - variant: &'static str, - value: &T, - ) -> Result - where - T: Serialize, - { - self.0 - .serialize_newtype_variant(name, variant_index, variant, &$wrapper(value)) - } - - fn serialize_none(self) -> Result { - self.0.serialize_none() - } - - fn serialize_some(self, value: &T) -> Result - where - T: Serialize, - { - self.0.serialize_some(&$wrapper(value)) - } - - fn serialize_seq(self, len: Option) -> Result { - self.0.serialize_seq(len).map($wrapper) - } - - fn serialize_tuple(self, len: usize) -> Result { - self.0.serialize_tuple(len).map($wrapper) - } - - fn serialize_tuple_struct( - self, - name: &'static str, - len: usize, - ) -> Result { - self.0.serialize_tuple_struct(name, len).map($wrapper) - } - - fn serialize_tuple_variant( - self, - name: &'static str, - variant_index: u32, - variant: &'static str, - len: usize, - ) -> Result { - self.0 - .serialize_tuple_variant(name, variant_index, variant, len) - .map($wrapper) - } - - fn serialize_map(self, len: Option) -> Result { - self.0.serialize_map(len).map($wrapper) - } - - fn serialize_struct( - self, - name: &'static str, - len: usize, - ) -> Result { - self.0.serialize_struct(name, len).map($wrapper) - } - - fn serialize_struct_variant( - self, - name: &'static str, - variant_index: u32, - variant: &'static str, - len: usize, - ) -> Result { - self.0 - .serialize_struct_variant(name, variant_index, variant, len) - .map($wrapper) - } - } - - impl SerializeSeq for $wrapper - where - S: SerializeSeq, - { - type Ok = S::Ok; - type Error = S::Error; - fn serialize_element(&mut self, value: &T) -> Result<(), S::Error> - where - T: Serialize, - { - self.0.serialize_element(&$wrapper(value)) - } - fn end(self) -> Result { - self.0.end() - } - } - - impl SerializeTuple for $wrapper - where - S: SerializeTuple, - { - type Ok = S::Ok; - type Error = S::Error; - fn serialize_element(&mut self, value: &T) -> Result<(), S::Error> - where - T: Serialize, - { - self.0.serialize_element(&$wrapper(value)) - } - fn end(self) -> Result { - self.0.end() - } - } - - impl SerializeTupleStruct for $wrapper - where - S: SerializeTupleStruct, - { - type Ok = S::Ok; - type Error = S::Error; - fn serialize_field(&mut self, value: &T) -> Result<(), S::Error> - where - T: Serialize, - { - self.0.serialize_field(&$wrapper(value)) - } - fn end(self) -> Result { - self.0.end() - } - } - - impl SerializeTupleVariant for $wrapper - where - S: SerializeTupleVariant, - { - type Ok = S::Ok; - type Error = S::Error; - fn serialize_field(&mut self, value: &T) -> Result<(), S::Error> - where - T: Serialize, - { - self.0.serialize_field(&$wrapper(value)) - } - fn end(self) -> Result { - self.0.end() - } - } - - impl SerializeMap for $wrapper - where - S: SerializeMap, - { - type Ok = S::Ok; - type Error = S::Error; - fn serialize_key(&mut self, key: &T) -> Result<(), S::Error> - where - T: Serialize, - { - self.0.serialize_key(&$wrapper(key)) - } - fn serialize_value(&mut self, value: &T) -> Result<(), S::Error> - where - T: Serialize, - { - self.0.serialize_value(&$wrapper(value)) - } - fn serialize_entry( - &mut self, - key: &K, - value: &V, - ) -> Result<(), S::Error> - where - K: Serialize, - V: Serialize, - { - self.0.serialize_entry(key, &$wrapper(value)) - } - fn end(self) -> Result { - self.0.end() - } - } - - impl SerializeStruct for $wrapper - where - S: SerializeStruct, - { - type Ok = S::Ok; - type Error = S::Error; - fn serialize_field( - &mut self, - name: &'static str, - field: &T, - ) -> Result<(), S::Error> - where - T: Serialize, - { - self.0.serialize_field(name, &$wrapper(field)) - } - fn end(self) -> Result { - self.0.end() - } - } - - impl SerializeStructVariant for $wrapper - where - S: SerializeStructVariant, - { - type Ok = S::Ok; - type Error = S::Error; - fn serialize_field( - &mut self, - name: &'static str, - field: &T, - ) -> Result<(), S::Error> - where - T: Serialize, - { - self.0.serialize_field(name, &$wrapper(field)) - } - fn end(self) -> Result { - self.0.end() - } - } - }; -} - -impl_serializer!(Readable, true); -impl_serializer!(Compact, false); - -use serde::de::{DeserializeSeed, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor}; - -macro_rules! forward_deserialize_methods { - ( $wrapper : ident ( $( $name: ident ),* ) ) => { - $( - fn $name(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - (self.0).$name($wrapper(visitor)) - } - )* - }; -} - -macro_rules! impl_deserializer { - ($wrapper:ident, $is_human_readable:expr) => { - impl<'de, D> Deserializer<'de> for $wrapper - where - D: Deserializer<'de>, - { - type Error = D::Error; - - forward_deserialize_methods! { - $wrapper ( - deserialize_any, - deserialize_bool, - deserialize_u8, - deserialize_u16, - deserialize_u32, - deserialize_u64, - deserialize_i8, - deserialize_i16, - deserialize_i32, - deserialize_i64, - deserialize_f32, - deserialize_f64, - deserialize_char, - deserialize_str, - deserialize_string, - deserialize_bytes, - deserialize_byte_buf, - deserialize_option, - deserialize_unit, - deserialize_seq, - deserialize_map, - deserialize_identifier, - deserialize_ignored_any - ) - } - - fn deserialize_unit_struct( - self, - name: &'static str, - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - self.0.deserialize_unit_struct(name, $wrapper(visitor)) - } - fn deserialize_newtype_struct( - self, - name: &'static str, - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - self.0.deserialize_newtype_struct(name, $wrapper(visitor)) - } - fn deserialize_tuple(self, len: usize, visitor: V) -> Result - where - V: Visitor<'de>, - { - self.0.deserialize_tuple(len, $wrapper(visitor)) - } - fn deserialize_tuple_struct( - self, - name: &'static str, - len: usize, - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - self.0 - .deserialize_tuple_struct(name, len, $wrapper(visitor)) - } - fn deserialize_struct( - self, - name: &'static str, - fields: &'static [&'static str], - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - self.0.deserialize_struct(name, fields, $wrapper(visitor)) - } - fn deserialize_enum( - self, - name: &'static str, - variants: &'static [&'static str], - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - self.0.deserialize_enum(name, variants, $wrapper(visitor)) - } - - fn is_human_readable(&self) -> bool { - $is_human_readable - } - } - - impl<'de, D> Visitor<'de> for $wrapper - where - D: Visitor<'de>, - { - type Value = D::Value; - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - self.0.expecting(formatter) - } - fn visit_bool(self, v: bool) -> Result - where - E: Error, - { - self.0.visit_bool(v) - } - fn visit_i8(self, v: i8) -> Result - where - E: Error, - { - self.0.visit_i8(v) - } - fn visit_i16(self, v: i16) -> Result - where - E: Error, - { - self.0.visit_i16(v) - } - fn visit_i32(self, v: i32) -> Result - where - E: Error, - { - self.0.visit_i32(v) - } - fn visit_i64(self, v: i64) -> Result - where - E: Error, - { - self.0.visit_i64(v) - } - fn visit_u8(self, v: u8) -> Result - where - E: Error, - { - self.0.visit_u8(v) - } - fn visit_u16(self, v: u16) -> Result - where - E: Error, - { - self.0.visit_u16(v) - } - fn visit_u32(self, v: u32) -> Result - where - E: Error, - { - self.0.visit_u32(v) - } - fn visit_u64(self, v: u64) -> Result - where - E: Error, - { - self.0.visit_u64(v) - } - fn visit_f32(self, v: f32) -> Result - where - E: Error, - { - self.0.visit_f32(v) - } - fn visit_f64(self, v: f64) -> Result - where - E: Error, - { - self.0.visit_f64(v) - } - fn visit_char(self, v: char) -> Result - where - E: Error, - { - self.0.visit_char(v) - } - fn visit_str(self, v: &str) -> Result - where - E: Error, - { - self.0.visit_str(v) - } - fn visit_borrowed_str(self, v: &'de str) -> Result - where - E: Error, - { - self.0.visit_borrowed_str(v) - } - fn visit_string(self, v: String) -> Result - where - E: Error, - { - self.0.visit_string(v) - } - fn visit_bytes(self, v: &[u8]) -> Result - where - E: Error, - { - self.0.visit_bytes(v) - } - fn visit_borrowed_bytes(self, v: &'de [u8]) -> Result - where - E: Error, - { - self.0.visit_borrowed_bytes(v) - } - fn visit_byte_buf(self, v: Vec) -> Result - where - E: Error, - { - self.0.visit_byte_buf(v) - } - fn visit_none(self) -> Result - where - E: Error, - { - self.0.visit_none() - } - fn visit_some(self, deserializer: D2) -> Result - where - D2: Deserializer<'de>, - { - self.0.visit_some($wrapper(deserializer)) - } - fn visit_unit(self) -> Result - where - E: Error, - { - self.0.visit_unit() - } - fn visit_newtype_struct(self, deserializer: D2) -> Result - where - D2: Deserializer<'de>, - { - self.0.visit_newtype_struct($wrapper(deserializer)) - } - fn visit_seq(self, seq: V) -> Result - where - V: SeqAccess<'de>, - { - self.0.visit_seq($wrapper(seq)) - } - fn visit_map(self, map: V) -> Result - where - V: MapAccess<'de>, - { - self.0.visit_map($wrapper(map)) - } - fn visit_enum(self, data: V) -> Result - where - V: EnumAccess<'de>, - { - self.0.visit_enum($wrapper(data)) - } - } - - impl<'de, D> SeqAccess<'de> for $wrapper - where - D: SeqAccess<'de>, - { - type Error = D::Error; - fn next_element_seed(&mut self, seed: T) -> Result, D::Error> - where - T: DeserializeSeed<'de>, - { - self.0.next_element_seed($wrapper(seed)) - } - fn size_hint(&self) -> Option { - self.0.size_hint() - } - } - - impl<'de, D> MapAccess<'de> for $wrapper - where - D: MapAccess<'de>, - { - type Error = D::Error; - fn next_key_seed(&mut self, seed: K) -> Result, D::Error> - where - K: DeserializeSeed<'de>, - { - self.0.next_key_seed($wrapper(seed)) - } - fn next_value_seed(&mut self, seed: V) -> Result - where - V: DeserializeSeed<'de>, - { - self.0.next_value_seed($wrapper(seed)) - } - fn next_entry_seed( - &mut self, - kseed: K, - vseed: V, - ) -> Result, D::Error> - where - K: DeserializeSeed<'de>, - V: DeserializeSeed<'de>, - { - self.0.next_entry_seed($wrapper(kseed), $wrapper(vseed)) - } - fn size_hint(&self) -> Option { - self.0.size_hint() - } - } - - impl<'de, D> EnumAccess<'de> for $wrapper - where - D: EnumAccess<'de>, - { - type Error = D::Error; - type Variant = $wrapper; - fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> - where - V: DeserializeSeed<'de>, - { - self.0 - .variant_seed($wrapper(seed)) - .map(|(value, variant)| (value, $wrapper(variant))) - } - } - - impl<'de, D> VariantAccess<'de> for $wrapper - where - D: VariantAccess<'de>, - { - type Error = D::Error; - fn unit_variant(self) -> Result<(), D::Error> { - self.0.unit_variant() - } - fn newtype_variant_seed(self, seed: T) -> Result - where - T: DeserializeSeed<'de>, - { - self.0.newtype_variant_seed($wrapper(seed)) - } - fn tuple_variant(self, len: usize, visitor: V) -> Result - where - V: Visitor<'de>, - { - self.0.tuple_variant(len, $wrapper(visitor)) - } - fn struct_variant( - self, - fields: &'static [&'static str], - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - self.0.struct_variant(fields, $wrapper(visitor)) - } - } - }; -} - -impl_deserializer!(Readable, true); -impl_deserializer!(Compact, false); diff --git a/serde_test/src/de.rs b/serde_test/src/de.rs deleted file mode 100644 index 673a0c0e..00000000 --- a/serde_test/src/de.rs +++ /dev/null @@ -1,683 +0,0 @@ -use serde::de::value::{MapAccessDeserializer, SeqAccessDeserializer}; -use serde::de::{ - self, Deserialize, DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess, SeqAccess, - VariantAccess, Visitor, -}; - -use error::Error; -use token::Token; - -#[derive(Debug)] -pub struct Deserializer<'de> { - tokens: &'de [Token], -} - -macro_rules! assert_next_token { - ($de:expr, $expected:expr) => { - match $de.next_token_opt() { - Some(token) if token == $expected => {} - Some(other) => panic!( - "expected Token::{} but deserialization wants Token::{}", - other, $expected - ), - None => panic!( - "end of tokens but deserialization wants Token::{}", - $expected - ), - } - }; -} - -macro_rules! unexpected { - ($token:expr) => { - panic!("deserialization did not expect this token: {}", $token) - }; -} - -macro_rules! end_of_tokens { - () => { - panic!("ran out of tokens to deserialize") - }; -} - -impl<'de> Deserializer<'de> { - pub fn new(tokens: &'de [Token]) -> Self { - Deserializer { tokens: tokens } - } - - fn peek_token_opt(&self) -> Option { - self.tokens.first().cloned() - } - - fn peek_token(&self) -> Token { - match self.peek_token_opt() { - Some(token) => token, - None => end_of_tokens!(), - } - } - - pub fn next_token_opt(&mut self) -> Option { - match self.tokens.split_first() { - Some((&first, rest)) => { - self.tokens = rest; - Some(first) - } - None => None, - } - } - - fn next_token(&mut self) -> Token { - match self.tokens.split_first() { - Some((&first, rest)) => { - self.tokens = rest; - first - } - None => end_of_tokens!(), - } - } - - pub fn remaining(&self) -> usize { - self.tokens.len() - } - - fn visit_seq( - &mut self, - len: Option, - end: Token, - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - let value = visitor.visit_seq(DeserializerSeqVisitor { - de: self, - len: len, - end: end, - })?; - assert_next_token!(self, end); - Ok(value) - } - - fn visit_map( - &mut self, - len: Option, - end: Token, - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - let value = visitor.visit_map(DeserializerMapVisitor { - de: self, - len: len, - end: end, - })?; - assert_next_token!(self, end); - Ok(value) - } -} - -impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { - type Error = Error; - - forward_to_deserialize_any! { - bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string - bytes byte_buf unit seq map identifier ignored_any - } - - fn deserialize_any(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - let token = self.next_token(); - match token { - Token::Bool(v) => visitor.visit_bool(v), - Token::I8(v) => visitor.visit_i8(v), - Token::I16(v) => visitor.visit_i16(v), - Token::I32(v) => visitor.visit_i32(v), - Token::I64(v) => visitor.visit_i64(v), - Token::U8(v) => visitor.visit_u8(v), - Token::U16(v) => visitor.visit_u16(v), - Token::U32(v) => visitor.visit_u32(v), - Token::U64(v) => visitor.visit_u64(v), - Token::F32(v) => visitor.visit_f32(v), - Token::F64(v) => visitor.visit_f64(v), - Token::Char(v) => visitor.visit_char(v), - Token::Str(v) => visitor.visit_str(v), - Token::BorrowedStr(v) => visitor.visit_borrowed_str(v), - Token::String(v) => visitor.visit_string(v.to_owned()), - Token::Bytes(v) => visitor.visit_bytes(v), - Token::BorrowedBytes(v) => visitor.visit_borrowed_bytes(v), - Token::ByteBuf(v) => visitor.visit_byte_buf(v.to_vec()), - Token::None => visitor.visit_none(), - Token::Some => visitor.visit_some(self), - Token::Unit | Token::UnitStruct { .. } => visitor.visit_unit(), - Token::NewtypeStruct { .. } => visitor.visit_newtype_struct(self), - Token::Seq { len } => self.visit_seq(len, Token::SeqEnd, visitor), - Token::Tuple { len } => self.visit_seq(Some(len), Token::TupleEnd, visitor), - Token::TupleStruct { len, .. } => { - self.visit_seq(Some(len), Token::TupleStructEnd, visitor) - } - Token::Map { len } => self.visit_map(len, Token::MapEnd, visitor), - Token::Struct { len, .. } => self.visit_map(Some(len), Token::StructEnd, visitor), - Token::Enum { .. } => { - let variant = self.next_token(); - let next = self.peek_token(); - match (variant, next) { - (Token::Str(variant), Token::Unit) => { - self.next_token(); - visitor.visit_str(variant) - } - (Token::BorrowedStr(variant), Token::Unit) => { - self.next_token(); - visitor.visit_borrowed_str(variant) - } - (Token::String(variant), Token::Unit) => { - self.next_token(); - visitor.visit_string(variant.to_string()) - } - (Token::Bytes(variant), Token::Unit) => { - self.next_token(); - visitor.visit_bytes(variant) - } - (Token::BorrowedBytes(variant), Token::Unit) => { - self.next_token(); - visitor.visit_borrowed_bytes(variant) - } - (Token::ByteBuf(variant), Token::Unit) => { - self.next_token(); - visitor.visit_byte_buf(variant.to_vec()) - } - (Token::U8(variant), Token::Unit) => { - self.next_token(); - visitor.visit_u8(variant) - } - (Token::U16(variant), Token::Unit) => { - self.next_token(); - visitor.visit_u16(variant) - } - (Token::U32(variant), Token::Unit) => { - self.next_token(); - visitor.visit_u32(variant) - } - (Token::U64(variant), Token::Unit) => { - self.next_token(); - visitor.visit_u64(variant) - } - (variant, Token::Unit) => unexpected!(variant), - (variant, _) => { - visitor.visit_map(EnumMapVisitor::new(self, variant, EnumFormat::Any)) - } - } - } - Token::UnitVariant { variant, .. } => visitor.visit_str(variant), - Token::NewtypeVariant { variant, .. } => visitor.visit_map(EnumMapVisitor::new( - self, - Token::Str(variant), - EnumFormat::Any, - )), - Token::TupleVariant { variant, .. } => visitor.visit_map(EnumMapVisitor::new( - self, - Token::Str(variant), - EnumFormat::Seq, - )), - Token::StructVariant { variant, .. } => visitor.visit_map(EnumMapVisitor::new( - self, - Token::Str(variant), - EnumFormat::Map, - )), - Token::SeqEnd - | Token::TupleEnd - | Token::TupleStructEnd - | Token::MapEnd - | Token::StructEnd - | Token::TupleVariantEnd - | Token::StructVariantEnd => { - unexpected!(token); - } - } - } - - fn deserialize_option(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - match self.peek_token() { - Token::Unit | Token::None => { - self.next_token(); - visitor.visit_none() - } - Token::Some => { - self.next_token(); - visitor.visit_some(self) - } - _ => self.deserialize_any(visitor), - } - } - - fn deserialize_enum( - self, - name: &'static str, - _variants: &'static [&'static str], - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - match self.peek_token() { - Token::Enum { name: n } if name == n => { - self.next_token(); - - visitor.visit_enum(DeserializerEnumVisitor { de: self }) - } - Token::UnitVariant { name: n, .. } - | Token::NewtypeVariant { name: n, .. } - | Token::TupleVariant { name: n, .. } - | Token::StructVariant { name: n, .. } - if name == n => - { - visitor.visit_enum(DeserializerEnumVisitor { de: self }) - } - _ => self.deserialize_any(visitor), - } - } - - fn deserialize_unit_struct(self, name: &'static str, visitor: V) -> Result - where - V: Visitor<'de>, - { - match self.peek_token() { - Token::UnitStruct { .. } => { - assert_next_token!(self, Token::UnitStruct { name: name }); - visitor.visit_unit() - } - _ => self.deserialize_any(visitor), - } - } - - fn deserialize_newtype_struct( - self, - name: &'static str, - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - match self.peek_token() { - Token::NewtypeStruct { .. } => { - assert_next_token!(self, Token::NewtypeStruct { name: name }); - visitor.visit_newtype_struct(self) - } - _ => self.deserialize_any(visitor), - } - } - - fn deserialize_tuple(self, len: usize, visitor: V) -> Result - where - V: Visitor<'de>, - { - match self.peek_token() { - Token::Unit | Token::UnitStruct { .. } => { - self.next_token(); - visitor.visit_unit() - } - Token::Seq { .. } => { - self.next_token(); - self.visit_seq(Some(len), Token::SeqEnd, visitor) - } - Token::Tuple { .. } => { - self.next_token(); - self.visit_seq(Some(len), Token::TupleEnd, visitor) - } - Token::TupleStruct { .. } => { - self.next_token(); - self.visit_seq(Some(len), Token::TupleStructEnd, visitor) - } - _ => self.deserialize_any(visitor), - } - } - - fn deserialize_tuple_struct( - self, - name: &'static str, - len: usize, - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - match self.peek_token() { - Token::Unit => { - self.next_token(); - visitor.visit_unit() - } - Token::UnitStruct { .. } => { - assert_next_token!(self, Token::UnitStruct { name: name }); - visitor.visit_unit() - } - Token::Seq { .. } => { - self.next_token(); - self.visit_seq(Some(len), Token::SeqEnd, visitor) - } - Token::Tuple { .. } => { - self.next_token(); - self.visit_seq(Some(len), Token::TupleEnd, visitor) - } - Token::TupleStruct { len: n, .. } => { - assert_next_token!(self, Token::TupleStruct { name: name, len: n }); - self.visit_seq(Some(len), Token::TupleStructEnd, visitor) - } - _ => self.deserialize_any(visitor), - } - } - - fn deserialize_struct( - self, - name: &'static str, - fields: &'static [&'static str], - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - match self.peek_token() { - Token::Struct { len: n, .. } => { - assert_next_token!(self, Token::Struct { name: name, len: n }); - self.visit_map(Some(fields.len()), Token::StructEnd, visitor) - } - Token::Map { .. } => { - self.next_token(); - self.visit_map(Some(fields.len()), Token::MapEnd, visitor) - } - _ => self.deserialize_any(visitor), - } - } - - fn is_human_readable(&self) -> bool { - panic!( - "Types which have different human-readable and compact representations \ - must explicitly mark their test cases with `serde_test::Configure`" - ); - } -} - -////////////////////////////////////////////////////////////////////////// - -struct DeserializerSeqVisitor<'a, 'de: 'a> { - de: &'a mut Deserializer<'de>, - len: Option, - end: Token, -} - -impl<'de, 'a> SeqAccess<'de> for DeserializerSeqVisitor<'a, 'de> { - type Error = Error; - - fn next_element_seed(&mut self, seed: T) -> Result, Error> - where - T: DeserializeSeed<'de>, - { - if self.de.peek_token_opt() == Some(self.end) { - return Ok(None); - } - self.len = self.len.map(|len| len.saturating_sub(1)); - seed.deserialize(&mut *self.de).map(Some) - } - - fn size_hint(&self) -> Option { - self.len - } -} - -////////////////////////////////////////////////////////////////////////// - -struct DeserializerMapVisitor<'a, 'de: 'a> { - de: &'a mut Deserializer<'de>, - len: Option, - end: Token, -} - -impl<'de, 'a> MapAccess<'de> for DeserializerMapVisitor<'a, 'de> { - type Error = Error; - - fn next_key_seed(&mut self, seed: K) -> Result, Error> - where - K: DeserializeSeed<'de>, - { - if self.de.peek_token_opt() == Some(self.end) { - return Ok(None); - } - self.len = self.len.map(|len| len.saturating_sub(1)); - seed.deserialize(&mut *self.de).map(Some) - } - - fn next_value_seed(&mut self, seed: V) -> Result - where - V: DeserializeSeed<'de>, - { - seed.deserialize(&mut *self.de) - } - - fn size_hint(&self) -> Option { - self.len - } -} - -////////////////////////////////////////////////////////////////////////// - -struct DeserializerEnumVisitor<'a, 'de: 'a> { - de: &'a mut Deserializer<'de>, -} - -impl<'de, 'a> EnumAccess<'de> for DeserializerEnumVisitor<'a, 'de> { - type Error = Error; - type Variant = Self; - - fn variant_seed(self, seed: V) -> Result<(V::Value, Self), Error> - where - V: DeserializeSeed<'de>, - { - match self.de.peek_token() { - Token::UnitVariant { variant: v, .. } - | Token::NewtypeVariant { variant: v, .. } - | Token::TupleVariant { variant: v, .. } - | Token::StructVariant { variant: v, .. } => { - let de = v.into_deserializer(); - let value = seed.deserialize(de)?; - Ok((value, self)) - } - _ => { - let value = seed.deserialize(&mut *self.de)?; - Ok((value, self)) - } - } - } -} - -impl<'de, 'a> VariantAccess<'de> for DeserializerEnumVisitor<'a, 'de> { - type Error = Error; - - fn unit_variant(self) -> Result<(), Error> { - match self.de.peek_token() { - Token::UnitVariant { .. } => { - self.de.next_token(); - Ok(()) - } - _ => Deserialize::deserialize(self.de), - } - } - - fn newtype_variant_seed(self, seed: T) -> Result - where - T: DeserializeSeed<'de>, - { - match self.de.peek_token() { - Token::NewtypeVariant { .. } => { - self.de.next_token(); - seed.deserialize(self.de) - } - _ => seed.deserialize(self.de), - } - } - - fn tuple_variant(self, len: usize, visitor: V) -> Result - where - V: Visitor<'de>, - { - match self.de.peek_token() { - Token::TupleVariant { len: enum_len, .. } => { - let token = self.de.next_token(); - - if len == enum_len { - self.de - .visit_seq(Some(len), Token::TupleVariantEnd, visitor) - } else { - unexpected!(token); - } - } - Token::Seq { - len: Some(enum_len), - } => { - let token = self.de.next_token(); - - if len == enum_len { - self.de.visit_seq(Some(len), Token::SeqEnd, visitor) - } else { - unexpected!(token); - } - } - _ => de::Deserializer::deserialize_any(self.de, visitor), - } - } - - fn struct_variant( - self, - fields: &'static [&'static str], - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - match self.de.peek_token() { - Token::StructVariant { len: enum_len, .. } => { - let token = self.de.next_token(); - - if fields.len() == enum_len { - self.de - .visit_map(Some(fields.len()), Token::StructVariantEnd, visitor) - } else { - unexpected!(token); - } - } - Token::Map { - len: Some(enum_len), - } => { - let token = self.de.next_token(); - - if fields.len() == enum_len { - self.de - .visit_map(Some(fields.len()), Token::MapEnd, visitor) - } else { - unexpected!(token); - } - } - _ => de::Deserializer::deserialize_any(self.de, visitor), - } - } -} - -////////////////////////////////////////////////////////////////////////// - -struct EnumMapVisitor<'a, 'de: 'a> { - de: &'a mut Deserializer<'de>, - variant: Option, - format: EnumFormat, -} - -enum EnumFormat { - Seq, - Map, - Any, -} - -impl<'a, 'de> EnumMapVisitor<'a, 'de> { - fn new(de: &'a mut Deserializer<'de>, variant: Token, format: EnumFormat) -> Self { - EnumMapVisitor { - de: de, - variant: Some(variant), - format: format, - } - } -} - -impl<'de, 'a> MapAccess<'de> for EnumMapVisitor<'a, 'de> { - type Error = Error; - - fn next_key_seed(&mut self, seed: K) -> Result, Error> - where - K: DeserializeSeed<'de>, - { - match self.variant.take() { - Some(Token::Str(variant)) => seed.deserialize(variant.into_deserializer()).map(Some), - Some(Token::Bytes(variant)) => seed - .deserialize(BytesDeserializer { value: variant }) - .map(Some), - Some(Token::U32(variant)) => seed.deserialize(variant.into_deserializer()).map(Some), - Some(other) => unexpected!(other), - None => Ok(None), - } - } - - fn next_value_seed(&mut self, seed: V) -> Result - where - V: DeserializeSeed<'de>, - { - match self.format { - EnumFormat::Seq => { - let value = { - let visitor = DeserializerSeqVisitor { - de: self.de, - len: None, - end: Token::TupleVariantEnd, - }; - seed.deserialize(SeqAccessDeserializer::new(visitor))? - }; - assert_next_token!(self.de, Token::TupleVariantEnd); - Ok(value) - } - EnumFormat::Map => { - let value = { - let visitor = DeserializerMapVisitor { - de: self.de, - len: None, - end: Token::StructVariantEnd, - }; - seed.deserialize(MapAccessDeserializer::new(visitor))? - }; - assert_next_token!(self.de, Token::StructVariantEnd); - Ok(value) - } - EnumFormat::Any => seed.deserialize(&mut *self.de), - } - } -} - -struct BytesDeserializer { - value: &'static [u8], -} - -impl<'de> de::Deserializer<'de> for BytesDeserializer { - type Error = Error; - - fn deserialize_any(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - visitor.visit_bytes(self.value) - } - - forward_to_deserialize_any! { - bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string - bytes byte_buf option unit unit_struct newtype_struct seq tuple - tuple_struct map struct enum identifier ignored_any - } -} diff --git a/serde_test/src/error.rs b/serde_test/src/error.rs deleted file mode 100644 index 54a71d2d..00000000 --- a/serde_test/src/error.rs +++ /dev/null @@ -1,43 +0,0 @@ -use std::error; -use std::fmt::{self, Display}; - -use serde::{de, ser}; - -#[derive(Clone, Debug)] -pub struct Error { - msg: String, -} - -impl ser::Error for Error { - fn custom(msg: T) -> Self { - Error { - msg: msg.to_string(), - } - } -} - -impl de::Error for Error { - fn custom(msg: T) -> Self { - Error { - msg: msg.to_string(), - } - } -} - -impl fmt::Display for Error { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str(&self.msg) - } -} - -impl error::Error for Error { - fn description(&self) -> &str { - &self.msg - } -} - -impl PartialEq for Error { - fn eq(&self, other: &str) -> bool { - self.msg == other - } -} diff --git a/serde_test/src/lib.rs b/serde_test/src/lib.rs deleted file mode 100644 index 3671ee61..00000000 --- a/serde_test/src/lib.rs +++ /dev/null @@ -1,190 +0,0 @@ -//! This crate provides a convenient concise way to write unit tests for -//! implementations of [`Serialize`] and [`Deserialize`]. -//! -//! [`Serialize`]: https://docs.serde.rs/serde/ser/trait.Serialize.html -//! [`Deserialize`]: https://docs.serde.rs/serde/de/trait.Deserialize.html -//! -//! The `Serialize` impl for a value can be characterized by the sequence of -//! [`Serializer`] calls that are made in the course of serializing the value, -//! so `serde_test` provides a [`Token`] abstraction which corresponds roughly -//! to `Serializer` method calls. There is an [`assert_ser_tokens`] function to -//! test that a value serializes to a particular sequence of method calls, an -//! [`assert_de_tokens`] function to test that a value can be deserialized from -//! a particular sequence of method calls, and an [`assert_tokens`] function to -//! test both directions. There are also functions to test expected failure -//! conditions. -//! -//! [`Serializer`]: https://docs.serde.rs/serde/ser/trait.Serializer.html -//! [`Token`]: https://docs.serde.rs/serde_test/enum.Token.html -//! [`assert_ser_tokens`]: https://docs.serde.rs/serde_test/fn.assert_ser_tokens.html -//! [`assert_de_tokens`]: https://docs.serde.rs/serde_test/fn.assert_de_tokens.html -//! [`assert_tokens`]: https://docs.serde.rs/serde_test/fn.assert_tokens.html -//! -//! Here is an example from the [`linked-hash-map`] crate. -//! -//! [`linked-hash-map`]: https://github.com/contain-rs/linked-hash-map -//! -//! ```edition2018 -//! # const IGNORE: &str = stringify! { -//! use linked_hash_map::LinkedHashMap; -//! # }; -//! use serde_test::{Token, assert_tokens}; -//! -//! # use std::fmt; -//! # use std::marker::PhantomData; -//! # -//! # use serde::ser::{Serialize, Serializer, SerializeMap}; -//! # use serde::de::{Deserialize, Deserializer, Visitor, MapAccess}; -//! # -//! # // Dumb imitation of LinkedHashMap. -//! # #[derive(PartialEq, Debug)] -//! # struct LinkedHashMap(Vec<(K, V)>); -//! # -//! # impl LinkedHashMap { -//! # fn new() -> Self { -//! # LinkedHashMap(Vec::new()) -//! # } -//! # -//! # fn insert(&mut self, k: K, v: V) { -//! # self.0.push((k, v)); -//! # } -//! # } -//! # -//! # impl Serialize for LinkedHashMap -//! # where -//! # K: Serialize, -//! # V: Serialize, -//! # { -//! # fn serialize(&self, serializer: S) -> Result -//! # where -//! # S: Serializer, -//! # { -//! # let mut map = serializer.serialize_map(Some(self.0.len()))?; -//! # for &(ref k, ref v) in &self.0 { -//! # map.serialize_entry(k, v)?; -//! # } -//! # map.end() -//! # } -//! # } -//! # -//! # struct LinkedHashMapVisitor(PhantomData<(K, V)>); -//! # -//! # impl<'de, K, V> Visitor<'de> for LinkedHashMapVisitor -//! # where -//! # K: Deserialize<'de>, -//! # V: Deserialize<'de>, -//! # { -//! # type Value = LinkedHashMap; -//! # -//! # fn expecting(&self, _: &mut fmt::Formatter) -> fmt::Result { -//! # unimplemented!() -//! # } -//! # -//! # fn visit_map(self, mut access: M) -> Result -//! # where -//! # M: MapAccess<'de>, -//! # { -//! # let mut map = LinkedHashMap::new(); -//! # while let Some((key, value)) = access.next_entry()? { -//! # map.insert(key, value); -//! # } -//! # Ok(map) -//! # } -//! # } -//! # -//! # impl<'de, K, V> Deserialize<'de> for LinkedHashMap -//! # where -//! # K: Deserialize<'de>, -//! # V: Deserialize<'de>, -//! # { -//! # fn deserialize(deserializer: D) -> Result -//! # where -//! # D: Deserializer<'de>, -//! # { -//! # deserializer.deserialize_map(LinkedHashMapVisitor(PhantomData)) -//! # } -//! # } -//! # -//! #[test] -//! # fn not_a_test_ser_de_empty() {} -//! fn test_ser_de_empty() { -//! let map = LinkedHashMap::::new(); -//! -//! assert_tokens(&map, &[ -//! Token::Map { len: Some(0) }, -//! Token::MapEnd, -//! ]); -//! } -//! -//! #[test] -//! # fn not_a_test_ser_de() {} -//! fn test_ser_de() { -//! let mut map = LinkedHashMap::new(); -//! map.insert('b', 20); -//! map.insert('a', 10); -//! map.insert('c', 30); -//! -//! assert_tokens(&map, &[ -//! Token::Map { len: Some(3) }, -//! Token::Char('b'), -//! Token::I32(20), -//! -//! Token::Char('a'), -//! Token::I32(10), -//! -//! Token::Char('c'), -//! Token::I32(30), -//! Token::MapEnd, -//! ]); -//! } -//! # -//! # fn main() { -//! # test_ser_de_empty(); -//! # test_ser_de(); -//! # } -//! ``` - -#![doc(html_root_url = "https://docs.rs/serde_test/1.0.136")] -#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))] -// Ignored clippy lints -#![cfg_attr(feature = "cargo-clippy", allow(float_cmp, needless_doctest_main))] -// Ignored clippy_pedantic lints -#![cfg_attr( - feature = "cargo-clippy", - allow( - cloned_instead_of_copied, - empty_line_after_outer_attr, - manual_assert, - missing_docs_in_private_items, - missing_panics_doc, - module_name_repetitions, - must_use_candidate, - redundant_field_names, - too_many_lines, - use_debug, - use_self - ) -)] - -#[macro_use] -extern crate serde; - -mod de; -mod error; -mod ser; - -mod assert; -mod configure; -mod token; - -pub use assert::{ - assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_ser_tokens_error, - assert_tokens, -}; -pub use token::Token; - -pub use configure::{Compact, Configure, Readable}; - -// Not public API. -#[doc(hidden)] -pub use de::Deserializer; diff --git a/serde_test/src/ser.rs b/serde_test/src/ser.rs deleted file mode 100644 index 0827e793..00000000 --- a/serde_test/src/ser.rs +++ /dev/null @@ -1,464 +0,0 @@ -use serde::{ser, Serialize}; - -use error::Error; -use token::Token; - -/// A `Serializer` that ensures that a value serializes to a given list of -/// tokens. -#[derive(Debug)] -pub struct Serializer<'a> { - tokens: &'a [Token], -} - -impl<'a> Serializer<'a> { - /// Creates the serializer. - pub fn new(tokens: &'a [Token]) -> Self { - Serializer { tokens: tokens } - } - - /// Pulls the next token off of the serializer, ignoring it. - fn next_token(&mut self) -> Option { - if let Some((&first, rest)) = self.tokens.split_first() { - self.tokens = rest; - Some(first) - } else { - None - } - } - - pub fn remaining(&self) -> usize { - self.tokens.len() - } -} - -macro_rules! assert_next_token { - ($ser:expr, $actual:ident) => {{ - assert_next_token!($ser, stringify!($actual), Token::$actual, true); - }}; - ($ser:expr, $actual:ident($v:expr)) => {{ - assert_next_token!( - $ser, - format_args!(concat!(stringify!($actual), "({:?})"), $v), - Token::$actual(v), - v == $v - ); - }}; - ($ser:expr, $actual:ident { $($k:ident),* }) => {{ - let compare = ($($k,)*); - let field_format = || { - use std::fmt::Write; - let mut buffer = String::new(); - $( - write!(&mut buffer, concat!(stringify!($k), ": {:?}, "), $k).unwrap(); - )* - buffer - }; - assert_next_token!( - $ser, - format_args!(concat!(stringify!($actual), " {{ {}}}"), field_format()), - Token::$actual { $($k),* }, - ($($k,)*) == compare - ); - }}; - ($ser:expr, $actual:expr, $pat:pat, $guard:expr) => { - match $ser.next_token() { - Some($pat) if $guard => {} - Some(expected) => { - panic!("expected Token::{} but serialized as {}", - expected, $actual); - } - None => { - panic!("expected end of tokens, but {} was serialized", - $actual); - } - } - }; -} - -impl<'s, 'a> ser::Serializer for &'s mut Serializer<'a> { - type Ok = (); - type Error = Error; - - type SerializeSeq = Self; - type SerializeTuple = Self; - type SerializeTupleStruct = Self; - type SerializeTupleVariant = Variant<'s, 'a>; - type SerializeMap = Self; - type SerializeStruct = Self; - type SerializeStructVariant = Variant<'s, 'a>; - - fn serialize_bool(self, v: bool) -> Result<(), Error> { - assert_next_token!(self, Bool(v)); - Ok(()) - } - - fn serialize_i8(self, v: i8) -> Result<(), Error> { - assert_next_token!(self, I8(v)); - Ok(()) - } - - fn serialize_i16(self, v: i16) -> Result<(), Error> { - assert_next_token!(self, I16(v)); - Ok(()) - } - - fn serialize_i32(self, v: i32) -> Result<(), Error> { - assert_next_token!(self, I32(v)); - Ok(()) - } - - fn serialize_i64(self, v: i64) -> Result<(), Error> { - assert_next_token!(self, I64(v)); - Ok(()) - } - - fn serialize_u8(self, v: u8) -> Result<(), Error> { - assert_next_token!(self, U8(v)); - Ok(()) - } - - fn serialize_u16(self, v: u16) -> Result<(), Error> { - assert_next_token!(self, U16(v)); - Ok(()) - } - - fn serialize_u32(self, v: u32) -> Result<(), Error> { - assert_next_token!(self, U32(v)); - Ok(()) - } - - fn serialize_u64(self, v: u64) -> Result<(), Error> { - assert_next_token!(self, U64(v)); - Ok(()) - } - - fn serialize_f32(self, v: f32) -> Result<(), Error> { - assert_next_token!(self, F32(v)); - Ok(()) - } - - fn serialize_f64(self, v: f64) -> Result<(), Error> { - assert_next_token!(self, F64(v)); - Ok(()) - } - - fn serialize_char(self, v: char) -> Result<(), Error> { - assert_next_token!(self, Char(v)); - Ok(()) - } - - fn serialize_str(self, v: &str) -> Result<(), Error> { - match self.tokens.first() { - Some(&Token::BorrowedStr(_)) => assert_next_token!(self, BorrowedStr(v)), - Some(&Token::String(_)) => assert_next_token!(self, String(v)), - _ => assert_next_token!(self, Str(v)), - } - Ok(()) - } - - fn serialize_bytes(self, v: &[u8]) -> Result<(), Self::Error> { - match self.tokens.first() { - Some(&Token::BorrowedBytes(_)) => assert_next_token!(self, BorrowedBytes(v)), - Some(&Token::ByteBuf(_)) => assert_next_token!(self, ByteBuf(v)), - _ => assert_next_token!(self, Bytes(v)), - } - Ok(()) - } - - fn serialize_unit(self) -> Result<(), Error> { - assert_next_token!(self, Unit); - Ok(()) - } - - fn serialize_unit_struct(self, name: &'static str) -> Result<(), Error> { - assert_next_token!(self, UnitStruct { name }); - Ok(()) - } - - fn serialize_unit_variant( - self, - name: &'static str, - _variant_index: u32, - variant: &'static str, - ) -> Result<(), Error> { - if self.tokens.first() == Some(&Token::Enum { name: name }) { - self.next_token(); - assert_next_token!(self, Str(variant)); - assert_next_token!(self, Unit); - } else { - assert_next_token!(self, UnitVariant { name, variant }); - } - Ok(()) - } - - fn serialize_newtype_struct(self, name: &'static str, value: &T) -> Result<(), Error> - where - T: Serialize, - { - assert_next_token!(self, NewtypeStruct { name }); - value.serialize(self) - } - - fn serialize_newtype_variant( - self, - name: &'static str, - _variant_index: u32, - variant: &'static str, - value: &T, - ) -> Result<(), Error> - where - T: Serialize, - { - if self.tokens.first() == Some(&Token::Enum { name: name }) { - self.next_token(); - assert_next_token!(self, Str(variant)); - } else { - assert_next_token!(self, NewtypeVariant { name, variant }); - } - value.serialize(self) - } - - fn serialize_none(self) -> Result<(), Error> { - assert_next_token!(self, None); - Ok(()) - } - - fn serialize_some(self, value: &T) -> Result<(), Error> - where - T: Serialize, - { - assert_next_token!(self, Some); - value.serialize(self) - } - - fn serialize_seq(self, len: Option) -> Result { - assert_next_token!(self, Seq { len }); - Ok(self) - } - - fn serialize_tuple(self, len: usize) -> Result { - assert_next_token!(self, Tuple { len }); - Ok(self) - } - - fn serialize_tuple_struct(self, name: &'static str, len: usize) -> Result { - assert_next_token!(self, TupleStruct { name, len }); - Ok(self) - } - - fn serialize_tuple_variant( - self, - name: &'static str, - _variant_index: u32, - variant: &'static str, - len: usize, - ) -> Result { - if self.tokens.first() == Some(&Token::Enum { name: name }) { - self.next_token(); - assert_next_token!(self, Str(variant)); - let len = Some(len); - assert_next_token!(self, Seq { len }); - Ok(Variant { - ser: self, - end: Token::SeqEnd, - }) - } else { - assert_next_token!(self, TupleVariant { name, variant, len }); - Ok(Variant { - ser: self, - end: Token::TupleVariantEnd, - }) - } - } - - fn serialize_map(self, len: Option) -> Result { - assert_next_token!(self, Map { len }); - Ok(self) - } - - fn serialize_struct(self, name: &'static str, len: usize) -> Result { - assert_next_token!(self, Struct { name, len }); - Ok(self) - } - - fn serialize_struct_variant( - self, - name: &'static str, - _variant_index: u32, - variant: &'static str, - len: usize, - ) -> Result { - if self.tokens.first() == Some(&Token::Enum { name: name }) { - self.next_token(); - assert_next_token!(self, Str(variant)); - let len = Some(len); - assert_next_token!(self, Map { len }); - Ok(Variant { - ser: self, - end: Token::MapEnd, - }) - } else { - assert_next_token!(self, StructVariant { name, variant, len }); - Ok(Variant { - ser: self, - end: Token::StructVariantEnd, - }) - } - } - - fn is_human_readable(&self) -> bool { - panic!( - "Types which have different human-readable and compact representations \ - must explicitly mark their test cases with `serde_test::Configure`" - ); - } -} - -pub struct Variant<'s, 'a: 's> { - ser: &'s mut Serializer<'a>, - end: Token, -} - -impl<'s, 'a> ser::SerializeSeq for &'s mut Serializer<'a> { - type Ok = (); - type Error = Error; - - fn serialize_element(&mut self, value: &T) -> Result<(), Error> - where - T: Serialize, - { - value.serialize(&mut **self) - } - - fn end(self) -> Result<(), Error> { - assert_next_token!(self, SeqEnd); - Ok(()) - } -} - -impl<'s, 'a> ser::SerializeTuple for &'s mut Serializer<'a> { - type Ok = (); - type Error = Error; - - fn serialize_element(&mut self, value: &T) -> Result<(), Error> - where - T: Serialize, - { - value.serialize(&mut **self) - } - - fn end(self) -> Result<(), Error> { - assert_next_token!(self, TupleEnd); - Ok(()) - } -} - -impl<'s, 'a> ser::SerializeTupleStruct for &'s mut Serializer<'a> { - type Ok = (); - type Error = Error; - - fn serialize_field(&mut self, value: &T) -> Result<(), Error> - where - T: Serialize, - { - value.serialize(&mut **self) - } - - fn end(self) -> Result<(), Error> { - assert_next_token!(self, TupleStructEnd); - Ok(()) - } -} - -impl<'s, 'a> ser::SerializeTupleVariant for Variant<'s, 'a> { - type Ok = (); - type Error = Error; - - fn serialize_field(&mut self, value: &T) -> Result<(), Error> - where - T: Serialize, - { - value.serialize(&mut *self.ser) - } - - fn end(self) -> Result<(), Error> { - match self.end { - Token::TupleVariantEnd => assert_next_token!(self.ser, TupleVariantEnd), - Token::SeqEnd => assert_next_token!(self.ser, SeqEnd), - _ => unreachable!(), - } - Ok(()) - } -} - -impl<'s, 'a> ser::SerializeMap for &'s mut Serializer<'a> { - type Ok = (); - type Error = Error; - - fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> - where - T: Serialize, - { - key.serialize(&mut **self) - } - - fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> - where - T: Serialize, - { - value.serialize(&mut **self) - } - - fn end(self) -> Result<(), Self::Error> { - assert_next_token!(self, MapEnd); - Ok(()) - } -} - -impl<'s, 'a> ser::SerializeStruct for &'s mut Serializer<'a> { - type Ok = (); - type Error = Error; - - fn serialize_field( - &mut self, - key: &'static str, - value: &T, - ) -> Result<(), Self::Error> - where - T: Serialize, - { - key.serialize(&mut **self)?; - value.serialize(&mut **self) - } - - fn end(self) -> Result<(), Self::Error> { - assert_next_token!(self, StructEnd); - Ok(()) - } -} - -impl<'s, 'a> ser::SerializeStructVariant for Variant<'s, 'a> { - type Ok = (); - type Error = Error; - - fn serialize_field( - &mut self, - key: &'static str, - value: &T, - ) -> Result<(), Self::Error> - where - T: Serialize, - { - key.serialize(&mut *self.ser)?; - value.serialize(&mut *self.ser) - } - - fn end(self) -> Result<(), Self::Error> { - match self.end { - Token::StructVariantEnd => assert_next_token!(self.ser, StructVariantEnd), - Token::MapEnd => assert_next_token!(self.ser, MapEnd), - _ => unreachable!(), - } - Ok(()) - } -} diff --git a/serde_test/src/token.rs b/serde_test/src/token.rs deleted file mode 100644 index 22513614..00000000 --- a/serde_test/src/token.rs +++ /dev/null @@ -1,519 +0,0 @@ -use std::fmt::{self, Debug, Display}; - -#[derive(Copy, Clone, PartialEq, Debug)] -pub enum Token { - /// A serialized `bool`. - /// - /// ```edition2018 - /// # use serde_test::{assert_tokens, Token}; - /// # - /// assert_tokens(&true, &[Token::Bool(true)]); - /// ``` - Bool(bool), - - /// A serialized `i8`. - /// - /// ```edition2018 - /// # use serde_test::{assert_tokens, Token}; - /// # - /// assert_tokens(&0i8, &[Token::I8(0)]); - /// ``` - I8(i8), - - /// A serialized `i16`. - /// - /// ```edition2018 - /// # use serde_test::{assert_tokens, Token}; - /// # - /// assert_tokens(&0i16, &[Token::I16(0)]); - /// ``` - I16(i16), - - /// A serialized `i32`. - /// - /// ```edition2018 - /// # use serde_test::{assert_tokens, Token}; - /// # - /// assert_tokens(&0i32, &[Token::I32(0)]); - /// ``` - I32(i32), - - /// A serialized `i64`. - /// - /// ```edition2018 - /// # use serde_test::{assert_tokens, Token}; - /// # - /// assert_tokens(&0i64, &[Token::I64(0)]); - /// ``` - I64(i64), - - /// A serialized `u8`. - /// - /// ```edition2018 - /// # use serde_test::{assert_tokens, Token}; - /// # - /// assert_tokens(&0u8, &[Token::U8(0)]); - /// ``` - U8(u8), - - /// A serialized `u16`. - /// - /// ```edition2018 - /// # use serde_test::{assert_tokens, Token}; - /// # - /// assert_tokens(&0u16, &[Token::U16(0)]); - /// ``` - U16(u16), - - /// A serialized `u32`. - /// - /// ```edition2018 - /// # use serde_test::{assert_tokens, Token}; - /// # - /// assert_tokens(&0u32, &[Token::U32(0)]); - /// ``` - U32(u32), - - /// A serialized `u64`. - /// - /// ```edition2018 - /// # use serde_test::{assert_tokens, Token}; - /// # - /// assert_tokens(&0u64, &[Token::U64(0)]); - /// ``` - U64(u64), - - /// A serialized `f32`. - /// - /// ```edition2018 - /// # use serde_test::{assert_tokens, Token}; - /// # - /// assert_tokens(&0f32, &[Token::F32(0.0)]); - /// ``` - F32(f32), - - /// A serialized `f64`. - /// - /// ```edition2018 - /// # use serde_test::{assert_tokens, Token}; - /// # - /// assert_tokens(&0f64, &[Token::F64(0.0)]); - /// ``` - F64(f64), - - /// A serialized `char`. - /// - /// ```edition2018 - /// # use serde_test::{assert_tokens, Token}; - /// # - /// assert_tokens(&'\n', &[Token::Char('\n')]); - /// ``` - Char(char), - - /// A serialized `str`. - /// - /// ```edition2018 - /// # use serde_test::{assert_tokens, Token}; - /// # - /// let s = String::from("transient"); - /// assert_tokens(&s, &[Token::Str("transient")]); - /// ``` - Str(&'static str), - - /// A borrowed `str`. - /// - /// ```edition2018 - /// # use serde_test::{assert_tokens, Token}; - /// # - /// let s: &str = "borrowed"; - /// assert_tokens(&s, &[Token::BorrowedStr("borrowed")]); - /// ``` - BorrowedStr(&'static str), - - /// A serialized `String`. - /// - /// ```edition2018 - /// # use serde_test::{assert_tokens, Token}; - /// # - /// let s = String::from("owned"); - /// assert_tokens(&s, &[Token::String("owned")]); - /// ``` - String(&'static str), - - /// A serialized `[u8]` - Bytes(&'static [u8]), - - /// A borrowed `[u8]`. - BorrowedBytes(&'static [u8]), - - /// A serialized `ByteBuf` - ByteBuf(&'static [u8]), - - /// A serialized `Option` containing none. - /// - /// ```edition2018 - /// # use serde_test::{assert_tokens, Token}; - /// # - /// let opt = None::; - /// assert_tokens(&opt, &[Token::None]); - /// ``` - None, - - /// The header to a serialized `Option` containing some value. - /// - /// The tokens of the value follow after this header. - /// - /// ```edition2018 - /// # use serde_test::{assert_tokens, Token}; - /// # - /// let opt = Some('c'); - /// assert_tokens(&opt, &[ - /// Token::Some, - /// Token::Char('c'), - /// ]); - /// ``` - Some, - - /// A serialized `()`. - /// - /// ```edition2018 - /// # use serde_test::{assert_tokens, Token}; - /// # - /// assert_tokens(&(), &[Token::Unit]); - /// ``` - Unit, - - /// A serialized unit struct of the given name. - /// - /// ```edition2018 - /// # use serde::{Serialize, Deserialize}; - /// # use serde_test::{assert_tokens, Token}; - /// # - /// # fn main() { - /// #[derive(Serialize, Deserialize, PartialEq, Debug)] - /// struct X; - /// - /// assert_tokens(&X, &[Token::UnitStruct { name: "X" }]); - /// # } - /// ``` - UnitStruct { name: &'static str }, - - /// A unit variant of an enum. - /// - /// ```edition2018 - /// # use serde::{Serialize, Deserialize}; - /// # use serde_test::{assert_tokens, Token}; - /// # - /// # fn main() { - /// #[derive(Serialize, Deserialize, PartialEq, Debug)] - /// enum E { - /// A, - /// } - /// - /// let a = E::A; - /// assert_tokens(&a, &[Token::UnitVariant { name: "E", variant: "A" }]); - /// # } - /// ``` - UnitVariant { - name: &'static str, - variant: &'static str, - }, - - /// The header to a serialized newtype struct of the given name. - /// - /// After this header is the value contained in the newtype struct. - /// - /// ```edition2018 - /// # use serde::{Serialize, Deserialize}; - /// # use serde_test::{assert_tokens, Token}; - /// # - /// # fn main() { - /// #[derive(Serialize, Deserialize, PartialEq, Debug)] - /// struct N(String); - /// - /// let n = N("newtype".to_owned()); - /// assert_tokens(&n, &[ - /// Token::NewtypeStruct { name: "N" }, - /// Token::String("newtype"), - /// ]); - /// # } - /// ``` - NewtypeStruct { name: &'static str }, - - /// The header to a newtype variant of an enum. - /// - /// After this header is the value contained in the newtype variant. - /// - /// ```edition2018 - /// # use serde::{Serialize, Deserialize}; - /// # use serde_test::{assert_tokens, Token}; - /// # - /// # fn main() { - /// #[derive(Serialize, Deserialize, PartialEq, Debug)] - /// enum E { - /// B(u8), - /// } - /// - /// let b = E::B(0); - /// assert_tokens(&b, &[ - /// Token::NewtypeVariant { name: "E", variant: "B" }, - /// Token::U8(0), - /// ]); - /// # } - /// ``` - NewtypeVariant { - name: &'static str, - variant: &'static str, - }, - - /// The header to a sequence. - /// - /// After this header are the elements of the sequence, followed by - /// `SeqEnd`. - /// - /// ```edition2018 - /// # use serde_test::{assert_tokens, Token}; - /// # - /// let vec = vec!['a', 'b', 'c']; - /// assert_tokens(&vec, &[ - /// Token::Seq { len: Some(3) }, - /// Token::Char('a'), - /// Token::Char('b'), - /// Token::Char('c'), - /// Token::SeqEnd, - /// ]); - /// ``` - Seq { len: Option }, - - /// An indicator of the end of a sequence. - SeqEnd, - - /// The header to a tuple. - /// - /// After this header are the elements of the tuple, followed by `TupleEnd`. - /// - /// ```edition2018 - /// # use serde_test::{assert_tokens, Token}; - /// # - /// let tuple = ('a', 100); - /// assert_tokens(&tuple, &[ - /// Token::Tuple { len: 2 }, - /// Token::Char('a'), - /// Token::I32(100), - /// Token::TupleEnd, - /// ]); - /// ``` - Tuple { len: usize }, - - /// An indicator of the end of a tuple. - TupleEnd, - - /// The header to a tuple struct. - /// - /// After this header are the fields of the tuple struct, followed by - /// `TupleStructEnd`. - /// - /// ```edition2018 - /// # use serde::{Serialize, Deserialize}; - /// # use serde_test::{assert_tokens, Token}; - /// # - /// # fn main() { - /// #[derive(Serialize, Deserialize, PartialEq, Debug)] - /// struct T(u8, u8); - /// - /// let t = T(0, 0); - /// assert_tokens(&t, &[ - /// Token::TupleStruct { name: "T", len: 2 }, - /// Token::U8(0), - /// Token::U8(0), - /// Token::TupleStructEnd, - /// ]); - /// # } - /// ``` - TupleStruct { name: &'static str, len: usize }, - - /// An indicator of the end of a tuple struct. - TupleStructEnd, - - /// The header to a tuple variant of an enum. - /// - /// After this header are the fields of the tuple variant, followed by - /// `TupleVariantEnd`. - /// - /// ```edition2018 - /// # use serde::{Serialize, Deserialize}; - /// # use serde_test::{assert_tokens, Token}; - /// # - /// # fn main() { - /// #[derive(Serialize, Deserialize, PartialEq, Debug)] - /// enum E { - /// C(u8, u8), - /// } - /// - /// let c = E::C(0, 0); - /// assert_tokens(&c, &[ - /// Token::TupleVariant { name: "E", variant: "C", len: 2 }, - /// Token::U8(0), - /// Token::U8(0), - /// Token::TupleVariantEnd, - /// ]); - /// # } - /// ``` - TupleVariant { - name: &'static str, - variant: &'static str, - len: usize, - }, - - /// An indicator of the end of a tuple variant. - TupleVariantEnd, - - /// The header to a map. - /// - /// After this header are the entries of the map, followed by `MapEnd`. - /// - /// ```edition2018 - /// # use serde_test::{assert_tokens, Token}; - /// # - /// use std::collections::BTreeMap; - /// - /// let mut map = BTreeMap::new(); - /// map.insert('A', 65); - /// map.insert('Z', 90); - /// - /// assert_tokens(&map, &[ - /// Token::Map { len: Some(2) }, - /// Token::Char('A'), - /// Token::I32(65), - /// Token::Char('Z'), - /// Token::I32(90), - /// Token::MapEnd, - /// ]); - /// ``` - Map { len: Option }, - - /// An indicator of the end of a map. - MapEnd, - - /// The header of a struct. - /// - /// After this header are the fields of the struct, followed by `StructEnd`. - /// - /// ```edition2018 - /// # use serde::{Serialize, Deserialize}; - /// # use serde_test::{assert_tokens, Token}; - /// # - /// # fn main() { - /// #[derive(Serialize, Deserialize, PartialEq, Debug)] - /// struct S { - /// a: u8, - /// b: u8, - /// } - /// - /// let s = S { a: 0, b: 0 }; - /// assert_tokens(&s, &[ - /// Token::Struct { name: "S", len: 2 }, - /// Token::Str("a"), - /// Token::U8(0), - /// Token::Str("b"), - /// Token::U8(0), - /// Token::StructEnd, - /// ]); - /// # } - /// ``` - Struct { name: &'static str, len: usize }, - - /// An indicator of the end of a struct. - StructEnd, - - /// The header of a struct variant of an enum. - /// - /// After this header are the fields of the struct variant, followed by - /// `StructVariantEnd`. - /// - /// ```edition2018 - /// # use serde::{Serialize, Deserialize}; - /// # use serde_test::{assert_tokens, Token}; - /// # - /// # fn main() { - /// #[derive(Serialize, Deserialize, PartialEq, Debug)] - /// enum E { - /// D { d: u8 }, - /// } - /// - /// let d = E::D { d: 0 }; - /// assert_tokens(&d, &[ - /// Token::StructVariant { name: "E", variant: "D", len: 1 }, - /// Token::Str("d"), - /// Token::U8(0), - /// Token::StructVariantEnd, - /// ]); - /// # } - /// ``` - StructVariant { - name: &'static str, - variant: &'static str, - len: usize, - }, - - /// An indicator of the end of a struct variant. - StructVariantEnd, - - /// The header to an enum of the given name. - /// - /// ```edition2018 - /// # use serde::{Serialize, Deserialize}; - /// # use serde_test::{assert_tokens, Token}; - /// # - /// # fn main() { - /// #[derive(Serialize, Deserialize, PartialEq, Debug)] - /// enum E { - /// A, - /// B(u8), - /// C(u8, u8), - /// D { d: u8 }, - /// } - /// - /// let a = E::A; - /// assert_tokens(&a, &[ - /// Token::Enum { name: "E" }, - /// Token::Str("A"), - /// Token::Unit, - /// ]); - /// - /// let b = E::B(0); - /// assert_tokens(&b, &[ - /// Token::Enum { name: "E" }, - /// Token::Str("B"), - /// Token::U8(0), - /// ]); - /// - /// let c = E::C(0, 0); - /// assert_tokens(&c, &[ - /// Token::Enum { name: "E" }, - /// Token::Str("C"), - /// Token::Seq { len: Some(2) }, - /// Token::U8(0), - /// Token::U8(0), - /// Token::SeqEnd, - /// ]); - /// - /// let d = E::D { d: 0 }; - /// assert_tokens(&d, &[ - /// Token::Enum { name: "E" }, - /// Token::Str("D"), - /// Token::Map { len: Some(1) }, - /// Token::Str("d"), - /// Token::U8(0), - /// Token::MapEnd, - /// ]); - /// # } - /// ``` - Enum { name: &'static str }, -} - -impl Display for Token { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - Debug::fmt(self, formatter) - } -} diff --git a/test_suite/Cargo.toml b/test_suite/Cargo.toml index 82c95922..b7686baf 100644 --- a/test_suite/Cargo.toml +++ b/test_suite/Cargo.toml @@ -4,23 +4,18 @@ version = "0.0.0" authors = ["Erick Tryzelaar ", "David Tolnay "] edition = "2018" publish = false -build = "build.rs" [features] -expandtest = [] unstable = ["serde/unstable"] [dependencies] serde = { path = "../serde" } -[build-dependencies] -toolchain_find = "0.1" - [dev-dependencies] +automod = "1.0.1" fnv = "1.0" -macrotest = "=1.0.0" rustversion = "1.0" -serde = { path = "../serde", features = ["rc", "derive"] } +serde = { path = "../serde", features = ["rc"] } serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] } -serde_test = { path = "../serde_test" } -trybuild = { version = "1.0.49", features = ["diff"] } +serde_test = "1.0.176" +trybuild = { version = "1.0.66", features = ["diff"] } diff --git a/test_suite/build.rs b/test_suite/build.rs deleted file mode 100644 index 4ead539f..00000000 --- a/test_suite/build.rs +++ /dev/null @@ -1,29 +0,0 @@ -use std::process::{Command, ExitStatus, Stdio}; - -fn has_cargo_expand() -> bool { - let cargo_expand = if cfg!(windows) { - "cargo-expand.exe" - } else { - "cargo-expand" - }; - - Command::new(cargo_expand) - .arg("--version") - .stdin(Stdio::null()) - .stdout(Stdio::null()) - .stderr(Stdio::null()) - .status() - .as_ref() - .map(ExitStatus::success) - .unwrap_or(false) -} - -fn has_rustfmt() -> bool { - toolchain_find::find_installed_component("rustfmt").is_some() -} - -fn main() { - if cfg!(feature = "expandtest") && has_cargo_expand() && has_rustfmt() { - println!("cargo:rustc-cfg=expandtest"); - } -} diff --git a/test_suite/no_std/Cargo.toml b/test_suite/no_std/Cargo.toml index 8746960c..5bf7eb2d 100644 --- a/test_suite/no_std/Cargo.toml +++ b/test_suite/no_std/Cargo.toml @@ -1,11 +1,13 @@ [package] name = "serde_derive_tests_no_std" version = "0.0.0" +authors = ["David Tolnay "] edition = "2018" publish = false [dependencies] libc = { version = "0.2", default-features = false } -serde = { path = "../../serde", default-features = false, features = ["derive"] } +serde = { path = "../../serde", default-features = false } +serde_derive = { path = "../../serde_derive" } [workspace] diff --git a/test_suite/no_std/src/main.rs b/test_suite/no_std/src/main.rs index deb32c5f..57b3f315 100644 --- a/test_suite/no_std/src/main.rs +++ b/test_suite/no_std/src/main.rs @@ -1,3 +1,4 @@ +#![allow(internal_features)] #![feature(lang_items, start)] #![no_std] @@ -19,7 +20,7 @@ fn panic(_info: &core::panic::PanicInfo) -> ! { ////////////////////////////////////////////////////////////////////////////// -use serde::{Serialize, Deserialize}; +use serde_derive::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] struct Unit; diff --git a/test_suite/tests/compiletest.rs b/test_suite/tests/compiletest.rs index 7118b9b3..621660b0 100644 --- a/test_suite/tests/compiletest.rs +++ b/test_suite/tests/compiletest.rs @@ -1,5 +1,7 @@ #[cfg_attr(target_os = "emscripten", ignore)] #[rustversion::attr(not(nightly), ignore)] +#[cfg_attr(miri, ignore)] +#[allow(unused_attributes)] #[test] fn ui() { let t = trybuild::TestCases::new(); diff --git a/test_suite/tests/expand/de_enum.expanded.rs b/test_suite/tests/expand/de_enum.expanded.rs deleted file mode 100644 index 4ea3b838..00000000 --- a/test_suite/tests/expand/de_enum.expanded.rs +++ /dev/null @@ -1,1426 +0,0 @@ -use serde::{Deserialize, Serialize}; -enum DeEnum { - Unit, - Seq(i8, B, C, D), - Map { a: i8, b: B, c: C, d: D }, - _Unit2, - _Seq2(i8, B, C, D), - _Map2 { a: i8, b: B, c: C, d: D }, -} -#[doc(hidden)] -#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] -const _: () = { - #[allow(unused_extern_crates, clippy::useless_attribute)] - extern crate serde as _serde; - #[automatically_derived] - impl _serde::Serialize for DeEnum - where - B: _serde::Serialize, - C: _serde::Serialize, - D: _serde::Serialize, - { - fn serialize<__S>( - &self, - __serializer: __S, - ) -> _serde::__private::Result<__S::Ok, __S::Error> - where - __S: _serde::Serializer, - { - match *self { - DeEnum::Unit => { - _serde::Serializer::serialize_unit_variant(__serializer, "DeEnum", 0u32, "Unit") - } - DeEnum::Seq(ref __field0, ref __field1, ref __field2, ref __field3) => { - let mut __serde_state = match _serde::Serializer::serialize_tuple_variant( - __serializer, - "DeEnum", - 1u32, - "Seq", - 0 + 1 + 1 + 1 + 1, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeTupleVariant::serialize_field( - &mut __serde_state, - __field0, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeTupleVariant::serialize_field( - &mut __serde_state, - __field1, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeTupleVariant::serialize_field( - &mut __serde_state, - __field2, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeTupleVariant::serialize_field( - &mut __serde_state, - __field3, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - _serde::ser::SerializeTupleVariant::end(__serde_state) - } - DeEnum::Map { - ref a, - ref b, - ref c, - ref d, - } => { - let mut __serde_state = match _serde::Serializer::serialize_struct_variant( - __serializer, - "DeEnum", - 2u32, - "Map", - 0 + 1 + 1 + 1 + 1, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeStructVariant::serialize_field( - &mut __serde_state, - "a", - a, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeStructVariant::serialize_field( - &mut __serde_state, - "b", - b, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeStructVariant::serialize_field( - &mut __serde_state, - "c", - c, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeStructVariant::serialize_field( - &mut __serde_state, - "d", - d, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - _serde::ser::SerializeStructVariant::end(__serde_state) - } - DeEnum::_Unit2 => _serde::Serializer::serialize_unit_variant( - __serializer, - "DeEnum", - 3u32, - "_Unit2", - ), - DeEnum::_Seq2(ref __field0, ref __field1, ref __field2, ref __field3) => { - let mut __serde_state = match _serde::Serializer::serialize_tuple_variant( - __serializer, - "DeEnum", - 4u32, - "_Seq2", - 0 + 1 + 1 + 1 + 1, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeTupleVariant::serialize_field( - &mut __serde_state, - __field0, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeTupleVariant::serialize_field( - &mut __serde_state, - __field1, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeTupleVariant::serialize_field( - &mut __serde_state, - __field2, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeTupleVariant::serialize_field( - &mut __serde_state, - __field3, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - _serde::ser::SerializeTupleVariant::end(__serde_state) - } - DeEnum::_Map2 { - ref a, - ref b, - ref c, - ref d, - } => { - let mut __serde_state = match _serde::Serializer::serialize_struct_variant( - __serializer, - "DeEnum", - 5u32, - "_Map2", - 0 + 1 + 1 + 1 + 1, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeStructVariant::serialize_field( - &mut __serde_state, - "a", - a, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeStructVariant::serialize_field( - &mut __serde_state, - "b", - b, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeStructVariant::serialize_field( - &mut __serde_state, - "c", - c, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeStructVariant::serialize_field( - &mut __serde_state, - "d", - d, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - _serde::ser::SerializeStructVariant::end(__serde_state) - } - } - } - } -}; -#[doc(hidden)] -#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] -const _: () = { - #[allow(unused_extern_crates, clippy::useless_attribute)] - extern crate serde as _serde; - #[automatically_derived] - impl<'de, B, C, D> _serde::Deserialize<'de> for DeEnum - where - B: _serde::Deserialize<'de>, - C: _serde::Deserialize<'de>, - D: _serde::Deserialize<'de>, - { - fn deserialize<__D>(__deserializer: __D) -> _serde::__private::Result - where - __D: _serde::Deserializer<'de>, - { - #[allow(non_camel_case_types)] - enum __Field { - __field0, - __field1, - __field2, - __field3, - __field4, - __field5, - } - struct __FieldVisitor; - impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { - type Value = __Field; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result { - _serde::__private::Formatter::write_str(__formatter, "variant identifier") - } - fn visit_u64<__E>(self, __value: u64) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - 0u64 => _serde::__private::Ok(__Field::__field0), - 1u64 => _serde::__private::Ok(__Field::__field1), - 2u64 => _serde::__private::Ok(__Field::__field2), - 3u64 => _serde::__private::Ok(__Field::__field3), - 4u64 => _serde::__private::Ok(__Field::__field4), - 5u64 => _serde::__private::Ok(__Field::__field5), - _ => _serde::__private::Err(_serde::de::Error::invalid_value( - _serde::de::Unexpected::Unsigned(__value), - &"variant index 0 <= i < 6", - )), - } - } - fn visit_str<__E>( - self, - __value: &str, - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - "Unit" => _serde::__private::Ok(__Field::__field0), - "Seq" => _serde::__private::Ok(__Field::__field1), - "Map" => _serde::__private::Ok(__Field::__field2), - "_Unit2" => _serde::__private::Ok(__Field::__field3), - "_Seq2" => _serde::__private::Ok(__Field::__field4), - "_Map2" => _serde::__private::Ok(__Field::__field5), - _ => _serde::__private::Err(_serde::de::Error::unknown_variant( - __value, VARIANTS, - )), - } - } - fn visit_bytes<__E>( - self, - __value: &[u8], - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - b"Unit" => _serde::__private::Ok(__Field::__field0), - b"Seq" => _serde::__private::Ok(__Field::__field1), - b"Map" => _serde::__private::Ok(__Field::__field2), - b"_Unit2" => _serde::__private::Ok(__Field::__field3), - b"_Seq2" => _serde::__private::Ok(__Field::__field4), - b"_Map2" => _serde::__private::Ok(__Field::__field5), - _ => { - let __value = &_serde::__private::from_utf8_lossy(__value); - _serde::__private::Err(_serde::de::Error::unknown_variant( - __value, VARIANTS, - )) - } - } - } - } - impl<'de> _serde::Deserialize<'de> for __Field { - #[inline] - fn deserialize<__D>( - __deserializer: __D, - ) -> _serde::__private::Result - where - __D: _serde::Deserializer<'de>, - { - _serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor) - } - } - struct __Visitor<'de, B, C, D> - where - B: _serde::Deserialize<'de>, - C: _serde::Deserialize<'de>, - D: _serde::Deserialize<'de>, - { - marker: _serde::__private::PhantomData>, - lifetime: _serde::__private::PhantomData<&'de ()>, - } - impl<'de, B, C, D> _serde::de::Visitor<'de> for __Visitor<'de, B, C, D> - where - B: _serde::Deserialize<'de>, - C: _serde::Deserialize<'de>, - D: _serde::Deserialize<'de>, - { - type Value = DeEnum; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result { - _serde::__private::Formatter::write_str(__formatter, "enum DeEnum") - } - fn visit_enum<__A>( - self, - __data: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::EnumAccess<'de>, - { - match match _serde::de::EnumAccess::variant(__data) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - (__Field::__field0, __variant) => { - match _serde::de::VariantAccess::unit_variant(__variant) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - _serde::__private::Ok(DeEnum::Unit) - } - (__Field::__field1, __variant) => { - struct __Visitor<'de, B, C, D> - where - B: _serde::Deserialize<'de>, - C: _serde::Deserialize<'de>, - D: _serde::Deserialize<'de>, - { - marker: _serde::__private::PhantomData>, - lifetime: _serde::__private::PhantomData<&'de ()>, - } - impl<'de, B, C, D> _serde::de::Visitor<'de> for __Visitor<'de, B, C, D> - where - B: _serde::Deserialize<'de>, - C: _serde::Deserialize<'de>, - D: _serde::Deserialize<'de>, - { - type Value = DeEnum; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result - { - _serde::__private::Formatter::write_str( - __formatter, - "tuple variant DeEnum::Seq", - ) - } - #[inline] - fn visit_seq<__A>( - self, - mut __seq: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::SeqAccess<'de>, - { - let __field0 = match match _serde::de::SeqAccess::next_element::< - i8, - >( - &mut __seq - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde::__private::Err( - _serde::de::Error::invalid_length( - 0usize, - &"tuple variant DeEnum::Seq with 4 elements", - ), - ); - } - }; - let __field1 = match match _serde::de::SeqAccess::next_element::< - B, - >( - &mut __seq - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde::__private::Err( - _serde::de::Error::invalid_length( - 1usize, - &"tuple variant DeEnum::Seq with 4 elements", - ), - ); - } - }; - let __field2 = match match _serde::de::SeqAccess::next_element::< - C, - >( - &mut __seq - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde::__private::Err( - _serde::de::Error::invalid_length( - 2usize, - &"tuple variant DeEnum::Seq with 4 elements", - ), - ); - } - }; - let __field3 = match match _serde::de::SeqAccess::next_element::< - D, - >( - &mut __seq - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde::__private::Err( - _serde::de::Error::invalid_length( - 3usize, - &"tuple variant DeEnum::Seq with 4 elements", - ), - ); - } - }; - _serde::__private::Ok(DeEnum::Seq( - __field0, __field1, __field2, __field3, - )) - } - } - _serde::de::VariantAccess::tuple_variant( - __variant, - 4usize, - __Visitor { - marker: _serde::__private::PhantomData::>, - lifetime: _serde::__private::PhantomData, - }, - ) - } - (__Field::__field2, __variant) => { - #[allow(non_camel_case_types)] - enum __Field { - __field0, - __field1, - __field2, - __field3, - __ignore, - } - struct __FieldVisitor; - impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { - type Value = __Field; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result - { - _serde::__private::Formatter::write_str( - __formatter, - "field identifier", - ) - } - fn visit_u64<__E>( - self, - __value: u64, - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - 0u64 => _serde::__private::Ok(__Field::__field0), - 1u64 => _serde::__private::Ok(__Field::__field1), - 2u64 => _serde::__private::Ok(__Field::__field2), - 3u64 => _serde::__private::Ok(__Field::__field3), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - fn visit_str<__E>( - self, - __value: &str, - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - "a" => _serde::__private::Ok(__Field::__field0), - "b" => _serde::__private::Ok(__Field::__field1), - "c" => _serde::__private::Ok(__Field::__field2), - "d" => _serde::__private::Ok(__Field::__field3), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - fn visit_bytes<__E>( - self, - __value: &[u8], - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - b"a" => _serde::__private::Ok(__Field::__field0), - b"b" => _serde::__private::Ok(__Field::__field1), - b"c" => _serde::__private::Ok(__Field::__field2), - b"d" => _serde::__private::Ok(__Field::__field3), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - } - impl<'de> _serde::Deserialize<'de> for __Field { - #[inline] - fn deserialize<__D>( - __deserializer: __D, - ) -> _serde::__private::Result - where - __D: _serde::Deserializer<'de>, - { - _serde::Deserializer::deserialize_identifier( - __deserializer, - __FieldVisitor, - ) - } - } - struct __Visitor<'de, B, C, D> - where - B: _serde::Deserialize<'de>, - C: _serde::Deserialize<'de>, - D: _serde::Deserialize<'de>, - { - marker: _serde::__private::PhantomData>, - lifetime: _serde::__private::PhantomData<&'de ()>, - } - impl<'de, B, C, D> _serde::de::Visitor<'de> for __Visitor<'de, B, C, D> - where - B: _serde::Deserialize<'de>, - C: _serde::Deserialize<'de>, - D: _serde::Deserialize<'de>, - { - type Value = DeEnum; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result - { - _serde::__private::Formatter::write_str( - __formatter, - "struct variant DeEnum::Map", - ) - } - #[inline] - fn visit_seq<__A>( - self, - mut __seq: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::SeqAccess<'de>, - { - let __field0 = match match _serde::de::SeqAccess::next_element::< - i8, - >( - &mut __seq - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde::__private::Err( - _serde::de::Error::invalid_length( - 0usize, - &"struct variant DeEnum::Map with 4 elements", - ), - ); - } - }; - let __field1 = match match _serde::de::SeqAccess::next_element::< - B, - >( - &mut __seq - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde::__private::Err( - _serde::de::Error::invalid_length( - 1usize, - &"struct variant DeEnum::Map with 4 elements", - ), - ); - } - }; - let __field2 = match match _serde::de::SeqAccess::next_element::< - C, - >( - &mut __seq - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde::__private::Err( - _serde::de::Error::invalid_length( - 2usize, - &"struct variant DeEnum::Map with 4 elements", - ), - ); - } - }; - let __field3 = match match _serde::de::SeqAccess::next_element::< - D, - >( - &mut __seq - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde::__private::Err( - _serde::de::Error::invalid_length( - 3usize, - &"struct variant DeEnum::Map with 4 elements", - ), - ); - } - }; - _serde::__private::Ok(DeEnum::Map { - a: __field0, - b: __field1, - c: __field2, - d: __field3, - }) - } - #[inline] - fn visit_map<__A>( - self, - mut __map: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::MapAccess<'de>, - { - let mut __field0: _serde::__private::Option = - _serde::__private::None; - let mut __field1: _serde::__private::Option = - _serde::__private::None; - let mut __field2: _serde::__private::Option = - _serde::__private::None; - let mut __field3: _serde::__private::Option = - _serde::__private::None; - while let _serde::__private::Some(__key) = - match _serde::de::MapAccess::next_key::<__Field>(&mut __map) - { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } - { - match __key { - __Field::__field0 => { - if _serde::__private::Option::is_some(&__field0) { - return _serde :: __private :: Err (< __A :: Error as _serde :: de :: Error > :: duplicate_field ("a")) ; - } - __field0 = _serde::__private::Some( - match _serde::de::MapAccess::next_value::( - &mut __map, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }, - ); - } - __Field::__field1 => { - if _serde::__private::Option::is_some(&__field1) { - return _serde :: __private :: Err (< __A :: Error as _serde :: de :: Error > :: duplicate_field ("b")) ; - } - __field1 = _serde::__private::Some( - match _serde::de::MapAccess::next_value::( - &mut __map, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }, - ); - } - __Field::__field2 => { - if _serde::__private::Option::is_some(&__field2) { - return _serde :: __private :: Err (< __A :: Error as _serde :: de :: Error > :: duplicate_field ("c")) ; - } - __field2 = _serde::__private::Some( - match _serde::de::MapAccess::next_value::( - &mut __map, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }, - ); - } - __Field::__field3 => { - if _serde::__private::Option::is_some(&__field3) { - return _serde :: __private :: Err (< __A :: Error as _serde :: de :: Error > :: duplicate_field ("d")) ; - } - __field3 = _serde::__private::Some( - match _serde::de::MapAccess::next_value::( - &mut __map, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }, - ); - } - _ => { - let _ = match _serde::de::MapAccess::next_value::< - _serde::de::IgnoredAny, - >( - &mut __map - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - } - } - } - let __field0 = match __field0 { - _serde::__private::Some(__field0) => __field0, - _serde::__private::None => { - match _serde::__private::de::missing_field("a") { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } - } - }; - let __field1 = match __field1 { - _serde::__private::Some(__field1) => __field1, - _serde::__private::None => { - match _serde::__private::de::missing_field("b") { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } - } - }; - let __field2 = match __field2 { - _serde::__private::Some(__field2) => __field2, - _serde::__private::None => { - match _serde::__private::de::missing_field("c") { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } - } - }; - let __field3 = match __field3 { - _serde::__private::Some(__field3) => __field3, - _serde::__private::None => { - match _serde::__private::de::missing_field("d") { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } - } - }; - _serde::__private::Ok(DeEnum::Map { - a: __field0, - b: __field1, - c: __field2, - d: __field3, - }) - } - } - const FIELDS: &'static [&'static str] = &["a", "b", "c", "d"]; - _serde::de::VariantAccess::struct_variant( - __variant, - FIELDS, - __Visitor { - marker: _serde::__private::PhantomData::>, - lifetime: _serde::__private::PhantomData, - }, - ) - } - (__Field::__field3, __variant) => { - match _serde::de::VariantAccess::unit_variant(__variant) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - _serde::__private::Ok(DeEnum::_Unit2) - } - (__Field::__field4, __variant) => { - struct __Visitor<'de, B, C, D> - where - B: _serde::Deserialize<'de>, - C: _serde::Deserialize<'de>, - D: _serde::Deserialize<'de>, - { - marker: _serde::__private::PhantomData>, - lifetime: _serde::__private::PhantomData<&'de ()>, - } - impl<'de, B, C, D> _serde::de::Visitor<'de> for __Visitor<'de, B, C, D> - where - B: _serde::Deserialize<'de>, - C: _serde::Deserialize<'de>, - D: _serde::Deserialize<'de>, - { - type Value = DeEnum; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result - { - _serde::__private::Formatter::write_str( - __formatter, - "tuple variant DeEnum::_Seq2", - ) - } - #[inline] - fn visit_seq<__A>( - self, - mut __seq: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::SeqAccess<'de>, - { - let __field0 = match match _serde::de::SeqAccess::next_element::< - i8, - >( - &mut __seq - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde::__private::Err( - _serde::de::Error::invalid_length( - 0usize, - &"tuple variant DeEnum::_Seq2 with 4 elements", - ), - ); - } - }; - let __field1 = match match _serde::de::SeqAccess::next_element::< - B, - >( - &mut __seq - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde::__private::Err( - _serde::de::Error::invalid_length( - 1usize, - &"tuple variant DeEnum::_Seq2 with 4 elements", - ), - ); - } - }; - let __field2 = match match _serde::de::SeqAccess::next_element::< - C, - >( - &mut __seq - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde::__private::Err( - _serde::de::Error::invalid_length( - 2usize, - &"tuple variant DeEnum::_Seq2 with 4 elements", - ), - ); - } - }; - let __field3 = match match _serde::de::SeqAccess::next_element::< - D, - >( - &mut __seq - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde::__private::Err( - _serde::de::Error::invalid_length( - 3usize, - &"tuple variant DeEnum::_Seq2 with 4 elements", - ), - ); - } - }; - _serde::__private::Ok(DeEnum::_Seq2( - __field0, __field1, __field2, __field3, - )) - } - } - _serde::de::VariantAccess::tuple_variant( - __variant, - 4usize, - __Visitor { - marker: _serde::__private::PhantomData::>, - lifetime: _serde::__private::PhantomData, - }, - ) - } - (__Field::__field5, __variant) => { - #[allow(non_camel_case_types)] - enum __Field { - __field0, - __field1, - __field2, - __field3, - __ignore, - } - struct __FieldVisitor; - impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { - type Value = __Field; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result - { - _serde::__private::Formatter::write_str( - __formatter, - "field identifier", - ) - } - fn visit_u64<__E>( - self, - __value: u64, - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - 0u64 => _serde::__private::Ok(__Field::__field0), - 1u64 => _serde::__private::Ok(__Field::__field1), - 2u64 => _serde::__private::Ok(__Field::__field2), - 3u64 => _serde::__private::Ok(__Field::__field3), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - fn visit_str<__E>( - self, - __value: &str, - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - "a" => _serde::__private::Ok(__Field::__field0), - "b" => _serde::__private::Ok(__Field::__field1), - "c" => _serde::__private::Ok(__Field::__field2), - "d" => _serde::__private::Ok(__Field::__field3), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - fn visit_bytes<__E>( - self, - __value: &[u8], - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - b"a" => _serde::__private::Ok(__Field::__field0), - b"b" => _serde::__private::Ok(__Field::__field1), - b"c" => _serde::__private::Ok(__Field::__field2), - b"d" => _serde::__private::Ok(__Field::__field3), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - } - impl<'de> _serde::Deserialize<'de> for __Field { - #[inline] - fn deserialize<__D>( - __deserializer: __D, - ) -> _serde::__private::Result - where - __D: _serde::Deserializer<'de>, - { - _serde::Deserializer::deserialize_identifier( - __deserializer, - __FieldVisitor, - ) - } - } - struct __Visitor<'de, B, C, D> - where - B: _serde::Deserialize<'de>, - C: _serde::Deserialize<'de>, - D: _serde::Deserialize<'de>, - { - marker: _serde::__private::PhantomData>, - lifetime: _serde::__private::PhantomData<&'de ()>, - } - impl<'de, B, C, D> _serde::de::Visitor<'de> for __Visitor<'de, B, C, D> - where - B: _serde::Deserialize<'de>, - C: _serde::Deserialize<'de>, - D: _serde::Deserialize<'de>, - { - type Value = DeEnum; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result - { - _serde::__private::Formatter::write_str( - __formatter, - "struct variant DeEnum::_Map2", - ) - } - #[inline] - fn visit_seq<__A>( - self, - mut __seq: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::SeqAccess<'de>, - { - let __field0 = match match _serde::de::SeqAccess::next_element::< - i8, - >( - &mut __seq - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde::__private::Err( - _serde::de::Error::invalid_length( - 0usize, - &"struct variant DeEnum::_Map2 with 4 elements", - ), - ); - } - }; - let __field1 = match match _serde::de::SeqAccess::next_element::< - B, - >( - &mut __seq - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde::__private::Err( - _serde::de::Error::invalid_length( - 1usize, - &"struct variant DeEnum::_Map2 with 4 elements", - ), - ); - } - }; - let __field2 = match match _serde::de::SeqAccess::next_element::< - C, - >( - &mut __seq - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde::__private::Err( - _serde::de::Error::invalid_length( - 2usize, - &"struct variant DeEnum::_Map2 with 4 elements", - ), - ); - } - }; - let __field3 = match match _serde::de::SeqAccess::next_element::< - D, - >( - &mut __seq - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde::__private::Err( - _serde::de::Error::invalid_length( - 3usize, - &"struct variant DeEnum::_Map2 with 4 elements", - ), - ); - } - }; - _serde::__private::Ok(DeEnum::_Map2 { - a: __field0, - b: __field1, - c: __field2, - d: __field3, - }) - } - #[inline] - fn visit_map<__A>( - self, - mut __map: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::MapAccess<'de>, - { - let mut __field0: _serde::__private::Option = - _serde::__private::None; - let mut __field1: _serde::__private::Option = - _serde::__private::None; - let mut __field2: _serde::__private::Option = - _serde::__private::None; - let mut __field3: _serde::__private::Option = - _serde::__private::None; - while let _serde::__private::Some(__key) = - match _serde::de::MapAccess::next_key::<__Field>(&mut __map) - { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } - { - match __key { - __Field::__field0 => { - if _serde::__private::Option::is_some(&__field0) { - return _serde :: __private :: Err (< __A :: Error as _serde :: de :: Error > :: duplicate_field ("a")) ; - } - __field0 = _serde::__private::Some( - match _serde::de::MapAccess::next_value::( - &mut __map, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }, - ); - } - __Field::__field1 => { - if _serde::__private::Option::is_some(&__field1) { - return _serde :: __private :: Err (< __A :: Error as _serde :: de :: Error > :: duplicate_field ("b")) ; - } - __field1 = _serde::__private::Some( - match _serde::de::MapAccess::next_value::( - &mut __map, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }, - ); - } - __Field::__field2 => { - if _serde::__private::Option::is_some(&__field2) { - return _serde :: __private :: Err (< __A :: Error as _serde :: de :: Error > :: duplicate_field ("c")) ; - } - __field2 = _serde::__private::Some( - match _serde::de::MapAccess::next_value::( - &mut __map, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }, - ); - } - __Field::__field3 => { - if _serde::__private::Option::is_some(&__field3) { - return _serde :: __private :: Err (< __A :: Error as _serde :: de :: Error > :: duplicate_field ("d")) ; - } - __field3 = _serde::__private::Some( - match _serde::de::MapAccess::next_value::( - &mut __map, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }, - ); - } - _ => { - let _ = match _serde::de::MapAccess::next_value::< - _serde::de::IgnoredAny, - >( - &mut __map - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - } - } - } - let __field0 = match __field0 { - _serde::__private::Some(__field0) => __field0, - _serde::__private::None => { - match _serde::__private::de::missing_field("a") { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } - } - }; - let __field1 = match __field1 { - _serde::__private::Some(__field1) => __field1, - _serde::__private::None => { - match _serde::__private::de::missing_field("b") { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } - } - }; - let __field2 = match __field2 { - _serde::__private::Some(__field2) => __field2, - _serde::__private::None => { - match _serde::__private::de::missing_field("c") { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } - } - }; - let __field3 = match __field3 { - _serde::__private::Some(__field3) => __field3, - _serde::__private::None => { - match _serde::__private::de::missing_field("d") { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } - } - }; - _serde::__private::Ok(DeEnum::_Map2 { - a: __field0, - b: __field1, - c: __field2, - d: __field3, - }) - } - } - const FIELDS: &'static [&'static str] = &["a", "b", "c", "d"]; - _serde::de::VariantAccess::struct_variant( - __variant, - FIELDS, - __Visitor { - marker: _serde::__private::PhantomData::>, - lifetime: _serde::__private::PhantomData, - }, - ) - } - } - } - } - const VARIANTS: &'static [&'static str] = - &["Unit", "Seq", "Map", "_Unit2", "_Seq2", "_Map2"]; - _serde::Deserializer::deserialize_enum( - __deserializer, - "DeEnum", - VARIANTS, - __Visitor { - marker: _serde::__private::PhantomData::>, - lifetime: _serde::__private::PhantomData, - }, - ) - } - } -}; diff --git a/test_suite/tests/expand/de_enum.rs b/test_suite/tests/expand/de_enum.rs deleted file mode 100644 index ac0c49b5..00000000 --- a/test_suite/tests/expand/de_enum.rs +++ /dev/null @@ -1,13 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Serialize, Deserialize)] -enum DeEnum { - Unit, - Seq(i8, B, C, D), - Map { a: i8, b: B, c: C, d: D }, - - // Make sure we can support more than one variant. - _Unit2, - _Seq2(i8, B, C, D), - _Map2 { a: i8, b: B, c: C, d: D }, -} diff --git a/test_suite/tests/expand/default_ty_param.expanded.rs b/test_suite/tests/expand/default_ty_param.expanded.rs deleted file mode 100644 index 829e65e8..00000000 --- a/test_suite/tests/expand/default_ty_param.expanded.rs +++ /dev/null @@ -1,410 +0,0 @@ -use serde::{Deserialize, Serialize}; -trait AssociatedType { - type X; -} -impl AssociatedType for i32 { - type X = i32; -} -struct DefaultTyParam = i32> { - phantom: PhantomData, -} -#[doc(hidden)] -#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] -const _: () = { - #[allow(unused_extern_crates, clippy::useless_attribute)] - extern crate serde as _serde; - #[automatically_derived] - impl> _serde::Serialize for DefaultTyParam { - fn serialize<__S>( - &self, - __serializer: __S, - ) -> _serde::__private::Result<__S::Ok, __S::Error> - where - __S: _serde::Serializer, - { - let mut __serde_state = match _serde::Serializer::serialize_struct( - __serializer, - "DefaultTyParam", - false as usize + 1, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeStruct::serialize_field( - &mut __serde_state, - "phantom", - &self.phantom, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - _serde::ser::SerializeStruct::end(__serde_state) - } - } -}; -#[doc(hidden)] -#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] -const _: () = { - #[allow(unused_extern_crates, clippy::useless_attribute)] - extern crate serde as _serde; - #[automatically_derived] - impl<'de, T: AssociatedType> _serde::Deserialize<'de> for DefaultTyParam { - fn deserialize<__D>(__deserializer: __D) -> _serde::__private::Result - where - __D: _serde::Deserializer<'de>, - { - #[allow(non_camel_case_types)] - enum __Field { - __field0, - __ignore, - } - struct __FieldVisitor; - impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { - type Value = __Field; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result { - _serde::__private::Formatter::write_str(__formatter, "field identifier") - } - fn visit_u64<__E>(self, __value: u64) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - 0u64 => _serde::__private::Ok(__Field::__field0), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - fn visit_str<__E>( - self, - __value: &str, - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - "phantom" => _serde::__private::Ok(__Field::__field0), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - fn visit_bytes<__E>( - self, - __value: &[u8], - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - b"phantom" => _serde::__private::Ok(__Field::__field0), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - } - impl<'de> _serde::Deserialize<'de> for __Field { - #[inline] - fn deserialize<__D>( - __deserializer: __D, - ) -> _serde::__private::Result - where - __D: _serde::Deserializer<'de>, - { - _serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor) - } - } - struct __Visitor<'de, T: AssociatedType> { - marker: _serde::__private::PhantomData>, - lifetime: _serde::__private::PhantomData<&'de ()>, - } - impl<'de, T: AssociatedType> _serde::de::Visitor<'de> for __Visitor<'de, T> { - type Value = DefaultTyParam; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result { - _serde::__private::Formatter::write_str(__formatter, "struct DefaultTyParam") - } - #[inline] - fn visit_seq<__A>( - self, - mut __seq: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::SeqAccess<'de>, - { - let __field0 = match match _serde::de::SeqAccess::next_element::>( - &mut __seq, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde::__private::Err(_serde::de::Error::invalid_length( - 0usize, - &"struct DefaultTyParam with 1 element", - )); - } - }; - _serde::__private::Ok(DefaultTyParam { phantom: __field0 }) - } - #[inline] - fn visit_map<__A>( - self, - mut __map: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::MapAccess<'de>, - { - let mut __field0: _serde::__private::Option> = - _serde::__private::None; - while let _serde::__private::Some(__key) = - match _serde::de::MapAccess::next_key::<__Field>(&mut __map) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } - { - match __key { - __Field::__field0 => { - if _serde::__private::Option::is_some(&__field0) { - return _serde::__private::Err( - <__A::Error as _serde::de::Error>::duplicate_field( - "phantom", - ), - ); - } - __field0 = _serde::__private::Some( - match _serde::de::MapAccess::next_value::>( - &mut __map, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }, - ); - } - _ => { - let _ = match _serde::de::MapAccess::next_value::< - _serde::de::IgnoredAny, - >(&mut __map) - { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - } - } - } - let __field0 = match __field0 { - _serde::__private::Some(__field0) => __field0, - _serde::__private::None => { - match _serde::__private::de::missing_field("phantom") { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } - } - }; - _serde::__private::Ok(DefaultTyParam { phantom: __field0 }) - } - } - const FIELDS: &'static [&'static str] = &["phantom"]; - _serde::Deserializer::deserialize_struct( - __deserializer, - "DefaultTyParam", - FIELDS, - __Visitor { - marker: _serde::__private::PhantomData::>, - lifetime: _serde::__private::PhantomData, - }, - ) - } - fn deserialize_in_place<__D>( - __deserializer: __D, - __place: &mut Self, - ) -> _serde::__private::Result<(), __D::Error> - where - __D: _serde::Deserializer<'de>, - { - #[allow(non_camel_case_types)] - enum __Field { - __field0, - __ignore, - } - struct __FieldVisitor; - impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { - type Value = __Field; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result { - _serde::__private::Formatter::write_str(__formatter, "field identifier") - } - fn visit_u64<__E>(self, __value: u64) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - 0u64 => _serde::__private::Ok(__Field::__field0), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - fn visit_str<__E>( - self, - __value: &str, - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - "phantom" => _serde::__private::Ok(__Field::__field0), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - fn visit_bytes<__E>( - self, - __value: &[u8], - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - b"phantom" => _serde::__private::Ok(__Field::__field0), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - } - impl<'de> _serde::Deserialize<'de> for __Field { - #[inline] - fn deserialize<__D>( - __deserializer: __D, - ) -> _serde::__private::Result - where - __D: _serde::Deserializer<'de>, - { - _serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor) - } - } - struct __Visitor<'de, 'place, T: AssociatedType + 'place> { - place: &'place mut DefaultTyParam, - lifetime: _serde::__private::PhantomData<&'de ()>, - } - impl<'de, 'place, T: AssociatedType + 'place> _serde::de::Visitor<'de> - for __Visitor<'de, 'place, T> - { - type Value = (); - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result { - _serde::__private::Formatter::write_str(__formatter, "struct DefaultTyParam") - } - #[inline] - fn visit_seq<__A>( - self, - mut __seq: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::SeqAccess<'de>, - { - if let _serde::__private::None = match _serde::de::SeqAccess::next_element_seed( - &mut __seq, - _serde::__private::de::InPlaceSeed(&mut self.place.phantom), - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - return _serde::__private::Err(_serde::de::Error::invalid_length( - 0usize, - &"struct DefaultTyParam with 1 element", - )); - } - _serde::__private::Ok(()) - } - #[inline] - fn visit_map<__A>( - self, - mut __map: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::MapAccess<'de>, - { - let mut __field0: bool = false; - while let _serde::__private::Some(__key) = - match _serde::de::MapAccess::next_key::<__Field>(&mut __map) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } - { - match __key { - __Field::__field0 => { - if __field0 { - return _serde::__private::Err( - <__A::Error as _serde::de::Error>::duplicate_field( - "phantom", - ), - ); - } - match _serde::de::MapAccess::next_value_seed( - &mut __map, - _serde::__private::de::InPlaceSeed(&mut self.place.phantom), - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - __field0 = true; - } - _ => { - let _ = match _serde::de::MapAccess::next_value::< - _serde::de::IgnoredAny, - >(&mut __map) - { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - } - } - } - if !__field0 { - self.place.phantom = match _serde::__private::de::missing_field("phantom") { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - }; - _serde::__private::Ok(()) - } - } - const FIELDS: &'static [&'static str] = &["phantom"]; - _serde::Deserializer::deserialize_struct( - __deserializer, - "DefaultTyParam", - FIELDS, - __Visitor { - place: __place, - lifetime: _serde::__private::PhantomData, - }, - ) - } - } -}; diff --git a/test_suite/tests/expand/default_ty_param.rs b/test_suite/tests/expand/default_ty_param.rs deleted file mode 100644 index 86ae9dd3..00000000 --- a/test_suite/tests/expand/default_ty_param.rs +++ /dev/null @@ -1,14 +0,0 @@ -use serde::{Deserialize, Serialize}; - -trait AssociatedType { - type X; -} - -impl AssociatedType for i32 { - type X = i32; -} - -#[derive(Serialize, Deserialize)] -struct DefaultTyParam = i32> { - phantom: PhantomData, -} diff --git a/test_suite/tests/expand/generic_enum.expanded.rs b/test_suite/tests/expand/generic_enum.expanded.rs deleted file mode 100644 index a4ad3109..00000000 --- a/test_suite/tests/expand/generic_enum.expanded.rs +++ /dev/null @@ -1,590 +0,0 @@ -use serde::{Deserialize, Serialize}; -pub enum GenericEnum { - Unit, - NewType(T), - Seq(T, U), - Map { x: T, y: U }, -} -#[doc(hidden)] -#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] -const _: () = { - #[allow(unused_extern_crates, clippy::useless_attribute)] - extern crate serde as _serde; - #[automatically_derived] - impl _serde::Serialize for GenericEnum - where - T: _serde::Serialize, - U: _serde::Serialize, - { - fn serialize<__S>( - &self, - __serializer: __S, - ) -> _serde::__private::Result<__S::Ok, __S::Error> - where - __S: _serde::Serializer, - { - match *self { - GenericEnum::Unit => _serde::Serializer::serialize_unit_variant( - __serializer, - "GenericEnum", - 0u32, - "Unit", - ), - GenericEnum::NewType(ref __field0) => { - _serde::Serializer::serialize_newtype_variant( - __serializer, - "GenericEnum", - 1u32, - "NewType", - __field0, - ) - } - GenericEnum::Seq(ref __field0, ref __field1) => { - let mut __serde_state = match _serde::Serializer::serialize_tuple_variant( - __serializer, - "GenericEnum", - 2u32, - "Seq", - 0 + 1 + 1, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeTupleVariant::serialize_field( - &mut __serde_state, - __field0, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeTupleVariant::serialize_field( - &mut __serde_state, - __field1, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - _serde::ser::SerializeTupleVariant::end(__serde_state) - } - GenericEnum::Map { ref x, ref y } => { - let mut __serde_state = match _serde::Serializer::serialize_struct_variant( - __serializer, - "GenericEnum", - 3u32, - "Map", - 0 + 1 + 1, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeStructVariant::serialize_field( - &mut __serde_state, - "x", - x, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeStructVariant::serialize_field( - &mut __serde_state, - "y", - y, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - _serde::ser::SerializeStructVariant::end(__serde_state) - } - } - } - } -}; -#[doc(hidden)] -#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] -const _: () = { - #[allow(unused_extern_crates, clippy::useless_attribute)] - extern crate serde as _serde; - #[automatically_derived] - impl<'de, T, U> _serde::Deserialize<'de> for GenericEnum - where - T: _serde::Deserialize<'de>, - U: _serde::Deserialize<'de>, - { - fn deserialize<__D>(__deserializer: __D) -> _serde::__private::Result - where - __D: _serde::Deserializer<'de>, - { - #[allow(non_camel_case_types)] - enum __Field { - __field0, - __field1, - __field2, - __field3, - } - struct __FieldVisitor; - impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { - type Value = __Field; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result { - _serde::__private::Formatter::write_str(__formatter, "variant identifier") - } - fn visit_u64<__E>(self, __value: u64) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - 0u64 => _serde::__private::Ok(__Field::__field0), - 1u64 => _serde::__private::Ok(__Field::__field1), - 2u64 => _serde::__private::Ok(__Field::__field2), - 3u64 => _serde::__private::Ok(__Field::__field3), - _ => _serde::__private::Err(_serde::de::Error::invalid_value( - _serde::de::Unexpected::Unsigned(__value), - &"variant index 0 <= i < 4", - )), - } - } - fn visit_str<__E>( - self, - __value: &str, - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - "Unit" => _serde::__private::Ok(__Field::__field0), - "NewType" => _serde::__private::Ok(__Field::__field1), - "Seq" => _serde::__private::Ok(__Field::__field2), - "Map" => _serde::__private::Ok(__Field::__field3), - _ => _serde::__private::Err(_serde::de::Error::unknown_variant( - __value, VARIANTS, - )), - } - } - fn visit_bytes<__E>( - self, - __value: &[u8], - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - b"Unit" => _serde::__private::Ok(__Field::__field0), - b"NewType" => _serde::__private::Ok(__Field::__field1), - b"Seq" => _serde::__private::Ok(__Field::__field2), - b"Map" => _serde::__private::Ok(__Field::__field3), - _ => { - let __value = &_serde::__private::from_utf8_lossy(__value); - _serde::__private::Err(_serde::de::Error::unknown_variant( - __value, VARIANTS, - )) - } - } - } - } - impl<'de> _serde::Deserialize<'de> for __Field { - #[inline] - fn deserialize<__D>( - __deserializer: __D, - ) -> _serde::__private::Result - where - __D: _serde::Deserializer<'de>, - { - _serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor) - } - } - struct __Visitor<'de, T, U> - where - T: _serde::Deserialize<'de>, - U: _serde::Deserialize<'de>, - { - marker: _serde::__private::PhantomData>, - lifetime: _serde::__private::PhantomData<&'de ()>, - } - impl<'de, T, U> _serde::de::Visitor<'de> for __Visitor<'de, T, U> - where - T: _serde::Deserialize<'de>, - U: _serde::Deserialize<'de>, - { - type Value = GenericEnum; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result { - _serde::__private::Formatter::write_str(__formatter, "enum GenericEnum") - } - fn visit_enum<__A>( - self, - __data: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::EnumAccess<'de>, - { - match match _serde::de::EnumAccess::variant(__data) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - (__Field::__field0, __variant) => { - match _serde::de::VariantAccess::unit_variant(__variant) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - _serde::__private::Ok(GenericEnum::Unit) - } - (__Field::__field1, __variant) => _serde::__private::Result::map( - _serde::de::VariantAccess::newtype_variant::(__variant), - GenericEnum::NewType, - ), - (__Field::__field2, __variant) => { - struct __Visitor<'de, T, U> - where - T: _serde::Deserialize<'de>, - U: _serde::Deserialize<'de>, - { - marker: _serde::__private::PhantomData>, - lifetime: _serde::__private::PhantomData<&'de ()>, - } - impl<'de, T, U> _serde::de::Visitor<'de> for __Visitor<'de, T, U> - where - T: _serde::Deserialize<'de>, - U: _serde::Deserialize<'de>, - { - type Value = GenericEnum; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result - { - _serde::__private::Formatter::write_str( - __formatter, - "tuple variant GenericEnum::Seq", - ) - } - #[inline] - fn visit_seq<__A>( - self, - mut __seq: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::SeqAccess<'de>, - { - let __field0 = match match _serde::de::SeqAccess::next_element::< - T, - >( - &mut __seq - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde :: __private :: Err (_serde :: de :: Error :: invalid_length (0usize , & "tuple variant GenericEnum::Seq with 2 elements")) ; - } - }; - let __field1 = match match _serde::de::SeqAccess::next_element::< - U, - >( - &mut __seq - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde :: __private :: Err (_serde :: de :: Error :: invalid_length (1usize , & "tuple variant GenericEnum::Seq with 2 elements")) ; - } - }; - _serde::__private::Ok(GenericEnum::Seq(__field0, __field1)) - } - } - _serde::de::VariantAccess::tuple_variant( - __variant, - 2usize, - __Visitor { - marker: _serde::__private::PhantomData::>, - lifetime: _serde::__private::PhantomData, - }, - ) - } - (__Field::__field3, __variant) => { - #[allow(non_camel_case_types)] - enum __Field { - __field0, - __field1, - __ignore, - } - struct __FieldVisitor; - impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { - type Value = __Field; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result - { - _serde::__private::Formatter::write_str( - __formatter, - "field identifier", - ) - } - fn visit_u64<__E>( - self, - __value: u64, - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - 0u64 => _serde::__private::Ok(__Field::__field0), - 1u64 => _serde::__private::Ok(__Field::__field1), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - fn visit_str<__E>( - self, - __value: &str, - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - "x" => _serde::__private::Ok(__Field::__field0), - "y" => _serde::__private::Ok(__Field::__field1), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - fn visit_bytes<__E>( - self, - __value: &[u8], - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - b"x" => _serde::__private::Ok(__Field::__field0), - b"y" => _serde::__private::Ok(__Field::__field1), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - } - impl<'de> _serde::Deserialize<'de> for __Field { - #[inline] - fn deserialize<__D>( - __deserializer: __D, - ) -> _serde::__private::Result - where - __D: _serde::Deserializer<'de>, - { - _serde::Deserializer::deserialize_identifier( - __deserializer, - __FieldVisitor, - ) - } - } - struct __Visitor<'de, T, U> - where - T: _serde::Deserialize<'de>, - U: _serde::Deserialize<'de>, - { - marker: _serde::__private::PhantomData>, - lifetime: _serde::__private::PhantomData<&'de ()>, - } - impl<'de, T, U> _serde::de::Visitor<'de> for __Visitor<'de, T, U> - where - T: _serde::Deserialize<'de>, - U: _serde::Deserialize<'de>, - { - type Value = GenericEnum; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result - { - _serde::__private::Formatter::write_str( - __formatter, - "struct variant GenericEnum::Map", - ) - } - #[inline] - fn visit_seq<__A>( - self, - mut __seq: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::SeqAccess<'de>, - { - let __field0 = match match _serde::de::SeqAccess::next_element::< - T, - >( - &mut __seq - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde :: __private :: Err (_serde :: de :: Error :: invalid_length (0usize , & "struct variant GenericEnum::Map with 2 elements")) ; - } - }; - let __field1 = match match _serde::de::SeqAccess::next_element::< - U, - >( - &mut __seq - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde :: __private :: Err (_serde :: de :: Error :: invalid_length (1usize , & "struct variant GenericEnum::Map with 2 elements")) ; - } - }; - _serde::__private::Ok(GenericEnum::Map { - x: __field0, - y: __field1, - }) - } - #[inline] - fn visit_map<__A>( - self, - mut __map: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::MapAccess<'de>, - { - let mut __field0: _serde::__private::Option = - _serde::__private::None; - let mut __field1: _serde::__private::Option = - _serde::__private::None; - while let _serde::__private::Some(__key) = - match _serde::de::MapAccess::next_key::<__Field>(&mut __map) - { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } - { - match __key { - __Field::__field0 => { - if _serde::__private::Option::is_some(&__field0) { - return _serde :: __private :: Err (< __A :: Error as _serde :: de :: Error > :: duplicate_field ("x")) ; - } - __field0 = _serde::__private::Some( - match _serde::de::MapAccess::next_value::( - &mut __map, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }, - ); - } - __Field::__field1 => { - if _serde::__private::Option::is_some(&__field1) { - return _serde :: __private :: Err (< __A :: Error as _serde :: de :: Error > :: duplicate_field ("y")) ; - } - __field1 = _serde::__private::Some( - match _serde::de::MapAccess::next_value::( - &mut __map, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }, - ); - } - _ => { - let _ = match _serde::de::MapAccess::next_value::< - _serde::de::IgnoredAny, - >( - &mut __map - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - } - } - } - let __field0 = match __field0 { - _serde::__private::Some(__field0) => __field0, - _serde::__private::None => { - match _serde::__private::de::missing_field("x") { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } - } - }; - let __field1 = match __field1 { - _serde::__private::Some(__field1) => __field1, - _serde::__private::None => { - match _serde::__private::de::missing_field("y") { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } - } - }; - _serde::__private::Ok(GenericEnum::Map { - x: __field0, - y: __field1, - }) - } - } - const FIELDS: &'static [&'static str] = &["x", "y"]; - _serde::de::VariantAccess::struct_variant( - __variant, - FIELDS, - __Visitor { - marker: _serde::__private::PhantomData::>, - lifetime: _serde::__private::PhantomData, - }, - ) - } - } - } - } - const VARIANTS: &'static [&'static str] = &["Unit", "NewType", "Seq", "Map"]; - _serde::Deserializer::deserialize_enum( - __deserializer, - "GenericEnum", - VARIANTS, - __Visitor { - marker: _serde::__private::PhantomData::>, - lifetime: _serde::__private::PhantomData, - }, - ) - } - } -}; diff --git a/test_suite/tests/expand/generic_enum.rs b/test_suite/tests/expand/generic_enum.rs deleted file mode 100644 index 400a5088..00000000 --- a/test_suite/tests/expand/generic_enum.rs +++ /dev/null @@ -1,9 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Serialize, Deserialize)] -pub enum GenericEnum { - Unit, - NewType(T), - Seq(T, U), - Map { x: T, y: U }, -} diff --git a/test_suite/tests/expand/generic_struct.expanded.rs b/test_suite/tests/expand/generic_struct.expanded.rs deleted file mode 100644 index bb16dc3b..00000000 --- a/test_suite/tests/expand/generic_struct.expanded.rs +++ /dev/null @@ -1,594 +0,0 @@ -use serde::{Deserialize, Serialize}; -pub struct GenericStruct { - x: T, -} -#[doc(hidden)] -#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] -const _: () = { - #[allow(unused_extern_crates, clippy::useless_attribute)] - extern crate serde as _serde; - #[automatically_derived] - impl _serde::Serialize for GenericStruct - where - T: _serde::Serialize, - { - fn serialize<__S>( - &self, - __serializer: __S, - ) -> _serde::__private::Result<__S::Ok, __S::Error> - where - __S: _serde::Serializer, - { - let mut __serde_state = match _serde::Serializer::serialize_struct( - __serializer, - "GenericStruct", - false as usize + 1, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeStruct::serialize_field(&mut __serde_state, "x", &self.x) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - _serde::ser::SerializeStruct::end(__serde_state) - } - } -}; -#[doc(hidden)] -#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] -const _: () = { - #[allow(unused_extern_crates, clippy::useless_attribute)] - extern crate serde as _serde; - #[automatically_derived] - impl<'de, T> _serde::Deserialize<'de> for GenericStruct - where - T: _serde::Deserialize<'de>, - { - fn deserialize<__D>(__deserializer: __D) -> _serde::__private::Result - where - __D: _serde::Deserializer<'de>, - { - #[allow(non_camel_case_types)] - enum __Field { - __field0, - __ignore, - } - struct __FieldVisitor; - impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { - type Value = __Field; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result { - _serde::__private::Formatter::write_str(__formatter, "field identifier") - } - fn visit_u64<__E>(self, __value: u64) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - 0u64 => _serde::__private::Ok(__Field::__field0), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - fn visit_str<__E>( - self, - __value: &str, - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - "x" => _serde::__private::Ok(__Field::__field0), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - fn visit_bytes<__E>( - self, - __value: &[u8], - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - b"x" => _serde::__private::Ok(__Field::__field0), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - } - impl<'de> _serde::Deserialize<'de> for __Field { - #[inline] - fn deserialize<__D>( - __deserializer: __D, - ) -> _serde::__private::Result - where - __D: _serde::Deserializer<'de>, - { - _serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor) - } - } - struct __Visitor<'de, T> - where - T: _serde::Deserialize<'de>, - { - marker: _serde::__private::PhantomData>, - lifetime: _serde::__private::PhantomData<&'de ()>, - } - impl<'de, T> _serde::de::Visitor<'de> for __Visitor<'de, T> - where - T: _serde::Deserialize<'de>, - { - type Value = GenericStruct; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result { - _serde::__private::Formatter::write_str(__formatter, "struct GenericStruct") - } - #[inline] - fn visit_seq<__A>( - self, - mut __seq: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::SeqAccess<'de>, - { - let __field0 = match match _serde::de::SeqAccess::next_element::(&mut __seq) - { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde::__private::Err(_serde::de::Error::invalid_length( - 0usize, - &"struct GenericStruct with 1 element", - )); - } - }; - _serde::__private::Ok(GenericStruct { x: __field0 }) - } - #[inline] - fn visit_map<__A>( - self, - mut __map: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::MapAccess<'de>, - { - let mut __field0: _serde::__private::Option = _serde::__private::None; - while let _serde::__private::Some(__key) = - match _serde::de::MapAccess::next_key::<__Field>(&mut __map) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } - { - match __key { - __Field::__field0 => { - if _serde::__private::Option::is_some(&__field0) { - return _serde::__private::Err( - <__A::Error as _serde::de::Error>::duplicate_field("x"), - ); - } - __field0 = _serde::__private::Some( - match _serde::de::MapAccess::next_value::(&mut __map) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }, - ); - } - _ => { - let _ = match _serde::de::MapAccess::next_value::< - _serde::de::IgnoredAny, - >(&mut __map) - { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - } - } - } - let __field0 = match __field0 { - _serde::__private::Some(__field0) => __field0, - _serde::__private::None => { - match _serde::__private::de::missing_field("x") { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } - } - }; - _serde::__private::Ok(GenericStruct { x: __field0 }) - } - } - const FIELDS: &'static [&'static str] = &["x"]; - _serde::Deserializer::deserialize_struct( - __deserializer, - "GenericStruct", - FIELDS, - __Visitor { - marker: _serde::__private::PhantomData::>, - lifetime: _serde::__private::PhantomData, - }, - ) - } - fn deserialize_in_place<__D>( - __deserializer: __D, - __place: &mut Self, - ) -> _serde::__private::Result<(), __D::Error> - where - __D: _serde::Deserializer<'de>, - { - #[allow(non_camel_case_types)] - enum __Field { - __field0, - __ignore, - } - struct __FieldVisitor; - impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { - type Value = __Field; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result { - _serde::__private::Formatter::write_str(__formatter, "field identifier") - } - fn visit_u64<__E>(self, __value: u64) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - 0u64 => _serde::__private::Ok(__Field::__field0), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - fn visit_str<__E>( - self, - __value: &str, - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - "x" => _serde::__private::Ok(__Field::__field0), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - fn visit_bytes<__E>( - self, - __value: &[u8], - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - b"x" => _serde::__private::Ok(__Field::__field0), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - } - impl<'de> _serde::Deserialize<'de> for __Field { - #[inline] - fn deserialize<__D>( - __deserializer: __D, - ) -> _serde::__private::Result - where - __D: _serde::Deserializer<'de>, - { - _serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor) - } - } - struct __Visitor<'de, 'place, T: 'place> - where - T: _serde::Deserialize<'de>, - { - place: &'place mut GenericStruct, - lifetime: _serde::__private::PhantomData<&'de ()>, - } - impl<'de, 'place, T: 'place> _serde::de::Visitor<'de> for __Visitor<'de, 'place, T> - where - T: _serde::Deserialize<'de>, - { - type Value = (); - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result { - _serde::__private::Formatter::write_str(__formatter, "struct GenericStruct") - } - #[inline] - fn visit_seq<__A>( - self, - mut __seq: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::SeqAccess<'de>, - { - if let _serde::__private::None = match _serde::de::SeqAccess::next_element_seed( - &mut __seq, - _serde::__private::de::InPlaceSeed(&mut self.place.x), - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - return _serde::__private::Err(_serde::de::Error::invalid_length( - 0usize, - &"struct GenericStruct with 1 element", - )); - } - _serde::__private::Ok(()) - } - #[inline] - fn visit_map<__A>( - self, - mut __map: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::MapAccess<'de>, - { - let mut __field0: bool = false; - while let _serde::__private::Some(__key) = - match _serde::de::MapAccess::next_key::<__Field>(&mut __map) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } - { - match __key { - __Field::__field0 => { - if __field0 { - return _serde::__private::Err( - <__A::Error as _serde::de::Error>::duplicate_field("x"), - ); - } - match _serde::de::MapAccess::next_value_seed( - &mut __map, - _serde::__private::de::InPlaceSeed(&mut self.place.x), - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - __field0 = true; - } - _ => { - let _ = match _serde::de::MapAccess::next_value::< - _serde::de::IgnoredAny, - >(&mut __map) - { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - } - } - } - if !__field0 { - self.place.x = match _serde::__private::de::missing_field("x") { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - }; - _serde::__private::Ok(()) - } - } - const FIELDS: &'static [&'static str] = &["x"]; - _serde::Deserializer::deserialize_struct( - __deserializer, - "GenericStruct", - FIELDS, - __Visitor { - place: __place, - lifetime: _serde::__private::PhantomData, - }, - ) - } - } -}; -pub struct GenericNewTypeStruct(T); -#[doc(hidden)] -#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] -const _: () = { - #[allow(unused_extern_crates, clippy::useless_attribute)] - extern crate serde as _serde; - #[automatically_derived] - impl _serde::Serialize for GenericNewTypeStruct - where - T: _serde::Serialize, - { - fn serialize<__S>( - &self, - __serializer: __S, - ) -> _serde::__private::Result<__S::Ok, __S::Error> - where - __S: _serde::Serializer, - { - _serde::Serializer::serialize_newtype_struct( - __serializer, - "GenericNewTypeStruct", - &self.0, - ) - } - } -}; -#[doc(hidden)] -#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] -const _: () = { - #[allow(unused_extern_crates, clippy::useless_attribute)] - extern crate serde as _serde; - #[automatically_derived] - impl<'de, T> _serde::Deserialize<'de> for GenericNewTypeStruct - where - T: _serde::Deserialize<'de>, - { - fn deserialize<__D>(__deserializer: __D) -> _serde::__private::Result - where - __D: _serde::Deserializer<'de>, - { - struct __Visitor<'de, T> - where - T: _serde::Deserialize<'de>, - { - marker: _serde::__private::PhantomData>, - lifetime: _serde::__private::PhantomData<&'de ()>, - } - impl<'de, T> _serde::de::Visitor<'de> for __Visitor<'de, T> - where - T: _serde::Deserialize<'de>, - { - type Value = GenericNewTypeStruct; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result { - _serde::__private::Formatter::write_str( - __formatter, - "tuple struct GenericNewTypeStruct", - ) - } - #[inline] - fn visit_newtype_struct<__E>( - self, - __e: __E, - ) -> _serde::__private::Result - where - __E: _serde::Deserializer<'de>, - { - let __field0: T = match ::deserialize(__e) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - _serde::__private::Ok(GenericNewTypeStruct(__field0)) - } - #[inline] - fn visit_seq<__A>( - self, - mut __seq: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::SeqAccess<'de>, - { - let __field0 = match match _serde::de::SeqAccess::next_element::(&mut __seq) - { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde::__private::Err(_serde::de::Error::invalid_length( - 0usize, - &"tuple struct GenericNewTypeStruct with 1 element", - )); - } - }; - _serde::__private::Ok(GenericNewTypeStruct(__field0)) - } - } - _serde::Deserializer::deserialize_newtype_struct( - __deserializer, - "GenericNewTypeStruct", - __Visitor { - marker: _serde::__private::PhantomData::>, - lifetime: _serde::__private::PhantomData, - }, - ) - } - fn deserialize_in_place<__D>( - __deserializer: __D, - __place: &mut Self, - ) -> _serde::__private::Result<(), __D::Error> - where - __D: _serde::Deserializer<'de>, - { - struct __Visitor<'de, 'place, T: 'place> - where - T: _serde::Deserialize<'de>, - { - place: &'place mut GenericNewTypeStruct, - lifetime: _serde::__private::PhantomData<&'de ()>, - } - impl<'de, 'place, T: 'place> _serde::de::Visitor<'de> for __Visitor<'de, 'place, T> - where - T: _serde::Deserialize<'de>, - { - type Value = (); - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result { - _serde::__private::Formatter::write_str( - __formatter, - "tuple struct GenericNewTypeStruct", - ) - } - #[inline] - fn visit_newtype_struct<__E>( - self, - __e: __E, - ) -> _serde::__private::Result - where - __E: _serde::Deserializer<'de>, - { - _serde::Deserialize::deserialize_in_place(__e, &mut self.place.0) - } - #[inline] - fn visit_seq<__A>( - self, - mut __seq: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::SeqAccess<'de>, - { - if let _serde::__private::None = match _serde::de::SeqAccess::next_element_seed( - &mut __seq, - _serde::__private::de::InPlaceSeed(&mut self.place.0), - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - return _serde::__private::Err(_serde::de::Error::invalid_length( - 0usize, - &"tuple struct GenericNewTypeStruct with 1 element", - )); - } - _serde::__private::Ok(()) - } - } - _serde::Deserializer::deserialize_newtype_struct( - __deserializer, - "GenericNewTypeStruct", - __Visitor { - place: __place, - lifetime: _serde::__private::PhantomData, - }, - ) - } - } -}; diff --git a/test_suite/tests/expand/generic_struct.rs b/test_suite/tests/expand/generic_struct.rs deleted file mode 100644 index 650cb977..00000000 --- a/test_suite/tests/expand/generic_struct.rs +++ /dev/null @@ -1,9 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Serialize, Deserialize)] -pub struct GenericStruct { - x: T, -} - -#[derive(Serialize, Deserialize)] -pub struct GenericNewTypeStruct(T); diff --git a/test_suite/tests/expand/generic_tuple_struct.expanded.rs b/test_suite/tests/expand/generic_tuple_struct.expanded.rs deleted file mode 100644 index 7012f9f4..00000000 --- a/test_suite/tests/expand/generic_tuple_struct.expanded.rs +++ /dev/null @@ -1,172 +0,0 @@ -use serde::{Deserialize, Serialize}; -pub struct GenericTupleStruct(T, U); -#[doc(hidden)] -#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] -const _: () = { - #[allow(unused_extern_crates, clippy::useless_attribute)] - extern crate serde as _serde; - #[automatically_derived] - impl<'de, T, U> _serde::Deserialize<'de> for GenericTupleStruct - where - T: _serde::Deserialize<'de>, - U: _serde::Deserialize<'de>, - { - fn deserialize<__D>(__deserializer: __D) -> _serde::__private::Result - where - __D: _serde::Deserializer<'de>, - { - struct __Visitor<'de, T, U> - where - T: _serde::Deserialize<'de>, - U: _serde::Deserialize<'de>, - { - marker: _serde::__private::PhantomData>, - lifetime: _serde::__private::PhantomData<&'de ()>, - } - impl<'de, T, U> _serde::de::Visitor<'de> for __Visitor<'de, T, U> - where - T: _serde::Deserialize<'de>, - U: _serde::Deserialize<'de>, - { - type Value = GenericTupleStruct; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result { - _serde::__private::Formatter::write_str( - __formatter, - "tuple struct GenericTupleStruct", - ) - } - #[inline] - fn visit_seq<__A>( - self, - mut __seq: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::SeqAccess<'de>, - { - let __field0 = match match _serde::de::SeqAccess::next_element::(&mut __seq) - { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde::__private::Err(_serde::de::Error::invalid_length( - 0usize, - &"tuple struct GenericTupleStruct with 2 elements", - )); - } - }; - let __field1 = match match _serde::de::SeqAccess::next_element::(&mut __seq) - { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde::__private::Err(_serde::de::Error::invalid_length( - 1usize, - &"tuple struct GenericTupleStruct with 2 elements", - )); - } - }; - _serde::__private::Ok(GenericTupleStruct(__field0, __field1)) - } - } - _serde::Deserializer::deserialize_tuple_struct( - __deserializer, - "GenericTupleStruct", - 2usize, - __Visitor { - marker: _serde::__private::PhantomData::>, - lifetime: _serde::__private::PhantomData, - }, - ) - } - fn deserialize_in_place<__D>( - __deserializer: __D, - __place: &mut Self, - ) -> _serde::__private::Result<(), __D::Error> - where - __D: _serde::Deserializer<'de>, - { - struct __Visitor<'de, 'place, T: 'place, U: 'place> - where - T: _serde::Deserialize<'de>, - U: _serde::Deserialize<'de>, - { - place: &'place mut GenericTupleStruct, - lifetime: _serde::__private::PhantomData<&'de ()>, - } - impl<'de, 'place, T: 'place, U: 'place> _serde::de::Visitor<'de> for __Visitor<'de, 'place, T, U> - where - T: _serde::Deserialize<'de>, - U: _serde::Deserialize<'de>, - { - type Value = (); - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result { - _serde::__private::Formatter::write_str( - __formatter, - "tuple struct GenericTupleStruct", - ) - } - #[inline] - fn visit_seq<__A>( - self, - mut __seq: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::SeqAccess<'de>, - { - if let _serde::__private::None = match _serde::de::SeqAccess::next_element_seed( - &mut __seq, - _serde::__private::de::InPlaceSeed(&mut self.place.0), - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - return _serde::__private::Err(_serde::de::Error::invalid_length( - 0usize, - &"tuple struct GenericTupleStruct with 2 elements", - )); - } - if let _serde::__private::None = match _serde::de::SeqAccess::next_element_seed( - &mut __seq, - _serde::__private::de::InPlaceSeed(&mut self.place.1), - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - return _serde::__private::Err(_serde::de::Error::invalid_length( - 1usize, - &"tuple struct GenericTupleStruct with 2 elements", - )); - } - _serde::__private::Ok(()) - } - } - _serde::Deserializer::deserialize_tuple_struct( - __deserializer, - "GenericTupleStruct", - 2usize, - __Visitor { - place: __place, - lifetime: _serde::__private::PhantomData, - }, - ) - } - } -}; diff --git a/test_suite/tests/expand/generic_tuple_struct.rs b/test_suite/tests/expand/generic_tuple_struct.rs deleted file mode 100644 index 90721db6..00000000 --- a/test_suite/tests/expand/generic_tuple_struct.rs +++ /dev/null @@ -1,4 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Deserialize)] -pub struct GenericTupleStruct(T, U); diff --git a/test_suite/tests/expand/lifetimes.expanded.rs b/test_suite/tests/expand/lifetimes.expanded.rs deleted file mode 100644 index cf2f0081..00000000 --- a/test_suite/tests/expand/lifetimes.expanded.rs +++ /dev/null @@ -1,607 +0,0 @@ -use serde::{Deserialize, Serialize}; -enum Lifetimes<'a> { - LifetimeSeq(&'a i32), - NoLifetimeSeq(i32), - LifetimeMap { a: &'a i32 }, - NoLifetimeMap { a: i32 }, -} -#[doc(hidden)] -#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] -const _: () = { - #[allow(unused_extern_crates, clippy::useless_attribute)] - extern crate serde as _serde; - #[automatically_derived] - impl<'a> _serde::Serialize for Lifetimes<'a> { - fn serialize<__S>( - &self, - __serializer: __S, - ) -> _serde::__private::Result<__S::Ok, __S::Error> - where - __S: _serde::Serializer, - { - match *self { - Lifetimes::LifetimeSeq(ref __field0) => { - _serde::Serializer::serialize_newtype_variant( - __serializer, - "Lifetimes", - 0u32, - "LifetimeSeq", - __field0, - ) - } - Lifetimes::NoLifetimeSeq(ref __field0) => { - _serde::Serializer::serialize_newtype_variant( - __serializer, - "Lifetimes", - 1u32, - "NoLifetimeSeq", - __field0, - ) - } - Lifetimes::LifetimeMap { ref a } => { - let mut __serde_state = match _serde::Serializer::serialize_struct_variant( - __serializer, - "Lifetimes", - 2u32, - "LifetimeMap", - 0 + 1, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeStructVariant::serialize_field( - &mut __serde_state, - "a", - a, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - _serde::ser::SerializeStructVariant::end(__serde_state) - } - Lifetimes::NoLifetimeMap { ref a } => { - let mut __serde_state = match _serde::Serializer::serialize_struct_variant( - __serializer, - "Lifetimes", - 3u32, - "NoLifetimeMap", - 0 + 1, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeStructVariant::serialize_field( - &mut __serde_state, - "a", - a, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - _serde::ser::SerializeStructVariant::end(__serde_state) - } - } - } - } -}; -#[doc(hidden)] -#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] -const _: () = { - #[allow(unused_extern_crates, clippy::useless_attribute)] - extern crate serde as _serde; - #[automatically_derived] - impl<'de, 'a> _serde::Deserialize<'de> for Lifetimes<'a> { - fn deserialize<__D>(__deserializer: __D) -> _serde::__private::Result - where - __D: _serde::Deserializer<'de>, - { - #[allow(non_camel_case_types)] - enum __Field { - __field0, - __field1, - __field2, - __field3, - } - struct __FieldVisitor; - impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { - type Value = __Field; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result { - _serde::__private::Formatter::write_str(__formatter, "variant identifier") - } - fn visit_u64<__E>(self, __value: u64) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - 0u64 => _serde::__private::Ok(__Field::__field0), - 1u64 => _serde::__private::Ok(__Field::__field1), - 2u64 => _serde::__private::Ok(__Field::__field2), - 3u64 => _serde::__private::Ok(__Field::__field3), - _ => _serde::__private::Err(_serde::de::Error::invalid_value( - _serde::de::Unexpected::Unsigned(__value), - &"variant index 0 <= i < 4", - )), - } - } - fn visit_str<__E>( - self, - __value: &str, - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - "LifetimeSeq" => _serde::__private::Ok(__Field::__field0), - "NoLifetimeSeq" => _serde::__private::Ok(__Field::__field1), - "LifetimeMap" => _serde::__private::Ok(__Field::__field2), - "NoLifetimeMap" => _serde::__private::Ok(__Field::__field3), - _ => _serde::__private::Err(_serde::de::Error::unknown_variant( - __value, VARIANTS, - )), - } - } - fn visit_bytes<__E>( - self, - __value: &[u8], - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - b"LifetimeSeq" => _serde::__private::Ok(__Field::__field0), - b"NoLifetimeSeq" => _serde::__private::Ok(__Field::__field1), - b"LifetimeMap" => _serde::__private::Ok(__Field::__field2), - b"NoLifetimeMap" => _serde::__private::Ok(__Field::__field3), - _ => { - let __value = &_serde::__private::from_utf8_lossy(__value); - _serde::__private::Err(_serde::de::Error::unknown_variant( - __value, VARIANTS, - )) - } - } - } - } - impl<'de> _serde::Deserialize<'de> for __Field { - #[inline] - fn deserialize<__D>( - __deserializer: __D, - ) -> _serde::__private::Result - where - __D: _serde::Deserializer<'de>, - { - _serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor) - } - } - struct __Visitor<'de, 'a> { - marker: _serde::__private::PhantomData>, - lifetime: _serde::__private::PhantomData<&'de ()>, - } - impl<'de, 'a> _serde::de::Visitor<'de> for __Visitor<'de, 'a> { - type Value = Lifetimes<'a>; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result { - _serde::__private::Formatter::write_str(__formatter, "enum Lifetimes") - } - fn visit_enum<__A>( - self, - __data: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::EnumAccess<'de>, - { - match match _serde::de::EnumAccess::variant(__data) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - (__Field::__field0, __variant) => _serde::__private::Result::map( - _serde::de::VariantAccess::newtype_variant::<&'a i32>(__variant), - Lifetimes::LifetimeSeq, - ), - (__Field::__field1, __variant) => _serde::__private::Result::map( - _serde::de::VariantAccess::newtype_variant::(__variant), - Lifetimes::NoLifetimeSeq, - ), - (__Field::__field2, __variant) => { - #[allow(non_camel_case_types)] - enum __Field { - __field0, - __ignore, - } - struct __FieldVisitor; - impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { - type Value = __Field; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result - { - _serde::__private::Formatter::write_str( - __formatter, - "field identifier", - ) - } - fn visit_u64<__E>( - self, - __value: u64, - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - 0u64 => _serde::__private::Ok(__Field::__field0), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - fn visit_str<__E>( - self, - __value: &str, - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - "a" => _serde::__private::Ok(__Field::__field0), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - fn visit_bytes<__E>( - self, - __value: &[u8], - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - b"a" => _serde::__private::Ok(__Field::__field0), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - } - impl<'de> _serde::Deserialize<'de> for __Field { - #[inline] - fn deserialize<__D>( - __deserializer: __D, - ) -> _serde::__private::Result - where - __D: _serde::Deserializer<'de>, - { - _serde::Deserializer::deserialize_identifier( - __deserializer, - __FieldVisitor, - ) - } - } - struct __Visitor<'de, 'a> { - marker: _serde::__private::PhantomData>, - lifetime: _serde::__private::PhantomData<&'de ()>, - } - impl<'de, 'a> _serde::de::Visitor<'de> for __Visitor<'de, 'a> { - type Value = Lifetimes<'a>; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result - { - _serde::__private::Formatter::write_str( - __formatter, - "struct variant Lifetimes::LifetimeMap", - ) - } - #[inline] - fn visit_seq<__A>( - self, - mut __seq: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::SeqAccess<'de>, - { - let __field0 = match match _serde::de::SeqAccess::next_element::< - &'a i32, - >( - &mut __seq - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde :: __private :: Err (_serde :: de :: Error :: invalid_length (0usize , & "struct variant Lifetimes::LifetimeMap with 1 element")) ; - } - }; - _serde::__private::Ok(Lifetimes::LifetimeMap { a: __field0 }) - } - #[inline] - fn visit_map<__A>( - self, - mut __map: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::MapAccess<'de>, - { - let mut __field0: _serde::__private::Option<&'a i32> = - _serde::__private::None; - while let _serde::__private::Some(__key) = - match _serde::de::MapAccess::next_key::<__Field>(&mut __map) - { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } - { - match __key { - __Field::__field0 => { - if _serde::__private::Option::is_some(&__field0) { - return _serde :: __private :: Err (< __A :: Error as _serde :: de :: Error > :: duplicate_field ("a")) ; - } - __field0 = _serde::__private::Some( - match _serde::de::MapAccess::next_value::<&'a i32>( - &mut __map, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }, - ); - } - _ => { - let _ = match _serde::de::MapAccess::next_value::< - _serde::de::IgnoredAny, - >( - &mut __map - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - } - } - } - let __field0 = match __field0 { - _serde::__private::Some(__field0) => __field0, - _serde::__private::None => { - match _serde::__private::de::missing_field("a") { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } - } - }; - _serde::__private::Ok(Lifetimes::LifetimeMap { a: __field0 }) - } - } - const FIELDS: &'static [&'static str] = &["a"]; - _serde::de::VariantAccess::struct_variant( - __variant, - FIELDS, - __Visitor { - marker: _serde::__private::PhantomData::>, - lifetime: _serde::__private::PhantomData, - }, - ) - } - (__Field::__field3, __variant) => { - #[allow(non_camel_case_types)] - enum __Field { - __field0, - __ignore, - } - struct __FieldVisitor; - impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { - type Value = __Field; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result - { - _serde::__private::Formatter::write_str( - __formatter, - "field identifier", - ) - } - fn visit_u64<__E>( - self, - __value: u64, - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - 0u64 => _serde::__private::Ok(__Field::__field0), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - fn visit_str<__E>( - self, - __value: &str, - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - "a" => _serde::__private::Ok(__Field::__field0), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - fn visit_bytes<__E>( - self, - __value: &[u8], - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - b"a" => _serde::__private::Ok(__Field::__field0), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - } - impl<'de> _serde::Deserialize<'de> for __Field { - #[inline] - fn deserialize<__D>( - __deserializer: __D, - ) -> _serde::__private::Result - where - __D: _serde::Deserializer<'de>, - { - _serde::Deserializer::deserialize_identifier( - __deserializer, - __FieldVisitor, - ) - } - } - struct __Visitor<'de, 'a> { - marker: _serde::__private::PhantomData>, - lifetime: _serde::__private::PhantomData<&'de ()>, - } - impl<'de, 'a> _serde::de::Visitor<'de> for __Visitor<'de, 'a> { - type Value = Lifetimes<'a>; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result - { - _serde::__private::Formatter::write_str( - __formatter, - "struct variant Lifetimes::NoLifetimeMap", - ) - } - #[inline] - fn visit_seq<__A>( - self, - mut __seq: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::SeqAccess<'de>, - { - let __field0 = match match _serde::de::SeqAccess::next_element::< - i32, - >( - &mut __seq - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde :: __private :: Err (_serde :: de :: Error :: invalid_length (0usize , & "struct variant Lifetimes::NoLifetimeMap with 1 element")) ; - } - }; - _serde::__private::Ok(Lifetimes::NoLifetimeMap { a: __field0 }) - } - #[inline] - fn visit_map<__A>( - self, - mut __map: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::MapAccess<'de>, - { - let mut __field0: _serde::__private::Option = - _serde::__private::None; - while let _serde::__private::Some(__key) = - match _serde::de::MapAccess::next_key::<__Field>(&mut __map) - { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } - { - match __key { - __Field::__field0 => { - if _serde::__private::Option::is_some(&__field0) { - return _serde :: __private :: Err (< __A :: Error as _serde :: de :: Error > :: duplicate_field ("a")) ; - } - __field0 = _serde::__private::Some( - match _serde::de::MapAccess::next_value::( - &mut __map, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }, - ); - } - _ => { - let _ = match _serde::de::MapAccess::next_value::< - _serde::de::IgnoredAny, - >( - &mut __map - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - } - } - } - let __field0 = match __field0 { - _serde::__private::Some(__field0) => __field0, - _serde::__private::None => { - match _serde::__private::de::missing_field("a") { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } - } - }; - _serde::__private::Ok(Lifetimes::NoLifetimeMap { a: __field0 }) - } - } - const FIELDS: &'static [&'static str] = &["a"]; - _serde::de::VariantAccess::struct_variant( - __variant, - FIELDS, - __Visitor { - marker: _serde::__private::PhantomData::>, - lifetime: _serde::__private::PhantomData, - }, - ) - } - } - } - } - const VARIANTS: &'static [&'static str] = &[ - "LifetimeSeq", - "NoLifetimeSeq", - "LifetimeMap", - "NoLifetimeMap", - ]; - _serde::Deserializer::deserialize_enum( - __deserializer, - "Lifetimes", - VARIANTS, - __Visitor { - marker: _serde::__private::PhantomData::>, - lifetime: _serde::__private::PhantomData, - }, - ) - } - } -}; diff --git a/test_suite/tests/expand/lifetimes.rs b/test_suite/tests/expand/lifetimes.rs deleted file mode 100644 index 0e899673..00000000 --- a/test_suite/tests/expand/lifetimes.rs +++ /dev/null @@ -1,9 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Serialize, Deserialize)] -enum Lifetimes<'a> { - LifetimeSeq(&'a i32), - NoLifetimeSeq(i32), - LifetimeMap { a: &'a i32 }, - NoLifetimeMap { a: i32 }, -} diff --git a/test_suite/tests/expand/named_map.expanded.rs b/test_suite/tests/expand/named_map.expanded.rs deleted file mode 100644 index e30ac34e..00000000 --- a/test_suite/tests/expand/named_map.expanded.rs +++ /dev/null @@ -1,628 +0,0 @@ -use serde::{Deserialize, Serialize}; -struct SerNamedMap<'a, 'b, A: 'a, B: 'b, C> { - a: &'a A, - b: &'b mut B, - c: C, -} -#[doc(hidden)] -#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] -const _: () = { - #[allow(unused_extern_crates, clippy::useless_attribute)] - extern crate serde as _serde; - #[automatically_derived] - impl<'a, 'b, A: 'a, B: 'b, C> _serde::Serialize for SerNamedMap<'a, 'b, A, B, C> - where - A: _serde::Serialize, - B: _serde::Serialize, - C: _serde::Serialize, - { - fn serialize<__S>( - &self, - __serializer: __S, - ) -> _serde::__private::Result<__S::Ok, __S::Error> - where - __S: _serde::Serializer, - { - let mut __serde_state = match _serde::Serializer::serialize_struct( - __serializer, - "SerNamedMap", - false as usize + 1 + 1 + 1, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeStruct::serialize_field(&mut __serde_state, "a", &self.a) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeStruct::serialize_field(&mut __serde_state, "b", &self.b) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeStruct::serialize_field(&mut __serde_state, "c", &self.c) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - _serde::ser::SerializeStruct::end(__serde_state) - } - } -}; -struct DeNamedMap { - a: A, - b: B, - c: C, -} -#[doc(hidden)] -#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] -const _: () = { - #[allow(unused_extern_crates, clippy::useless_attribute)] - extern crate serde as _serde; - #[automatically_derived] - impl<'de, A, B, C> _serde::Deserialize<'de> for DeNamedMap - where - A: _serde::Deserialize<'de>, - B: _serde::Deserialize<'de>, - C: _serde::Deserialize<'de>, - { - fn deserialize<__D>(__deserializer: __D) -> _serde::__private::Result - where - __D: _serde::Deserializer<'de>, - { - #[allow(non_camel_case_types)] - enum __Field { - __field0, - __field1, - __field2, - __ignore, - } - struct __FieldVisitor; - impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { - type Value = __Field; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result { - _serde::__private::Formatter::write_str(__formatter, "field identifier") - } - fn visit_u64<__E>(self, __value: u64) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - 0u64 => _serde::__private::Ok(__Field::__field0), - 1u64 => _serde::__private::Ok(__Field::__field1), - 2u64 => _serde::__private::Ok(__Field::__field2), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - fn visit_str<__E>( - self, - __value: &str, - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - "a" => _serde::__private::Ok(__Field::__field0), - "b" => _serde::__private::Ok(__Field::__field1), - "c" => _serde::__private::Ok(__Field::__field2), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - fn visit_bytes<__E>( - self, - __value: &[u8], - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - b"a" => _serde::__private::Ok(__Field::__field0), - b"b" => _serde::__private::Ok(__Field::__field1), - b"c" => _serde::__private::Ok(__Field::__field2), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - } - impl<'de> _serde::Deserialize<'de> for __Field { - #[inline] - fn deserialize<__D>( - __deserializer: __D, - ) -> _serde::__private::Result - where - __D: _serde::Deserializer<'de>, - { - _serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor) - } - } - struct __Visitor<'de, A, B, C> - where - A: _serde::Deserialize<'de>, - B: _serde::Deserialize<'de>, - C: _serde::Deserialize<'de>, - { - marker: _serde::__private::PhantomData>, - lifetime: _serde::__private::PhantomData<&'de ()>, - } - impl<'de, A, B, C> _serde::de::Visitor<'de> for __Visitor<'de, A, B, C> - where - A: _serde::Deserialize<'de>, - B: _serde::Deserialize<'de>, - C: _serde::Deserialize<'de>, - { - type Value = DeNamedMap; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result { - _serde::__private::Formatter::write_str(__formatter, "struct DeNamedMap") - } - #[inline] - fn visit_seq<__A>( - self, - mut __seq: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::SeqAccess<'de>, - { - let __field0 = match match _serde::de::SeqAccess::next_element::(&mut __seq) - { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde::__private::Err(_serde::de::Error::invalid_length( - 0usize, - &"struct DeNamedMap with 3 elements", - )); - } - }; - let __field1 = match match _serde::de::SeqAccess::next_element::(&mut __seq) - { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde::__private::Err(_serde::de::Error::invalid_length( - 1usize, - &"struct DeNamedMap with 3 elements", - )); - } - }; - let __field2 = match match _serde::de::SeqAccess::next_element::(&mut __seq) - { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde::__private::Err(_serde::de::Error::invalid_length( - 2usize, - &"struct DeNamedMap with 3 elements", - )); - } - }; - _serde::__private::Ok(DeNamedMap { - a: __field0, - b: __field1, - c: __field2, - }) - } - #[inline] - fn visit_map<__A>( - self, - mut __map: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::MapAccess<'de>, - { - let mut __field0: _serde::__private::Option = _serde::__private::None; - let mut __field1: _serde::__private::Option = _serde::__private::None; - let mut __field2: _serde::__private::Option = _serde::__private::None; - while let _serde::__private::Some(__key) = - match _serde::de::MapAccess::next_key::<__Field>(&mut __map) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } - { - match __key { - __Field::__field0 => { - if _serde::__private::Option::is_some(&__field0) { - return _serde::__private::Err( - <__A::Error as _serde::de::Error>::duplicate_field("a"), - ); - } - __field0 = _serde::__private::Some( - match _serde::de::MapAccess::next_value::(&mut __map) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }, - ); - } - __Field::__field1 => { - if _serde::__private::Option::is_some(&__field1) { - return _serde::__private::Err( - <__A::Error as _serde::de::Error>::duplicate_field("b"), - ); - } - __field1 = _serde::__private::Some( - match _serde::de::MapAccess::next_value::(&mut __map) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }, - ); - } - __Field::__field2 => { - if _serde::__private::Option::is_some(&__field2) { - return _serde::__private::Err( - <__A::Error as _serde::de::Error>::duplicate_field("c"), - ); - } - __field2 = _serde::__private::Some( - match _serde::de::MapAccess::next_value::(&mut __map) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }, - ); - } - _ => { - let _ = match _serde::de::MapAccess::next_value::< - _serde::de::IgnoredAny, - >(&mut __map) - { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - } - } - } - let __field0 = match __field0 { - _serde::__private::Some(__field0) => __field0, - _serde::__private::None => { - match _serde::__private::de::missing_field("a") { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } - } - }; - let __field1 = match __field1 { - _serde::__private::Some(__field1) => __field1, - _serde::__private::None => { - match _serde::__private::de::missing_field("b") { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } - } - }; - let __field2 = match __field2 { - _serde::__private::Some(__field2) => __field2, - _serde::__private::None => { - match _serde::__private::de::missing_field("c") { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } - } - }; - _serde::__private::Ok(DeNamedMap { - a: __field0, - b: __field1, - c: __field2, - }) - } - } - const FIELDS: &'static [&'static str] = &["a", "b", "c"]; - _serde::Deserializer::deserialize_struct( - __deserializer, - "DeNamedMap", - FIELDS, - __Visitor { - marker: _serde::__private::PhantomData::>, - lifetime: _serde::__private::PhantomData, - }, - ) - } - fn deserialize_in_place<__D>( - __deserializer: __D, - __place: &mut Self, - ) -> _serde::__private::Result<(), __D::Error> - where - __D: _serde::Deserializer<'de>, - { - #[allow(non_camel_case_types)] - enum __Field { - __field0, - __field1, - __field2, - __ignore, - } - struct __FieldVisitor; - impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { - type Value = __Field; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result { - _serde::__private::Formatter::write_str(__formatter, "field identifier") - } - fn visit_u64<__E>(self, __value: u64) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - 0u64 => _serde::__private::Ok(__Field::__field0), - 1u64 => _serde::__private::Ok(__Field::__field1), - 2u64 => _serde::__private::Ok(__Field::__field2), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - fn visit_str<__E>( - self, - __value: &str, - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - "a" => _serde::__private::Ok(__Field::__field0), - "b" => _serde::__private::Ok(__Field::__field1), - "c" => _serde::__private::Ok(__Field::__field2), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - fn visit_bytes<__E>( - self, - __value: &[u8], - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - b"a" => _serde::__private::Ok(__Field::__field0), - b"b" => _serde::__private::Ok(__Field::__field1), - b"c" => _serde::__private::Ok(__Field::__field2), - _ => _serde::__private::Ok(__Field::__ignore), - } - } - } - impl<'de> _serde::Deserialize<'de> for __Field { - #[inline] - fn deserialize<__D>( - __deserializer: __D, - ) -> _serde::__private::Result - where - __D: _serde::Deserializer<'de>, - { - _serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor) - } - } - struct __Visitor<'de, 'place, A: 'place, B: 'place, C: 'place> - where - A: _serde::Deserialize<'de>, - B: _serde::Deserialize<'de>, - C: _serde::Deserialize<'de>, - { - place: &'place mut DeNamedMap, - lifetime: _serde::__private::PhantomData<&'de ()>, - } - impl<'de, 'place, A: 'place, B: 'place, C: 'place> _serde::de::Visitor<'de> - for __Visitor<'de, 'place, A, B, C> - where - A: _serde::Deserialize<'de>, - B: _serde::Deserialize<'de>, - C: _serde::Deserialize<'de>, - { - type Value = (); - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result { - _serde::__private::Formatter::write_str(__formatter, "struct DeNamedMap") - } - #[inline] - fn visit_seq<__A>( - self, - mut __seq: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::SeqAccess<'de>, - { - if let _serde::__private::None = match _serde::de::SeqAccess::next_element_seed( - &mut __seq, - _serde::__private::de::InPlaceSeed(&mut self.place.a), - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - return _serde::__private::Err(_serde::de::Error::invalid_length( - 0usize, - &"struct DeNamedMap with 3 elements", - )); - } - if let _serde::__private::None = match _serde::de::SeqAccess::next_element_seed( - &mut __seq, - _serde::__private::de::InPlaceSeed(&mut self.place.b), - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - return _serde::__private::Err(_serde::de::Error::invalid_length( - 1usize, - &"struct DeNamedMap with 3 elements", - )); - } - if let _serde::__private::None = match _serde::de::SeqAccess::next_element_seed( - &mut __seq, - _serde::__private::de::InPlaceSeed(&mut self.place.c), - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - return _serde::__private::Err(_serde::de::Error::invalid_length( - 2usize, - &"struct DeNamedMap with 3 elements", - )); - } - _serde::__private::Ok(()) - } - #[inline] - fn visit_map<__A>( - self, - mut __map: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::MapAccess<'de>, - { - let mut __field0: bool = false; - let mut __field1: bool = false; - let mut __field2: bool = false; - while let _serde::__private::Some(__key) = - match _serde::de::MapAccess::next_key::<__Field>(&mut __map) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } - { - match __key { - __Field::__field0 => { - if __field0 { - return _serde::__private::Err( - <__A::Error as _serde::de::Error>::duplicate_field("a"), - ); - } - match _serde::de::MapAccess::next_value_seed( - &mut __map, - _serde::__private::de::InPlaceSeed(&mut self.place.a), - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - __field0 = true; - } - __Field::__field1 => { - if __field1 { - return _serde::__private::Err( - <__A::Error as _serde::de::Error>::duplicate_field("b"), - ); - } - match _serde::de::MapAccess::next_value_seed( - &mut __map, - _serde::__private::de::InPlaceSeed(&mut self.place.b), - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - __field1 = true; - } - __Field::__field2 => { - if __field2 { - return _serde::__private::Err( - <__A::Error as _serde::de::Error>::duplicate_field("c"), - ); - } - match _serde::de::MapAccess::next_value_seed( - &mut __map, - _serde::__private::de::InPlaceSeed(&mut self.place.c), - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - __field2 = true; - } - _ => { - let _ = match _serde::de::MapAccess::next_value::< - _serde::de::IgnoredAny, - >(&mut __map) - { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - } - } - } - if !__field0 { - self.place.a = match _serde::__private::de::missing_field("a") { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - }; - if !__field1 { - self.place.b = match _serde::__private::de::missing_field("b") { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - }; - if !__field2 { - self.place.c = match _serde::__private::de::missing_field("c") { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - }; - _serde::__private::Ok(()) - } - } - const FIELDS: &'static [&'static str] = &["a", "b", "c"]; - _serde::Deserializer::deserialize_struct( - __deserializer, - "DeNamedMap", - FIELDS, - __Visitor { - place: __place, - lifetime: _serde::__private::PhantomData, - }, - ) - } - } -}; diff --git a/test_suite/tests/expand/named_map.rs b/test_suite/tests/expand/named_map.rs deleted file mode 100644 index 367e9b52..00000000 --- a/test_suite/tests/expand/named_map.rs +++ /dev/null @@ -1,15 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Serialize)] -struct SerNamedMap<'a, 'b, A: 'a, B: 'b, C> { - a: &'a A, - b: &'b mut B, - c: C, -} - -#[derive(Deserialize)] -struct DeNamedMap { - a: A, - b: B, - c: C, -} diff --git a/test_suite/tests/expand/named_tuple.expanded.rs b/test_suite/tests/expand/named_tuple.expanded.rs deleted file mode 100644 index be083f63..00000000 --- a/test_suite/tests/expand/named_tuple.expanded.rs +++ /dev/null @@ -1,259 +0,0 @@ -use serde::{Deserialize, Serialize}; -struct SerNamedTuple<'a, 'b, A: 'a, B: 'b, C>(&'a A, &'b mut B, C); -#[doc(hidden)] -#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] -const _: () = { - #[allow(unused_extern_crates, clippy::useless_attribute)] - extern crate serde as _serde; - #[automatically_derived] - impl<'a, 'b, A: 'a, B: 'b, C> _serde::Serialize for SerNamedTuple<'a, 'b, A, B, C> - where - A: _serde::Serialize, - B: _serde::Serialize, - C: _serde::Serialize, - { - fn serialize<__S>( - &self, - __serializer: __S, - ) -> _serde::__private::Result<__S::Ok, __S::Error> - where - __S: _serde::Serializer, - { - let mut __serde_state = match _serde::Serializer::serialize_tuple_struct( - __serializer, - "SerNamedTuple", - 0 + 1 + 1 + 1, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeTupleStruct::serialize_field(&mut __serde_state, &self.0) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeTupleStruct::serialize_field(&mut __serde_state, &self.1) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeTupleStruct::serialize_field(&mut __serde_state, &self.2) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - _serde::ser::SerializeTupleStruct::end(__serde_state) - } - } -}; -struct DeNamedTuple(A, B, C); -#[doc(hidden)] -#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] -const _: () = { - #[allow(unused_extern_crates, clippy::useless_attribute)] - extern crate serde as _serde; - #[automatically_derived] - impl<'de, A, B, C> _serde::Deserialize<'de> for DeNamedTuple - where - A: _serde::Deserialize<'de>, - B: _serde::Deserialize<'de>, - C: _serde::Deserialize<'de>, - { - fn deserialize<__D>(__deserializer: __D) -> _serde::__private::Result - where - __D: _serde::Deserializer<'de>, - { - struct __Visitor<'de, A, B, C> - where - A: _serde::Deserialize<'de>, - B: _serde::Deserialize<'de>, - C: _serde::Deserialize<'de>, - { - marker: _serde::__private::PhantomData>, - lifetime: _serde::__private::PhantomData<&'de ()>, - } - impl<'de, A, B, C> _serde::de::Visitor<'de> for __Visitor<'de, A, B, C> - where - A: _serde::Deserialize<'de>, - B: _serde::Deserialize<'de>, - C: _serde::Deserialize<'de>, - { - type Value = DeNamedTuple; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result { - _serde::__private::Formatter::write_str( - __formatter, - "tuple struct DeNamedTuple", - ) - } - #[inline] - fn visit_seq<__A>( - self, - mut __seq: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::SeqAccess<'de>, - { - let __field0 = match match _serde::de::SeqAccess::next_element::(&mut __seq) - { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde::__private::Err(_serde::de::Error::invalid_length( - 0usize, - &"tuple struct DeNamedTuple with 3 elements", - )); - } - }; - let __field1 = match match _serde::de::SeqAccess::next_element::(&mut __seq) - { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde::__private::Err(_serde::de::Error::invalid_length( - 1usize, - &"tuple struct DeNamedTuple with 3 elements", - )); - } - }; - let __field2 = match match _serde::de::SeqAccess::next_element::(&mut __seq) - { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - _serde::__private::Some(__value) => __value, - _serde::__private::None => { - return _serde::__private::Err(_serde::de::Error::invalid_length( - 2usize, - &"tuple struct DeNamedTuple with 3 elements", - )); - } - }; - _serde::__private::Ok(DeNamedTuple(__field0, __field1, __field2)) - } - } - _serde::Deserializer::deserialize_tuple_struct( - __deserializer, - "DeNamedTuple", - 3usize, - __Visitor { - marker: _serde::__private::PhantomData::>, - lifetime: _serde::__private::PhantomData, - }, - ) - } - fn deserialize_in_place<__D>( - __deserializer: __D, - __place: &mut Self, - ) -> _serde::__private::Result<(), __D::Error> - where - __D: _serde::Deserializer<'de>, - { - struct __Visitor<'de, 'place, A: 'place, B: 'place, C: 'place> - where - A: _serde::Deserialize<'de>, - B: _serde::Deserialize<'de>, - C: _serde::Deserialize<'de>, - { - place: &'place mut DeNamedTuple, - lifetime: _serde::__private::PhantomData<&'de ()>, - } - impl<'de, 'place, A: 'place, B: 'place, C: 'place> _serde::de::Visitor<'de> - for __Visitor<'de, 'place, A, B, C> - where - A: _serde::Deserialize<'de>, - B: _serde::Deserialize<'de>, - C: _serde::Deserialize<'de>, - { - type Value = (); - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result { - _serde::__private::Formatter::write_str( - __formatter, - "tuple struct DeNamedTuple", - ) - } - #[inline] - fn visit_seq<__A>( - self, - mut __seq: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::SeqAccess<'de>, - { - if let _serde::__private::None = match _serde::de::SeqAccess::next_element_seed( - &mut __seq, - _serde::__private::de::InPlaceSeed(&mut self.place.0), - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - return _serde::__private::Err(_serde::de::Error::invalid_length( - 0usize, - &"tuple struct DeNamedTuple with 3 elements", - )); - } - if let _serde::__private::None = match _serde::de::SeqAccess::next_element_seed( - &mut __seq, - _serde::__private::de::InPlaceSeed(&mut self.place.1), - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - return _serde::__private::Err(_serde::de::Error::invalid_length( - 1usize, - &"tuple struct DeNamedTuple with 3 elements", - )); - } - if let _serde::__private::None = match _serde::de::SeqAccess::next_element_seed( - &mut __seq, - _serde::__private::de::InPlaceSeed(&mut self.place.2), - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - } { - return _serde::__private::Err(_serde::de::Error::invalid_length( - 2usize, - &"tuple struct DeNamedTuple with 3 elements", - )); - } - _serde::__private::Ok(()) - } - } - _serde::Deserializer::deserialize_tuple_struct( - __deserializer, - "DeNamedTuple", - 3usize, - __Visitor { - place: __place, - lifetime: _serde::__private::PhantomData, - }, - ) - } - } -}; diff --git a/test_suite/tests/expand/named_tuple.rs b/test_suite/tests/expand/named_tuple.rs deleted file mode 100644 index b9e8847d..00000000 --- a/test_suite/tests/expand/named_tuple.rs +++ /dev/null @@ -1,7 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Serialize)] -struct SerNamedTuple<'a, 'b, A: 'a, B: 'b, C>(&'a A, &'b mut B, C); - -#[derive(Deserialize)] -struct DeNamedTuple(A, B, C); diff --git a/test_suite/tests/expand/named_unit.expanded.rs b/test_suite/tests/expand/named_unit.expanded.rs deleted file mode 100644 index 87876b77..00000000 --- a/test_suite/tests/expand/named_unit.expanded.rs +++ /dev/null @@ -1,52 +0,0 @@ -use serde::{Deserialize, Serialize}; -struct NamedUnit; -#[doc(hidden)] -#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] -const _: () = { - #[allow(unused_extern_crates, clippy::useless_attribute)] - extern crate serde as _serde; - #[automatically_derived] - impl _serde::Serialize for NamedUnit { - fn serialize<__S>( - &self, - __serializer: __S, - ) -> _serde::__private::Result<__S::Ok, __S::Error> - where - __S: _serde::Serializer, - { - _serde::Serializer::serialize_unit_struct(__serializer, "NamedUnit") - } - } -}; -#[doc(hidden)] -#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] -const _: () = { - #[allow(unused_extern_crates, clippy::useless_attribute)] - extern crate serde as _serde; - #[automatically_derived] - impl<'de> _serde::Deserialize<'de> for NamedUnit { - fn deserialize<__D>(__deserializer: __D) -> _serde::__private::Result - where - __D: _serde::Deserializer<'de>, - { - struct __Visitor; - impl<'de> _serde::de::Visitor<'de> for __Visitor { - type Value = NamedUnit; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result { - _serde::__private::Formatter::write_str(__formatter, "unit struct NamedUnit") - } - #[inline] - fn visit_unit<__E>(self) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - _serde::__private::Ok(NamedUnit) - } - } - _serde::Deserializer::deserialize_unit_struct(__deserializer, "NamedUnit", __Visitor) - } - } -}; diff --git a/test_suite/tests/expand/named_unit.rs b/test_suite/tests/expand/named_unit.rs deleted file mode 100644 index 35d71bf9..00000000 --- a/test_suite/tests/expand/named_unit.rs +++ /dev/null @@ -1,4 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Serialize, Deserialize)] -struct NamedUnit; diff --git a/test_suite/tests/expand/ser_enum.expanded.rs b/test_suite/tests/expand/ser_enum.expanded.rs deleted file mode 100644 index b0a83ca3..00000000 --- a/test_suite/tests/expand/ser_enum.expanded.rs +++ /dev/null @@ -1,271 +0,0 @@ -use serde::Serialize; -enum SerEnum<'a, B: 'a, C: 'a, D> -where - D: 'a, -{ - Unit, - Seq(i8, B, &'a C, &'a mut D), - Map { a: i8, b: B, c: &'a C, d: &'a mut D }, - _Unit2, - _Seq2(i8, B, &'a C, &'a mut D), - _Map2 { a: i8, b: B, c: &'a C, d: &'a mut D }, -} -#[doc(hidden)] -#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] -const _: () = { - #[allow(unused_extern_crates, clippy::useless_attribute)] - extern crate serde as _serde; - #[automatically_derived] - impl<'a, B: 'a, C: 'a, D> _serde::Serialize for SerEnum<'a, B, C, D> - where - D: 'a, - B: _serde::Serialize, - C: _serde::Serialize, - D: _serde::Serialize, - { - fn serialize<__S>( - &self, - __serializer: __S, - ) -> _serde::__private::Result<__S::Ok, __S::Error> - where - __S: _serde::Serializer, - { - match *self { - SerEnum::Unit => _serde::Serializer::serialize_unit_variant( - __serializer, - "SerEnum", - 0u32, - "Unit", - ), - SerEnum::Seq(ref __field0, ref __field1, ref __field2, ref __field3) => { - let mut __serde_state = match _serde::Serializer::serialize_tuple_variant( - __serializer, - "SerEnum", - 1u32, - "Seq", - 0 + 1 + 1 + 1 + 1, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeTupleVariant::serialize_field( - &mut __serde_state, - __field0, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeTupleVariant::serialize_field( - &mut __serde_state, - __field1, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeTupleVariant::serialize_field( - &mut __serde_state, - __field2, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeTupleVariant::serialize_field( - &mut __serde_state, - __field3, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - _serde::ser::SerializeTupleVariant::end(__serde_state) - } - SerEnum::Map { - ref a, - ref b, - ref c, - ref d, - } => { - let mut __serde_state = match _serde::Serializer::serialize_struct_variant( - __serializer, - "SerEnum", - 2u32, - "Map", - 0 + 1 + 1 + 1 + 1, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeStructVariant::serialize_field( - &mut __serde_state, - "a", - a, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeStructVariant::serialize_field( - &mut __serde_state, - "b", - b, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeStructVariant::serialize_field( - &mut __serde_state, - "c", - c, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeStructVariant::serialize_field( - &mut __serde_state, - "d", - d, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - _serde::ser::SerializeStructVariant::end(__serde_state) - } - SerEnum::_Unit2 => _serde::Serializer::serialize_unit_variant( - __serializer, - "SerEnum", - 3u32, - "_Unit2", - ), - SerEnum::_Seq2(ref __field0, ref __field1, ref __field2, ref __field3) => { - let mut __serde_state = match _serde::Serializer::serialize_tuple_variant( - __serializer, - "SerEnum", - 4u32, - "_Seq2", - 0 + 1 + 1 + 1 + 1, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeTupleVariant::serialize_field( - &mut __serde_state, - __field0, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeTupleVariant::serialize_field( - &mut __serde_state, - __field1, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeTupleVariant::serialize_field( - &mut __serde_state, - __field2, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeTupleVariant::serialize_field( - &mut __serde_state, - __field3, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - _serde::ser::SerializeTupleVariant::end(__serde_state) - } - SerEnum::_Map2 { - ref a, - ref b, - ref c, - ref d, - } => { - let mut __serde_state = match _serde::Serializer::serialize_struct_variant( - __serializer, - "SerEnum", - 5u32, - "_Map2", - 0 + 1 + 1 + 1 + 1, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeStructVariant::serialize_field( - &mut __serde_state, - "a", - a, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeStructVariant::serialize_field( - &mut __serde_state, - "b", - b, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeStructVariant::serialize_field( - &mut __serde_state, - "c", - c, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - match _serde::ser::SerializeStructVariant::serialize_field( - &mut __serde_state, - "d", - d, - ) { - _serde::__private::Ok(__val) => __val, - _serde::__private::Err(__err) => { - return _serde::__private::Err(__err); - } - }; - _serde::ser::SerializeStructVariant::end(__serde_state) - } - } - } - } -}; diff --git a/test_suite/tests/expand/ser_enum.rs b/test_suite/tests/expand/ser_enum.rs deleted file mode 100644 index 15c97a23..00000000 --- a/test_suite/tests/expand/ser_enum.rs +++ /dev/null @@ -1,16 +0,0 @@ -use serde::Serialize; - -#[derive(Serialize)] -enum SerEnum<'a, B: 'a, C: 'a, D> -where - D: 'a, -{ - Unit, - Seq(i8, B, &'a C, &'a mut D), - Map { a: i8, b: B, c: &'a C, d: &'a mut D }, - - // Make sure we can support more than one variant. - _Unit2, - _Seq2(i8, B, &'a C, &'a mut D), - _Map2 { a: i8, b: B, c: &'a C, d: &'a mut D }, -} diff --git a/test_suite/tests/expand/void.expanded.rs b/test_suite/tests/expand/void.expanded.rs deleted file mode 100644 index 35e6763d..00000000 --- a/test_suite/tests/expand/void.expanded.rs +++ /dev/null @@ -1,132 +0,0 @@ -use serde::{Deserialize, Serialize}; -enum Void {} -#[doc(hidden)] -#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] -const _: () = { - #[allow(unused_extern_crates, clippy::useless_attribute)] - extern crate serde as _serde; - #[automatically_derived] - impl _serde::Serialize for Void { - fn serialize<__S>( - &self, - __serializer: __S, - ) -> _serde::__private::Result<__S::Ok, __S::Error> - where - __S: _serde::Serializer, - { - match *self {} - } - } -}; -#[doc(hidden)] -#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] -const _: () = { - #[allow(unused_extern_crates, clippy::useless_attribute)] - extern crate serde as _serde; - #[automatically_derived] - impl<'de> _serde::Deserialize<'de> for Void { - fn deserialize<__D>(__deserializer: __D) -> _serde::__private::Result - where - __D: _serde::Deserializer<'de>, - { - #[allow(non_camel_case_types)] - enum __Field {} - struct __FieldVisitor; - impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { - type Value = __Field; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result { - _serde::__private::Formatter::write_str(__formatter, "variant identifier") - } - fn visit_u64<__E>(self, __value: u64) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - _ => _serde::__private::Err(_serde::de::Error::invalid_value( - _serde::de::Unexpected::Unsigned(__value), - &"variant index 0 <= i < 0", - )), - } - } - fn visit_str<__E>( - self, - __value: &str, - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - _ => _serde::__private::Err(_serde::de::Error::unknown_variant( - __value, VARIANTS, - )), - } - } - fn visit_bytes<__E>( - self, - __value: &[u8], - ) -> _serde::__private::Result - where - __E: _serde::de::Error, - { - match __value { - _ => { - let __value = &_serde::__private::from_utf8_lossy(__value); - _serde::__private::Err(_serde::de::Error::unknown_variant( - __value, VARIANTS, - )) - } - } - } - } - impl<'de> _serde::Deserialize<'de> for __Field { - #[inline] - fn deserialize<__D>( - __deserializer: __D, - ) -> _serde::__private::Result - where - __D: _serde::Deserializer<'de>, - { - _serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor) - } - } - struct __Visitor<'de> { - marker: _serde::__private::PhantomData, - lifetime: _serde::__private::PhantomData<&'de ()>, - } - impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> { - type Value = Void; - fn expecting( - &self, - __formatter: &mut _serde::__private::Formatter, - ) -> _serde::__private::fmt::Result { - _serde::__private::Formatter::write_str(__formatter, "enum Void") - } - fn visit_enum<__A>( - self, - __data: __A, - ) -> _serde::__private::Result - where - __A: _serde::de::EnumAccess<'de>, - { - _serde::__private::Result::map( - _serde::de::EnumAccess::variant::<__Field>(__data), - |(__impossible, _)| match __impossible {}, - ) - } - } - const VARIANTS: &'static [&'static str] = &[]; - _serde::Deserializer::deserialize_enum( - __deserializer, - "Void", - VARIANTS, - __Visitor { - marker: _serde::__private::PhantomData::, - lifetime: _serde::__private::PhantomData, - }, - ) - } - } -}; diff --git a/test_suite/tests/expand/void.rs b/test_suite/tests/expand/void.rs deleted file mode 100644 index bd0d7f4a..00000000 --- a/test_suite/tests/expand/void.rs +++ /dev/null @@ -1,4 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Serialize, Deserialize)] -enum Void {} diff --git a/test_suite/tests/expandtest.rs b/test_suite/tests/expandtest.rs deleted file mode 100644 index 84516970..00000000 --- a/test_suite/tests/expandtest.rs +++ /dev/null @@ -1,8 +0,0 @@ -#[cfg_attr(target_os = "emscripten", ignore)] -#[cfg_attr(not(expandtest), ignore)] -#[rustversion::attr(not(nightly), ignore)] -#[allow(unused_attributes)] -#[test] -fn expandtest() { - macrotest::expand("tests/expand/*.rs"); -} diff --git a/test_suite/tests/macros/mod.rs b/test_suite/tests/macros/mod.rs index 282d2069..d6632446 100644 --- a/test_suite/tests/macros/mod.rs +++ b/test_suite/tests/macros/mod.rs @@ -1,3 +1,5 @@ +#![allow(unused_macro_rules)] + use serde_test::Token; use std::iter; diff --git a/test_suite/tests/regression.rs b/test_suite/tests/regression.rs new file mode 100644 index 00000000..fb2b25c8 --- /dev/null +++ b/test_suite/tests/regression.rs @@ -0,0 +1,3 @@ +mod regression { + automod::dir!("tests/regression"); +} diff --git a/test_suite/tests/regression/issue2371.rs b/test_suite/tests/regression/issue2371.rs new file mode 100644 index 00000000..e4832af3 --- /dev/null +++ b/test_suite/tests/regression/issue2371.rs @@ -0,0 +1,43 @@ +use serde_derive::Deserialize; + +#[derive(Deserialize)] +pub struct Nested; + +#[derive(Deserialize)] +pub enum ExternallyTagged { + Flatten { + #[serde(flatten)] + nested: Nested, + string: &'static str, + }, +} + +#[derive(Deserialize)] +#[serde(tag = "tag")] +pub enum InternallyTagged { + Flatten { + #[serde(flatten)] + nested: Nested, + string: &'static str, + }, +} + +#[derive(Deserialize)] +#[serde(tag = "tag", content = "content")] +pub enum AdjacentlyTagged { + Flatten { + #[serde(flatten)] + nested: Nested, + string: &'static str, + }, +} + +#[derive(Deserialize)] +#[serde(untagged)] +pub enum UntaggedWorkaround { + Flatten { + #[serde(flatten)] + nested: Nested, + string: &'static str, + }, +} diff --git a/test_suite/tests/regression/issue2409.rs b/test_suite/tests/regression/issue2409.rs new file mode 100644 index 00000000..cdfe4dc5 --- /dev/null +++ b/test_suite/tests/regression/issue2409.rs @@ -0,0 +1,11 @@ +use serde_derive::Deserialize; + +macro_rules! bug { + ($serde_path:literal) => { + #[derive(Deserialize)] + #[serde(crate = $serde_path)] + pub struct Struct; + }; +} + +bug!("serde"); diff --git a/test_suite/tests/regression/issue2415.rs b/test_suite/tests/regression/issue2415.rs new file mode 100644 index 00000000..31c52270 --- /dev/null +++ b/test_suite/tests/regression/issue2415.rs @@ -0,0 +1,5 @@ +use serde_derive::Serialize; + +#[derive(Serialize)] +#[serde()] +pub struct S; diff --git a/test_suite/tests/test_annotations.rs b/test_suite/tests/test_annotations.rs index c97de81a..566f7d43 100644 --- a/test_suite/tests/test_annotations.rs +++ b/test_suite/tests/test_annotations.rs @@ -1,24 +1,26 @@ #![allow( clippy::cast_lossless, + clippy::derive_partial_eq_without_eq, clippy::from_over_into, // Clippy bug: https://github.com/rust-lang/rust-clippy/issues/7422 clippy::nonstandard_macro_braces, clippy::too_many_lines, - clippy::trivially_copy_pass_by_ref + clippy::trivially_copy_pass_by_ref, + clippy::type_repetition_in_bounds, + clippy::uninlined_format_args, )] -use serde::de::{self, MapAccess, Unexpected, Visitor}; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; - -use std::collections::{BTreeMap, HashMap}; -use std::convert::TryFrom; -use std::fmt; -use std::marker::PhantomData; - +use serde::de::{self, Deserialize, Deserializer, IgnoredAny, MapAccess, Unexpected, Visitor}; +use serde::ser::{Serialize, Serializer}; +use serde_derive::{Deserialize, Serialize}; use serde_test::{ assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_ser_tokens_error, assert_tokens, Token, }; +use std::collections::{BTreeMap, HashMap}; +use std::convert::TryFrom; +use std::fmt; +use std::marker::PhantomData; trait MyDefault: Sized { fn my_default() -> Self; @@ -112,42 +114,6 @@ struct CollectOther { extra: HashMap, } -#[derive(Debug, PartialEq, Serialize, Deserialize)] -struct FlattenStructEnumWrapper { - #[serde(flatten)] - data: FlattenStructEnum, - #[serde(flatten)] - extra: HashMap, -} - -#[derive(Debug, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -enum FlattenStructEnum { - InsertInteger { index: u32, value: u32 }, -} - -#[derive(Debug, PartialEq, Serialize, Deserialize)] -struct FlattenStructTagContentEnumWrapper { - outer: u32, - #[serde(flatten)] - data: FlattenStructTagContentEnumNewtype, -} - -#[derive(Debug, PartialEq, Serialize, Deserialize)] -struct FlattenStructTagContentEnumNewtype(pub FlattenStructTagContentEnum); - -#[derive(Debug, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "snake_case", tag = "type", content = "value")] -enum FlattenStructTagContentEnum { - InsertInteger { index: u32, value: u32 }, - NewtypeVariant(FlattenStructTagContentEnumNewtypeVariant), -} - -#[derive(Debug, PartialEq, Serialize, Deserialize)] -struct FlattenStructTagContentEnumNewtypeVariant { - value: u32, -} - #[test] fn test_default_struct() { assert_de_tokens( @@ -639,7 +605,7 @@ fn test_unknown_field_rename_struct() { Token::Str("a4"), Token::I32(3), ], - "unknown field `a4`, expected one of `a1`, `a2`, `a6`", + "unknown field `a4`, expected one of `a1`, `a2`, `a3`, `a5`, `a6`", ); } @@ -777,7 +743,7 @@ fn test_rename_enum() { Token::StructVariant { name: "AliasEnum", variant: "sailor_moon", - len: 3, + len: 5, }, Token::Str("a"), Token::I8(0), @@ -795,7 +761,7 @@ fn test_rename_enum() { Token::StructVariant { name: "AliasEnum", variant: "usagi_tsukino", - len: 3, + len: 5, }, Token::Str("a"), Token::I8(0), @@ -824,7 +790,7 @@ fn test_unknown_field_rename_enum() { Token::StructVariant { name: "AliasEnum", variant: "usagi_tsukino", - len: 3, + len: 5, }, Token::Str("a"), Token::I8(0), @@ -833,7 +799,7 @@ fn test_unknown_field_rename_enum() { Token::Str("d"), Token::I8(2), ], - "unknown field `d`, expected one of `a`, `b`, `f`", + "unknown field `d`, expected one of `a`, `b`, `c`, `e`, `f`", ); } @@ -1233,7 +1199,7 @@ fn serialize_variant_as_string(f1: &str, f2: &u8, serializer: S) -> Result(deserializer: D) -> Result<(String, u8), D::Error> @@ -1242,22 +1208,17 @@ where { let s = String::deserialize(deserializer)?; let mut pieces = s.split(';'); - let f1 = match pieces.next() { - Some(x) => x, - None => return Err(de::Error::invalid_length(0, &"2")), + let Some(f1) = pieces.next() else { + return Err(de::Error::invalid_length(0, &"2")); }; - let f2 = match pieces.next() { - Some(x) => x, - None => return Err(de::Error::invalid_length(1, &"2")), + let Some(f2) = pieces.next() else { + return Err(de::Error::invalid_length(1, &"2")); }; - let f2 = match f2.parse() { - Ok(n) => n, - Err(_) => { - return Err(de::Error::invalid_value( - Unexpected::Str(f2), - &"an 8-bit signed integer", - )); - } + let Ok(f2) = f2.parse() else { + return Err(de::Error::invalid_value( + Unexpected::Str(f2), + &"an 8-bit signed integer", + )); }; Ok((f1.into(), f2)) } @@ -1535,7 +1496,7 @@ fn test_invalid_length_enum() { Token::TupleVariant { name: "InvalidLengthEnum", variant: "B", - len: 3, + len: 2, }, Token::I32(1), Token::TupleVariantEnd, @@ -1646,149 +1607,6 @@ fn test_collect_other() { ); } -#[test] -fn test_flatten_struct_enum() { - let mut extra = HashMap::new(); - extra.insert("extra_key".into(), "extra value".into()); - let change_request = FlattenStructEnumWrapper { - data: FlattenStructEnum::InsertInteger { - index: 0, - value: 42, - }, - extra, - }; - assert_de_tokens( - &change_request, - &[ - Token::Map { len: None }, - Token::Str("insert_integer"), - Token::Map { len: None }, - Token::Str("index"), - Token::U32(0), - Token::Str("value"), - Token::U32(42), - Token::MapEnd, - Token::Str("extra_key"), - Token::Str("extra value"), - Token::MapEnd, - ], - ); - assert_ser_tokens( - &change_request, - &[ - Token::Map { len: None }, - Token::Str("insert_integer"), - Token::Struct { - len: 2, - name: "insert_integer", - }, - Token::Str("index"), - Token::U32(0), - Token::Str("value"), - Token::U32(42), - Token::StructEnd, - Token::Str("extra_key"), - Token::Str("extra value"), - Token::MapEnd, - ], - ); -} - -#[test] -fn test_flatten_struct_tag_content_enum() { - let change_request = FlattenStructTagContentEnumWrapper { - outer: 42, - data: FlattenStructTagContentEnumNewtype(FlattenStructTagContentEnum::InsertInteger { - index: 0, - value: 42, - }), - }; - assert_de_tokens( - &change_request, - &[ - Token::Map { len: None }, - Token::Str("outer"), - Token::U32(42), - Token::Str("type"), - Token::Str("insert_integer"), - Token::Str("value"), - Token::Map { len: None }, - Token::Str("index"), - Token::U32(0), - Token::Str("value"), - Token::U32(42), - Token::MapEnd, - Token::MapEnd, - ], - ); - assert_ser_tokens( - &change_request, - &[ - Token::Map { len: None }, - Token::Str("outer"), - Token::U32(42), - Token::Str("type"), - Token::Str("insert_integer"), - Token::Str("value"), - Token::Struct { - len: 2, - name: "insert_integer", - }, - Token::Str("index"), - Token::U32(0), - Token::Str("value"), - Token::U32(42), - Token::StructEnd, - Token::MapEnd, - ], - ); -} - -#[test] -fn test_flatten_struct_tag_content_enum_newtype() { - let change_request = FlattenStructTagContentEnumWrapper { - outer: 42, - data: FlattenStructTagContentEnumNewtype(FlattenStructTagContentEnum::NewtypeVariant( - FlattenStructTagContentEnumNewtypeVariant { value: 23 }, - )), - }; - assert_de_tokens( - &change_request, - &[ - Token::Map { len: None }, - Token::Str("outer"), - Token::U32(42), - Token::Str("type"), - Token::Str("newtype_variant"), - Token::Str("value"), - Token::Map { len: None }, - Token::Str("value"), - Token::U32(23), - Token::MapEnd, - Token::MapEnd, - ], - ); - assert_ser_tokens( - &change_request, - &[ - Token::Map { len: None }, - Token::Str("outer"), - Token::U32(42), - Token::Str("type"), - Token::Str("newtype_variant"), - Token::Str("value"), - Token::Struct { - len: 1, - name: "FlattenStructTagContentEnumNewtypeVariant", - }, - Token::Str("value"), - Token::U32(23), - Token::StructEnd, - Token::MapEnd, - ], - ); -} - #[test] fn test_unknown_field_in_flatten() { #[derive(Debug, PartialEq, Serialize, Deserialize)] @@ -2145,86 +1963,6 @@ fn test_lifetime_propagation_for_flatten() { ); } -#[test] -fn test_flatten_enum_newtype() { - #[derive(Serialize, Deserialize, PartialEq, Debug)] - struct S { - #[serde(flatten)] - flat: E, - } - - #[derive(Serialize, Deserialize, PartialEq, Debug)] - enum E { - Q(HashMap), - } - - let e = E::Q({ - let mut map = HashMap::new(); - map.insert("k".to_owned(), "v".to_owned()); - map - }); - let s = S { flat: e }; - - assert_tokens( - &s, - &[ - Token::Map { len: None }, - Token::Str("Q"), - Token::Map { len: Some(1) }, - Token::Str("k"), - Token::Str("v"), - Token::MapEnd, - Token::MapEnd, - ], - ); -} - -#[test] -fn test_flatten_internally_tagged() { - #[derive(Serialize, Deserialize, PartialEq, Debug)] - struct S { - #[serde(flatten)] - x: X, - #[serde(flatten)] - y: Y, - } - - #[derive(Serialize, Deserialize, PartialEq, Debug)] - #[serde(tag = "typeX")] - enum X { - A { a: i32 }, - B { b: i32 }, - } - - #[derive(Serialize, Deserialize, PartialEq, Debug)] - #[serde(tag = "typeY")] - enum Y { - C { c: i32 }, - D { d: i32 }, - } - - let s = S { - x: X::B { b: 1 }, - y: Y::D { d: 2 }, - }; - - assert_tokens( - &s, - &[ - Token::Map { len: None }, - Token::Str("typeX"), - Token::Str("B"), - Token::Str("b"), - Token::I32(1), - Token::Str("typeY"), - Token::Str("D"), - Token::Str("d"), - Token::I32(2), - Token::MapEnd, - ], - ); -} - #[test] fn test_externally_tagged_enum_containing_flatten() { #[derive(Serialize, Deserialize, PartialEq, Debug)] @@ -2263,6 +2001,39 @@ fn test_externally_tagged_enum_containing_flatten() { ); } +#[test] +fn test_internally_tagged_enum_with_skipped_conflict() { + #[derive(Serialize, Deserialize, PartialEq, Debug)] + #[serde(tag = "t")] + enum Data { + A, + #[serde(skip)] + #[allow(dead_code)] + B { + t: String, + }, + C { + #[serde(default, skip)] + t: String, + }, + } + + let data = Data::C { t: String::new() }; + + assert_tokens( + &data, + &[ + Token::Struct { + name: "Data", + len: 1, + }, + Token::Str("t"), + Token::Str("C"), + Token::StructEnd, + ], + ); +} + #[test] fn test_internally_tagged_enum_containing_flatten() { #[derive(Serialize, Deserialize, PartialEq, Debug)] @@ -2300,6 +2071,78 @@ fn test_internally_tagged_enum_containing_flatten() { ); } +#[test] +fn test_internally_tagged_enum_new_type_with_unit() { + #[derive(Serialize, Deserialize, PartialEq, Debug)] + #[serde(tag = "t")] + enum Data { + A(()), + } + + assert_tokens( + &Data::A(()), + &[ + Token::Map { len: Some(1) }, + Token::Str("t"), + Token::Str("A"), + Token::MapEnd, + ], + ); +} + +#[test] +fn test_adjacently_tagged_enum_bytes() { + #[derive(Serialize, Deserialize, PartialEq, Debug)] + #[serde(tag = "t", content = "c")] + enum Data { + A { a: i32 }, + } + + let data = Data::A { a: 0 }; + + assert_tokens( + &data, + &[ + Token::Struct { + name: "Data", + len: 2, + }, + Token::Str("t"), + Token::UnitVariant { + name: "Data", + variant: "A", + }, + Token::Str("c"), + Token::Struct { name: "A", len: 1 }, + Token::Str("a"), + Token::I32(0), + Token::StructEnd, + Token::StructEnd, + ], + ); + + assert_de_tokens( + &data, + &[ + Token::Struct { + name: "Data", + len: 2, + }, + Token::Bytes(b"t"), + Token::UnitVariant { + name: "Data", + variant: "A", + }, + Token::Bytes(b"c"), + Token::Struct { name: "A", len: 1 }, + Token::Str("a"), + Token::I32(0), + Token::StructEnd, + Token::StructEnd, + ], + ); +} + #[test] fn test_adjacently_tagged_enum_containing_flatten() { #[derive(Serialize, Deserialize, PartialEq, Debug)] @@ -2330,7 +2173,10 @@ fn test_adjacently_tagged_enum_containing_flatten() { len: 2, }, Token::Str("t"), - Token::Str("A"), + Token::UnitVariant { + name: "Data", + variant: "A", + }, Token::Str("c"), Token::Map { len: None }, Token::Str("a"), @@ -2379,32 +2225,221 @@ fn test_untagged_enum_containing_flatten() { } #[test] -fn test_flatten_untagged_enum() { +fn test_partially_untagged_enum() { #[derive(Serialize, Deserialize, PartialEq, Debug)] - struct Outer { - #[serde(flatten)] - inner: Inner, + enum Exp { + Lambda(u32, Box), + #[serde(untagged)] + App(Box, Box), + #[serde(untagged)] + Var(u32), } + use Exp::*; - #[derive(Serialize, Deserialize, PartialEq, Debug)] - #[serde(untagged)] - enum Inner { - Variant { a: i32 }, - } - - let data = Outer { - inner: Inner::Variant { a: 0 }, - }; - + let data = Lambda(0, Box::new(App(Box::new(Var(0)), Box::new(Var(0))))); assert_tokens( + &data, + &[ + Token::TupleVariant { + name: "Exp", + variant: "Lambda", + len: 2, + }, + Token::U32(0), + Token::Tuple { len: 2 }, + Token::U32(0), + Token::U32(0), + Token::TupleEnd, + Token::TupleVariantEnd, + ], + ); +} + +#[test] +fn test_partially_untagged_enum_generic() { + trait Trait { + type Assoc; + type Assoc2; + } + + #[derive(Serialize, Deserialize, PartialEq, Debug)] + enum E + where + A: Trait, + { + A(A::Assoc), + #[serde(untagged)] + B(A::Assoc2), + } + + impl Trait for () { + type Assoc = T; + type Assoc2 = bool; + } + + type MyE = E<(), bool, u32>; + use E::*; + + assert_tokens::(&B(true), &[Token::Bool(true)]); + + assert_tokens::( + &A(5), + &[ + Token::NewtypeVariant { + name: "E", + variant: "A", + }, + Token::U32(5), + ], + ); +} + +#[test] +fn test_partially_untagged_enum_desugared() { + #[derive(Serialize, Deserialize, PartialEq, Debug)] + enum Test { + A(u32, u32), + B(u32), + #[serde(untagged)] + C(u32), + #[serde(untagged)] + D(u32, u32), + } + use Test::*; + + mod desugared { + use super::*; + #[derive(Serialize, Deserialize, PartialEq, Debug)] + pub(super) enum Test { + A(u32, u32), + B(u32), + } + } + use desugared::Test as TestTagged; + + #[derive(Serialize, Deserialize, PartialEq, Debug)] + #[serde(untagged)] + enum TestUntagged { + Tagged(TestTagged), + C(u32), + D(u32, u32), + } + + impl From for TestUntagged { + fn from(test: Test) -> Self { + match test { + A(x, y) => TestUntagged::Tagged(TestTagged::A(x, y)), + B(x) => TestUntagged::Tagged(TestTagged::B(x)), + C(x) => TestUntagged::C(x), + D(x, y) => TestUntagged::D(x, y), + } + } + } + + fn assert_tokens_desugared(value: Test, tokens: &[Token]) { + assert_tokens(&value, tokens); + let desugared: TestUntagged = value.into(); + assert_tokens(&desugared, tokens); + } + + assert_tokens_desugared( + A(0, 1), + &[ + Token::TupleVariant { + name: "Test", + variant: "A", + len: 2, + }, + Token::U32(0), + Token::U32(1), + Token::TupleVariantEnd, + ], + ); + + assert_tokens_desugared( + B(1), + &[ + Token::NewtypeVariant { + name: "Test", + variant: "B", + }, + Token::U32(1), + ], + ); + + assert_tokens_desugared(C(2), &[Token::U32(2)]); + + assert_tokens_desugared( + D(3, 5), + &[ + Token::Tuple { len: 2 }, + Token::U32(3), + Token::U32(5), + Token::TupleEnd, + ], + ); +} + +#[test] +fn test_partially_untagged_internally_tagged_enum() { + #[derive(Serialize, Deserialize, PartialEq, Debug)] + #[serde(tag = "t")] + enum Data { + A, + B, + #[serde(untagged)] + Var(u32), + } + + let data = Data::A; + + assert_de_tokens( &data, &[ Token::Map { len: None }, - Token::Str("a"), - Token::I32(0), + Token::Str("t"), + Token::Str("A"), Token::MapEnd, ], ); + + let data = Data::Var(42); + + assert_de_tokens(&data, &[Token::U32(42)]); + + // TODO test error output +} + +#[test] +fn test_partially_untagged_adjacently_tagged_enum() { + #[derive(Serialize, Deserialize, PartialEq, Debug)] + #[serde(tag = "t", content = "c")] + enum Data { + A(u32), + B, + #[serde(untagged)] + Var(u32), + } + + let data = Data::A(7); + + assert_de_tokens( + &data, + &[ + Token::Map { len: None }, + Token::Str("t"), + Token::Str("A"), + Token::Str("c"), + Token::U32(7), + Token::MapEnd, + ], + ); + + let data = Data::Var(42); + + assert_de_tokens(&data, &[Token::U32(42)]); + + // TODO test error output } #[test] @@ -2477,6 +2512,31 @@ fn test_flatten_option() { ); } +#[test] +fn test_flatten_ignored_any() { + #[derive(Deserialize, PartialEq, Debug)] + struct Outer { + #[serde(flatten)] + inner: IgnoredAny, + } + + assert_de_tokens( + &Outer { inner: IgnoredAny }, + &[Token::Map { len: None }, Token::MapEnd], + ); + + assert_de_tokens( + &Outer { inner: IgnoredAny }, + &[ + Token::Struct { + name: "DoNotMatter", + len: 0, + }, + Token::StructEnd, + ], + ); +} + #[test] fn test_transparent_struct() { #[derive(Serialize, Deserialize, PartialEq, Debug)] @@ -2538,48 +2598,6 @@ fn test_internally_tagged_unit_enum_with_unknown_fields() { ); } -#[test] -fn test_flattened_internally_tagged_unit_enum_with_unknown_fields() { - #[derive(Deserialize, PartialEq, Debug)] - struct S { - #[serde(flatten)] - x: X, - #[serde(flatten)] - y: Y, - } - - #[derive(Deserialize, PartialEq, Debug)] - #[serde(tag = "typeX")] - enum X { - A, - } - - #[derive(Deserialize, PartialEq, Debug)] - #[serde(tag = "typeY")] - enum Y { - B { c: u32 }, - } - - let s = S { - x: X::A, - y: Y::B { c: 0 }, - }; - - assert_de_tokens( - &s, - &[ - Token::Map { len: None }, - Token::Str("typeX"), - Token::Str("A"), - Token::Str("typeY"), - Token::Str("B"), - Token::Str("c"), - Token::I32(0), - Token::MapEnd, - ], - ); -} - #[test] fn test_flatten_any_after_flatten_struct() { #[derive(PartialEq, Debug)] @@ -2641,6 +2659,68 @@ fn test_flatten_any_after_flatten_struct() { ); } +#[test] +fn test_alias_in_flatten_context() { + #[derive(Debug, PartialEq, Deserialize)] + struct Outer { + #[serde(flatten)] + a: AliasStruct, + b: i32, + } + + assert_de_tokens( + &Outer { + a: AliasStruct { + a1: 1, + a2: 2, + a4: 4, + }, + b: 7, + }, + &[ + Token::Struct { + name: "Outer", + len: 4, + }, + Token::Str("a1"), + Token::I32(1), + Token::Str("a2"), + Token::I32(2), + Token::Str("a5"), + Token::I32(4), + Token::Str("b"), + Token::I32(7), + Token::StructEnd, + ], + ); + + assert_de_tokens( + &Outer { + a: AliasStruct { + a1: 1, + a2: 2, + a4: 4, + }, + b: 7, + }, + &[ + Token::Struct { + name: "Outer", + len: 4, + }, + Token::Str("a1"), + Token::I32(1), + Token::Str("a2"), + Token::I32(2), + Token::Str("a6"), + Token::I32(4), + Token::Str("b"), + Token::I32(7), + Token::StructEnd, + ], + ); +} + #[test] fn test_expecting_message() { #[derive(Deserialize, PartialEq, Debug)] @@ -2658,7 +2738,9 @@ fn test_expecting_message() { #[derive(Deserialize)] #[serde(expecting = "something strange...")] struct Struct { + #[allow(dead_code)] question: String, + #[allow(dead_code)] answer: u32, } @@ -2699,7 +2781,7 @@ fn test_expecting_message_externally_tagged_enum() { // Check that #[serde(expecting = "...")] doesn't affect variant identifier error message assert_de_tokens_error::( &[Token::Enum { name: "Enum" }, Token::Unit], - r#"invalid type: unit value, expected variant identifier"#, + "invalid type: unit value, expected variant identifier", ); } @@ -2720,7 +2802,7 @@ fn test_expecting_message_internally_tagged_enum() { // Check that #[serde(expecting = "...")] doesn't affect variant identifier error message assert_de_tokens_error::( &[Token::Map { len: None }, Token::Str("tag"), Token::Unit], - r#"invalid type: unit value, expected variant identifier"#, + "invalid type: unit value, expected variant identifier", ); } @@ -2746,7 +2828,7 @@ fn test_expecting_message_adjacently_tagged_enum() { // Check that #[serde(expecting = "...")] doesn't affect variant identifier error message assert_de_tokens_error::( &[Token::Map { len: None }, Token::Str("tag"), Token::Unit], - r#"invalid type: unit value, expected variant identifier"#, + "invalid type: unit value, expected variant of enum Enum", ); } @@ -2759,7 +2841,7 @@ fn test_expecting_message_untagged_tagged_enum() { Untagged, } - assert_de_tokens_error::(&[Token::Str("Untagged")], r#"something strange..."#); + assert_de_tokens_error::(&[Token::Str("Untagged")], "something strange..."); } #[test] @@ -2780,7 +2862,7 @@ fn test_expecting_message_identifier_enum() { assert_de_tokens_error::( &[Token::Unit], - r#"invalid type: unit value, expected something strange..."#, + "invalid type: unit value, expected something strange...", ); assert_de_tokens_error::( @@ -2789,12 +2871,12 @@ fn test_expecting_message_identifier_enum() { Token::Str("Unknown"), Token::None, ], - r#"invalid type: map, expected something strange..."#, + "invalid type: map, expected something strange...", ); assert_de_tokens_error::( &[Token::Unit], - r#"invalid type: unit value, expected something strange..."#, + "invalid type: unit value, expected something strange...", ); assert_de_tokens_error::( @@ -2805,6 +2887,348 @@ fn test_expecting_message_identifier_enum() { Token::Str("Unknown"), Token::None, ], - r#"invalid type: map, expected something strange..."#, + "invalid type: map, expected something strange...", ); } + +mod flatten { + use super::*; + + mod enum_ { + use super::*; + + mod externally_tagged { + use super::*; + use std::iter::FromIterator; + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + struct Flatten { + #[serde(flatten)] + data: Enum, + + #[serde(flatten)] + extra: HashMap, + } + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + enum Enum { + Newtype(HashMap), + Tuple(u32, u32), + Struct { index: u32, value: u32 }, + } + + #[test] + fn newtype() { + assert_tokens( + &Flatten { + data: Enum::Newtype(HashMap::from_iter([("key".into(), "value".into())])), + extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]), + }, + &[ + Token::Map { len: None }, + Token::Str("Newtype"), // variant + Token::Map { len: Some(1) }, + Token::Str("key"), + Token::Str("value"), + Token::MapEnd, + Token::Str("extra_key"), + Token::Str("extra value"), + Token::MapEnd, + ], + ); + } + + // Reaches crate::private::de::content::VariantDeserializer::tuple_variant + // Content::Seq case + // via FlatMapDeserializer::deserialize_enum + #[test] + fn tuple() { + assert_tokens( + &Flatten { + data: Enum::Tuple(0, 42), + extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]), + }, + &[ + Token::Map { len: None }, + Token::Str("Tuple"), // variant + Token::Seq { len: Some(2) }, + Token::U32(0), + Token::U32(42), + Token::SeqEnd, + Token::Str("extra_key"), + Token::Str("extra value"), + Token::MapEnd, + ], + ); + } + + // Reaches crate::private::de::content::VariantDeserializer::struct_variant + // Content::Seq case + // via FlatMapDeserializer::deserialize_enum + #[test] + fn struct_from_seq() { + assert_de_tokens( + &Flatten { + data: Enum::Struct { + index: 0, + value: 42, + }, + extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]), + }, + &[ + Token::Map { len: None }, + Token::Str("Struct"), // variant + Token::Seq { len: Some(2) }, + Token::U32(0), // index + Token::U32(42), // value + Token::SeqEnd, + Token::Str("extra_key"), + Token::Str("extra value"), + Token::MapEnd, + ], + ); + } + + // Reaches crate::private::de::content::VariantDeserializer::struct_variant + // Content::Map case + // via FlatMapDeserializer::deserialize_enum + #[test] + fn struct_from_map() { + assert_tokens( + &Flatten { + data: Enum::Struct { + index: 0, + value: 42, + }, + extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]), + }, + &[ + Token::Map { len: None }, + Token::Str("Struct"), // variant + Token::Struct { + len: 2, + name: "Struct", + }, + Token::Str("index"), + Token::U32(0), + Token::Str("value"), + Token::U32(42), + Token::StructEnd, + Token::Str("extra_key"), + Token::Str("extra value"), + Token::MapEnd, + ], + ); + } + } + + mod adjacently_tagged { + use super::*; + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + struct Flatten { + outer: u32, + + #[serde(flatten)] + data: NewtypeWrapper, + } + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + struct NewtypeWrapper(pub Enum); + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(tag = "tag", content = "content")] + enum Enum { + Newtype(NewtypeVariant), + Struct { index: u32, value: u32 }, + } + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + struct NewtypeVariant { + value: u32, + } + + #[test] + fn struct_() { + assert_tokens( + &Flatten { + outer: 42, + data: NewtypeWrapper(Enum::Struct { + index: 0, + value: 42, + }), + }, + &[ + Token::Map { len: None }, + Token::Str("outer"), + Token::U32(42), + Token::Str("tag"), + Token::UnitVariant { + name: "Enum", + variant: "Struct", + }, + Token::Str("content"), + Token::Struct { + len: 2, + name: "Struct", + }, + Token::Str("index"), + Token::U32(0), + Token::Str("value"), + Token::U32(42), + Token::StructEnd, + Token::MapEnd, + ], + ); + } + + #[test] + fn newtype() { + assert_tokens( + &Flatten { + outer: 42, + data: NewtypeWrapper(Enum::Newtype(NewtypeVariant { value: 23 })), + }, + &[ + Token::Map { len: None }, + Token::Str("outer"), + Token::U32(42), + Token::Str("tag"), + Token::UnitVariant { + name: "Enum", + variant: "Newtype", + }, + Token::Str("content"), + Token::Struct { + len: 1, + name: "NewtypeVariant", + }, + Token::Str("value"), + Token::U32(23), + Token::StructEnd, + Token::MapEnd, + ], + ); + } + } + + mod internally_tagged { + use super::*; + + #[test] + fn structs() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + struct Flatten { + #[serde(flatten)] + x: X, + #[serde(flatten)] + y: Y, + } + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(tag = "typeX")] + enum X { + A { a: i32 }, + B { b: i32 }, + } + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(tag = "typeY")] + enum Y { + C { c: i32 }, + D { d: i32 }, + } + + assert_tokens( + &Flatten { + x: X::B { b: 1 }, + y: Y::D { d: 2 }, + }, + &[ + Token::Map { len: None }, + Token::Str("typeX"), + Token::Str("B"), + Token::Str("b"), + Token::I32(1), + Token::Str("typeY"), + Token::Str("D"), + Token::Str("d"), + Token::I32(2), + Token::MapEnd, + ], + ); + } + + #[test] + fn unit_enum_with_unknown_fields() { + #[derive(Debug, PartialEq, Deserialize)] + struct Flatten { + #[serde(flatten)] + x: X, + #[serde(flatten)] + y: Y, + } + + #[derive(Debug, PartialEq, Deserialize)] + #[serde(tag = "typeX")] + enum X { + A, + } + + #[derive(Debug, PartialEq, Deserialize)] + #[serde(tag = "typeY")] + enum Y { + B { c: u32 }, + } + + assert_de_tokens( + &Flatten { + x: X::A, + y: Y::B { c: 0 }, + }, + &[ + Token::Map { len: None }, + Token::Str("typeX"), + Token::Str("A"), + Token::Str("typeY"), + Token::Str("B"), + Token::Str("c"), + Token::I32(0), + Token::MapEnd, + ], + ); + } + } + + mod untagged { + use super::*; + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + struct Flatten { + #[serde(flatten)] + data: Enum, + } + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(untagged)] + enum Enum { + Struct { a: i32 }, + } + + #[test] + fn struct_() { + assert_tokens( + &Flatten { + data: Enum::Struct { a: 0 }, + }, + &[ + Token::Map { len: None }, + Token::Str("a"), + Token::I32(0), + Token::MapEnd, + ], + ); + } + } + } +} diff --git a/test_suite/tests/test_borrow.rs b/test_suite/tests/test_borrow.rs index 7810b52b..f749ec32 100644 --- a/test_suite/tests/test_borrow.rs +++ b/test_suite/tests/test_borrow.rs @@ -1,8 +1,13 @@ -#![allow(clippy::items_after_statements, clippy::used_underscore_binding)] +#![allow( + clippy::derive_partial_eq_without_eq, + clippy::items_after_statements, + clippy::used_underscore_binding +)] -use serde::{Deserialize, Deserializer}; +use serde::de::value::{BorrowedStrDeserializer, MapDeserializer}; +use serde::de::{Deserialize, Deserializer, IntoDeserializer}; +use serde_derive::Deserialize; use serde_test::{assert_de_tokens, assert_de_tokens_error, Token}; - use std::borrow::Cow; #[test] @@ -126,20 +131,22 @@ fn test_cow() { borrowed: Cow<'b, str>, } - let tokens = &[ - Token::Struct { - name: "Cows", - len: 2, - }, - Token::Str("copied"), - Token::BorrowedStr("copied"), - Token::Str("borrowed"), - Token::BorrowedStr("borrowed"), - Token::StructEnd, - ]; + struct BorrowedStr(&'static str); - let mut de = serde_test::Deserializer::new(tokens); - let cows = Cows::deserialize(&mut de).unwrap(); + impl<'de> IntoDeserializer<'de> for BorrowedStr { + type Deserializer = BorrowedStrDeserializer<'de, serde::de::value::Error>; + + fn into_deserializer(self) -> Self::Deserializer { + BorrowedStrDeserializer::new(self.0) + } + } + + let de = MapDeserializer::new(IntoIterator::into_iter([ + ("copied", BorrowedStr("copied")), + ("borrowed", BorrowedStr("borrowed")), + ])); + + let cows = Cows::deserialize(de).unwrap(); match cows.copied { Cow::Owned(ref s) if s == "copied" => {} diff --git a/test_suite/tests/test_de.rs b/test_suite/tests/test_de.rs index b765449e..3ca0fde3 100644 --- a/test_suite/tests/test_de.rs +++ b/test_suite/tests/test_de.rs @@ -1,17 +1,25 @@ #![allow( clippy::cast_lossless, clippy::decimal_literal_representation, + clippy::derive_partial_eq_without_eq, clippy::empty_enum, clippy::manual_assert, clippy::needless_pass_by_value, + clippy::uninlined_format_args, clippy::unreadable_literal )] #![cfg_attr(feature = "unstable", feature(never_type))] +use fnv::FnvHasher; +use serde::de::value::{F32Deserializer, F64Deserializer}; +use serde::de::{Deserialize, DeserializeOwned, Deserializer, IntoDeserializer}; +use serde_derive::Deserialize; +use serde_test::{assert_de_tokens, Configure, Token}; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::default::Default; use std::ffi::{CStr, CString, OsString}; use std::fmt::Debug; +use std::iter; use std::net; use std::num::{ NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128, @@ -24,16 +32,10 @@ use std::sync::atomic::{ AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8, AtomicUsize, Ordering, }; -use std::sync::{Arc, Weak as ArcWeak}; -use std::time::{Duration, UNIX_EPOCH}; - #[cfg(target_arch = "x86_64")] use std::sync::atomic::{AtomicI64, AtomicU64}; - -use fnv::FnvHasher; -use serde::de::DeserializeOwned; -use serde::{Deserialize, Deserializer}; -use serde_test::{assert_de_tokens, Configure, Token}; +use std::sync::{Arc, Weak as ArcWeak}; +use std::time::{Duration, UNIX_EPOCH}; #[macro_use] mod macros; @@ -43,6 +45,9 @@ mod macros; #[derive(Copy, Clone, PartialEq, Debug, Deserialize)] struct UnitStruct; +#[derive(Copy, Clone, PartialEq, Debug, Deserialize)] +struct GenericUnitStruct; + #[derive(PartialEq, Debug, Deserialize)] struct NewtypeStruct(i32); @@ -197,12 +202,11 @@ fn assert_de_tokens_ignore(ignorable_tokens: &[Token]) { ] .into_iter() .chain(ignorable_tokens.iter().copied()) - .chain(vec![Token::MapEnd].into_iter()) + .chain(iter::once(Token::MapEnd)) .collect(); - let mut de = serde_test::Deserializer::new(&concated_tokens); - let base = IgnoreBase::deserialize(&mut de).unwrap(); - assert_eq!(base, IgnoreBase { a: 1 }); + let expected = IgnoreBase { a: 1 }; + assert_de_tokens(&expected, &concated_tokens); } ////////////////////////////////////////////////////////////////////////// @@ -829,6 +833,26 @@ fn test_f64() { test(1.11, &[Token::F64(1.11)]); } +#[test] +fn test_nan() { + let f32_deserializer = F32Deserializer::::new; + let f64_deserializer = F64Deserializer::::new; + + let pos_f32_nan = f32_deserializer(f32::NAN.copysign(1.0)); + let pos_f64_nan = f64_deserializer(f64::NAN.copysign(1.0)); + assert!(f32::deserialize(pos_f32_nan).unwrap().is_sign_positive()); + assert!(f32::deserialize(pos_f64_nan).unwrap().is_sign_positive()); + assert!(f64::deserialize(pos_f32_nan).unwrap().is_sign_positive()); + assert!(f64::deserialize(pos_f64_nan).unwrap().is_sign_positive()); + + let neg_f32_nan = f32_deserializer(f32::NAN.copysign(-1.0)); + let neg_f64_nan = f64_deserializer(f64::NAN.copysign(-1.0)); + assert!(f32::deserialize(neg_f32_nan).unwrap().is_sign_negative()); + assert!(f32::deserialize(neg_f64_nan).unwrap().is_sign_negative()); + assert!(f64::deserialize(neg_f32_nan).unwrap().is_sign_negative()); + assert!(f64::deserialize(neg_f64_nan).unwrap().is_sign_negative()); +} + #[test] fn test_char() { test('a', &[Token::Char('a')]); @@ -881,6 +905,17 @@ fn test_unit_struct() { test(UnitStruct, &[Token::UnitStruct { name: "UnitStruct" }]); } +#[test] +fn test_generic_unit_struct() { + test(GenericUnitStruct::<8>, &[Token::Unit]); + test( + GenericUnitStruct::<8>, + &[Token::UnitStruct { + name: "GenericUnitStruct", + }], + ); +} + #[test] fn test_newtype_struct() { test( @@ -1863,6 +1898,46 @@ fn test_range_inclusive() { ); } +#[test] +fn test_range_from() { + test( + 1u32.., + &[ + Token::Struct { + name: "RangeFrom", + len: 1, + }, + Token::Str("start"), + Token::U32(1), + Token::StructEnd, + ], + ); + test( + 1u32.., + &[Token::Seq { len: Some(1) }, Token::U32(1), Token::SeqEnd], + ); +} + +#[test] +fn test_range_to() { + test( + ..2u32, + &[ + Token::Struct { + name: "RangeTo", + len: 1, + }, + Token::Str("end"), + Token::U32(2), + Token::StructEnd, + ], + ); + test( + ..2u32, + &[Token::Seq { len: Some(1) }, Token::U32(2), Token::SeqEnd], + ); +} + #[test] fn test_bound() { test( @@ -2243,39 +2318,34 @@ fn test_cstr() { #[test] fn test_atomics() { - fn test(load: L, val: T, token: Token) + fn test(load: L, val: T) where L: Fn(&A, Ordering) -> T, A: DeserializeOwned, - T: PartialEq + Debug, + T: PartialEq + Debug + Copy + for<'de> IntoDeserializer<'de>, { - let tokens = &[token]; - let mut de = serde_test::Deserializer::new(tokens); - match A::deserialize(&mut de) { + match A::deserialize(val.into_deserializer()) { Ok(v) => { let loaded = load(&v, Ordering::Relaxed); assert_eq!(val, loaded); } Err(e) => panic!("tokens failed to deserialize: {}", e), - }; - if de.remaining() > 0 { - panic!("{} remaining tokens", de.remaining()); } } - test(AtomicBool::load, true, Token::Bool(true)); - test(AtomicI8::load, -127, Token::I8(-127i8)); - test(AtomicI16::load, -510, Token::I16(-510i16)); - test(AtomicI32::load, -131072, Token::I32(-131072i32)); - test(AtomicIsize::load, -131072isize, Token::I32(-131072)); - test(AtomicU8::load, 127, Token::U8(127u8)); - test(AtomicU16::load, 510u16, Token::U16(510u16)); - test(AtomicU32::load, 131072u32, Token::U32(131072u32)); - test(AtomicUsize::load, 131072usize, Token::U32(131072)); + test(AtomicBool::load, true); + test(AtomicI8::load, -127i8); + test(AtomicI16::load, -510i16); + test(AtomicI32::load, -131072i32); + test(AtomicIsize::load, -131072isize); + test(AtomicU8::load, 127u8); + test(AtomicU16::load, 510u16); + test(AtomicU32::load, 131072u32); + test(AtomicUsize::load, 131072usize); #[cfg(target_arch = "x86_64")] { - test(AtomicI64::load, -8589934592, Token::I64(-8589934592)); - test(AtomicU64::load, 8589934592u64, Token::U64(8589934592)); + test(AtomicI64::load, -8589934592i64); + test(AtomicU64::load, 8589934592u64); } } diff --git a/test_suite/tests/test_de_error.rs b/test_suite/tests/test_de_error.rs index d37c20c9..d1ea2b91 100644 --- a/test_suite/tests/test_de_error.rs +++ b/test_suite/tests/test_de_error.rs @@ -1,8 +1,12 @@ -#![allow(clippy::empty_enum, clippy::unreadable_literal)] +#![allow( + clippy::derive_partial_eq_without_eq, + clippy::empty_enum, + clippy::unreadable_literal +)] #![cfg_attr(feature = "unstable", feature(never_type))] -use serde::de::IntoDeserializer; -use serde::Deserialize; +use serde::de::{Deserialize, IntoDeserializer}; +use serde_derive::Deserialize; use serde_test::{assert_de_tokens_error, Token}; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::ffi::{CStr, CString}; @@ -1430,7 +1434,7 @@ fn test_number_from_string() { fn test_integer_from_float() { assert_de_tokens_error::( &[Token::F32(0.0)], - "invalid type: floating point `0`, expected isize", + "invalid type: floating point `0.0`, expected isize", ); } diff --git a/test_suite/tests/test_gen.rs b/test_suite/tests/test_gen.rs index fc8c0a6e..97b0a96e 100644 --- a/test_suite/tests/test_gen.rs +++ b/test_suite/tests/test_gen.rs @@ -6,6 +6,8 @@ #![allow( unknown_lints, mixed_script_confusables, + clippy::derive_partial_eq_without_eq, + clippy::extra_unused_type_parameters, clippy::items_after_statements, clippy::missing_errors_doc, clippy::missing_panics_doc, @@ -14,12 +16,13 @@ clippy::nonstandard_macro_braces, clippy::ptr_arg, clippy::too_many_lines, - clippy::trivially_copy_pass_by_ref + clippy::trivially_copy_pass_by_ref, + clippy::type_repetition_in_bounds )] -use serde::de::DeserializeOwned; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; - +use serde::de::{Deserialize, DeserializeOwned, Deserializer}; +use serde::ser::{Serialize, Serializer}; +use serde_derive::{Deserialize, Serialize}; use std::borrow::Cow; use std::marker::PhantomData; use std::option::Option as StdOption; @@ -254,6 +257,16 @@ fn test_gen() { } assert::>(); + type PhantomDataAlias = PhantomData; + + #[derive(Serialize, Deserialize)] + #[serde(bound = "")] + struct PhantomDataWrapper { + #[serde(default)] + field: PhantomDataAlias, + } + assert::>(); + #[derive(Serialize, Deserialize)] struct CowStr<'a>(Cow<'a, str>); assert::(); @@ -391,7 +404,7 @@ fn test_gen() { } mod vis { - use serde::{Deserialize, Serialize}; + use serde_derive::{Deserialize, Serialize}; pub struct S; @@ -623,7 +636,7 @@ fn test_gen() { mod restricted { mod inner { - use serde::{Deserialize, Serialize}; + use serde_derive::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] struct Restricted { @@ -649,6 +662,7 @@ fn test_gen() { #[derive(Deserialize)] struct ImplicitlyBorrowedOption<'a> { + #[allow(dead_code)] option: std::option::Option<&'a str>, } @@ -672,14 +686,16 @@ fn test_gen() { #[derive(Deserialize)] #[serde(untagged)] - enum UntaggedWithBorrow<'a> { + pub enum UntaggedWithBorrow<'a> { Single(#[serde(borrow)] RelObject<'a>), Many(#[serde(borrow)] Vec>), } #[derive(Deserialize)] struct RelObject<'a> { + #[allow(dead_code)] ty: &'a str, + #[allow(dead_code)] id: String, } @@ -723,6 +739,7 @@ fn test_gen() { ($field:ty) => { #[derive(Deserialize)] struct MacroRules<'a> { + #[allow(dead_code)] field: $field, } }; @@ -739,6 +756,7 @@ fn test_gen() { #[derive(Deserialize)] struct BorrowLifetimeInsideMacro<'a> { #[serde(borrow = "'a")] + #[allow(dead_code)] f: mac!(Cow<'a, str>), } @@ -747,6 +765,10 @@ fn test_gen() { #[serde(serialize_with = "vec_first_element")] vec: Vec, } + + #[derive(Deserialize)] + #[serde(bound(deserialize = "[&'de str; N]: Copy"))] + struct GenericUnitStruct; } ////////////////////////////////////////////////////////////////////////// @@ -821,7 +843,7 @@ pub fn is_zero(n: &u8) -> bool { *n == 0 } -fn vec_first_element(vec: &Vec, serializer: S) -> StdResult +fn vec_first_element(vec: &[T], serializer: S) -> StdResult where T: Serialize, S: Serializer, diff --git a/test_suite/tests/test_identifier.rs b/test_suite/tests/test_identifier.rs index 12c6697e..4e141414 100644 --- a/test_suite/tests/test_identifier.rs +++ b/test_suite/tests/test_identifier.rs @@ -1,85 +1,188 @@ //! Tests for `#[serde(field_identifier)]` and `#[serde(variant_identifier)]` -use serde::Deserialize; -use serde_test::{assert_de_tokens, Token}; -#[test] -fn test_variant_identifier() { +#![allow(clippy::derive_partial_eq_without_eq)] + +use serde_derive::Deserialize; +use serde_test::{assert_de_tokens, assert_de_tokens_error, Token}; + +mod variant_identifier { + use super::*; + #[derive(Deserialize, Debug, PartialEq)] #[serde(variant_identifier)] enum V { Aaa, + #[serde(alias = "Ccc", alias = "Ddd")] Bbb, } - assert_de_tokens(&V::Aaa, &[Token::U8(0)]); - assert_de_tokens(&V::Aaa, &[Token::U16(0)]); - assert_de_tokens(&V::Aaa, &[Token::U32(0)]); - assert_de_tokens(&V::Aaa, &[Token::U64(0)]); - assert_de_tokens(&V::Aaa, &[Token::Str("Aaa")]); - assert_de_tokens(&V::Aaa, &[Token::Bytes(b"Aaa")]); + #[test] + fn variant1() { + assert_de_tokens(&V::Aaa, &[Token::U8(0)]); + assert_de_tokens(&V::Aaa, &[Token::U16(0)]); + assert_de_tokens(&V::Aaa, &[Token::U32(0)]); + assert_de_tokens(&V::Aaa, &[Token::U64(0)]); + assert_de_tokens(&V::Aaa, &[Token::Str("Aaa")]); + assert_de_tokens(&V::Aaa, &[Token::Bytes(b"Aaa")]); + } + + #[test] + fn aliases() { + assert_de_tokens(&V::Bbb, &[Token::U8(1)]); + assert_de_tokens(&V::Bbb, &[Token::U16(1)]); + assert_de_tokens(&V::Bbb, &[Token::U32(1)]); + assert_de_tokens(&V::Bbb, &[Token::U64(1)]); + + assert_de_tokens(&V::Bbb, &[Token::Str("Bbb")]); + assert_de_tokens(&V::Bbb, &[Token::Bytes(b"Bbb")]); + + assert_de_tokens(&V::Bbb, &[Token::Str("Ccc")]); + assert_de_tokens(&V::Bbb, &[Token::Bytes(b"Ccc")]); + + assert_de_tokens(&V::Bbb, &[Token::Str("Ddd")]); + assert_de_tokens(&V::Bbb, &[Token::Bytes(b"Ddd")]); + } + + #[test] + fn unknown() { + assert_de_tokens_error::( + &[Token::U8(42)], + "invalid value: integer `42`, expected variant index 0 <= i < 2", + ); + assert_de_tokens_error::( + &[Token::U16(42)], + "invalid value: integer `42`, expected variant index 0 <= i < 2", + ); + assert_de_tokens_error::( + &[Token::U32(42)], + "invalid value: integer `42`, expected variant index 0 <= i < 2", + ); + assert_de_tokens_error::( + &[Token::U64(42)], + "invalid value: integer `42`, expected variant index 0 <= i < 2", + ); + assert_de_tokens_error::( + &[Token::Str("Unknown")], + "unknown variant `Unknown`, expected one of `Aaa`, `Bbb`, `Ccc`, `Ddd`", + ); + assert_de_tokens_error::( + &[Token::Bytes(b"Unknown")], + "unknown variant `Unknown`, expected one of `Aaa`, `Bbb`, `Ccc`, `Ddd`", + ); + } } -#[test] -fn test_field_identifier() { +mod field_identifier { + use super::*; + #[derive(Deserialize, Debug, PartialEq)] #[serde(field_identifier, rename_all = "snake_case")] enum F { Aaa, + #[serde(alias = "ccc", alias = "ddd")] Bbb, } - assert_de_tokens(&F::Aaa, &[Token::U8(0)]); - assert_de_tokens(&F::Aaa, &[Token::U16(0)]); - assert_de_tokens(&F::Aaa, &[Token::U32(0)]); - assert_de_tokens(&F::Aaa, &[Token::U64(0)]); - assert_de_tokens(&F::Aaa, &[Token::Str("aaa")]); - assert_de_tokens(&F::Aaa, &[Token::Bytes(b"aaa")]); -} - -#[test] -fn test_unit_fallthrough() { - #[derive(Deserialize, Debug, PartialEq)] - #[serde(field_identifier, rename_all = "snake_case")] - enum F { - Aaa, - Bbb, - #[serde(other)] - Other, + #[test] + fn field1() { + assert_de_tokens(&F::Aaa, &[Token::U8(0)]); + assert_de_tokens(&F::Aaa, &[Token::U16(0)]); + assert_de_tokens(&F::Aaa, &[Token::U32(0)]); + assert_de_tokens(&F::Aaa, &[Token::U64(0)]); + assert_de_tokens(&F::Aaa, &[Token::Str("aaa")]); + assert_de_tokens(&F::Aaa, &[Token::Bytes(b"aaa")]); } - assert_de_tokens(&F::Other, &[Token::U8(42)]); - assert_de_tokens(&F::Other, &[Token::U16(42)]); - assert_de_tokens(&F::Other, &[Token::U32(42)]); - assert_de_tokens(&F::Other, &[Token::U64(42)]); - assert_de_tokens(&F::Other, &[Token::Str("x")]); -} + #[test] + fn aliases() { + assert_de_tokens(&F::Bbb, &[Token::U8(1)]); + assert_de_tokens(&F::Bbb, &[Token::U16(1)]); + assert_de_tokens(&F::Bbb, &[Token::U32(1)]); + assert_de_tokens(&F::Bbb, &[Token::U64(1)]); -#[test] -fn test_newtype_fallthrough() { - #[derive(Deserialize, Debug, PartialEq)] - #[serde(field_identifier, rename_all = "snake_case")] - enum F { - Aaa, - Bbb, - Other(String), + assert_de_tokens(&F::Bbb, &[Token::Str("bbb")]); + assert_de_tokens(&F::Bbb, &[Token::Bytes(b"bbb")]); + + assert_de_tokens(&F::Bbb, &[Token::Str("ccc")]); + assert_de_tokens(&F::Bbb, &[Token::Bytes(b"ccc")]); + + assert_de_tokens(&F::Bbb, &[Token::Str("ddd")]); + assert_de_tokens(&F::Bbb, &[Token::Bytes(b"ddd")]); } - assert_de_tokens(&F::Other("x".to_owned()), &[Token::Str("x")]); -} - -#[test] -fn test_newtype_fallthrough_generic() { - #[derive(Deserialize, Debug, PartialEq)] - #[serde(field_identifier, rename_all = "snake_case")] - enum F { - Aaa, - Bbb, - Other(T), + #[test] + fn unknown() { + assert_de_tokens_error::( + &[Token::U8(42)], + "invalid value: integer `42`, expected field index 0 <= i < 2", + ); + assert_de_tokens_error::( + &[Token::U16(42)], + "invalid value: integer `42`, expected field index 0 <= i < 2", + ); + assert_de_tokens_error::( + &[Token::U32(42)], + "invalid value: integer `42`, expected field index 0 <= i < 2", + ); + assert_de_tokens_error::( + &[Token::U64(42)], + "invalid value: integer `42`, expected field index 0 <= i < 2", + ); + assert_de_tokens_error::( + &[Token::Str("unknown")], + "unknown field `unknown`, expected one of `aaa`, `bbb`, `ccc`, `ddd`", + ); + assert_de_tokens_error::( + &[Token::Bytes(b"unknown")], + "unknown field `unknown`, expected one of `aaa`, `bbb`, `ccc`, `ddd`", + ); } - assert_de_tokens(&F::Other(42u8), &[Token::U8(42)]); - assert_de_tokens(&F::Other(42u16), &[Token::U16(42)]); - assert_de_tokens(&F::Other(42u32), &[Token::U32(42)]); - assert_de_tokens(&F::Other(42u64), &[Token::U64(42)]); - assert_de_tokens(&F::Other("x".to_owned()), &[Token::Str("x")]); + #[test] + fn unit_fallthrough() { + #[derive(Deserialize, Debug, PartialEq)] + #[serde(field_identifier, rename_all = "snake_case")] + enum F { + Aaa, + Bbb, + #[serde(other)] + Other, + } + + assert_de_tokens(&F::Other, &[Token::U8(42)]); + assert_de_tokens(&F::Other, &[Token::U16(42)]); + assert_de_tokens(&F::Other, &[Token::U32(42)]); + assert_de_tokens(&F::Other, &[Token::U64(42)]); + assert_de_tokens(&F::Other, &[Token::Str("x")]); + } + + #[test] + fn newtype_fallthrough() { + #[derive(Deserialize, Debug, PartialEq)] + #[serde(field_identifier, rename_all = "snake_case")] + enum F { + Aaa, + Bbb, + Other(String), + } + + assert_de_tokens(&F::Other("x".to_owned()), &[Token::Str("x")]); + } + + #[test] + fn newtype_fallthrough_generic() { + #[derive(Deserialize, Debug, PartialEq)] + #[serde(field_identifier, rename_all = "snake_case")] + enum F { + Aaa, + Bbb, + Other(T), + } + + assert_de_tokens(&F::Other(42u8), &[Token::U8(42)]); + assert_de_tokens(&F::Other(42u16), &[Token::U16(42)]); + assert_de_tokens(&F::Other(42u32), &[Token::U32(42)]); + assert_de_tokens(&F::Other(42u64), &[Token::U64(42)]); + assert_de_tokens(&F::Other("x".to_owned()), &[Token::Str("x")]); + } } diff --git a/test_suite/tests/test_ignored_any.rs b/test_suite/tests/test_ignored_any.rs index 921cdfc7..955b7974 100644 --- a/test_suite/tests/test_ignored_any.rs +++ b/test_suite/tests/test_ignored_any.rs @@ -1,8 +1,12 @@ +#![allow(clippy::derive_partial_eq_without_eq)] + use serde::de::value::{Error, MapDeserializer, SeqDeserializer}; use serde::de::{ - DeserializeSeed, EnumAccess, IgnoredAny, IntoDeserializer, VariantAccess, Visitor, + Deserialize, DeserializeSeed, Deserializer, EnumAccess, IgnoredAny, IntoDeserializer, + VariantAccess, Visitor, }; -use serde::{forward_to_deserialize_any, Deserialize, Deserializer}; +use serde::forward_to_deserialize_any; +use serde_derive::Deserialize; #[derive(PartialEq, Debug, Deserialize)] enum Target { diff --git a/test_suite/tests/test_macros.rs b/test_suite/tests/test_macros.rs index 47179edf..02c36c41 100644 --- a/test_suite/tests/test_macros.rs +++ b/test_suite/tests/test_macros.rs @@ -1,5 +1,6 @@ #![deny(trivial_numeric_casts)] #![allow( + clippy::derive_partial_eq_without_eq, clippy::enum_variant_names, clippy::redundant_field_names, clippy::too_many_lines @@ -7,11 +8,10 @@ mod bytes; -use serde::{Deserialize, Serialize}; +use serde_derive::{Deserialize, Serialize}; use serde_test::{ assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_tokens, Token, }; - use std::collections::BTreeMap; use std::marker::PhantomData; @@ -472,7 +472,10 @@ fn test_adjacently_tagged_newtype_struct() { }, Token::U32(5), Token::Str("t"), - Token::Str("Newtype"), + Token::UnitVariant { + name: "E", + variant: "Newtype", + }, Token::StructEnd, ], ); @@ -811,6 +814,100 @@ fn test_internally_tagged_enum() { ); } +#[test] +fn test_internally_tagged_enum_with_untagged_variant() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(tag = "kind")] + enum InternallyTagged { + Tagged { + a: u8, + }, + #[serde(untagged)] + Untagged { + kind: String, + b: u8, + }, + } + + assert_de_tokens( + &InternallyTagged::Tagged { a: 1 }, + &[ + Token::Map { len: Some(2) }, + Token::Str("kind"), + Token::Str("Tagged"), + Token::Str("a"), + Token::U8(1), + Token::MapEnd, + ], + ); + + assert_tokens( + &InternallyTagged::Tagged { a: 1 }, + &[ + Token::Struct { + name: "InternallyTagged", + len: 2, + }, + Token::Str("kind"), + Token::Str("Tagged"), + Token::Str("a"), + Token::U8(1), + Token::StructEnd, + ], + ); + + assert_de_tokens( + &InternallyTagged::Untagged { + kind: "Foo".to_owned(), + b: 2, + }, + &[ + Token::Map { len: Some(2) }, + Token::Str("kind"), + Token::Str("Foo"), + Token::Str("b"), + Token::U8(2), + Token::MapEnd, + ], + ); + + assert_tokens( + &InternallyTagged::Untagged { + kind: "Foo".to_owned(), + b: 2, + }, + &[ + Token::Struct { + name: "InternallyTagged", + len: 2, + }, + Token::Str("kind"), + Token::Str("Foo"), + Token::Str("b"), + Token::U8(2), + Token::StructEnd, + ], + ); + + assert_tokens( + &InternallyTagged::Untagged { + kind: "Tagged".to_owned(), + b: 2, + }, + &[ + Token::Struct { + name: "InternallyTagged", + len: 2, + }, + Token::Str("kind"), + Token::Str("Tagged"), + Token::Str("b"), + Token::U8(2), + Token::StructEnd, + ], + ); +} + #[test] fn test_internally_tagged_bytes() { #[derive(Debug, PartialEq, Deserialize)] @@ -1066,7 +1163,10 @@ fn test_adjacently_tagged_enum() { len: 1, }, Token::Str("t"), - Token::Str("Unit"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Unit", + }, Token::StructEnd, ], ); @@ -1080,7 +1180,10 @@ fn test_adjacently_tagged_enum() { len: 2, }, Token::Str("t"), - Token::Str("Unit"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Unit", + }, Token::StructEnd, ], ); @@ -1094,7 +1197,10 @@ fn test_adjacently_tagged_enum() { len: 2, }, Token::Str("t"), - Token::Str("Unit"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Unit", + }, Token::Str("c"), Token::Unit, Token::StructEnd, @@ -1112,7 +1218,10 @@ fn test_adjacently_tagged_enum() { Token::Str("c"), Token::Unit, Token::Str("t"), - Token::Str("Unit"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Unit", + }, Token::StructEnd, ], ); @@ -1128,7 +1237,10 @@ fn test_adjacently_tagged_enum() { Token::Str("f"), Token::Unit, Token::Str("t"), - Token::Str("Unit"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Unit", + }, Token::Str("g"), Token::Unit, Token::Str("c"), @@ -1148,7 +1260,10 @@ fn test_adjacently_tagged_enum() { len: 2, }, Token::Str("t"), - Token::Str("Newtype"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Newtype", + }, Token::Str("c"), Token::U8(1), Token::StructEnd, @@ -1166,7 +1281,10 @@ fn test_adjacently_tagged_enum() { Token::Str("c"), Token::U8(1), Token::Str("t"), - Token::Str("Newtype"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Newtype", + }, Token::StructEnd, ], ); @@ -1180,7 +1298,10 @@ fn test_adjacently_tagged_enum() { len: 1, }, Token::Str("t"), - Token::Str("Newtype"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Newtype", + }, Token::StructEnd, ], ); @@ -1194,7 +1315,10 @@ fn test_adjacently_tagged_enum() { len: 2, }, Token::Str("t"), - Token::Str("Tuple"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Tuple", + }, Token::Str("c"), Token::Tuple { len: 2 }, Token::U8(1), @@ -1218,7 +1342,10 @@ fn test_adjacently_tagged_enum() { Token::U8(1), Token::TupleEnd, Token::Str("t"), - Token::Str("Tuple"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Tuple", + }, Token::StructEnd, ], ); @@ -1232,7 +1359,10 @@ fn test_adjacently_tagged_enum() { len: 2, }, Token::Str("t"), - Token::Str("Struct"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Struct", + }, Token::Str("c"), Token::Struct { name: "Struct", @@ -1262,7 +1392,48 @@ fn test_adjacently_tagged_enum() { Token::U8(1), Token::StructEnd, Token::Str("t"), - Token::Str("Struct"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Struct", + }, + Token::StructEnd, + ], + ); + + // integer field keys + assert_de_tokens( + &AdjacentlyTagged::Newtype::(1), + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::U64(1), // content field + Token::U8(1), + Token::U64(0), // tag field + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Newtype", + }, + Token::StructEnd, + ], + ); + + // byte-array field keys + assert_de_tokens( + &AdjacentlyTagged::Newtype::(1), + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Bytes(b"c"), + Token::U8(1), + Token::Bytes(b"t"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Newtype", + }, Token::StructEnd, ], ); @@ -1284,7 +1455,10 @@ fn test_adjacently_tagged_enum_deny_unknown_fields() { len: 2, }, Token::Str("t"), - Token::Str("Unit"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Unit", + }, Token::Str("c"), Token::Unit, Token::StructEnd, @@ -1298,7 +1472,10 @@ fn test_adjacently_tagged_enum_deny_unknown_fields() { len: 2, }, Token::Str("t"), - Token::Str("Unit"), + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Unit", + }, Token::Str("c"), Token::Unit, Token::Str("h"), @@ -1329,6 +1506,35 @@ fn test_adjacently_tagged_enum_deny_unknown_fields() { ], r#"invalid value: string "h", expected "t" or "c""#, ); + + assert_de_tokens_error::( + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::U64(0), // tag field + Token::UnitVariant { + name: "AdjacentlyTagged", + variant: "Unit", + }, + Token::U64(3), + ], + r#"invalid value: integer `3`, expected "t" or "c""#, + ); + + assert_de_tokens_error::( + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 2, + }, + Token::Bytes(b"c"), + Token::Unit, + Token::Bytes(b"h"), + ], + r#"invalid value: byte array, expected "t" or "c""#, + ); } #[test] @@ -1371,6 +1577,9 @@ fn test_enum_in_internally_tagged_enum() { ], ); + // Reaches crate::private::de::content::VariantDeserializer::tuple_variant + // Content::Seq case + // via ContentDeserializer::deserialize_enum assert_tokens( &Outer::Inner(Inner::Tuple(1, 1)), &[ @@ -1389,6 +1598,9 @@ fn test_enum_in_internally_tagged_enum() { ], ); + // Reaches crate::private::de::content::VariantDeserializer::struct_variant + // Content::Map case + // via ContentDeserializer::deserialize_enum assert_tokens( &Outer::Inner(Inner::Struct { f: 1 }), &[ @@ -1406,6 +1618,23 @@ fn test_enum_in_internally_tagged_enum() { Token::MapEnd, ], ); + + // Reaches crate::private::de::content::VariantDeserializer::struct_variant + // Content::Seq case + // via ContentDeserializer::deserialize_enum + assert_de_tokens( + &Outer::Inner(Inner::Struct { f: 1 }), + &[ + Token::Map { len: Some(2) }, + Token::Str("type"), + Token::Str("Inner"), + Token::Str("Struct"), + Token::Seq { len: Some(1) }, + Token::U8(1), // f + Token::SeqEnd, + Token::MapEnd, + ], + ); } #[test] @@ -1484,7 +1713,10 @@ fn test_internally_tagged_struct_with_flattened_field() { Token::Str("tag_struct"), Token::Str("Struct"), Token::Str("tag_enum"), - Token::Str("A"), + Token::UnitVariant { + name: "Enum", + variant: "A", + }, Token::Str("content"), Token::U64(0), Token::MapEnd, @@ -1865,6 +2097,62 @@ fn test_rename_all() { ); } +#[test] +fn test_rename_all_fields() { + #[derive(Serialize, Deserialize, Debug, PartialEq)] + #[serde(rename_all_fields = "kebab-case")] + enum E { + V1, + V2(bool), + V3 { + a_field: bool, + another_field: bool, + #[serde(rename = "last-field")] + yet_another_field: bool, + }, + #[serde(rename_all = "snake_case")] + V4 { + a_field: bool, + }, + } + + assert_tokens( + &E::V3 { + a_field: true, + another_field: true, + yet_another_field: true, + }, + &[ + Token::StructVariant { + name: "E", + variant: "V3", + len: 3, + }, + Token::Str("a-field"), + Token::Bool(true), + Token::Str("another-field"), + Token::Bool(true), + Token::Str("last-field"), + Token::Bool(true), + Token::StructVariantEnd, + ], + ); + + assert_tokens( + &E::V4 { a_field: true }, + &[ + Token::StructVariant { + name: "E", + variant: "V4", + len: 1, + }, + Token::Str("a_field"), + Token::Bool(true), + Token::StructVariantEnd, + ], + ); +} + #[test] fn test_untagged_newtype_variant_containing_unit_struct_not_map() { #[derive(Debug, PartialEq, Serialize, Deserialize)] @@ -1927,7 +2215,6 @@ fn test_internally_tagged_newtype_variant_containing_unit_struct() { ); } -#[deny(unaligned_references)] #[test] fn test_packed_struct_can_derive_serialize() { #[derive(Copy, Clone, Serialize)] diff --git a/test_suite/tests/test_remote.rs b/test_suite/tests/test_remote.rs index a38eaa32..c1f152eb 100644 --- a/test_suite/tests/test_remote.rs +++ b/test_suite/tests/test_remote.rs @@ -1,6 +1,6 @@ #![allow(clippy::redundant_field_names)] -use serde::{Deserialize, Serialize}; +use serde_derive::{Deserialize, Serialize}; mod remote { pub struct Unit; @@ -74,6 +74,21 @@ mod remote { &self.b } } + + pub struct StructGeneric { + pub value: T, + } + + impl StructGeneric { + #[allow(dead_code)] + pub fn get_value(&self) -> &T { + &self.value + } + } + + pub enum EnumGeneric { + Variant(T), + } } #[derive(Serialize, Deserialize)] @@ -104,6 +119,15 @@ struct Test { #[serde(with = "StructPubDef")] struct_pub: remote::StructPub, + + #[serde(with = "StructConcrete")] + struct_concrete: remote::StructGeneric, + + #[serde(with = "EnumConcrete")] + enum_concrete: remote::EnumGeneric, + + #[serde(with = "ErrorKindDef")] + io_error_kind: ErrorKind, } #[derive(Serialize, Deserialize)] @@ -157,6 +181,42 @@ struct StructPubDef { b: remote::Unit, } +#[derive(Serialize, Deserialize)] +#[serde(remote = "remote::StructGeneric")] +struct StructGenericWithGetterDef { + #[serde(getter = "remote::StructGeneric::get_value")] + value: T, +} + +#[derive(Serialize, Deserialize)] +#[serde(remote = "remote::StructGeneric")] +struct StructConcrete { + value: u8, +} + +#[derive(Serialize, Deserialize)] +#[serde(remote = "remote::EnumGeneric")] +enum EnumConcrete { + Variant(u8), +} + +#[derive(Debug)] +enum ErrorKind { + NotFound, + PermissionDenied, + #[allow(dead_code)] + ConnectionRefused, +} + +#[derive(Serialize, Deserialize)] +#[serde(remote = "ErrorKind")] +#[non_exhaustive] +enum ErrorKindDef { + NotFound, + PermissionDenied, + // ... +} + impl From for remote::PrimitivePriv { fn from(def: PrimitivePrivDef) -> Self { remote::PrimitivePriv::new(def.0) @@ -180,3 +240,9 @@ impl From for remote::StructPriv { remote::StructPriv::new(def.a, def.b) } } + +impl From> for remote::StructGeneric { + fn from(def: StructGenericWithGetterDef) -> Self { + remote::StructGeneric { value: def.value } + } +} diff --git a/test_suite/tests/test_roundtrip.rs b/test_suite/tests/test_roundtrip.rs index a54c28e6..00c21892 100644 --- a/test_suite/tests/test_roundtrip.rs +++ b/test_suite/tests/test_roundtrip.rs @@ -1,5 +1,4 @@ use serde_test::{assert_tokens, Configure, Token}; - use std::net; #[macro_use] diff --git a/test_suite/tests/test_self.rs b/test_suite/tests/test_self.rs index 77fc9a20..516bdeae 100644 --- a/test_suite/tests/test_self.rs +++ b/test_suite/tests/test_self.rs @@ -1,6 +1,6 @@ #![allow(clippy::used_underscore_binding)] -use serde::{Deserialize, Serialize}; +use serde_derive::{Deserialize, Serialize}; #[test] fn test_self() { diff --git a/test_suite/tests/test_ser.rs b/test_suite/tests/test_ser.rs index 0105d760..71ec3bc5 100644 --- a/test_suite/tests/test_ser.rs +++ b/test_suite/tests/test_ser.rs @@ -1,6 +1,9 @@ -#![allow(clippy::unreadable_literal)] +#![allow(clippy::derive_partial_eq_without_eq, clippy::unreadable_literal)] #![cfg_attr(feature = "unstable", feature(never_type))] +use fnv::FnvHasher; +use serde_derive::Serialize; +use serde_test::{assert_ser_tokens, assert_ser_tokens_error, Configure, Token}; use std::cell::RefCell; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::ffi::CString; @@ -9,21 +12,16 @@ use std::num::Wrapping; use std::ops::Bound; use std::path::{Path, PathBuf}; use std::rc::{Rc, Weak as RcWeak}; +#[cfg(unix)] +use std::str; use std::sync::atomic::{ AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8, AtomicUsize, }; -use std::sync::{Arc, Weak as ArcWeak}; -use std::time::{Duration, UNIX_EPOCH}; - -#[cfg(unix)] -use std::str; #[cfg(target_arch = "x86_64")] use std::sync::atomic::{AtomicI64, AtomicU64}; - -use fnv::FnvHasher; -use serde::Serialize; -use serde_test::{assert_ser_tokens, assert_ser_tokens_error, Configure, Token}; +use std::sync::{Arc, Mutex, RwLock, Weak as ArcWeak}; +use std::time::{Duration, UNIX_EPOCH}; #[macro_use] mod macros; @@ -502,6 +500,38 @@ fn test_range_inclusive() { ); } +#[test] +fn test_range_from() { + assert_ser_tokens( + &(1u32..), + &[ + Token::Struct { + name: "RangeFrom", + len: 1, + }, + Token::Str("start"), + Token::U32(1), + Token::StructEnd, + ], + ); +} + +#[test] +fn test_range_to() { + assert_ser_tokens( + &(..2u32), + &[ + Token::Struct { + name: "RangeTo", + len: 1, + }, + Token::Str("end"), + Token::U32(2), + Token::StructEnd, + ], + ); +} + #[test] fn test_bound() { assert_ser_tokens( @@ -800,17 +830,14 @@ fn test_never_result() { #[test] #[cfg(unix)] fn test_cannot_serialize_paths() { - let path = unsafe { str::from_utf8_unchecked(b"Hello \xF0\x90\x80World") }; + use std::ffi::OsStr; + use std::os::unix::ffi::OsStrExt; + assert_ser_tokens_error( - &Path::new(path), + &Path::new(OsStr::from_bytes(b"Hello \xF0\x90\x80World")), &[], "path contains invalid UTF-8 characters", ); - - let mut path_buf = PathBuf::new(); - path_buf.push(path); - - assert_ser_tokens_error(&path_buf, &[], "path contains invalid UTF-8 characters"); } #[test] @@ -850,3 +877,39 @@ fn test_integer128() { assert_ser_tokens_error(&1u128, &[], "u128 is not supported"); } + +#[test] +fn test_refcell_dst() { + assert_ser_tokens( + &RefCell::new([true]) as &RefCell<[bool]>, + &[ + Token::Seq { len: Some(1) }, + Token::Bool(true), + Token::SeqEnd, + ], + ); +} + +#[test] +fn test_mutex_dst() { + assert_ser_tokens( + &Mutex::new([true]) as &Mutex<[bool]>, + &[ + Token::Seq { len: Some(1) }, + Token::Bool(true), + Token::SeqEnd, + ], + ); +} + +#[test] +fn test_rwlock_dst() { + assert_ser_tokens( + &RwLock::new([true]) as &RwLock<[bool]>, + &[ + Token::Seq { len: Some(1) }, + Token::Bool(true), + Token::SeqEnd, + ], + ); +} diff --git a/test_suite/tests/test_serde_path.rs b/test_suite/tests/test_serde_path.rs index eb6c7aba..127b557e 100644 --- a/test_suite/tests/test_serde_path.rs +++ b/test_suite/tests/test_serde_path.rs @@ -1,8 +1,11 @@ -#![allow(clippy::type_repetition_in_bounds)] +#![allow( + clippy::extra_unused_type_parameters, + clippy::type_repetition_in_bounds +)] #[test] fn test_gen_custom_serde() { - #[derive(serde::Serialize, serde::Deserialize)] + #[derive(serde_derive::Serialize, serde_derive::Deserialize)] #[serde(crate = "fake_serde")] struct Foo; @@ -24,19 +27,21 @@ mod fake_serde { { } + #[allow(dead_code)] pub trait Serialize { fn serialize(&self, serializer: S) -> Result; } + #[allow(dead_code)] pub trait Deserialize<'a>: Sized { fn deserialize>(deserializer: D) -> Result; } } -trait AssertNotSerdeSerialize {} +pub trait AssertNotSerdeSerialize {} impl AssertNotSerdeSerialize for T {} -trait AssertNotSerdeDeserialize<'a> {} +pub trait AssertNotSerdeDeserialize<'a> {} impl<'a, T: serde::Deserialize<'a>> AssertNotSerdeDeserialize<'a> for T {} diff --git a/test_suite/tests/test_unstable.rs b/test_suite/tests/test_unstable.rs index f650512d..0f4cfa59 100644 --- a/test_suite/tests/test_unstable.rs +++ b/test_suite/tests/test_unstable.rs @@ -1,4 +1,5 @@ #![deny(warnings)] +#![allow(clippy::derive_partial_eq_without_eq)] // This test target is convoluted with the actual #[test] in a separate file to // get it so that the stable compiler does not need to parse the code of the diff --git a/test_suite/tests/test_value.rs b/test_suite/tests/test_value.rs index 4d3cd6b5..3a1922c0 100644 --- a/test_suite/tests/test_value.rs +++ b/test_suite/tests/test_value.rs @@ -1,8 +1,8 @@ -#![allow(clippy::similar_names)] +#![allow(clippy::derive_partial_eq_without_eq, clippy::similar_names)] use serde::de::value::{self, MapAccessDeserializer}; -use serde::de::{IntoDeserializer, MapAccess, Visitor}; -use serde::{Deserialize, Deserializer}; +use serde::de::{Deserialize, Deserializer, IntoDeserializer, MapAccess, Visitor}; +use serde_derive::Deserialize; use serde_test::{assert_de_tokens, Token}; use std::fmt; @@ -63,7 +63,7 @@ fn test_map_access_to_enum() { type Value = Potential; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "a map") + formatter.write_str("a map") } fn visit_map(self, map: A) -> Result diff --git a/test_suite/tests/ui/borrow/duplicate_variant.stderr b/test_suite/tests/ui/borrow/duplicate_variant.stderr index eaeaf97e..cd0746c2 100644 --- a/test_suite/tests/ui/borrow/duplicate_variant.stderr +++ b/test_suite/tests/ui/borrow/duplicate_variant.stderr @@ -1,5 +1,5 @@ error: duplicate serde attribute `borrow` - --> tests/ui/borrow/duplicate_variant.rs:8:13 + --> tests/ui/borrow/duplicate_variant.rs:9:15 | -8 | #[serde(borrow)] - | ^^^^^^ +9 | S(#[serde(borrow)] Str<'a>), + | ^^^^^^ diff --git a/test_suite/tests/ui/borrow/empty_lifetimes.rs b/test_suite/tests/ui/borrow/empty_lifetimes.rs index 8aab744a..71d17214 100644 --- a/test_suite/tests/ui/borrow/empty_lifetimes.rs +++ b/test_suite/tests/ui/borrow/empty_lifetimes.rs @@ -3,6 +3,8 @@ use serde_derive::Deserialize; #[derive(Deserialize)] struct Test<'a> { #[serde(borrow = "")] + r: &'a str, + #[serde(borrow = " ")] s: &'a str, } diff --git a/test_suite/tests/ui/borrow/empty_lifetimes.stderr b/test_suite/tests/ui/borrow/empty_lifetimes.stderr index c009714a..6f1f5c63 100644 --- a/test_suite/tests/ui/borrow/empty_lifetimes.stderr +++ b/test_suite/tests/ui/borrow/empty_lifetimes.stderr @@ -3,3 +3,9 @@ error: at least one lifetime must be borrowed | 5 | #[serde(borrow = "")] | ^^ + +error: at least one lifetime must be borrowed + --> tests/ui/borrow/empty_lifetimes.rs:7:22 + | +7 | #[serde(borrow = " ")] + | ^^^^ diff --git a/test_suite/tests/ui/conflict/flatten-newtype-struct.rs b/test_suite/tests/ui/conflict/flatten-newtype-struct.rs index 541cbc5d..e3719330 100644 --- a/test_suite/tests/ui/conflict/flatten-newtype-struct.rs +++ b/test_suite/tests/ui/conflict/flatten-newtype-struct.rs @@ -1,5 +1,4 @@ use serde_derive::Serialize; - use std::collections::HashMap; #[derive(Serialize)] diff --git a/test_suite/tests/ui/conflict/flatten-newtype-struct.stderr b/test_suite/tests/ui/conflict/flatten-newtype-struct.stderr index 8b0e2153..852cfb95 100644 --- a/test_suite/tests/ui/conflict/flatten-newtype-struct.stderr +++ b/test_suite/tests/ui/conflict/flatten-newtype-struct.stderr @@ -1,5 +1,5 @@ error: #[serde(flatten)] cannot be used on newtype structs - --> tests/ui/conflict/flatten-newtype-struct.rs:6:12 + --> tests/ui/conflict/flatten-newtype-struct.rs:5:12 | -6 | struct Foo(#[serde(flatten)] HashMap); +5 | struct Foo(#[serde(flatten)] HashMap); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/test_suite/tests/ui/conflict/flatten-tuple-struct.rs b/test_suite/tests/ui/conflict/flatten-tuple-struct.rs index 5d69060d..9e1820d3 100644 --- a/test_suite/tests/ui/conflict/flatten-tuple-struct.rs +++ b/test_suite/tests/ui/conflict/flatten-tuple-struct.rs @@ -1,5 +1,4 @@ use serde_derive::Serialize; - use std::collections::HashMap; #[derive(Serialize)] diff --git a/test_suite/tests/ui/conflict/flatten-tuple-struct.stderr b/test_suite/tests/ui/conflict/flatten-tuple-struct.stderr index b72aaf98..93c110bd 100644 --- a/test_suite/tests/ui/conflict/flatten-tuple-struct.stderr +++ b/test_suite/tests/ui/conflict/flatten-tuple-struct.stderr @@ -1,5 +1,5 @@ error: #[serde(flatten)] cannot be used on tuple structs - --> tests/ui/conflict/flatten-tuple-struct.rs:6:17 + --> tests/ui/conflict/flatten-tuple-struct.rs:5:17 | -6 | struct Foo(u32, #[serde(flatten)] HashMap); +5 | struct Foo(u32, #[serde(flatten)] HashMap); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/test_suite/tests/ui/default-attribute/enum.stderr b/test_suite/tests/ui/default-attribute/enum.stderr index 8f58ad66..27fbc146 100644 --- a/test_suite/tests/ui/default-attribute/enum.stderr +++ b/test_suite/tests/ui/default-attribute/enum.stderr @@ -1,5 +1,5 @@ -error: #[serde(default)] can only be used on structs with named fields - --> tests/ui/default-attribute/enum.rs:5:1 +error: #[serde(default)] can only be used on structs + --> tests/ui/default-attribute/enum.rs:4:9 | -5 | enum E { - | ^^^^ +4 | #[serde(default)] + | ^^^^^^^ diff --git a/test_suite/tests/ui/default-attribute/enum_path.stderr b/test_suite/tests/ui/default-attribute/enum_path.stderr index 008c1242..65ef3ac4 100644 --- a/test_suite/tests/ui/default-attribute/enum_path.stderr +++ b/test_suite/tests/ui/default-attribute/enum_path.stderr @@ -1,5 +1,5 @@ -error: #[serde(default = "...")] can only be used on structs with named fields - --> tests/ui/default-attribute/enum_path.rs:5:1 +error: #[serde(default = "...")] can only be used on structs + --> tests/ui/default-attribute/enum_path.rs:4:9 | -5 | enum E { - | ^^^^ +4 | #[serde(default = "default_e")] + | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/test_suite/tests/ui/default-attribute/nameless_struct_fields.rs b/test_suite/tests/ui/default-attribute/nameless_struct_fields.rs deleted file mode 100644 index fe21e0d4..00000000 --- a/test_suite/tests/ui/default-attribute/nameless_struct_fields.rs +++ /dev/null @@ -1,7 +0,0 @@ -use serde_derive::Deserialize; - -#[derive(Deserialize)] -#[serde(default)] -struct T(u8, u8); - -fn main() {} diff --git a/test_suite/tests/ui/default-attribute/nameless_struct_fields.stderr b/test_suite/tests/ui/default-attribute/nameless_struct_fields.stderr deleted file mode 100644 index 98da114e..00000000 --- a/test_suite/tests/ui/default-attribute/nameless_struct_fields.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: #[serde(default)] can only be used on structs with named fields - --> tests/ui/default-attribute/nameless_struct_fields.rs:5:9 - | -5 | struct T(u8, u8); - | ^^^^^^^^ diff --git a/test_suite/tests/ui/default-attribute/nameless_struct_fields_path.rs b/test_suite/tests/ui/default-attribute/nameless_struct_fields_path.rs deleted file mode 100644 index f7859ce5..00000000 --- a/test_suite/tests/ui/default-attribute/nameless_struct_fields_path.rs +++ /dev/null @@ -1,7 +0,0 @@ -use serde_derive::Deserialize; - -#[derive(Deserialize)] -#[serde(default = "default_t")] -struct T(u8, u8); - -fn main() {} diff --git a/test_suite/tests/ui/default-attribute/nameless_struct_fields_path.stderr b/test_suite/tests/ui/default-attribute/nameless_struct_fields_path.stderr deleted file mode 100644 index 40415ff9..00000000 --- a/test_suite/tests/ui/default-attribute/nameless_struct_fields_path.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: #[serde(default = "...")] can only be used on structs with named fields - --> tests/ui/default-attribute/nameless_struct_fields_path.rs:5:9 - | -5 | struct T(u8, u8); - | ^^^^^^^^ diff --git a/test_suite/tests/ui/default-attribute/tuple_struct.rs b/test_suite/tests/ui/default-attribute/tuple_struct.rs new file mode 100644 index 00000000..486abba7 --- /dev/null +++ b/test_suite/tests/ui/default-attribute/tuple_struct.rs @@ -0,0 +1,47 @@ +use serde_derive::Deserialize; + +// No errors expected. +#[derive(Deserialize)] +struct T0(u8, u8); + +// No errors expected: +// - If both fields are provided, both get value from data. +// - If only one field is provided, the second gets default value. +#[derive(Deserialize)] +struct T1(u8, #[serde(default)] u8); + +// ERROR: The first field can get default value only if sequence is empty, but +// that mean that all other fields cannot be deserialized without errors. +#[derive(Deserialize)] +struct T2(#[serde(default)] u8, u8, u8); + +// No errors expected: +// - If both fields are provided, both get value from data. +// - If only one field is provided, the second gets default value. +// - If no fields are provided, both get default value. +#[derive(Deserialize)] +struct T3(#[serde(default)] u8, #[serde(default)] u8); + +//////////////////////////////////////////////////////////////////////////////// + +// No errors expected -- missing fields get default values. +#[derive(Deserialize, Default)] +#[serde(default)] +struct T4(u8, u8); + +// No errors expected -- missing fields get default values. +#[derive(Deserialize, Default)] +#[serde(default)] +struct T5(#[serde(default)] u8, u8); + +// No errors expected -- missing fields get default values. +#[derive(Deserialize, Default)] +#[serde(default)] +struct T6(u8, #[serde(default)] u8); + +// No errors expected -- missing fields get default values. +#[derive(Deserialize, Default)] +#[serde(default)] +struct T7(#[serde(default)] u8, #[serde(default)] u8); + +fn main() {} diff --git a/test_suite/tests/ui/default-attribute/tuple_struct.stderr b/test_suite/tests/ui/default-attribute/tuple_struct.stderr new file mode 100644 index 00000000..7af857e6 --- /dev/null +++ b/test_suite/tests/ui/default-attribute/tuple_struct.stderr @@ -0,0 +1,11 @@ +error: field must have #[serde(default)] because previous field 0 has #[serde(default)] + --> tests/ui/default-attribute/tuple_struct.rs:16:33 + | +16 | struct T2(#[serde(default)] u8, u8, u8); + | ^^ + +error: field must have #[serde(default)] because previous field 0 has #[serde(default)] + --> tests/ui/default-attribute/tuple_struct.rs:16:37 + | +16 | struct T2(#[serde(default)] u8, u8, u8); + | ^^ diff --git a/test_suite/tests/ui/default-attribute/tuple_struct_path.rs b/test_suite/tests/ui/default-attribute/tuple_struct_path.rs new file mode 100644 index 00000000..48b07cbd --- /dev/null +++ b/test_suite/tests/ui/default-attribute/tuple_struct_path.rs @@ -0,0 +1,76 @@ +use serde_derive::Deserialize; + +fn d() -> T { + unimplemented!() +} + +// No errors expected: +// - If both fields are provided, both get value from data. +// - If only one field is provided, the second gets default value. +#[derive(Deserialize)] +struct T1(u8, #[serde(default = "d")] u8); + +// ERROR: The first field can get default value only if sequence is empty, but +// that mean that all other fields cannot be deserialized without errors. +#[derive(Deserialize)] +struct T2(#[serde(default = "d")] u8, u8, u8); + +// No errors expected: +// - If both fields are provided, both get value from data. +// - If only one field is provided, the second gets default value. +// - If no fields are provided, both get default value. +#[derive(Deserialize)] +struct T3(#[serde(default = "d")] u8, #[serde(default = "d")] u8); + +//////////////////////////////////////////////////////////////////////////////// + +// No errors expected -- missing fields get default values. +#[derive(Deserialize, Default)] +#[serde(default)] +struct T1D(#[serde(default = "d")] u8, u8); + +// No errors expected -- missing fields get default values. +#[derive(Deserialize, Default)] +#[serde(default)] +struct T2D(u8, #[serde(default = "d")] u8); + +// No errors expected -- missing fields get default values. +#[derive(Deserialize, Default)] +#[serde(default)] +struct T3D(#[serde(default = "d")] u8, #[serde(default = "d")] u8); + +//////////////////////////////////////////////////////////////////////////////// + +// No errors expected -- missing fields get default values. +#[derive(Deserialize)] +#[serde(default = "d")] +struct T1Path(#[serde(default)] u8, u8); + +// No errors expected -- missing fields get default values. +#[derive(Deserialize)] +#[serde(default = "d")] +struct T2Path(u8, #[serde(default)] u8); + +// No errors expected -- missing fields get default values. +#[derive(Deserialize)] +#[serde(default = "d")] +struct T3Path(#[serde(default)] u8, #[serde(default)] u8); + +//////////////////////////////////////////////////////////////////////////////// + +// No errors expected -- missing fields get default values. +#[derive(Deserialize)] +#[serde(default = "d")] +struct T1PathD(#[serde(default = "d")] u8, u8); + +// No errors expected -- missing fields get default values. +#[derive(Deserialize)] +#[serde(default = "d")] +struct T2PathD(u8, #[serde(default = "d")] u8); + +// No errors expected -- missing fields get default values. +#[derive(Deserialize)] +#[serde(default = "d")] +struct T3PathD(#[serde(default = "d")] u8, #[serde(default = "d")] u8); + +fn main() {} diff --git a/test_suite/tests/ui/default-attribute/tuple_struct_path.stderr b/test_suite/tests/ui/default-attribute/tuple_struct_path.stderr new file mode 100644 index 00000000..92bf8cf2 --- /dev/null +++ b/test_suite/tests/ui/default-attribute/tuple_struct_path.stderr @@ -0,0 +1,11 @@ +error: field must have #[serde(default)] because previous field 0 has #[serde(default)] + --> tests/ui/default-attribute/tuple_struct_path.rs:16:39 + | +16 | struct T2(#[serde(default = "d")] u8, u8, u8); + | ^^ + +error: field must have #[serde(default)] because previous field 0 has #[serde(default)] + --> tests/ui/default-attribute/tuple_struct_path.rs:16:43 + | +16 | struct T2(#[serde(default = "d")] u8, u8, u8); + | ^^ diff --git a/test_suite/tests/ui/enum-representation/partially_tagged_wrong_order.rs b/test_suite/tests/ui/enum-representation/partially_tagged_wrong_order.rs new file mode 100644 index 00000000..a33398ca --- /dev/null +++ b/test_suite/tests/ui/enum-representation/partially_tagged_wrong_order.rs @@ -0,0 +1,10 @@ +use serde_derive::Serialize; + +#[derive(Serialize)] +enum E { + #[serde(untagged)] + A(u8), + B(String), +} + +fn main() {} diff --git a/test_suite/tests/ui/enum-representation/partially_tagged_wrong_order.stderr b/test_suite/tests/ui/enum-representation/partially_tagged_wrong_order.stderr new file mode 100644 index 00000000..08ee2666 --- /dev/null +++ b/test_suite/tests/ui/enum-representation/partially_tagged_wrong_order.stderr @@ -0,0 +1,5 @@ +error: all variants with the #[serde(untagged)] attribute must be placed at the end of the enum + --> tests/ui/enum-representation/partially_tagged_wrong_order.rs:6:5 + | +6 | A(u8), + | ^ diff --git a/test_suite/tests/ui/enum-representation/untagged-struct.stderr b/test_suite/tests/ui/enum-representation/untagged-struct.stderr index 74eb0ae2..495a9f4f 100644 --- a/test_suite/tests/ui/enum-representation/untagged-struct.stderr +++ b/test_suite/tests/ui/enum-representation/untagged-struct.stderr @@ -1,5 +1,5 @@ error: #[serde(untagged)] can only be used on enums - --> tests/ui/enum-representation/untagged-struct.rs:5:1 + --> tests/ui/enum-representation/untagged-struct.rs:4:9 | -5 | struct S; - | ^^^^^^ +4 | #[serde(untagged)] + | ^^^^^^^^ diff --git a/test_suite/tests/ui/malformed/cut_off.stderr b/test_suite/tests/ui/malformed/cut_off.stderr index 7b00eec9..fed0d555 100644 --- a/test_suite/tests/ui/malformed/cut_off.stderr +++ b/test_suite/tests/ui/malformed/cut_off.stderr @@ -1,4 +1,4 @@ -error: unexpected end of input, expected literal +error: unexpected end of input, expected an expression --> tests/ui/malformed/cut_off.rs:4:17 | 4 | #[serde(rename =)] diff --git a/test_suite/tests/ui/malformed/not_list.stderr b/test_suite/tests/ui/malformed/not_list.stderr index 0812d755..799069a2 100644 --- a/test_suite/tests/ui/malformed/not_list.stderr +++ b/test_suite/tests/ui/malformed/not_list.stderr @@ -1,11 +1,11 @@ -error: expected #[serde(...)] +error: expected attribute arguments in parentheses: #[serde(...)] --> tests/ui/malformed/not_list.rs:4:3 | 4 | #[serde] | ^^^^^ -error: expected #[serde(...)] - --> tests/ui/malformed/not_list.rs:5:3 +error: expected parentheses: #[serde(...)] + --> tests/ui/malformed/not_list.rs:5:9 | 5 | #[serde = "?"] - | ^^^^^^^^^^^ + | ^ diff --git a/test_suite/tests/ui/malformed/str_suffix.rs b/test_suite/tests/ui/malformed/str_suffix.rs new file mode 100644 index 00000000..20f13dfc --- /dev/null +++ b/test_suite/tests/ui/malformed/str_suffix.rs @@ -0,0 +1,10 @@ +use serde_derive::Serialize; + +#[derive(Serialize)] +#[serde(bound = ""huh)] +pub struct Struct { + #[serde(rename = ""what)] + pub field: i32, +} + +fn main() {} diff --git a/test_suite/tests/ui/malformed/str_suffix.stderr b/test_suite/tests/ui/malformed/str_suffix.stderr new file mode 100644 index 00000000..3d4beae6 --- /dev/null +++ b/test_suite/tests/ui/malformed/str_suffix.stderr @@ -0,0 +1,11 @@ +error: unexpected suffix `huh` on string literal + --> tests/ui/malformed/str_suffix.rs:4:17 + | +4 | #[serde(bound = ""huh)] + | ^^^^^ + +error: unexpected suffix `what` on string literal + --> tests/ui/malformed/str_suffix.rs:6:22 + | +6 | #[serde(rename = ""what)] + | ^^^^^^ diff --git a/test_suite/tests/ui/malformed/trailing_expr.rs b/test_suite/tests/ui/malformed/trailing_expr.rs new file mode 100644 index 00000000..f117e023 --- /dev/null +++ b/test_suite/tests/ui/malformed/trailing_expr.rs @@ -0,0 +1,9 @@ +use serde_derive::Serialize; + +#[derive(Serialize)] +struct S { + #[serde(skip_serializing_if, x.is_empty())] + x: Vec<()>, +} + +fn main() {} diff --git a/test_suite/tests/ui/malformed/trailing_expr.stderr b/test_suite/tests/ui/malformed/trailing_expr.stderr new file mode 100644 index 00000000..539d7a35 --- /dev/null +++ b/test_suite/tests/ui/malformed/trailing_expr.stderr @@ -0,0 +1,5 @@ +error: expected `=` + --> tests/ui/malformed/trailing_expr.rs:5:32 + | +5 | #[serde(skip_serializing_if, x.is_empty())] + | ^ diff --git a/test_suite/tests/ui/remote/double_generic.rs b/test_suite/tests/ui/remote/double_generic.rs new file mode 100644 index 00000000..0e286a91 --- /dev/null +++ b/test_suite/tests/ui/remote/double_generic.rs @@ -0,0 +1,17 @@ +use serde_derive::{Deserialize, Serialize}; + +mod remote { + pub struct Struct { + pub t: T, + pub u: U, + } +} + +#[derive(Serialize, Deserialize)] +#[serde(remote = "remote::StructGeneric")] +struct StructDef { + t: u8, + u: U, +} + +fn main() {} diff --git a/test_suite/tests/ui/remote/double_generic.stderr b/test_suite/tests/ui/remote/double_generic.stderr new file mode 100644 index 00000000..4188b44a --- /dev/null +++ b/test_suite/tests/ui/remote/double_generic.stderr @@ -0,0 +1,5 @@ +error: remove generic parameters from this path + --> tests/ui/remote/double_generic.rs:11:18 + | +11 | #[serde(remote = "remote::StructGeneric")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/test_suite/tests/ui/remote/missing_field.rs b/test_suite/tests/ui/remote/missing_field.rs index e3f3ec8f..91656934 100644 --- a/test_suite/tests/ui/remote/missing_field.rs +++ b/test_suite/tests/ui/remote/missing_field.rs @@ -1,4 +1,4 @@ -use serde_derive::{Serialize, Deserialize}; +use serde_derive::{Deserialize, Serialize}; mod remote { pub struct S { diff --git a/test_suite/tests/ui/remote/unknown_field.rs b/test_suite/tests/ui/remote/unknown_field.rs index dd59cdcc..d21e7ffe 100644 --- a/test_suite/tests/ui/remote/unknown_field.rs +++ b/test_suite/tests/ui/remote/unknown_field.rs @@ -1,4 +1,4 @@ -use serde_derive::{Serialize, Deserialize}; +use serde_derive::{Deserialize, Serialize}; mod remote { pub struct S { diff --git a/test_suite/tests/ui/remote/unknown_field.stderr b/test_suite/tests/ui/remote/unknown_field.stderr index 152ffb60..f7efacde 100644 --- a/test_suite/tests/ui/remote/unknown_field.stderr +++ b/test_suite/tests/ui/remote/unknown_field.stderr @@ -2,10 +2,17 @@ error[E0609]: no field `b` on type `&remote::S` --> tests/ui/remote/unknown_field.rs:12:5 | 12 | b: u8, - | ^ help: a field with a similar name exists: `a` + | ^ unknown field + | +help: a field with a similar name exists + | +12 | a: u8, + | ~ error[E0560]: struct `remote::S` has no field named `b` --> tests/ui/remote/unknown_field.rs:12:5 | 12 | b: u8, - | ^ help: a field with a similar name exists: `a` + | ^ `remote::S` does not have this field + | + = note: all struct fields are already assigned diff --git a/test_suite/tests/ui/remote/wrong_de.stderr b/test_suite/tests/ui/remote/wrong_de.stderr index 41bdbb33..be7b7878 100644 --- a/test_suite/tests/ui/remote/wrong_de.stderr +++ b/test_suite/tests/ui/remote/wrong_de.stderr @@ -3,9 +3,12 @@ error[E0308]: mismatched types | 7 | #[derive(Deserialize)] | ^^^^^^^^^^^ expected `u16`, found `u8` +8 | #[serde(remote = "remote::S")] + | ----------- arguments to this struct are incorrect | +note: tuple struct defined here + --> tests/ui/remote/wrong_de.rs:4:16 + | +4 | pub struct S(pub u16); + | ^ = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info) -help: you can convert a `u8` to a `u16` - | -7 | #[derive(Deserialize.into())] - | +++++++ diff --git a/test_suite/tests/ui/remote/wrong_getter.stderr b/test_suite/tests/ui/remote/wrong_getter.stderr index a7b226ec..c686ff55 100644 --- a/test_suite/tests/ui/remote/wrong_getter.stderr +++ b/test_suite/tests/ui/remote/wrong_getter.stderr @@ -2,8 +2,16 @@ error[E0308]: mismatched types --> tests/ui/remote/wrong_getter.rs:15:10 | 15 | #[derive(Serialize)] - | ^^^^^^^^^ expected `u8`, found `u16` + | ^^^^^^^^^ + | | + | expected `&u8`, found `&u16` + | arguments to this function are incorrect | = note: expected reference `&u8` found reference `&u16` +note: function defined here + --> $WORKSPACE/serde/src/private/ser.rs + | + | pub fn constrain(t: &T) -> &T { + | ^^^^^^^^^ = note: this error originates in the derive macro `Serialize` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/test_suite/tests/ui/remote/wrong_ser.stderr b/test_suite/tests/ui/remote/wrong_ser.stderr index d45731cd..52f00470 100644 --- a/test_suite/tests/ui/remote/wrong_ser.stderr +++ b/test_suite/tests/ui/remote/wrong_ser.stderr @@ -2,8 +2,16 @@ error[E0308]: mismatched types --> tests/ui/remote/wrong_ser.rs:9:10 | 9 | #[derive(Serialize)] - | ^^^^^^^^^ expected `u8`, found `u16` + | ^^^^^^^^^ + | | + | expected `&u8`, found `&u16` + | arguments to this function are incorrect | = note: expected reference `&u8` found reference `&u16` +note: function defined here + --> $WORKSPACE/serde/src/private/ser.rs + | + | pub fn constrain(t: &T) -> &T { + | ^^^^^^^^^ = note: this error originates in the derive macro `Serialize` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/test_suite/tests/ui/struct-representation/internally-tagged-tuple.stderr b/test_suite/tests/ui/struct-representation/internally-tagged-tuple.stderr index e6282aeb..9b25305d 100644 --- a/test_suite/tests/ui/struct-representation/internally-tagged-tuple.stderr +++ b/test_suite/tests/ui/struct-representation/internally-tagged-tuple.stderr @@ -1,5 +1,5 @@ error: #[serde(tag = "...")] can only be used on enums and structs with named fields - --> tests/ui/struct-representation/internally-tagged-tuple.rs:5:9 + --> tests/ui/struct-representation/internally-tagged-tuple.rs:4:9 | -5 | struct S(u8, u8); - | ^^^^^^^^ +4 | #[serde(tag = "type")] + | ^^^^^^^^^^^^ diff --git a/test_suite/tests/ui/struct-representation/internally-tagged-unit.stderr b/test_suite/tests/ui/struct-representation/internally-tagged-unit.stderr index 040c44e4..1961ee59 100644 --- a/test_suite/tests/ui/struct-representation/internally-tagged-unit.stderr +++ b/test_suite/tests/ui/struct-representation/internally-tagged-unit.stderr @@ -1,7 +1,5 @@ error: #[serde(tag = "...")] can only be used on enums and structs with named fields - --> tests/ui/struct-representation/internally-tagged-unit.rs:3:10 + --> tests/ui/struct-representation/internally-tagged-unit.rs:4:9 | -3 | #[derive(Serialize)] - | ^^^^^^^^^ - | - = note: this error originates in the derive macro `Serialize` (in Nightly builds, run with -Z macro-backtrace for more info) +4 | #[serde(tag = "type")] + | ^^^^^^^^^^^^ diff --git a/test_suite/tests/ui/unexpected-literal/container.stderr b/test_suite/tests/ui/unexpected-literal/container.stderr index 44af1c52..826aff31 100644 --- a/test_suite/tests/ui/unexpected-literal/container.stderr +++ b/test_suite/tests/ui/unexpected-literal/container.stderr @@ -1,4 +1,4 @@ -error: unexpected literal in serde container attribute +error: unexpected literal in nested attribute, expected ident --> tests/ui/unexpected-literal/container.rs:4:9 | 4 | #[serde("literal")] diff --git a/test_suite/tests/ui/unexpected-literal/field.stderr b/test_suite/tests/ui/unexpected-literal/field.stderr index c8884653..aa29a5e5 100644 --- a/test_suite/tests/ui/unexpected-literal/field.stderr +++ b/test_suite/tests/ui/unexpected-literal/field.stderr @@ -1,4 +1,4 @@ -error: unexpected literal in serde field attribute +error: unexpected literal in nested attribute, expected ident --> tests/ui/unexpected-literal/field.rs:5:13 | 5 | #[serde("literal")] diff --git a/test_suite/tests/ui/unexpected-literal/variant.stderr b/test_suite/tests/ui/unexpected-literal/variant.stderr index 11314581..1e803529 100644 --- a/test_suite/tests/ui/unexpected-literal/variant.stderr +++ b/test_suite/tests/ui/unexpected-literal/variant.stderr @@ -1,4 +1,4 @@ -error: unexpected literal in serde variant attribute +error: unexpected literal in nested attribute, expected ident --> tests/ui/unexpected-literal/variant.rs:5:13 | 5 | #[serde("literal")] diff --git a/test_suite/tests/unstable/mod.rs b/test_suite/tests/unstable/mod.rs index b0c221e6..8060b2ad 100644 --- a/test_suite/tests/unstable/mod.rs +++ b/test_suite/tests/unstable/mod.rs @@ -1,4 +1,4 @@ -use serde::{Deserialize, Serialize}; +use serde_derive::{Deserialize, Serialize}; use serde_test::{assert_tokens, Token}; #[test]