mirror of
https://gitee.com/openharmony/third_party_rust_serde
synced 2024-11-27 00:50:42 +00:00
回退 'Pull Request !3 : serde 1.0.136升级至1.0.197'
This commit is contained in:
parent
920b30a6e4
commit
ff504fee13
140
.github/workflows/ci.yml
vendored
140
.github/workflows/ci.yml
vendored
@ -3,12 +3,8 @@ name: CI
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
schedule: [cron: "40 1 * * *"]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
RUSTFLAGS: -Dwarnings
|
||||
|
||||
@ -16,18 +12,16 @@ jobs:
|
||||
test:
|
||||
name: Test suite
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2
|
||||
- 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@v4
|
||||
- uses: actions/checkout@v2
|
||||
- uses: dtolnay/rust-toolchain@nightly
|
||||
- run: cd test_suite && cargo test --features unstable -- --skip ui --exact
|
||||
|
||||
@ -38,14 +32,15 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
rust: [stable, beta]
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2
|
||||
- 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)' || ''}}
|
||||
@ -54,22 +49,33 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu, windows]
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2
|
||||
- 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'
|
||||
- run: cd serde_derive && cargo check --tests
|
||||
env:
|
||||
RUSTFLAGS: --cfg exhaustive ${{env.RUSTFLAGS}}
|
||||
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
|
||||
|
||||
build:
|
||||
name: Rust ${{matrix.rust}}
|
||||
@ -77,24 +83,38 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
rust: [1.31.0, 1.34.0]
|
||||
timeout-minutes: 45
|
||||
rust: [1.19.0, 1.20.0, 1.21.0, 1.25.0, 1.26.0, 1.34.0]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2
|
||||
- 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 && 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 --no-default-features
|
||||
- run: cd serde && cargo build
|
||||
|
||||
derive:
|
||||
name: Rust 1.56.0
|
||||
name: Rust 1.31.0
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@1.56.0
|
||||
- uses: actions/checkout@v2
|
||||
- uses: dtolnay/rust-toolchain@1.31.0
|
||||
- run: cd serde && cargo check --no-default-features
|
||||
- run: cd serde && cargo check
|
||||
- run: cd serde_derive && cargo check
|
||||
@ -102,71 +122,43 @@ jobs:
|
||||
alloc:
|
||||
name: Rust 1.36.0
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2
|
||||
- uses: dtolnay/rust-toolchain@1.36.0
|
||||
- run: cd serde && cargo build --no-default-features --features alloc
|
||||
|
||||
minimal:
|
||||
name: Minimal versions
|
||||
emscripten:
|
||||
name: Emscripten
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2
|
||||
- uses: dtolnay/rust-toolchain@nightly
|
||||
- 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
|
||||
- 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
|
||||
|
||||
clippy:
|
||||
name: Clippy
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name != 'pull_request'
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2
|
||||
- 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
|
||||
|
@ -3,13 +3,6 @@ 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 }
|
||||
|
@ -174,3 +174,28 @@ 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.
|
||||
|
@ -3,7 +3,7 @@
|
||||
"Name": "serde",
|
||||
"License": "Apache License V2.0",
|
||||
"License File": "LICENSE-APACHE",
|
||||
"Version Number": "1.0.197",
|
||||
"Version Number": "1.0.136",
|
||||
"Owner": "xuelei3@huawei.com",
|
||||
"Upstream URL": "https://github.com/serde-rs/serde",
|
||||
"Description": "A generic serialization/deserialization framework."
|
||||
|
14
README.md
14
README.md
@ -1,13 +1,13 @@
|
||||
# Serde   [![Build Status]][actions] [![Latest Version]][crates.io] [![serde msrv]][Rust 1.31] [![serde_derive msrv]][Rust 1.56]
|
||||
# Serde   [![Build Status]][actions] [![Latest Version]][crates.io] [![serde: rustc 1.13+]][Rust 1.13] [![serde_derive: rustc 1.31+]][Rust 1.31]
|
||||
|
||||
[Build Status]: https://img.shields.io/github/actions/workflow/status/serde-rs/serde/ci.yml?branch=master
|
||||
[Build Status]: https://img.shields.io/github/workflow/status/serde-rs/serde/CI/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 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
|
||||
[serde: rustc 1.13+]: https://img.shields.io/badge/serde-rustc_1.13+-lightgray.svg
|
||||
[serde_derive: rustc 1.31+]: https://img.shields.io/badge/serde_derive-rustc_1.31+-lightgray.svg
|
||||
[Rust 1.13]: https://blog.rust-lang.org/2016/11/10/Rust-1.13.html
|
||||
[Rust 1.31]: https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html
|
||||
[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.rs/serde)
|
||||
- [API documentation](https://docs.serde.rs/serde/)
|
||||
- [Release notes](https://github.com/serde-rs/serde/releases)
|
||||
|
||||
## Serde in action
|
||||
@ -48,7 +48,7 @@ serde_json = "1.0"
|
||||
<p></p>
|
||||
|
||||
```rust
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
struct Point {
|
||||
|
@ -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.rs/serde)
|
||||
- [API documentation](https://docs.serde.rs/serde/)
|
||||
- [Release notes](https://github.com/serde-rs/serde/releases)
|
||||
|
||||
## Serde in action
|
||||
|
||||
```rust
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
struct Point {
|
||||
|
@ -19,8 +19,8 @@ ohos_cargo_crate("lib") {
|
||||
crate_root = "src/lib.rs"
|
||||
|
||||
sources = [ "src/lib.rs" ]
|
||||
edition = "2018"
|
||||
cargo_pkg_version = "1.0.195"
|
||||
edition = "2015"
|
||||
cargo_pkg_version = "1.0.136"
|
||||
cargo_pkg_authors = "Erick Tryzelaar <erick.tryzelaar@gmail.com>, David Tolnay <dtolnay@gmail.com>"
|
||||
cargo_pkg_name = "serde"
|
||||
cargo_pkg_description = "A generic serialization/deserialization framework"
|
||||
|
@ -1,43 +1,30 @@
|
||||
[package]
|
||||
name = "serde"
|
||||
version = "1.0.197"
|
||||
version = "1.0.136" # remember to update html_root_url and serde_derive dependency
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
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"]
|
||||
rust-version = "1.15"
|
||||
license = "MIT OR Apache-2.0"
|
||||
readme = "crates-io.md"
|
||||
description = "A generic serialization/deserialization framework"
|
||||
homepage = "https://serde.rs"
|
||||
repository = "https://github.com/serde-rs/serde"
|
||||
rust-version = "1.31"
|
||||
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"
|
||||
|
||||
[dependencies]
|
||||
serde_derive = { version = "1", optional = true, path = "../serde_derive" }
|
||||
serde_derive = { version = "=1.0.136", optional = true, path = "../serde_derive" }
|
||||
|
||||
[dev-dependencies]
|
||||
serde_derive = { version = "1", path = "../serde_derive" }
|
||||
|
||||
[lib]
|
||||
doc-scrape-examples = false
|
||||
serde_derive = { version = "1.0", path = "../serde_derive" }
|
||||
|
||||
[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 #################################################################
|
||||
|
120
serde/build.rs
120
serde/build.rs
@ -6,8 +6,6 @@ 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,
|
||||
@ -16,6 +14,73 @@ 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<Box<T>> for Rc<T> / Arc<T> stabilized in Rust 1.21:
|
||||
// https://doc.rust-lang.org/std/rc/struct.Rc.html#impl-From<Box<T>>
|
||||
// https://doc.rust-lang.org/std/sync/struct.Arc.html#impl-From<Box<T>>
|
||||
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
|
||||
@ -24,45 +89,24 @@ 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");
|
||||
}
|
||||
|
||||
// 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");
|
||||
// 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");
|
||||
}
|
||||
|
||||
// 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");
|
||||
if minor < 34 || !has_atomic32 {
|
||||
println!("cargo:rustc-cfg=no_std_atomic");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::lib::fmt::{self, Write};
|
||||
use crate::lib::str;
|
||||
use lib::fmt::{self, Write};
|
||||
use lib::str;
|
||||
|
||||
pub(super) struct Buf<'a> {
|
||||
pub struct Buf<'a> {
|
||||
bytes: &'a mut [u8],
|
||||
offset: usize,
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::lib::*;
|
||||
use lib::*;
|
||||
|
||||
use crate::de::{
|
||||
use de::{
|
||||
Deserialize, Deserializer, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor,
|
||||
};
|
||||
|
||||
@ -10,12 +10,13 @@ use crate::de::{
|
||||
/// any type, except that it does not store any information about the data that
|
||||
/// gets deserialized.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// use std::fmt;
|
||||
/// use std::marker::PhantomData;
|
||||
///
|
||||
/// 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`.
|
||||
@ -107,7 +108,7 @@ use crate::de::{
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[derive(Copy, Clone, Debug, Default, PartialEq)]
|
||||
#[derive(Copy, Clone, Debug, Default)]
|
||||
pub struct IgnoredAny;
|
||||
|
||||
impl<'de> Visitor<'de> for IgnoredAny {
|
||||
@ -129,10 +130,12 @@ impl<'de> Visitor<'de> for IgnoredAny {
|
||||
Ok(IgnoredAny)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_i128<E>(self, x: i128) -> Result<Self::Value, E> {
|
||||
let _ = x;
|
||||
Ok(IgnoredAny)
|
||||
serde_if_integer128! {
|
||||
#[inline]
|
||||
fn visit_i128<E>(self, x: i128) -> Result<Self::Value, E> {
|
||||
let _ = x;
|
||||
Ok(IgnoredAny)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -141,10 +144,12 @@ impl<'de> Visitor<'de> for IgnoredAny {
|
||||
Ok(IgnoredAny)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_u128<E>(self, x: u128) -> Result<Self::Value, E> {
|
||||
let _ = x;
|
||||
Ok(IgnoredAny)
|
||||
serde_if_integer128! {
|
||||
#[inline]
|
||||
fn visit_u128<E>(self, x: u128) -> Result<Self::Value, E> {
|
||||
let _ = x;
|
||||
Ok(IgnoredAny)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -193,7 +198,7 @@ impl<'de> Visitor<'de> for IgnoredAny {
|
||||
where
|
||||
A: SeqAccess<'de>,
|
||||
{
|
||||
while let Some(IgnoredAny) = tri!(seq.next_element()) {
|
||||
while let Some(IgnoredAny) = try!(seq.next_element()) {
|
||||
// Gobble
|
||||
}
|
||||
Ok(IgnoredAny)
|
||||
@ -204,7 +209,7 @@ impl<'de> Visitor<'de> for IgnoredAny {
|
||||
where
|
||||
A: MapAccess<'de>,
|
||||
{
|
||||
while let Some((IgnoredAny, IgnoredAny)) = tri!(map.next_entry()) {
|
||||
while let Some((IgnoredAny, IgnoredAny)) = try!(map.next_entry()) {
|
||||
// Gobble
|
||||
}
|
||||
Ok(IgnoredAny)
|
||||
@ -223,7 +228,7 @@ impl<'de> Visitor<'de> for IgnoredAny {
|
||||
where
|
||||
A: EnumAccess<'de>,
|
||||
{
|
||||
tri!(data.variant::<IgnoredAny>()).1.newtype_variant()
|
||||
data.variant::<IgnoredAny>()?.1.newtype_variant()
|
||||
}
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -30,7 +30,7 @@
|
||||
//! # The Deserializer trait
|
||||
//!
|
||||
//! [`Deserializer`] implementations are provided by third-party crates, for
|
||||
//! example [`serde_json`], [`serde_yaml`] and [`postcard`].
|
||||
//! example [`serde_json`], [`serde_yaml`] and [`bincode`].
|
||||
//!
|
||||
//! A partial list of well-maintained formats is given on the [Serde
|
||||
//! website][data formats].
|
||||
@ -64,8 +64,8 @@
|
||||
//! - RefCell\<T\>
|
||||
//! - Mutex\<T\>
|
||||
//! - RwLock\<T\>
|
||||
//! - Rc\<T\> *(if* features = \["rc"\] *is enabled)*
|
||||
//! - Arc\<T\> *(if* features = \["rc"\] *is enabled)*
|
||||
//! - Rc\<T\> *(if* features = ["rc"] *is enabled)*
|
||||
//! - Arc\<T\> *(if* features = ["rc"] *is enabled)*
|
||||
//! - **Collection types**:
|
||||
//! - BTreeMap\<K, V\>
|
||||
//! - BTreeSet\<T\>
|
||||
@ -104,7 +104,7 @@
|
||||
//! [`Deserialize`]: ../trait.Deserialize.html
|
||||
//! [`Deserializer`]: ../trait.Deserializer.html
|
||||
//! [`LinkedHashMap<K, V>`]: https://docs.rs/linked-hash-map/*/linked_hash_map/struct.LinkedHashMap.html
|
||||
//! [`postcard`]: https://github.com/jamesmunns/postcard
|
||||
//! [`bincode`]: https://github.com/servo/bincode
|
||||
//! [`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,28 +112,26 @@
|
||||
//! [derive section of the manual]: https://serde.rs/derive.html
|
||||
//! [data formats]: https://serde.rs/#data-formats
|
||||
|
||||
use crate::lib::*;
|
||||
use lib::*;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
pub mod value;
|
||||
|
||||
#[cfg(not(no_integer128))]
|
||||
mod format;
|
||||
mod ignored_any;
|
||||
mod impls;
|
||||
pub(crate) mod size_hint;
|
||||
mod utf8;
|
||||
|
||||
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;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -164,7 +162,7 @@ macro_rules! declare_error_trait {
|
||||
///
|
||||
/// The message should not be capitalized and should not end with a period.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use std::str::FromStr;
|
||||
/// #
|
||||
/// # struct IpAddr;
|
||||
@ -309,7 +307,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.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use std::fmt;
|
||||
/// #
|
||||
/// # use serde::de::{self, Unexpected, Visitor};
|
||||
@ -402,20 +400,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 `{}`", WithDecimalPoint(f)),
|
||||
Float(f) => write!(formatter, "floating point `{}`", f),
|
||||
Char(c) => write!(formatter, "character `{}`", c),
|
||||
Str(s) => write!(formatter, "string {:?}", s),
|
||||
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"),
|
||||
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"),
|
||||
Other(other) => formatter.write_str(other),
|
||||
}
|
||||
}
|
||||
@ -434,10 +432,11 @@ impl<'a> fmt::Display for Unexpected<'a> {
|
||||
/// Within the context of a `Visitor` implementation, the `Visitor` itself
|
||||
/// (`&self`) is an implementation of this trait.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// # use serde::de::{self, Unexpected, Visitor};
|
||||
/// ```edition2018
|
||||
/// # use std::fmt;
|
||||
/// #
|
||||
/// # use serde::de::{self, Unexpected, Visitor};
|
||||
/// #
|
||||
/// # struct Example;
|
||||
/// #
|
||||
/// # impl<'de> Visitor<'de> for Example {
|
||||
@ -458,7 +457,7 @@ impl<'a> fmt::Display for Unexpected<'a> {
|
||||
///
|
||||
/// Outside of a `Visitor`, `&"..."` can be used.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use serde::de::{self, Unexpected};
|
||||
/// #
|
||||
/// # fn example<E>() -> Result<(), E>
|
||||
@ -466,10 +465,7 @@ 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 {
|
||||
@ -505,8 +501,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][crate::de]. All of these
|
||||
/// can be deserialized using Serde out of the box.
|
||||
/// standard library types. The complete list is [here][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
|
||||
@ -522,6 +518,7 @@ impl<'a> Display for Expected + 'a {
|
||||
/// `LinkedHashMap<K, V>` 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
|
||||
///
|
||||
@ -568,7 +565,7 @@ pub trait Deserialize<'de>: Sized {
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
// Default implementation just delegates to `deserialize` impl.
|
||||
*place = tri!(Deserialize::deserialize(deserializer));
|
||||
*place = Deserialize::deserialize(deserializer)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -581,7 +578,7 @@ pub trait Deserialize<'de>: Sized {
|
||||
/// from the input string, but a `from_reader` function may only deserialize
|
||||
/// owned data.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use serde::de::{Deserialize, DeserializeOwned};
|
||||
/// # use std::io::{Read, Result};
|
||||
/// #
|
||||
@ -620,7 +617,7 @@ impl<T> DeserializeOwned for T where T: for<'de> Deserialize<'de> {}
|
||||
///
|
||||
/// The canonical API for stateless deserialization looks like this:
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use serde::Deserialize;
|
||||
/// #
|
||||
/// # enum Error {}
|
||||
@ -634,7 +631,7 @@ impl<T> 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:
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use serde::de::DeserializeSeed;
|
||||
/// #
|
||||
/// # enum Error {}
|
||||
@ -667,11 +664,12 @@ impl<T> DeserializeOwned for T where T: for<'de> Deserialize<'de> {}
|
||||
/// into it. This requires stateful deserialization using the `DeserializeSeed`
|
||||
/// trait.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// use serde::de::{Deserialize, DeserializeSeed, Deserializer, SeqAccess, Visitor};
|
||||
/// ```edition2018
|
||||
/// 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<T>. The `deserialize` method of
|
||||
@ -710,11 +708,6 @@ impl<T> 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()? {
|
||||
@ -864,10 +857,10 @@ where
|
||||
/// The `Deserializer` trait supports two entry point styles which enables
|
||||
/// different kinds of deserialization.
|
||||
///
|
||||
/// 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
|
||||
/// 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
|
||||
/// `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
|
||||
@ -876,7 +869,7 @@ where
|
||||
/// `Deserializer::deserialize_any`.
|
||||
///
|
||||
/// 2. The various `deserialize_*` methods. Non-self-describing formats like
|
||||
/// Postcard need to be told what is in the input in order to deserialize it.
|
||||
/// Bincode 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
|
||||
@ -886,7 +879,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 Postcard and many
|
||||
/// deserialize from self-describing formats only, ruling out Bincode and many
|
||||
/// others.
|
||||
///
|
||||
/// [Serde data model]: https://serde.rs/data-model.html
|
||||
@ -917,7 +910,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 Postcard and
|
||||
/// deserialize from self-describing formats only, ruling out Bincode and
|
||||
/// many others.
|
||||
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
@ -948,15 +941,18 @@ pub trait Deserializer<'de>: Sized {
|
||||
where
|
||||
V: Visitor<'de>;
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting an `i128` value.
|
||||
///
|
||||
/// The default behavior unconditionally returns an error.
|
||||
fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
let _ = visitor;
|
||||
Err(Error::custom("i128 is not supported"))
|
||||
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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: Visitor<'de>
|
||||
{
|
||||
let _ = visitor;
|
||||
Err(Error::custom("i128 is not supported"))
|
||||
}
|
||||
}
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting a `u8` value.
|
||||
@ -979,15 +975,18 @@ pub trait Deserializer<'de>: Sized {
|
||||
where
|
||||
V: Visitor<'de>;
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting an `u128` value.
|
||||
///
|
||||
/// The default behavior unconditionally returns an error.
|
||||
fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
let _ = visitor;
|
||||
Err(Error::custom("u128 is not supported"))
|
||||
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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: Visitor<'de>
|
||||
{
|
||||
let _ = visitor;
|
||||
Err(Error::custom("u128 is not supported"))
|
||||
}
|
||||
}
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting a `f32` value.
|
||||
@ -1152,10 +1151,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 Postcard will prefer the
|
||||
/// human-readable one and binary formats like Bincode will prefer the
|
||||
/// compact one.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use std::ops::Add;
|
||||
/// # use std::str::FromStr;
|
||||
/// #
|
||||
@ -1222,11 +1221,11 @@ pub trait Deserializer<'de>: Sized {
|
||||
#[doc(hidden)]
|
||||
fn __deserialize_content<V>(
|
||||
self,
|
||||
_: crate::actually_private::T,
|
||||
_: ::actually_private::T,
|
||||
visitor: V,
|
||||
) -> Result<crate::__private::de::Content<'de>, Self::Error>
|
||||
) -> Result<::private::de::Content<'de>, Self::Error>
|
||||
where
|
||||
V: Visitor<'de, Value = crate::__private::de::Content<'de>>,
|
||||
V: Visitor<'de, Value = ::private::de::Content<'de>>,
|
||||
{
|
||||
self.deserialize_any(visitor)
|
||||
}
|
||||
@ -1246,10 +1245,11 @@ pub trait Deserializer<'de>: Sized {
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```edition2021
|
||||
/// # use serde::de::{self, Unexpected, Visitor};
|
||||
/// ```edition2018
|
||||
/// # use std::fmt;
|
||||
/// #
|
||||
/// # use serde::de::{self, Unexpected, Visitor};
|
||||
/// #
|
||||
/// /// A visitor that deserializes a long string - a string containing at least
|
||||
/// /// some minimum number of bytes.
|
||||
/// struct LongString {
|
||||
@ -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.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use std::fmt;
|
||||
/// #
|
||||
/// # struct S {
|
||||
@ -1359,20 +1359,20 @@ pub trait Visitor<'de>: Sized {
|
||||
Err(Error::invalid_type(Unexpected::Signed(v), &self))
|
||||
}
|
||||
|
||||
/// The input contains a `i128`.
|
||||
///
|
||||
/// The default implementation fails with a type error.
|
||||
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
|
||||
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,
|
||||
))
|
||||
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<E>(self, v: i128) -> Result<Self::Value, E>
|
||||
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))
|
||||
}
|
||||
|
||||
/// The input contains a `u128`.
|
||||
///
|
||||
/// The default implementation fails with a type error.
|
||||
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
|
||||
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,
|
||||
))
|
||||
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<E>(self, v: u128) -> Result<Self::Value, E>
|
||||
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(v.encode_utf8(&mut [0u8; 4]))
|
||||
self.visit_str(utf8::encode(v).as_str())
|
||||
}
|
||||
|
||||
/// The input contains a string. The lifetime of the string is ephemeral and
|
||||
@ -1525,7 +1525,6 @@ 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<E>(self, v: String) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
@ -1548,6 +1547,7 @@ 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 Postcard data containing bytes can be deserialized with zero
|
||||
/// example Bincode 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,7 +1584,6 @@ pub trait Visitor<'de>: Sized {
|
||||
/// The default implementation forwards to `visit_bytes` and then drops the
|
||||
/// `Vec<u8>`.
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
@ -1828,9 +1827,9 @@ pub trait MapAccess<'de> {
|
||||
K: DeserializeSeed<'de>,
|
||||
V: DeserializeSeed<'de>,
|
||||
{
|
||||
match tri!(self.next_key_seed(kseed)) {
|
||||
match try!(self.next_key_seed(kseed)) {
|
||||
Some(key) => {
|
||||
let value = tri!(self.next_value_seed(vseed));
|
||||
let value = try!(self.next_value_seed(vseed));
|
||||
Ok(Some((key, value)))
|
||||
}
|
||||
None => Ok(None),
|
||||
@ -2032,7 +2031,7 @@ pub trait VariantAccess<'de>: Sized {
|
||||
/// If the data contains a different type of variant, the following
|
||||
/// `invalid_type` error should be constructed:
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected};
|
||||
/// #
|
||||
/// # struct X;
|
||||
@ -2072,7 +2071,7 @@ pub trait VariantAccess<'de>: Sized {
|
||||
/// If the data contains a different type of variant, the following
|
||||
/// `invalid_type` error should be constructed:
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected};
|
||||
/// #
|
||||
/// # struct X;
|
||||
@ -2128,7 +2127,7 @@ pub trait VariantAccess<'de>: Sized {
|
||||
/// If the data contains a different type of variant, the following
|
||||
/// `invalid_type` error should be constructed:
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected};
|
||||
/// #
|
||||
/// # struct X;
|
||||
@ -2145,7 +2144,11 @@ pub trait VariantAccess<'de>: Sized {
|
||||
/// # T: DeserializeSeed<'de>,
|
||||
/// # { unimplemented!() }
|
||||
/// #
|
||||
/// fn tuple_variant<V>(self, _len: usize, _visitor: V) -> Result<V::Value, Self::Error>
|
||||
/// fn tuple_variant<V>(
|
||||
/// self,
|
||||
/// _len: usize,
|
||||
/// _visitor: V,
|
||||
/// ) -> Result<V::Value, Self::Error>
|
||||
/// where
|
||||
/// V: Visitor<'de>,
|
||||
/// {
|
||||
@ -2171,7 +2174,7 @@ pub trait VariantAccess<'de>: Sized {
|
||||
/// If the data contains a different type of variant, the following
|
||||
/// `invalid_type` error should be constructed:
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected};
|
||||
/// #
|
||||
/// # struct X;
|
||||
@ -2231,10 +2234,10 @@ pub trait VariantAccess<'de>: Sized {
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```edition2021
|
||||
/// use serde::de::{value, Deserialize, IntoDeserializer};
|
||||
/// use serde_derive::Deserialize;
|
||||
/// ```edition2018
|
||||
/// use std::str::FromStr;
|
||||
/// use serde::Deserialize;
|
||||
/// use serde::de::{value, IntoDeserializer};
|
||||
///
|
||||
/// #[derive(Deserialize)]
|
||||
/// enum Setting {
|
||||
@ -2278,48 +2281,15 @@ impl Display for OneOf {
|
||||
1 => write!(formatter, "`{}`", self.names[0]),
|
||||
2 => write!(formatter, "`{}` or `{}`", self.names[0], self.names[1]),
|
||||
_ => {
|
||||
tri!(formatter.write_str("one of "));
|
||||
try!(write!(formatter, "one of "));
|
||||
for (i, alt) in self.names.iter().enumerate() {
|
||||
if i > 0 {
|
||||
tri!(formatter.write_str(", "));
|
||||
try!(write!(formatter, ", "));
|
||||
}
|
||||
tri!(write!(formatter, "`{}`", alt));
|
||||
try!(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(())
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::de::{Deserialize, DeserializeSeed, Deserializer};
|
||||
use de::{Deserialize, DeserializeSeed, Deserializer};
|
||||
|
||||
/// A DeserializeSeed helper for implementing deserialize_in_place Visitors.
|
||||
///
|
||||
|
46
serde/src/de/utf8.rs
Normal file
46
serde/src/de/utf8.rs
Normal file
@ -0,0 +1,46 @@
|
||||
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()
|
||||
}
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
//! Building blocks for deserializing basic values using the `IntoDeserializer`
|
||||
//! trait.
|
||||
//!
|
||||
//! ```edition2021
|
||||
//! use serde::de::{value, Deserialize, IntoDeserializer};
|
||||
//! use serde_derive::Deserialize;
|
||||
//! ```edition2018
|
||||
//! use std::str::FromStr;
|
||||
//! use serde::Deserialize;
|
||||
//! use serde::de::{value, IntoDeserializer};
|
||||
//!
|
||||
//! #[derive(Deserialize)]
|
||||
//! enum Setting {
|
||||
@ -21,11 +21,12 @@
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
use crate::lib::*;
|
||||
use lib::*;
|
||||
|
||||
use self::private::{First, Second};
|
||||
use crate::de::{self, size_hint, Deserializer, Expected, IntoDeserializer, SeqAccess, Visitor};
|
||||
use crate::ser;
|
||||
use __private::size_hint;
|
||||
use de::{self, Deserializer, Expected, IntoDeserializer, SeqAccess, Visitor};
|
||||
use ser;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -112,7 +113,6 @@ 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,7 +128,9 @@ where
|
||||
type Deserializer = UnitDeserializer<E>;
|
||||
|
||||
fn into_deserializer(self) -> UnitDeserializer<E> {
|
||||
UnitDeserializer::new()
|
||||
UnitDeserializer {
|
||||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -139,15 +141,6 @@ pub struct UnitDeserializer<E> {
|
||||
|
||||
impl_copy_clone!(UnitDeserializer);
|
||||
|
||||
impl<E> UnitDeserializer<E> {
|
||||
#[allow(missing_docs)]
|
||||
pub fn new() -> Self {
|
||||
UnitDeserializer {
|
||||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, E> de::Deserializer<'de> for UnitDeserializer<E>
|
||||
where
|
||||
E: de::Error,
|
||||
@ -185,14 +178,12 @@ impl<E> Debug for UnitDeserializer<E> {
|
||||
|
||||
/// A deserializer that cannot be instantiated.
|
||||
#[cfg(feature = "unstable")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "unstable")))]
|
||||
pub struct NeverDeserializer<E> {
|
||||
never: !,
|
||||
marker: PhantomData<E>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "unstable")))]
|
||||
impl<'de, E> IntoDeserializer<'de, E> for !
|
||||
where
|
||||
E: de::Error,
|
||||
@ -245,15 +236,8 @@ macro_rules! primitive_deserializer {
|
||||
type Deserializer = $name<E>;
|
||||
|
||||
fn into_deserializer(self) -> $name<E> {
|
||||
$name::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> $name<E> {
|
||||
#[allow(missing_docs)]
|
||||
pub fn new(value: $ty) -> Self {
|
||||
$name {
|
||||
value,
|
||||
value: self,
|
||||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -295,17 +279,20 @@ 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<E> {
|
||||
value: u32,
|
||||
@ -321,15 +308,8 @@ where
|
||||
type Deserializer = U32Deserializer<E>;
|
||||
|
||||
fn into_deserializer(self) -> U32Deserializer<E> {
|
||||
U32Deserializer::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> U32Deserializer<E> {
|
||||
#[allow(missing_docs)]
|
||||
pub fn new(value: u32) -> Self {
|
||||
U32Deserializer {
|
||||
value,
|
||||
value: self,
|
||||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -410,15 +390,8 @@ 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,
|
||||
value: self,
|
||||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -497,7 +470,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,
|
||||
}
|
||||
}
|
||||
@ -565,7 +538,6 @@ 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<E> {
|
||||
value: String,
|
||||
marker: PhantomData<E>,
|
||||
@ -582,7 +554,6 @@ impl<E> Clone for StringDeserializer<E> {
|
||||
}
|
||||
|
||||
#[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,
|
||||
@ -590,16 +561,8 @@ where
|
||||
type Deserializer = StringDeserializer<E>;
|
||||
|
||||
fn into_deserializer(self) -> StringDeserializer<E> {
|
||||
StringDeserializer::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
impl<E> StringDeserializer<E> {
|
||||
#[allow(missing_docs)]
|
||||
pub fn new(value: String) -> Self {
|
||||
StringDeserializer {
|
||||
value,
|
||||
value: self,
|
||||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -641,7 +604,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
impl<'de, E> de::EnumAccess<'de> for StringDeserializer<E>
|
||||
impl<'de, 'a, E> de::EnumAccess<'de> for StringDeserializer<E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
@ -670,7 +633,6 @@ impl<E> Debug for StringDeserializer<E> {
|
||||
|
||||
/// A deserializer holding a `Cow<str>`.
|
||||
#[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<E>,
|
||||
@ -687,7 +649,6 @@ 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,
|
||||
@ -695,16 +656,8 @@ 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,
|
||||
value: self,
|
||||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -786,7 +739,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,
|
||||
}
|
||||
}
|
||||
@ -845,7 +798,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,
|
||||
}
|
||||
}
|
||||
@ -940,8 +893,8 @@ where
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
let v = tri!(visitor.visit_seq(&mut self));
|
||||
tri!(self.end());
|
||||
let v = try!(visitor.visit_seq(&mut self));
|
||||
try!(self.end());
|
||||
Ok(v)
|
||||
}
|
||||
|
||||
@ -983,7 +936,7 @@ struct ExpectedInSeq(usize);
|
||||
impl Expected for ExpectedInSeq {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
if self.0 == 1 {
|
||||
formatter.write_str("1 element in sequence")
|
||||
write!(formatter, "1 element in sequence")
|
||||
} else {
|
||||
write!(formatter, "{} elements in sequence", self.0)
|
||||
}
|
||||
@ -1006,7 +959,6 @@ 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<T>
|
||||
where
|
||||
T: IntoDeserializer<'de, E>,
|
||||
@ -1020,7 +972,6 @@ 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<T>
|
||||
where
|
||||
T: IntoDeserializer<'de, E> + Eq + Ord,
|
||||
@ -1034,7 +985,6 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||
impl<'de, T, S, E> IntoDeserializer<'de, E> for HashSet<T, S>
|
||||
where
|
||||
T: IntoDeserializer<'de, E> + Eq + Hash,
|
||||
@ -1059,7 +1009,7 @@ pub struct SeqAccessDeserializer<A> {
|
||||
impl<A> SeqAccessDeserializer<A> {
|
||||
/// Construct a new `SeqAccessDeserializer<A>`.
|
||||
pub fn new(seq: A) -> Self {
|
||||
SeqAccessDeserializer { seq }
|
||||
SeqAccessDeserializer { seq: seq }
|
||||
}
|
||||
}
|
||||
|
||||
@ -1168,8 +1118,8 @@ where
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
let value = tri!(visitor.visit_map(&mut self));
|
||||
tri!(self.end());
|
||||
let value = try!(visitor.visit_map(&mut self));
|
||||
try!(self.end());
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
@ -1177,8 +1127,8 @@ where
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
let value = tri!(visitor.visit_seq(&mut self));
|
||||
tri!(self.end());
|
||||
let value = try!(visitor.visit_seq(&mut self));
|
||||
try!(self.end());
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
@ -1242,8 +1192,8 @@ where
|
||||
{
|
||||
match self.next_pair() {
|
||||
Some((key, value)) => {
|
||||
let key = tri!(kseed.deserialize(key.into_deserializer()));
|
||||
let value = tri!(vseed.deserialize(value.into_deserializer()));
|
||||
let key = try!(kseed.deserialize(key.into_deserializer()));
|
||||
let value = try!(vseed.deserialize(value.into_deserializer()));
|
||||
Ok(Some((key, value)))
|
||||
}
|
||||
None => Ok(None),
|
||||
@ -1347,7 +1297,7 @@ where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
let mut pair_visitor = PairVisitor(Some(self.0), Some(self.1), PhantomData);
|
||||
let pair = tri!(visitor.visit_seq(&mut pair_visitor));
|
||||
let pair = try!(visitor.visit_seq(&mut pair_visitor));
|
||||
if pair_visitor.1.is_none() {
|
||||
Ok(pair)
|
||||
} else {
|
||||
@ -1411,7 +1361,7 @@ struct ExpectedInMap(usize);
|
||||
impl Expected for ExpectedInMap {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
if self.0 == 1 {
|
||||
formatter.write_str("1 element in map")
|
||||
write!(formatter, "1 element in map")
|
||||
} else {
|
||||
write!(formatter, "{} elements in map", self.0)
|
||||
}
|
||||
@ -1421,7 +1371,6 @@ 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<K, V>
|
||||
where
|
||||
K: IntoDeserializer<'de, E> + Eq + Ord,
|
||||
@ -1436,7 +1385,6 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||
impl<'de, K, V, S, E> IntoDeserializer<'de, E> for HashMap<K, V, S>
|
||||
where
|
||||
K: IntoDeserializer<'de, E> + Eq + Hash,
|
||||
@ -1462,7 +1410,7 @@ pub struct MapAccessDeserializer<A> {
|
||||
impl<A> MapAccessDeserializer<A> {
|
||||
/// Construct a new `MapAccessDeserializer<A>`.
|
||||
pub fn new(map: A) -> Self {
|
||||
MapAccessDeserializer { map }
|
||||
MapAccessDeserializer { map: map }
|
||||
}
|
||||
}
|
||||
|
||||
@ -1509,7 +1457,7 @@ where
|
||||
where
|
||||
T: de::DeserializeSeed<'de>,
|
||||
{
|
||||
match tri!(self.map.next_key_seed(seed)) {
|
||||
match 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")),
|
||||
}
|
||||
@ -1518,47 +1466,10 @@ where
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// A deserializer holding an `EnumAccess`.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct EnumAccessDeserializer<A> {
|
||||
access: A,
|
||||
}
|
||||
|
||||
impl<A> EnumAccessDeserializer<A> {
|
||||
/// Construct a new `EnumAccessDeserializer<A>`.
|
||||
pub fn new(access: A) -> Self {
|
||||
EnumAccessDeserializer { access }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, A> de::Deserializer<'de> for EnumAccessDeserializer<A>
|
||||
where
|
||||
A: de::EnumAccess<'de>,
|
||||
{
|
||||
type Error = A::Error;
|
||||
|
||||
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
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 lib::*;
|
||||
|
||||
use crate::de::{
|
||||
self, DeserializeSeed, Deserializer, MapAccess, Unexpected, VariantAccess, Visitor,
|
||||
};
|
||||
use de::{self, DeserializeSeed, Deserializer, MapAccess, Unexpected, VariantAccess, Visitor};
|
||||
|
||||
pub struct UnitOnly<E> {
|
||||
marker: PhantomData<E>,
|
||||
@ -1623,7 +1534,7 @@ mod private {
|
||||
}
|
||||
|
||||
pub fn map_as_enum<A>(map: A) -> MapAsEnum<A> {
|
||||
MapAsEnum { map }
|
||||
MapAsEnum { map: map }
|
||||
}
|
||||
|
||||
impl<'de, A> VariantAccess<'de> for MapAsEnum<A>
|
||||
@ -1647,7 +1558,10 @@ mod private {
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
self.map.next_value_seed(SeedTupleVariant { len, visitor })
|
||||
self.map.next_value_seed(SeedTupleVariant {
|
||||
len: len,
|
||||
visitor: visitor,
|
||||
})
|
||||
}
|
||||
|
||||
fn struct_variant<V>(
|
||||
@ -1658,7 +1572,8 @@ mod private {
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
self.map.next_value_seed(SeedStructVariant { visitor })
|
||||
self.map
|
||||
.next_value_seed(SeedStructVariant { visitor: visitor })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,82 @@
|
||||
// No longer used. Old versions of serde used this macro for supporting targets
|
||||
// that did not yet have 128-bit integer support.
|
||||
/// 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<Self::Ok, Self::Error> {
|
||||
/// /* ... */
|
||||
/// # unimplemented!()
|
||||
/// }
|
||||
///
|
||||
/// /* ... */
|
||||
///
|
||||
/// serde_if_integer128! {
|
||||
/// fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> {
|
||||
/// /* ... */
|
||||
/// # unimplemented!()
|
||||
/// }
|
||||
///
|
||||
/// fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
|
||||
/// /* ... */
|
||||
/// # 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))]
|
||||
#[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)*) => {};
|
||||
}
|
||||
|
219
serde/src/lib.rs
219
serde/src/lib.rs
@ -31,7 +31,8 @@
|
||||
//! for Serde by the community.
|
||||
//!
|
||||
//! - [JSON], the ubiquitous JavaScript Object Notation used by many HTTP APIs.
|
||||
//! - [Postcard], a no\_std and embedded-systems friendly compact binary format.
|
||||
//! - [Bincode], a compact binary format
|
||||
//! used for IPC within the Servo rendering engine.
|
||||
//! - [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
|
||||
@ -44,9 +45,8 @@
|
||||
//! - [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,103 +54,91 @@
|
||||
//! - [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.
|
||||
//! - [Bencode], a simple binary format used in the BitTorrent protocol.
|
||||
//! - [Token streams], for processing Rust procedural macro input.
|
||||
//! *(deserialization only)*
|
||||
//! - [FlexBuffers], the schemaless cousin of Google's FlatBuffers zero-copy serialization format.
|
||||
//! - [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
|
||||
//! [Postcard]: https://github.com/jamesmunns/postcard
|
||||
//! [Bincode]: https://github.com/servo/bincode
|
||||
//! [CBOR]: https://github.com/enarx/ciborium
|
||||
//! [YAML]: https://github.com/dtolnay/serde-yaml
|
||||
//! [MessagePack]: https://github.com/3Hren/msgpack-rust
|
||||
//! [TOML]: https://docs.rs/toml
|
||||
//! [TOML]: https://github.com/alexcrichton/toml-rs
|
||||
//! [Pickle]: https://github.com/birkenfeld/serde-pickle
|
||||
//! [RON]: https://github.com/ron-rs/ron
|
||||
//! [BSON]: https://github.com/mongodb/bson-rust
|
||||
//! [Avro]: https://docs.rs/apache-avro
|
||||
//! [BSON]: https://github.com/zonyitoo/bson-rs
|
||||
//! [Avro]: https://github.com/flavray/avro-rs
|
||||
//! [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-parameter-store.html
|
||||
//! [AWS Parameter Store]: https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-paramstore.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.197")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.136")]
|
||||
// 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(error_in_core, never_type))]
|
||||
#![cfg_attr(feature = "unstable", feature(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
|
||||
#![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,
|
||||
#![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,
|
||||
)
|
||||
)]
|
||||
// Restrictions
|
||||
#![deny(clippy::question_mark_used)]
|
||||
// Rustc lints.
|
||||
#![deny(missing_docs, unused_imports)]
|
||||
|
||||
@ -170,26 +158,21 @@ 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;
|
||||
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::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::marker::{self, PhantomData};
|
||||
pub use self::core::num::Wrapping;
|
||||
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;
|
||||
pub use self::core::ops::Range;
|
||||
pub use self::core::option::{self, Option};
|
||||
pub use self::core::result::{self, Result};
|
||||
|
||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||
pub use alloc::borrow::{Cow, ToOwned};
|
||||
@ -226,23 +209,13 @@ 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::{OsStr, OsString};
|
||||
pub use std::ffi::{CStr, CString, OsStr, OsString};
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::hash::{BuildHasher, Hash};
|
||||
#[cfg(feature = "std")]
|
||||
@ -254,39 +227,28 @@ mod lib {
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
#[cfg(all(feature = "std", no_target_has_atomic, not(no_std_atomic)))]
|
||||
#[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)))]
|
||||
pub use std::sync::atomic::{
|
||||
AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8,
|
||||
AtomicUsize, Ordering,
|
||||
};
|
||||
#[cfg(all(feature = "std", no_target_has_atomic, not(no_std_atomic64)))]
|
||||
#[cfg(all(feature = "std", not(no_std_atomic64)))]
|
||||
pub use std::sync::atomic::{AtomicI64, AtomicU64};
|
||||
|
||||
#[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),
|
||||
}
|
||||
};
|
||||
#[cfg(any(feature = "std", not(no_core_duration)))]
|
||||
pub use self::core::time::Duration;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -301,19 +263,24 @@ pub mod de;
|
||||
pub mod ser;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use crate::de::{Deserialize, Deserializer};
|
||||
pub use de::{Deserialize, Deserializer};
|
||||
#[doc(inline)]
|
||||
pub use crate::ser::{Serialize, Serializer};
|
||||
pub use 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(any(feature = "std", feature = "unstable")))]
|
||||
#[cfg(not(feature = "std"))]
|
||||
mod std_error;
|
||||
|
||||
// Re-export #[derive(Serialize, Deserialize)].
|
||||
@ -322,12 +289,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")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
|
||||
pub use serde_derive::{Deserialize, Serialize};
|
||||
#[doc(hidden)]
|
||||
pub use serde_derive::*;
|
||||
|
||||
#[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))]
|
||||
mod actually_private {
|
||||
|
@ -11,7 +11,7 @@
|
||||
/// input. This requires repetitive implementations of all the [`Deserializer`]
|
||||
/// trait methods.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # 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.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use serde::forward_to_deserialize_any;
|
||||
/// # use serde::de::{value, Deserializer, Visitor};
|
||||
/// #
|
||||
@ -78,10 +78,11 @@
|
||||
/// called `V`. A different type parameter and a different lifetime can be
|
||||
/// specified explicitly if necessary.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use std::marker::PhantomData;
|
||||
/// #
|
||||
/// # use serde::forward_to_deserialize_any;
|
||||
/// # use serde::de::{value, Deserializer, Visitor};
|
||||
/// # use std::marker::PhantomData;
|
||||
/// #
|
||||
/// # struct MyDeserializer<V>(PhantomData<V>);
|
||||
/// #
|
||||
@ -154,7 +155,9 @@ macro_rules! forward_to_deserialize_any_helper {
|
||||
forward_to_deserialize_any_method!{deserialize_i64<$l, $v>()}
|
||||
};
|
||||
(i128<$l:tt, $v:ident>) => {
|
||||
forward_to_deserialize_any_method!{deserialize_i128<$l, $v>()}
|
||||
serde_if_integer128! {
|
||||
forward_to_deserialize_any_method!{deserialize_i128<$l, $v>()}
|
||||
}
|
||||
};
|
||||
(u8<$l:tt, $v:ident>) => {
|
||||
forward_to_deserialize_any_method!{deserialize_u8<$l, $v>()}
|
||||
@ -169,7 +172,9 @@ macro_rules! forward_to_deserialize_any_helper {
|
||||
forward_to_deserialize_any_method!{deserialize_u64<$l, $v>()}
|
||||
};
|
||||
(u128<$l:tt, $v:ident>) => {
|
||||
forward_to_deserialize_any_method!{deserialize_u128<$l, $v>()}
|
||||
serde_if_integer128! {
|
||||
forward_to_deserialize_any_method!{deserialize_u128<$l, $v>()}
|
||||
}
|
||||
};
|
||||
(f32<$l:tt, $v:ident>) => {
|
||||
forward_to_deserialize_any_method!{deserialize_f32<$l, $v>()}
|
||||
|
@ -1,13 +1,10 @@
|
||||
use crate::lib::*;
|
||||
use lib::*;
|
||||
|
||||
use crate::de::value::{BorrowedBytesDeserializer, BytesDeserializer};
|
||||
use crate::de::{
|
||||
Deserialize, DeserializeSeed, Deserializer, EnumAccess, Error, IntoDeserializer, VariantAccess,
|
||||
Visitor,
|
||||
};
|
||||
use de::value::{BorrowedBytesDeserializer, BytesDeserializer};
|
||||
use de::{Deserialize, Deserializer, Error, IntoDeserializer, Visitor};
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
use crate::de::{MapAccess, Unexpected};
|
||||
use de::{DeserializeSeed, MapAccess, Unexpected};
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
pub use self::content::{
|
||||
@ -16,7 +13,7 @@ pub use self::content::{
|
||||
TagOrContentField, TagOrContentFieldVisitor, TaggedContentVisitor, UntaggedUnitVisitor,
|
||||
};
|
||||
|
||||
pub use crate::seed::InPlaceSeed;
|
||||
pub use seed::InPlaceSeed;
|
||||
|
||||
/// If the missing field is of type `Option<T>` then treat is as `None`,
|
||||
/// otherwise it is an error.
|
||||
@ -206,13 +203,13 @@ mod content {
|
||||
// This issue is tracking making some of this stuff public:
|
||||
// https://github.com/serde-rs/serde/issues/741
|
||||
|
||||
use crate::lib::*;
|
||||
use lib::*;
|
||||
|
||||
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,
|
||||
use __private::size_hint;
|
||||
use actually_private;
|
||||
use de::{
|
||||
self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, IgnoredAny,
|
||||
MapAccess, SeqAccess, Unexpected, Visitor,
|
||||
};
|
||||
|
||||
/// Used from generated code to buffer the contents of the Deserializer when
|
||||
@ -302,17 +299,6 @@ 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<Content<'de>>,
|
||||
}
|
||||
@ -488,9 +474,8 @@ mod content {
|
||||
where
|
||||
V: SeqAccess<'de>,
|
||||
{
|
||||
let mut vec =
|
||||
Vec::<Content>::with_capacity(size_hint::cautious::<Content>(visitor.size_hint()));
|
||||
while let Some(e) = tri!(visitor.next_element()) {
|
||||
let mut vec = Vec::with_capacity(size_hint::cautious(visitor.size_hint()));
|
||||
while let Some(e) = try!(visitor.next_element()) {
|
||||
vec.push(e);
|
||||
}
|
||||
Ok(Content::Seq(vec))
|
||||
@ -500,11 +485,8 @@ mod content {
|
||||
where
|
||||
V: MapAccess<'de>,
|
||||
{
|
||||
let mut vec =
|
||||
Vec::<(Content, Content)>::with_capacity(
|
||||
size_hint::cautious::<(Content, Content)>(visitor.size_hint()),
|
||||
);
|
||||
while let Some(kv) = tri!(visitor.next_entry()) {
|
||||
let mut vec = Vec::with_capacity(size_hint::cautious(visitor.size_hint()));
|
||||
while let Some(kv) = try!(visitor.next_entry()) {
|
||||
vec.push(kv);
|
||||
}
|
||||
Ok(Content::Map(vec))
|
||||
@ -536,7 +518,7 @@ mod content {
|
||||
impl<'de> TagOrContentVisitor<'de> {
|
||||
fn new(name: &'static str) -> Self {
|
||||
TagOrContentVisitor {
|
||||
name,
|
||||
name: name,
|
||||
value: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -815,29 +797,51 @@ mod content {
|
||||
/// Used by generated code to deserialize an internally tagged enum.
|
||||
///
|
||||
/// Not public API.
|
||||
pub struct TaggedContentVisitor<T> {
|
||||
tag_name: &'static str,
|
||||
expecting: &'static str,
|
||||
value: PhantomData<T>,
|
||||
pub struct TaggedContent<'de, T> {
|
||||
pub tag: T,
|
||||
pub content: Content<'de>,
|
||||
}
|
||||
|
||||
impl<T> TaggedContentVisitor<T> {
|
||||
/// Not public API.
|
||||
pub struct TaggedContentVisitor<'de, T> {
|
||||
tag_name: &'static str,
|
||||
expecting: &'static str,
|
||||
value: PhantomData<TaggedContent<'de, T>>,
|
||||
}
|
||||
|
||||
impl<'de, T> TaggedContentVisitor<'de, T> {
|
||||
/// 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> Visitor<'de> for TaggedContentVisitor<T>
|
||||
impl<'de, T> DeserializeSeed<'de> for TaggedContentVisitor<'de, T>
|
||||
where
|
||||
T: Deserialize<'de>,
|
||||
{
|
||||
type Value = (T, Content<'de>);
|
||||
type Value = TaggedContent<'de, T>;
|
||||
|
||||
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
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>;
|
||||
|
||||
fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt.write_str(self.expecting)
|
||||
@ -847,14 +851,17 @@ mod content {
|
||||
where
|
||||
S: SeqAccess<'de>,
|
||||
{
|
||||
let tag = match tri!(seq.next_element()) {
|
||||
let tag = match try!(seq.next_element()) {
|
||||
Some(tag) => tag,
|
||||
None => {
|
||||
return Err(de::Error::missing_field(self.tag_name));
|
||||
}
|
||||
};
|
||||
let rest = de::value::SeqAccessDeserializer::new(seq);
|
||||
Ok((tag, tri!(Content::deserialize(rest))))
|
||||
Ok(TaggedContent {
|
||||
tag: tag,
|
||||
content: try!(Content::deserialize(rest)),
|
||||
})
|
||||
}
|
||||
|
||||
fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
|
||||
@ -862,27 +869,27 @@ mod content {
|
||||
M: MapAccess<'de>,
|
||||
{
|
||||
let mut tag = None;
|
||||
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))) {
|
||||
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))) {
|
||||
match k {
|
||||
TagOrContent::Tag => {
|
||||
if tag.is_some() {
|
||||
return Err(de::Error::duplicate_field(self.tag_name));
|
||||
}
|
||||
tag = Some(tri!(map.next_value()));
|
||||
tag = Some(try!(map.next_value()));
|
||||
}
|
||||
TagOrContent::Content(k) => {
|
||||
let v = tri!(map.next_value());
|
||||
let v = try!(map.next_value());
|
||||
vec.push((k, v));
|
||||
}
|
||||
}
|
||||
}
|
||||
match tag {
|
||||
None => Err(de::Error::missing_field(self.tag_name)),
|
||||
Some(tag) => Ok((tag, Content::Map(vec))),
|
||||
Some(tag) => Ok(TaggedContent {
|
||||
tag: tag,
|
||||
content: Content::Map(vec),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -908,7 +915,7 @@ mod content {
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
deserializer.deserialize_identifier(self)
|
||||
deserializer.deserialize_str(self)
|
||||
}
|
||||
}
|
||||
|
||||
@ -919,20 +926,6 @@ mod content {
|
||||
write!(formatter, "{:?} or {:?}", self.tag, self.content)
|
||||
}
|
||||
|
||||
fn visit_u64<E>(self, field_index: u64) -> Result<Self::Value, E>
|
||||
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<E>(self, field: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
@ -945,19 +938,6 @@ mod content {
|
||||
Err(de::Error::invalid_value(Unexpected::Str(field), &self))
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, field: &[u8]) -> Result<Self::Value, E>
|
||||
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
|
||||
@ -983,7 +963,7 @@ mod content {
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
deserializer.deserialize_identifier(self)
|
||||
deserializer.deserialize_str(self)
|
||||
}
|
||||
}
|
||||
|
||||
@ -998,31 +978,13 @@ mod content {
|
||||
)
|
||||
}
|
||||
|
||||
fn visit_u64<E>(self, field_index: u64) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
match field_index {
|
||||
0 => Ok(TagContentOtherField::Tag),
|
||||
1 => Ok(TagContentOtherField::Content),
|
||||
_ => Ok(TagContentOtherField::Other),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, field: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
self.visit_bytes(field.as_bytes())
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, field: &[u8]) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
if field == self.tag.as_bytes() {
|
||||
if field == self.tag {
|
||||
Ok(TagContentOtherField::Tag)
|
||||
} else if field == self.content.as_bytes() {
|
||||
} else if field == self.content {
|
||||
Ok(TagContentOtherField::Content)
|
||||
} else {
|
||||
Ok(TagContentOtherField::Other)
|
||||
@ -1088,9 +1050,9 @@ mod content {
|
||||
E: de::Error,
|
||||
{
|
||||
let seq = content.into_iter().map(ContentDeserializer::new);
|
||||
let mut seq_visitor = SeqDeserializer::new(seq);
|
||||
let value = tri!(visitor.visit_seq(&mut seq_visitor));
|
||||
tri!(seq_visitor.end());
|
||||
let mut seq_visitor = de::value::SeqDeserializer::new(seq);
|
||||
let value = try!(visitor.visit_seq(&mut seq_visitor));
|
||||
try!(seq_visitor.end());
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
@ -1105,9 +1067,9 @@ mod content {
|
||||
let map = content
|
||||
.into_iter()
|
||||
.map(|(k, v)| (ContentDeserializer::new(k), ContentDeserializer::new(v)));
|
||||
let mut map_visitor = MapDeserializer::new(map);
|
||||
let value = tri!(visitor.visit_map(&mut map_visitor));
|
||||
tri!(map_visitor.end());
|
||||
let mut map_visitor = de::value::MapDeserializer::new(map);
|
||||
let value = try!(visitor.visit_map(&mut map_visitor));
|
||||
try!(map_visitor.end());
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
@ -1300,17 +1262,6 @@ mod content {
|
||||
{
|
||||
match self.content {
|
||||
Content::Unit => visitor.visit_unit(),
|
||||
|
||||
// Allow deserializing newtype variant containing unit.
|
||||
//
|
||||
// #[derive(Deserialize)]
|
||||
// #[serde(tag = "result")]
|
||||
// enum Response<T> {
|
||||
// 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)),
|
||||
}
|
||||
}
|
||||
@ -1495,7 +1446,7 @@ mod content {
|
||||
/// private API, don't use
|
||||
pub fn new(content: Content<'de>) -> Self {
|
||||
ContentDeserializer {
|
||||
content,
|
||||
content: content,
|
||||
err: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -1516,8 +1467,8 @@ mod content {
|
||||
{
|
||||
pub fn new(variant: Content<'de>, value: Option<Content<'de>>) -> EnumDeserializer<'de, E> {
|
||||
EnumDeserializer {
|
||||
variant,
|
||||
value,
|
||||
variant: variant,
|
||||
value: value,
|
||||
err: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -1583,7 +1534,7 @@ mod content {
|
||||
{
|
||||
match self.value {
|
||||
Some(Content::Seq(v)) => {
|
||||
de::Deserializer::deserialize_any(SeqDeserializer::new(v.into_iter()), visitor)
|
||||
de::Deserializer::deserialize_any(SeqDeserializer::new(v), visitor)
|
||||
}
|
||||
Some(other) => Err(de::Error::invalid_type(
|
||||
other.unexpected(),
|
||||
@ -1606,10 +1557,10 @@ mod content {
|
||||
{
|
||||
match self.value {
|
||||
Some(Content::Map(v)) => {
|
||||
de::Deserializer::deserialize_any(MapDeserializer::new(v.into_iter()), visitor)
|
||||
de::Deserializer::deserialize_any(MapDeserializer::new(v), visitor)
|
||||
}
|
||||
Some(Content::Seq(v)) => {
|
||||
de::Deserializer::deserialize_any(SeqDeserializer::new(v.into_iter()), visitor)
|
||||
de::Deserializer::deserialize_any(SeqDeserializer::new(v), visitor)
|
||||
}
|
||||
Some(other) => Err(de::Error::invalid_type(
|
||||
other.unexpected(),
|
||||
@ -1623,6 +1574,156 @@ mod content {
|
||||
}
|
||||
}
|
||||
|
||||
struct SeqDeserializer<'de, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
iter: <Vec<Content<'de>> as IntoIterator>::IntoIter,
|
||||
err: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<'de, E> SeqDeserializer<'de, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
fn new(vec: Vec<Content<'de>>) -> 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<V>(mut self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
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<T>(&mut self, seed: T) -> Result<Option<T::Value>, 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<usize> {
|
||||
size_hint::from_bounds(&self.iter)
|
||||
}
|
||||
}
|
||||
|
||||
struct MapDeserializer<'de, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
iter: <Vec<(Content<'de>, Content<'de>)> as IntoIterator>::IntoIter,
|
||||
value: Option<Content<'de>>,
|
||||
err: PhantomData<E>,
|
||||
}
|
||||
|
||||
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<T>(&mut self, seed: T) -> Result<Option<T::Value>, 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<T>(&mut self, seed: T) -> Result<T::Value, Self::Error>
|
||||
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<usize> {
|
||||
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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
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>,
|
||||
@ -1684,9 +1785,9 @@ mod content {
|
||||
E: de::Error,
|
||||
{
|
||||
let seq = content.iter().map(ContentRefDeserializer::new);
|
||||
let mut seq_visitor = SeqDeserializer::new(seq);
|
||||
let value = tri!(visitor.visit_seq(&mut seq_visitor));
|
||||
tri!(seq_visitor.end());
|
||||
let mut seq_visitor = de::value::SeqDeserializer::new(seq);
|
||||
let value = try!(visitor.visit_seq(&mut seq_visitor));
|
||||
try!(seq_visitor.end());
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
@ -1698,15 +1799,15 @@ mod content {
|
||||
V: Visitor<'de>,
|
||||
E: de::Error,
|
||||
{
|
||||
let map = content.iter().map(|(k, v)| {
|
||||
let map = content.iter().map(|&(ref k, ref v)| {
|
||||
(
|
||||
ContentRefDeserializer::new(k),
|
||||
ContentRefDeserializer::new(v),
|
||||
)
|
||||
});
|
||||
let mut map_visitor = MapDeserializer::new(map);
|
||||
let value = tri!(visitor.visit_map(&mut map_visitor));
|
||||
tri!(map_visitor.end());
|
||||
let mut map_visitor = de::value::MapDeserializer::new(map);
|
||||
let value = try!(visitor.visit_map(&mut map_visitor));
|
||||
try!(map_visitor.end());
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
@ -1995,7 +2096,7 @@ mod content {
|
||||
let (variant, value) = match *self.content {
|
||||
Content::Map(ref value) => {
|
||||
let mut iter = value.iter();
|
||||
let (variant, value) = match iter.next() {
|
||||
let &(ref variant, ref value) = match iter.next() {
|
||||
Some(v) => v,
|
||||
None => {
|
||||
return Err(de::Error::invalid_value(
|
||||
@ -2023,8 +2124,8 @@ mod content {
|
||||
};
|
||||
|
||||
visitor.visit_enum(EnumRefDeserializer {
|
||||
variant,
|
||||
value,
|
||||
variant: variant,
|
||||
value: value,
|
||||
err: PhantomData,
|
||||
})
|
||||
}
|
||||
@ -2068,20 +2169,12 @@ 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,
|
||||
@ -2150,7 +2243,7 @@ mod content {
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
match self.value {
|
||||
Some(Content::Seq(v)) => {
|
||||
Some(&Content::Seq(ref v)) => {
|
||||
de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor)
|
||||
}
|
||||
Some(other) => Err(de::Error::invalid_type(
|
||||
@ -2173,10 +2266,10 @@ mod content {
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
match self.value {
|
||||
Some(Content::Map(v)) => {
|
||||
Some(&Content::Map(ref v)) => {
|
||||
de::Deserializer::deserialize_any(MapRefDeserializer::new(v), visitor)
|
||||
}
|
||||
Some(Content::Seq(v)) => {
|
||||
Some(&Content::Seq(ref v)) => {
|
||||
de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor)
|
||||
}
|
||||
Some(other) => Err(de::Error::invalid_type(
|
||||
@ -2226,7 +2319,7 @@ mod content {
|
||||
if len == 0 {
|
||||
visitor.visit_unit()
|
||||
} else {
|
||||
let ret = tri!(visitor.visit_seq(&mut self));
|
||||
let ret = try!(visitor.visit_seq(&mut self));
|
||||
let remaining = self.iter.len();
|
||||
if remaining == 0 {
|
||||
Ok(ret)
|
||||
@ -2299,7 +2392,7 @@ mod content {
|
||||
T: de::DeserializeSeed<'de>,
|
||||
{
|
||||
match self.iter.next() {
|
||||
Some((key, value)) => {
|
||||
Some(&(ref key, ref value)) => {
|
||||
self.value = Some(value);
|
||||
seed.deserialize(ContentRefDeserializer::new(key)).map(Some)
|
||||
}
|
||||
@ -2377,8 +2470,8 @@ mod content {
|
||||
/// Not public API.
|
||||
pub fn new(type_name: &'a str, variant_name: &'a str) -> Self {
|
||||
InternallyTaggedUnitVisitor {
|
||||
type_name,
|
||||
variant_name,
|
||||
type_name: type_name,
|
||||
variant_name: variant_name,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2405,7 +2498,7 @@ mod content {
|
||||
where
|
||||
M: MapAccess<'de>,
|
||||
{
|
||||
while tri!(access.next_entry::<IgnoredAny, IgnoredAny>()).is_some() {}
|
||||
while try!(access.next_entry::<IgnoredAny, IgnoredAny>()).is_some() {}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -2422,8 +2515,8 @@ mod content {
|
||||
/// Not public API.
|
||||
pub fn new(type_name: &'a str, variant_name: &'a str) -> Self {
|
||||
UntaggedUnitVisitor {
|
||||
type_name,
|
||||
variant_name,
|
||||
type_name: type_name,
|
||||
variant_name: variant_name,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2604,7 +2697,7 @@ where
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
macro_rules! forward_to_deserialize_other {
|
||||
($($func:ident ($($arg:ty),*))*) => {
|
||||
($($func:ident ( $($arg:ty),* ))*) => {
|
||||
$(
|
||||
fn $func<V>(self, $(_: $arg,)* _visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
@ -2627,7 +2720,11 @@ where
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
self.deserialize_map(visitor)
|
||||
visitor.visit_map(FlatInternallyTaggedAccess {
|
||||
iter: self.0.iter_mut(),
|
||||
pending: None,
|
||||
_marker: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
fn deserialize_enum<V>(
|
||||
@ -2639,8 +2736,17 @@ where
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
for entry in self.0 {
|
||||
if let Some((key, value)) = flat_map_take_entry(entry, variants) {
|
||||
for item in self.0.iter_mut() {
|
||||
// items in the vector are nulled out when used. So we can only use
|
||||
// an item if it's still filled in and if the field is one we care
|
||||
// about.
|
||||
let use_item = match *item {
|
||||
None => false,
|
||||
Some((ref c, _)) => c.as_str().map_or(false, |x| variants.contains(&x)),
|
||||
};
|
||||
|
||||
if use_item {
|
||||
let (key, value) = item.take().unwrap();
|
||||
return visitor.visit_enum(EnumDeserializer::new(key, Some(value)));
|
||||
}
|
||||
}
|
||||
@ -2655,11 +2761,7 @@ where
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_map(FlatMapAccess {
|
||||
iter: self.0.iter(),
|
||||
pending_content: None,
|
||||
_marker: PhantomData,
|
||||
})
|
||||
visitor.visit_map(FlatMapAccess::new(self.0.iter()))
|
||||
}
|
||||
|
||||
fn deserialize_struct<V>(
|
||||
@ -2671,12 +2773,7 @@ where
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_map(FlatStructAccess {
|
||||
iter: self.0.iter_mut(),
|
||||
pending_content: None,
|
||||
fields,
|
||||
_marker: PhantomData,
|
||||
})
|
||||
visitor.visit_map(FlatStructAccess::new(self.0.iter_mut(), fields))
|
||||
}
|
||||
|
||||
fn deserialize_newtype_struct<V>(self, _name: &str, visitor: V) -> Result<V::Value, Self::Error>
|
||||
@ -2703,13 +2800,6 @@ where
|
||||
visitor.visit_unit()
|
||||
}
|
||||
|
||||
fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_unit()
|
||||
}
|
||||
|
||||
forward_to_deserialize_other! {
|
||||
deserialize_bool()
|
||||
deserialize_i8()
|
||||
@ -2732,16 +2822,30 @@ where
|
||||
deserialize_tuple(usize)
|
||||
deserialize_tuple_struct(&'static str, usize)
|
||||
deserialize_identifier()
|
||||
deserialize_ignored_any()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
struct FlatMapAccess<'a, 'de: 'a, E> {
|
||||
pub struct FlatMapAccess<'a, 'de: 'a, E> {
|
||||
iter: slice::Iter<'a, Option<(Content<'de>, Content<'de>)>>,
|
||||
pending_content: Option<&'a Content<'de>>,
|
||||
_marker: PhantomData<E>,
|
||||
}
|
||||
|
||||
#[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
|
||||
@ -2756,10 +2860,6 @@ 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);
|
||||
}
|
||||
@ -2779,13 +2879,28 @@ where
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
struct FlatStructAccess<'a, 'de: 'a, E> {
|
||||
pub struct FlatStructAccess<'a, 'de: 'a, E> {
|
||||
iter: slice::IterMut<'a, Option<(Content<'de>, Content<'de>)>>,
|
||||
pending_content: Option<Content<'de>>,
|
||||
fields: &'static [&'static str],
|
||||
_marker: PhantomData<E>,
|
||||
}
|
||||
|
||||
#[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
|
||||
@ -2797,8 +2912,17 @@ where
|
||||
where
|
||||
T: DeserializeSeed<'de>,
|
||||
{
|
||||
for entry in self.iter.by_ref() {
|
||||
if let Some((key, content)) = flat_map_take_entry(entry, self.fields) {
|
||||
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();
|
||||
self.pending_content = Some(content);
|
||||
return seed.deserialize(ContentDeserializer::new(key)).map(Some);
|
||||
}
|
||||
@ -2817,76 +2941,44 @@ 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"))]
|
||||
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
|
||||
}
|
||||
pub struct FlatInternallyTaggedAccess<'a, 'de: 'a, E> {
|
||||
iter: slice::IterMut<'a, Option<(Content<'de>, Content<'de>)>>,
|
||||
pending: Option<&'a Content<'de>>,
|
||||
_marker: PhantomData<E>,
|
||||
}
|
||||
|
||||
pub struct AdjacentlyTaggedEnumVariantSeed<F> {
|
||||
pub enum_name: &'static str,
|
||||
pub variants: &'static [&'static str],
|
||||
pub fields_enum: PhantomData<F>,
|
||||
}
|
||||
|
||||
pub struct AdjacentlyTaggedEnumVariantVisitor<F> {
|
||||
enum_name: &'static str,
|
||||
fields_enum: PhantomData<F>,
|
||||
}
|
||||
|
||||
impl<'de, F> Visitor<'de> for AdjacentlyTaggedEnumVariantVisitor<F>
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
impl<'a, 'de, E> MapAccess<'de> for FlatInternallyTaggedAccess<'a, 'de, E>
|
||||
where
|
||||
F: Deserialize<'de>,
|
||||
E: Error,
|
||||
{
|
||||
type Value = F;
|
||||
type Error = E;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(formatter, "variant of enum {}", self.enum_name)
|
||||
fn next_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, 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 visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
|
||||
fn next_value_seed<T>(&mut self, seed: T) -> Result<T::Value, Self::Error>
|
||||
where
|
||||
A: EnumAccess<'de>,
|
||||
T: DeserializeSeed<'de>,
|
||||
{
|
||||
let (variant, variant_access) = tri!(data.variant());
|
||||
tri!(variant_access.unit_variant());
|
||||
Ok(variant)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, F> DeserializeSeed<'de> for AdjacentlyTaggedEnumVariantSeed<F>
|
||||
where
|
||||
F: Deserialize<'de>,
|
||||
{
|
||||
type Value = F;
|
||||
|
||||
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
deserializer.deserialize_enum(
|
||||
self.enum_name,
|
||||
self.variants,
|
||||
AdjacentlyTaggedEnumVariantVisitor {
|
||||
enum_name: self.enum_name,
|
||||
fields_enum: PhantomData,
|
||||
},
|
||||
)
|
||||
match self.pending.take() {
|
||||
Some(value) => seed.deserialize(ContentRefDeserializer::new(value)),
|
||||
None => panic!("value is missing"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
// Used only by Serde doc tests. Not public API.
|
||||
|
||||
use crate::lib::*;
|
||||
use lib::*;
|
||||
|
||||
use crate::ser;
|
||||
use ser;
|
||||
|
||||
#[doc(hidden)]
|
||||
#[derive(Debug)]
|
||||
|
@ -3,28 +3,30 @@ 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 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 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 self::string::from_utf8_lossy;
|
||||
|
||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
||||
pub use crate::lib::{ToString, Vec};
|
||||
pub use lib::{ToString, Vec};
|
||||
|
||||
#[cfg(not(no_core_try_from))]
|
||||
pub use crate::lib::convert::TryFrom;
|
||||
pub use lib::convert::TryFrom;
|
||||
|
||||
mod string {
|
||||
use crate::lib::*;
|
||||
use lib::*;
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
pub fn from_utf8_lossy(bytes: &[u8]) -> Cow<str> {
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::lib::*;
|
||||
use lib::*;
|
||||
|
||||
use crate::ser::{self, Impossible, Serialize, SerializeMap, SerializeStruct, Serializer};
|
||||
use 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,
|
||||
variant_ident,
|
||||
tag,
|
||||
variant_name,
|
||||
type_ident: type_ident,
|
||||
variant_ident: variant_ident,
|
||||
tag: tag,
|
||||
variant_name: variant_name,
|
||||
delegate: serializer,
|
||||
})
|
||||
}
|
||||
@ -51,6 +51,7 @@ enum Unsupported {
|
||||
String,
|
||||
ByteArray,
|
||||
Optional,
|
||||
Unit,
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
UnitStruct,
|
||||
Sequence,
|
||||
@ -69,6 +70,7 @@ 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"),
|
||||
@ -182,14 +184,12 @@ where
|
||||
}
|
||||
|
||||
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
|
||||
let mut map = tri!(self.delegate.serialize_map(Some(1)));
|
||||
tri!(map.serialize_entry(self.tag, self.variant_name));
|
||||
map.end()
|
||||
Err(self.bad_type(Unsupported::Unit))
|
||||
}
|
||||
|
||||
fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
|
||||
let mut map = tri!(self.delegate.serialize_map(Some(1)));
|
||||
tri!(map.serialize_entry(self.tag, self.variant_name));
|
||||
let mut map = try!(self.delegate.serialize_map(Some(1)));
|
||||
try!(map.serialize_entry(self.tag, self.variant_name));
|
||||
map.end()
|
||||
}
|
||||
|
||||
@ -199,9 +199,9 @@ where
|
||||
_: u32,
|
||||
inner_variant: &'static str,
|
||||
) -> Result<Self::Ok, Self::Error> {
|
||||
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, &()));
|
||||
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, &()));
|
||||
map.end()
|
||||
}
|
||||
|
||||
@ -226,9 +226,9 @@ where
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
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));
|
||||
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));
|
||||
map.end()
|
||||
}
|
||||
|
||||
@ -269,9 +269,9 @@ where
|
||||
inner_variant: &'static str,
|
||||
len: usize,
|
||||
) -> Result<Self::SerializeTupleVariant, Self::Error> {
|
||||
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));
|
||||
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));
|
||||
Ok(SerializeTupleVariantAsMapValue::new(
|
||||
map,
|
||||
inner_variant,
|
||||
@ -280,8 +280,8 @@ where
|
||||
}
|
||||
|
||||
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
|
||||
let mut map = tri!(self.delegate.serialize_map(len.map(|len| len + 1)));
|
||||
tri!(map.serialize_entry(self.tag, self.variant_name));
|
||||
let mut map = try!(self.delegate.serialize_map(len.map(|len| len + 1)));
|
||||
try!(map.serialize_entry(self.tag, self.variant_name));
|
||||
Ok(map)
|
||||
}
|
||||
|
||||
@ -290,8 +290,8 @@ where
|
||||
name: &'static str,
|
||||
len: usize,
|
||||
) -> Result<Self::SerializeStruct, Self::Error> {
|
||||
let mut state = tri!(self.delegate.serialize_struct(name, len + 1));
|
||||
tri!(state.serialize_field(self.tag, self.variant_name));
|
||||
let mut state = try!(self.delegate.serialize_struct(name, len + 1));
|
||||
try!(state.serialize_field(self.tag, self.variant_name));
|
||||
Ok(state)
|
||||
}
|
||||
|
||||
@ -316,9 +316,9 @@ where
|
||||
inner_variant: &'static str,
|
||||
len: usize,
|
||||
) -> Result<Self::SerializeStructVariant, Self::Error> {
|
||||
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));
|
||||
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));
|
||||
Ok(SerializeStructVariantAsMapValue::new(
|
||||
map,
|
||||
inner_variant,
|
||||
@ -337,9 +337,9 @@ where
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
mod content {
|
||||
use crate::lib::*;
|
||||
use lib::*;
|
||||
|
||||
use crate::ser::{self, Serialize, Serializer};
|
||||
use ser::{self, Serialize, Serializer};
|
||||
|
||||
pub struct SerializeTupleVariantAsMapValue<M> {
|
||||
map: M,
|
||||
@ -350,8 +350,8 @@ mod content {
|
||||
impl<M> SerializeTupleVariantAsMapValue<M> {
|
||||
pub fn new(map: M, name: &'static str, len: usize) -> Self {
|
||||
SerializeTupleVariantAsMapValue {
|
||||
map,
|
||||
name,
|
||||
map: map,
|
||||
name: name,
|
||||
fields: Vec::with_capacity(len),
|
||||
}
|
||||
}
|
||||
@ -368,13 +368,13 @@ mod content {
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
let value = tri!(value.serialize(ContentSerializer::<M::Error>::new()));
|
||||
let value = try!(value.serialize(ContentSerializer::<M::Error>::new()));
|
||||
self.fields.push(value);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn end(mut self) -> Result<M::Ok, M::Error> {
|
||||
tri!(self
|
||||
try!(self
|
||||
.map
|
||||
.serialize_value(&Content::TupleStruct(self.name, self.fields)));
|
||||
self.map.end()
|
||||
@ -390,8 +390,8 @@ mod content {
|
||||
impl<M> SerializeStructVariantAsMapValue<M> {
|
||||
pub fn new(map: M, name: &'static str, len: usize) -> Self {
|
||||
SerializeStructVariantAsMapValue {
|
||||
map,
|
||||
name,
|
||||
map: map,
|
||||
name: name,
|
||||
fields: Vec::with_capacity(len),
|
||||
}
|
||||
}
|
||||
@ -412,13 +412,13 @@ mod content {
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
let value = tri!(value.serialize(ContentSerializer::<M::Error>::new()));
|
||||
let value = try!(value.serialize(ContentSerializer::<M::Error>::new()));
|
||||
self.fields.push((key, value));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn end(mut self) -> Result<M::Ok, M::Error> {
|
||||
tri!(self
|
||||
try!(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 crate::ser::SerializeTuple;
|
||||
let mut tuple = tri!(serializer.serialize_tuple(elements.len()));
|
||||
use ser::SerializeTuple;
|
||||
let mut tuple = try!(serializer.serialize_tuple(elements.len()));
|
||||
for e in elements {
|
||||
tri!(tuple.serialize_element(e));
|
||||
try!(tuple.serialize_element(e));
|
||||
}
|
||||
tuple.end()
|
||||
}
|
||||
Content::TupleStruct(n, ref fields) => {
|
||||
use crate::ser::SerializeTupleStruct;
|
||||
let mut ts = tri!(serializer.serialize_tuple_struct(n, fields.len()));
|
||||
use ser::SerializeTupleStruct;
|
||||
let mut ts = try!(serializer.serialize_tuple_struct(n, fields.len()));
|
||||
for f in fields {
|
||||
tri!(ts.serialize_field(f));
|
||||
try!(ts.serialize_field(f));
|
||||
}
|
||||
ts.end()
|
||||
}
|
||||
Content::TupleVariant(n, i, v, ref fields) => {
|
||||
use crate::ser::SerializeTupleVariant;
|
||||
let mut tv = tri!(serializer.serialize_tuple_variant(n, i, v, fields.len()));
|
||||
use ser::SerializeTupleVariant;
|
||||
let mut tv = try!(serializer.serialize_tuple_variant(n, i, v, fields.len()));
|
||||
for f in fields {
|
||||
tri!(tv.serialize_field(f));
|
||||
try!(tv.serialize_field(f));
|
||||
}
|
||||
tv.end()
|
||||
}
|
||||
Content::Map(ref entries) => {
|
||||
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));
|
||||
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));
|
||||
}
|
||||
map.end()
|
||||
}
|
||||
Content::Struct(n, ref fields) => {
|
||||
use crate::ser::SerializeStruct;
|
||||
let mut s = tri!(serializer.serialize_struct(n, fields.len()));
|
||||
use ser::SerializeStruct;
|
||||
let mut s = try!(serializer.serialize_struct(n, fields.len()));
|
||||
for &(k, ref v) in fields {
|
||||
tri!(s.serialize_field(k, v));
|
||||
try!(s.serialize_field(k, v));
|
||||
}
|
||||
s.end()
|
||||
}
|
||||
Content::StructVariant(n, i, v, ref fields) => {
|
||||
use crate::ser::SerializeStructVariant;
|
||||
let mut sv = tri!(serializer.serialize_struct_variant(n, i, v, fields.len()));
|
||||
use ser::SerializeStructVariant;
|
||||
let mut sv = try!(serializer.serialize_struct_variant(n, i, v, fields.len()));
|
||||
for &(k, ref v) in fields {
|
||||
tri!(sv.serialize_field(k, v));
|
||||
try!(sv.serialize_field(k, v));
|
||||
}
|
||||
sv.end()
|
||||
}
|
||||
@ -639,7 +639,7 @@ mod content {
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
Ok(Content::Some(Box::new(tri!(value.serialize(self)))))
|
||||
Ok(Content::Some(Box::new(try!(value.serialize(self)))))
|
||||
}
|
||||
|
||||
fn serialize_unit(self) -> Result<Content, E> {
|
||||
@ -669,7 +669,7 @@ mod content {
|
||||
{
|
||||
Ok(Content::NewtypeStruct(
|
||||
name,
|
||||
Box::new(tri!(value.serialize(self))),
|
||||
Box::new(try!(value.serialize(self))),
|
||||
))
|
||||
}
|
||||
|
||||
@ -687,7 +687,7 @@ mod content {
|
||||
name,
|
||||
variant_index,
|
||||
variant,
|
||||
Box::new(tri!(value.serialize(self))),
|
||||
Box::new(try!(value.serialize(self))),
|
||||
))
|
||||
}
|
||||
|
||||
@ -711,7 +711,7 @@ mod content {
|
||||
len: usize,
|
||||
) -> Result<Self::SerializeTupleStruct, E> {
|
||||
Ok(SerializeTupleStruct {
|
||||
name,
|
||||
name: name,
|
||||
fields: Vec::with_capacity(len),
|
||||
error: PhantomData,
|
||||
})
|
||||
@ -725,9 +725,9 @@ mod content {
|
||||
len: usize,
|
||||
) -> Result<Self::SerializeTupleVariant, E> {
|
||||
Ok(SerializeTupleVariant {
|
||||
name,
|
||||
variant_index,
|
||||
variant,
|
||||
name: name,
|
||||
variant_index: variant_index,
|
||||
variant: variant,
|
||||
fields: Vec::with_capacity(len),
|
||||
error: PhantomData,
|
||||
})
|
||||
@ -747,7 +747,7 @@ mod content {
|
||||
len: usize,
|
||||
) -> Result<Self::SerializeStruct, E> {
|
||||
Ok(SerializeStruct {
|
||||
name,
|
||||
name: name,
|
||||
fields: Vec::with_capacity(len),
|
||||
error: PhantomData,
|
||||
})
|
||||
@ -761,9 +761,9 @@ mod content {
|
||||
len: usize,
|
||||
) -> Result<Self::SerializeStructVariant, E> {
|
||||
Ok(SerializeStructVariant {
|
||||
name,
|
||||
variant_index,
|
||||
variant,
|
||||
name: name,
|
||||
variant_index: variant_index,
|
||||
variant: variant,
|
||||
fields: Vec::with_capacity(len),
|
||||
error: PhantomData,
|
||||
})
|
||||
@ -786,7 +786,7 @@ mod content {
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
|
||||
let value = try!(value.serialize(ContentSerializer::<E>::new()));
|
||||
self.elements.push(value);
|
||||
Ok(())
|
||||
}
|
||||
@ -812,7 +812,7 @@ mod content {
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
|
||||
let value = try!(value.serialize(ContentSerializer::<E>::new()));
|
||||
self.elements.push(value);
|
||||
Ok(())
|
||||
}
|
||||
@ -839,7 +839,7 @@ mod content {
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
|
||||
let value = try!(value.serialize(ContentSerializer::<E>::new()));
|
||||
self.fields.push(value);
|
||||
Ok(())
|
||||
}
|
||||
@ -868,7 +868,7 @@ mod content {
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
|
||||
let value = try!(value.serialize(ContentSerializer::<E>::new()));
|
||||
self.fields.push(value);
|
||||
Ok(())
|
||||
}
|
||||
@ -900,7 +900,7 @@ mod content {
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
let key = tri!(key.serialize(ContentSerializer::<E>::new()));
|
||||
let key = try!(key.serialize(ContentSerializer::<E>::new()));
|
||||
self.key = Some(key);
|
||||
Ok(())
|
||||
}
|
||||
@ -913,7 +913,7 @@ mod content {
|
||||
.key
|
||||
.take()
|
||||
.expect("serialize_value called before serialize_key");
|
||||
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
|
||||
let value = try!(value.serialize(ContentSerializer::<E>::new()));
|
||||
self.entries.push((key, value));
|
||||
Ok(())
|
||||
}
|
||||
@ -927,8 +927,8 @@ mod content {
|
||||
K: Serialize,
|
||||
V: Serialize,
|
||||
{
|
||||
let key = tri!(key.serialize(ContentSerializer::<E>::new()));
|
||||
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
|
||||
let key = try!(key.serialize(ContentSerializer::<E>::new()));
|
||||
let value = try!(value.serialize(ContentSerializer::<E>::new()));
|
||||
self.entries.push((key, value));
|
||||
Ok(())
|
||||
}
|
||||
@ -951,7 +951,7 @@ mod content {
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
|
||||
let value = try!(value.serialize(ContentSerializer::<E>::new()));
|
||||
self.fields.push((key, value));
|
||||
Ok(())
|
||||
}
|
||||
@ -980,7 +980,7 @@ mod content {
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
|
||||
let value = try!(value.serialize(ContentSerializer::<E>::new()));
|
||||
self.fields.push((key, value));
|
||||
Ok(())
|
||||
}
|
||||
@ -1025,7 +1025,7 @@ where
|
||||
type SerializeTupleStruct = Impossible<Self::Ok, M::Error>;
|
||||
type SerializeMap = FlatMapSerializeMap<'a, M>;
|
||||
type SerializeStruct = FlatMapSerializeStruct<'a, M>;
|
||||
type SerializeTupleVariant = FlatMapSerializeTupleVariantAsMapValue<'a, M>;
|
||||
type SerializeTupleVariant = Impossible<Self::Ok, M::Error>;
|
||||
type SerializeStructVariant = FlatMapSerializeStructVariantAsMapValue<'a, M>;
|
||||
|
||||
fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
|
||||
@ -1133,7 +1133,7 @@ where
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
tri!(self.0.serialize_key(variant));
|
||||
try!(self.0.serialize_key(variant));
|
||||
self.0.serialize_value(value)
|
||||
}
|
||||
|
||||
@ -1157,11 +1157,10 @@ where
|
||||
self,
|
||||
_: &'static str,
|
||||
_: u32,
|
||||
variant: &'static str,
|
||||
_: &'static str,
|
||||
_: usize,
|
||||
) -> Result<Self::SerializeTupleVariant, Self::Error> {
|
||||
tri!(self.0.serialize_key(variant));
|
||||
Ok(FlatMapSerializeTupleVariantAsMapValue::new(self.0))
|
||||
Err(Self::bad_type(Unsupported::Enum))
|
||||
}
|
||||
|
||||
fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
|
||||
@ -1183,7 +1182,7 @@ where
|
||||
inner_variant: &'static str,
|
||||
_: usize,
|
||||
) -> Result<Self::SerializeStructVariant, Self::Error> {
|
||||
tri!(self.0.serialize_key(inner_variant));
|
||||
try!(self.0.serialize_key(inner_variant));
|
||||
Ok(FlatMapSerializeStructVariantAsMapValue::new(
|
||||
self.0,
|
||||
inner_variant,
|
||||
@ -1260,52 +1259,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
pub struct FlatMapSerializeTupleVariantAsMapValue<'a, M: 'a> {
|
||||
map: &'a mut M,
|
||||
fields: Vec<Content>,
|
||||
}
|
||||
|
||||
#[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<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
let value = tri!(value.serialize(ContentSerializer::<M::Error>::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,
|
||||
@ -1320,8 +1273,8 @@ where
|
||||
{
|
||||
fn new(map: &'a mut M, name: &'static str) -> FlatMapSerializeStructVariantAsMapValue<'a, M> {
|
||||
FlatMapSerializeStructVariantAsMapValue {
|
||||
map,
|
||||
name,
|
||||
map: map,
|
||||
name: name,
|
||||
fields: Vec::new(),
|
||||
}
|
||||
}
|
||||
@ -1343,43 +1296,15 @@ where
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
let value = tri!(value.serialize(ContentSerializer::<M::Error>::new()));
|
||||
let value = try!(value.serialize(ContentSerializer::<M::Error>::new()));
|
||||
self.fields.push((key, value));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn end(self) -> Result<(), Self::Error> {
|
||||
tri!(self
|
||||
try!(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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
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<T>(pub T);
|
||||
|
||||
impl<T> Display for CannotSerializeVariant<T>
|
||||
where
|
||||
T: Debug,
|
||||
{
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(formatter, "enum variant cannot be serialized: {:?}", self.0)
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::lib::*;
|
||||
use lib::*;
|
||||
|
||||
pub fn from_bounds<I>(iter: &I) -> Option<usize>
|
||||
where
|
||||
@ -8,17 +8,9 @@ where
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
pub fn cautious<Element>(hint: Option<usize>) -> usize {
|
||||
const MAX_PREALLOC_BYTES: usize = 1024 * 1024;
|
||||
|
||||
if mem::size_of::<Element>() == 0 {
|
||||
0
|
||||
} else {
|
||||
cmp::min(
|
||||
hint.unwrap_or(0),
|
||||
MAX_PREALLOC_BYTES / mem::size_of::<Element>(),
|
||||
)
|
||||
}
|
||||
#[inline]
|
||||
pub fn cautious(hint: Option<usize>) -> usize {
|
||||
cmp::min(hint.unwrap_or(0), 4096)
|
||||
}
|
||||
|
||||
fn helper(bounds: (usize, Option<usize>)) -> Option<usize> {
|
@ -1,5 +1,5 @@
|
||||
use crate::lib::*;
|
||||
use crate::ser::{Error, Impossible, Serialize, Serializer};
|
||||
use lib::*;
|
||||
use ser::{Error, Impossible, Serialize, Serializer};
|
||||
|
||||
impl Error for fmt::Error {
|
||||
fn custom<T: Display>(_msg: T) -> Self {
|
||||
@ -17,9 +17,8 @@ macro_rules! fmt_primitives {
|
||||
};
|
||||
}
|
||||
|
||||
/// ```edition2021
|
||||
/// use serde::ser::Serialize;
|
||||
/// use serde_derive::Serialize;
|
||||
/// ```edition2018
|
||||
/// use serde::Serialize;
|
||||
/// use std::fmt::{self, Display};
|
||||
///
|
||||
/// #[derive(Serialize)]
|
||||
@ -52,12 +51,10 @@ 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,
|
||||
@ -65,6 +62,13 @@ 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,
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::lib::*;
|
||||
use lib::*;
|
||||
|
||||
use crate::ser::{Error, Serialize, SerializeTuple, Serializer};
|
||||
use ser::{Error, Serialize, SerializeTuple, Serializer};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -24,17 +24,20 @@ 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 {
|
||||
@ -48,7 +51,6 @@ 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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
@ -70,8 +72,7 @@ impl<'a> Serialize for fmt::Arguments<'a> {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(any(feature = "std", not(no_core_cstr)))]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||
#[cfg(feature = "std")]
|
||||
impl Serialize for CStr {
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
@ -82,8 +83,7 @@ impl Serialize for CStr {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", all(not(no_core_cstr), feature = "alloc")))]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
#[cfg(feature = "std")]
|
||||
impl Serialize for CString {
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
@ -133,7 +133,7 @@ impl<T> Serialize for [T; 0] {
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
tri!(serializer.serialize_tuple(0)).end()
|
||||
try!(serializer.serialize_tuple(0)).end()
|
||||
}
|
||||
}
|
||||
|
||||
@ -149,9 +149,9 @@ macro_rules! array_impls {
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut seq = tri!(serializer.serialize_tuple($len));
|
||||
let mut seq = try!(serializer.serialize_tuple($len));
|
||||
for e in self {
|
||||
tri!(seq.serialize_element(e));
|
||||
try!(seq.serialize_element(e));
|
||||
}
|
||||
seq.end()
|
||||
}
|
||||
@ -182,35 +182,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(no_relaxed_trait_bounds))]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
macro_rules! seq_impl {
|
||||
(
|
||||
$(#[$attr:meta])*
|
||||
$ty:ident <T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)*>
|
||||
) => {
|
||||
$(#[$attr])*
|
||||
impl<T $(, $typaram)*> Serialize for $ty<T $(, $typaram)*>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.collect_seq(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(no_relaxed_trait_bounds)]
|
||||
macro_rules! seq_impl {
|
||||
(
|
||||
$(#[$attr:meta])*
|
||||
$ty:ident <T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)*>
|
||||
) => {
|
||||
$(#[$attr])*
|
||||
($ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)* >) => {
|
||||
impl<T $(, $typaram)*> Serialize for $ty<T $(, $typaram)*>
|
||||
where
|
||||
T: Serialize $(+ $tbound1 $(+ $tbound2)*)*,
|
||||
@ -227,41 +201,23 @@ macro_rules! seq_impl {
|
||||
}
|
||||
}
|
||||
|
||||
seq_impl! {
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
BinaryHeap<T: Ord>
|
||||
}
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
seq_impl!(BinaryHeap<T: Ord>);
|
||||
|
||||
seq_impl! {
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
BTreeSet<T: Ord>
|
||||
}
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
seq_impl!(BTreeSet<T: Ord>);
|
||||
|
||||
seq_impl! {
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||
HashSet<T: Eq + Hash, H: BuildHasher>
|
||||
}
|
||||
#[cfg(feature = "std")]
|
||||
seq_impl!(HashSet<T: Eq + Hash, H: BuildHasher>);
|
||||
|
||||
seq_impl! {
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
LinkedList<T>
|
||||
}
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
seq_impl!(LinkedList<T>);
|
||||
|
||||
seq_impl! {
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
Vec<T>
|
||||
}
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
seq_impl!(Vec<T>);
|
||||
|
||||
seq_impl! {
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
VecDeque<T>
|
||||
}
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
seq_impl!(VecDeque<T>);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -274,32 +230,16 @@ where
|
||||
S: Serializer,
|
||||
{
|
||||
use super::SerializeStruct;
|
||||
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<Idx> Serialize for RangeFrom<Idx>
|
||||
where
|
||||
Idx: Serialize,
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
use super::SerializeStruct;
|
||||
let mut state = tri!(serializer.serialize_struct("RangeFrom", 1));
|
||||
tri!(state.serialize_field("start", &self.start));
|
||||
let mut state = try!(serializer.serialize_struct("Range", 2));
|
||||
try!(state.serialize_field("start", &self.start));
|
||||
try!(state.serialize_field("end", &self.end));
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(not(no_range_inclusive))]
|
||||
impl<Idx> Serialize for RangeInclusive<Idx>
|
||||
where
|
||||
Idx: Serialize,
|
||||
@ -309,32 +249,16 @@ where
|
||||
S: Serializer,
|
||||
{
|
||||
use super::SerializeStruct;
|
||||
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<Idx> Serialize for RangeTo<Idx>
|
||||
where
|
||||
Idx: Serialize,
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
use super::SerializeStruct;
|
||||
let mut state = tri!(serializer.serialize_struct("RangeTo", 1));
|
||||
tri!(state.serialize_field("end", &self.end));
|
||||
let mut state = try!(serializer.serialize_struct("RangeInclusive", 2));
|
||||
try!(state.serialize_field("start", &self.start()));
|
||||
try!(state.serialize_field("end", &self.end()));
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(any(not(no_ops_bound), all(feature = "std", not(no_collections_bound))))]
|
||||
impl<T> Serialize for Bound<T>
|
||||
where
|
||||
T: Serialize,
|
||||
@ -368,7 +292,6 @@ impl Serialize for () {
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "unstable")))]
|
||||
impl Serialize for ! {
|
||||
fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@ -392,9 +315,9 @@ macro_rules! tuple_impls {
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut tuple = tri!(serializer.serialize_tuple($len));
|
||||
let mut tuple = try!(serializer.serialize_tuple($len));
|
||||
$(
|
||||
tri!(tuple.serialize_element(&self.$n));
|
||||
try!(tuple.serialize_element(&self.$n));
|
||||
)+
|
||||
tuple.end()
|
||||
}
|
||||
@ -424,36 +347,9 @@ tuple_impls! {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(not(no_relaxed_trait_bounds))]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
macro_rules! map_impl {
|
||||
(
|
||||
$(#[$attr:meta])*
|
||||
$ty:ident <K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)*>
|
||||
) => {
|
||||
$(#[$attr])*
|
||||
impl<K, V $(, $typaram)*> Serialize for $ty<K, V $(, $typaram)*>
|
||||
where
|
||||
K: Serialize,
|
||||
V: Serialize,
|
||||
{
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.collect_map(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(no_relaxed_trait_bounds)]
|
||||
macro_rules! map_impl {
|
||||
(
|
||||
$(#[$attr:meta])*
|
||||
$ty:ident <K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)*>
|
||||
) => {
|
||||
$(#[$attr])*
|
||||
($ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)* >) => {
|
||||
impl<K, V $(, $typaram)*> Serialize for $ty<K, V $(, $typaram)*>
|
||||
where
|
||||
K: Serialize $(+ $kbound1 $(+ $kbound2)*)*,
|
||||
@ -471,26 +367,20 @@ macro_rules! map_impl {
|
||||
}
|
||||
}
|
||||
|
||||
map_impl! {
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
BTreeMap<K: Ord, V>
|
||||
}
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
map_impl!(BTreeMap<K: Ord, V>);
|
||||
|
||||
map_impl! {
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||
HashMap<K: Eq + Hash, V, H: BuildHasher>
|
||||
}
|
||||
#[cfg(feature = "std")]
|
||||
map_impl!(HashMap<K: Eq + Hash, V, H: BuildHasher>);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
macro_rules! deref_impl {
|
||||
(
|
||||
$(#[$attr:meta])*
|
||||
$(#[doc = $doc:tt])*
|
||||
<$($desc:tt)+
|
||||
) => {
|
||||
$(#[$attr])*
|
||||
$(#[doc = $doc])*
|
||||
impl <$($desc)+ {
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
@ -503,20 +393,13 @@ macro_rules! deref_impl {
|
||||
};
|
||||
}
|
||||
|
||||
deref_impl! {
|
||||
<'a, T: ?Sized> Serialize for &'a T where T: Serialize
|
||||
}
|
||||
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 mut T where T: Serialize
|
||||
}
|
||||
|
||||
deref_impl! {
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
<T: ?Sized> Serialize for Box<T> where T: Serialize
|
||||
}
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
deref_impl!(<T: ?Sized> Serialize for Box<T> where T: Serialize);
|
||||
|
||||
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||
deref_impl! {
|
||||
/// This impl requires the [`"rc"`] Cargo feature of Serde.
|
||||
///
|
||||
@ -526,11 +409,10 @@ 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")))))]
|
||||
<T: ?Sized> Serialize for Rc<T> where T: Serialize
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||
deref_impl! {
|
||||
/// This impl requires the [`"rc"`] Cargo feature of Serde.
|
||||
///
|
||||
@ -540,16 +422,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")))))]
|
||||
<T: ?Sized> Serialize for Arc<T> where T: Serialize
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -557,10 +434,6 @@ deref_impl! {
|
||||
///
|
||||
/// [`"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<T: ?Sized> Serialize for RcWeak<T>
|
||||
where
|
||||
T: Serialize,
|
||||
@ -577,10 +450,6 @@ 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<T: ?Sized> Serialize for ArcWeak<T>
|
||||
where
|
||||
T: Serialize,
|
||||
@ -596,8 +465,9 @@ where
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
macro_rules! nonzero_integers {
|
||||
($($T:ident,)+) => {
|
||||
( $( $T: ident, )+ ) => {
|
||||
$(
|
||||
#[cfg(not(no_num_nonzero))]
|
||||
impl Serialize for num::$T {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@ -615,7 +485,6 @@ nonzero_integers! {
|
||||
NonZeroU16,
|
||||
NonZeroU32,
|
||||
NonZeroU64,
|
||||
NonZeroU128,
|
||||
NonZeroUsize,
|
||||
}
|
||||
|
||||
@ -625,10 +494,22 @@ 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<T> Serialize for Cell<T>
|
||||
where
|
||||
T: Serialize + Copy,
|
||||
@ -641,7 +522,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Serialize for RefCell<T>
|
||||
impl<T> Serialize for RefCell<T>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
@ -657,8 +538,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||
impl<T: ?Sized> Serialize for Mutex<T>
|
||||
impl<T> Serialize for Mutex<T>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
@ -674,8 +554,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||
impl<T: ?Sized> Serialize for RwLock<T>
|
||||
impl<T> Serialize for RwLock<T>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
@ -712,15 +591,16 @@ where
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(any(feature = "std", not(no_core_duration)))]
|
||||
impl Serialize for Duration {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
use super::SerializeStruct;
|
||||
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()));
|
||||
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()));
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
@ -728,20 +608,18 @@ impl Serialize for Duration {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||
impl Serialize for SystemTime {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
use super::SerializeStruct;
|
||||
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()));
|
||||
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()));
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
@ -773,7 +651,6 @@ macro_rules! serialize_display_bounded_length {
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||
impl Serialize for net::IpAddr {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@ -798,7 +675,7 @@ impl Serialize for net::IpAddr {
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
const DEC_DIGITS_LUT: &[u8] = b"\
|
||||
const DEC_DIGITS_LUT: &'static [u8] = b"\
|
||||
0001020304050607080910111213141516171819\
|
||||
2021222324252627282930313233343536373839\
|
||||
4041424344454647484950515253545556575859\
|
||||
@ -844,7 +721,6 @@ fn test_format_u8() {
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||
impl Serialize for net::Ipv4Addr {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@ -859,9 +735,8 @@ impl Serialize for net::Ipv4Addr {
|
||||
// Skip over delimiters that we initialized buf with
|
||||
written += format_u8(*oct, &mut buf[written + 1..]) + 1;
|
||||
}
|
||||
// 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)
|
||||
// We've only written ASCII bytes to the buffer, so it is valid UTF-8
|
||||
serializer.serialize_str(unsafe { str::from_utf8_unchecked(&buf[..written]) })
|
||||
} else {
|
||||
self.octets().serialize(serializer)
|
||||
}
|
||||
@ -869,7 +744,6 @@ impl Serialize for net::Ipv4Addr {
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||
impl Serialize for net::Ipv6Addr {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@ -886,7 +760,6 @@ impl Serialize for net::Ipv6Addr {
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||
impl Serialize for net::SocketAddr {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@ -911,7 +784,6 @@ impl Serialize for net::SocketAddr {
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||
impl Serialize for net::SocketAddrV4 {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@ -928,7 +800,6 @@ impl Serialize for net::SocketAddrV4 {
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||
impl Serialize for net::SocketAddrV6 {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@ -950,7 +821,6 @@ impl Serialize for net::SocketAddrV6 {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||
impl Serialize for Path {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@ -964,7 +834,6 @@ impl Serialize for Path {
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||
impl Serialize for PathBuf {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@ -975,7 +844,6 @@ 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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
@ -998,7 +866,6 @@ 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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@ -1023,6 +890,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(no_core_reverse))]
|
||||
impl<T> Serialize for Reverse<T>
|
||||
where
|
||||
T: Serialize,
|
||||
@ -1040,17 +908,15 @@ where
|
||||
|
||||
#[cfg(all(feature = "std", not(no_std_atomic)))]
|
||||
macro_rules! atomic_impl {
|
||||
($($ty:ident $size:expr)*) => {
|
||||
($($ty:ident)*) => {
|
||||
$(
|
||||
#[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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
// Matches the atomic ordering used in libcore for the Debug impl
|
||||
self.load(Ordering::Relaxed).serialize(serializer)
|
||||
self.load(Ordering::SeqCst).serialize(serializer)
|
||||
}
|
||||
}
|
||||
)*
|
||||
@ -1059,19 +925,12 @@ macro_rules! atomic_impl {
|
||||
|
||||
#[cfg(all(feature = "std", not(no_std_atomic)))]
|
||||
atomic_impl! {
|
||||
AtomicBool "8"
|
||||
AtomicI8 "8"
|
||||
AtomicI16 "16"
|
||||
AtomicI32 "32"
|
||||
AtomicIsize "ptr"
|
||||
AtomicU8 "8"
|
||||
AtomicU16 "16"
|
||||
AtomicU32 "32"
|
||||
AtomicUsize "ptr"
|
||||
AtomicBool
|
||||
AtomicI8 AtomicI16 AtomicI32 AtomicIsize
|
||||
AtomicU8 AtomicU16 AtomicU32 AtomicUsize
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "std", not(no_std_atomic64)))]
|
||||
atomic_impl! {
|
||||
AtomicI64 "64"
|
||||
AtomicU64 "64"
|
||||
AtomicI64 AtomicU64
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
//! This module contains `Impossible` serializer and its implementations.
|
||||
|
||||
use crate::lib::*;
|
||||
use lib::*;
|
||||
|
||||
use crate::ser::{
|
||||
use ser::{
|
||||
self, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
|
||||
SerializeTuple, SerializeTupleStruct, SerializeTupleVariant,
|
||||
};
|
||||
@ -15,7 +15,7 @@ use crate::ser::{
|
||||
/// [`SerializeTuple`], [`SerializeTupleStruct`], [`SerializeTupleVariant`],
|
||||
/// [`SerializeMap`], [`SerializeStruct`], and [`SerializeStructVariant`].
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use serde::ser::{Serializer, Impossible};
|
||||
/// # use serde::__private::doc::Error;
|
||||
/// #
|
||||
|
@ -30,7 +30,7 @@
|
||||
//! # The Serializer trait
|
||||
//!
|
||||
//! [`Serializer`] implementations are provided by third-party crates, for
|
||||
//! example [`serde_json`], [`serde_yaml`] and [`postcard`].
|
||||
//! example [`serde_json`], [`serde_yaml`] and [`bincode`].
|
||||
//!
|
||||
//! A partial list of well-maintained formats is given on the [Serde
|
||||
//! website][data formats].
|
||||
@ -61,8 +61,8 @@
|
||||
//! - RefCell\<T\>
|
||||
//! - Mutex\<T\>
|
||||
//! - RwLock\<T\>
|
||||
//! - Rc\<T\> *(if* features = \["rc"\] *is enabled)*
|
||||
//! - Arc\<T\> *(if* features = \["rc"\] *is enabled)*
|
||||
//! - Rc\<T\> *(if* features = ["rc"] *is enabled)*
|
||||
//! - Arc\<T\> *(if* features = ["rc"] *is enabled)*
|
||||
//! - **Collection types**:
|
||||
//! - BTreeMap\<K, V\>
|
||||
//! - BTreeSet\<T\>
|
||||
@ -99,7 +99,7 @@
|
||||
//! [`LinkedHashMap<K, V>`]: https://docs.rs/linked-hash-map/*/linked_hash_map/struct.LinkedHashMap.html
|
||||
//! [`Serialize`]: ../trait.Serialize.html
|
||||
//! [`Serializer`]: ../trait.Serializer.html
|
||||
//! [`postcard`]: https://github.com/jamesmunns/postcard
|
||||
//! [`bincode`]: https://github.com/servo/bincode
|
||||
//! [`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 crate::lib::*;
|
||||
use lib::*;
|
||||
|
||||
mod fmt;
|
||||
mod impls;
|
||||
@ -115,15 +115,12 @@ 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;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -149,7 +146,7 @@ macro_rules! declare_error_trait {
|
||||
/// For example, a filesystem [`Path`] may refuse to serialize
|
||||
/// itself if it contains invalid UTF-8 data.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # struct Path;
|
||||
/// #
|
||||
/// # impl Path {
|
||||
@ -194,8 +191,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][crate::ser]. All of
|
||||
/// these can be serialized using Serde out of the box.
|
||||
/// standard library types. The complete list is [here][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
|
||||
@ -215,13 +212,14 @@ 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.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// use serde::ser::{Serialize, SerializeStruct, Serializer};
|
||||
///
|
||||
/// struct Person {
|
||||
@ -316,7 +314,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 Postcard. This is not a requirement of the `Serializer` trait, and
|
||||
/// JSON or Bincode. 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
|
||||
@ -388,7 +386,7 @@ pub trait Serializer: Sized {
|
||||
|
||||
/// Serialize a `bool` value.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use serde::Serializer;
|
||||
/// #
|
||||
/// # serde::__private_serialize!();
|
||||
@ -410,7 +408,7 @@ pub trait Serializer: Sized {
|
||||
/// reasonable implementation would be to cast the value to `i64` and
|
||||
/// forward to `serialize_i64`.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use serde::Serializer;
|
||||
/// #
|
||||
/// # serde::__private_serialize!();
|
||||
@ -432,7 +430,7 @@ pub trait Serializer: Sized {
|
||||
/// reasonable implementation would be to cast the value to `i64` and
|
||||
/// forward to `serialize_i64`.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use serde::Serializer;
|
||||
/// #
|
||||
/// # serde::__private_serialize!();
|
||||
@ -454,7 +452,7 @@ pub trait Serializer: Sized {
|
||||
/// reasonable implementation would be to cast the value to `i64` and
|
||||
/// forward to `serialize_i64`.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use serde::Serializer;
|
||||
/// #
|
||||
/// # serde::__private_serialize!();
|
||||
@ -472,7 +470,7 @@ pub trait Serializer: Sized {
|
||||
|
||||
/// Serialize an `i64` value.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use serde::Serializer;
|
||||
/// #
|
||||
/// # serde::__private_serialize!();
|
||||
@ -488,27 +486,30 @@ pub trait Serializer: Sized {
|
||||
/// ```
|
||||
fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error>;
|
||||
|
||||
/// Serialize an `i128` value.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// # use serde::Serializer;
|
||||
/// #
|
||||
/// # serde::__private_serialize!();
|
||||
/// #
|
||||
/// impl Serialize for i128 {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// serializer.serialize_i128(*self)
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// The default behavior unconditionally returns an error.
|
||||
fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> {
|
||||
let _ = v;
|
||||
Err(Error::custom("i128 is not supported"))
|
||||
serde_if_integer128! {
|
||||
/// Serialize an `i128` value.
|
||||
///
|
||||
/// ```edition2018
|
||||
/// # use serde::Serializer;
|
||||
/// #
|
||||
/// # serde::__private_serialize!();
|
||||
/// #
|
||||
/// impl Serialize for i128 {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// 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<Self::Ok, Self::Error> {
|
||||
let _ = v;
|
||||
Err(Error::custom("i128 is not supported"))
|
||||
}
|
||||
}
|
||||
|
||||
/// Serialize a `u8` value.
|
||||
@ -517,7 +518,7 @@ pub trait Serializer: Sized {
|
||||
/// reasonable implementation would be to cast the value to `u64` and
|
||||
/// forward to `serialize_u64`.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use serde::Serializer;
|
||||
/// #
|
||||
/// # serde::__private_serialize!();
|
||||
@ -539,7 +540,7 @@ pub trait Serializer: Sized {
|
||||
/// reasonable implementation would be to cast the value to `u64` and
|
||||
/// forward to `serialize_u64`.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use serde::Serializer;
|
||||
/// #
|
||||
/// # serde::__private_serialize!();
|
||||
@ -561,7 +562,7 @@ pub trait Serializer: Sized {
|
||||
/// reasonable implementation would be to cast the value to `u64` and
|
||||
/// forward to `serialize_u64`.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use serde::Serializer;
|
||||
/// #
|
||||
/// # serde::__private_serialize!();
|
||||
@ -579,7 +580,7 @@ pub trait Serializer: Sized {
|
||||
|
||||
/// Serialize a `u64` value.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use serde::Serializer;
|
||||
/// #
|
||||
/// # serde::__private_serialize!();
|
||||
@ -595,27 +596,30 @@ pub trait Serializer: Sized {
|
||||
/// ```
|
||||
fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error>;
|
||||
|
||||
/// Serialize a `u128` value.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// # use serde::Serializer;
|
||||
/// #
|
||||
/// # serde::__private_serialize!();
|
||||
/// #
|
||||
/// impl Serialize for u128 {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// serializer.serialize_u128(*self)
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// The default behavior unconditionally returns an error.
|
||||
fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
|
||||
let _ = v;
|
||||
Err(Error::custom("u128 is not supported"))
|
||||
serde_if_integer128! {
|
||||
/// Serialize a `u128` value.
|
||||
///
|
||||
/// ```edition2018
|
||||
/// # use serde::Serializer;
|
||||
/// #
|
||||
/// # serde::__private_serialize!();
|
||||
/// #
|
||||
/// impl Serialize for u128 {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// 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<Self::Ok, Self::Error> {
|
||||
let _ = v;
|
||||
Err(Error::custom("u128 is not supported"))
|
||||
}
|
||||
}
|
||||
|
||||
/// Serialize an `f32` value.
|
||||
@ -624,7 +628,7 @@ pub trait Serializer: Sized {
|
||||
/// reasonable implementation would be to cast the value to `f64` and
|
||||
/// forward to `serialize_f64`.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use serde::Serializer;
|
||||
/// #
|
||||
/// # serde::__private_serialize!();
|
||||
@ -642,7 +646,7 @@ pub trait Serializer: Sized {
|
||||
|
||||
/// Serialize an `f64` value.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use serde::Serializer;
|
||||
/// #
|
||||
/// # serde::__private_serialize!();
|
||||
@ -663,7 +667,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`.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use serde::Serializer;
|
||||
/// #
|
||||
/// # serde::__private_serialize!();
|
||||
@ -681,7 +685,7 @@ pub trait Serializer: Sized {
|
||||
|
||||
/// Serialize a `&str`.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use serde::Serializer;
|
||||
/// #
|
||||
/// # serde::__private_serialize!();
|
||||
@ -705,7 +709,7 @@ pub trait Serializer: Sized {
|
||||
/// `serialize_seq`. If forwarded, the implementation looks usually just
|
||||
/// like this:
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use serde::ser::{Serializer, SerializeSeq};
|
||||
/// # use serde::__private::doc::Error;
|
||||
/// #
|
||||
@ -734,7 +738,7 @@ pub trait Serializer: Sized {
|
||||
|
||||
/// Serialize a [`None`] value.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use serde::{Serialize, Serializer};
|
||||
/// #
|
||||
/// # enum Option<T> {
|
||||
@ -767,7 +771,7 @@ pub trait Serializer: Sized {
|
||||
|
||||
/// Serialize a [`Some(T)`] value.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use serde::{Serialize, Serializer};
|
||||
/// #
|
||||
/// # enum Option<T> {
|
||||
@ -802,7 +806,7 @@ pub trait Serializer: Sized {
|
||||
|
||||
/// Serialize a `()` value.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use serde::Serializer;
|
||||
/// #
|
||||
/// # serde::__private_serialize!();
|
||||
@ -822,7 +826,7 @@ pub trait Serializer: Sized {
|
||||
///
|
||||
/// A reasonable implementation would be to forward to `serialize_unit`.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// use serde::{Serialize, Serializer};
|
||||
///
|
||||
/// struct Nothing;
|
||||
@ -844,7 +848,7 @@ pub trait Serializer: Sized {
|
||||
/// this variant within the enum, and the `variant` is the name of the
|
||||
/// variant.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// use serde::{Serialize, Serializer};
|
||||
///
|
||||
/// enum E {
|
||||
@ -877,7 +881,7 @@ pub trait Serializer: Sized {
|
||||
/// wrappers around the data they contain. A reasonable implementation would
|
||||
/// be to forward to `value.serialize(self)`.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// use serde::{Serialize, Serializer};
|
||||
///
|
||||
/// struct Millimeters(u8);
|
||||
@ -905,7 +909,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.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// use serde::{Serialize, Serializer};
|
||||
///
|
||||
/// enum E {
|
||||
@ -943,7 +947,7 @@ pub trait Serializer: Sized {
|
||||
/// not be computable before the sequence is iterated. Some serializers only
|
||||
/// support sequences whose length is known up front.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use std::marker::PhantomData;
|
||||
/// #
|
||||
/// # struct Vec<T>(PhantomData<T>);
|
||||
@ -956,14 +960,14 @@ pub trait Serializer: Sized {
|
||||
/// #
|
||||
/// # impl<'a, T> IntoIterator for &'a Vec<T> {
|
||||
/// # type Item = &'a T;
|
||||
/// # type IntoIter = Box<dyn Iterator<Item = &'a T>>;
|
||||
/// # type IntoIter = Box<Iterator<Item = &'a T>>;
|
||||
/// #
|
||||
/// # fn into_iter(self) -> Self::IntoIter {
|
||||
/// # unimplemented!()
|
||||
/// # }
|
||||
/// # }
|
||||
/// #
|
||||
/// use serde::ser::{Serialize, SerializeSeq, Serializer};
|
||||
/// use serde::ser::{Serialize, Serializer, SerializeSeq};
|
||||
///
|
||||
/// impl<T> Serialize for Vec<T>
|
||||
/// where
|
||||
@ -988,8 +992,8 @@ pub trait Serializer: Sized {
|
||||
/// This call must be followed by zero or more calls to `serialize_element`,
|
||||
/// then a call to `end`.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// use serde::ser::{Serialize, SerializeTuple, Serializer};
|
||||
/// ```edition2018
|
||||
/// use serde::ser::{Serialize, Serializer, SerializeTuple};
|
||||
///
|
||||
/// # mod fool {
|
||||
/// # trait Serialize {}
|
||||
@ -1018,7 +1022,7 @@ pub trait Serializer: Sized {
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// use serde::ser::{Serialize, SerializeTuple, Serializer};
|
||||
///
|
||||
/// const VRAM_SIZE: usize = 386;
|
||||
@ -1046,7 +1050,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.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// use serde::ser::{Serialize, SerializeTupleStruct, Serializer};
|
||||
///
|
||||
/// struct Rgb(u8, u8, u8);
|
||||
@ -1078,7 +1082,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.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// use serde::ser::{Serialize, SerializeTupleVariant, Serializer};
|
||||
///
|
||||
/// enum E {
|
||||
@ -1124,7 +1128,7 @@ pub trait Serializer: Sized {
|
||||
/// be computable before the map is iterated. Some serializers only support
|
||||
/// maps whose length is known up front.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use std::marker::PhantomData;
|
||||
/// #
|
||||
/// # struct HashMap<K, V>(PhantomData<K>, PhantomData<V>);
|
||||
@ -1137,14 +1141,14 @@ pub trait Serializer: Sized {
|
||||
/// #
|
||||
/// # impl<'a, K, V> IntoIterator for &'a HashMap<K, V> {
|
||||
/// # type Item = (&'a K, &'a V);
|
||||
/// # type IntoIter = Box<dyn Iterator<Item = (&'a K, &'a V)>>;
|
||||
/// # type IntoIter = Box<Iterator<Item = (&'a K, &'a V)>>;
|
||||
/// #
|
||||
/// # fn into_iter(self) -> Self::IntoIter {
|
||||
/// # unimplemented!()
|
||||
/// # }
|
||||
/// # }
|
||||
/// #
|
||||
/// use serde::ser::{Serialize, SerializeMap, Serializer};
|
||||
/// use serde::ser::{Serialize, Serializer, SerializeMap};
|
||||
///
|
||||
/// impl<K, V> Serialize for HashMap<K, V>
|
||||
/// where
|
||||
@ -1172,7 +1176,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.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// use serde::ser::{Serialize, SerializeStruct, Serializer};
|
||||
///
|
||||
/// struct Rgb {
|
||||
@ -1208,7 +1212,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.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// use serde::ser::{Serialize, SerializeStructVariant, Serializer};
|
||||
///
|
||||
/// enum E {
|
||||
@ -1250,7 +1254,7 @@ pub trait Serializer: Sized {
|
||||
/// using [`serialize_seq`]. Implementors should not need to override this
|
||||
/// method.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// use serde::{Serialize, Serializer};
|
||||
///
|
||||
/// struct SecretlyOneHigher {
|
||||
@ -1273,9 +1277,22 @@ pub trait Serializer: Sized {
|
||||
I: IntoIterator,
|
||||
<I as IntoIterator>::Item: Serialize,
|
||||
{
|
||||
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)));
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
serializer.end()
|
||||
}
|
||||
|
||||
@ -1285,7 +1302,7 @@ pub trait Serializer: Sized {
|
||||
/// using [`serialize_map`]. Implementors should not need to override this
|
||||
/// method.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// use serde::{Serialize, Serializer};
|
||||
/// use std::collections::BTreeSet;
|
||||
///
|
||||
@ -1311,9 +1328,22 @@ pub trait Serializer: Sized {
|
||||
V: Serialize,
|
||||
I: IntoIterator<Item = (K, V)>,
|
||||
{
|
||||
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)));
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
serializer.end()
|
||||
}
|
||||
|
||||
@ -1323,7 +1353,7 @@ pub trait Serializer: Sized {
|
||||
/// delegates to [`serialize_str`]. Serializers are encouraged to provide a
|
||||
/// more efficient implementation if possible.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # struct DateTime;
|
||||
/// #
|
||||
/// # impl DateTime {
|
||||
@ -1338,7 +1368,9 @@ 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()))
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
@ -1359,7 +1391,7 @@ pub trait Serializer: Sized {
|
||||
/// of this method. If no more sensible behavior is possible, the
|
||||
/// implementation is expected to return an error.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # struct DateTime;
|
||||
/// #
|
||||
/// # impl DateTime {
|
||||
@ -1374,7 +1406,9 @@ 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()))
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
@ -1389,10 +1423,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 Postcard will prefer the
|
||||
/// human-readable one and binary formats like Bincode will prefer the
|
||||
/// compact one.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use std::fmt::{self, Display};
|
||||
/// #
|
||||
/// # struct Timestamp;
|
||||
@ -1441,7 +1475,7 @@ pub trait Serializer: Sized {
|
||||
///
|
||||
/// # Example use
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use std::marker::PhantomData;
|
||||
/// #
|
||||
/// # struct Vec<T>(PhantomData<T>);
|
||||
@ -1454,13 +1488,13 @@ pub trait Serializer: Sized {
|
||||
/// #
|
||||
/// # impl<'a, T> IntoIterator for &'a Vec<T> {
|
||||
/// # type Item = &'a T;
|
||||
/// # type IntoIter = Box<dyn Iterator<Item = &'a T>>;
|
||||
/// # type IntoIter = Box<Iterator<Item = &'a T>>;
|
||||
/// # fn into_iter(self) -> Self::IntoIter {
|
||||
/// # unimplemented!()
|
||||
/// # }
|
||||
/// # }
|
||||
/// #
|
||||
/// use serde::ser::{Serialize, SerializeSeq, Serializer};
|
||||
/// use serde::ser::{Serialize, Serializer, SerializeSeq};
|
||||
///
|
||||
/// impl<T> Serialize for Vec<T>
|
||||
/// where
|
||||
@ -1505,8 +1539,8 @@ pub trait SerializeSeq {
|
||||
///
|
||||
/// # Example use
|
||||
///
|
||||
/// ```edition2021
|
||||
/// use serde::ser::{Serialize, SerializeTuple, Serializer};
|
||||
/// ```edition2018
|
||||
/// use serde::ser::{Serialize, Serializer, SerializeTuple};
|
||||
///
|
||||
/// # mod fool {
|
||||
/// # trait Serialize {}
|
||||
@ -1535,7 +1569,7 @@ pub trait SerializeSeq {
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use std::marker::PhantomData;
|
||||
/// #
|
||||
/// # struct Array<T>(PhantomData<T>);
|
||||
@ -1548,13 +1582,13 @@ pub trait SerializeSeq {
|
||||
/// #
|
||||
/// # impl<'a, T> IntoIterator for &'a Array<T> {
|
||||
/// # type Item = &'a T;
|
||||
/// # type IntoIter = Box<dyn Iterator<Item = &'a T>>;
|
||||
/// # type IntoIter = Box<Iterator<Item = &'a T>>;
|
||||
/// # fn into_iter(self) -> Self::IntoIter {
|
||||
/// # unimplemented!()
|
||||
/// # }
|
||||
/// # }
|
||||
/// #
|
||||
/// use serde::ser::{Serialize, SerializeTuple, Serializer};
|
||||
/// use serde::ser::{Serialize, Serializer, SerializeTuple};
|
||||
///
|
||||
/// # mod fool {
|
||||
/// # trait Serialize {}
|
||||
@ -1605,7 +1639,7 @@ pub trait SerializeTuple {
|
||||
///
|
||||
/// # Example use
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// use serde::ser::{Serialize, SerializeTupleStruct, Serializer};
|
||||
///
|
||||
/// struct Rgb(u8, u8, u8);
|
||||
@ -1650,7 +1684,7 @@ pub trait SerializeTupleStruct {
|
||||
///
|
||||
/// # Example use
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// use serde::ser::{Serialize, SerializeTupleVariant, Serializer};
|
||||
///
|
||||
/// enum E {
|
||||
@ -1708,7 +1742,7 @@ pub trait SerializeTupleVariant {
|
||||
///
|
||||
/// # Example use
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// # use std::marker::PhantomData;
|
||||
/// #
|
||||
/// # struct HashMap<K, V>(PhantomData<K>, PhantomData<V>);
|
||||
@ -1721,14 +1755,14 @@ pub trait SerializeTupleVariant {
|
||||
/// #
|
||||
/// # impl<'a, K, V> IntoIterator for &'a HashMap<K, V> {
|
||||
/// # type Item = (&'a K, &'a V);
|
||||
/// # type IntoIter = Box<dyn Iterator<Item = (&'a K, &'a V)>>;
|
||||
/// # type IntoIter = Box<Iterator<Item = (&'a K, &'a V)>>;
|
||||
/// #
|
||||
/// # fn into_iter(self) -> Self::IntoIter {
|
||||
/// # unimplemented!()
|
||||
/// # }
|
||||
/// # }
|
||||
/// #
|
||||
/// use serde::ser::{Serialize, SerializeMap, Serializer};
|
||||
/// use serde::ser::{Serialize, Serializer, SerializeMap};
|
||||
///
|
||||
/// impl<K, V> Serialize for HashMap<K, V>
|
||||
/// where
|
||||
@ -1807,7 +1841,7 @@ pub trait SerializeMap {
|
||||
K: Serialize,
|
||||
V: Serialize,
|
||||
{
|
||||
tri!(self.serialize_key(key));
|
||||
try!(self.serialize_key(key));
|
||||
self.serialize_value(value)
|
||||
}
|
||||
|
||||
@ -1819,7 +1853,7 @@ pub trait SerializeMap {
|
||||
///
|
||||
/// # Example use
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// use serde::ser::{Serialize, SerializeStruct, Serializer};
|
||||
///
|
||||
/// struct Rgb {
|
||||
@ -1879,7 +1913,7 @@ pub trait SerializeStruct {
|
||||
///
|
||||
/// # Example use
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// use serde::ser::{Serialize, SerializeStructVariant, Serializer};
|
||||
///
|
||||
/// enum E {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::lib::{Debug, Display};
|
||||
use 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 crate::lib::{Debug, Display};
|
||||
/// generally provide their error types with a `std::error::Error` impl
|
||||
/// directly:
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// #[derive(Debug)]
|
||||
/// struct MySerError {...}
|
||||
///
|
||||
@ -29,7 +29,7 @@ use crate::lib::{Debug, Display};
|
||||
/// std = ["serde/std"]
|
||||
/// ```
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// #[cfg(feature = "std")]
|
||||
/// impl std::error::Error for MySerError {}
|
||||
/// ```
|
||||
@ -37,7 +37,7 @@ use crate::lib::{Debug, Display};
|
||||
/// ... or else provide the std Error impl unconditionally via Serde's
|
||||
/// re-export:
|
||||
///
|
||||
/// ```edition2021
|
||||
/// ```edition2018
|
||||
/// impl serde::ser::StdError for MySerError {}
|
||||
/// ```
|
||||
pub trait Error: Debug + Display {
|
||||
|
@ -1,16 +1,16 @@
|
||||
[package]
|
||||
name = "serde_derive"
|
||||
version = "1.0.197"
|
||||
version = "1.0.136" # remember to update html_root_url
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
categories = ["no-std", "no-std::no-alloc"]
|
||||
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
||||
documentation = "https://serde.rs/derive.html"
|
||||
homepage = "https://serde.rs"
|
||||
keywords = ["serde", "serialization", "no_std", "derive"]
|
||||
rust-version = "1.31"
|
||||
license = "MIT OR Apache-2.0"
|
||||
readme = "crates-io.md"
|
||||
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
||||
homepage = "https://serde.rs"
|
||||
repository = "https://github.com/serde-rs/serde"
|
||||
rust-version = "1.56"
|
||||
documentation = "https://serde.rs/derive.html"
|
||||
keywords = ["serde", "serialization", "no_std"]
|
||||
readme = "crates-io.md"
|
||||
include = ["build.rs", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
|
||||
|
||||
[features]
|
||||
default = []
|
||||
@ -21,13 +21,12 @@ name = "serde_derive"
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = { workspace = true, features = ["proc-macro"] }
|
||||
quote = { workspace = true, features = ["proc-macro"] }
|
||||
syn = { workspace = true, features = ["clone-impls", "derive", "parsing", "printing", "proc-macro"] }
|
||||
proc-macro2 = "1.0"
|
||||
quote = "1.0"
|
||||
syn = "1.0.60"
|
||||
|
||||
[dev-dependencies]
|
||||
serde = { version = "1", path = "../serde" }
|
||||
serde = { version = "1.0", path = "../serde" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
rustdoc-args = ["--generate-link-to-definition"]
|
||||
|
36
serde_derive/build.rs
Normal file
36
serde_derive/build.rs
Normal file
@ -0,0 +1,36 @@
|
||||
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<u32> {
|
||||
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()
|
||||
}
|
@ -1,9 +1,12 @@
|
||||
use crate::internals::ast::{Container, Data};
|
||||
use crate::internals::{attr, ungroup};
|
||||
use proc_macro2::Span;
|
||||
use std::collections::HashSet;
|
||||
|
||||
use syn;
|
||||
use syn::punctuated::{Pair, Punctuated};
|
||||
use syn::Token;
|
||||
|
||||
use internals::ast::{Container, Data};
|
||||
use internals::{attr, ungroup};
|
||||
|
||||
use proc_macro2::Span;
|
||||
|
||||
// Remove the default from every type parameter because in the generated impls
|
||||
// they look like associated types: "error: associated type bindings are not
|
||||
@ -144,7 +147,6 @@ 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 {
|
||||
@ -182,6 +184,9 @@ pub fn with_bound(
|
||||
|
||||
syn::Type::Infer(_) | syn::Type::Never(_) | syn::Type::Verbatim(_) => {}
|
||||
|
||||
#[cfg(test)]
|
||||
syn::Type::__TestExhaustive(_) => unimplemented!(),
|
||||
#[cfg(not(test))]
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@ -196,14 +201,11 @@ 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::AssocType(arg) => self.visit_type(&arg.ty),
|
||||
syn::GenericArgument::Binding(arg) => self.visit_type(&arg.ty),
|
||||
syn::GenericArgument::Lifetime(_)
|
||||
| syn::GenericArgument::Const(_)
|
||||
| syn::GenericArgument::AssocConst(_)
|
||||
| syn::GenericArgument::Constraint(_) => {}
|
||||
_ => {}
|
||||
| syn::GenericArgument::Constraint(_)
|
||||
| syn::GenericArgument::Const(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -225,10 +227,8 @@ 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::Verbatim(_) => {}
|
||||
_ => {}
|
||||
syn::TypeParamBound::Lifetime(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -253,7 +253,7 @@ pub fn with_bound(
|
||||
};
|
||||
match &cont.data {
|
||||
Data::Enum(variants) => {
|
||||
for variant in variants {
|
||||
for variant in variants.iter() {
|
||||
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::LifetimeParam {
|
||||
let def = syn::LifetimeDef {
|
||||
attrs: Vec::new(),
|
||||
lifetime: bound.clone(),
|
||||
colon_token: None,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,23 @@
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
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))
|
||||
};
|
||||
|
||||
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;
|
||||
@ -15,9 +31,18 @@ pub fn wrap_in_const(serde_path: Option<&syn::Path>, code: TokenStream) -> Token
|
||||
quote! {
|
||||
#[doc(hidden)]
|
||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||
const _: () = {
|
||||
const #dummy_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()
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::ToTokens;
|
||||
use syn::{token, Token};
|
||||
use syn::token;
|
||||
|
||||
pub enum Fragment {
|
||||
/// Tokens that can be used as an expression.
|
||||
|
@ -1,8 +1,10 @@
|
||||
//! A Serde ast, parsed from the Syn ast and ready to generate Rust code.
|
||||
|
||||
use crate::internals::{attr, check, Ctxt, Derive};
|
||||
use internals::attr;
|
||||
use internals::check;
|
||||
use internals::{Ctxt, Derive};
|
||||
use syn;
|
||||
use syn::punctuated::Punctuated;
|
||||
use syn::Token;
|
||||
|
||||
/// A source data structure annotated with `#[derive(Serialize)]` and/or `#[derive(Deserialize)]`,
|
||||
/// parsed into an internal representation.
|
||||
@ -86,12 +88,9 @@ impl<'a> Container<'a> {
|
||||
if field.attrs.flatten() {
|
||||
has_flatten = true;
|
||||
}
|
||||
field.attrs.rename_by_rules(
|
||||
variant
|
||||
.attrs
|
||||
.rename_all_rules()
|
||||
.or(attrs.rename_all_fields_rules()),
|
||||
);
|
||||
field
|
||||
.attrs
|
||||
.rename_by_rules(variant.attrs.rename_all_rules());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -122,7 +121,7 @@ impl<'a> Container<'a> {
|
||||
}
|
||||
|
||||
impl<'a> Data<'a> {
|
||||
pub fn all_fields(&'a self) -> Box<dyn Iterator<Item = &'a Field<'a>> + 'a> {
|
||||
pub fn all_fields(&'a self) -> Box<Iterator<Item = &'a Field<'a>> + 'a> {
|
||||
match self {
|
||||
Data::Enum(variants) => {
|
||||
Box::new(variants.iter().flat_map(|variant| variant.fields.iter()))
|
||||
@ -141,7 +140,7 @@ fn enum_from_ast<'a>(
|
||||
variants: &'a Punctuated<syn::Variant, Token![,]>,
|
||||
container_default: &attr::Default,
|
||||
) -> Vec<Variant<'a>> {
|
||||
let variants: Vec<Variant> = variants
|
||||
variants
|
||||
.iter()
|
||||
.map(|variant| {
|
||||
let attrs = attr::Variant::from_ast(cx, variant);
|
||||
@ -155,20 +154,7 @@ fn enum_from_ast<'a>(
|
||||
original: variant,
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let index_of_last_tagged_variant = variants
|
||||
.iter()
|
||||
.rposition(|variant| !variant.attrs.untagged());
|
||||
if let Some(index_of_last_tagged_variant) = index_of_last_tagged_variant {
|
||||
for variant in &variants[..index_of_last_tagged_variant] {
|
||||
if variant.attrs.untagged() {
|
||||
cx.error_spanned_by(&variant.ident, "all variants with the #[serde(untagged)] attribute must be placed at the end of the enum");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
variants
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn struct_from_ast<'a>(
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,9 +1,14 @@
|
||||
//! Code to convert the Rust-styled field/variant (e.g. `my_field`, `MyType`) to the
|
||||
//! case of the source (e.g. `my-field`, `MY_FIELD`).
|
||||
|
||||
use self::RenameRule::*;
|
||||
// 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::*;
|
||||
|
||||
/// The different possible ways to change case of fields in a struct, or variants in an enum.
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub enum RenameRule {
|
||||
@ -54,8 +59,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(),
|
||||
@ -79,8 +84,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 => {
|
||||
@ -107,14 +112,6 @@ 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> {
|
||||
|
@ -1,13 +1,11 @@
|
||||
use crate::internals::ast::{Container, Data, Field, Style};
|
||||
use crate::internals::attr::{Default, Identifier, TagType};
|
||||
use crate::internals::{ungroup, Ctxt, Derive};
|
||||
use internals::ast::{Container, Data, Field, Style};
|
||||
use internals::attr::{Identifier, TagType};
|
||||
use internals::{ungroup, Ctxt, Derive};
|
||||
use syn::{Member, Type};
|
||||
|
||||
// Cross-cutting checks that require looking at more than a single attrs object.
|
||||
// Simpler checks should happen when parsing and building the attrs.
|
||||
/// Cross-cutting checks that require looking at more than a single attrs
|
||||
/// object. Simpler checks should happen when parsing and building the attrs.
|
||||
pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) {
|
||||
check_default_on_tuple(cx, cont);
|
||||
check_remote_generic(cx, cont);
|
||||
check_getter(cx, cont);
|
||||
check_flatten(cx, cont);
|
||||
check_identifier(cx, cont);
|
||||
@ -18,63 +16,8 @@ pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) {
|
||||
check_from_and_try_from(cx, cont);
|
||||
}
|
||||
|
||||
// If some field of a tuple struct is marked #[serde(default)] then all fields
|
||||
// after it must also be marked with that attribute, or the struct must have a
|
||||
// container-level serde(default) attribute. A field's default value is only
|
||||
// used for tuple fields if the sequence is exhausted at that point; that means
|
||||
// all subsequent fields will fail to deserialize if they don't have their own
|
||||
// default.
|
||||
fn check_default_on_tuple(cx: &Ctxt, cont: &Container) {
|
||||
if let Default::None = cont.attrs.default() {
|
||||
if let Data::Struct(Style::Tuple, fields) = &cont.data {
|
||||
let mut first_default_index = None;
|
||||
for (i, field) in fields.iter().enumerate() {
|
||||
// Skipped fields automatically get the #[serde(default)]
|
||||
// attribute. We are interested only on non-skipped fields here.
|
||||
if field.attrs.skip_deserializing() {
|
||||
continue;
|
||||
}
|
||||
if let Default::None = field.attrs.default() {
|
||||
if let Some(first) = first_default_index {
|
||||
cx.error_spanned_by(
|
||||
field.ty,
|
||||
format!("field must have #[serde(default)] because previous field {} has #[serde(default)]", first),
|
||||
);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if first_default_index.is_none() {
|
||||
first_default_index = Some(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remote derive definition type must have either all of the generics of the
|
||||
// remote type:
|
||||
//
|
||||
// #[serde(remote = "Generic")]
|
||||
// struct Generic<T> {…}
|
||||
//
|
||||
// or none of them, i.e. defining impls for one concrete instantiation of the
|
||||
// remote type only:
|
||||
//
|
||||
// #[serde(remote = "Generic<T>")]
|
||||
// struct ConcreteDef {…}
|
||||
//
|
||||
fn check_remote_generic(cx: &Ctxt, cont: &Container) {
|
||||
if let Some(remote) = cont.attrs.remote() {
|
||||
let local_has_generic = !cont.generics.params.is_empty();
|
||||
let remote_has_generic = !remote.segments.last().unwrap().arguments.is_none();
|
||||
if local_has_generic && remote_has_generic {
|
||||
cx.error_spanned_by(remote, "remove generic parameters from this path");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Getters are only allowed inside structs (not enums) with the `remote`
|
||||
// attribute.
|
||||
/// Getters are only allowed inside structs (not enums) with the `remote`
|
||||
/// attribute.
|
||||
fn check_getter(cx: &Ctxt, cont: &Container) {
|
||||
match cont.data {
|
||||
Data::Enum(_) => {
|
||||
@ -96,7 +39,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) => {
|
||||
@ -135,16 +78,18 @@ 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() {
|
||||
@ -221,15 +166,17 @@ 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 {
|
||||
for variant in variants.iter() {
|
||||
if variant.attrs.serialize_with().is_some() {
|
||||
if variant.attrs.skip_serializing() {
|
||||
cx.error_spanned_by(
|
||||
@ -294,9 +241,10 @@ 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,
|
||||
@ -318,14 +266,9 @@ 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() || variant.attrs.skip_serializing());
|
||||
let check_de =
|
||||
!(field.attrs.skip_deserializing() || variant.attrs.skip_deserializing());
|
||||
let check_ser = !field.attrs.skip_serializing();
|
||||
let check_de = !field.attrs.skip_deserializing();
|
||||
let name = field.attrs.name();
|
||||
let ser_name = name.serialize_name();
|
||||
|
||||
@ -347,8 +290,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),
|
||||
@ -366,7 +309,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;
|
||||
|
@ -2,6 +2,7 @@ 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.
|
||||
///
|
||||
@ -43,19 +44,12 @@ impl Ctxt {
|
||||
}
|
||||
|
||||
/// Consume this object, producing a formatted error string if there are errors.
|
||||
pub fn check(self) -> syn::Result<()> {
|
||||
let mut errors = self.errors.borrow_mut().take().unwrap().into_iter();
|
||||
|
||||
let mut combined = match errors.next() {
|
||||
Some(first) => first,
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
||||
for rest in errors {
|
||||
combined.combine(rest);
|
||||
pub fn check(self) -> Result<(), Vec<syn::Error>> {
|
||||
let errors = self.errors.borrow_mut().take().unwrap();
|
||||
match errors.len() {
|
||||
0 => Ok(()),
|
||||
_ => Err(errors),
|
||||
}
|
||||
|
||||
Err(combined)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,18 +1,19 @@
|
||||
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,
|
||||
|
@ -1,11 +1,11 @@
|
||||
use crate::internals::respan::respan;
|
||||
use internals::respan::respan;
|
||||
use proc_macro2::Span;
|
||||
use quote::ToTokens;
|
||||
use std::mem;
|
||||
use syn::punctuated::Punctuated;
|
||||
use syn::{
|
||||
parse_quote, Data, DeriveInput, Expr, ExprPath, GenericArgument, GenericParam, Generics, Macro,
|
||||
Path, PathArguments, QSelf, ReturnType, Token, Type, TypeParamBound, TypePath, WherePredicate,
|
||||
Path, PathArguments, QSelf, ReturnType, Type, TypeParamBound, TypePath, WherePredicate,
|
||||
};
|
||||
|
||||
pub fn replace_receiver(input: &mut DeriveInput) {
|
||||
@ -107,7 +107,6 @@ 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);
|
||||
@ -148,6 +147,9 @@ impl ReplaceReceiver<'_> {
|
||||
|
||||
Type::Infer(_) | Type::Never(_) | Type::Verbatim(_) => {}
|
||||
|
||||
#[cfg(test)]
|
||||
Type::__TestExhaustive(_) => unimplemented!(),
|
||||
#[cfg(not(test))]
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@ -178,14 +180,11 @@ 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::AssocType(arg) => self.visit_type_mut(&mut arg.ty),
|
||||
GenericArgument::Binding(arg) => self.visit_type_mut(&mut arg.ty),
|
||||
GenericArgument::Lifetime(_)
|
||||
| GenericArgument::Const(_)
|
||||
| GenericArgument::AssocConst(_)
|
||||
| GenericArgument::Constraint(_) => {}
|
||||
_ => {}
|
||||
| GenericArgument::Constraint(_)
|
||||
| GenericArgument::Const(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -207,10 +206,8 @@ 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::Verbatim(_) => {}
|
||||
_ => {}
|
||||
TypeParamBound::Lifetime(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -228,15 +225,13 @@ 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::Lifetime(_) | WherePredicate::Eq(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,19 +13,15 @@ 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");
|
||||
@ -39,6 +35,7 @@ pub const TRY_FROM: Symbol = Symbol("try_from");
|
||||
pub const UNTAGGED: Symbol = Symbol("untagged");
|
||||
pub const VARIANT_IDENTIFIER: Symbol = Symbol("variant_identifier");
|
||||
pub const WITH: Symbol = Symbol("with");
|
||||
pub const EXPECTING: Symbol = Symbol("expecting");
|
||||
|
||||
impl PartialEq<Symbol> for Ident {
|
||||
fn eq(&self, word: &Symbol) -> bool {
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! This crate provides Serde's two derive macros.
|
||||
//!
|
||||
//! ```edition2021
|
||||
//! # use serde_derive::{Deserialize, Serialize};
|
||||
//! ```edition2018
|
||||
//! # use serde_derive::{Serialize, Deserialize};
|
||||
//! #
|
||||
//! #[derive(Serialize, Deserialize)]
|
||||
//! # struct S;
|
||||
@ -13,7 +13,8 @@
|
||||
//!
|
||||
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.197")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.136")]
|
||||
#![allow(unknown_lints, bare_trait_objects)]
|
||||
// Ignored clippy lints
|
||||
#![allow(
|
||||
// clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054
|
||||
@ -21,7 +22,6 @@
|
||||
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_untyped,
|
||||
clippy::let_underscore_drop,
|
||||
clippy::manual_assert,
|
||||
clippy::map_err_ignore,
|
||||
clippy::match_same_arms,
|
||||
@ -50,6 +50,7 @@
|
||||
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,
|
||||
@ -59,18 +60,18 @@
|
||||
clippy::use_self,
|
||||
clippy::wildcard_imports
|
||||
)]
|
||||
#![cfg_attr(all(test, exhaustive), feature(non_exhaustive_omitted_patterns_lint))]
|
||||
|
||||
extern crate proc_macro2;
|
||||
#[macro_use]
|
||||
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]
|
||||
@ -82,13 +83,13 @@ mod de;
|
||||
mod dummy;
|
||||
mod pretend;
|
||||
mod ser;
|
||||
mod this;
|
||||
mod try;
|
||||
|
||||
#[proc_macro_derive(Serialize, attributes(serde))]
|
||||
pub fn derive_serialize(input: TokenStream) -> TokenStream {
|
||||
let mut input = parse_macro_input!(input as DeriveInput);
|
||||
ser::expand_derive_serialize(&mut input)
|
||||
.unwrap_or_else(syn::Error::into_compile_error)
|
||||
.unwrap_or_else(to_compile_errors)
|
||||
.into()
|
||||
}
|
||||
|
||||
@ -96,6 +97,11 @@ 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(syn::Error::into_compile_error)
|
||||
.unwrap_or_else(to_compile_errors)
|
||||
.into()
|
||||
}
|
||||
|
||||
fn to_compile_errors(errors: Vec<syn::Error>) -> proc_macro2::TokenStream {
|
||||
let compile_errors = errors.iter().map(syn::Error::to_compile_error);
|
||||
quote!(#(#compile_errors)*)
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::internals::ast::{Container, Data, Field, Style, Variant};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
use quote::format_ident;
|
||||
|
||||
use internals::ast::{Container, Data, Field, Style, Variant};
|
||||
|
||||
// Suppress dead_code warnings that would otherwise appear when using a remote
|
||||
// derive. Other than this pretend code, a struct annotated with remote derive
|
||||
@ -64,14 +65,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 | Style::Tuple | Style::Newtype, fields) => {
|
||||
Data::Struct(Style::Struct, fields) => {
|
||||
if is_packed {
|
||||
pretend_fields_used_struct_packed(cont, fields)
|
||||
} else {
|
||||
pretend_fields_used_struct(cont, fields)
|
||||
}
|
||||
}
|
||||
Data::Struct(Style::Unit, _) => quote!(),
|
||||
Data::Struct(_, _) => quote!(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -96,14 +97,29 @@ fn pretend_fields_used_struct_packed(cont: &Container, fields: &[Field]) -> Toke
|
||||
|
||||
let members = fields.iter().map(|field| &field.member).collect::<Vec<_>>();
|
||||
|
||||
quote! {
|
||||
match _serde::__private::None::<&#type_ident #ty_generics> {
|
||||
_serde::__private::Some(__v @ #type_ident { #(#members: _),* }) => {
|
||||
#(
|
||||
let _ = _serde::__private::ptr::addr_of!(__v.#members);
|
||||
)*
|
||||
#[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),* }) => {}
|
||||
_ => {}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -115,13 +131,13 @@ fn pretend_fields_used_enum(cont: &Container, variants: &[Variant]) -> TokenStre
|
||||
let patterns = variants
|
||||
.iter()
|
||||
.filter_map(|variant| match variant.style {
|
||||
Style::Struct | Style::Tuple | Style::Newtype => {
|
||||
Style::Struct => {
|
||||
let variant_ident = &variant.ident;
|
||||
let members = variant.fields.iter().map(|field| &field.member);
|
||||
let placeholders = (0usize..).map(|i| format_ident!("__v{}", i));
|
||||
Some(quote!(#type_ident::#variant_ident { #(#members: #placeholders),* }))
|
||||
}
|
||||
Style::Unit => None,
|
||||
_ => None,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
|
@ -1,13 +1,17 @@
|
||||
use crate::fragment::{Fragment, Match, Stmts};
|
||||
use crate::internals::ast::{Container, Data, Field, Style, Variant};
|
||||
use crate::internals::{attr, replace_receiver, Ctxt, Derive};
|
||||
use crate::{bound, dummy, pretend, this};
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use quote::{quote, quote_spanned};
|
||||
use syn::spanned::Spanned;
|
||||
use syn::{parse_quote, Ident, Index, Member};
|
||||
use syn::{self, Ident, Index, Member};
|
||||
|
||||
pub fn expand_derive_serialize(input: &mut syn::DeriveInput) -> syn::Result<TokenStream> {
|
||||
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<TokenStream, Vec<syn::Error>> {
|
||||
replace_receiver(input);
|
||||
|
||||
let ctxt = Ctxt::new();
|
||||
@ -54,6 +58,8 @@ pub fn expand_derive_serialize(input: &mut syn::DeriveInput) -> syn::Result<Toke
|
||||
|
||||
Ok(dummy::wrap_in_const(
|
||||
cont.attrs.custom_serde_path(),
|
||||
"SERIALIZE",
|
||||
ident,
|
||||
impl_block,
|
||||
))
|
||||
}
|
||||
@ -76,13 +82,9 @@ struct Parameters {
|
||||
self_var: Ident,
|
||||
|
||||
/// Path to the type the impl is for. Either a single `Ident` for local
|
||||
/// types (does not include generic parameters) or `some::remote::Path` for
|
||||
/// remote types.
|
||||
this_type: syn::Path,
|
||||
|
||||
/// Same as `this_type` but using `::<T>` for generic parameters for use in
|
||||
/// expression position.
|
||||
this_value: syn::Path,
|
||||
/// types or `some::remote::Ident` for remote types. Does not include
|
||||
/// generic parameters.
|
||||
this: syn::Path,
|
||||
|
||||
/// Generics including any explicit and inferred bounds for the impl.
|
||||
generics: syn::Generics,
|
||||
@ -103,15 +105,18 @@ impl Parameters {
|
||||
Ident::new("self", Span::call_site())
|
||||
};
|
||||
|
||||
let this_type = this::this_type(cont);
|
||||
let this_value = this::this_value(cont);
|
||||
let this = match cont.attrs.remote() {
|
||||
Some(remote) => remote.clone(),
|
||||
None => cont.ident.clone().into(),
|
||||
};
|
||||
|
||||
let is_packed = cont.attrs.is_packed();
|
||||
|
||||
let generics = build_generics(cont);
|
||||
|
||||
Parameters {
|
||||
self_var,
|
||||
this_type,
|
||||
this_value,
|
||||
this,
|
||||
generics,
|
||||
is_remote,
|
||||
is_packed,
|
||||
@ -121,7 +126,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_type.segments.last().unwrap().ident.to_string()
|
||||
self.this.segments.last().unwrap().ident.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
@ -282,7 +287,7 @@ fn serialize_tuple_struct(
|
||||
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
|
||||
|
||||
quote_block! {
|
||||
let #let_mut __serde_state = _serde::Serializer::serialize_tuple_struct(__serializer, #type_name, #len)?;
|
||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_struct(__serializer, #type_name, #len));
|
||||
#(#serialize_stmts)*
|
||||
_serde::ser::SerializeTupleStruct::end(__serde_state)
|
||||
}
|
||||
@ -304,7 +309,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! {
|
||||
#func(&mut __serde_state, #tag, #type_name)?;
|
||||
try!(#func(&mut __serde_state, #tag, #type_name));
|
||||
}
|
||||
}
|
||||
_ => quote! {},
|
||||
@ -345,7 +350,7 @@ fn serialize_struct_as_struct(
|
||||
);
|
||||
|
||||
quote_block! {
|
||||
let #let_mut __serde_state = _serde::Serializer::serialize_struct(__serializer, #type_name, #len)?;
|
||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct(__serializer, #type_name, #len));
|
||||
#tag_field
|
||||
#(#serialize_fields)*
|
||||
_serde::ser::SerializeStruct::end(__serde_state)
|
||||
@ -389,7 +394,7 @@ fn serialize_struct_as_map(
|
||||
};
|
||||
|
||||
quote_block! {
|
||||
let #let_mut __serde_state = _serde::Serializer::serialize_map(__serializer, #len)?;
|
||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(__serializer, #len));
|
||||
#tag_field
|
||||
#(#serialize_fields)*
|
||||
_serde::ser::SerializeMap::end(__serde_state)
|
||||
@ -401,7 +406,7 @@ fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Cont
|
||||
|
||||
let self_var = ¶ms.self_var;
|
||||
|
||||
let mut arms: Vec<_> = variants
|
||||
let arms: Vec<_> = variants
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(variant_index, variant)| {
|
||||
@ -409,12 +414,6 @@ 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)*
|
||||
@ -428,7 +427,7 @@ fn serialize_variant(
|
||||
variant_index: u32,
|
||||
cattrs: &attr::Container,
|
||||
) -> TokenStream {
|
||||
let this_value = ¶ms.this_value;
|
||||
let this = ¶ms.this;
|
||||
let variant_ident = &variant.ident;
|
||||
|
||||
if variant.attrs.skip_serializing() {
|
||||
@ -446,56 +445,47 @@ fn serialize_variant(
|
||||
Style::Struct => quote!({ .. }),
|
||||
};
|
||||
quote! {
|
||||
#this_value::#variant_ident #fields_pat => #skipped_err,
|
||||
#this::#variant_ident #fields_pat => #skipped_err,
|
||||
}
|
||||
} else {
|
||||
// variant wasn't skipped
|
||||
let case = match variant.style {
|
||||
Style::Unit => {
|
||||
quote! {
|
||||
#this_value::#variant_ident
|
||||
#this::#variant_ident
|
||||
}
|
||||
}
|
||||
Style::Newtype => {
|
||||
quote! {
|
||||
#this_value::#variant_ident(ref __field0)
|
||||
#this::#variant_ident(ref __field0)
|
||||
}
|
||||
}
|
||||
Style::Tuple => {
|
||||
let field_names = (0..variant.fields.len())
|
||||
.map(|i| Ident::new(&format!("__field{}", i), Span::call_site()));
|
||||
quote! {
|
||||
#this_value::#variant_ident(#(ref #field_names),*)
|
||||
#this::#variant_ident(#(ref #field_names),*)
|
||||
}
|
||||
}
|
||||
Style::Struct => {
|
||||
let members = variant.fields.iter().map(|f| &f.member);
|
||||
quote! {
|
||||
#this_value::#variant_ident { #(ref #members),* }
|
||||
#this::#variant_ident { #(ref #members),* }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let body = Match(match (cattrs.tag(), variant.attrs.untagged()) {
|
||||
(attr::TagType::External, false) => {
|
||||
let body = Match(match cattrs.tag() {
|
||||
attr::TagType::External => {
|
||||
serialize_externally_tagged_variant(params, variant, variant_index, cattrs)
|
||||
}
|
||||
(attr::TagType::Internal { tag }, false) => {
|
||||
attr::TagType::Internal { tag } => {
|
||||
serialize_internally_tagged_variant(params, variant, cattrs, tag)
|
||||
}
|
||||
(attr::TagType::Adjacent { tag, content }, false) => {
|
||||
serialize_adjacently_tagged_variant(
|
||||
params,
|
||||
variant,
|
||||
cattrs,
|
||||
variant_index,
|
||||
tag,
|
||||
content,
|
||||
)
|
||||
}
|
||||
(attr::TagType::None, _) | (_, true) => {
|
||||
serialize_untagged_variant(params, variant, cattrs)
|
||||
attr::TagType::Adjacent { tag, content } => {
|
||||
serialize_adjacently_tagged_variant(params, variant, cattrs, tag, content)
|
||||
}
|
||||
attr::TagType::None => serialize_untagged_variant(params, variant, cattrs),
|
||||
});
|
||||
|
||||
quote! {
|
||||
@ -572,7 +562,7 @@ fn serialize_externally_tagged_variant(
|
||||
},
|
||||
params,
|
||||
&variant.fields,
|
||||
type_name,
|
||||
&type_name,
|
||||
),
|
||||
}
|
||||
}
|
||||
@ -606,10 +596,10 @@ fn serialize_internally_tagged_variant(
|
||||
match effective_style(variant) {
|
||||
Style::Unit => {
|
||||
quote_block! {
|
||||
let mut __struct = _serde::Serializer::serialize_struct(
|
||||
__serializer, #type_name, 1)?;
|
||||
_serde::ser::SerializeStruct::serialize_field(
|
||||
&mut __struct, #tag, #variant_name)?;
|
||||
let mut __struct = try!(_serde::Serializer::serialize_struct(
|
||||
__serializer, #type_name, 1));
|
||||
try!(_serde::ser::SerializeStruct::serialize_field(
|
||||
&mut __struct, #tag, #variant_name));
|
||||
_serde::ser::SerializeStruct::end(__struct)
|
||||
}
|
||||
}
|
||||
@ -637,7 +627,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"),
|
||||
}
|
||||
@ -647,20 +637,12 @@ fn serialize_adjacently_tagged_variant(
|
||||
params: &Parameters,
|
||||
variant: &Variant,
|
||||
cattrs: &attr::Container,
|
||||
variant_index: u32,
|
||||
tag: &str,
|
||||
content: &str,
|
||||
) -> Fragment {
|
||||
let this_type = ¶ms.this_type;
|
||||
let this = ¶ms.this;
|
||||
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);
|
||||
@ -671,10 +653,10 @@ fn serialize_adjacently_tagged_variant(
|
||||
match effective_style(variant) {
|
||||
Style::Unit => {
|
||||
return quote_block! {
|
||||
let mut __struct = _serde::Serializer::serialize_struct(
|
||||
__serializer, #type_name, 1)?;
|
||||
_serde::ser::SerializeStruct::serialize_field(
|
||||
&mut __struct, #tag, #serialize_variant)?;
|
||||
let mut __struct = try!(_serde::Serializer::serialize_struct(
|
||||
__serializer, #type_name, 1));
|
||||
try!(_serde::ser::SerializeStruct::serialize_field(
|
||||
&mut __struct, #tag, #variant_name));
|
||||
_serde::ser::SerializeStruct::end(__struct)
|
||||
};
|
||||
}
|
||||
@ -688,12 +670,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 = _serde::Serializer::serialize_struct(
|
||||
__serializer, #type_name, 2)?;
|
||||
_serde::ser::SerializeStruct::serialize_field(
|
||||
&mut __struct, #tag, #serialize_variant)?;
|
||||
#func(
|
||||
&mut __struct, #content, #field_expr)?;
|
||||
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));
|
||||
_serde::ser::SerializeStruct::end(__struct)
|
||||
};
|
||||
}
|
||||
@ -704,13 +686,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: &[_] = &match variant.style {
|
||||
let fields_ident: &Vec<_> = &match variant.style {
|
||||
Style::Unit => {
|
||||
if variant.attrs.serialize_with().is_some() {
|
||||
vec![]
|
||||
@ -735,10 +717,9 @@ 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_type #ty_generics>,
|
||||
phantom: _serde::__private::PhantomData<#this #ty_generics>,
|
||||
}
|
||||
|
||||
impl #wrapper_impl_generics _serde::Serialize for __AdjacentlyTagged #wrapper_ty_generics #where_clause {
|
||||
@ -753,15 +734,15 @@ fn serialize_adjacently_tagged_variant(
|
||||
}
|
||||
}
|
||||
|
||||
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(
|
||||
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(
|
||||
&mut __struct, #content, &__AdjacentlyTagged {
|
||||
data: (#(#fields_ident,)*),
|
||||
phantom: _serde::__private::PhantomData::<#this_type #ty_generics>,
|
||||
})?;
|
||||
phantom: _serde::__private::PhantomData::<#this #ty_generics>,
|
||||
}));
|
||||
_serde::ser::SerializeStruct::end(__struct)
|
||||
}
|
||||
}
|
||||
@ -800,16 +781,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<'a> {
|
||||
enum TupleVariant {
|
||||
ExternallyTagged {
|
||||
type_name: &'a str,
|
||||
type_name: String,
|
||||
variant_index: u32,
|
||||
variant_name: &'a str,
|
||||
variant_name: String,
|
||||
},
|
||||
Untagged,
|
||||
}
|
||||
@ -851,21 +832,21 @@ fn serialize_tuple_variant(
|
||||
variant_name,
|
||||
} => {
|
||||
quote_block! {
|
||||
let #let_mut __serde_state = _serde::Serializer::serialize_tuple_variant(
|
||||
let #let_mut __serde_state = try!(_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 = _serde::Serializer::serialize_tuple(
|
||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple(
|
||||
__serializer,
|
||||
#len)?;
|
||||
#len));
|
||||
#(#serialize_stmts)*
|
||||
_serde::ser::SerializeTuple::end(__serde_state)
|
||||
}
|
||||
@ -876,17 +857,17 @@ fn serialize_tuple_variant(
|
||||
enum StructVariant<'a> {
|
||||
ExternallyTagged {
|
||||
variant_index: u32,
|
||||
variant_name: &'a str,
|
||||
variant_name: String,
|
||||
},
|
||||
InternallyTagged {
|
||||
tag: &'a str,
|
||||
variant_name: &'a str,
|
||||
variant_name: String,
|
||||
},
|
||||
Untagged,
|
||||
}
|
||||
|
||||
fn serialize_struct_variant(
|
||||
context: StructVariant,
|
||||
fn serialize_struct_variant<'a>(
|
||||
context: StructVariant<'a>,
|
||||
params: &Parameters,
|
||||
fields: &[Field],
|
||||
name: &str,
|
||||
@ -928,40 +909,40 @@ fn serialize_struct_variant(
|
||||
variant_name,
|
||||
} => {
|
||||
quote_block! {
|
||||
let #let_mut __serde_state = _serde::Serializer::serialize_struct_variant(
|
||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct_variant(
|
||||
__serializer,
|
||||
#name,
|
||||
#variant_index,
|
||||
#variant_name,
|
||||
#len,
|
||||
)?;
|
||||
));
|
||||
#(#serialize_fields)*
|
||||
_serde::ser::SerializeStructVariant::end(__serde_state)
|
||||
}
|
||||
}
|
||||
StructVariant::InternallyTagged { tag, variant_name } => {
|
||||
quote_block! {
|
||||
let mut __serde_state = _serde::Serializer::serialize_struct(
|
||||
let mut __serde_state = try!(_serde::Serializer::serialize_struct(
|
||||
__serializer,
|
||||
#name,
|
||||
#len + 1,
|
||||
)?;
|
||||
_serde::ser::SerializeStruct::serialize_field(
|
||||
));
|
||||
try!(_serde::ser::SerializeStruct::serialize_field(
|
||||
&mut __serde_state,
|
||||
#tag,
|
||||
#variant_name,
|
||||
)?;
|
||||
));
|
||||
#(#serialize_fields)*
|
||||
_serde::ser::SerializeStruct::end(__serde_state)
|
||||
}
|
||||
}
|
||||
StructVariant::Untagged => {
|
||||
quote_block! {
|
||||
let #let_mut __serde_state = _serde::Serializer::serialize_struct(
|
||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct(
|
||||
__serializer,
|
||||
#name,
|
||||
#len,
|
||||
)?;
|
||||
));
|
||||
#(#serialize_fields)*
|
||||
_serde::ser::SerializeStruct::end(__serde_state)
|
||||
}
|
||||
@ -969,8 +950,8 @@ fn serialize_struct_variant(
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_struct_variant_with_flatten(
|
||||
context: StructVariant,
|
||||
fn serialize_struct_variant_with_flatten<'a>(
|
||||
context: StructVariant<'a>,
|
||||
params: &Parameters,
|
||||
fields: &[Field],
|
||||
name: &str,
|
||||
@ -990,7 +971,7 @@ fn serialize_struct_variant_with_flatten(
|
||||
variant_index,
|
||||
variant_name,
|
||||
} => {
|
||||
let this_type = ¶ms.this_type;
|
||||
let this = ¶ms.this;
|
||||
let fields_ty = fields.iter().map(|f| &f.ty);
|
||||
let members = &fields.iter().map(|f| &f.member).collect::<Vec<_>>();
|
||||
|
||||
@ -999,10 +980,9 @@ fn serialize_struct_variant_with_flatten(
|
||||
let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
|
||||
|
||||
quote_block! {
|
||||
#[doc(hidden)]
|
||||
struct __EnumFlatten #wrapper_generics #where_clause {
|
||||
data: (#(&'__a #fields_ty,)*),
|
||||
phantom: _serde::__private::PhantomData<#this_type #ty_generics>,
|
||||
phantom: _serde::__private::PhantomData<#this #ty_generics>,
|
||||
}
|
||||
|
||||
impl #wrapper_impl_generics _serde::Serialize for __EnumFlatten #wrapper_ty_generics #where_clause {
|
||||
@ -1011,9 +991,9 @@ fn serialize_struct_variant_with_flatten(
|
||||
__S: _serde::Serializer,
|
||||
{
|
||||
let (#(#members,)*) = self.data;
|
||||
let #let_mut __serde_state = _serde::Serializer::serialize_map(
|
||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
|
||||
__serializer,
|
||||
_serde::__private::None)?;
|
||||
_serde::__private::None));
|
||||
#(#serialize_fields)*
|
||||
_serde::ser::SerializeMap::end(__serde_state)
|
||||
}
|
||||
@ -1026,29 +1006,29 @@ fn serialize_struct_variant_with_flatten(
|
||||
#variant_name,
|
||||
&__EnumFlatten {
|
||||
data: (#(#members,)*),
|
||||
phantom: _serde::__private::PhantomData::<#this_type #ty_generics>,
|
||||
phantom: _serde::__private::PhantomData::<#this #ty_generics>,
|
||||
})
|
||||
}
|
||||
}
|
||||
StructVariant::InternallyTagged { tag, variant_name } => {
|
||||
quote_block! {
|
||||
let #let_mut __serde_state = _serde::Serializer::serialize_map(
|
||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
|
||||
__serializer,
|
||||
_serde::__private::None)?;
|
||||
_serde::ser::SerializeMap::serialize_entry(
|
||||
_serde::__private::None));
|
||||
try!(_serde::ser::SerializeMap::serialize_entry(
|
||||
&mut __serde_state,
|
||||
#tag,
|
||||
#variant_name,
|
||||
)?;
|
||||
));
|
||||
#(#serialize_fields)*
|
||||
_serde::ser::SerializeMap::end(__serde_state)
|
||||
}
|
||||
}
|
||||
StructVariant::Untagged => {
|
||||
quote_block! {
|
||||
let #let_mut __serde_state = _serde::Serializer::serialize_map(
|
||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
|
||||
__serializer,
|
||||
_serde::__private::None)?;
|
||||
_serde::__private::None));
|
||||
#(#serialize_fields)*
|
||||
_serde::ser::SerializeMap::end(__serde_state)
|
||||
}
|
||||
@ -1093,7 +1073,7 @@ fn serialize_tuple_struct_visitor(
|
||||
let span = field.original.span();
|
||||
let func = tuple_trait.serialize_element(span);
|
||||
let ser = quote! {
|
||||
#func(&mut __serde_state, #field_expr)?;
|
||||
try!(#func(&mut __serde_state, #field_expr));
|
||||
};
|
||||
|
||||
match skip {
|
||||
@ -1137,12 +1117,12 @@ fn serialize_struct_visitor(
|
||||
let ser = if field.attrs.flatten() {
|
||||
let func = quote_spanned!(span=> _serde::Serialize::serialize);
|
||||
quote! {
|
||||
#func(&#field_expr, _serde::__private::ser::FlatMapSerializer(&mut __serde_state))?;
|
||||
try!(#func(&#field_expr, _serde::__private::ser::FlatMapSerializer(&mut __serde_state)));
|
||||
}
|
||||
} else {
|
||||
let func = struct_trait.serialize_field(span);
|
||||
quote! {
|
||||
#func(&mut __serde_state, #key_expr, #field_expr)?;
|
||||
try!(#func(&mut __serde_state, #key_expr, #field_expr));
|
||||
}
|
||||
};
|
||||
|
||||
@ -1154,7 +1134,7 @@ fn serialize_struct_visitor(
|
||||
if !#skip {
|
||||
#ser
|
||||
} else {
|
||||
#skip_func(&mut __serde_state, #key_expr)?;
|
||||
try!(#skip_func(&mut __serde_state, #key_expr));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -1212,7 +1192,7 @@ fn wrap_serialize_with(
|
||||
field_tys: &[&syn::Type],
|
||||
field_exprs: &[TokenStream],
|
||||
) -> TokenStream {
|
||||
let this_type = ¶ms.this_type;
|
||||
let this = ¶ms.this;
|
||||
let (_, ty_generics, where_clause) = params.generics.split_for_impl();
|
||||
|
||||
let wrapper_generics = if field_exprs.is_empty() {
|
||||
@ -1230,10 +1210,9 @@ fn wrap_serialize_with(
|
||||
});
|
||||
|
||||
quote!({
|
||||
#[doc(hidden)]
|
||||
struct __SerializeWith #wrapper_impl_generics #where_clause {
|
||||
values: (#(&'__a #field_tys, )*),
|
||||
phantom: _serde::__private::PhantomData<#this_type #ty_generics>,
|
||||
phantom: _serde::__private::PhantomData<#this #ty_generics>,
|
||||
}
|
||||
|
||||
impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause {
|
||||
@ -1247,14 +1226,14 @@ fn wrap_serialize_with(
|
||||
|
||||
&__SerializeWith {
|
||||
values: (#(#field_exprs, )*),
|
||||
phantom: _serde::__private::PhantomData::<#this_type #ty_generics>,
|
||||
phantom: _serde::__private::PhantomData::<#this #ty_generics>,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Serialization of an empty struct results in code like:
|
||||
//
|
||||
// let mut __serde_state = serializer.serialize_struct("S", 0)?;
|
||||
// let mut __serde_state = try!(serializer.serialize_struct("S", 0));
|
||||
// _serde::ser::SerializeStruct::end(__serde_state)
|
||||
//
|
||||
// where we want to omit the `mut` to avoid a warning.
|
||||
|
@ -1,32 +0,0 @@
|
||||
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())
|
||||
}
|
||||
}
|
24
serde_derive/src/try.rs
Normal file
24
serde_derive/src/try.rs
Normal file
@ -0,0 +1,24 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,24 +1,23 @@
|
||||
[package]
|
||||
name = "serde_derive_internals"
|
||||
version = "0.29.0"
|
||||
version = "0.26.0" # remember to update html_root_url
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
description = "AST representation used by Serde derive macros. Unstable."
|
||||
documentation = "https://docs.rs/serde_derive_internals"
|
||||
exclude = ["build.rs"]
|
||||
homepage = "https://serde.rs"
|
||||
keywords = ["serde", "serialization"]
|
||||
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"
|
||||
rust-version = "1.56"
|
||||
documentation = "https://docs.rs/serde_derive_internals"
|
||||
keywords = ["serde", "serialization"]
|
||||
include = ["lib.rs", "src/**/*.rs", "LICENSE-APACHE", "LICENSE-MIT"]
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = { workspace = true }
|
||||
quote = { workspace = true }
|
||||
syn = { workspace = true, features = ["clone-impls", "derive", "parsing", "printing"] }
|
||||
proc-macro2 = "1.0"
|
||||
quote = "1.0"
|
||||
syn = { version = "1.0.60", default-features = false, features = ["derive", "parsing", "printing", "clone-impls"] }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
rustdoc-args = ["--generate-link-to-definition"]
|
||||
|
@ -1,9 +1,6 @@
|
||||
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
|
||||
|
@ -1,10 +1,10 @@
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.29.0")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.26.0")]
|
||||
#![allow(unknown_lints, bare_trait_objects)]
|
||||
// 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_untyped,
|
||||
clippy::let_underscore_drop,
|
||||
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")]
|
||||
|
24
serde_test/Cargo.toml
Normal file
24
serde_test/Cargo.toml
Normal file
@ -0,0 +1,24 @@
|
||||
[package]
|
||||
name = "serde_test"
|
||||
version = "1.0.136" # remember to update html_root_url
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
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"]
|
1
serde_test/LICENSE-APACHE
Symbolic link
1
serde_test/LICENSE-APACHE
Symbolic link
@ -0,0 +1 @@
|
||||
../LICENSE-APACHE
|
1
serde_test/LICENSE-MIT
Symbolic link
1
serde_test/LICENSE-MIT
Symbolic link
@ -0,0 +1 @@
|
||||
../LICENSE-MIT
|
1
serde_test/README.md
Symbolic link
1
serde_test/README.md
Symbolic link
@ -0,0 +1 @@
|
||||
../README.md
|
48
serde_test/build.rs
Normal file
48
serde_test/build.rs
Normal file
@ -0,0 +1,48 @@
|
||||
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<u32> {
|
||||
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()
|
||||
}
|
1
serde_test/crates-io.md
Symbolic link
1
serde_test/crates-io.md
Symbolic link
@ -0,0 +1 @@
|
||||
../crates-io.md
|
223
serde_test/src/assert.rs
Normal file
223
serde_test/src/assert.rs
Normal file
@ -0,0 +1,223 @@
|
||||
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<T: ?Sized>(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<Mutex<u32>>,
|
||||
/// }
|
||||
///
|
||||
/// 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<T: ?Sized>(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::<S>(
|
||||
/// &[
|
||||
/// 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());
|
||||
}
|
||||
}
|
847
serde_test/src/configure.rs
Normal file
847
serde_test/src/configure.rs
Normal file
@ -0,0 +1,847 @@
|
||||
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: ?Sized>(T);
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Compact<T: ?Sized>(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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// 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<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
/// 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<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Readable(self)
|
||||
}
|
||||
/// Marks `self` as using `is_human_readable == false`
|
||||
fn compact(self) -> Compact<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Compact(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Configure for T {}
|
||||
|
||||
impl<T: ?Sized> Serialize for Readable<T>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
self.0.serialize(Readable(serializer))
|
||||
}
|
||||
}
|
||||
impl<T: ?Sized> Serialize for Compact<T>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
self.0.serialize(Compact(serializer))
|
||||
}
|
||||
}
|
||||
impl<'de, T> Deserialize<'de> for Readable<T>
|
||||
where
|
||||
T: Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
T::deserialize(Readable(deserializer)).map(Readable)
|
||||
}
|
||||
}
|
||||
impl<'de, T> Deserialize<'de> for Compact<T>
|
||||
where
|
||||
T: Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
T::deserialize(Compact(deserializer)).map(Compact)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, T> DeserializeSeed<'de> for Readable<T>
|
||||
where
|
||||
T: DeserializeSeed<'de>,
|
||||
{
|
||||
type Value = T::Value;
|
||||
|
||||
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
self.0.deserialize(Readable(deserializer))
|
||||
}
|
||||
}
|
||||
impl<'de, T> DeserializeSeed<'de> for Compact<T>
|
||||
where
|
||||
T: DeserializeSeed<'de>,
|
||||
{
|
||||
type Value = T::Value;
|
||||
|
||||
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
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<Self::Ok, Self::Error>);
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_serializer {
|
||||
($wrapper:ident, $is_human_readable:expr) => {
|
||||
impl<S> Serializer for $wrapper<S>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
type Ok = S::Ok;
|
||||
type Error = S::Error;
|
||||
|
||||
type SerializeSeq = $wrapper<S::SerializeSeq>;
|
||||
type SerializeTuple = $wrapper<S::SerializeTuple>;
|
||||
type SerializeTupleStruct = $wrapper<S::SerializeTupleStruct>;
|
||||
type SerializeTupleVariant = $wrapper<S::SerializeTupleVariant>;
|
||||
type SerializeMap = $wrapper<S::SerializeMap>;
|
||||
type SerializeStruct = $wrapper<S::SerializeStruct>;
|
||||
type SerializeStructVariant = $wrapper<S::SerializeStructVariant>;
|
||||
|
||||
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<S::Ok, S::Error> {
|
||||
self.0.serialize_unit()
|
||||
}
|
||||
|
||||
fn serialize_unit_variant(
|
||||
self,
|
||||
name: &'static str,
|
||||
variant_index: u32,
|
||||
variant: &'static str,
|
||||
) -> Result<S::Ok, S::Error> {
|
||||
self.0.serialize_unit_variant(name, variant_index, variant)
|
||||
}
|
||||
|
||||
fn serialize_newtype_struct<T: ?Sized>(
|
||||
self,
|
||||
name: &'static str,
|
||||
value: &T,
|
||||
) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
self.0.serialize_newtype_struct(name, &$wrapper(value))
|
||||
}
|
||||
|
||||
fn serialize_newtype_variant<T: ?Sized>(
|
||||
self,
|
||||
name: &'static str,
|
||||
variant_index: u32,
|
||||
variant: &'static str,
|
||||
value: &T,
|
||||
) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
self.0
|
||||
.serialize_newtype_variant(name, variant_index, variant, &$wrapper(value))
|
||||
}
|
||||
|
||||
fn serialize_none(self) -> Result<S::Ok, Self::Error> {
|
||||
self.0.serialize_none()
|
||||
}
|
||||
|
||||
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<S::Ok, Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
self.0.serialize_some(&$wrapper(value))
|
||||
}
|
||||
|
||||
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
|
||||
self.0.serialize_seq(len).map($wrapper)
|
||||
}
|
||||
|
||||
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
|
||||
self.0.serialize_tuple(len).map($wrapper)
|
||||
}
|
||||
|
||||
fn serialize_tuple_struct(
|
||||
self,
|
||||
name: &'static str,
|
||||
len: usize,
|
||||
) -> Result<Self::SerializeTupleStruct, Self::Error> {
|
||||
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::SerializeTupleVariant, Self::Error> {
|
||||
self.0
|
||||
.serialize_tuple_variant(name, variant_index, variant, len)
|
||||
.map($wrapper)
|
||||
}
|
||||
|
||||
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
|
||||
self.0.serialize_map(len).map($wrapper)
|
||||
}
|
||||
|
||||
fn serialize_struct(
|
||||
self,
|
||||
name: &'static str,
|
||||
len: usize,
|
||||
) -> Result<Self::SerializeStruct, Self::Error> {
|
||||
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::SerializeStructVariant, Self::Error> {
|
||||
self.0
|
||||
.serialize_struct_variant(name, variant_index, variant, len)
|
||||
.map($wrapper)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> SerializeSeq for $wrapper<S>
|
||||
where
|
||||
S: SerializeSeq,
|
||||
{
|
||||
type Ok = S::Ok;
|
||||
type Error = S::Error;
|
||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), S::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
self.0.serialize_element(&$wrapper(value))
|
||||
}
|
||||
fn end(self) -> Result<S::Ok, S::Error> {
|
||||
self.0.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> SerializeTuple for $wrapper<S>
|
||||
where
|
||||
S: SerializeTuple,
|
||||
{
|
||||
type Ok = S::Ok;
|
||||
type Error = S::Error;
|
||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), S::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
self.0.serialize_element(&$wrapper(value))
|
||||
}
|
||||
fn end(self) -> Result<S::Ok, S::Error> {
|
||||
self.0.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> SerializeTupleStruct for $wrapper<S>
|
||||
where
|
||||
S: SerializeTupleStruct,
|
||||
{
|
||||
type Ok = S::Ok;
|
||||
type Error = S::Error;
|
||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), S::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
self.0.serialize_field(&$wrapper(value))
|
||||
}
|
||||
fn end(self) -> Result<S::Ok, S::Error> {
|
||||
self.0.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> SerializeTupleVariant for $wrapper<S>
|
||||
where
|
||||
S: SerializeTupleVariant,
|
||||
{
|
||||
type Ok = S::Ok;
|
||||
type Error = S::Error;
|
||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), S::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
self.0.serialize_field(&$wrapper(value))
|
||||
}
|
||||
fn end(self) -> Result<S::Ok, S::Error> {
|
||||
self.0.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> SerializeMap for $wrapper<S>
|
||||
where
|
||||
S: SerializeMap,
|
||||
{
|
||||
type Ok = S::Ok;
|
||||
type Error = S::Error;
|
||||
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), S::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
self.0.serialize_key(&$wrapper(key))
|
||||
}
|
||||
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), S::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
self.0.serialize_value(&$wrapper(value))
|
||||
}
|
||||
fn serialize_entry<K: ?Sized, V: ?Sized>(
|
||||
&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<S::Ok, S::Error> {
|
||||
self.0.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> SerializeStruct for $wrapper<S>
|
||||
where
|
||||
S: SerializeStruct,
|
||||
{
|
||||
type Ok = S::Ok;
|
||||
type Error = S::Error;
|
||||
fn serialize_field<T: ?Sized>(
|
||||
&mut self,
|
||||
name: &'static str,
|
||||
field: &T,
|
||||
) -> Result<(), S::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
self.0.serialize_field(name, &$wrapper(field))
|
||||
}
|
||||
fn end(self) -> Result<S::Ok, S::Error> {
|
||||
self.0.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> SerializeStructVariant for $wrapper<S>
|
||||
where
|
||||
S: SerializeStructVariant,
|
||||
{
|
||||
type Ok = S::Ok;
|
||||
type Error = S::Error;
|
||||
fn serialize_field<T: ?Sized>(
|
||||
&mut self,
|
||||
name: &'static str,
|
||||
field: &T,
|
||||
) -> Result<(), S::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
self.0.serialize_field(name, &$wrapper(field))
|
||||
}
|
||||
fn end(self) -> Result<S::Ok, S::Error> {
|
||||
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<V>(self, visitor: V) -> Result<V::Value, D::Error>
|
||||
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<D>
|
||||
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<V>(
|
||||
self,
|
||||
name: &'static str,
|
||||
visitor: V,
|
||||
) -> Result<V::Value, D::Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
self.0.deserialize_unit_struct(name, $wrapper(visitor))
|
||||
}
|
||||
fn deserialize_newtype_struct<V>(
|
||||
self,
|
||||
name: &'static str,
|
||||
visitor: V,
|
||||
) -> Result<V::Value, D::Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
self.0.deserialize_newtype_struct(name, $wrapper(visitor))
|
||||
}
|
||||
fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, D::Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
self.0.deserialize_tuple(len, $wrapper(visitor))
|
||||
}
|
||||
fn deserialize_tuple_struct<V>(
|
||||
self,
|
||||
name: &'static str,
|
||||
len: usize,
|
||||
visitor: V,
|
||||
) -> Result<V::Value, D::Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
self.0
|
||||
.deserialize_tuple_struct(name, len, $wrapper(visitor))
|
||||
}
|
||||
fn deserialize_struct<V>(
|
||||
self,
|
||||
name: &'static str,
|
||||
fields: &'static [&'static str],
|
||||
visitor: V,
|
||||
) -> Result<V::Value, D::Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
self.0.deserialize_struct(name, fields, $wrapper(visitor))
|
||||
}
|
||||
fn deserialize_enum<V>(
|
||||
self,
|
||||
name: &'static str,
|
||||
variants: &'static [&'static str],
|
||||
visitor: V,
|
||||
) -> Result<V::Value, D::Error>
|
||||
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<D>
|
||||
where
|
||||
D: Visitor<'de>,
|
||||
{
|
||||
type Value = D::Value;
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.0.expecting(formatter)
|
||||
}
|
||||
fn visit_bool<E>(self, v: bool) -> Result<D::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
self.0.visit_bool(v)
|
||||
}
|
||||
fn visit_i8<E>(self, v: i8) -> Result<D::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
self.0.visit_i8(v)
|
||||
}
|
||||
fn visit_i16<E>(self, v: i16) -> Result<D::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
self.0.visit_i16(v)
|
||||
}
|
||||
fn visit_i32<E>(self, v: i32) -> Result<D::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
self.0.visit_i32(v)
|
||||
}
|
||||
fn visit_i64<E>(self, v: i64) -> Result<D::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
self.0.visit_i64(v)
|
||||
}
|
||||
fn visit_u8<E>(self, v: u8) -> Result<D::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
self.0.visit_u8(v)
|
||||
}
|
||||
fn visit_u16<E>(self, v: u16) -> Result<D::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
self.0.visit_u16(v)
|
||||
}
|
||||
fn visit_u32<E>(self, v: u32) -> Result<D::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
self.0.visit_u32(v)
|
||||
}
|
||||
fn visit_u64<E>(self, v: u64) -> Result<D::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
self.0.visit_u64(v)
|
||||
}
|
||||
fn visit_f32<E>(self, v: f32) -> Result<D::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
self.0.visit_f32(v)
|
||||
}
|
||||
fn visit_f64<E>(self, v: f64) -> Result<D::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
self.0.visit_f64(v)
|
||||
}
|
||||
fn visit_char<E>(self, v: char) -> Result<D::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
self.0.visit_char(v)
|
||||
}
|
||||
fn visit_str<E>(self, v: &str) -> Result<D::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
self.0.visit_str(v)
|
||||
}
|
||||
fn visit_borrowed_str<E>(self, v: &'de str) -> Result<D::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
self.0.visit_borrowed_str(v)
|
||||
}
|
||||
fn visit_string<E>(self, v: String) -> Result<D::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
self.0.visit_string(v)
|
||||
}
|
||||
fn visit_bytes<E>(self, v: &[u8]) -> Result<D::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
self.0.visit_bytes(v)
|
||||
}
|
||||
fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<D::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
self.0.visit_borrowed_bytes(v)
|
||||
}
|
||||
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<D::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
self.0.visit_byte_buf(v)
|
||||
}
|
||||
fn visit_none<E>(self) -> Result<D::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
self.0.visit_none()
|
||||
}
|
||||
fn visit_some<D2>(self, deserializer: D2) -> Result<Self::Value, D2::Error>
|
||||
where
|
||||
D2: Deserializer<'de>,
|
||||
{
|
||||
self.0.visit_some($wrapper(deserializer))
|
||||
}
|
||||
fn visit_unit<E>(self) -> Result<D::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
self.0.visit_unit()
|
||||
}
|
||||
fn visit_newtype_struct<D2>(self, deserializer: D2) -> Result<Self::Value, D2::Error>
|
||||
where
|
||||
D2: Deserializer<'de>,
|
||||
{
|
||||
self.0.visit_newtype_struct($wrapper(deserializer))
|
||||
}
|
||||
fn visit_seq<V>(self, seq: V) -> Result<D::Value, V::Error>
|
||||
where
|
||||
V: SeqAccess<'de>,
|
||||
{
|
||||
self.0.visit_seq($wrapper(seq))
|
||||
}
|
||||
fn visit_map<V>(self, map: V) -> Result<D::Value, V::Error>
|
||||
where
|
||||
V: MapAccess<'de>,
|
||||
{
|
||||
self.0.visit_map($wrapper(map))
|
||||
}
|
||||
fn visit_enum<V>(self, data: V) -> Result<D::Value, V::Error>
|
||||
where
|
||||
V: EnumAccess<'de>,
|
||||
{
|
||||
self.0.visit_enum($wrapper(data))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, D> SeqAccess<'de> for $wrapper<D>
|
||||
where
|
||||
D: SeqAccess<'de>,
|
||||
{
|
||||
type Error = D::Error;
|
||||
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, D::Error>
|
||||
where
|
||||
T: DeserializeSeed<'de>,
|
||||
{
|
||||
self.0.next_element_seed($wrapper(seed))
|
||||
}
|
||||
fn size_hint(&self) -> Option<usize> {
|
||||
self.0.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, D> MapAccess<'de> for $wrapper<D>
|
||||
where
|
||||
D: MapAccess<'de>,
|
||||
{
|
||||
type Error = D::Error;
|
||||
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, D::Error>
|
||||
where
|
||||
K: DeserializeSeed<'de>,
|
||||
{
|
||||
self.0.next_key_seed($wrapper(seed))
|
||||
}
|
||||
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, D::Error>
|
||||
where
|
||||
V: DeserializeSeed<'de>,
|
||||
{
|
||||
self.0.next_value_seed($wrapper(seed))
|
||||
}
|
||||
fn next_entry_seed<K, V>(
|
||||
&mut self,
|
||||
kseed: K,
|
||||
vseed: V,
|
||||
) -> Result<Option<(K::Value, V::Value)>, D::Error>
|
||||
where
|
||||
K: DeserializeSeed<'de>,
|
||||
V: DeserializeSeed<'de>,
|
||||
{
|
||||
self.0.next_entry_seed($wrapper(kseed), $wrapper(vseed))
|
||||
}
|
||||
fn size_hint(&self) -> Option<usize> {
|
||||
self.0.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, D> EnumAccess<'de> for $wrapper<D>
|
||||
where
|
||||
D: EnumAccess<'de>,
|
||||
{
|
||||
type Error = D::Error;
|
||||
type Variant = $wrapper<D::Variant>;
|
||||
fn variant_seed<V>(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<D>
|
||||
where
|
||||
D: VariantAccess<'de>,
|
||||
{
|
||||
type Error = D::Error;
|
||||
fn unit_variant(self) -> Result<(), D::Error> {
|
||||
self.0.unit_variant()
|
||||
}
|
||||
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, D::Error>
|
||||
where
|
||||
T: DeserializeSeed<'de>,
|
||||
{
|
||||
self.0.newtype_variant_seed($wrapper(seed))
|
||||
}
|
||||
fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value, D::Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
self.0.tuple_variant(len, $wrapper(visitor))
|
||||
}
|
||||
fn struct_variant<V>(
|
||||
self,
|
||||
fields: &'static [&'static str],
|
||||
visitor: V,
|
||||
) -> Result<V::Value, D::Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
self.0.struct_variant(fields, $wrapper(visitor))
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_deserializer!(Readable, true);
|
||||
impl_deserializer!(Compact, false);
|
683
serde_test/src/de.rs
Normal file
683
serde_test/src/de.rs
Normal file
@ -0,0 +1,683 @@
|
||||
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<Token> {
|
||||
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<Token> {
|
||||
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<V>(
|
||||
&mut self,
|
||||
len: Option<usize>,
|
||||
end: Token,
|
||||
visitor: V,
|
||||
) -> Result<V::Value, Error>
|
||||
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<V>(
|
||||
&mut self,
|
||||
len: Option<usize>,
|
||||
end: Token,
|
||||
visitor: V,
|
||||
) -> Result<V::Value, Error>
|
||||
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<V>(self, visitor: V) -> Result<V::Value, Error>
|
||||
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<V>(self, visitor: V) -> Result<V::Value, Error>
|
||||
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<V>(
|
||||
self,
|
||||
name: &'static str,
|
||||
_variants: &'static [&'static str],
|
||||
visitor: V,
|
||||
) -> Result<V::Value, Error>
|
||||
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<V>(self, name: &'static str, visitor: V) -> Result<V::Value, Error>
|
||||
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<V>(
|
||||
self,
|
||||
name: &'static str,
|
||||
visitor: V,
|
||||
) -> Result<V::Value, Error>
|
||||
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<V>(self, len: usize, visitor: V) -> Result<V::Value, Error>
|
||||
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<V>(
|
||||
self,
|
||||
name: &'static str,
|
||||
len: usize,
|
||||
visitor: V,
|
||||
) -> Result<V::Value, Error>
|
||||
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<V>(
|
||||
self,
|
||||
name: &'static str,
|
||||
fields: &'static [&'static str],
|
||||
visitor: V,
|
||||
) -> Result<V::Value, Error>
|
||||
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<usize>,
|
||||
end: Token,
|
||||
}
|
||||
|
||||
impl<'de, 'a> SeqAccess<'de> for DeserializerSeqVisitor<'a, 'de> {
|
||||
type Error = Error;
|
||||
|
||||
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, 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<usize> {
|
||||
self.len
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct DeserializerMapVisitor<'a, 'de: 'a> {
|
||||
de: &'a mut Deserializer<'de>,
|
||||
len: Option<usize>,
|
||||
end: Token,
|
||||
}
|
||||
|
||||
impl<'de, 'a> MapAccess<'de> for DeserializerMapVisitor<'a, 'de> {
|
||||
type Error = Error;
|
||||
|
||||
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, 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<V>(&mut self, seed: V) -> Result<V::Value, Error>
|
||||
where
|
||||
V: DeserializeSeed<'de>,
|
||||
{
|
||||
seed.deserialize(&mut *self.de)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> Option<usize> {
|
||||
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<V>(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<T>(self, seed: T) -> Result<T::Value, Self::Error>
|
||||
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<V>(self, len: usize, visitor: V) -> Result<V::Value, Error>
|
||||
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<V>(
|
||||
self,
|
||||
fields: &'static [&'static str],
|
||||
visitor: V,
|
||||
) -> Result<V::Value, Error>
|
||||
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<Token>,
|
||||
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<K>(&mut self, seed: K) -> Result<Option<K::Value>, 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<V>(&mut self, seed: V) -> Result<V::Value, Error>
|
||||
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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
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
|
||||
}
|
||||
}
|
43
serde_test/src/error.rs
Normal file
43
serde_test/src/error.rs
Normal file
@ -0,0 +1,43 @@
|
||||
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<T: Display>(msg: T) -> Self {
|
||||
Error {
|
||||
msg: msg.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl de::Error for Error {
|
||||
fn custom<T: Display>(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<str> for Error {
|
||||
fn eq(&self, other: &str) -> bool {
|
||||
self.msg == other
|
||||
}
|
||||
}
|
190
serde_test/src/lib.rs
Normal file
190
serde_test/src/lib.rs
Normal file
@ -0,0 +1,190 @@
|
||||
//! 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<K, V>(Vec<(K, V)>);
|
||||
//! #
|
||||
//! # impl<K, V> LinkedHashMap<K, V> {
|
||||
//! # fn new() -> Self {
|
||||
//! # LinkedHashMap(Vec::new())
|
||||
//! # }
|
||||
//! #
|
||||
//! # fn insert(&mut self, k: K, v: V) {
|
||||
//! # self.0.push((k, v));
|
||||
//! # }
|
||||
//! # }
|
||||
//! #
|
||||
//! # impl<K, V> Serialize for LinkedHashMap<K, V>
|
||||
//! # where
|
||||
//! # K: Serialize,
|
||||
//! # V: Serialize,
|
||||
//! # {
|
||||
//! # fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
//! # 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<K, V>(PhantomData<(K, V)>);
|
||||
//! #
|
||||
//! # impl<'de, K, V> Visitor<'de> for LinkedHashMapVisitor<K, V>
|
||||
//! # where
|
||||
//! # K: Deserialize<'de>,
|
||||
//! # V: Deserialize<'de>,
|
||||
//! # {
|
||||
//! # type Value = LinkedHashMap<K, V>;
|
||||
//! #
|
||||
//! # fn expecting(&self, _: &mut fmt::Formatter) -> fmt::Result {
|
||||
//! # unimplemented!()
|
||||
//! # }
|
||||
//! #
|
||||
//! # fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
|
||||
//! # 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<K, V>
|
||||
//! # where
|
||||
//! # K: Deserialize<'de>,
|
||||
//! # V: Deserialize<'de>,
|
||||
//! # {
|
||||
//! # fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
//! # 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::<char, u32>::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;
|
464
serde_test/src/ser.rs
Normal file
464
serde_test/src/ser.rs
Normal file
@ -0,0 +1,464 @@
|
||||
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<Token> {
|
||||
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<T: ?Sized>(self, name: &'static str, value: &T) -> Result<(), Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
assert_next_token!(self, NewtypeStruct { name });
|
||||
value.serialize(self)
|
||||
}
|
||||
|
||||
fn serialize_newtype_variant<T: ?Sized>(
|
||||
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<T: ?Sized>(self, value: &T) -> Result<(), Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
assert_next_token!(self, Some);
|
||||
value.serialize(self)
|
||||
}
|
||||
|
||||
fn serialize_seq(self, len: Option<usize>) -> Result<Self, Error> {
|
||||
assert_next_token!(self, Seq { len });
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn serialize_tuple(self, len: usize) -> Result<Self, Error> {
|
||||
assert_next_token!(self, Tuple { len });
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn serialize_tuple_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
|
||||
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<Self::SerializeTupleVariant, Error> {
|
||||
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<usize>) -> Result<Self, Error> {
|
||||
assert_next_token!(self, Map { len });
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
|
||||
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<Self::SerializeStructVariant, Error> {
|
||||
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<T: ?Sized>(&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<T: ?Sized>(&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<T: ?Sized>(&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<T: ?Sized>(&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<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
key.serialize(&mut **self)
|
||||
}
|
||||
|
||||
fn serialize_value<T: ?Sized>(&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<T: ?Sized>(
|
||||
&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<T: ?Sized>(
|
||||
&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(())
|
||||
}
|
||||
}
|
519
serde_test/src/token.rs
Normal file
519
serde_test/src/token.rs
Normal file
@ -0,0 +1,519 @@
|
||||
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<T>` containing none.
|
||||
///
|
||||
/// ```edition2018
|
||||
/// # use serde_test::{assert_tokens, Token};
|
||||
/// #
|
||||
/// let opt = None::<char>;
|
||||
/// assert_tokens(&opt, &[Token::None]);
|
||||
/// ```
|
||||
None,
|
||||
|
||||
/// The header to a serialized `Option<T>` 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<usize> },
|
||||
|
||||
/// 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<usize> },
|
||||
|
||||
/// 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)
|
||||
}
|
||||
}
|
@ -4,18 +4,23 @@ version = "0.0.0"
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
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"] }
|
||||
serde = { path = "../serde", features = ["rc", "derive"] }
|
||||
serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] }
|
||||
serde_test = "1.0.176"
|
||||
trybuild = { version = "1.0.66", features = ["diff"] }
|
||||
serde_test = { path = "../serde_test" }
|
||||
trybuild = { version = "1.0.49", features = ["diff"] }
|
||||
|
29
test_suite/build.rs
Normal file
29
test_suite/build.rs
Normal file
@ -0,0 +1,29 @@
|
||||
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");
|
||||
}
|
||||
}
|
@ -1,13 +1,11 @@
|
||||
[package]
|
||||
name = "serde_derive_tests_no_std"
|
||||
version = "0.0.0"
|
||||
authors = ["David Tolnay <dtolnay@gmail.com>"]
|
||||
edition = "2018"
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
libc = { version = "0.2", default-features = false }
|
||||
serde = { path = "../../serde", default-features = false }
|
||||
serde_derive = { path = "../../serde_derive" }
|
||||
serde = { path = "../../serde", default-features = false, features = ["derive"] }
|
||||
|
||||
[workspace]
|
||||
|
@ -1,4 +1,3 @@
|
||||
#![allow(internal_features)]
|
||||
#![feature(lang_items, start)]
|
||||
#![no_std]
|
||||
|
||||
@ -20,7 +19,7 @@ fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Unit;
|
||||
|
@ -1,7 +1,5 @@
|
||||
#[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();
|
||||
|
1426
test_suite/tests/expand/de_enum.expanded.rs
Normal file
1426
test_suite/tests/expand/de_enum.expanded.rs
Normal file
File diff suppressed because it is too large
Load Diff
13
test_suite/tests/expand/de_enum.rs
Normal file
13
test_suite/tests/expand/de_enum.rs
Normal file
@ -0,0 +1,13 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum DeEnum<B, C, D> {
|
||||
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 },
|
||||
}
|
410
test_suite/tests/expand/default_ty_param.expanded.rs
Normal file
410
test_suite/tests/expand/default_ty_param.expanded.rs
Normal file
@ -0,0 +1,410 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
trait AssociatedType {
|
||||
type X;
|
||||
}
|
||||
impl AssociatedType for i32 {
|
||||
type X = i32;
|
||||
}
|
||||
struct DefaultTyParam<T: AssociatedType<X = i32> = i32> {
|
||||
phantom: PhantomData<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<T: AssociatedType<X = i32>> _serde::Serialize for DefaultTyParam<T> {
|
||||
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<X = i32>> _serde::Deserialize<'de> for DefaultTyParam<T> {
|
||||
fn deserialize<__D>(__deserializer: __D) -> _serde::__private::Result<Self, __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<Self::Value, __E>
|
||||
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<Self::Value, __E>
|
||||
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<Self::Value, __E>
|
||||
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<Self, __D::Error>
|
||||
where
|
||||
__D: _serde::Deserializer<'de>,
|
||||
{
|
||||
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor)
|
||||
}
|
||||
}
|
||||
struct __Visitor<'de, T: AssociatedType<X = i32>> {
|
||||
marker: _serde::__private::PhantomData<DefaultTyParam<T>>,
|
||||
lifetime: _serde::__private::PhantomData<&'de ()>,
|
||||
}
|
||||
impl<'de, T: AssociatedType<X = i32>> _serde::de::Visitor<'de> for __Visitor<'de, T> {
|
||||
type Value = DefaultTyParam<T>;
|
||||
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<Self::Value, __A::Error>
|
||||
where
|
||||
__A: _serde::de::SeqAccess<'de>,
|
||||
{
|
||||
let __field0 = match match _serde::de::SeqAccess::next_element::<PhantomData<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 DefaultTyParam with 1 element",
|
||||
));
|
||||
}
|
||||
};
|
||||
_serde::__private::Ok(DefaultTyParam { phantom: __field0 })
|
||||
}
|
||||
#[inline]
|
||||
fn visit_map<__A>(
|
||||
self,
|
||||
mut __map: __A,
|
||||
) -> _serde::__private::Result<Self::Value, __A::Error>
|
||||
where
|
||||
__A: _serde::de::MapAccess<'de>,
|
||||
{
|
||||
let mut __field0: _serde::__private::Option<PhantomData<T>> =
|
||||
_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::<PhantomData<T>>(
|
||||
&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::<DefaultTyParam<T>>,
|
||||
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<Self::Value, __E>
|
||||
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<Self::Value, __E>
|
||||
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<Self::Value, __E>
|
||||
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<Self, __D::Error>
|
||||
where
|
||||
__D: _serde::Deserializer<'de>,
|
||||
{
|
||||
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor)
|
||||
}
|
||||
}
|
||||
struct __Visitor<'de, 'place, T: AssociatedType<X = i32> + 'place> {
|
||||
place: &'place mut DefaultTyParam<T>,
|
||||
lifetime: _serde::__private::PhantomData<&'de ()>,
|
||||
}
|
||||
impl<'de, 'place, T: AssociatedType<X = i32> + '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<Self::Value, __A::Error>
|
||||
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<Self::Value, __A::Error>
|
||||
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,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
};
|
14
test_suite/tests/expand/default_ty_param.rs
Normal file
14
test_suite/tests/expand/default_ty_param.rs
Normal file
@ -0,0 +1,14 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
trait AssociatedType {
|
||||
type X;
|
||||
}
|
||||
|
||||
impl AssociatedType for i32 {
|
||||
type X = i32;
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct DefaultTyParam<T: AssociatedType<X = i32> = i32> {
|
||||
phantom: PhantomData<T>,
|
||||
}
|
590
test_suite/tests/expand/generic_enum.expanded.rs
Normal file
590
test_suite/tests/expand/generic_enum.expanded.rs
Normal file
@ -0,0 +1,590 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
pub enum GenericEnum<T, U> {
|
||||
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<T, U> _serde::Serialize for GenericEnum<T, U>
|
||||
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<T, U>
|
||||
where
|
||||
T: _serde::Deserialize<'de>,
|
||||
U: _serde::Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<__D>(__deserializer: __D) -> _serde::__private::Result<Self, __D::Error>
|
||||
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<Self::Value, __E>
|
||||
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<Self::Value, __E>
|
||||
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<Self::Value, __E>
|
||||
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<Self, __D::Error>
|
||||
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<GenericEnum<T, U>>,
|
||||
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<T, U>;
|
||||
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<Self::Value, __A::Error>
|
||||
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::<T>(__variant),
|
||||
GenericEnum::NewType,
|
||||
),
|
||||
(__Field::__field2, __variant) => {
|
||||
struct __Visitor<'de, T, U>
|
||||
where
|
||||
T: _serde::Deserialize<'de>,
|
||||
U: _serde::Deserialize<'de>,
|
||||
{
|
||||
marker: _serde::__private::PhantomData<GenericEnum<T, U>>,
|
||||
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<T, U>;
|
||||
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<Self::Value, __A::Error>
|
||||
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::<GenericEnum<T, U>>,
|
||||
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<Self::Value, __E>
|
||||
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<Self::Value, __E>
|
||||
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<Self::Value, __E>
|
||||
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<Self, __D::Error>
|
||||
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<GenericEnum<T, U>>,
|
||||
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<T, U>;
|
||||
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<Self::Value, __A::Error>
|
||||
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<Self::Value, __A::Error>
|
||||
where
|
||||
__A: _serde::de::MapAccess<'de>,
|
||||
{
|
||||
let mut __field0: _serde::__private::Option<T> =
|
||||
_serde::__private::None;
|
||||
let mut __field1: _serde::__private::Option<U> =
|
||||
_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::<T>(
|
||||
&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::<U>(
|
||||
&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::<GenericEnum<T, U>>,
|
||||
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::<GenericEnum<T, U>>,
|
||||
lifetime: _serde::__private::PhantomData,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
};
|
9
test_suite/tests/expand/generic_enum.rs
Normal file
9
test_suite/tests/expand/generic_enum.rs
Normal file
@ -0,0 +1,9 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub enum GenericEnum<T, U> {
|
||||
Unit,
|
||||
NewType(T),
|
||||
Seq(T, U),
|
||||
Map { x: T, y: U },
|
||||
}
|
594
test_suite/tests/expand/generic_struct.expanded.rs
Normal file
594
test_suite/tests/expand/generic_struct.expanded.rs
Normal file
@ -0,0 +1,594 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
pub struct GenericStruct<T> {
|
||||
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<T> _serde::Serialize for GenericStruct<T>
|
||||
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<T>
|
||||
where
|
||||
T: _serde::Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<__D>(__deserializer: __D) -> _serde::__private::Result<Self, __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<Self::Value, __E>
|
||||
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<Self::Value, __E>
|
||||
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<Self::Value, __E>
|
||||
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<Self, __D::Error>
|
||||
where
|
||||
__D: _serde::Deserializer<'de>,
|
||||
{
|
||||
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor)
|
||||
}
|
||||
}
|
||||
struct __Visitor<'de, T>
|
||||
where
|
||||
T: _serde::Deserialize<'de>,
|
||||
{
|
||||
marker: _serde::__private::PhantomData<GenericStruct<T>>,
|
||||
lifetime: _serde::__private::PhantomData<&'de ()>,
|
||||
}
|
||||
impl<'de, T> _serde::de::Visitor<'de> for __Visitor<'de, T>
|
||||
where
|
||||
T: _serde::Deserialize<'de>,
|
||||
{
|
||||
type Value = GenericStruct<T>;
|
||||
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<Self::Value, __A::Error>
|
||||
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 GenericStruct with 1 element",
|
||||
));
|
||||
}
|
||||
};
|
||||
_serde::__private::Ok(GenericStruct { x: __field0 })
|
||||
}
|
||||
#[inline]
|
||||
fn visit_map<__A>(
|
||||
self,
|
||||
mut __map: __A,
|
||||
) -> _serde::__private::Result<Self::Value, __A::Error>
|
||||
where
|
||||
__A: _serde::de::MapAccess<'de>,
|
||||
{
|
||||
let mut __field0: _serde::__private::Option<T> = _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::<T>(&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::<GenericStruct<T>>,
|
||||
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<Self::Value, __E>
|
||||
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<Self::Value, __E>
|
||||
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<Self::Value, __E>
|
||||
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<Self, __D::Error>
|
||||
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<T>,
|
||||
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<Self::Value, __A::Error>
|
||||
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<Self::Value, __A::Error>
|
||||
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>(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<T> _serde::Serialize for GenericNewTypeStruct<T>
|
||||
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<T>
|
||||
where
|
||||
T: _serde::Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<__D>(__deserializer: __D) -> _serde::__private::Result<Self, __D::Error>
|
||||
where
|
||||
__D: _serde::Deserializer<'de>,
|
||||
{
|
||||
struct __Visitor<'de, T>
|
||||
where
|
||||
T: _serde::Deserialize<'de>,
|
||||
{
|
||||
marker: _serde::__private::PhantomData<GenericNewTypeStruct<T>>,
|
||||
lifetime: _serde::__private::PhantomData<&'de ()>,
|
||||
}
|
||||
impl<'de, T> _serde::de::Visitor<'de> for __Visitor<'de, T>
|
||||
where
|
||||
T: _serde::Deserialize<'de>,
|
||||
{
|
||||
type Value = GenericNewTypeStruct<T>;
|
||||
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<Self::Value, __E::Error>
|
||||
where
|
||||
__E: _serde::Deserializer<'de>,
|
||||
{
|
||||
let __field0: T = match <T as _serde::Deserialize>::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<Self::Value, __A::Error>
|
||||
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 struct GenericNewTypeStruct with 1 element",
|
||||
));
|
||||
}
|
||||
};
|
||||
_serde::__private::Ok(GenericNewTypeStruct(__field0))
|
||||
}
|
||||
}
|
||||
_serde::Deserializer::deserialize_newtype_struct(
|
||||
__deserializer,
|
||||
"GenericNewTypeStruct",
|
||||
__Visitor {
|
||||
marker: _serde::__private::PhantomData::<GenericNewTypeStruct<T>>,
|
||||
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<T>,
|
||||
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<Self::Value, __E::Error>
|
||||
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<Self::Value, __A::Error>
|
||||
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,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
};
|
9
test_suite/tests/expand/generic_struct.rs
Normal file
9
test_suite/tests/expand/generic_struct.rs
Normal file
@ -0,0 +1,9 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct GenericStruct<T> {
|
||||
x: T,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct GenericNewTypeStruct<T>(T);
|
172
test_suite/tests/expand/generic_tuple_struct.expanded.rs
Normal file
172
test_suite/tests/expand/generic_tuple_struct.expanded.rs
Normal file
@ -0,0 +1,172 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
pub struct GenericTupleStruct<T, U>(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<T, U>
|
||||
where
|
||||
T: _serde::Deserialize<'de>,
|
||||
U: _serde::Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<__D>(__deserializer: __D) -> _serde::__private::Result<Self, __D::Error>
|
||||
where
|
||||
__D: _serde::Deserializer<'de>,
|
||||
{
|
||||
struct __Visitor<'de, T, U>
|
||||
where
|
||||
T: _serde::Deserialize<'de>,
|
||||
U: _serde::Deserialize<'de>,
|
||||
{
|
||||
marker: _serde::__private::PhantomData<GenericTupleStruct<T, U>>,
|
||||
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<T, U>;
|
||||
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<Self::Value, __A::Error>
|
||||
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 struct GenericTupleStruct 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 struct GenericTupleStruct with 2 elements",
|
||||
));
|
||||
}
|
||||
};
|
||||
_serde::__private::Ok(GenericTupleStruct(__field0, __field1))
|
||||
}
|
||||
}
|
||||
_serde::Deserializer::deserialize_tuple_struct(
|
||||
__deserializer,
|
||||
"GenericTupleStruct",
|
||||
2usize,
|
||||
__Visitor {
|
||||
marker: _serde::__private::PhantomData::<GenericTupleStruct<T, U>>,
|
||||
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<T, U>,
|
||||
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<Self::Value, __A::Error>
|
||||
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,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
};
|
4
test_suite/tests/expand/generic_tuple_struct.rs
Normal file
4
test_suite/tests/expand/generic_tuple_struct.rs
Normal file
@ -0,0 +1,4 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct GenericTupleStruct<T, U>(T, U);
|
607
test_suite/tests/expand/lifetimes.expanded.rs
Normal file
607
test_suite/tests/expand/lifetimes.expanded.rs
Normal file
@ -0,0 +1,607 @@
|
||||
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<Self, __D::Error>
|
||||
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<Self::Value, __E>
|
||||
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<Self::Value, __E>
|
||||
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<Self::Value, __E>
|
||||
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<Self, __D::Error>
|
||||
where
|
||||
__D: _serde::Deserializer<'de>,
|
||||
{
|
||||
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor)
|
||||
}
|
||||
}
|
||||
struct __Visitor<'de, 'a> {
|
||||
marker: _serde::__private::PhantomData<Lifetimes<'a>>,
|
||||
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<Self::Value, __A::Error>
|
||||
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::<i32>(__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<Self::Value, __E>
|
||||
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<Self::Value, __E>
|
||||
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<Self::Value, __E>
|
||||
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<Self, __D::Error>
|
||||
where
|
||||
__D: _serde::Deserializer<'de>,
|
||||
{
|
||||
_serde::Deserializer::deserialize_identifier(
|
||||
__deserializer,
|
||||
__FieldVisitor,
|
||||
)
|
||||
}
|
||||
}
|
||||
struct __Visitor<'de, 'a> {
|
||||
marker: _serde::__private::PhantomData<Lifetimes<'a>>,
|
||||
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<Self::Value, __A::Error>
|
||||
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<Self::Value, __A::Error>
|
||||
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::<Lifetimes<'a>>,
|
||||
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<Self::Value, __E>
|
||||
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<Self::Value, __E>
|
||||
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<Self::Value, __E>
|
||||
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<Self, __D::Error>
|
||||
where
|
||||
__D: _serde::Deserializer<'de>,
|
||||
{
|
||||
_serde::Deserializer::deserialize_identifier(
|
||||
__deserializer,
|
||||
__FieldVisitor,
|
||||
)
|
||||
}
|
||||
}
|
||||
struct __Visitor<'de, 'a> {
|
||||
marker: _serde::__private::PhantomData<Lifetimes<'a>>,
|
||||
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<Self::Value, __A::Error>
|
||||
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<Self::Value, __A::Error>
|
||||
where
|
||||
__A: _serde::de::MapAccess<'de>,
|
||||
{
|
||||
let mut __field0: _serde::__private::Option<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::<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::NoLifetimeMap { a: __field0 })
|
||||
}
|
||||
}
|
||||
const FIELDS: &'static [&'static str] = &["a"];
|
||||
_serde::de::VariantAccess::struct_variant(
|
||||
__variant,
|
||||
FIELDS,
|
||||
__Visitor {
|
||||
marker: _serde::__private::PhantomData::<Lifetimes<'a>>,
|
||||
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::<Lifetimes<'a>>,
|
||||
lifetime: _serde::__private::PhantomData,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
};
|
9
test_suite/tests/expand/lifetimes.rs
Normal file
9
test_suite/tests/expand/lifetimes.rs
Normal file
@ -0,0 +1,9 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum Lifetimes<'a> {
|
||||
LifetimeSeq(&'a i32),
|
||||
NoLifetimeSeq(i32),
|
||||
LifetimeMap { a: &'a i32 },
|
||||
NoLifetimeMap { a: i32 },
|
||||
}
|
628
test_suite/tests/expand/named_map.expanded.rs
Normal file
628
test_suite/tests/expand/named_map.expanded.rs
Normal file
@ -0,0 +1,628 @@
|
||||
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, B, C> {
|
||||
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<A, B, C>
|
||||
where
|
||||
A: _serde::Deserialize<'de>,
|
||||
B: _serde::Deserialize<'de>,
|
||||
C: _serde::Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<__D>(__deserializer: __D) -> _serde::__private::Result<Self, __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<Self::Value, __E>
|
||||
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<Self::Value, __E>
|
||||
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<Self::Value, __E>
|
||||
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<Self, __D::Error>
|
||||
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<DeNamedMap<A, B, C>>,
|
||||
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<A, B, C>;
|
||||
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<Self::Value, __A::Error>
|
||||
where
|
||||
__A: _serde::de::SeqAccess<'de>,
|
||||
{
|
||||
let __field0 = match match _serde::de::SeqAccess::next_element::<A>(&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::<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 DeNamedMap with 3 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 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<Self::Value, __A::Error>
|
||||
where
|
||||
__A: _serde::de::MapAccess<'de>,
|
||||
{
|
||||
let mut __field0: _serde::__private::Option<A> = _serde::__private::None;
|
||||
let mut __field1: _serde::__private::Option<B> = _serde::__private::None;
|
||||
let mut __field2: _serde::__private::Option<C> = _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>(&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::<B>(&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::<C>(&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::<DeNamedMap<A, B, C>>,
|
||||
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<Self::Value, __E>
|
||||
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<Self::Value, __E>
|
||||
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<Self::Value, __E>
|
||||
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<Self, __D::Error>
|
||||
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<A, B, C>,
|
||||
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<Self::Value, __A::Error>
|
||||
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<Self::Value, __A::Error>
|
||||
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,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
};
|
15
test_suite/tests/expand/named_map.rs
Normal file
15
test_suite/tests/expand/named_map.rs
Normal file
@ -0,0 +1,15 @@
|
||||
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, B, C> {
|
||||
a: A,
|
||||
b: B,
|
||||
c: C,
|
||||
}
|
259
test_suite/tests/expand/named_tuple.expanded.rs
Normal file
259
test_suite/tests/expand/named_tuple.expanded.rs
Normal file
@ -0,0 +1,259 @@
|
||||
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>(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<A, B, C>
|
||||
where
|
||||
A: _serde::Deserialize<'de>,
|
||||
B: _serde::Deserialize<'de>,
|
||||
C: _serde::Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<__D>(__deserializer: __D) -> _serde::__private::Result<Self, __D::Error>
|
||||
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<DeNamedTuple<A, B, C>>,
|
||||
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<A, B, C>;
|
||||
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<Self::Value, __A::Error>
|
||||
where
|
||||
__A: _serde::de::SeqAccess<'de>,
|
||||
{
|
||||
let __field0 = match match _serde::de::SeqAccess::next_element::<A>(&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::<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 struct DeNamedTuple with 3 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 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::<DeNamedTuple<A, B, C>>,
|
||||
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<A, B, C>,
|
||||
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<Self::Value, __A::Error>
|
||||
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,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
};
|
7
test_suite/tests/expand/named_tuple.rs
Normal file
7
test_suite/tests/expand/named_tuple.rs
Normal file
@ -0,0 +1,7 @@
|
||||
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>(A, B, C);
|
52
test_suite/tests/expand/named_unit.expanded.rs
Normal file
52
test_suite/tests/expand/named_unit.expanded.rs
Normal file
@ -0,0 +1,52 @@
|
||||
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<Self, __D::Error>
|
||||
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<Self::Value, __E>
|
||||
where
|
||||
__E: _serde::de::Error,
|
||||
{
|
||||
_serde::__private::Ok(NamedUnit)
|
||||
}
|
||||
}
|
||||
_serde::Deserializer::deserialize_unit_struct(__deserializer, "NamedUnit", __Visitor)
|
||||
}
|
||||
}
|
||||
};
|
4
test_suite/tests/expand/named_unit.rs
Normal file
4
test_suite/tests/expand/named_unit.rs
Normal file
@ -0,0 +1,4 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct NamedUnit;
|
271
test_suite/tests/expand/ser_enum.expanded.rs
Normal file
271
test_suite/tests/expand/ser_enum.expanded.rs
Normal file
@ -0,0 +1,271 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
16
test_suite/tests/expand/ser_enum.rs
Normal file
16
test_suite/tests/expand/ser_enum.rs
Normal file
@ -0,0 +1,16 @@
|
||||
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 },
|
||||
}
|
132
test_suite/tests/expand/void.expanded.rs
Normal file
132
test_suite/tests/expand/void.expanded.rs
Normal file
@ -0,0 +1,132 @@
|
||||
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<Self, __D::Error>
|
||||
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<Self::Value, __E>
|
||||
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<Self::Value, __E>
|
||||
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<Self::Value, __E>
|
||||
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<Self, __D::Error>
|
||||
where
|
||||
__D: _serde::Deserializer<'de>,
|
||||
{
|
||||
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor)
|
||||
}
|
||||
}
|
||||
struct __Visitor<'de> {
|
||||
marker: _serde::__private::PhantomData<Void>,
|
||||
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<Self::Value, __A::Error>
|
||||
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::<Void>,
|
||||
lifetime: _serde::__private::PhantomData,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
};
|
4
test_suite/tests/expand/void.rs
Normal file
4
test_suite/tests/expand/void.rs
Normal file
@ -0,0 +1,4 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum Void {}
|
8
test_suite/tests/expandtest.rs
Normal file
8
test_suite/tests/expandtest.rs
Normal file
@ -0,0 +1,8 @@
|
||||
#[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");
|
||||
}
|
@ -1,5 +1,3 @@
|
||||
#![allow(unused_macro_rules)]
|
||||
|
||||
use serde_test::Token;
|
||||
use std::iter;
|
||||
|
||||
|
@ -1,3 +0,0 @@
|
||||
mod regression {
|
||||
automod::dir!("tests/regression");
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
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,
|
||||
},
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
use serde_derive::Deserialize;
|
||||
|
||||
macro_rules! bug {
|
||||
($serde_path:literal) => {
|
||||
#[derive(Deserialize)]
|
||||
#[serde(crate = $serde_path)]
|
||||
pub struct Struct;
|
||||
};
|
||||
}
|
||||
|
||||
bug!("serde");
|
@ -1,5 +0,0 @@
|
||||
use serde_derive::Serialize;
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde()]
|
||||
pub struct S;
|
File diff suppressed because it is too large
Load Diff
@ -1,13 +1,8 @@
|
||||
#![allow(
|
||||
clippy::derive_partial_eq_without_eq,
|
||||
clippy::items_after_statements,
|
||||
clippy::used_underscore_binding
|
||||
)]
|
||||
#![allow(clippy::items_after_statements, clippy::used_underscore_binding)]
|
||||
|
||||
use serde::de::value::{BorrowedStrDeserializer, MapDeserializer};
|
||||
use serde::de::{Deserialize, Deserializer, IntoDeserializer};
|
||||
use serde_derive::Deserialize;
|
||||
use serde::{Deserialize, Deserializer};
|
||||
use serde_test::{assert_de_tokens, assert_de_tokens_error, Token};
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
||||
#[test]
|
||||
@ -131,22 +126,20 @@ fn test_cow() {
|
||||
borrowed: Cow<'b, str>,
|
||||
}
|
||||
|
||||
struct BorrowedStr(&'static str);
|
||||
let tokens = &[
|
||||
Token::Struct {
|
||||
name: "Cows",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("copied"),
|
||||
Token::BorrowedStr("copied"),
|
||||
Token::Str("borrowed"),
|
||||
Token::BorrowedStr("borrowed"),
|
||||
Token::StructEnd,
|
||||
];
|
||||
|
||||
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();
|
||||
let mut de = serde_test::Deserializer::new(tokens);
|
||||
let cows = Cows::deserialize(&mut de).unwrap();
|
||||
|
||||
match cows.copied {
|
||||
Cow::Owned(ref s) if s == "copied" => {}
|
||||
|
@ -1,25 +1,17 @@
|
||||
#![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,
|
||||
@ -32,11 +24,17 @@ use std::sync::atomic::{
|
||||
AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8,
|
||||
AtomicUsize, Ordering,
|
||||
};
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use std::sync::atomic::{AtomicI64, AtomicU64};
|
||||
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};
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
@ -45,9 +43,6 @@ mod macros;
|
||||
#[derive(Copy, Clone, PartialEq, Debug, Deserialize)]
|
||||
struct UnitStruct;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Debug, Deserialize)]
|
||||
struct GenericUnitStruct<const N: u8>;
|
||||
|
||||
#[derive(PartialEq, Debug, Deserialize)]
|
||||
struct NewtypeStruct(i32);
|
||||
|
||||
@ -202,11 +197,12 @@ fn assert_de_tokens_ignore(ignorable_tokens: &[Token]) {
|
||||
]
|
||||
.into_iter()
|
||||
.chain(ignorable_tokens.iter().copied())
|
||||
.chain(iter::once(Token::MapEnd))
|
||||
.chain(vec![Token::MapEnd].into_iter())
|
||||
.collect();
|
||||
|
||||
let expected = IgnoreBase { a: 1 };
|
||||
assert_de_tokens(&expected, &concated_tokens);
|
||||
let mut de = serde_test::Deserializer::new(&concated_tokens);
|
||||
let base = IgnoreBase::deserialize(&mut de).unwrap();
|
||||
assert_eq!(base, IgnoreBase { a: 1 });
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@ -833,26 +829,6 @@ fn test_f64() {
|
||||
test(1.11, &[Token::F64(1.11)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nan() {
|
||||
let f32_deserializer = F32Deserializer::<serde::de::value::Error>::new;
|
||||
let f64_deserializer = F64Deserializer::<serde::de::value::Error>::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')]);
|
||||
@ -905,17 +881,6 @@ 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(
|
||||
@ -1898,46 +1863,6 @@ 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(
|
||||
@ -2318,34 +2243,39 @@ fn test_cstr() {
|
||||
|
||||
#[test]
|
||||
fn test_atomics() {
|
||||
fn test<L, A, T>(load: L, val: T)
|
||||
fn test<L, A, T>(load: L, val: T, token: Token)
|
||||
where
|
||||
L: Fn(&A, Ordering) -> T,
|
||||
A: DeserializeOwned,
|
||||
T: PartialEq + Debug + Copy + for<'de> IntoDeserializer<'de>,
|
||||
T: PartialEq + Debug,
|
||||
{
|
||||
match A::deserialize(val.into_deserializer()) {
|
||||
let tokens = &[token];
|
||||
let mut de = serde_test::Deserializer::new(tokens);
|
||||
match A::deserialize(&mut de) {
|
||||
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);
|
||||
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);
|
||||
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));
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
{
|
||||
test(AtomicI64::load, -8589934592i64);
|
||||
test(AtomicU64::load, 8589934592u64);
|
||||
test(AtomicI64::load, -8589934592, Token::I64(-8589934592));
|
||||
test(AtomicU64::load, 8589934592u64, Token::U64(8589934592));
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user