mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-04-22 21:48:02 +00:00
Compare commits
208 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 026e91a68c | |||
| bfbedac919 | |||
| 4036ff88ed | |||
| 1b4da41f97 | |||
| f61d452814 | |||
| f9866097a0 | |||
| 77a6a9d4e1 | |||
| 547d843cca | |||
| 005cb84593 | |||
| fd5b5e9aa5 | |||
| 0647a7c1fe | |||
| 85c73ef8de | |||
| 5ba1796a7e | |||
| e52b7b380f | |||
| 84c7419652 | |||
| 536221b1f9 | |||
| fc55ac70d3 | |||
| 2afe5b4ef9 | |||
| b4ec2595c9 | |||
| c3ac7b675a | |||
| 24614e44bf | |||
| 9b868ef831 | |||
| c3eaf76430 | |||
| 32958dec3b | |||
| d64a97ba1e | |||
| c3df3372a1 | |||
| 8764353fe2 | |||
| e08c5de5dd | |||
| bc5af506bd | |||
| 28a092261b | |||
| 18dcae0a77 | |||
| 58c307f9cc | |||
| 8cc4809414 | |||
| 1179158def | |||
| 91aa40e749 | |||
| 595019e979 | |||
| b0d7917f88 | |||
| 8e6637a1e4 | |||
| 694fe05953 | |||
| f3dfd2a237 | |||
| 9e6158e9e6 | |||
| d577c4a2ce | |||
| fee0b82a40 | |||
| 7aafa26314 | |||
| d5bc546ca5 | |||
| 45ae217728 | |||
| b7b97dda73 | |||
| 5d3c563d46 | |||
| 376185458b | |||
| a8f14840ab | |||
| 9e32a40b1c | |||
| 87f635e54d | |||
| d4b2dfbde2 | |||
| f6ab0bc56f | |||
| 48cc2a6327 | |||
| 3202a6858a | |||
| b4f1bc16ff | |||
| 029ab46f71 | |||
| 220ca0ca9d | |||
| 20306f493a | |||
| cc865ac523 | |||
| 2d973c1805 | |||
| 6ca499b2dd | |||
| 1477028717 | |||
| 789740be0d | |||
| 8fe7539bb2 | |||
| f6623a3654 | |||
| c4fb923335 | |||
| 65b7eea775 | |||
| 01cd696fd1 | |||
| c13b3f7e68 | |||
| a6571ee0da | |||
| 6e38afff49 | |||
| 3d1b19ed90 | |||
| 5b24f88e73 | |||
| 74d06708dd | |||
| 3bfab6ef7f | |||
| 364cd8d8f7 | |||
| 9f8c579bf5 | |||
| eae7c2d684 | |||
| 3f43fca90d | |||
| 76449488ca | |||
| 00c4b0cef8 | |||
| 89139e2c11 | |||
| c9cab490f7 | |||
| 5fa711d75d | |||
| f5d8ae423a | |||
| 1d54973b92 | |||
| b8fafefd85 | |||
| c42ebb8839 | |||
| 9e680620b5 | |||
| 846f865de2 | |||
| ede9762a58 | |||
| d438c2d67b | |||
| bef110b92a | |||
| b971ef11d1 | |||
| 29d9f69399 | |||
| aecb4083bd | |||
| 1c675ab3a3 | |||
| dd619630a3 | |||
| 111803ab07 | |||
| 0024f74f34 | |||
| 03eec42c33 | |||
| 196f311ae2 | |||
| 38d9e0b209 | |||
| 6502b31316 | |||
| 6f1a8c3115 | |||
| d883c94cc9 | |||
| 961fa59a74 | |||
| 8bc71def55 | |||
| 7c65a9dc0e | |||
| d2d977a6c6 | |||
| a9a6ee9d7f | |||
| 28c5d215c1 | |||
| 3d6a789562 | |||
| a0e68698e3 | |||
| 44613c7d01 | |||
| c706281df3 | |||
| 65d75b8fe3 | |||
| 332b0cba40 | |||
| 8c4af41296 | |||
| 24a78f071b | |||
| c91c33436d | |||
| 2083f43a28 | |||
| 4676abdc9e | |||
| 35700eb23e | |||
| 59892e7b58 | |||
| 97dd07a7d1 | |||
| c8bc97c81b | |||
| 9dacfbbd69 | |||
| 05c2509d07 | |||
| 64f949b37b | |||
| 3f339de36a | |||
| 215c2b71ef | |||
| ce8fef7e0b | |||
| 0726b2c479 | |||
| 589549d7e6 | |||
| edb1a586d8 | |||
| 11c2917040 | |||
| 6ba9c12ff6 | |||
| d2fcc346b9 | |||
| a091a07aa2 | |||
| bb4135cae8 | |||
| 8de84b7ca3 | |||
| 9cdf332029 | |||
| e94fc65f01 | |||
| b908487476 | |||
| 2a7c7faeb4 | |||
| e302e15eea | |||
| 1cbea892cf | |||
| 37a32857a2 | |||
| 8c4aad3a59 | |||
| 1774794b19 | |||
| 1af23f1f2d | |||
| 94fbc3d388 | |||
| 8da2058e2a | |||
| 09993a904a | |||
| 5d1403461c | |||
| ddc1ee564b | |||
| 00a54b848a | |||
| dad15b9fd0 | |||
| d89c19f903 | |||
| 146dc0fad5 | |||
| d26852deef | |||
| e1c27243b2 | |||
| dbbfe7abe2 | |||
| dc24d12ce0 | |||
| 4e7533e872 | |||
| 5d036515ed | |||
| a741293886 | |||
| f8d0b26d2f | |||
| 7007c1bea5 | |||
| 0d8ebac7e1 | |||
| 212c42c74f | |||
| 919f6be887 | |||
| c0f70428ba | |||
| e797c90ebd | |||
| fc04d1219a | |||
| df4ad5884d | |||
| 3c7dd6fc1e | |||
| 8b196ea1c8 | |||
| 1f8c8ad5a3 | |||
| 870925d503 | |||
| d593215ef7 | |||
| 110af31b48 | |||
| 360606b9a6 | |||
| 151b45ae36 | |||
| 2ea7e1300f | |||
| 4617c957b9 | |||
| 2547ed83ca | |||
| bfcd44704f | |||
| 7b548db91e | |||
| d39dea85ad | |||
| 5e56c9fba8 | |||
| 8d3a03288b | |||
| cb490ec16d | |||
| 45271c3676 | |||
| 6a097eca93 | |||
| 84d1c5385d | |||
| 05a5b7e3c6 | |||
| 3bff326fb3 | |||
| aaadd93878 | |||
| 9c864f0b02 | |||
| 070cce0d9c | |||
| b58e8bac12 | |||
| ada50b077e | |||
| 5e313a7330 | |||
| 2a36d11238 |
+29
-44
@@ -18,7 +18,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@nightly
|
||||
- run: cd test_suite && cargo test --features unstable
|
||||
|
||||
@@ -27,7 +27,7 @@ jobs:
|
||||
runs-on: windows-latest
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@nightly
|
||||
- run: cd test_suite && cargo test --features unstable -- --skip ui --exact
|
||||
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
rust: [stable, beta]
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@master
|
||||
with:
|
||||
toolchain: ${{matrix.rust}}
|
||||
@@ -56,7 +56,7 @@ jobs:
|
||||
os: [ubuntu, windows]
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@nightly
|
||||
- run: cd serde && cargo build
|
||||
- run: cd serde && cargo build --no-default-features
|
||||
@@ -80,10 +80,11 @@ jobs:
|
||||
rust: [1.31.0, 1.34.0]
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@master
|
||||
with:
|
||||
toolchain: ${{matrix.rust}}
|
||||
- run: sed -i '/"test_suite"/d' Cargo.toml
|
||||
- run: cd serde && cargo build --features rc
|
||||
- run: cd serde && cargo build --no-default-features
|
||||
- run: cd serde && cargo build
|
||||
@@ -93,71 +94,54 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@1.56.0
|
||||
- run: sed -i '/"test_suite"/d' Cargo.toml
|
||||
- run: cd serde && cargo check --no-default-features
|
||||
- run: cd serde && cargo check
|
||||
- run: cd serde_derive && cargo check
|
||||
- run: cd precompiled/serde_derive && cargo check
|
||||
|
||||
alloc:
|
||||
name: Rust 1.36.0
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@1.36.0
|
||||
- run: sed -i '/"test_suite"/d' Cargo.toml
|
||||
- run: cd serde && cargo build --no-default-features --features alloc
|
||||
|
||||
precompiled:
|
||||
name: Precompiled
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dtolnay/rust-toolchain@nightly
|
||||
with:
|
||||
components: rust-src
|
||||
targets: x86_64-unknown-linux-musl
|
||||
- run: precompiled/build.sh
|
||||
- name: replace serde_derive dependency with precompiled
|
||||
run: |
|
||||
# FIXME: consider using `cargo rm serde_derive` but it's currently broken
|
||||
# https://github.com/rust-lang/cargo/issues/12419
|
||||
sed -i '/serde_derive =/d' serde/Cargo.toml
|
||||
sed -i '/derive = \["serde_derive"\]/d' serde/Cargo.toml
|
||||
sed -i '/"serde_derive"/d' Cargo.toml
|
||||
sed -i '/\[workspace\]/d' precompiled/serde_derive/Cargo.toml
|
||||
cargo add --dev serde_derive --path precompiled/serde_derive --manifest-path test_suite/Cargo.toml
|
||||
git diff
|
||||
- run: cd test_suite && cargo test --features unstable -- --skip ui --exact
|
||||
|
||||
macos:
|
||||
name: macOS
|
||||
runs-on: macos-latest
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- run: cd precompiled/serde_derive && cargo check
|
||||
|
||||
minimal:
|
||||
name: Minimal versions
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- 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
|
||||
|
||||
clippy:
|
||||
name: Clippy
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name != 'pull_request'
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@clippy
|
||||
- run: cd serde && cargo clippy --features rc,unstable -- -Dclippy::all -Dclippy::pedantic
|
||||
- run: cd serde_derive && cargo clippy -- -Dclippy::all -Dclippy::pedantic
|
||||
@@ -170,7 +154,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@miri
|
||||
- run: cargo miri setup
|
||||
- run: cd serde && cargo miri test --features derive,rc,unstable
|
||||
@@ -186,6 +170,7 @@ jobs:
|
||||
if: github.event_name != 'pull_request'
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- uses: dtolnay/install@cargo-outdated
|
||||
- run: cargo outdated --workspace --exit-code 1
|
||||
|
||||
@@ -8,3 +8,8 @@ members = [
|
||||
|
||||
[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 }
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Serde   [![Build Status]][actions] [![Latest Version]][crates.io] [![serde: rustc 1.31+]][Rust 1.31] [![serde_derive: rustc 1.56+]][Rust 1.56]
|
||||
# Serde   [![Build Status]][actions] [![Latest Version]][crates.io] [![serde msrv]][Rust 1.31] [![serde_derive msrv]][Rust 1.56]
|
||||
|
||||
[Build Status]: https://img.shields.io/github/actions/workflow/status/serde-rs/serde/ci.yml?branch=master
|
||||
[actions]: https://github.com/serde-rs/serde/actions?query=branch%3Amaster
|
||||
[Latest Version]: https://img.shields.io/crates/v/serde.svg
|
||||
[crates.io]: https://crates.io/crates/serde
|
||||
[serde: rustc 1.31+]: https://img.shields.io/badge/serde-rustc_1.31+-lightgray.svg
|
||||
[serde_derive: rustc 1.56+]: https://img.shields.io/badge/serde_derive-rustc_1.56+-lightgray.svg
|
||||
[serde msrv]: https://img.shields.io/crates/msrv/serde.svg?label=serde%20msrv&color=lightgray
|
||||
[serde_derive msrv]: https://img.shields.io/crates/msrv/serde_derive.svg?label=serde_derive%20msrv&color=lightgray
|
||||
[Rust 1.31]: https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html
|
||||
[Rust 1.56]: https://blog.rust-lang.org/2021/10/21/Rust-1.56.0.html
|
||||
|
||||
|
||||
+2
-2
@@ -46,8 +46,8 @@ fn main() {
|
||||
Serde is one of the most widely used Rust libraries so any place that Rustaceans
|
||||
congregate will be able to help you out. For chat, consider trying the
|
||||
[#rust-questions] or [#rust-beginners] channels of the unofficial community
|
||||
Discord (invite: <https://discord.gg/rust-lang-community>, the [#rust-usage] or
|
||||
[#beginners] channels of the official Rust Project Discord (invite:
|
||||
Discord (invite: <https://discord.gg/rust-lang-community>), the [#rust-usage]
|
||||
or [#beginners] channels of the official Rust Project Discord (invite:
|
||||
<https://discord.gg/rust-lang>), or the [#general][zulip] stream in Zulip. For
|
||||
asynchronous, consider the [\[rust\] tag on StackOverflow][stackoverflow], the
|
||||
[/r/rust] subreddit which has a pinned weekly easy questions post, or the Rust
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
/serde_derive/serde_derive-x86_64-unknown-linux-gnu
|
||||
@@ -1,14 +0,0 @@
|
||||
[workspace]
|
||||
members = ["bin", "proc-macro2"]
|
||||
resolver = "2"
|
||||
|
||||
[patch.crates-io]
|
||||
proc-macro2 = { path = "proc-macro2" }
|
||||
|
||||
[profile.precompiled]
|
||||
inherits = "release"
|
||||
codegen-units = 1
|
||||
lto = true
|
||||
opt-level = "z"
|
||||
panic = "abort"
|
||||
strip = true
|
||||
@@ -1,17 +0,0 @@
|
||||
[package]
|
||||
name = "serde_derive"
|
||||
version = "1.0.182"
|
||||
authors = ["David Tolnay <dtolnay@gmail.com>"]
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
||||
[[bin]]
|
||||
name = "serde_derive"
|
||||
path = "main.rs"
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = "1"
|
||||
quote = { version = "1", default-features = false }
|
||||
syn = { version = "2.0.28", default-features = false, features = ["clone-impls", "derive", "full", "parsing", "printing"] }
|
||||
@@ -1,4 +0,0 @@
|
||||
fn main() {
|
||||
println!("cargo:rustc-cfg=precompiled");
|
||||
println!("cargo:rustc-cfg=feature=\"deserialize_in_place\"");
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
extern crate proc_macro2;
|
||||
|
||||
use proc_macro2::watt;
|
||||
use proc_macro2::watt::buffer::InputBuffer;
|
||||
use std::alloc::{GlobalAlloc, Layout, System};
|
||||
use std::io::{self, Read, Write};
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
struct MonotonicAllocator;
|
||||
|
||||
#[global_allocator]
|
||||
static ALLOCATOR: MonotonicAllocator = MonotonicAllocator;
|
||||
|
||||
unsafe impl GlobalAlloc for MonotonicAllocator {
|
||||
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||
System.alloc(layout)
|
||||
}
|
||||
|
||||
unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {
|
||||
// Leak: this cuts 3% of code size from the precompiled macro binary.
|
||||
// There is no way that serde_derive would fill up all memory on the
|
||||
// host. When the subprocess exits, operating system will clean this up.
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut buf = Vec::new();
|
||||
io::stdin().read_to_end(&mut buf).unwrap();
|
||||
|
||||
let mut buf = InputBuffer::new(&buf);
|
||||
let derive = match buf.read_u8() {
|
||||
0 => serde_derive::derive_serialize,
|
||||
1 => serde_derive::derive_deserialize,
|
||||
2 => {
|
||||
serde_derive::DESERIALIZE_IN_PLACE.store(true, Ordering::Relaxed);
|
||||
serde_derive::derive_deserialize
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let input = watt::load(&mut buf);
|
||||
let output = derive(input);
|
||||
let bytes = watt::linearize(output);
|
||||
io::stdout().write_all(&bytes).unwrap();
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
../../serde_derive/src
|
||||
@@ -1,21 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null
|
||||
set -e -x
|
||||
|
||||
# TODO: Sanitize host filesystem paths. https://github.com/rust-lang/cargo/issues/12137
|
||||
|
||||
cargo +nightly build \
|
||||
--manifest-path bin/Cargo.toml \
|
||||
--bin serde_derive \
|
||||
--profile precompiled \
|
||||
-Z unstable-options \
|
||||
-Z build-std=std,panic_abort \
|
||||
-Z build-std-features=panic_immediate_abort \
|
||||
--target x86_64-unknown-linux-musl \
|
||||
--out-dir serde_derive
|
||||
|
||||
rm -f serde_derive/serde_derive-x86_64-unknown-linux-gnu
|
||||
mv serde_derive/serde_derive{,-x86_64-unknown-linux-gnu}
|
||||
|
||||
#upx --best --lzma serde_derive/serde_derive-x86_64-unknown-linux-gnu
|
||||
@@ -1,8 +0,0 @@
|
||||
[package]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.66"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = { package = "proc-macro2-fallback", version = "1" }
|
||||
@@ -1,815 +0,0 @@
|
||||
#[doc(hidden)]
|
||||
pub mod watt;
|
||||
|
||||
use crate::extra::DelimSpan;
|
||||
use crate::watt::Identity;
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt::{self, Debug, Display};
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::ops::RangeBounds;
|
||||
use std::str::FromStr;
|
||||
|
||||
pub use proc_macro2::{Delimiter, Spacing};
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Span {
|
||||
lo: u32,
|
||||
hi: u32,
|
||||
}
|
||||
|
||||
impl Span {
|
||||
pub fn call_site() -> Self {
|
||||
Span { lo: 0, hi: 0 }
|
||||
}
|
||||
|
||||
pub fn join(&self, other: Self) -> Option<Self> {
|
||||
Some(Span {
|
||||
lo: self.lo,
|
||||
hi: other.hi,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum TokenTree {
|
||||
Group(Group),
|
||||
Ident(Ident),
|
||||
Punct(Punct),
|
||||
Literal(Literal),
|
||||
}
|
||||
|
||||
impl TokenTree {
|
||||
pub fn span(&self) -> Span {
|
||||
match self {
|
||||
TokenTree::Group(group) => group.span(),
|
||||
TokenTree::Ident(ident) => ident.span(),
|
||||
TokenTree::Punct(punct) => punct.span(),
|
||||
TokenTree::Literal(literal) => literal.span(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_span(&mut self, span: Span) {
|
||||
match self {
|
||||
TokenTree::Group(group) => group.set_span(span),
|
||||
TokenTree::Ident(ident) => ident.set_span(span),
|
||||
TokenTree::Punct(punct) => punct.set_span(span),
|
||||
TokenTree::Literal(literal) => literal.set_span(span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Group> for TokenTree {
|
||||
fn from(group: Group) -> Self {
|
||||
TokenTree::Group(group)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Ident> for TokenTree {
|
||||
fn from(ident: Ident) -> Self {
|
||||
TokenTree::Ident(ident)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Punct> for TokenTree {
|
||||
fn from(punct: Punct) -> Self {
|
||||
TokenTree::Punct(punct)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Literal> for TokenTree {
|
||||
fn from(literal: Literal) -> Self {
|
||||
TokenTree::Literal(literal)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for TokenTree {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
TokenTree::Group(group) => Debug::fmt(group, formatter),
|
||||
TokenTree::Ident(ident) => {
|
||||
let mut debug = formatter.debug_struct("Ident");
|
||||
debug.field("sym", &format_args!("{}", ident));
|
||||
debug.finish()
|
||||
}
|
||||
TokenTree::Punct(punct) => Debug::fmt(punct, formatter),
|
||||
TokenTree::Literal(literal) => Debug::fmt(literal, formatter),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Group {
|
||||
delimiter: Delimiter,
|
||||
stream: Vec<TokenTree>,
|
||||
span: Span,
|
||||
span_open: Span,
|
||||
span_close: Span,
|
||||
identity: u32,
|
||||
}
|
||||
|
||||
impl Group {
|
||||
pub fn new(delimiter: Delimiter, stream: TokenStream) -> Self {
|
||||
Group {
|
||||
delimiter,
|
||||
stream: stream.content,
|
||||
span: Span::call_site(),
|
||||
span_open: Span::call_site(),
|
||||
span_close: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stream(&self) -> TokenStream {
|
||||
TokenStream {
|
||||
content: self.stream.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn delimiter(&self) -> Delimiter {
|
||||
self.delimiter
|
||||
}
|
||||
|
||||
pub fn span(&self) -> Span {
|
||||
self.span
|
||||
}
|
||||
|
||||
pub fn span_open(&self) -> Span {
|
||||
self.span_open
|
||||
}
|
||||
|
||||
pub fn span_close(&self) -> Span {
|
||||
self.span_close
|
||||
}
|
||||
|
||||
pub fn delim_span(&self) -> DelimSpan {
|
||||
DelimSpan {
|
||||
join: self.span,
|
||||
open: self.span_open,
|
||||
close: self.span_close,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_span(&mut self, span: Span) {
|
||||
self.span = span;
|
||||
self.identity |= Identity::RESPANNED;
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Group {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
let (open, close) = match self.delimiter {
|
||||
Delimiter::Parenthesis => ("(", ")"),
|
||||
Delimiter::Brace => ("{ ", "}"),
|
||||
Delimiter::Bracket => ("[", "]"),
|
||||
Delimiter::None => ("", ""),
|
||||
};
|
||||
|
||||
formatter.write_str(open)?;
|
||||
display_tokens(&self.stream, formatter)?;
|
||||
if self.delimiter == Delimiter::Brace && !self.stream.is_empty() {
|
||||
formatter.write_str(" ")?;
|
||||
}
|
||||
formatter.write_str(close)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Group {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
let mut debug = formatter.debug_struct("Group");
|
||||
debug.field("delimiter", &self.delimiter);
|
||||
debug.field("stream", &self.stream);
|
||||
debug.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Ident {
|
||||
fallback: proc_macro2::Ident,
|
||||
span: Span,
|
||||
identity: u32,
|
||||
}
|
||||
|
||||
impl Ident {
|
||||
pub fn new(string: &str, span: Span) -> Self {
|
||||
Ident {
|
||||
fallback: proc_macro2::Ident::new(string, proc_macro2::Span::call_site()),
|
||||
span,
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_raw(string: &str, span: Span) -> Self {
|
||||
Ident {
|
||||
fallback: proc_macro2::Ident::new_raw(string, proc_macro2::Span::call_site()),
|
||||
span,
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn span(&self) -> Span {
|
||||
self.span
|
||||
}
|
||||
|
||||
pub fn set_span(&mut self, span: Span) {
|
||||
self.span = span;
|
||||
self.identity |= Identity::RESPANNED;
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Ident {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
Display::fmt(&self.fallback, formatter)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Ident {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
Debug::fmt(&self.fallback, formatter)
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Ident {}
|
||||
|
||||
impl PartialEq for Ident {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
PartialEq::eq(&self.fallback, &other.fallback)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PartialEq<T> for Ident
|
||||
where
|
||||
T: ?Sized + AsRef<str>,
|
||||
{
|
||||
fn eq(&self, other: &T) -> bool {
|
||||
PartialEq::eq(&self.fallback, other)
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Ident {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
Ord::cmp(&self.fallback, &other.fallback)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for Ident {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
PartialOrd::partial_cmp(&self.fallback, &other.fallback)
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for Ident {
|
||||
fn hash<H: Hasher>(&self, hasher: &mut H) {
|
||||
Hash::hash(&self.fallback, hasher);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Punct {
|
||||
fallback: proc_macro2::Punct,
|
||||
span: Span,
|
||||
identity: u32,
|
||||
}
|
||||
|
||||
impl Punct {
|
||||
pub fn new(ch: char, spacing: Spacing) -> Self {
|
||||
Punct {
|
||||
fallback: proc_macro2::Punct::new(ch, spacing),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_char(&self) -> char {
|
||||
self.fallback.as_char()
|
||||
}
|
||||
|
||||
pub fn spacing(&self) -> Spacing {
|
||||
self.fallback.spacing()
|
||||
}
|
||||
|
||||
pub fn span(&self) -> Span {
|
||||
self.span
|
||||
}
|
||||
|
||||
pub fn set_span(&mut self, span: Span) {
|
||||
self.span = span;
|
||||
self.identity |= Identity::RESPANNED;
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Punct {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
Display::fmt(&self.fallback, formatter)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Punct {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
Debug::fmt(&self.fallback, formatter)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Literal {
|
||||
fallback: proc_macro2::Literal,
|
||||
span: Span,
|
||||
identity: u32,
|
||||
}
|
||||
|
||||
impl Literal {
|
||||
pub fn u8_suffixed(n: u8) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::u8_suffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn u16_suffixed(n: u16) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::u16_suffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn u32_suffixed(n: u32) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::u32_suffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn u64_suffixed(n: u64) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::u64_suffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn u128_suffixed(n: u128) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::u128_suffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn usize_suffixed(n: usize) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::usize_suffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn i8_suffixed(n: i8) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::i8_suffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn i16_suffixed(n: i16) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::i16_suffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn i32_suffixed(n: i32) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::i32_suffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn i64_suffixed(n: i64) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::i64_suffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn i128_suffixed(n: i128) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::i128_suffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn isize_suffixed(n: isize) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::isize_suffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn u8_unsuffixed(n: u8) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::u8_unsuffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn u16_unsuffixed(n: u16) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::u16_unsuffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn u32_unsuffixed(n: u32) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::u32_unsuffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn u64_unsuffixed(n: u64) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::u64_unsuffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn u128_unsuffixed(n: u128) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::u128_unsuffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn usize_unsuffixed(n: usize) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::usize_unsuffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn i8_unsuffixed(n: i8) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::i8_unsuffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn i16_unsuffixed(n: i16) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::i16_unsuffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn i32_unsuffixed(n: i32) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::i32_unsuffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn i64_unsuffixed(n: i64) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::i64_unsuffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn i128_unsuffixed(n: i128) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::i128_unsuffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn isize_unsuffixed(n: isize) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::isize_unsuffixed(n),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn f64_unsuffixed(f: f64) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::f64_unsuffixed(f),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn f64_suffixed(f: f64) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::f64_suffixed(f),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn f32_unsuffixed(f: f32) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::f32_unsuffixed(f),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn f32_suffixed(f: f32) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::f32_suffixed(f),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn string(string: &str) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::string(string),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn character(ch: char) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::character(ch),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn byte_string(s: &[u8]) -> Self {
|
||||
Literal {
|
||||
fallback: proc_macro2::Literal::byte_string(s),
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn span(&self) -> Span {
|
||||
self.span
|
||||
}
|
||||
|
||||
pub fn set_span(&mut self, span: Span) {
|
||||
self.span = span;
|
||||
self.identity |= Identity::RESPANNED;
|
||||
}
|
||||
|
||||
pub fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span> {
|
||||
let _ = range;
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Literal {
|
||||
type Err = LexError;
|
||||
|
||||
fn from_str(repr: &str) -> Result<Self, Self::Err> {
|
||||
let fallback = match proc_macro2::Literal::from_str(repr) {
|
||||
Ok(literal) => literal,
|
||||
Err(error) => {
|
||||
return Err(LexError {
|
||||
fallback: error,
|
||||
span: Span::call_site(),
|
||||
});
|
||||
}
|
||||
};
|
||||
Ok(Literal {
|
||||
fallback,
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Literal {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
Display::fmt(&self.fallback, formatter)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Literal {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
Debug::fmt(&self.fallback, formatter)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TokenStream {
|
||||
content: Vec<TokenTree>,
|
||||
}
|
||||
|
||||
impl TokenStream {
|
||||
pub fn new() -> Self {
|
||||
TokenStream {
|
||||
content: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.content.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoIterator for TokenStream {
|
||||
type Item = TokenTree;
|
||||
type IntoIter = token_stream::IntoIter;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
token_stream::IntoIter {
|
||||
iter: self.content.into_iter(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Extend<TokenStream> for TokenStream {
|
||||
fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
|
||||
self.content.extend(streams.into_iter().flatten());
|
||||
}
|
||||
}
|
||||
|
||||
impl Extend<TokenTree> for TokenStream {
|
||||
fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, streams: I) {
|
||||
self.content.extend(streams);
|
||||
}
|
||||
}
|
||||
|
||||
impl FromIterator<TokenStream> for TokenStream {
|
||||
fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
|
||||
let content = streams.into_iter().flatten().collect();
|
||||
TokenStream { content }
|
||||
}
|
||||
}
|
||||
|
||||
impl FromIterator<TokenTree> for TokenStream {
|
||||
fn from_iter<I: IntoIterator<Item = TokenTree>>(streams: I) -> Self {
|
||||
let content = streams.into_iter().collect();
|
||||
TokenStream { content }
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for TokenStream {
|
||||
type Err = LexError;
|
||||
|
||||
fn from_str(string: &str) -> Result<Self, Self::Err> {
|
||||
let fallback = match proc_macro2::TokenStream::from_str(string) {
|
||||
Ok(token_stream) => token_stream,
|
||||
Err(error) => {
|
||||
return Err(LexError {
|
||||
fallback: error,
|
||||
span: Span::call_site(),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
fn convert_token_stream(stream: proc_macro2::TokenStream) -> TokenStream {
|
||||
TokenStream {
|
||||
content: stream.into_iter().map(convert_token_tree).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_token_tree(token: proc_macro2::TokenTree) -> TokenTree {
|
||||
match token {
|
||||
proc_macro2::TokenTree::Group(group) => TokenTree::Group(Group::new(
|
||||
group.delimiter(),
|
||||
convert_token_stream(group.stream()),
|
||||
)),
|
||||
proc_macro2::TokenTree::Ident(ident) => TokenTree::Ident(Ident {
|
||||
fallback: ident,
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}),
|
||||
proc_macro2::TokenTree::Punct(punct) => TokenTree::Punct(Punct {
|
||||
fallback: punct,
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}),
|
||||
proc_macro2::TokenTree::Literal(literal) => TokenTree::Literal(Literal {
|
||||
fallback: literal,
|
||||
span: Span::call_site(),
|
||||
identity: Identity::NOVEL,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(convert_token_stream(fallback))
|
||||
}
|
||||
}
|
||||
|
||||
fn display_tokens(tokens: &[TokenTree], formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
let mut joint = false;
|
||||
for (i, token) in tokens.iter().enumerate() {
|
||||
if i != 0 && !joint {
|
||||
write!(formatter, " ")?;
|
||||
}
|
||||
joint = false;
|
||||
match token {
|
||||
TokenTree::Group(group) => Display::fmt(group, formatter),
|
||||
TokenTree::Ident(ident) => Display::fmt(ident, formatter),
|
||||
TokenTree::Punct(punct) => {
|
||||
joint = punct.spacing() == Spacing::Joint;
|
||||
Display::fmt(punct, formatter)
|
||||
}
|
||||
TokenTree::Literal(literal) => Display::fmt(literal, formatter),
|
||||
}?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl Display for TokenStream {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
display_tokens(&self.content, formatter)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for TokenStream {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("TokenStream ")?;
|
||||
formatter.debug_list().entries(&self.content).finish()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LexError {
|
||||
fallback: proc_macro2::LexError,
|
||||
span: Span,
|
||||
}
|
||||
|
||||
impl LexError {
|
||||
pub fn span(&self) -> Span {
|
||||
self.span
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for LexError {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
Debug::fmt(&self.fallback, formatter)
|
||||
}
|
||||
}
|
||||
|
||||
pub mod token_stream {
|
||||
use super::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct IntoIter {
|
||||
pub(crate) iter: <Vec<TokenTree> as IntoIterator>::IntoIter,
|
||||
}
|
||||
|
||||
impl Iterator for IntoIter {
|
||||
type Item = TokenTree;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.iter.next()
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod extra {
|
||||
use crate::Span;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct DelimSpan {
|
||||
pub(crate) join: Span,
|
||||
pub(crate) open: Span,
|
||||
pub(crate) close: Span,
|
||||
}
|
||||
|
||||
impl DelimSpan {
|
||||
pub fn join(&self) -> Span {
|
||||
self.join
|
||||
}
|
||||
|
||||
pub fn open(&self) -> Span {
|
||||
self.open
|
||||
}
|
||||
|
||||
pub fn close(&self) -> Span {
|
||||
self.close
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
use std::str;
|
||||
|
||||
pub struct OutputBuffer {
|
||||
bytes: Vec<u8>,
|
||||
}
|
||||
|
||||
impl OutputBuffer {
|
||||
pub fn new() -> Self {
|
||||
OutputBuffer { bytes: Vec::new() }
|
||||
}
|
||||
|
||||
pub fn write_u8(&mut self, value: u8) {
|
||||
self.bytes.push(value);
|
||||
}
|
||||
|
||||
pub fn write_u16(&mut self, value: u16) {
|
||||
self.bytes.extend_from_slice(&value.to_le_bytes());
|
||||
}
|
||||
|
||||
pub fn write_u32(&mut self, value: u32) {
|
||||
self.bytes.extend_from_slice(&value.to_le_bytes());
|
||||
}
|
||||
|
||||
pub fn write_str(&mut self, value: &str) {
|
||||
self.bytes.extend_from_slice(value.as_bytes());
|
||||
}
|
||||
|
||||
pub fn into_bytes(self) -> Vec<u8> {
|
||||
self.bytes
|
||||
}
|
||||
}
|
||||
|
||||
pub struct InputBuffer<'a> {
|
||||
bytes: &'a [u8],
|
||||
}
|
||||
|
||||
impl<'a> InputBuffer<'a> {
|
||||
pub fn new(bytes: &'a [u8]) -> Self {
|
||||
InputBuffer { bytes }
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.bytes.is_empty()
|
||||
}
|
||||
|
||||
pub fn read_u8(&mut self) -> u8 {
|
||||
let (first, rest) = self.bytes.split_first().unwrap();
|
||||
self.bytes = rest;
|
||||
*first
|
||||
}
|
||||
|
||||
pub fn read_u16(&mut self) -> u16 {
|
||||
let (value, rest) = self.bytes.split_at(2);
|
||||
self.bytes = rest;
|
||||
u16::from_le_bytes([value[0], value[1]])
|
||||
}
|
||||
|
||||
pub fn read_u32(&mut self) -> u32 {
|
||||
let (value, rest) = self.bytes.split_at(4);
|
||||
self.bytes = rest;
|
||||
u32::from_le_bytes([value[0], value[1], value[2], value[3]])
|
||||
}
|
||||
|
||||
pub fn read_str(&mut self, len: usize) -> &'a str {
|
||||
let (string, rest) = self.bytes.split_at(len);
|
||||
self.bytes = rest;
|
||||
str::from_utf8(string).unwrap()
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
pub enum Bytecode {}
|
||||
|
||||
impl Bytecode {
|
||||
pub const GROUP_PARENTHESIS: u8 = 0;
|
||||
pub const GROUP_BRACE: u8 = 1;
|
||||
pub const GROUP_BRACKET: u8 = 2;
|
||||
pub const GROUP_NONE: u8 = 3;
|
||||
pub const IDENT: u8 = 4;
|
||||
pub const PUNCT_ALONE: u8 = 5;
|
||||
pub const PUNCT_JOINT: u8 = 6;
|
||||
pub const LITERAL: u8 = 7;
|
||||
pub const LOAD_GROUP: u8 = 8;
|
||||
pub const LOAD_IDENT: u8 = 9;
|
||||
pub const LOAD_PUNCT: u8 = 10;
|
||||
pub const LOAD_LITERAL: u8 = 11;
|
||||
pub const SET_SPAN: u8 = 12;
|
||||
}
|
||||
@@ -1,205 +0,0 @@
|
||||
pub mod buffer;
|
||||
pub mod bytecode;
|
||||
|
||||
use crate::watt::buffer::{InputBuffer, OutputBuffer};
|
||||
use crate::watt::bytecode::Bytecode;
|
||||
use crate::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
|
||||
use std::str::FromStr;
|
||||
|
||||
pub enum Kind {
|
||||
Group(Delimiter),
|
||||
Ident,
|
||||
Punct(Spacing),
|
||||
Literal,
|
||||
}
|
||||
|
||||
pub enum Identity {}
|
||||
|
||||
impl Identity {
|
||||
pub const RESPANNED: u32 = 1 << 31;
|
||||
pub const NOVEL: u32 = u32::MAX;
|
||||
}
|
||||
|
||||
impl Span {
|
||||
fn is_call_site(&self) -> bool {
|
||||
self.lo == 0 && self.hi == 0
|
||||
}
|
||||
}
|
||||
|
||||
fn post_increment(counter: &mut u32) -> impl FnMut() -> u32 + '_ {
|
||||
|| {
|
||||
let value = *counter;
|
||||
*counter += 1;
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load(buf: &mut InputBuffer) -> TokenStream {
|
||||
let mut span_counter = 1;
|
||||
let mut next_span = post_increment(&mut span_counter);
|
||||
let mut next_span = || {
|
||||
let next = next_span();
|
||||
Span { lo: next, hi: next }
|
||||
};
|
||||
|
||||
let [mut group_counter, mut ident_counter, mut punct_counter, mut literal_counter] = [0; 4];
|
||||
let mut next_group = post_increment(&mut group_counter);
|
||||
let mut next_ident = post_increment(&mut ident_counter);
|
||||
let mut next_punct = post_increment(&mut punct_counter);
|
||||
let mut next_literal = post_increment(&mut literal_counter);
|
||||
|
||||
let mut trees = Vec::new();
|
||||
while !buf.is_empty() {
|
||||
match match buf.read_u8() {
|
||||
Bytecode::GROUP_PARENTHESIS => Kind::Group(Delimiter::Parenthesis),
|
||||
Bytecode::GROUP_BRACE => Kind::Group(Delimiter::Brace),
|
||||
Bytecode::GROUP_BRACKET => Kind::Group(Delimiter::Bracket),
|
||||
Bytecode::GROUP_NONE => Kind::Group(Delimiter::None),
|
||||
Bytecode::IDENT => Kind::Ident,
|
||||
Bytecode::PUNCT_ALONE => Kind::Punct(Spacing::Alone),
|
||||
Bytecode::PUNCT_JOINT => Kind::Punct(Spacing::Joint),
|
||||
Bytecode::LITERAL => Kind::Literal,
|
||||
_ => unreachable!(),
|
||||
} {
|
||||
Kind::Group(delimiter) => {
|
||||
let len = buf.read_u32();
|
||||
let stream = trees.drain(trees.len() - len as usize..).collect();
|
||||
trees.push(TokenTree::Group(Group {
|
||||
delimiter,
|
||||
stream,
|
||||
span: next_span(),
|
||||
span_open: next_span(),
|
||||
span_close: next_span(),
|
||||
identity: next_group(),
|
||||
}));
|
||||
}
|
||||
Kind::Ident => {
|
||||
let len = buf.read_u16();
|
||||
let repr = buf.read_str(len as usize);
|
||||
let ident = if let Some(repr) = repr.strip_prefix("r#") {
|
||||
proc_macro2::Ident::new_raw(repr, proc_macro2::Span::call_site())
|
||||
} else if repr == "$crate" {
|
||||
proc_macro2::Ident::new("crate", proc_macro2::Span::call_site())
|
||||
} else {
|
||||
proc_macro2::Ident::new(repr, proc_macro2::Span::call_site())
|
||||
};
|
||||
trees.push(TokenTree::Ident(Ident {
|
||||
fallback: ident,
|
||||
span: next_span(),
|
||||
identity: next_ident(),
|
||||
}));
|
||||
}
|
||||
Kind::Punct(spacing) => {
|
||||
let ch = buf.read_u8();
|
||||
assert!(ch.is_ascii());
|
||||
let punct = proc_macro2::Punct::new(ch as char, spacing);
|
||||
trees.push(TokenTree::Punct(Punct {
|
||||
fallback: punct,
|
||||
span: next_span(),
|
||||
identity: next_punct(),
|
||||
}));
|
||||
}
|
||||
Kind::Literal => {
|
||||
let len = buf.read_u16();
|
||||
let repr = buf.read_str(len as usize);
|
||||
let literal = proc_macro2::Literal::from_str(repr).unwrap();
|
||||
trees.push(TokenTree::Literal(Literal {
|
||||
fallback: literal,
|
||||
span: next_span(),
|
||||
identity: next_literal(),
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TokenStream { content: trees }
|
||||
}
|
||||
|
||||
pub fn linearize(tokens: TokenStream) -> Vec<u8> {
|
||||
let mut buf = OutputBuffer::new();
|
||||
for token in &tokens.content {
|
||||
linearize_token(token, &mut buf);
|
||||
}
|
||||
buf.into_bytes()
|
||||
}
|
||||
|
||||
fn linearize_token(token: &TokenTree, buf: &mut OutputBuffer) {
|
||||
let needs_span;
|
||||
match token {
|
||||
TokenTree::Group(group) => {
|
||||
if group.identity < Identity::NOVEL {
|
||||
buf.write_u8(Bytecode::LOAD_GROUP);
|
||||
buf.write_u32(group.identity & !Identity::RESPANNED);
|
||||
needs_span = group.identity >= Identity::RESPANNED;
|
||||
} else {
|
||||
let len = group.stream.len();
|
||||
assert!(len <= u32::MAX as usize);
|
||||
for token in &group.stream {
|
||||
linearize_token(token, buf);
|
||||
}
|
||||
buf.write_u8(match group.delimiter {
|
||||
Delimiter::Parenthesis => Bytecode::GROUP_PARENTHESIS,
|
||||
Delimiter::Brace => Bytecode::GROUP_BRACE,
|
||||
Delimiter::Bracket => Bytecode::GROUP_BRACKET,
|
||||
Delimiter::None => Bytecode::GROUP_NONE,
|
||||
});
|
||||
buf.write_u32(len as u32);
|
||||
needs_span = !group.span.is_call_site();
|
||||
}
|
||||
}
|
||||
TokenTree::Ident(ident) => {
|
||||
if ident.identity < Identity::NOVEL {
|
||||
buf.write_u8(Bytecode::LOAD_IDENT);
|
||||
buf.write_u32(ident.identity & !Identity::RESPANNED);
|
||||
needs_span = ident.identity >= Identity::RESPANNED;
|
||||
} else {
|
||||
buf.write_u8(Bytecode::IDENT);
|
||||
let repr = ident.to_string();
|
||||
assert!(repr.len() <= u16::MAX as usize);
|
||||
buf.write_u16(repr.len() as u16);
|
||||
buf.write_str(&repr);
|
||||
linearize_span(ident.span, buf);
|
||||
needs_span = false;
|
||||
}
|
||||
}
|
||||
TokenTree::Punct(punct) => {
|
||||
if punct.identity < Identity::NOVEL {
|
||||
buf.write_u8(Bytecode::LOAD_PUNCT);
|
||||
buf.write_u32(punct.identity & !Identity::RESPANNED);
|
||||
needs_span = punct.identity >= Identity::RESPANNED;
|
||||
} else {
|
||||
buf.write_u8(match punct.spacing() {
|
||||
Spacing::Alone => Bytecode::PUNCT_ALONE,
|
||||
Spacing::Joint => Bytecode::PUNCT_JOINT,
|
||||
});
|
||||
let ch = punct.as_char();
|
||||
assert!(ch.is_ascii());
|
||||
buf.write_u8(ch as u8);
|
||||
needs_span = !punct.span.is_call_site();
|
||||
}
|
||||
}
|
||||
TokenTree::Literal(literal) => {
|
||||
if literal.identity < Identity::NOVEL {
|
||||
buf.write_u8(Bytecode::LOAD_LITERAL);
|
||||
buf.write_u32(literal.identity & !Identity::RESPANNED);
|
||||
needs_span = literal.identity >= Identity::RESPANNED;
|
||||
} else {
|
||||
buf.write_u8(Bytecode::LITERAL);
|
||||
let repr = literal.to_string();
|
||||
assert!(repr.len() <= u16::MAX as usize);
|
||||
buf.write_u16(repr.len() as u16);
|
||||
buf.write_str(&repr);
|
||||
needs_span = !literal.span.is_call_site();
|
||||
}
|
||||
}
|
||||
}
|
||||
if needs_span {
|
||||
buf.write_u8(Bytecode::SET_SPAN);
|
||||
linearize_span(token.span(), buf);
|
||||
}
|
||||
}
|
||||
|
||||
fn linearize_span(span: Span, buf: &mut OutputBuffer) {
|
||||
buf.write_u32(span.lo);
|
||||
buf.write_u32(span.hi);
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
[package]
|
||||
name = "serde_derive"
|
||||
version = "1.0.182"
|
||||
authors = ["David Tolnay <dtolnay@gmail.com>"]
|
||||
categories = ["no-std", "no-std::no-alloc"]
|
||||
description = "Implementation of #[derive(Serialize, Deserialize)]"
|
||||
documentation = "https://serde.rs/derive.html"
|
||||
edition = "2015"
|
||||
homepage = "https://serde.rs"
|
||||
include = ["serde_derive-x86_64-unknown-linux-gnu", "src", "LICENSE-APACHE", "LICENSE-MIT"]
|
||||
keywords = ["serde", "serialization", "no_std", "derive"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
readme = "crates-io.md"
|
||||
repository = "https://github.com/serde-rs/serde"
|
||||
rust-version = "1.56"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
deserialize_in_place = []
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[target.'cfg(not(all(target_arch = "x86_64", target_os = "linux", target_env = "gnu")))'.dependencies]
|
||||
proc-macro2 = "1"
|
||||
quote = "1"
|
||||
syn = "2.0.28"
|
||||
|
||||
[dev-dependencies]
|
||||
serde = { version = "1", path = "../../serde" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
rustdoc-args = ["--generate-link-to-definition"]
|
||||
|
||||
[workspace]
|
||||
@@ -1 +0,0 @@
|
||||
../../LICENSE-APACHE
|
||||
@@ -1 +0,0 @@
|
||||
../../LICENSE-MIT
|
||||
@@ -1 +0,0 @@
|
||||
../../README.md
|
||||
@@ -1 +0,0 @@
|
||||
../../crates-io.md
|
||||
@@ -1 +0,0 @@
|
||||
../../../serde_derive/src/bound.rs
|
||||
@@ -1 +0,0 @@
|
||||
../../proc-macro2/src/watt/buffer.rs
|
||||
@@ -1 +0,0 @@
|
||||
../../proc-macro2/src/watt/bytecode.rs
|
||||
@@ -1 +0,0 @@
|
||||
../../../serde_derive/src/de.rs
|
||||
@@ -1 +0,0 @@
|
||||
../../../serde_derive/src/dummy.rs
|
||||
@@ -1 +0,0 @@
|
||||
../../../serde_derive/src/fragment.rs
|
||||
@@ -1 +0,0 @@
|
||||
../../../serde_derive/src/internals/
|
||||
@@ -1,22 +0,0 @@
|
||||
//! This crate provides Serde's two derive macros.
|
||||
//!
|
||||
//! ```edition2021
|
||||
//! # use serde_derive::{Deserialize, Serialize};
|
||||
//! #
|
||||
//! #[derive(Serialize, Deserialize)]
|
||||
//! # struct S;
|
||||
//! #
|
||||
//! # fn main() {}
|
||||
//! ```
|
||||
//!
|
||||
//! Please refer to [https://serde.rs/derive.html] for how to set this up.
|
||||
//!
|
||||
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.182")]
|
||||
|
||||
#[cfg(not(all(target_arch = "x86_64", target_os = "linux", target_env = "gnu")))]
|
||||
include!("lib_from_source.rs");
|
||||
|
||||
#[cfg(all(target_arch = "x86_64", target_os = "linux", target_env = "gnu"))]
|
||||
include!("lib_precompiled.rs");
|
||||
@@ -1,35 +0,0 @@
|
||||
extern crate proc_macro;
|
||||
extern crate proc_macro2;
|
||||
extern crate quote;
|
||||
extern crate syn;
|
||||
|
||||
#[macro_use]
|
||||
mod bound;
|
||||
#[macro_use]
|
||||
mod fragment;
|
||||
|
||||
mod de;
|
||||
mod dummy;
|
||||
mod internals;
|
||||
mod pretend;
|
||||
mod ser;
|
||||
mod this;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use syn::{parse_macro_input, DeriveInput};
|
||||
|
||||
#[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)
|
||||
.into()
|
||||
}
|
||||
|
||||
#[proc_macro_derive(Deserialize, attributes(serde))]
|
||||
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)
|
||||
.into()
|
||||
}
|
||||
@@ -1,234 +0,0 @@
|
||||
extern crate proc_macro;
|
||||
|
||||
mod buffer;
|
||||
mod bytecode;
|
||||
|
||||
use crate::buffer::{InputBuffer, OutputBuffer};
|
||||
use crate::bytecode::Bytecode;
|
||||
use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
|
||||
use std::io::{ErrorKind, Read, Write};
|
||||
use std::iter::FromIterator;
|
||||
use std::path::Path;
|
||||
use std::process::{Command, ExitStatus, Stdio};
|
||||
use std::str::FromStr;
|
||||
|
||||
#[proc_macro_derive(Serialize, attributes(serde))]
|
||||
pub fn derive_serialize(input: TokenStream) -> TokenStream {
|
||||
derive(0, input)
|
||||
}
|
||||
|
||||
#[proc_macro_derive(Deserialize, attributes(serde))]
|
||||
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
|
||||
derive(1 + cfg!(feature = "deserialize_in_place") as u8, input)
|
||||
}
|
||||
|
||||
fn derive(select: u8, input: TokenStream) -> TokenStream {
|
||||
let mut memory = TokenMemory::default();
|
||||
let mut buf = OutputBuffer::new();
|
||||
buf.write_u8(select);
|
||||
|
||||
memory.spans.push(Span::call_site());
|
||||
for token in input {
|
||||
memory.linearize_token(token, &mut buf);
|
||||
}
|
||||
|
||||
let exe_path = Path::new(concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/serde_derive-x86_64-unknown-linux-gnu",
|
||||
));
|
||||
let mut child = match Command::new(exe_path)
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
{
|
||||
Ok(child) => child,
|
||||
Err(io_error) => {
|
||||
if io_error.kind() == ErrorKind::NotFound {
|
||||
panic!(
|
||||
"file missing from serde_derive manifest directory during macro expansion: {}",
|
||||
exe_path.display(),
|
||||
);
|
||||
} else {
|
||||
panic!("failed to spawn process: {}", io_error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let mut stdin = child.stdin.take().unwrap();
|
||||
let mut buf = buf.into_bytes();
|
||||
stdin.write_all(&buf).unwrap();
|
||||
drop(stdin);
|
||||
|
||||
let mut stdout = child.stdout.take().unwrap();
|
||||
buf.clear();
|
||||
stdout.read_to_end(&mut buf).unwrap();
|
||||
|
||||
let success = child.wait().as_ref().map_or(true, ExitStatus::success);
|
||||
if !success || buf.is_empty() {
|
||||
panic!();
|
||||
}
|
||||
|
||||
let mut buf = InputBuffer::new(&buf);
|
||||
memory.receive(&mut buf)
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct TokenMemory {
|
||||
spans: Vec<Span>,
|
||||
groups: Vec<Group>,
|
||||
idents: Vec<Ident>,
|
||||
puncts: Vec<Punct>,
|
||||
literals: Vec<Literal>,
|
||||
}
|
||||
|
||||
enum Kind {
|
||||
Group(Delimiter),
|
||||
Ident,
|
||||
Punct(Spacing),
|
||||
Literal,
|
||||
}
|
||||
|
||||
impl TokenMemory {
|
||||
// Depth-first post-order traversal.
|
||||
fn linearize_token(&mut self, token: TokenTree, buf: &mut OutputBuffer) {
|
||||
match token {
|
||||
TokenTree::Group(group) => {
|
||||
let mut len = 0usize;
|
||||
for token in group.stream() {
|
||||
self.linearize_token(token, buf);
|
||||
len += 1;
|
||||
}
|
||||
assert!(len <= u32::MAX as usize);
|
||||
buf.write_u8(match group.delimiter() {
|
||||
Delimiter::Parenthesis => Bytecode::GROUP_PARENTHESIS,
|
||||
Delimiter::Brace => Bytecode::GROUP_BRACE,
|
||||
Delimiter::Bracket => Bytecode::GROUP_BRACKET,
|
||||
Delimiter::None => Bytecode::GROUP_NONE,
|
||||
});
|
||||
buf.write_u32(len as u32);
|
||||
self.spans
|
||||
.extend([group.span(), group.span_open(), group.span_close()]);
|
||||
self.groups.push(group);
|
||||
}
|
||||
TokenTree::Ident(ident) => {
|
||||
buf.write_u8(Bytecode::IDENT);
|
||||
let repr = ident.to_string();
|
||||
assert!(repr.len() <= u16::MAX as usize);
|
||||
buf.write_u16(repr.len() as u16);
|
||||
buf.write_str(&repr);
|
||||
self.spans.push(ident.span());
|
||||
self.idents.push(ident);
|
||||
}
|
||||
TokenTree::Punct(punct) => {
|
||||
buf.write_u8(match punct.spacing() {
|
||||
Spacing::Alone => Bytecode::PUNCT_ALONE,
|
||||
Spacing::Joint => Bytecode::PUNCT_JOINT,
|
||||
});
|
||||
let ch = punct.as_char();
|
||||
assert!(ch.is_ascii());
|
||||
buf.write_u8(ch as u8);
|
||||
self.spans.push(punct.span());
|
||||
self.puncts.push(punct);
|
||||
}
|
||||
TokenTree::Literal(literal) => {
|
||||
buf.write_u8(Bytecode::LITERAL);
|
||||
let repr = literal.to_string();
|
||||
assert!(repr.len() <= u16::MAX as usize);
|
||||
buf.write_u16(repr.len() as u16);
|
||||
buf.write_str(&repr);
|
||||
self.spans.push(literal.span());
|
||||
self.literals.push(literal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn receive(&self, buf: &mut InputBuffer) -> TokenStream {
|
||||
let mut trees = Vec::new();
|
||||
while !buf.is_empty() {
|
||||
match match buf.read_u8() {
|
||||
Bytecode::GROUP_PARENTHESIS => Kind::Group(Delimiter::Parenthesis),
|
||||
Bytecode::GROUP_BRACE => Kind::Group(Delimiter::Brace),
|
||||
Bytecode::GROUP_BRACKET => Kind::Group(Delimiter::Bracket),
|
||||
Bytecode::GROUP_NONE => Kind::Group(Delimiter::None),
|
||||
Bytecode::IDENT => Kind::Ident,
|
||||
Bytecode::PUNCT_ALONE => Kind::Punct(Spacing::Alone),
|
||||
Bytecode::PUNCT_JOINT => Kind::Punct(Spacing::Joint),
|
||||
Bytecode::LITERAL => Kind::Literal,
|
||||
Bytecode::LOAD_GROUP => {
|
||||
let identity = buf.read_u32();
|
||||
let group = self.groups[identity as usize].clone();
|
||||
trees.push(TokenTree::Group(group));
|
||||
continue;
|
||||
}
|
||||
Bytecode::LOAD_IDENT => {
|
||||
let identity = buf.read_u32();
|
||||
let ident = self.idents[identity as usize].clone();
|
||||
trees.push(TokenTree::Ident(ident));
|
||||
continue;
|
||||
}
|
||||
Bytecode::LOAD_PUNCT => {
|
||||
let identity = buf.read_u32();
|
||||
let punct = self.puncts[identity as usize].clone();
|
||||
trees.push(TokenTree::Punct(punct));
|
||||
continue;
|
||||
}
|
||||
Bytecode::LOAD_LITERAL => {
|
||||
let identity = buf.read_u32();
|
||||
let literal = self.literals[identity as usize].clone();
|
||||
trees.push(TokenTree::Literal(literal));
|
||||
continue;
|
||||
}
|
||||
Bytecode::SET_SPAN => {
|
||||
trees.last_mut().unwrap().set_span(self.read_span(buf));
|
||||
continue;
|
||||
}
|
||||
_ => unreachable!(),
|
||||
} {
|
||||
Kind::Group(delimiter) => {
|
||||
let len = buf.read_u32();
|
||||
let stream = trees.drain(trees.len() - len as usize..).collect();
|
||||
let group = Group::new(delimiter, stream);
|
||||
trees.push(TokenTree::Group(group));
|
||||
}
|
||||
Kind::Ident => {
|
||||
let len = buf.read_u16();
|
||||
let repr = buf.read_str(len as usize);
|
||||
let span = self.read_span(buf);
|
||||
let ident = if let Some(repr) = repr.strip_prefix("r#") {
|
||||
Ident::new_raw(repr, span)
|
||||
} else {
|
||||
Ident::new(repr, span)
|
||||
};
|
||||
trees.push(TokenTree::Ident(ident));
|
||||
}
|
||||
Kind::Punct(spacing) => {
|
||||
let ch = buf.read_u8();
|
||||
assert!(ch.is_ascii());
|
||||
let punct = Punct::new(ch as char, spacing);
|
||||
trees.push(TokenTree::Punct(punct));
|
||||
}
|
||||
Kind::Literal => {
|
||||
let len = buf.read_u16();
|
||||
let repr = buf.read_str(len as usize);
|
||||
let literal = Literal::from_str(repr).unwrap();
|
||||
trees.push(TokenTree::Literal(literal));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TokenStream::from_iter(trees)
|
||||
}
|
||||
|
||||
fn read_span(&self, buf: &mut InputBuffer) -> Span {
|
||||
let lo = buf.read_u32();
|
||||
let hi = buf.read_u32();
|
||||
let span = self.spans[lo as usize];
|
||||
if lo == hi {
|
||||
span
|
||||
} else {
|
||||
#[cfg(any())] // FIXME
|
||||
return span.join(self.spans[hi as usize]).unwrap_or(span);
|
||||
span
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
../../../serde_derive/src/pretend.rs
|
||||
@@ -1 +0,0 @@
|
||||
../../../serde_derive/src/ser.rs
|
||||
@@ -1 +0,0 @@
|
||||
../../../serde_derive/src/this.rs
|
||||
+11
-3
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde"
|
||||
version = "1.0.182" # remember to update html_root_url and serde_derive dependency
|
||||
version = "1.0.208"
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
build = "build.rs"
|
||||
categories = ["encoding", "no-std", "no-std::no-alloc"]
|
||||
@@ -15,7 +15,7 @@ repository = "https://github.com/serde-rs/serde"
|
||||
rust-version = "1.31"
|
||||
|
||||
[dependencies]
|
||||
serde_derive = { version = "=1.0.182", optional = true, path = "../serde_derive" }
|
||||
serde_derive = { version = "1", optional = true, path = "../serde_derive" }
|
||||
|
||||
[dev-dependencies]
|
||||
serde_derive = { version = "1", path = "../serde_derive" }
|
||||
@@ -27,10 +27,18 @@ doc-scrape-examples = false
|
||||
features = ["derive", "rc"]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["derive"]
|
||||
features = ["derive", "rc", "unstable"]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
rustdoc-args = ["--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.208", path = "../serde_derive" }
|
||||
|
||||
|
||||
### FEATURES #################################################################
|
||||
|
||||
|
||||
+31
-5
@@ -13,6 +13,21 @@ fn main() {
|
||||
None => return,
|
||||
};
|
||||
|
||||
if minor >= 77 {
|
||||
println!("cargo:rustc-check-cfg=cfg(no_core_cstr)");
|
||||
println!("cargo:rustc-check-cfg=cfg(no_core_num_saturating)");
|
||||
println!("cargo:rustc-check-cfg=cfg(no_core_try_from)");
|
||||
println!("cargo:rustc-check-cfg=cfg(no_diagnostic_namespace)");
|
||||
println!("cargo:rustc-check-cfg=cfg(no_float_copysign)");
|
||||
println!("cargo:rustc-check-cfg=cfg(no_num_nonzero_signed)");
|
||||
println!("cargo:rustc-check-cfg=cfg(no_relaxed_trait_bounds)");
|
||||
println!("cargo:rustc-check-cfg=cfg(no_serde_derive)");
|
||||
println!("cargo:rustc-check-cfg=cfg(no_std_atomic)");
|
||||
println!("cargo:rustc-check-cfg=cfg(no_std_atomic64)");
|
||||
println!("cargo:rustc-check-cfg=cfg(no_systemtime_checked_add)");
|
||||
println!("cargo:rustc-check-cfg=cfg(no_target_has_atomic)");
|
||||
}
|
||||
|
||||
let target = env::var("TARGET").unwrap();
|
||||
let emscripten = target == "asmjs-unknown-emscripten" || target == "wasm32-unknown-emscripten";
|
||||
|
||||
@@ -27,11 +42,10 @@ fn main() {
|
||||
println!("cargo:rustc-cfg=no_relaxed_trait_bounds");
|
||||
}
|
||||
|
||||
// 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 emscripten && minor < 40 {
|
||||
println!("cargo:rustc-cfg=no_integer128");
|
||||
// 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");
|
||||
}
|
||||
|
||||
// Current minimum supported version of serde_derive crate is Rust 1.56.
|
||||
@@ -65,6 +79,18 @@ fn main() {
|
||||
if minor < 64 {
|
||||
println!("cargo:rustc-cfg=no_core_cstr");
|
||||
}
|
||||
|
||||
// Support for core::num::Saturating and std::num::Saturating stabilized in Rust 1.74
|
||||
// https://blog.rust-lang.org/2023/11/16/Rust-1.74.0.html#stabilized-apis
|
||||
if minor < 74 {
|
||||
println!("cargo:rustc-cfg=no_core_num_saturating");
|
||||
}
|
||||
|
||||
// Support for the `#[diagnostic]` tool attribute namespace
|
||||
// https://blog.rust-lang.org/2024/05/02/Rust-1.78.0.html#diagnostic-attributes
|
||||
if minor < 78 {
|
||||
println!("cargo:rustc-cfg=no_diagnostic_namespace");
|
||||
}
|
||||
}
|
||||
|
||||
fn rustc_minor_version() -> Option<u32> {
|
||||
|
||||
@@ -129,12 +129,10 @@ impl<'de> Visitor<'de> for IgnoredAny {
|
||||
Ok(IgnoredAny)
|
||||
}
|
||||
|
||||
serde_if_integer128! {
|
||||
#[inline]
|
||||
fn visit_i128<E>(self, x: i128) -> Result<Self::Value, E> {
|
||||
let _ = x;
|
||||
Ok(IgnoredAny)
|
||||
}
|
||||
#[inline]
|
||||
fn visit_i128<E>(self, x: i128) -> Result<Self::Value, E> {
|
||||
let _ = x;
|
||||
Ok(IgnoredAny)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -143,12 +141,10 @@ impl<'de> Visitor<'de> for IgnoredAny {
|
||||
Ok(IgnoredAny)
|
||||
}
|
||||
|
||||
serde_if_integer128! {
|
||||
#[inline]
|
||||
fn visit_u128<E>(self, x: u128) -> Result<Self::Value, E> {
|
||||
let _ = x;
|
||||
Ok(IgnoredAny)
|
||||
}
|
||||
#[inline]
|
||||
fn visit_u128<E>(self, x: u128) -> Result<Self::Value, E> {
|
||||
let _ = x;
|
||||
Ok(IgnoredAny)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
||||
+552
-320
File diff suppressed because it is too large
Load Diff
+113
-76
@@ -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\>
|
||||
@@ -118,12 +118,10 @@ use crate::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;
|
||||
|
||||
@@ -404,20 +402,20 @@ impl<'a> fmt::Display for Unexpected<'a> {
|
||||
Bool(b) => write!(formatter, "boolean `{}`", b),
|
||||
Unsigned(i) => write!(formatter, "integer `{}`", i),
|
||||
Signed(i) => write!(formatter, "integer `{}`", i),
|
||||
Float(f) => write!(formatter, "floating point `{}`", f),
|
||||
Float(f) => write!(formatter, "floating point `{}`", WithDecimalPoint(f)),
|
||||
Char(c) => write!(formatter, "character `{}`", c),
|
||||
Str(s) => write!(formatter, "string {:?}", s),
|
||||
Bytes(_) => write!(formatter, "byte array"),
|
||||
Unit => write!(formatter, "unit value"),
|
||||
Option => write!(formatter, "Option value"),
|
||||
NewtypeStruct => write!(formatter, "newtype struct"),
|
||||
Seq => write!(formatter, "sequence"),
|
||||
Map => write!(formatter, "map"),
|
||||
Enum => write!(formatter, "enum"),
|
||||
UnitVariant => write!(formatter, "unit variant"),
|
||||
NewtypeVariant => write!(formatter, "newtype variant"),
|
||||
TupleVariant => write!(formatter, "tuple variant"),
|
||||
StructVariant => write!(formatter, "struct variant"),
|
||||
Bytes(_) => formatter.write_str("byte array"),
|
||||
Unit => formatter.write_str("unit value"),
|
||||
Option => formatter.write_str("Option value"),
|
||||
NewtypeStruct => formatter.write_str("newtype struct"),
|
||||
Seq => formatter.write_str("sequence"),
|
||||
Map => formatter.write_str("map"),
|
||||
Enum => formatter.write_str("enum"),
|
||||
UnitVariant => formatter.write_str("unit variant"),
|
||||
NewtypeVariant => formatter.write_str("newtype variant"),
|
||||
TupleVariant => formatter.write_str("tuple variant"),
|
||||
StructVariant => formatter.write_str("struct variant"),
|
||||
Other(other) => formatter.write_str(other),
|
||||
}
|
||||
}
|
||||
@@ -534,6 +532,13 @@ impl<'a> Display for Expected + 'a {
|
||||
/// deserializer lifetimes] for a more detailed explanation of these lifetimes.
|
||||
///
|
||||
/// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html
|
||||
#[cfg_attr(
|
||||
not(no_diagnostic_namespace),
|
||||
diagnostic::on_unimplemented(
|
||||
note = "for local types consider adding `#[derive(serde::Deserialize)]` to your `{Self}` type",
|
||||
note = "for types from other crates check whether the crate offers a `serde` feature flag",
|
||||
)
|
||||
)]
|
||||
pub trait Deserialize<'de>: Sized {
|
||||
/// Deserialize this value from the given Serde deserializer.
|
||||
///
|
||||
@@ -950,18 +955,15 @@ pub trait Deserializer<'de>: Sized {
|
||||
where
|
||||
V: Visitor<'de>;
|
||||
|
||||
serde_if_integer128! {
|
||||
/// Hint that the `Deserialize` type is expecting an `i128` value.
|
||||
///
|
||||
/// This method is available only on Rust compiler versions >=1.26. The
|
||||
/// default behavior unconditionally returns an error.
|
||||
fn deserialize_i128<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 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"))
|
||||
}
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting a `u8` value.
|
||||
@@ -984,18 +986,15 @@ pub trait Deserializer<'de>: Sized {
|
||||
where
|
||||
V: Visitor<'de>;
|
||||
|
||||
serde_if_integer128! {
|
||||
/// Hint that the `Deserialize` type is expecting an `u128` value.
|
||||
///
|
||||
/// This method is available only on Rust compiler versions >=1.26. The
|
||||
/// default behavior unconditionally returns an error.
|
||||
fn deserialize_u128<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 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"))
|
||||
}
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting a `f32` value.
|
||||
@@ -1367,20 +1366,20 @@ pub trait Visitor<'de>: Sized {
|
||||
Err(Error::invalid_type(Unexpected::Signed(v), &self))
|
||||
}
|
||||
|
||||
serde_if_integer128! {
|
||||
/// The input contains a `i128`.
|
||||
///
|
||||
/// This method is available only on Rust compiler versions >=1.26. The
|
||||
/// default implementation fails with a type error.
|
||||
fn visit_i128<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 `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,
|
||||
))
|
||||
}
|
||||
|
||||
/// The input contains a `u8`.
|
||||
@@ -1429,20 +1428,20 @@ pub trait Visitor<'de>: Sized {
|
||||
Err(Error::invalid_type(Unexpected::Unsigned(v), &self))
|
||||
}
|
||||
|
||||
serde_if_integer128! {
|
||||
/// The input contains a `u128`.
|
||||
///
|
||||
/// This method is available only on Rust compiler versions >=1.26. The
|
||||
/// default implementation fails with a type error.
|
||||
fn visit_u128<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 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,
|
||||
))
|
||||
}
|
||||
|
||||
/// The input contains an `f32`.
|
||||
@@ -1478,7 +1477,7 @@ pub trait Visitor<'de>: Sized {
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
self.visit_str(utf8::encode(v).as_str())
|
||||
self.visit_str(v.encode_utf8(&mut [0u8; 4]))
|
||||
}
|
||||
|
||||
/// The input contains a string. The lifetime of the string is ephemeral and
|
||||
@@ -1533,6 +1532,7 @@ pub trait Visitor<'de>: Sized {
|
||||
/// `String`.
|
||||
#[inline]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
@@ -1555,7 +1555,6 @@ pub trait Visitor<'de>: Sized {
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
let _ = v;
|
||||
Err(Error::invalid_type(Unexpected::Bytes(v), &self))
|
||||
}
|
||||
|
||||
@@ -1592,6 +1591,7 @@ 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(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
@@ -1742,9 +1742,9 @@ pub trait SeqAccess<'de> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, 'a, A: ?Sized> SeqAccess<'de> for &'a mut A
|
||||
impl<'de, 'a, A> SeqAccess<'de> for &'a mut A
|
||||
where
|
||||
A: SeqAccess<'de>,
|
||||
A: ?Sized + SeqAccess<'de>,
|
||||
{
|
||||
type Error = A::Error;
|
||||
|
||||
@@ -1895,9 +1895,9 @@ pub trait MapAccess<'de> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, 'a, A: ?Sized> MapAccess<'de> for &'a mut A
|
||||
impl<'de, 'a, A> MapAccess<'de> for &'a mut A
|
||||
where
|
||||
A: MapAccess<'de>,
|
||||
A: ?Sized + MapAccess<'de>,
|
||||
{
|
||||
type Error = A::Error;
|
||||
|
||||
@@ -2285,10 +2285,10 @@ impl Display for OneOf {
|
||||
1 => write!(formatter, "`{}`", self.names[0]),
|
||||
2 => write!(formatter, "`{}` or `{}`", self.names[0], self.names[1]),
|
||||
_ => {
|
||||
tri!(write!(formatter, "one of "));
|
||||
tri!(formatter.write_str("one of "));
|
||||
for (i, alt) in self.names.iter().enumerate() {
|
||||
if i > 0 {
|
||||
tri!(write!(formatter, ", "));
|
||||
tri!(formatter.write_str(", "));
|
||||
}
|
||||
tri!(write!(formatter, "`{}`", alt));
|
||||
}
|
||||
@@ -2297,3 +2297,40 @@ impl Display for OneOf {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
if self.0.is_finite() {
|
||||
let mut writer = LookForDecimalPoint {
|
||||
formatter,
|
||||
has_decimal_point: false,
|
||||
};
|
||||
tri!(write!(writer, "{}", self.0));
|
||||
if !writer.has_decimal_point {
|
||||
tri!(formatter.write_str(".0"));
|
||||
}
|
||||
} else {
|
||||
tri!(write!(formatter, "{}", self.0));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
use crate::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, 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()
|
||||
}
|
||||
}
|
||||
+16
-7
@@ -112,6 +112,7 @@ impl Debug for Error {
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
impl error::Error for Error {
|
||||
fn description(&self) -> &str {
|
||||
&self.err
|
||||
@@ -184,12 +185,14 @@ impl<E> Debug for UnitDeserializer<E> {
|
||||
|
||||
/// A deserializer that cannot be instantiated.
|
||||
#[cfg(feature = "unstable")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
|
||||
pub struct NeverDeserializer<E> {
|
||||
never: !,
|
||||
marker: PhantomData<E>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
|
||||
impl<'de, E> IntoDeserializer<'de, E> for !
|
||||
where
|
||||
E: de::Error,
|
||||
@@ -292,20 +295,17 @@ primitive_deserializer!(i8, "an `i8`.", I8Deserializer, visit_i8);
|
||||
primitive_deserializer!(i16, "an `i16`.", I16Deserializer, visit_i16);
|
||||
primitive_deserializer!(i32, "an `i32`.", I32Deserializer, visit_i32);
|
||||
primitive_deserializer!(i64, "an `i64`.", I64Deserializer, visit_i64);
|
||||
primitive_deserializer!(i128, "an `i128`.", I128Deserializer, visit_i128);
|
||||
primitive_deserializer!(isize, "an `isize`.", IsizeDeserializer, visit_i64 as i64);
|
||||
primitive_deserializer!(u8, "a `u8`.", U8Deserializer, visit_u8);
|
||||
primitive_deserializer!(u16, "a `u16`.", U16Deserializer, visit_u16);
|
||||
primitive_deserializer!(u64, "a `u64`.", U64Deserializer, visit_u64);
|
||||
primitive_deserializer!(u128, "a `u128`.", U128Deserializer, visit_u128);
|
||||
primitive_deserializer!(usize, "a `usize`.", UsizeDeserializer, visit_u64 as u64);
|
||||
primitive_deserializer!(f32, "an `f32`.", F32Deserializer, visit_f32);
|
||||
primitive_deserializer!(f64, "an `f64`.", F64Deserializer, visit_f64);
|
||||
primitive_deserializer!(char, "a `char`.", CharDeserializer, visit_char);
|
||||
|
||||
serde_if_integer128! {
|
||||
primitive_deserializer!(i128, "an `i128`.", I128Deserializer, visit_i128);
|
||||
primitive_deserializer!(u128, "a `u128`.", U128Deserializer, visit_u128);
|
||||
}
|
||||
|
||||
/// A deserializer holding a `u32`.
|
||||
pub struct U32Deserializer<E> {
|
||||
value: u32,
|
||||
@@ -565,6 +565,7 @@ impl<'de, E> Debug for BorrowedStrDeserializer<'de, E> {
|
||||
|
||||
/// A deserializer holding a `String`.
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
pub struct StringDeserializer<E> {
|
||||
value: String,
|
||||
marker: PhantomData<E>,
|
||||
@@ -581,6 +582,7 @@ impl<E> Clone for StringDeserializer<E> {
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
impl<'de, E> IntoDeserializer<'de, E> for String
|
||||
where
|
||||
E: de::Error,
|
||||
@@ -668,6 +670,7 @@ impl<E> Debug for StringDeserializer<E> {
|
||||
|
||||
/// A deserializer holding a `Cow<str>`.
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
pub struct CowStrDeserializer<'a, E> {
|
||||
value: Cow<'a, str>,
|
||||
marker: PhantomData<E>,
|
||||
@@ -684,6 +687,7 @@ impl<'a, E> Clone for CowStrDeserializer<'a, E> {
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
impl<'de, 'a, E> IntoDeserializer<'de, E> for Cow<'a, str>
|
||||
where
|
||||
E: de::Error,
|
||||
@@ -979,7 +983,7 @@ struct ExpectedInSeq(usize);
|
||||
impl Expected for ExpectedInSeq {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
if self.0 == 1 {
|
||||
write!(formatter, "1 element in sequence")
|
||||
formatter.write_str("1 element in sequence")
|
||||
} else {
|
||||
write!(formatter, "{} elements in sequence", self.0)
|
||||
}
|
||||
@@ -1002,6 +1006,7 @@ where
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
impl<'de, T, E> IntoDeserializer<'de, E> for Vec<T>
|
||||
where
|
||||
T: IntoDeserializer<'de, E>,
|
||||
@@ -1015,6 +1020,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
impl<'de, T, E> IntoDeserializer<'de, E> for BTreeSet<T>
|
||||
where
|
||||
T: IntoDeserializer<'de, E> + Eq + Ord,
|
||||
@@ -1028,6 +1034,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
impl<'de, T, S, E> IntoDeserializer<'de, E> for HashSet<T, S>
|
||||
where
|
||||
T: IntoDeserializer<'de, E> + Eq + Hash,
|
||||
@@ -1404,7 +1411,7 @@ struct ExpectedInMap(usize);
|
||||
impl Expected for ExpectedInMap {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
if self.0 == 1 {
|
||||
write!(formatter, "1 element in map")
|
||||
formatter.write_str("1 element in map")
|
||||
} else {
|
||||
write!(formatter, "{} elements in map", self.0)
|
||||
}
|
||||
@@ -1414,6 +1421,7 @@ impl Expected for ExpectedInMap {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(docsrs, 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,
|
||||
@@ -1428,6 +1436,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, 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,
|
||||
|
||||
+3
-76
@@ -1,82 +1,9 @@
|
||||
/// Conditional compilation depending on whether Serde is built with support for
|
||||
/// 128-bit integers.
|
||||
///
|
||||
/// Data formats that wish to support Rust compiler versions older than 1.26
|
||||
/// (or targets that lack 128-bit integers) may place the i128 / u128 methods
|
||||
/// of their Serializer and Deserializer behind this macro.
|
||||
///
|
||||
/// Data formats that require a minimum Rust compiler version of at least 1.26,
|
||||
/// or do not target platforms that lack 128-bit integers, do not need to
|
||||
/// bother with this macro and may assume support for 128-bit integers.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// # 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.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// macro_rules! serde_if_integer128 {
|
||||
/// ($($tt:tt)*) => {
|
||||
/// $($tt)*
|
||||
/// };
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// When built without support for 128-bit integers, this macro expands to
|
||||
/// nothing.
|
||||
///
|
||||
/// ```edition2021
|
||||
/// macro_rules! serde_if_integer128 {
|
||||
/// ($($tt:tt)*) => {};
|
||||
/// }
|
||||
/// ```
|
||||
#[cfg(not(no_integer128))]
|
||||
// No longer used. Old versions of serde used this macro for supporting targets
|
||||
// that did not yet have 128-bit integer support.
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! serde_if_integer128 {
|
||||
($($tt:tt)*) => {
|
||||
$($tt)*
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(no_integer128)]
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! serde_if_integer128 {
|
||||
($($tt:tt)*) => {};
|
||||
}
|
||||
|
||||
+23
-10
@@ -63,6 +63,7 @@
|
||||
//! 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
|
||||
@@ -89,18 +90,22 @@
|
||||
//! [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.182")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.208")]
|
||||
// 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(docsrs, feature(doc_cfg, rustdoc_internals))]
|
||||
#![cfg_attr(docsrs, allow(internal_features))]
|
||||
// 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)]
|
||||
// Ignored clippy and clippy_pedantic lints
|
||||
#![allow(
|
||||
@@ -114,11 +119,11 @@
|
||||
// integer and float ser/de requires these sorts of casts
|
||||
clippy::cast_possible_truncation,
|
||||
clippy::cast_possible_wrap,
|
||||
clippy::cast_precision_loss,
|
||||
clippy::cast_sign_loss,
|
||||
// things are often more readable this way
|
||||
clippy::cast_lossless,
|
||||
clippy::module_name_repetitions,
|
||||
clippy::option_if_let_else,
|
||||
clippy::single_match_else,
|
||||
clippy::type_complexity,
|
||||
clippy::use_self,
|
||||
@@ -127,6 +132,7 @@
|
||||
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,
|
||||
@@ -166,22 +172,25 @@ mod lib {
|
||||
pub use std::*;
|
||||
}
|
||||
|
||||
pub use self::core::{cmp, iter, mem, num, ptr, slice, str};
|
||||
pub use self::core::{f32, f64};
|
||||
pub use self::core::{i16, i32, i64, i8, isize};
|
||||
pub use self::core::{iter, num, ptr, str};
|
||||
pub use self::core::{u16, u32, u64, u8, usize};
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
pub use self::core::{cmp, mem, slice};
|
||||
|
||||
pub use self::core::cell::{Cell, RefCell};
|
||||
pub use self::core::clone::{self, Clone};
|
||||
pub use self::core::clone;
|
||||
pub use self::core::cmp::Reverse;
|
||||
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::convert;
|
||||
pub use self::core::default;
|
||||
pub use self::core::fmt::{self, Debug, Display, Write as FmtWrite};
|
||||
pub use self::core::marker::{self, PhantomData};
|
||||
pub use self::core::num::Wrapping;
|
||||
pub use self::core::ops::{Bound, Range, RangeFrom, RangeInclusive, RangeTo};
|
||||
pub use self::core::option::{self, Option};
|
||||
pub use self::core::result::{self, Result};
|
||||
pub use self::core::option;
|
||||
pub use self::core::result;
|
||||
pub use self::core::time::Duration;
|
||||
|
||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||
@@ -267,6 +276,9 @@ mod lib {
|
||||
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};
|
||||
|
||||
#[cfg(not(no_core_num_saturating))]
|
||||
pub use self::core::num::Saturating;
|
||||
}
|
||||
|
||||
// None of this crate's error handling needs the `From::from` error conversion
|
||||
@@ -319,6 +331,7 @@ extern crate serde_derive;
|
||||
|
||||
/// Derive macro available if serde is built with `features = ["derive"]`.
|
||||
#[cfg(feature = "serde_derive")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
|
||||
pub use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))]
|
||||
|
||||
+3
-7
@@ -123,7 +123,7 @@ macro_rules! forward_to_deserialize_any {
|
||||
macro_rules! forward_to_deserialize_any_method {
|
||||
($func:ident<$l:tt, $v:ident>($($arg:ident : $ty:ty),*)) => {
|
||||
#[inline]
|
||||
fn $func<$v>(self, $($arg: $ty,)* visitor: $v) -> $crate::__private::Result<$v::Value, Self::Error>
|
||||
fn $func<$v>(self, $($arg: $ty,)* visitor: $v) -> $crate::__private::Result<$v::Value, <Self as $crate::de::Deserializer<$l>>::Error>
|
||||
where
|
||||
$v: $crate::de::Visitor<$l>,
|
||||
{
|
||||
@@ -154,9 +154,7 @@ macro_rules! forward_to_deserialize_any_helper {
|
||||
forward_to_deserialize_any_method!{deserialize_i64<$l, $v>()}
|
||||
};
|
||||
(i128<$l:tt, $v:ident>) => {
|
||||
serde_if_integer128! {
|
||||
forward_to_deserialize_any_method!{deserialize_i128<$l, $v>()}
|
||||
}
|
||||
forward_to_deserialize_any_method!{deserialize_i128<$l, $v>()}
|
||||
};
|
||||
(u8<$l:tt, $v:ident>) => {
|
||||
forward_to_deserialize_any_method!{deserialize_u8<$l, $v>()}
|
||||
@@ -171,9 +169,7 @@ macro_rules! forward_to_deserialize_any_helper {
|
||||
forward_to_deserialize_any_method!{deserialize_u64<$l, $v>()}
|
||||
};
|
||||
(u128<$l:tt, $v:ident>) => {
|
||||
serde_if_integer128! {
|
||||
forward_to_deserialize_any_method!{deserialize_u128<$l, $v>()}
|
||||
}
|
||||
forward_to_deserialize_any_method!{deserialize_u128<$l, $v>()}
|
||||
};
|
||||
(f32<$l:tt, $v:ident>) => {
|
||||
forward_to_deserialize_any_method!{deserialize_f32<$l, $v>()}
|
||||
|
||||
+18
-1
@@ -313,6 +313,8 @@ mod content {
|
||||
}
|
||||
}
|
||||
|
||||
/// Used to capture data in [`Content`] from other deserializers.
|
||||
/// Cannot capture externally tagged enums, `i128` and `u128`.
|
||||
struct ContentVisitor<'de> {
|
||||
value: PhantomData<Content<'de>>,
|
||||
}
|
||||
@@ -528,6 +530,8 @@ mod content {
|
||||
Content(Content<'de>),
|
||||
}
|
||||
|
||||
/// Serves as a seed for deserializing a key of internally tagged enum.
|
||||
/// Cannot capture externally tagged enums, `i128` and `u128`.
|
||||
struct TagOrContentVisitor<'de> {
|
||||
name: &'static str,
|
||||
value: PhantomData<TagOrContent<'de>>,
|
||||
@@ -814,6 +818,9 @@ mod content {
|
||||
|
||||
/// Used by generated code to deserialize an internally tagged enum.
|
||||
///
|
||||
/// Captures map or sequence from the original deserializer and searches
|
||||
/// a tag in it (in case of sequence, tag is the first element of sequence).
|
||||
///
|
||||
/// Not public API.
|
||||
pub struct TaggedContentVisitor<T> {
|
||||
tag_name: &'static str,
|
||||
@@ -2703,6 +2710,17 @@ where
|
||||
visitor.visit_unit()
|
||||
}
|
||||
|
||||
fn deserialize_unit_struct<V>(
|
||||
self,
|
||||
_name: &'static str,
|
||||
visitor: V,
|
||||
) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_unit()
|
||||
}
|
||||
|
||||
fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
@@ -2727,7 +2745,6 @@ where
|
||||
deserialize_string()
|
||||
deserialize_bytes()
|
||||
deserialize_byte_buf()
|
||||
deserialize_unit_struct(&'static str)
|
||||
deserialize_seq()
|
||||
deserialize_tuple(usize)
|
||||
deserialize_tuple_struct(&'static str, usize)
|
||||
|
||||
@@ -56,7 +56,10 @@ macro_rules! __serialize_unimplemented {
|
||||
#[macro_export]
|
||||
macro_rules! __serialize_unimplemented_method {
|
||||
($func:ident $(<$t:ident>)* ($($arg:ty),*) -> $ret:ident) => {
|
||||
fn $func $(<$t: ?Sized + $crate::Serialize>)* (self $(, _: $arg)*) -> $crate::__private::Result<Self::$ret, Self::Error> {
|
||||
fn $func $(<$t>)* (self $(, _: $arg)*) -> $crate::__private::Result<Self::$ret, Self::Error>
|
||||
where
|
||||
$($t: ?Sized + $crate::Serialize,)*
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
};
|
||||
|
||||
+71
-83
@@ -51,8 +51,6 @@ enum Unsupported {
|
||||
String,
|
||||
ByteArray,
|
||||
Optional,
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
UnitStruct,
|
||||
Sequence,
|
||||
Tuple,
|
||||
TupleStruct,
|
||||
@@ -69,8 +67,6 @@ impl Display for Unsupported {
|
||||
Unsupported::String => formatter.write_str("a string"),
|
||||
Unsupported::ByteArray => formatter.write_str("a byte array"),
|
||||
Unsupported::Optional => formatter.write_str("an optional"),
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
Unsupported::UnitStruct => formatter.write_str("unit struct"),
|
||||
Unsupported::Sequence => formatter.write_str("a sequence"),
|
||||
Unsupported::Tuple => formatter.write_str("a tuple"),
|
||||
Unsupported::TupleStruct => formatter.write_str("a tuple struct"),
|
||||
@@ -174,9 +170,9 @@ where
|
||||
Err(self.bad_type(Unsupported::Optional))
|
||||
}
|
||||
|
||||
fn serialize_some<T: ?Sized>(self, _: &T) -> Result<Self::Ok, Self::Error>
|
||||
fn serialize_some<T>(self, _: &T) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
Err(self.bad_type(Unsupported::Optional))
|
||||
}
|
||||
@@ -205,18 +201,18 @@ where
|
||||
map.end()
|
||||
}
|
||||
|
||||
fn serialize_newtype_struct<T: ?Sized>(
|
||||
fn serialize_newtype_struct<T>(
|
||||
self,
|
||||
_: &'static str,
|
||||
value: &T,
|
||||
) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
value.serialize(self)
|
||||
}
|
||||
|
||||
fn serialize_newtype_variant<T: ?Sized>(
|
||||
fn serialize_newtype_variant<T>(
|
||||
self,
|
||||
_: &'static str,
|
||||
_: u32,
|
||||
@@ -224,7 +220,7 @@ where
|
||||
inner_value: &T,
|
||||
) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let mut map = tri!(self.delegate.serialize_map(Some(2)));
|
||||
tri!(map.serialize_entry(self.tag, self.variant_name));
|
||||
@@ -327,9 +323,9 @@ where
|
||||
}
|
||||
|
||||
#[cfg(not(any(feature = "std", feature = "alloc")))]
|
||||
fn collect_str<T: ?Sized>(self, _: &T) -> Result<Self::Ok, Self::Error>
|
||||
fn collect_str<T>(self, _: &T) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Display,
|
||||
T: ?Sized + Display,
|
||||
{
|
||||
Err(self.bad_type(Unsupported::String))
|
||||
}
|
||||
@@ -364,9 +360,9 @@ mod content {
|
||||
type Ok = M::Ok;
|
||||
type Error = M::Error;
|
||||
|
||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), M::Error>
|
||||
fn serialize_field<T>(&mut self, value: &T) -> Result<(), M::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let value = tri!(value.serialize(ContentSerializer::<M::Error>::new()));
|
||||
self.fields.push(value);
|
||||
@@ -404,13 +400,9 @@ mod content {
|
||||
type Ok = M::Ok;
|
||||
type Error = M::Error;
|
||||
|
||||
fn serialize_field<T: ?Sized>(
|
||||
&mut self,
|
||||
key: &'static str,
|
||||
value: &T,
|
||||
) -> Result<(), M::Error>
|
||||
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), M::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let value = tri!(value.serialize(ContentSerializer::<M::Error>::new()));
|
||||
self.fields.push((key, value));
|
||||
@@ -635,9 +627,9 @@ mod content {
|
||||
Ok(Content::None)
|
||||
}
|
||||
|
||||
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Content, E>
|
||||
fn serialize_some<T>(self, value: &T) -> Result<Content, E>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
Ok(Content::Some(Box::new(tri!(value.serialize(self)))))
|
||||
}
|
||||
@@ -659,13 +651,9 @@ mod content {
|
||||
Ok(Content::UnitVariant(name, variant_index, variant))
|
||||
}
|
||||
|
||||
fn serialize_newtype_struct<T: ?Sized>(
|
||||
self,
|
||||
name: &'static str,
|
||||
value: &T,
|
||||
) -> Result<Content, E>
|
||||
fn serialize_newtype_struct<T>(self, name: &'static str, value: &T) -> Result<Content, E>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
Ok(Content::NewtypeStruct(
|
||||
name,
|
||||
@@ -673,7 +661,7 @@ mod content {
|
||||
))
|
||||
}
|
||||
|
||||
fn serialize_newtype_variant<T: ?Sized>(
|
||||
fn serialize_newtype_variant<T>(
|
||||
self,
|
||||
name: &'static str,
|
||||
variant_index: u32,
|
||||
@@ -681,7 +669,7 @@ mod content {
|
||||
value: &T,
|
||||
) -> Result<Content, E>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
Ok(Content::NewtypeVariant(
|
||||
name,
|
||||
@@ -782,9 +770,9 @@ mod content {
|
||||
type Ok = Content;
|
||||
type Error = E;
|
||||
|
||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), E>
|
||||
fn serialize_element<T>(&mut self, value: &T) -> Result<(), E>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
|
||||
self.elements.push(value);
|
||||
@@ -808,9 +796,9 @@ mod content {
|
||||
type Ok = Content;
|
||||
type Error = E;
|
||||
|
||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), E>
|
||||
fn serialize_element<T>(&mut self, value: &T) -> Result<(), E>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
|
||||
self.elements.push(value);
|
||||
@@ -835,9 +823,9 @@ mod content {
|
||||
type Ok = Content;
|
||||
type Error = E;
|
||||
|
||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), E>
|
||||
fn serialize_field<T>(&mut self, value: &T) -> Result<(), E>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
|
||||
self.fields.push(value);
|
||||
@@ -864,9 +852,9 @@ mod content {
|
||||
type Ok = Content;
|
||||
type Error = E;
|
||||
|
||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), E>
|
||||
fn serialize_field<T>(&mut self, value: &T) -> Result<(), E>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
|
||||
self.fields.push(value);
|
||||
@@ -896,18 +884,18 @@ mod content {
|
||||
type Ok = Content;
|
||||
type Error = E;
|
||||
|
||||
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), E>
|
||||
fn serialize_key<T>(&mut self, key: &T) -> Result<(), E>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let key = tri!(key.serialize(ContentSerializer::<E>::new()));
|
||||
self.key = Some(key);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), E>
|
||||
fn serialize_value<T>(&mut self, value: &T) -> Result<(), E>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let key = self
|
||||
.key
|
||||
@@ -922,10 +910,10 @@ mod content {
|
||||
Ok(Content::Map(self.entries))
|
||||
}
|
||||
|
||||
fn serialize_entry<K: ?Sized, V: ?Sized>(&mut self, key: &K, value: &V) -> Result<(), E>
|
||||
fn serialize_entry<K, V>(&mut self, key: &K, value: &V) -> Result<(), E>
|
||||
where
|
||||
K: Serialize,
|
||||
V: Serialize,
|
||||
K: ?Sized + Serialize,
|
||||
V: ?Sized + Serialize,
|
||||
{
|
||||
let key = tri!(key.serialize(ContentSerializer::<E>::new()));
|
||||
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
|
||||
@@ -947,9 +935,9 @@ mod content {
|
||||
type Ok = Content;
|
||||
type Error = E;
|
||||
|
||||
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), E>
|
||||
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), E>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
|
||||
self.fields.push((key, value));
|
||||
@@ -976,9 +964,9 @@ mod content {
|
||||
type Ok = Content;
|
||||
type Error = E;
|
||||
|
||||
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), E>
|
||||
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), E>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let value = tri!(value.serialize(ContentSerializer::<E>::new()));
|
||||
self.fields.push((key, value));
|
||||
@@ -1088,9 +1076,9 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
|
||||
fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
value.serialize(self)
|
||||
}
|
||||
@@ -1100,7 +1088,7 @@ where
|
||||
}
|
||||
|
||||
fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
|
||||
Err(Self::bad_type(Unsupported::UnitStruct))
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_unit_variant(
|
||||
@@ -1112,18 +1100,18 @@ where
|
||||
Err(Self::bad_type(Unsupported::Enum))
|
||||
}
|
||||
|
||||
fn serialize_newtype_struct<T: ?Sized>(
|
||||
fn serialize_newtype_struct<T>(
|
||||
self,
|
||||
_: &'static str,
|
||||
value: &T,
|
||||
) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
value.serialize(self)
|
||||
}
|
||||
|
||||
fn serialize_newtype_variant<T: ?Sized>(
|
||||
fn serialize_newtype_variant<T>(
|
||||
self,
|
||||
_: &'static str,
|
||||
_: u32,
|
||||
@@ -1131,10 +1119,9 @@ where
|
||||
value: &T,
|
||||
) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
tri!(self.0.serialize_key(variant));
|
||||
self.0.serialize_value(value)
|
||||
self.0.serialize_entry(variant, value)
|
||||
}
|
||||
|
||||
fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
|
||||
@@ -1202,28 +1189,24 @@ where
|
||||
type Ok = ();
|
||||
type Error = M::Error;
|
||||
|
||||
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
|
||||
fn serialize_key<T>(&mut self, key: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
self.0.serialize_key(key)
|
||||
}
|
||||
|
||||
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
fn serialize_value<T>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
self.0.serialize_value(value)
|
||||
}
|
||||
|
||||
fn serialize_entry<K: ?Sized, V: ?Sized>(
|
||||
&mut self,
|
||||
key: &K,
|
||||
value: &V,
|
||||
) -> Result<(), Self::Error>
|
||||
fn serialize_entry<K, V>(&mut self, key: &K, value: &V) -> Result<(), Self::Error>
|
||||
where
|
||||
K: Serialize,
|
||||
V: Serialize,
|
||||
K: ?Sized + Serialize,
|
||||
V: ?Sized + Serialize,
|
||||
{
|
||||
self.0.serialize_entry(key, value)
|
||||
}
|
||||
@@ -1244,13 +1227,9 @@ where
|
||||
type Ok = ();
|
||||
type Error = M::Error;
|
||||
|
||||
fn serialize_field<T: ?Sized>(
|
||||
&mut self,
|
||||
key: &'static str,
|
||||
value: &T,
|
||||
) -> Result<(), Self::Error>
|
||||
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
self.0.serialize_entry(key, value)
|
||||
}
|
||||
@@ -1289,9 +1268,9 @@ where
|
||||
type Ok = ();
|
||||
type Error = M::Error;
|
||||
|
||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let value = tri!(value.serialize(ContentSerializer::<M::Error>::new()));
|
||||
self.fields.push(value);
|
||||
@@ -1335,13 +1314,9 @@ where
|
||||
type Ok = ();
|
||||
type Error = M::Error;
|
||||
|
||||
fn serialize_field<T: ?Sized>(
|
||||
&mut self,
|
||||
key: &'static str,
|
||||
value: &T,
|
||||
) -> Result<(), Self::Error>
|
||||
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let value = tri!(value.serialize(ContentSerializer::<M::Error>::new()));
|
||||
self.fields.push((key, value));
|
||||
@@ -1370,3 +1345,16 @@ impl Serialize for AdjacentlyTaggedEnumVariant {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
+10
-15
@@ -52,10 +52,12 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
|
||||
serialize_i16: i16,
|
||||
serialize_i32: i32,
|
||||
serialize_i64: i64,
|
||||
serialize_i128: i128,
|
||||
serialize_u8: u8,
|
||||
serialize_u16: u16,
|
||||
serialize_u32: u32,
|
||||
serialize_u64: u64,
|
||||
serialize_u128: u128,
|
||||
serialize_f32: f32,
|
||||
serialize_f64: f64,
|
||||
serialize_char: char,
|
||||
@@ -63,13 +65,6 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
|
||||
serialize_unit_struct: &'static str,
|
||||
}
|
||||
|
||||
serde_if_integer128! {
|
||||
fmt_primitives! {
|
||||
serialize_i128: i128,
|
||||
serialize_u128: u128,
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_unit_variant(
|
||||
self,
|
||||
_name: &'static str,
|
||||
@@ -79,9 +74,9 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
|
||||
Display::fmt(variant, self)
|
||||
}
|
||||
|
||||
fn serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, value: &T) -> fmt::Result
|
||||
fn serialize_newtype_struct<T>(self, _name: &'static str, value: &T) -> fmt::Result
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
Serialize::serialize(value, self)
|
||||
}
|
||||
@@ -94,9 +89,9 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
|
||||
Err(fmt::Error)
|
||||
}
|
||||
|
||||
fn serialize_some<T: ?Sized>(self, _value: &T) -> fmt::Result
|
||||
fn serialize_some<T>(self, _value: &T) -> fmt::Result
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
Err(fmt::Error)
|
||||
}
|
||||
@@ -105,7 +100,7 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
|
||||
Err(fmt::Error)
|
||||
}
|
||||
|
||||
fn serialize_newtype_variant<T: ?Sized>(
|
||||
fn serialize_newtype_variant<T>(
|
||||
self,
|
||||
_name: &'static str,
|
||||
_variant_index: u32,
|
||||
@@ -113,7 +108,7 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
|
||||
_value: &T,
|
||||
) -> fmt::Result
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
Err(fmt::Error)
|
||||
}
|
||||
@@ -166,9 +161,9 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
|
||||
Err(fmt::Error)
|
||||
}
|
||||
|
||||
fn collect_str<T: ?Sized>(self, value: &T) -> fmt::Result
|
||||
fn collect_str<T>(self, value: &T) -> fmt::Result
|
||||
where
|
||||
T: Display,
|
||||
T: ?Sized + Display,
|
||||
{
|
||||
Display::fmt(value, self)
|
||||
}
|
||||
|
||||
+178
-78
@@ -24,20 +24,17 @@ primitive_impl!(i8, serialize_i8);
|
||||
primitive_impl!(i16, serialize_i16);
|
||||
primitive_impl!(i32, serialize_i32);
|
||||
primitive_impl!(i64, serialize_i64);
|
||||
primitive_impl!(i128, serialize_i128);
|
||||
primitive_impl!(usize, serialize_u64 as u64);
|
||||
primitive_impl!(u8, serialize_u8);
|
||||
primitive_impl!(u16, serialize_u16);
|
||||
primitive_impl!(u32, serialize_u32);
|
||||
primitive_impl!(u64, serialize_u64);
|
||||
primitive_impl!(u128, serialize_u128);
|
||||
primitive_impl!(f32, serialize_f32);
|
||||
primitive_impl!(f64, serialize_f64);
|
||||
primitive_impl!(char, serialize_char);
|
||||
|
||||
serde_if_integer128! {
|
||||
primitive_impl!(i128, serialize_i128);
|
||||
primitive_impl!(u128, serialize_u128);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
impl Serialize for str {
|
||||
@@ -51,6 +48,7 @@ impl Serialize for str {
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
impl Serialize for String {
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
@@ -73,6 +71,7 @@ impl<'a> Serialize for fmt::Arguments<'a> {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(any(feature = "std", not(no_core_cstr)))]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
impl Serialize for CStr {
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
@@ -84,6 +83,7 @@ impl Serialize for CStr {
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", all(not(no_core_cstr), feature = "alloc")))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
impl Serialize for CString {
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
@@ -114,7 +114,10 @@ where
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
impl<T: ?Sized> Serialize for PhantomData<T> {
|
||||
impl<T> Serialize for PhantomData<T>
|
||||
where
|
||||
T: ?Sized,
|
||||
{
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -182,9 +185,13 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(any(feature = "std", feature = "alloc"), not(no_relaxed_trait_bounds)))]
|
||||
#[cfg(not(no_relaxed_trait_bounds))]
|
||||
macro_rules! seq_impl {
|
||||
($ty:ident <T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)*>) => {
|
||||
(
|
||||
$(#[$attr:meta])*
|
||||
$ty:ident <T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)*>
|
||||
) => {
|
||||
$(#[$attr])*
|
||||
impl<T $(, $typaram)*> Serialize for $ty<T $(, $typaram)*>
|
||||
where
|
||||
T: Serialize,
|
||||
@@ -200,9 +207,13 @@ macro_rules! seq_impl {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(any(feature = "std", feature = "alloc"), no_relaxed_trait_bounds))]
|
||||
#[cfg(no_relaxed_trait_bounds)]
|
||||
macro_rules! seq_impl {
|
||||
($ty:ident <T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)*>) => {
|
||||
(
|
||||
$(#[$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 $(+ $tbound1 $(+ $tbound2)*)*,
|
||||
@@ -219,23 +230,41 @@ macro_rules! seq_impl {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
seq_impl!(BinaryHeap<T: Ord>);
|
||||
seq_impl! {
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
BinaryHeap<T: Ord>
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
seq_impl!(BTreeSet<T: Ord>);
|
||||
seq_impl! {
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
BTreeSet<T: Ord>
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
seq_impl!(HashSet<T: Eq + Hash, H: BuildHasher>);
|
||||
seq_impl! {
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
HashSet<T: Eq + Hash, H: BuildHasher>
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
seq_impl!(LinkedList<T>);
|
||||
seq_impl! {
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
LinkedList<T>
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
seq_impl!(Vec<T>);
|
||||
seq_impl! {
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
Vec<T>
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
seq_impl!(VecDeque<T>);
|
||||
seq_impl! {
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
VecDeque<T>
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -342,6 +371,7 @@ impl Serialize for () {
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
|
||||
impl Serialize for ! {
|
||||
fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -356,28 +386,46 @@ impl Serialize for ! {
|
||||
macro_rules! tuple_impls {
|
||||
($($len:expr => ($($n:tt $name:ident)+))+) => {
|
||||
$(
|
||||
#[cfg_attr(docsrs, doc(hidden))]
|
||||
impl<$($name),+> Serialize for ($($name,)+)
|
||||
where
|
||||
$($name: Serialize,)+
|
||||
{
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut tuple = tri!(serializer.serialize_tuple($len));
|
||||
$(
|
||||
tri!(tuple.serialize_element(&self.$n));
|
||||
)+
|
||||
tuple.end()
|
||||
}
|
||||
tuple_impl_body!($len => ($($n)+));
|
||||
}
|
||||
)+
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! tuple_impl_body {
|
||||
($len:expr => ($($n:tt)+)) => {
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut tuple = tri!(serializer.serialize_tuple($len));
|
||||
$(
|
||||
tri!(tuple.serialize_element(&self.$n));
|
||||
)+
|
||||
tuple.end()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg_attr(docsrs, doc(fake_variadic))]
|
||||
#[cfg_attr(
|
||||
docsrs,
|
||||
doc = "This trait is implemented for tuples up to 16 items long."
|
||||
)]
|
||||
impl<T> Serialize for (T,)
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
tuple_impl_body!(1 => (0));
|
||||
}
|
||||
|
||||
tuple_impls! {
|
||||
1 => (0 T0)
|
||||
2 => (0 T0 1 T1)
|
||||
3 => (0 T0 1 T1 2 T2)
|
||||
4 => (0 T0 1 T1 2 T2 3 T3)
|
||||
@@ -397,9 +445,13 @@ tuple_impls! {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(all(any(feature = "std", feature = "alloc"), not(no_relaxed_trait_bounds)))]
|
||||
#[cfg(not(no_relaxed_trait_bounds))]
|
||||
macro_rules! map_impl {
|
||||
($ty:ident <K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)*>) => {
|
||||
(
|
||||
$(#[$attr:meta])*
|
||||
$ty:ident <K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)*>
|
||||
) => {
|
||||
$(#[$attr])*
|
||||
impl<K, V $(, $typaram)*> Serialize for $ty<K, V $(, $typaram)*>
|
||||
where
|
||||
K: Serialize,
|
||||
@@ -416,9 +468,13 @@ macro_rules! map_impl {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(any(feature = "std", feature = "alloc"), no_relaxed_trait_bounds))]
|
||||
#[cfg(no_relaxed_trait_bounds)]
|
||||
macro_rules! map_impl {
|
||||
($ty:ident <K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)*>) => {
|
||||
(
|
||||
$(#[$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 $(+ $kbound1 $(+ $kbound2)*)*,
|
||||
@@ -436,20 +492,26 @@ macro_rules! map_impl {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
map_impl!(BTreeMap<K: Ord, V>);
|
||||
map_impl! {
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
BTreeMap<K: Ord, V>
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
map_impl!(HashMap<K: Eq + Hash, V, H: BuildHasher>);
|
||||
map_impl! {
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
HashMap<K: Eq + Hash, V, H: BuildHasher>
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
macro_rules! deref_impl {
|
||||
(
|
||||
$(#[doc = $doc:tt])*
|
||||
$(#[$attr:meta])*
|
||||
<$($desc:tt)+
|
||||
) => {
|
||||
$(#[doc = $doc])*
|
||||
$(#[$attr])*
|
||||
impl <$($desc)+ {
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
@@ -462,13 +524,20 @@ macro_rules! deref_impl {
|
||||
};
|
||||
}
|
||||
|
||||
deref_impl!(<'a, T: ?Sized> Serialize for &'a T where T: Serialize);
|
||||
deref_impl!(<'a, T: ?Sized> Serialize for &'a mut T where T: Serialize);
|
||||
deref_impl! {
|
||||
<'a, T> Serialize for &'a T where T: ?Sized + Serialize
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
deref_impl!(<T: ?Sized> Serialize for Box<T> where T: Serialize);
|
||||
deref_impl! {
|
||||
<'a, T> Serialize for &'a mut T where T: ?Sized + Serialize
|
||||
}
|
||||
|
||||
deref_impl! {
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
<T> Serialize for Box<T> where T: ?Sized + Serialize
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||
deref_impl! {
|
||||
/// This impl requires the [`"rc"`] Cargo feature of Serde.
|
||||
///
|
||||
@@ -478,10 +547,11 @@ deref_impl! {
|
||||
/// repeated data.
|
||||
///
|
||||
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
||||
<T: ?Sized> Serialize for Rc<T> where T: Serialize
|
||||
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||
#[cfg_attr(docsrs, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))]
|
||||
<T> Serialize for Rc<T> where T: ?Sized + Serialize
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||
deref_impl! {
|
||||
/// This impl requires the [`"rc"`] Cargo feature of Serde.
|
||||
///
|
||||
@@ -491,11 +561,16 @@ deref_impl! {
|
||||
/// repeated data.
|
||||
///
|
||||
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
||||
<T: ?Sized> Serialize for Arc<T> where T: Serialize
|
||||
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||
#[cfg_attr(docsrs, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))]
|
||||
<T> Serialize for Arc<T> where T: ?Sized + Serialize
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned);
|
||||
deref_impl! {
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||
<'a, T> Serialize for Cow<'a, T> where T: ?Sized + Serialize + ToOwned
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -503,9 +578,13 @@ deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwne
|
||||
///
|
||||
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
||||
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||
impl<T: ?Sized> Serialize for RcWeak<T>
|
||||
#[cfg_attr(
|
||||
docsrs,
|
||||
doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc"))))
|
||||
)]
|
||||
impl<T> Serialize for RcWeak<T>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -519,9 +598,13 @@ where
|
||||
///
|
||||
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
||||
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||
impl<T: ?Sized> Serialize for ArcWeak<T>
|
||||
#[cfg_attr(
|
||||
docsrs,
|
||||
doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc"))))
|
||||
)]
|
||||
impl<T> Serialize for ArcWeak<T>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -553,6 +636,7 @@ nonzero_integers! {
|
||||
NonZeroU16,
|
||||
NonZeroU32,
|
||||
NonZeroU64,
|
||||
NonZeroU128,
|
||||
NonZeroUsize,
|
||||
}
|
||||
|
||||
@@ -562,22 +646,10 @@ nonzero_integers! {
|
||||
NonZeroI16,
|
||||
NonZeroI32,
|
||||
NonZeroI64,
|
||||
NonZeroI128,
|
||||
NonZeroIsize,
|
||||
}
|
||||
|
||||
// Currently 128-bit integers do not work on Emscripten targets so we need an
|
||||
// additional `#[cfg]`
|
||||
serde_if_integer128! {
|
||||
nonzero_integers! {
|
||||
NonZeroU128,
|
||||
}
|
||||
|
||||
#[cfg(not(no_num_nonzero_signed))]
|
||||
nonzero_integers! {
|
||||
NonZeroI128,
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Serialize for Cell<T>
|
||||
where
|
||||
T: Serialize + Copy,
|
||||
@@ -590,9 +662,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Serialize for RefCell<T>
|
||||
impl<T> Serialize for RefCell<T>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -606,9 +678,10 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<T: ?Sized> Serialize for Mutex<T>
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
impl<T> Serialize for Mutex<T>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -622,9 +695,10 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<T: ?Sized> Serialize for RwLock<T>
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
impl<T> Serialize for RwLock<T>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -675,6 +749,7 @@ impl Serialize for Duration {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
impl Serialize for SystemTime {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -719,6 +794,7 @@ macro_rules! serialize_display_bounded_length {
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
impl Serialize for net::IpAddr {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -789,6 +865,7 @@ fn test_format_u8() {
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
impl Serialize for net::Ipv4Addr {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -813,6 +890,7 @@ impl Serialize for net::Ipv4Addr {
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
impl Serialize for net::Ipv6Addr {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -829,6 +907,7 @@ impl Serialize for net::Ipv6Addr {
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
impl Serialize for net::SocketAddr {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -853,6 +932,7 @@ impl Serialize for net::SocketAddr {
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
impl Serialize for net::SocketAddrV4 {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -869,6 +949,7 @@ impl Serialize for net::SocketAddrV4 {
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
impl Serialize for net::SocketAddrV6 {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -890,6 +971,7 @@ impl Serialize for net::SocketAddrV6 {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
impl Serialize for Path {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -903,6 +985,7 @@ impl Serialize for Path {
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
impl Serialize for PathBuf {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -913,6 +996,7 @@ impl Serialize for PathBuf {
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "std", any(unix, windows)))]
|
||||
#[cfg_attr(docsrs, 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>
|
||||
@@ -935,6 +1019,7 @@ impl Serialize for OsStr {
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "std", any(unix, windows)))]
|
||||
#[cfg_attr(docsrs, doc(cfg(all(feature = "std", any(unix, windows)))))]
|
||||
impl Serialize for OsString {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -959,6 +1044,20 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(no_core_num_saturating))]
|
||||
impl<T> Serialize for Saturating<T>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
self.0.serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Serialize for Reverse<T>
|
||||
where
|
||||
T: Serialize,
|
||||
@@ -979,6 +1078,7 @@ macro_rules! atomic_impl {
|
||||
($($ty:ident $size:expr)*) => {
|
||||
$(
|
||||
#[cfg(any(no_target_has_atomic, target_has_atomic = $size))]
|
||||
#[cfg_attr(docsrs, 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
|
||||
|
||||
+16
-16
@@ -72,9 +72,9 @@ where
|
||||
type Ok = Ok;
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
|
||||
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Error>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let _ = value;
|
||||
match self.void {}
|
||||
@@ -92,9 +92,9 @@ where
|
||||
type Ok = Ok;
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
|
||||
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Error>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let _ = value;
|
||||
match self.void {}
|
||||
@@ -112,9 +112,9 @@ where
|
||||
type Ok = Ok;
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
|
||||
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Error>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let _ = value;
|
||||
match self.void {}
|
||||
@@ -132,9 +132,9 @@ where
|
||||
type Ok = Ok;
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
|
||||
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Error>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let _ = value;
|
||||
match self.void {}
|
||||
@@ -152,17 +152,17 @@ where
|
||||
type Ok = Ok;
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Error>
|
||||
fn serialize_key<T>(&mut self, key: &T) -> Result<(), Error>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let _ = key;
|
||||
match self.void {}
|
||||
}
|
||||
|
||||
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
|
||||
fn serialize_value<T>(&mut self, value: &T) -> Result<(), Error>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let _ = value;
|
||||
match self.void {}
|
||||
@@ -180,9 +180,9 @@ where
|
||||
type Ok = Ok;
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
|
||||
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let _ = key;
|
||||
let _ = value;
|
||||
@@ -201,9 +201,9 @@ where
|
||||
type Ok = Ok;
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
|
||||
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
|
||||
where
|
||||
T: Serialize,
|
||||
T: ?Sized + Serialize,
|
||||
{
|
||||
let _ = key;
|
||||
let _ = value;
|
||||
|
||||
+88
-92
@@ -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\>
|
||||
@@ -215,6 +215,13 @@ declare_error_trait!(Error: Sized + Debug + Display);
|
||||
/// [`linked-hash-map`]: https://crates.io/crates/linked-hash-map
|
||||
/// [`serde_derive`]: https://crates.io/crates/serde_derive
|
||||
/// [derive section of the manual]: https://serde.rs/derive.html
|
||||
#[cfg_attr(
|
||||
not(no_diagnostic_namespace),
|
||||
diagnostic::on_unimplemented(
|
||||
note = "for local types consider adding `#[derive(serde::Serialize)]` to your `{Self}` type",
|
||||
note = "for types from other crates check whether the crate offers a `serde` feature flag",
|
||||
)
|
||||
)]
|
||||
pub trait Serialize {
|
||||
/// Serialize this value into the given Serde serializer.
|
||||
///
|
||||
@@ -488,30 +495,27 @@ pub trait Serializer: Sized {
|
||||
/// ```
|
||||
fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error>;
|
||||
|
||||
serde_if_integer128! {
|
||||
/// 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)
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// 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 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"))
|
||||
}
|
||||
|
||||
/// Serialize a `u8` value.
|
||||
@@ -598,30 +602,27 @@ pub trait Serializer: Sized {
|
||||
/// ```
|
||||
fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error>;
|
||||
|
||||
serde_if_integer128! {
|
||||
/// 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)
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// 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 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"))
|
||||
}
|
||||
|
||||
/// Serialize an `f32` value.
|
||||
@@ -802,9 +803,9 @@ pub trait Serializer: Sized {
|
||||
/// ```
|
||||
///
|
||||
/// [`Some(T)`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.Some
|
||||
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
|
||||
fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Serialize;
|
||||
T: ?Sized + Serialize;
|
||||
|
||||
/// Serialize a `()` value.
|
||||
///
|
||||
@@ -897,13 +898,13 @@ pub trait Serializer: Sized {
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
fn serialize_newtype_struct<T: ?Sized>(
|
||||
fn serialize_newtype_struct<T>(
|
||||
self,
|
||||
name: &'static str,
|
||||
value: &T,
|
||||
) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Serialize;
|
||||
T: ?Sized + Serialize;
|
||||
|
||||
/// Serialize a newtype variant like `E::N` in `enum E { N(u8) }`.
|
||||
///
|
||||
@@ -931,7 +932,7 @@ pub trait Serializer: Sized {
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
fn serialize_newtype_variant<T: ?Sized>(
|
||||
fn serialize_newtype_variant<T>(
|
||||
self,
|
||||
name: &'static str,
|
||||
variant_index: u32,
|
||||
@@ -939,7 +940,7 @@ pub trait Serializer: Sized {
|
||||
value: &T,
|
||||
) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Serialize;
|
||||
T: ?Sized + Serialize;
|
||||
|
||||
/// Begin to serialize a variably sized sequence. This call must be
|
||||
/// followed by zero or more calls to `serialize_element`, then a call to
|
||||
@@ -1176,7 +1177,8 @@ pub trait Serializer: Sized {
|
||||
/// then a call to `end`.
|
||||
///
|
||||
/// The `name` is the name of the struct and the `len` is the number of
|
||||
/// data fields that will be serialized.
|
||||
/// data fields that will be serialized. `len` does not include fields
|
||||
/// which are skipped with [`SerializeStruct::skip_field`].
|
||||
///
|
||||
/// ```edition2021
|
||||
/// use serde::ser::{Serialize, SerializeStruct, Serializer};
|
||||
@@ -1213,6 +1215,8 @@ pub trait Serializer: Sized {
|
||||
/// The `name` is the name of the enum, the `variant_index` is the index of
|
||||
/// 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.
|
||||
/// `len` does not include fields which are skipped with
|
||||
/// [`SerializeStructVariant::skip_field`].
|
||||
///
|
||||
/// ```edition2021
|
||||
/// use serde::ser::{Serialize, SerializeStructVariant, Serializer};
|
||||
@@ -1352,9 +1356,9 @@ pub trait Serializer: Sized {
|
||||
/// [`String`]: https://doc.rust-lang.org/std/string/struct.String.html
|
||||
/// [`serialize_str`]: #tymethod.serialize_str
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
fn collect_str<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
|
||||
fn collect_str<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Display,
|
||||
T: ?Sized + Display,
|
||||
{
|
||||
self.serialize_str(&value.to_string())
|
||||
}
|
||||
@@ -1385,9 +1389,9 @@ pub trait Serializer: Sized {
|
||||
/// }
|
||||
/// ```
|
||||
#[cfg(not(any(feature = "std", feature = "alloc")))]
|
||||
fn collect_str<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
|
||||
fn collect_str<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Display;
|
||||
T: ?Sized + Display;
|
||||
|
||||
/// Determine whether `Serialize` implementations should serialize in
|
||||
/// human-readable form.
|
||||
@@ -1499,9 +1503,9 @@ pub trait SerializeSeq {
|
||||
type Error: Error;
|
||||
|
||||
/// Serialize a sequence element.
|
||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize;
|
||||
T: ?Sized + Serialize;
|
||||
|
||||
/// Finish serializing a sequence.
|
||||
fn end(self) -> Result<Self::Ok, Self::Error>;
|
||||
@@ -1599,9 +1603,9 @@ pub trait SerializeTuple {
|
||||
type Error: Error;
|
||||
|
||||
/// Serialize a tuple element.
|
||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize;
|
||||
T: ?Sized + Serialize;
|
||||
|
||||
/// Finish serializing a tuple.
|
||||
fn end(self) -> Result<Self::Ok, Self::Error>;
|
||||
@@ -1644,9 +1648,9 @@ pub trait SerializeTupleStruct {
|
||||
type Error: Error;
|
||||
|
||||
/// Serialize a tuple struct field.
|
||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize;
|
||||
T: ?Sized + Serialize;
|
||||
|
||||
/// Finish serializing a tuple struct.
|
||||
fn end(self) -> Result<Self::Ok, Self::Error>;
|
||||
@@ -1702,9 +1706,9 @@ pub trait SerializeTupleVariant {
|
||||
type Error: Error;
|
||||
|
||||
/// Serialize a tuple variant field.
|
||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize;
|
||||
T: ?Sized + Serialize;
|
||||
|
||||
/// Finish serializing a tuple variant.
|
||||
fn end(self) -> Result<Self::Ok, Self::Error>;
|
||||
@@ -1773,9 +1777,9 @@ pub trait SerializeMap {
|
||||
/// `serialize_entry` instead as it may be implemented more efficiently in
|
||||
/// some formats compared to a pair of calls to `serialize_key` and
|
||||
/// `serialize_value`.
|
||||
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
|
||||
fn serialize_key<T>(&mut self, key: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize;
|
||||
T: ?Sized + Serialize;
|
||||
|
||||
/// Serialize a map value.
|
||||
///
|
||||
@@ -1783,9 +1787,9 @@ pub trait SerializeMap {
|
||||
///
|
||||
/// Calling `serialize_value` before `serialize_key` is incorrect and is
|
||||
/// allowed to panic or produce bogus results.
|
||||
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
fn serialize_value<T>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize;
|
||||
T: ?Sized + Serialize;
|
||||
|
||||
/// Serialize a map entry consisting of a key and a value.
|
||||
///
|
||||
@@ -1804,14 +1808,10 @@ pub trait SerializeMap {
|
||||
/// [`Serialize`]: ../trait.Serialize.html
|
||||
/// [`serialize_key`]: #tymethod.serialize_key
|
||||
/// [`serialize_value`]: #tymethod.serialize_value
|
||||
fn serialize_entry<K: ?Sized, V: ?Sized>(
|
||||
&mut self,
|
||||
key: &K,
|
||||
value: &V,
|
||||
) -> Result<(), Self::Error>
|
||||
fn serialize_entry<K, V>(&mut self, key: &K, value: &V) -> Result<(), Self::Error>
|
||||
where
|
||||
K: Serialize,
|
||||
V: Serialize,
|
||||
K: ?Sized + Serialize,
|
||||
V: ?Sized + Serialize,
|
||||
{
|
||||
tri!(self.serialize_key(key));
|
||||
self.serialize_value(value)
|
||||
@@ -1862,15 +1862,13 @@ pub trait SerializeStruct {
|
||||
type Error: Error;
|
||||
|
||||
/// Serialize a struct field.
|
||||
fn serialize_field<T: ?Sized>(
|
||||
&mut self,
|
||||
key: &'static str,
|
||||
value: &T,
|
||||
) -> Result<(), Self::Error>
|
||||
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize;
|
||||
T: ?Sized + Serialize;
|
||||
|
||||
/// Indicate that a struct field has been skipped.
|
||||
///
|
||||
/// The default implementation does nothing.
|
||||
#[inline]
|
||||
fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> {
|
||||
let _ = key;
|
||||
@@ -1928,15 +1926,13 @@ pub trait SerializeStructVariant {
|
||||
type Error: Error;
|
||||
|
||||
/// Serialize a struct variant field.
|
||||
fn serialize_field<T: ?Sized>(
|
||||
&mut self,
|
||||
key: &'static str,
|
||||
value: &T,
|
||||
) -> Result<(), Self::Error>
|
||||
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize;
|
||||
T: ?Sized + Serialize;
|
||||
|
||||
/// Indicate that a struct variant field has been skipped.
|
||||
///
|
||||
/// The default implementation does nothing.
|
||||
#[inline]
|
||||
fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> {
|
||||
let _ = key;
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
[package]
|
||||
name = "serde_derive"
|
||||
version = "1.0.182" # remember to update html_root_url
|
||||
version = "1.0.208"
|
||||
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"
|
||||
edition = "2015"
|
||||
exclude = ["build.rs"]
|
||||
homepage = "https://serde.rs"
|
||||
keywords = ["serde", "serialization", "no_std", "derive"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
@@ -21,9 +23,9 @@ name = "serde_derive"
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = "1.0"
|
||||
quote = "1.0"
|
||||
syn = "2.0.28"
|
||||
proc-macro2 = { workspace = true, features = ["proc-macro"] }
|
||||
quote = { workspace = true, features = ["proc-macro"] }
|
||||
syn = { workspace = true, features = ["clone-impls", "derive", "parsing", "printing", "proc-macro"] }
|
||||
|
||||
[dev-dependencies]
|
||||
serde = { version = "1", path = "../serde" }
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fn main() {
|
||||
// Warning: build.rs is not published to crates.io.
|
||||
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
println!("cargo:rustc-cfg=check_cfg");
|
||||
println!("cargo:rustc-check-cfg=cfg(check_cfg)");
|
||||
println!("cargo:rustc-check-cfg=cfg(exhaustive)");
|
||||
}
|
||||
@@ -144,6 +144,7 @@ pub fn with_bound(
|
||||
|
||||
fn visit_type(&mut self, ty: &'ast syn::Type) {
|
||||
match ty {
|
||||
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
syn::Type::Array(ty) => self.visit_type(&ty.elem),
|
||||
syn::Type::BareFn(ty) => {
|
||||
for arg in &ty.inputs {
|
||||
@@ -181,7 +182,6 @@ pub fn with_bound(
|
||||
|
||||
syn::Type::Infer(_) | syn::Type::Never(_) | syn::Type::Verbatim(_) => {}
|
||||
|
||||
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -196,16 +196,13 @@ 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::Lifetime(_)
|
||||
| syn::GenericArgument::Const(_)
|
||||
| syn::GenericArgument::AssocConst(_)
|
||||
| syn::GenericArgument::Constraint(_) => {}
|
||||
#[cfg_attr(
|
||||
all(test, exhaustive),
|
||||
deny(non_exhaustive_omitted_patterns)
|
||||
)]
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -228,9 +225,9 @@ 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(_) => {}
|
||||
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
+102
-65
@@ -6,8 +6,6 @@ use proc_macro2::{Literal, Span, TokenStream};
|
||||
use quote::{quote, quote_spanned, ToTokens};
|
||||
use std::collections::BTreeSet;
|
||||
use std::ptr;
|
||||
#[cfg(precompiled)]
|
||||
use std::sync::atomic::Ordering;
|
||||
use syn::punctuated::Punctuated;
|
||||
use syn::spanned::Spanned;
|
||||
use syn::{parse_quote, Ident, Index, Member};
|
||||
@@ -301,11 +299,6 @@ fn deserialize_body(cont: &Container, params: &Parameters) -> Fragment {
|
||||
|
||||
#[cfg(feature = "deserialize_in_place")]
|
||||
fn deserialize_in_place_body(cont: &Container, params: &Parameters) -> Option<Stmts> {
|
||||
#[cfg(precompiled)]
|
||||
if !crate::DESERIALIZE_IN_PLACE.load(Ordering::Relaxed) {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Only remote derives have getters, and we do not generate
|
||||
// deserialize_in_place for remote derives.
|
||||
assert!(!params.has_getter);
|
||||
@@ -468,7 +461,10 @@ fn deserialize_tuple(
|
||||
cattrs: &attr::Container,
|
||||
form: TupleForm,
|
||||
) -> Fragment {
|
||||
assert!(!cattrs.has_flatten());
|
||||
assert!(
|
||||
!has_flatten(fields),
|
||||
"tuples and tuple variants cannot have flatten fields"
|
||||
);
|
||||
|
||||
let field_count = fields
|
||||
.iter()
|
||||
@@ -586,7 +582,10 @@ fn deserialize_tuple_in_place(
|
||||
fields: &[Field],
|
||||
cattrs: &attr::Container,
|
||||
) -> Fragment {
|
||||
assert!(!cattrs.has_flatten());
|
||||
assert!(
|
||||
!has_flatten(fields),
|
||||
"tuples and tuple variants cannot have flatten fields"
|
||||
);
|
||||
|
||||
let field_count = fields
|
||||
.iter()
|
||||
@@ -965,18 +964,15 @@ fn deserialize_struct(
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
let field_visitor = Stmts(deserialize_generated_identifier(
|
||||
&field_names_idents,
|
||||
cattrs,
|
||||
false,
|
||||
None,
|
||||
));
|
||||
|
||||
let has_flatten = has_flatten(fields);
|
||||
let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs, has_flatten);
|
||||
|
||||
// untagged struct variants do not get a visit_seq method. The same applies to
|
||||
// structs that only have a map representation.
|
||||
let visit_seq = match form {
|
||||
StructForm::Untagged(..) => None,
|
||||
_ if cattrs.has_flatten() => None,
|
||||
_ if has_flatten => None,
|
||||
_ => {
|
||||
let mut_seq = if field_names_idents.is_empty() {
|
||||
quote!(_)
|
||||
@@ -999,10 +995,16 @@ fn deserialize_struct(
|
||||
})
|
||||
}
|
||||
};
|
||||
let visit_map = Stmts(deserialize_map(&type_path, params, fields, cattrs));
|
||||
let visit_map = Stmts(deserialize_map(
|
||||
&type_path,
|
||||
params,
|
||||
fields,
|
||||
cattrs,
|
||||
has_flatten,
|
||||
));
|
||||
|
||||
let visitor_seed = match form {
|
||||
StructForm::ExternallyTagged(..) if cattrs.has_flatten() => Some(quote! {
|
||||
StructForm::ExternallyTagged(..) if has_flatten => Some(quote! {
|
||||
impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Visitor #de_ty_generics #where_clause {
|
||||
type Value = #this_type #ty_generics;
|
||||
|
||||
@@ -1017,7 +1019,7 @@ fn deserialize_struct(
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let fields_stmt = if cattrs.has_flatten() {
|
||||
let fields_stmt = if has_flatten {
|
||||
None
|
||||
} else {
|
||||
let field_names = field_names_idents
|
||||
@@ -1037,7 +1039,7 @@ fn deserialize_struct(
|
||||
}
|
||||
};
|
||||
let dispatch = match form {
|
||||
StructForm::Struct if cattrs.has_flatten() => quote! {
|
||||
StructForm::Struct if has_flatten => quote! {
|
||||
_serde::Deserializer::deserialize_map(__deserializer, #visitor_expr)
|
||||
},
|
||||
StructForm::Struct => {
|
||||
@@ -1046,7 +1048,7 @@ fn deserialize_struct(
|
||||
_serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, #visitor_expr)
|
||||
}
|
||||
}
|
||||
StructForm::ExternallyTagged(_) if cattrs.has_flatten() => quote! {
|
||||
StructForm::ExternallyTagged(_) if has_flatten => quote! {
|
||||
_serde::de::VariantAccess::newtype_variant_seed(__variant, #visitor_expr)
|
||||
},
|
||||
StructForm::ExternallyTagged(_) => quote! {
|
||||
@@ -1103,7 +1105,7 @@ fn deserialize_struct_in_place(
|
||||
) -> Option<Fragment> {
|
||||
// for now we do not support in_place deserialization for structs that
|
||||
// are represented as map.
|
||||
if cattrs.has_flatten() {
|
||||
if has_flatten(fields) {
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -1128,12 +1130,7 @@ fn deserialize_struct_in_place(
|
||||
})
|
||||
.collect();
|
||||
|
||||
let field_visitor = Stmts(deserialize_generated_identifier(
|
||||
&field_names_idents,
|
||||
cattrs,
|
||||
false,
|
||||
None,
|
||||
));
|
||||
let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs, false);
|
||||
|
||||
let mut_seq = if field_names_idents.is_empty() {
|
||||
quote!(_)
|
||||
@@ -1227,10 +1224,7 @@ fn deserialize_homogeneous_enum(
|
||||
}
|
||||
}
|
||||
|
||||
fn prepare_enum_variant_enum(
|
||||
variants: &[Variant],
|
||||
cattrs: &attr::Container,
|
||||
) -> (TokenStream, Stmts) {
|
||||
fn prepare_enum_variant_enum(variants: &[Variant]) -> (TokenStream, Stmts) {
|
||||
let mut deserialized_variants = variants
|
||||
.iter()
|
||||
.enumerate()
|
||||
@@ -1247,7 +1241,12 @@ fn prepare_enum_variant_enum(
|
||||
})
|
||||
.collect();
|
||||
|
||||
let other_idx = deserialized_variants.position(|(_, variant)| variant.attrs.other());
|
||||
let fallthrough = deserialized_variants
|
||||
.position(|(_, variant)| variant.attrs.other())
|
||||
.map(|other_idx| {
|
||||
let ignore_variant = variant_names_idents[other_idx].1.clone();
|
||||
quote!(_serde::__private::Ok(__Field::#ignore_variant))
|
||||
});
|
||||
|
||||
let variants_stmt = {
|
||||
let variant_names = variant_names_idents.iter().map(|(name, _, _)| name);
|
||||
@@ -1259,9 +1258,10 @@ fn prepare_enum_variant_enum(
|
||||
|
||||
let variant_visitor = Stmts(deserialize_generated_identifier(
|
||||
&variant_names_idents,
|
||||
cattrs,
|
||||
false, // variant identifiers do not depend on the presence of flatten fields
|
||||
true,
|
||||
other_idx,
|
||||
None,
|
||||
fallthrough,
|
||||
));
|
||||
|
||||
(variants_stmt, variant_visitor)
|
||||
@@ -1281,7 +1281,7 @@ fn deserialize_externally_tagged_enum(
|
||||
let expecting = format!("enum {}", params.type_name());
|
||||
let expecting = cattrs.expecting().unwrap_or(&expecting);
|
||||
|
||||
let (variants_stmt, variant_visitor) = prepare_enum_variant_enum(variants, cattrs);
|
||||
let (variants_stmt, variant_visitor) = prepare_enum_variant_enum(variants);
|
||||
|
||||
// Match arms to extract a variant from a string
|
||||
let variant_arms = variants
|
||||
@@ -1366,7 +1366,7 @@ fn deserialize_internally_tagged_enum(
|
||||
cattrs: &attr::Container,
|
||||
tag: &str,
|
||||
) -> Fragment {
|
||||
let (variants_stmt, variant_visitor) = prepare_enum_variant_enum(variants, cattrs);
|
||||
let (variants_stmt, variant_visitor) = prepare_enum_variant_enum(variants);
|
||||
|
||||
// Match arms to extract a variant from a string
|
||||
let variant_arms = variants
|
||||
@@ -1420,7 +1420,7 @@ fn deserialize_adjacently_tagged_enum(
|
||||
split_with_de_lifetime(params);
|
||||
let delife = params.borrowed.de_lifetime();
|
||||
|
||||
let (variants_stmt, variant_visitor) = prepare_enum_variant_enum(variants, cattrs);
|
||||
let (variants_stmt, variant_visitor) = prepare_enum_variant_enum(variants);
|
||||
|
||||
let variant_arms: &Vec<_> = &variants
|
||||
.iter()
|
||||
@@ -1748,7 +1748,6 @@ fn deserialize_untagged_enum_after(
|
||||
quote!(__deserializer),
|
||||
))
|
||||
});
|
||||
let attempts = first_attempt.into_iter().chain(attempts);
|
||||
// TODO this message could be better by saving the errors from the failed
|
||||
// attempts. The heuristic used by TOML was to count the number of fields
|
||||
// processed before an error, and use the error that happened after the
|
||||
@@ -1761,10 +1760,23 @@ fn deserialize_untagged_enum_after(
|
||||
);
|
||||
let fallthrough_msg = cattrs.expecting().unwrap_or(&fallthrough_msg);
|
||||
|
||||
// Ignore any error associated with non-untagged deserialization so that we
|
||||
// can fall through to the untagged variants. This may be infallible so we
|
||||
// need to provide the error type.
|
||||
let first_attempt = first_attempt.map(|expr| {
|
||||
quote! {
|
||||
if let _serde::__private::Result::<_, __D::Error>::Ok(__ok) = (|| #expr)() {
|
||||
return _serde::__private::Ok(__ok);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
quote_block! {
|
||||
let __content = <_serde::__private::de::Content as _serde::Deserialize>::deserialize(__deserializer)?;
|
||||
let __deserializer = _serde::__private::de::ContentRefDeserializer::<__D::Error>::new(&__content);
|
||||
|
||||
#first_attempt
|
||||
|
||||
#(
|
||||
if let _serde::__private::Ok(__ok) = #attempts {
|
||||
return _serde::__private::Ok(__ok);
|
||||
@@ -1839,7 +1851,7 @@ fn deserialize_internally_tagged_variant(
|
||||
let this_value = ¶ms.this_value;
|
||||
let type_name = params.type_name();
|
||||
let variant_name = variant.ident.to_string();
|
||||
let default = variant.fields.get(0).map(|field| {
|
||||
let default = variant.fields.first().map(|field| {
|
||||
let default = Expr(expr_is_missing(field, cattrs));
|
||||
quote!((#default))
|
||||
});
|
||||
@@ -1884,7 +1896,7 @@ fn deserialize_untagged_variant(
|
||||
let this_value = ¶ms.this_value;
|
||||
let type_name = params.type_name();
|
||||
let variant_name = variant.ident.to_string();
|
||||
let default = variant.fields.get(0).map(|field| {
|
||||
let default = variant.fields.first().map(|field| {
|
||||
let default = Expr(expr_is_missing(field, cattrs));
|
||||
quote!((#default))
|
||||
});
|
||||
@@ -1984,40 +1996,25 @@ fn deserialize_untagged_newtype_variant(
|
||||
|
||||
fn deserialize_generated_identifier(
|
||||
fields: &[(&str, Ident, &BTreeSet<String>)],
|
||||
cattrs: &attr::Container,
|
||||
has_flatten: bool,
|
||||
is_variant: bool,
|
||||
other_idx: Option<usize>,
|
||||
ignore_variant: Option<TokenStream>,
|
||||
fallthrough: Option<TokenStream>,
|
||||
) -> Fragment {
|
||||
let this_value = quote!(__Field);
|
||||
let field_idents: &Vec<_> = &fields.iter().map(|(_, ident, _)| ident).collect();
|
||||
|
||||
let (ignore_variant, fallthrough) = if !is_variant && cattrs.has_flatten() {
|
||||
let ignore_variant = quote!(__other(_serde::__private::de::Content<'de>),);
|
||||
let fallthrough = quote!(_serde::__private::Ok(__Field::__other(__value)));
|
||||
(Some(ignore_variant), Some(fallthrough))
|
||||
} else if let Some(other_idx) = other_idx {
|
||||
let ignore_variant = fields[other_idx].1.clone();
|
||||
let fallthrough = quote!(_serde::__private::Ok(__Field::#ignore_variant));
|
||||
(None, Some(fallthrough))
|
||||
} else if is_variant || cattrs.deny_unknown_fields() {
|
||||
(None, None)
|
||||
} else {
|
||||
let ignore_variant = quote!(__ignore,);
|
||||
let fallthrough = quote!(_serde::__private::Ok(__Field::__ignore));
|
||||
(Some(ignore_variant), Some(fallthrough))
|
||||
};
|
||||
|
||||
let visitor_impl = Stmts(deserialize_identifier(
|
||||
&this_value,
|
||||
fields,
|
||||
is_variant,
|
||||
fallthrough,
|
||||
None,
|
||||
!is_variant && cattrs.has_flatten(),
|
||||
!is_variant && has_flatten,
|
||||
None,
|
||||
));
|
||||
|
||||
let lifetime = if !is_variant && cattrs.has_flatten() {
|
||||
let lifetime = if !is_variant && has_flatten {
|
||||
Some(quote!(<'de>))
|
||||
} else {
|
||||
None
|
||||
@@ -2052,6 +2049,34 @@ fn deserialize_generated_identifier(
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates enum and its `Deserialize` implementation that represents each
|
||||
/// non-skipped field of the struct
|
||||
fn deserialize_field_identifier(
|
||||
fields: &[(&str, Ident, &BTreeSet<String>)],
|
||||
cattrs: &attr::Container,
|
||||
has_flatten: bool,
|
||||
) -> Stmts {
|
||||
let (ignore_variant, fallthrough) = if has_flatten {
|
||||
let ignore_variant = quote!(__other(_serde::__private::de::Content<'de>),);
|
||||
let fallthrough = quote!(_serde::__private::Ok(__Field::__other(__value)));
|
||||
(Some(ignore_variant), Some(fallthrough))
|
||||
} else if cattrs.deny_unknown_fields() {
|
||||
(None, None)
|
||||
} else {
|
||||
let ignore_variant = quote!(__ignore,);
|
||||
let fallthrough = quote!(_serde::__private::Ok(__Field::__ignore));
|
||||
(Some(ignore_variant), Some(fallthrough))
|
||||
};
|
||||
|
||||
Stmts(deserialize_generated_identifier(
|
||||
fields,
|
||||
has_flatten,
|
||||
false,
|
||||
ignore_variant,
|
||||
fallthrough,
|
||||
))
|
||||
}
|
||||
|
||||
// Generates `Deserialize::deserialize` body for an enum with
|
||||
// `serde(field_identifier)` or `serde(variant_identifier)` attribute.
|
||||
fn deserialize_custom_identifier(
|
||||
@@ -2447,6 +2472,7 @@ fn deserialize_map(
|
||||
params: &Parameters,
|
||||
fields: &[Field],
|
||||
cattrs: &attr::Container,
|
||||
has_flatten: bool,
|
||||
) -> Fragment {
|
||||
// Create the field names for the fields.
|
||||
let fields_names: Vec<_> = fields
|
||||
@@ -2467,7 +2493,7 @@ fn deserialize_map(
|
||||
});
|
||||
|
||||
// Collect contents for flatten fields into a buffer
|
||||
let let_collect = if cattrs.has_flatten() {
|
||||
let let_collect = if has_flatten {
|
||||
Some(quote! {
|
||||
let mut __collect = _serde::__private::Vec::<_serde::__private::Option<(
|
||||
_serde::__private::de::Content,
|
||||
@@ -2519,7 +2545,7 @@ fn deserialize_map(
|
||||
});
|
||||
|
||||
// Visit ignored values to consume them
|
||||
let ignored_arm = if cattrs.has_flatten() {
|
||||
let ignored_arm = if has_flatten {
|
||||
Some(quote! {
|
||||
__Field::__other(__name) => {
|
||||
__collect.push(_serde::__private::Some((
|
||||
@@ -2589,7 +2615,7 @@ fn deserialize_map(
|
||||
}
|
||||
});
|
||||
|
||||
let collected_deny_unknown_fields = if cattrs.has_flatten() && cattrs.deny_unknown_fields() {
|
||||
let collected_deny_unknown_fields = if has_flatten && cattrs.deny_unknown_fields() {
|
||||
Some(quote! {
|
||||
if let _serde::__private::Some(_serde::__private::Some((__key, _))) =
|
||||
__collect.into_iter().filter(_serde::__private::Option::is_some).next()
|
||||
@@ -2665,7 +2691,10 @@ fn deserialize_map_in_place(
|
||||
fields: &[Field],
|
||||
cattrs: &attr::Container,
|
||||
) -> Fragment {
|
||||
assert!(!cattrs.has_flatten());
|
||||
assert!(
|
||||
!has_flatten(fields),
|
||||
"inplace deserialization of maps does not support flatten fields"
|
||||
);
|
||||
|
||||
// Create the field names for the fields.
|
||||
let fields_names: Vec<_> = fields
|
||||
@@ -2998,6 +3027,14 @@ fn effective_style(variant: &Variant) -> Style {
|
||||
}
|
||||
}
|
||||
|
||||
/// True if there is any field with a `#[serde(flatten)]` attribute, other than
|
||||
/// fields which are skipped.
|
||||
fn has_flatten(fields: &[Field]) -> bool {
|
||||
fields
|
||||
.iter()
|
||||
.any(|field| field.attrs.flatten() && !field.attrs.skip_deserializing())
|
||||
}
|
||||
|
||||
struct DeImplGenerics<'a>(&'a Parameters);
|
||||
#[cfg(feature = "deserialize_in_place")]
|
||||
struct InPlaceImplGenerics<'a>(&'a Parameters);
|
||||
|
||||
@@ -63,7 +63,7 @@ impl<'a> Container<'a> {
|
||||
item: &'a syn::DeriveInput,
|
||||
derive: Derive,
|
||||
) -> Option<Container<'a>> {
|
||||
let mut attrs = attr::Container::from_ast(cx, item);
|
||||
let attrs = attr::Container::from_ast(cx, item);
|
||||
|
||||
let mut data = match &item.data {
|
||||
syn::Data::Enum(data) => Data::Enum(enum_from_ast(cx, &data.variants, attrs.default())),
|
||||
@@ -77,15 +77,11 @@ impl<'a> Container<'a> {
|
||||
}
|
||||
};
|
||||
|
||||
let mut has_flatten = false;
|
||||
match &mut data {
|
||||
Data::Enum(variants) => {
|
||||
for variant in variants {
|
||||
variant.attrs.rename_by_rules(attrs.rename_all_rules());
|
||||
for field in &mut variant.fields {
|
||||
if field.attrs.flatten() {
|
||||
has_flatten = true;
|
||||
}
|
||||
field.attrs.rename_by_rules(
|
||||
variant
|
||||
.attrs
|
||||
@@ -97,18 +93,11 @@ impl<'a> Container<'a> {
|
||||
}
|
||||
Data::Struct(_, fields) => {
|
||||
for field in fields {
|
||||
if field.attrs.flatten() {
|
||||
has_flatten = true;
|
||||
}
|
||||
field.attrs.rename_by_rules(attrs.rename_all_rules());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if has_flatten {
|
||||
attrs.mark_has_flatten();
|
||||
}
|
||||
|
||||
let mut item = Container {
|
||||
ident: item.ident.clone(),
|
||||
attrs,
|
||||
|
||||
@@ -185,8 +185,8 @@ impl Name {
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct RenameAllRules {
|
||||
serialize: RenameRule,
|
||||
deserialize: RenameRule,
|
||||
pub serialize: RenameRule,
|
||||
pub deserialize: RenameRule,
|
||||
}
|
||||
|
||||
impl RenameAllRules {
|
||||
@@ -216,11 +216,11 @@ pub struct Container {
|
||||
type_into: Option<syn::Type>,
|
||||
remote: Option<syn::Path>,
|
||||
identifier: Identifier,
|
||||
has_flatten: bool,
|
||||
serde_path: Option<syn::Path>,
|
||||
is_packed: bool,
|
||||
/// Error message generated when type can't be deserialized
|
||||
expecting: Option<String>,
|
||||
non_exhaustive: bool,
|
||||
}
|
||||
|
||||
/// Styles of representing an enum.
|
||||
@@ -306,9 +306,12 @@ impl Container {
|
||||
let mut variant_identifier = BoolAttr::none(cx, VARIANT_IDENTIFIER);
|
||||
let mut serde_path = Attr::none(cx, CRATE);
|
||||
let mut expecting = Attr::none(cx, EXPECTING);
|
||||
let mut non_exhaustive = false;
|
||||
|
||||
for attr in &item.attrs {
|
||||
if attr.path() != SERDE {
|
||||
non_exhaustive |=
|
||||
matches!(&attr.meta, syn::Meta::Path(path) if path == NON_EXHAUSTIVE);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -583,10 +586,10 @@ impl Container {
|
||||
type_into: type_into.get(),
|
||||
remote: remote.get(),
|
||||
identifier: decide_identifier(cx, item, field_identifier, variant_identifier),
|
||||
has_flatten: false,
|
||||
serde_path: serde_path.get(),
|
||||
is_packed,
|
||||
expecting: expecting.get(),
|
||||
non_exhaustive,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -650,14 +653,6 @@ impl Container {
|
||||
self.identifier
|
||||
}
|
||||
|
||||
pub fn has_flatten(&self) -> bool {
|
||||
self.has_flatten
|
||||
}
|
||||
|
||||
pub fn mark_has_flatten(&mut self) {
|
||||
self.has_flatten = true;
|
||||
}
|
||||
|
||||
pub fn custom_serde_path(&self) -> Option<&syn::Path> {
|
||||
self.serde_path.as_ref()
|
||||
}
|
||||
@@ -672,6 +667,10 @@ impl Container {
|
||||
pub fn expecting(&self) -> Option<&str> {
|
||||
self.expecting.as_ref().map(String::as_ref)
|
||||
}
|
||||
|
||||
pub fn non_exhaustive(&self) -> bool {
|
||||
self.non_exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
fn decide_tag(
|
||||
@@ -707,7 +706,7 @@ fn decide_tag(
|
||||
}
|
||||
TagType::Internal { tag }
|
||||
}
|
||||
(Some((untagged_tokens, _)), Some((tag_tokens, _)), None) => {
|
||||
(Some((untagged_tokens, ())), Some((tag_tokens, _)), None) => {
|
||||
let msg = "enum cannot be both untagged and internally tagged";
|
||||
cx.error_spanned_by(untagged_tokens, msg);
|
||||
cx.error_spanned_by(tag_tokens, msg);
|
||||
@@ -718,14 +717,14 @@ fn decide_tag(
|
||||
cx.error_spanned_by(content_tokens, msg);
|
||||
TagType::External
|
||||
}
|
||||
(Some((untagged_tokens, _)), None, Some((content_tokens, _))) => {
|
||||
(Some((untagged_tokens, ())), None, Some((content_tokens, _))) => {
|
||||
let msg = "untagged enum cannot have #[serde(content = \"...\")]";
|
||||
cx.error_spanned_by(untagged_tokens, msg);
|
||||
cx.error_spanned_by(content_tokens, msg);
|
||||
TagType::External
|
||||
}
|
||||
(None, Some((_, tag)), Some((_, content))) => TagType::Adjacent { tag, content },
|
||||
(Some((untagged_tokens, _)), Some((tag_tokens, _)), Some((content_tokens, _))) => {
|
||||
(Some((untagged_tokens, ())), Some((tag_tokens, _)), Some((content_tokens, _))) => {
|
||||
let msg = "untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]";
|
||||
cx.error_spanned_by(untagged_tokens, msg);
|
||||
cx.error_spanned_by(tag_tokens, msg);
|
||||
@@ -747,7 +746,7 @@ fn decide_identifier(
|
||||
variant_identifier.0.get_with_tokens(),
|
||||
) {
|
||||
(_, None, None) => Identifier::No,
|
||||
(_, Some((field_identifier_tokens, _)), Some((variant_identifier_tokens, _))) => {
|
||||
(_, Some((field_identifier_tokens, ())), Some((variant_identifier_tokens, ()))) => {
|
||||
let msg =
|
||||
"#[serde(field_identifier)] and #[serde(variant_identifier)] cannot both be set";
|
||||
cx.error_spanned_by(field_identifier_tokens, msg);
|
||||
@@ -1785,6 +1784,7 @@ fn borrowable_lifetimes(
|
||||
|
||||
fn collect_lifetimes(ty: &syn::Type, out: &mut BTreeSet<syn::Lifetime>) {
|
||||
match ty {
|
||||
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
syn::Type::Slice(ty) => {
|
||||
collect_lifetimes(&ty.elem, out);
|
||||
}
|
||||
@@ -1820,7 +1820,10 @@ fn collect_lifetimes(ty: &syn::Type, out: &mut BTreeSet<syn::Lifetime>) {
|
||||
syn::GenericArgument::AssocType(binding) => {
|
||||
collect_lifetimes(&binding.ty, out);
|
||||
}
|
||||
_ => {}
|
||||
syn::GenericArgument::Const(_)
|
||||
| syn::GenericArgument::AssocConst(_)
|
||||
| syn::GenericArgument::Constraint(_)
|
||||
| _ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1842,7 +1845,6 @@ fn collect_lifetimes(ty: &syn::Type, out: &mut BTreeSet<syn::Lifetime>) {
|
||||
| syn::Type::Infer(_)
|
||||
| syn::Type::Verbatim(_) => {}
|
||||
|
||||
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,6 +318,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());
|
||||
|
||||
@@ -84,7 +84,7 @@ impl ReplaceReceiver<'_> {
|
||||
self.visit_type_mut_impl(ty);
|
||||
return;
|
||||
};
|
||||
*ty = self.self_ty(span).into();
|
||||
*ty = Type::Path(self.self_ty(span));
|
||||
}
|
||||
|
||||
// `Self::Assoc` -> `<Receiver>::Assoc`
|
||||
@@ -107,6 +107,7 @@ impl ReplaceReceiver<'_> {
|
||||
|
||||
fn visit_type_mut_impl(&mut self, ty: &mut Type) {
|
||||
match ty {
|
||||
#![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
Type::Array(ty) => {
|
||||
self.visit_type_mut(&mut ty.elem);
|
||||
self.visit_expr_mut(&mut ty.len);
|
||||
@@ -147,7 +148,6 @@ impl ReplaceReceiver<'_> {
|
||||
|
||||
Type::Infer(_) | Type::Never(_) | Type::Verbatim(_) => {}
|
||||
|
||||
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -178,13 +178,13 @@ 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::Lifetime(_)
|
||||
| GenericArgument::Const(_)
|
||||
| GenericArgument::AssocConst(_)
|
||||
| GenericArgument::Constraint(_) => {}
|
||||
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -207,9 +207,9 @@ 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(_) => {}
|
||||
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -228,6 +228,7 @@ 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 {
|
||||
@@ -235,7 +236,6 @@ impl ReplaceReceiver<'_> {
|
||||
}
|
||||
}
|
||||
WherePredicate::Lifetime(_) => {}
|
||||
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ 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");
|
||||
|
||||
+4
-23
@@ -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.182")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.208")]
|
||||
#![cfg_attr(not(check_cfg), allow(unexpected_cfgs))]
|
||||
// Ignored clippy lints
|
||||
#![allow(
|
||||
// clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054
|
||||
@@ -50,7 +51,6 @@
|
||||
clippy::match_wildcard_for_single_variants,
|
||||
clippy::module_name_repetitions,
|
||||
clippy::must_use_candidate,
|
||||
clippy::option_if_let_else,
|
||||
clippy::similar_names,
|
||||
clippy::single_match_else,
|
||||
clippy::struct_excessive_bools,
|
||||
@@ -66,17 +66,11 @@ extern crate proc_macro2;
|
||||
extern crate quote;
|
||||
extern crate syn;
|
||||
|
||||
#[cfg(not(precompiled))]
|
||||
extern crate proc_macro;
|
||||
#[cfg(precompiled)]
|
||||
extern crate proc_macro2 as proc_macro;
|
||||
|
||||
mod internals;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
#[cfg(precompiled)]
|
||||
use std::sync::atomic::AtomicBool;
|
||||
#[cfg(not(precompiled))]
|
||||
use syn::parse_macro_input;
|
||||
use syn::DeriveInput;
|
||||
|
||||
@@ -91,20 +85,7 @@ mod pretend;
|
||||
mod ser;
|
||||
mod this;
|
||||
|
||||
#[cfg(precompiled)]
|
||||
macro_rules! parse_macro_input {
|
||||
($tokenstream:ident as $ty:ty) => {
|
||||
match syn::parse2::<$ty>($tokenstream) {
|
||||
Ok(data) => data,
|
||||
Err(err) => return err.to_compile_error(),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(precompiled)]
|
||||
pub static DESERIALIZE_IN_PLACE: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
#[cfg_attr(not(precompiled), proc_macro_derive(Serialize, attributes(serde)))]
|
||||
#[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)
|
||||
@@ -112,7 +93,7 @@ pub fn derive_serialize(input: TokenStream) -> TokenStream {
|
||||
.into()
|
||||
}
|
||||
|
||||
#[cfg_attr(not(precompiled), proc_macro_derive(Deserialize, attributes(serde)))]
|
||||
#[proc_macro_derive(Deserialize, attributes(serde))]
|
||||
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
|
||||
let mut input = parse_macro_input!(input as DeriveInput);
|
||||
de::expand_derive_deserialize(&mut input)
|
||||
|
||||
@@ -64,14 +64,14 @@ pub fn pretend_used(cont: &Container, is_packed: bool) -> TokenStream {
|
||||
fn pretend_fields_used(cont: &Container, is_packed: bool) -> TokenStream {
|
||||
match &cont.data {
|
||||
Data::Enum(variants) => pretend_fields_used_enum(cont, variants),
|
||||
Data::Struct(Style::Struct, fields) => {
|
||||
Data::Struct(Style::Struct | Style::Tuple | Style::Newtype, fields) => {
|
||||
if is_packed {
|
||||
pretend_fields_used_struct_packed(cont, fields)
|
||||
} else {
|
||||
pretend_fields_used_struct(cont, fields)
|
||||
}
|
||||
}
|
||||
Data::Struct(_, _) => quote!(),
|
||||
Data::Struct(Style::Unit, _) => quote!(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,13 +115,13 @@ fn pretend_fields_used_enum(cont: &Container, variants: &[Variant]) -> TokenStre
|
||||
let patterns = variants
|
||||
.iter()
|
||||
.filter_map(|variant| match variant.style {
|
||||
Style::Struct => {
|
||||
Style::Struct | Style::Tuple | Style::Newtype => {
|
||||
let variant_ident = &variant.ident;
|
||||
let members = variant.fields.iter().map(|field| &field.member);
|
||||
let placeholders = (0usize..).map(|i| format_ident!("__v{}", i));
|
||||
Some(quote!(#type_ident::#variant_ident { #(#members: #placeholders),* }))
|
||||
}
|
||||
_ => None,
|
||||
Style::Unit => None,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
|
||||
+21
-24
@@ -289,9 +289,18 @@ fn serialize_tuple_struct(
|
||||
}
|
||||
|
||||
fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Container) -> Fragment {
|
||||
assert!(fields.len() as u64 <= u64::from(u32::max_value()));
|
||||
assert!(
|
||||
fields.len() as u64 <= u64::from(u32::MAX),
|
||||
"too many fields in {}: {}, maximum supported count is {}",
|
||||
cattrs.name().serialize_name(),
|
||||
fields.len(),
|
||||
u32::MAX,
|
||||
);
|
||||
|
||||
if cattrs.has_flatten() {
|
||||
let has_non_skipped_flatten = fields
|
||||
.iter()
|
||||
.any(|field| field.attrs.flatten() && !field.attrs.skip_serializing());
|
||||
if has_non_skipped_flatten {
|
||||
serialize_struct_as_map(params, fields, cattrs)
|
||||
} else {
|
||||
serialize_struct_as_struct(params, fields, cattrs)
|
||||
@@ -370,26 +379,8 @@ fn serialize_struct_as_map(
|
||||
|
||||
let let_mut = mut_if(serialized_fields.peek().is_some() || tag_field_exists);
|
||||
|
||||
let len = if cattrs.has_flatten() {
|
||||
quote!(_serde::__private::None)
|
||||
} else {
|
||||
let len = serialized_fields
|
||||
.map(|field| match field.attrs.skip_serializing_if() {
|
||||
None => quote!(1),
|
||||
Some(path) => {
|
||||
let field_expr = get_member(params, field, &field.member);
|
||||
quote!(if #path(#field_expr) { 0 } else { 1 })
|
||||
}
|
||||
})
|
||||
.fold(
|
||||
quote!(#tag_field_exists as usize),
|
||||
|sum, expr| quote!(#sum + #expr),
|
||||
);
|
||||
quote!(_serde::__private::Some(#len))
|
||||
};
|
||||
|
||||
quote_block! {
|
||||
let #let_mut __serde_state = _serde::Serializer::serialize_map(__serializer, #len)?;
|
||||
let #let_mut __serde_state = _serde::Serializer::serialize_map(__serializer, _serde::__private::None)?;
|
||||
#tag_field
|
||||
#(#serialize_fields)*
|
||||
_serde::ser::SerializeMap::end(__serde_state)
|
||||
@@ -397,11 +388,11 @@ fn serialize_struct_as_map(
|
||||
}
|
||||
|
||||
fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Container) -> Fragment {
|
||||
assert!(variants.len() as u64 <= u64::from(u32::max_value()));
|
||||
assert!(variants.len() as u64 <= u64::from(u32::MAX));
|
||||
|
||||
let self_var = ¶ms.self_var;
|
||||
|
||||
let arms: Vec<_> = variants
|
||||
let mut arms: Vec<_> = variants
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(variant_index, variant)| {
|
||||
@@ -409,6 +400,12 @@ fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Cont
|
||||
})
|
||||
.collect();
|
||||
|
||||
if cattrs.remote().is_some() && cattrs.non_exhaustive() {
|
||||
arms.push(quote! {
|
||||
ref unrecognized => _serde::__private::Err(_serde::ser::Error::custom(_serde::__private::ser::CannotSerializeVariant(unrecognized))),
|
||||
});
|
||||
}
|
||||
|
||||
quote_expr! {
|
||||
match *#self_var {
|
||||
#(#arms)*
|
||||
@@ -704,7 +701,7 @@ fn serialize_adjacently_tagged_variant(
|
||||
});
|
||||
|
||||
let fields_ty = variant.fields.iter().map(|f| &f.ty);
|
||||
let fields_ident: &Vec<_> = &match variant.style {
|
||||
let fields_ident: &[_] = &match variant.style {
|
||||
Style::Unit => {
|
||||
if variant.attrs.serialize_with().is_some() {
|
||||
vec![]
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
[package]
|
||||
name = "serde_derive_internals"
|
||||
version = "0.28.0" # remember to update html_root_url
|
||||
version = "0.29.1"
|
||||
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"
|
||||
edition = "2015"
|
||||
exclude = ["build.rs"]
|
||||
homepage = "https://serde.rs"
|
||||
keywords = ["serde", "serialization"]
|
||||
@@ -15,9 +16,9 @@ rust-version = "1.56"
|
||||
path = "lib.rs"
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = "1.0"
|
||||
quote = "1.0"
|
||||
syn = { version = "2.0.28", default-features = false, features = ["clone-impls", "derive", "parsing", "printing"] }
|
||||
proc-macro2 = { workspace = true }
|
||||
quote = { workspace = true }
|
||||
syn = { workspace = true, features = ["clone-impls", "derive", "parsing", "printing"] }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
use std::path::Path;
|
||||
|
||||
fn main() {
|
||||
// Warning: build.rs is not published to crates.io.
|
||||
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
println!("cargo:rerun-if-changed=src/mod.rs");
|
||||
|
||||
println!("cargo:rustc-cfg=check_cfg");
|
||||
println!("cargo:rustc-check-cfg=cfg(check_cfg)");
|
||||
println!("cargo:rustc-check-cfg=cfg(exhaustive)");
|
||||
println!("cargo:rustc-check-cfg=cfg(serde_build_from_git)");
|
||||
println!("cargo:rustc-check-cfg=cfg(feature, values(\"deserialize_in_place\"))");
|
||||
|
||||
// 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,4 +1,5 @@
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.28.0")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.29.1")]
|
||||
#![cfg_attr(not(check_cfg), allow(unexpected_cfgs))]
|
||||
// Ignored clippy lints
|
||||
#![allow(
|
||||
clippy::cognitive_complexity,
|
||||
|
||||
@@ -18,4 +18,4 @@ rustversion = "1.0"
|
||||
serde = { path = "../serde", features = ["rc"] }
|
||||
serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] }
|
||||
serde_test = "1.0.176"
|
||||
trybuild = { version = "1.0.66", features = ["diff"] }
|
||||
trybuild = { version = "1.0.97", features = ["diff"] }
|
||||
|
||||
@@ -23,21 +23,21 @@ fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Unit;
|
||||
pub struct Unit;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Newtype(u8);
|
||||
pub struct Newtype(u8);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Tuple(u8, u8);
|
||||
pub struct Tuple(u8, u8);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Struct {
|
||||
pub struct Struct {
|
||||
f: u8,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum Enum {
|
||||
pub enum Enum {
|
||||
Unit,
|
||||
Newtype(u8),
|
||||
Tuple(u8, u8),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#[cfg_attr(target_os = "emscripten", ignore)]
|
||||
#[rustversion::attr(not(nightly), ignore)]
|
||||
#[cfg_attr(miri, ignore)]
|
||||
#[cfg_attr(target_os = "emscripten", ignore = "disabled on Emscripten")]
|
||||
#[rustversion::attr(not(nightly), ignore = "requires nightly")]
|
||||
#[cfg_attr(miri, ignore = "incompatible with miri")]
|
||||
#[allow(unused_attributes)]
|
||||
#[test]
|
||||
fn ui() {
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
#![allow(dead_code)] // we do not read enum fields
|
||||
|
||||
use serde_derive::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Nested;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub enum ExternallyTagged1 {
|
||||
Tuple(f64, String),
|
||||
Flatten {
|
||||
#[serde(flatten)]
|
||||
nested: Nested,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub enum ExternallyTagged2 {
|
||||
Flatten {
|
||||
#[serde(flatten)]
|
||||
nested: Nested,
|
||||
},
|
||||
Tuple(f64, String),
|
||||
}
|
||||
|
||||
// Internally tagged enums cannot contain tuple variants so not tested here
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(tag = "tag", content = "content")]
|
||||
pub enum AdjacentlyTagged1 {
|
||||
Tuple(f64, String),
|
||||
Flatten {
|
||||
#[serde(flatten)]
|
||||
nested: Nested,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(tag = "tag", content = "content")]
|
||||
pub enum AdjacentlyTagged2 {
|
||||
Flatten {
|
||||
#[serde(flatten)]
|
||||
nested: Nested,
|
||||
},
|
||||
Tuple(f64, String),
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum Untagged1 {
|
||||
Tuple(f64, String),
|
||||
Flatten {
|
||||
#[serde(flatten)]
|
||||
nested: Nested,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum Untagged2 {
|
||||
Flatten {
|
||||
#[serde(flatten)]
|
||||
nested: Nested,
|
||||
},
|
||||
Tuple(f64, String),
|
||||
}
|
||||
@@ -7,7 +7,9 @@ pub struct Nested;
|
||||
pub enum ExternallyTagged {
|
||||
Flatten {
|
||||
#[serde(flatten)]
|
||||
#[allow(dead_code)]
|
||||
nested: Nested,
|
||||
#[allow(dead_code)]
|
||||
string: &'static str,
|
||||
},
|
||||
}
|
||||
@@ -17,7 +19,9 @@ pub enum ExternallyTagged {
|
||||
pub enum InternallyTagged {
|
||||
Flatten {
|
||||
#[serde(flatten)]
|
||||
#[allow(dead_code)]
|
||||
nested: Nested,
|
||||
#[allow(dead_code)]
|
||||
string: &'static str,
|
||||
},
|
||||
}
|
||||
@@ -27,7 +31,9 @@ pub enum InternallyTagged {
|
||||
pub enum AdjacentlyTagged {
|
||||
Flatten {
|
||||
#[serde(flatten)]
|
||||
#[allow(dead_code)]
|
||||
nested: Nested,
|
||||
#[allow(dead_code)]
|
||||
string: &'static str,
|
||||
},
|
||||
}
|
||||
@@ -37,7 +43,9 @@ pub enum AdjacentlyTagged {
|
||||
pub enum UntaggedWorkaround {
|
||||
Flatten {
|
||||
#[serde(flatten)]
|
||||
#[allow(dead_code)]
|
||||
nested: Nested,
|
||||
#[allow(dead_code)]
|
||||
string: &'static str,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
use serde_derive::{Serialize, Deserialize};
|
||||
use serde_test::{assert_tokens, Token};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq)]
|
||||
enum Enum {
|
||||
Simple {
|
||||
a: i32,
|
||||
},
|
||||
Flatten {
|
||||
#[serde(flatten)]
|
||||
flatten: (),
|
||||
a: i32,
|
||||
},
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_variant() {
|
||||
assert_tokens(
|
||||
&Enum::Simple { a: 42 },
|
||||
&[
|
||||
Token::StructVariant { name: "Enum", variant: "Simple", len: 1 },
|
||||
Token::Str("a"),
|
||||
Token::I32(42),
|
||||
Token::StructVariantEnd,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn flatten_variant() {
|
||||
assert_tokens(
|
||||
&Enum::Flatten { flatten: (), a: 42 },
|
||||
&[
|
||||
Token::NewtypeVariant { name: "Enum", variant: "Flatten" },
|
||||
Token::Map { len: None },
|
||||
Token::Str("a"),
|
||||
Token::I32(42),
|
||||
Token::MapEnd,
|
||||
]
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#![allow(dead_code)] // we do not read enum fields
|
||||
|
||||
use serde_derive::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub enum A {
|
||||
B {
|
||||
c: String,
|
||||
},
|
||||
D {
|
||||
#[serde(flatten)]
|
||||
e: E,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct E {}
|
||||
@@ -1815,6 +1815,32 @@ fn test_flatten_unit() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_flatten_unit_struct() {
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
struct Response<T> {
|
||||
#[serde(flatten)]
|
||||
data: T,
|
||||
status: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
struct Unit;
|
||||
|
||||
assert_tokens(
|
||||
&Response {
|
||||
data: Unit,
|
||||
status: 0,
|
||||
},
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::Str("status"),
|
||||
Token::U64(0),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_flatten_unsupported_type() {
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
@@ -2380,6 +2406,118 @@ fn test_partially_untagged_enum_desugared() {
|
||||
);
|
||||
}
|
||||
|
||||
// Regression test for https://github.com/serde-rs/serde/issues/1904
|
||||
#[test]
|
||||
fn test_enum_tuple_and_struct_with_flatten() {
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
enum Outer {
|
||||
Tuple(f64, i32),
|
||||
Flatten {
|
||||
#[serde(flatten)]
|
||||
nested: Nested,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
struct Nested {
|
||||
a: i32,
|
||||
b: i32,
|
||||
}
|
||||
|
||||
assert_tokens(
|
||||
&Outer::Tuple(1.2, 3),
|
||||
&[
|
||||
Token::TupleVariant {
|
||||
name: "Outer",
|
||||
variant: "Tuple",
|
||||
len: 2,
|
||||
},
|
||||
Token::F64(1.2),
|
||||
Token::I32(3),
|
||||
Token::TupleVariantEnd,
|
||||
],
|
||||
);
|
||||
assert_tokens(
|
||||
&Outer::Flatten {
|
||||
nested: Nested { a: 1, b: 2 },
|
||||
},
|
||||
&[
|
||||
Token::NewtypeVariant {
|
||||
name: "Outer",
|
||||
variant: "Flatten",
|
||||
},
|
||||
Token::Map { len: None },
|
||||
Token::Str("a"),
|
||||
Token::I32(1),
|
||||
Token::Str("b"),
|
||||
Token::I32(2),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_partially_untagged_internally_tagged_enum() {
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
#[serde(tag = "t")]
|
||||
enum Data {
|
||||
A,
|
||||
B,
|
||||
#[serde(untagged)]
|
||||
Var(u32),
|
||||
}
|
||||
|
||||
let data = Data::A;
|
||||
|
||||
assert_de_tokens(
|
||||
&data,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::Str("t"),
|
||||
Token::Str("A"),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
|
||||
let data = Data::Var(42);
|
||||
|
||||
assert_de_tokens(&data, &[Token::U32(42)]);
|
||||
|
||||
// TODO test error output
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_partially_untagged_adjacently_tagged_enum() {
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
#[serde(tag = "t", content = "c")]
|
||||
enum Data {
|
||||
A(u32),
|
||||
B,
|
||||
#[serde(untagged)]
|
||||
Var(u32),
|
||||
}
|
||||
|
||||
let data = Data::A(7);
|
||||
|
||||
assert_de_tokens(
|
||||
&data,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::Str("t"),
|
||||
Token::Str("A"),
|
||||
Token::Str("c"),
|
||||
Token::U32(7),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
|
||||
let data = Data::Var(42);
|
||||
|
||||
assert_de_tokens(&data, &[Token::U32(42)]);
|
||||
|
||||
// TODO test error output
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_flatten_option() {
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
@@ -2719,7 +2857,7 @@ fn test_expecting_message_externally_tagged_enum() {
|
||||
// Check that #[serde(expecting = "...")] doesn't affect variant identifier error message
|
||||
assert_de_tokens_error::<Enum>(
|
||||
&[Token::Enum { name: "Enum" }, Token::Unit],
|
||||
r#"invalid type: unit value, expected variant identifier"#,
|
||||
"invalid type: unit value, expected variant identifier",
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2740,7 +2878,7 @@ fn test_expecting_message_internally_tagged_enum() {
|
||||
// Check that #[serde(expecting = "...")] doesn't affect variant identifier error message
|
||||
assert_de_tokens_error::<Enum>(
|
||||
&[Token::Map { len: None }, Token::Str("tag"), Token::Unit],
|
||||
r#"invalid type: unit value, expected variant identifier"#,
|
||||
"invalid type: unit value, expected variant identifier",
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2766,7 +2904,7 @@ fn test_expecting_message_adjacently_tagged_enum() {
|
||||
// Check that #[serde(expecting = "...")] doesn't affect variant identifier error message
|
||||
assert_de_tokens_error::<Enum>(
|
||||
&[Token::Map { len: None }, Token::Str("tag"), Token::Unit],
|
||||
r#"invalid type: unit value, expected variant of enum Enum"#,
|
||||
"invalid type: unit value, expected variant of enum Enum",
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2779,7 +2917,7 @@ fn test_expecting_message_untagged_tagged_enum() {
|
||||
Untagged,
|
||||
}
|
||||
|
||||
assert_de_tokens_error::<Enum>(&[Token::Str("Untagged")], r#"something strange..."#);
|
||||
assert_de_tokens_error::<Enum>(&[Token::Str("Untagged")], "something strange...");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -2800,7 +2938,7 @@ fn test_expecting_message_identifier_enum() {
|
||||
|
||||
assert_de_tokens_error::<FieldEnum>(
|
||||
&[Token::Unit],
|
||||
r#"invalid type: unit value, expected something strange..."#,
|
||||
"invalid type: unit value, expected something strange...",
|
||||
);
|
||||
|
||||
assert_de_tokens_error::<FieldEnum>(
|
||||
@@ -2809,12 +2947,12 @@ fn test_expecting_message_identifier_enum() {
|
||||
Token::Str("Unknown"),
|
||||
Token::None,
|
||||
],
|
||||
r#"invalid type: map, expected something strange..."#,
|
||||
"invalid type: map, expected something strange...",
|
||||
);
|
||||
|
||||
assert_de_tokens_error::<VariantEnum>(
|
||||
&[Token::Unit],
|
||||
r#"invalid type: unit value, expected something strange..."#,
|
||||
"invalid type: unit value, expected something strange...",
|
||||
);
|
||||
|
||||
assert_de_tokens_error::<VariantEnum>(
|
||||
@@ -2825,7 +2963,7 @@ fn test_expecting_message_identifier_enum() {
|
||||
Token::Str("Unknown"),
|
||||
Token::None,
|
||||
],
|
||||
r#"invalid type: map, expected something strange..."#,
|
||||
"invalid type: map, expected something strange...",
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ fn test_cow() {
|
||||
#[test]
|
||||
fn test_lifetimes() {
|
||||
#[derive(Deserialize)]
|
||||
struct Cows<'a, 'b> {
|
||||
pub struct Cows<'a, 'b> {
|
||||
_copied: Cow<'a, str>,
|
||||
|
||||
#[serde(borrow)]
|
||||
@@ -178,7 +178,7 @@ fn test_lifetimes() {
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct Wrap<'a, 'b> {
|
||||
pub struct Wrap<'a, 'b> {
|
||||
#[serde(borrow = "'b")]
|
||||
_cows: Cows<'a, 'b>,
|
||||
}
|
||||
|
||||
+100
-2
@@ -11,6 +11,7 @@
|
||||
#![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};
|
||||
@@ -22,7 +23,7 @@ use std::iter;
|
||||
use std::net;
|
||||
use std::num::{
|
||||
NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128,
|
||||
NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, Wrapping,
|
||||
NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, Saturating, Wrapping,
|
||||
};
|
||||
use std::ops::Bound;
|
||||
use std::path::{Path, PathBuf};
|
||||
@@ -92,7 +93,7 @@ struct StructSkipDefault {
|
||||
|
||||
#[derive(PartialEq, Debug, Deserialize)]
|
||||
#[serde(default)]
|
||||
struct StructSkipDefaultGeneric<T> {
|
||||
pub struct StructSkipDefaultGeneric<T> {
|
||||
#[serde(skip_deserializing)]
|
||||
t: T,
|
||||
}
|
||||
@@ -832,6 +833,26 @@ 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')]);
|
||||
@@ -1877,6 +1898,46 @@ fn test_range_inclusive() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_range_from() {
|
||||
test(
|
||||
1u32..,
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "RangeFrom",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("start"),
|
||||
Token::U32(1),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
test(
|
||||
1u32..,
|
||||
&[Token::Seq { len: Some(1) }, Token::U32(1), Token::SeqEnd],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_range_to() {
|
||||
test(
|
||||
..2u32,
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "RangeTo",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("end"),
|
||||
Token::U32(2),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
test(
|
||||
..2u32,
|
||||
&[Token::Seq { len: Some(1) }, Token::U32(2), Token::SeqEnd],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bound() {
|
||||
test(
|
||||
@@ -2004,6 +2065,43 @@ fn test_wrapping() {
|
||||
test(Wrapping(1usize), &[Token::U64(1)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_saturating() {
|
||||
test(Saturating(1usize), &[Token::U32(1)]);
|
||||
test(Saturating(1usize), &[Token::U64(1)]);
|
||||
test(Saturating(0u8), &[Token::I8(0)]);
|
||||
test(Saturating(0u16), &[Token::I16(0)]);
|
||||
|
||||
// saturate input values at the minimum or maximum value
|
||||
test(Saturating(u8::MAX), &[Token::U16(u16::MAX)]);
|
||||
test(Saturating(u8::MAX), &[Token::U16(u8::MAX as u16 + 1)]);
|
||||
test(Saturating(u16::MAX), &[Token::U32(u32::MAX)]);
|
||||
test(Saturating(u32::MAX), &[Token::U64(u64::MAX)]);
|
||||
test(Saturating(u8::MIN), &[Token::I8(i8::MIN)]);
|
||||
test(Saturating(u16::MIN), &[Token::I16(i16::MIN)]);
|
||||
test(Saturating(u32::MIN), &[Token::I32(i32::MIN)]);
|
||||
test(Saturating(i8::MIN), &[Token::I16(i16::MIN)]);
|
||||
test(Saturating(i16::MIN), &[Token::I32(i32::MIN)]);
|
||||
test(Saturating(i32::MIN), &[Token::I64(i64::MIN)]);
|
||||
|
||||
test(Saturating(u8::MIN), &[Token::I8(-1)]);
|
||||
test(Saturating(u16::MIN), &[Token::I16(-1)]);
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
{
|
||||
test(Saturating(usize::MIN), &[Token::U64(u64::MIN)]);
|
||||
test(Saturating(usize::MAX), &[Token::U64(u64::MAX)]);
|
||||
test(Saturating(isize::MIN), &[Token::I64(i64::MIN)]);
|
||||
test(Saturating(isize::MAX), &[Token::I64(i64::MAX)]);
|
||||
test(Saturating(0usize), &[Token::I64(i64::MIN)]);
|
||||
|
||||
test(
|
||||
Saturating(9_223_372_036_854_775_807usize),
|
||||
&[Token::I64(i64::MAX)],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rc_dst() {
|
||||
test(Rc::<str>::from("s"), &[Token::Str("s")]);
|
||||
|
||||
@@ -1434,7 +1434,15 @@ fn test_number_from_string() {
|
||||
fn test_integer_from_float() {
|
||||
assert_de_tokens_error::<isize>(
|
||||
&[Token::F32(0.0)],
|
||||
"invalid type: floating point `0`, expected isize",
|
||||
"invalid type: floating point `0.0`, expected isize",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nan_no_decimal_point() {
|
||||
assert_de_tokens_error::<isize>(
|
||||
&[Token::F32(f32::NAN)],
|
||||
"invalid type: floating point `NaN`, expected isize",
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1459,7 +1467,7 @@ fn test_duration_overflow_seq() {
|
||||
assert_de_tokens_error::<Duration>(
|
||||
&[
|
||||
Token::Seq { len: Some(2) },
|
||||
Token::U64(u64::max_value()),
|
||||
Token::U64(u64::MAX),
|
||||
Token::U32(1_000_000_000),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
@@ -1476,7 +1484,7 @@ fn test_duration_overflow_struct() {
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("secs"),
|
||||
Token::U64(u64::max_value()),
|
||||
Token::U64(u64::MAX),
|
||||
Token::Str("nanos"),
|
||||
Token::U32(1_000_000_000),
|
||||
Token::StructEnd,
|
||||
@@ -1490,7 +1498,7 @@ fn test_systemtime_overflow_seq() {
|
||||
assert_de_tokens_error::<SystemTime>(
|
||||
&[
|
||||
Token::Seq { len: Some(2) },
|
||||
Token::U64(u64::max_value()),
|
||||
Token::U64(u64::MAX),
|
||||
Token::U32(1_000_000_000),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
@@ -1507,7 +1515,7 @@ fn test_systemtime_overflow_struct() {
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("secs_since_epoch"),
|
||||
Token::U64(u64::max_value()),
|
||||
Token::U64(u64::MAX),
|
||||
Token::Str("nanos_since_epoch"),
|
||||
Token::U32(1_000_000_000),
|
||||
Token::StructEnd,
|
||||
@@ -1516,13 +1524,12 @@ fn test_systemtime_overflow_struct() {
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(systemtime_checked_add)]
|
||||
#[test]
|
||||
fn test_systemtime_overflow() {
|
||||
assert_de_tokens_error::<SystemTime>(
|
||||
&[
|
||||
Token::Seq { len: Some(2) },
|
||||
Token::U64(u64::max_value()),
|
||||
Token::U64(u64::MAX),
|
||||
Token::U32(0),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#![deny(warnings)]
|
||||
#![allow(
|
||||
confusable_idents,
|
||||
unknown_lints,
|
||||
mixed_script_confusables,
|
||||
clippy::derive_partial_eq_without_eq,
|
||||
@@ -19,6 +20,7 @@
|
||||
clippy::trivially_copy_pass_by_ref,
|
||||
clippy::type_repetition_in_bounds
|
||||
)]
|
||||
#![deny(clippy::collection_is_never_read)]
|
||||
|
||||
use serde::de::{Deserialize, DeserializeOwned, Deserializer};
|
||||
use serde::ser::{Serialize, Serializer};
|
||||
@@ -287,60 +289,60 @@ fn test_gen() {
|
||||
assert::<EmptyEnumVariant>();
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct NonAsciiIdents {
|
||||
pub struct NonAsciiIdents {
|
||||
σ: f64,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct EmptyBraced {}
|
||||
pub struct EmptyBraced {}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct EmptyBracedDenyUnknown {}
|
||||
pub struct EmptyBracedDenyUnknown {}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct BracedSkipAll {
|
||||
pub struct BracedSkipAll {
|
||||
#[serde(skip_deserializing)]
|
||||
f: u8,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct BracedSkipAllDenyUnknown {
|
||||
pub struct BracedSkipAllDenyUnknown {
|
||||
#[serde(skip_deserializing)]
|
||||
f: u8,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct EmptyTuple();
|
||||
pub struct EmptyTuple();
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct EmptyTupleDenyUnknown();
|
||||
pub struct EmptyTupleDenyUnknown();
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct TupleSkipAll(#[serde(skip_deserializing)] u8);
|
||||
pub struct TupleSkipAll(#[serde(skip_deserializing)] u8);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct TupleSkipAllDenyUnknown(#[serde(skip_deserializing)] u8);
|
||||
pub struct TupleSkipAllDenyUnknown(#[serde(skip_deserializing)] u8);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum EmptyEnum {}
|
||||
pub enum EmptyEnum {}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
enum EmptyEnumDenyUnknown {}
|
||||
pub enum EmptyEnumDenyUnknown {}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum EnumSkipAll {
|
||||
pub enum EnumSkipAll {
|
||||
#[serde(skip_deserializing)]
|
||||
#[allow(dead_code)]
|
||||
Variant,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum EmptyVariants {
|
||||
pub enum EmptyVariants {
|
||||
Braced {},
|
||||
Tuple(),
|
||||
BracedSkip {
|
||||
@@ -352,7 +354,7 @@ fn test_gen() {
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
enum EmptyVariantsDenyUnknown {
|
||||
pub enum EmptyVariantsDenyUnknown {
|
||||
Braced {},
|
||||
Tuple(),
|
||||
BracedSkip {
|
||||
@@ -364,21 +366,21 @@ fn test_gen() {
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct UnitDenyUnknown;
|
||||
pub struct UnitDenyUnknown;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct EmptyArray {
|
||||
pub struct EmptyArray {
|
||||
empty: [X; 0],
|
||||
}
|
||||
|
||||
enum Or<A, B> {
|
||||
pub enum Or<A, B> {
|
||||
A(A),
|
||||
B(B),
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(untagged, remote = "Or")]
|
||||
enum OrDef<A, B> {
|
||||
pub enum OrDef<A, B> {
|
||||
A(A),
|
||||
B(B),
|
||||
}
|
||||
@@ -390,7 +392,7 @@ fn test_gen() {
|
||||
struct StrDef<'a>(&'a str);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Remote<'a> {
|
||||
pub struct Remote<'a> {
|
||||
#[serde(with = "OrDef")]
|
||||
or: Or<u8, bool>,
|
||||
#[serde(borrow, with = "StrDef")]
|
||||
@@ -398,7 +400,7 @@ fn test_gen() {
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum BorrowVariant<'a> {
|
||||
pub enum BorrowVariant<'a> {
|
||||
#[serde(borrow, with = "StrDef")]
|
||||
S(Str<'a>),
|
||||
}
|
||||
@@ -415,14 +417,14 @@ fn test_gen() {
|
||||
|
||||
// This would not work if SDef::serialize / deserialize are private.
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct RemoteVisibility {
|
||||
pub struct RemoteVisibility {
|
||||
#[serde(with = "vis::SDef")]
|
||||
s: vis::S,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "Self")]
|
||||
struct RemoteSelf;
|
||||
pub struct RemoteSelf;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum ExternallyTaggedVariantWith {
|
||||
@@ -546,26 +548,45 @@ fn test_gen() {
|
||||
assert::<FlattenWith>();
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct FlattenDenyUnknown<T> {
|
||||
pub struct Flatten<T> {
|
||||
#[serde(flatten)]
|
||||
t: T,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct StaticStrStruct<'a> {
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct FlattenDenyUnknown<T> {
|
||||
#[serde(flatten)]
|
||||
t: T,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct SkipDeserializing<T> {
|
||||
#[serde(skip_deserializing)]
|
||||
flat: T,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct SkipDeserializingDenyUnknown<T> {
|
||||
#[serde(skip_deserializing)]
|
||||
flat: T,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct StaticStrStruct<'a> {
|
||||
a: &'a str,
|
||||
b: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct StaticStrTupleStruct<'a>(&'a str, &'static str);
|
||||
pub struct StaticStrTupleStruct<'a>(&'a str, &'static str);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct StaticStrNewtypeStruct(&'static str);
|
||||
pub struct StaticStrNewtypeStruct(&'static str);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum StaticStrEnum<'a> {
|
||||
pub enum StaticStrEnum<'a> {
|
||||
Struct { a: &'a str, b: &'static str },
|
||||
Tuple(&'a str, &'static str),
|
||||
Newtype(&'static str),
|
||||
@@ -639,6 +660,7 @@ fn test_gen() {
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[allow(dead_code)]
|
||||
struct Restricted {
|
||||
pub(super) a: usize,
|
||||
pub(in super::inner) b: usize,
|
||||
@@ -648,7 +670,7 @@ fn test_gen() {
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(tag = "t", content = "c")]
|
||||
enum AdjacentlyTaggedVoid {}
|
||||
pub enum AdjacentlyTaggedVoid {}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum SkippedVariant<T> {
|
||||
@@ -661,14 +683,13 @@ fn test_gen() {
|
||||
assert::<SkippedVariant<X>>();
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct ImplicitlyBorrowedOption<'a> {
|
||||
#[allow(dead_code)]
|
||||
pub struct ImplicitlyBorrowedOption<'a> {
|
||||
option: std::option::Option<&'a str>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum UntaggedNewtypeVariantWith {
|
||||
pub enum UntaggedNewtypeVariantWith {
|
||||
Newtype(
|
||||
#[serde(serialize_with = "ser_x")]
|
||||
#[serde(deserialize_with = "de_x")]
|
||||
@@ -678,7 +699,7 @@ fn test_gen() {
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
struct TransparentWith {
|
||||
pub struct TransparentWith {
|
||||
#[serde(serialize_with = "ser_x")]
|
||||
#[serde(deserialize_with = "de_x")]
|
||||
x: X,
|
||||
@@ -686,41 +707,60 @@ fn test_gen() {
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum UntaggedWithBorrow<'a> {
|
||||
Single(#[serde(borrow)] RelObject<'a>),
|
||||
Many(#[serde(borrow)] Vec<RelObject<'a>>),
|
||||
pub enum UntaggedWithBorrow<'a> {
|
||||
Single(
|
||||
#[serde(borrow)]
|
||||
#[allow(dead_code)]
|
||||
RelObject<'a>,
|
||||
),
|
||||
Many(
|
||||
#[serde(borrow)]
|
||||
#[allow(dead_code)]
|
||||
Vec<RelObject<'a>>,
|
||||
),
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct RelObject<'a> {
|
||||
#[allow(dead_code)]
|
||||
pub struct RelObject<'a> {
|
||||
ty: &'a str,
|
||||
#[allow(dead_code)]
|
||||
id: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct FlattenSkipSerializing<T> {
|
||||
pub struct FlattenSkipSerializing<T> {
|
||||
#[serde(flatten, skip_serializing)]
|
||||
#[allow(dead_code)]
|
||||
flat: T,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct FlattenSkipSerializingIf<T> {
|
||||
pub struct FlattenSkipSerializingIf<T> {
|
||||
#[serde(flatten, skip_serializing_if = "StdOption::is_none")]
|
||||
flat: StdOption<T>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct FlattenSkipDeserializing<T> {
|
||||
pub struct FlattenSkipDeserializing<T> {
|
||||
#[serde(flatten, skip_deserializing)]
|
||||
flat: T,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum Inner<T> {
|
||||
Builder {
|
||||
s: T,
|
||||
#[serde(flatten)]
|
||||
o: T,
|
||||
},
|
||||
Default {
|
||||
s: T,
|
||||
},
|
||||
}
|
||||
|
||||
// https://github.com/serde-rs/serde/issues/1804
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum Message {
|
||||
pub enum Message {
|
||||
#[serde(skip)]
|
||||
#[allow(dead_code)]
|
||||
String(String),
|
||||
@@ -730,6 +770,7 @@ fn test_gen() {
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[repr(packed)]
|
||||
#[allow(dead_code)]
|
||||
struct Packed {
|
||||
x: u8,
|
||||
y: u16,
|
||||
@@ -738,8 +779,7 @@ fn test_gen() {
|
||||
macro_rules! deriving {
|
||||
($field:ty) => {
|
||||
#[derive(Deserialize)]
|
||||
struct MacroRules<'a> {
|
||||
#[allow(dead_code)]
|
||||
pub struct MacroRules<'a> {
|
||||
field: $field,
|
||||
}
|
||||
};
|
||||
@@ -754,21 +794,20 @@ fn test_gen() {
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct BorrowLifetimeInsideMacro<'a> {
|
||||
pub struct BorrowLifetimeInsideMacro<'a> {
|
||||
#[serde(borrow = "'a")]
|
||||
#[allow(dead_code)]
|
||||
f: mac!(Cow<'a, str>),
|
||||
pub f: mac!(Cow<'a, str>),
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct Struct {
|
||||
pub struct Struct {
|
||||
#[serde(serialize_with = "vec_first_element")]
|
||||
vec: Vec<Self>,
|
||||
pub vec: Vec<Self>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(bound(deserialize = "[&'de str; N]: Copy"))]
|
||||
struct GenericUnitStruct<const N: usize>;
|
||||
pub struct GenericUnitStruct<const N: usize>;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -843,7 +882,7 @@ pub fn is_zero(n: &u8) -> bool {
|
||||
*n == 0
|
||||
}
|
||||
|
||||
fn vec_first_element<T, S>(vec: &Vec<T>, serializer: S) -> StdResult<S::Ok, S::Error>
|
||||
fn vec_first_element<T, S>(vec: &[T], serializer: S) -> StdResult<S::Ok, S::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
S: Serializer,
|
||||
@@ -855,7 +894,7 @@ where
|
||||
|
||||
#[derive(Debug, PartialEq, Deserialize)]
|
||||
#[serde(tag = "tag")]
|
||||
enum InternallyTagged {
|
||||
pub enum InternallyTagged {
|
||||
#[serde(deserialize_with = "deserialize_generic")]
|
||||
Unit,
|
||||
|
||||
|
||||
@@ -814,6 +814,100 @@ fn test_internally_tagged_enum() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_internally_tagged_enum_with_untagged_variant() {
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(tag = "kind")]
|
||||
enum InternallyTagged {
|
||||
Tagged {
|
||||
a: u8,
|
||||
},
|
||||
#[serde(untagged)]
|
||||
Untagged {
|
||||
kind: String,
|
||||
b: u8,
|
||||
},
|
||||
}
|
||||
|
||||
assert_de_tokens(
|
||||
&InternallyTagged::Tagged { a: 1 },
|
||||
&[
|
||||
Token::Map { len: Some(2) },
|
||||
Token::Str("kind"),
|
||||
Token::Str("Tagged"),
|
||||
Token::Str("a"),
|
||||
Token::U8(1),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_tokens(
|
||||
&InternallyTagged::Tagged { a: 1 },
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "InternallyTagged",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("kind"),
|
||||
Token::Str("Tagged"),
|
||||
Token::Str("a"),
|
||||
Token::U8(1),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&InternallyTagged::Untagged {
|
||||
kind: "Foo".to_owned(),
|
||||
b: 2,
|
||||
},
|
||||
&[
|
||||
Token::Map { len: Some(2) },
|
||||
Token::Str("kind"),
|
||||
Token::Str("Foo"),
|
||||
Token::Str("b"),
|
||||
Token::U8(2),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_tokens(
|
||||
&InternallyTagged::Untagged {
|
||||
kind: "Foo".to_owned(),
|
||||
b: 2,
|
||||
},
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "InternallyTagged",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("kind"),
|
||||
Token::Str("Foo"),
|
||||
Token::Str("b"),
|
||||
Token::U8(2),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_tokens(
|
||||
&InternallyTagged::Untagged {
|
||||
kind: "Tagged".to_owned(),
|
||||
b: 2,
|
||||
},
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "InternallyTagged",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("kind"),
|
||||
Token::Str("Tagged"),
|
||||
Token::Str("b"),
|
||||
Token::U8(2),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_internally_tagged_bytes() {
|
||||
#[derive(Debug, PartialEq, Deserialize)]
|
||||
@@ -987,6 +1081,15 @@ fn test_internally_tagged_struct_variant_containing_unit_variant() {
|
||||
Log { level: Level },
|
||||
}
|
||||
|
||||
assert_de_tokens(
|
||||
&Level::Info,
|
||||
&[
|
||||
Token::Enum { name: "Level" },
|
||||
Token::BorrowedStr("Info"),
|
||||
Token::Unit,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&Message::Log { level: Level::Info },
|
||||
&[
|
||||
@@ -997,7 +1100,9 @@ fn test_internally_tagged_struct_variant_containing_unit_variant() {
|
||||
Token::Str("action"),
|
||||
Token::Str("Log"),
|
||||
Token::Str("level"),
|
||||
Token::Enum { name: "Level" },
|
||||
Token::BorrowedStr("Info"),
|
||||
Token::Unit,
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
@@ -1009,7 +1114,9 @@ fn test_internally_tagged_struct_variant_containing_unit_variant() {
|
||||
Token::Str("action"),
|
||||
Token::Str("Log"),
|
||||
Token::Str("level"),
|
||||
Token::Enum { name: "Level" },
|
||||
Token::BorrowedStr("Info"),
|
||||
Token::Unit,
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
@@ -1019,7 +1126,9 @@ fn test_internally_tagged_struct_variant_containing_unit_variant() {
|
||||
&[
|
||||
Token::Seq { len: Some(2) },
|
||||
Token::Str("Log"),
|
||||
Token::Enum { name: "Level" },
|
||||
Token::BorrowedStr("Info"),
|
||||
Token::Unit,
|
||||
Token::SeqEnd,
|
||||
],
|
||||
);
|
||||
@@ -2125,24 +2234,28 @@ fn test_internally_tagged_newtype_variant_containing_unit_struct() {
|
||||
fn test_packed_struct_can_derive_serialize() {
|
||||
#[derive(Copy, Clone, Serialize)]
|
||||
#[repr(packed, C)]
|
||||
#[allow(dead_code)]
|
||||
struct PackedC {
|
||||
t: f32,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Serialize)]
|
||||
#[repr(C, packed)]
|
||||
#[allow(dead_code)]
|
||||
struct CPacked {
|
||||
t: f32,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Serialize)]
|
||||
#[repr(C, packed(2))]
|
||||
#[allow(dead_code)]
|
||||
struct CPacked2 {
|
||||
t: f32,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Serialize)]
|
||||
#[repr(packed(2), C)]
|
||||
#[allow(dead_code)]
|
||||
struct Packed2C {
|
||||
t: f32,
|
||||
}
|
||||
|
||||
@@ -7,14 +7,17 @@ mod remote {
|
||||
|
||||
pub struct PrimitivePriv(u8);
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct PrimitivePub(pub u8);
|
||||
|
||||
pub struct NewtypePriv(Unit);
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct NewtypePub(pub Unit);
|
||||
|
||||
pub struct TuplePriv(u8, Unit);
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct TuplePub(pub u8, pub Unit);
|
||||
|
||||
pub struct StructPriv {
|
||||
@@ -22,6 +25,7 @@ mod remote {
|
||||
b: Unit,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct StructPub {
|
||||
pub a: u8,
|
||||
pub b: Unit,
|
||||
@@ -86,12 +90,14 @@ mod remote {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub enum EnumGeneric<T> {
|
||||
Variant(T),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[allow(dead_code)]
|
||||
struct Test {
|
||||
#[serde(with = "UnitDef")]
|
||||
unit: remote::Unit,
|
||||
@@ -125,10 +131,14 @@ struct Test {
|
||||
|
||||
#[serde(with = "EnumConcrete")]
|
||||
enum_concrete: remote::EnumGeneric<u8>,
|
||||
|
||||
#[serde(with = "ErrorKindDef")]
|
||||
io_error_kind: ErrorKind,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "remote::Unit")]
|
||||
#[allow(dead_code)]
|
||||
struct UnitDef;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
@@ -137,6 +147,7 @@ struct PrimitivePrivDef(#[serde(getter = "remote::PrimitivePriv::get")] u8);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "remote::PrimitivePub")]
|
||||
#[allow(dead_code)]
|
||||
struct PrimitivePubDef(u8);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
@@ -145,6 +156,7 @@ struct NewtypePrivDef(#[serde(getter = "remote::NewtypePriv::get", with = "UnitD
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "remote::NewtypePub")]
|
||||
#[allow(dead_code)]
|
||||
struct NewtypePubDef(#[serde(with = "UnitDef")] remote::Unit);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
@@ -156,6 +168,7 @@ struct TuplePrivDef(
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "remote::TuplePub")]
|
||||
#[allow(dead_code)]
|
||||
struct TuplePubDef(u8, #[serde(with = "UnitDef")] remote::Unit);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
@@ -171,6 +184,7 @@ struct StructPrivDef {
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "remote::StructPub")]
|
||||
#[allow(dead_code)]
|
||||
struct StructPubDef {
|
||||
a: u8,
|
||||
|
||||
@@ -187,16 +201,37 @@ struct StructGenericWithGetterDef<T> {
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "remote::StructGeneric<u8>")]
|
||||
#[allow(dead_code)]
|
||||
struct StructConcrete {
|
||||
value: u8,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "remote::EnumGeneric<u8>")]
|
||||
#[allow(dead_code)]
|
||||
enum EnumConcrete {
|
||||
Variant(u8),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[allow(dead_code)]
|
||||
enum ErrorKind {
|
||||
NotFound,
|
||||
PermissionDenied,
|
||||
#[allow(dead_code)]
|
||||
ConnectionRefused,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "ErrorKind")]
|
||||
#[non_exhaustive]
|
||||
#[allow(dead_code)]
|
||||
enum ErrorKindDef {
|
||||
NotFound,
|
||||
PermissionDenied,
|
||||
// ...
|
||||
}
|
||||
|
||||
impl From<PrimitivePrivDef> for remote::PrimitivePriv {
|
||||
fn from(def: PrimitivePrivDef) -> Self {
|
||||
remote::PrimitivePriv::new(def.0)
|
||||
|
||||
@@ -41,7 +41,7 @@ fn test_self() {
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
struct Tuple(
|
||||
pub struct Tuple(
|
||||
Box<Self>,
|
||||
Box<<Self as Trait>::Assoc>,
|
||||
[(); Self::ASSOC],
|
||||
@@ -60,7 +60,7 @@ fn test_self() {
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
enum Enum {
|
||||
pub enum Enum {
|
||||
Struct {
|
||||
_f1: Box<Self>,
|
||||
_f2: Box<<Self as Trait>::Assoc>,
|
||||
|
||||
@@ -8,7 +8,7 @@ use std::cell::RefCell;
|
||||
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
|
||||
use std::ffi::CString;
|
||||
use std::net;
|
||||
use std::num::Wrapping;
|
||||
use std::num::{Saturating, Wrapping};
|
||||
use std::ops::Bound;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::rc::{Rc, Weak as RcWeak};
|
||||
@@ -500,6 +500,38 @@ fn test_range_inclusive() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_range_from() {
|
||||
assert_ser_tokens(
|
||||
&(1u32..),
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "RangeFrom",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("start"),
|
||||
Token::U32(1),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_range_to() {
|
||||
assert_ser_tokens(
|
||||
&(..2u32),
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "RangeTo",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("end"),
|
||||
Token::U32(2),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bound() {
|
||||
assert_ser_tokens(
|
||||
@@ -592,6 +624,11 @@ fn test_wrapping() {
|
||||
assert_ser_tokens(&Wrapping(1usize), &[Token::U64(1)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_saturating() {
|
||||
assert_ser_tokens(&Saturating(1usize), &[Token::U64(1)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rc_dst() {
|
||||
assert_ser_tokens(&Rc::<str>::from("s"), &[Token::Str("s")]);
|
||||
|
||||
@@ -27,19 +27,21 @@ mod fake_serde {
|
||||
{
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub trait Serialize {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>;
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub trait Deserialize<'a>: Sized {
|
||||
fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error>;
|
||||
}
|
||||
}
|
||||
|
||||
trait AssertNotSerdeSerialize {}
|
||||
pub trait AssertNotSerdeSerialize {}
|
||||
|
||||
impl<T: serde::Serialize> AssertNotSerdeSerialize for T {}
|
||||
|
||||
trait AssertNotSerdeDeserialize<'a> {}
|
||||
pub trait AssertNotSerdeDeserialize<'a> {}
|
||||
|
||||
impl<'a, T: serde::Deserialize<'a>> AssertNotSerdeDeserialize<'a> for T {}
|
||||
|
||||
@@ -63,7 +63,7 @@ fn test_map_access_to_enum() {
|
||||
type Value = Potential;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(formatter, "a map")
|
||||
formatter.write_str("a map")
|
||||
}
|
||||
|
||||
fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
use serde::de::Deserialize;
|
||||
use serde::ser::Serialize;
|
||||
|
||||
fn to_string<T>(_: &T) -> String
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn from_str<'de, T>(_: &'de str) -> T
|
||||
where
|
||||
T: Deserialize<'de>,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
struct MyStruct;
|
||||
|
||||
fn main() {
|
||||
to_string(&MyStruct);
|
||||
let _: MyStruct = from_str("");
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
error[E0277]: the trait bound `MyStruct: Serialize` is not satisfied
|
||||
--> tests/ui/on_unimplemented.rs:21:15
|
||||
|
|
||||
21 | to_string(&MyStruct);
|
||||
| --------- ^^^^^^^^^ the trait `Serialize` is not implemented for `MyStruct`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: for local types consider adding `#[derive(serde::Serialize)]` to your `MyStruct` type
|
||||
= note: for types from other crates check whether the crate offers a `serde` feature flag
|
||||
= help: the following other types implement trait `Serialize`:
|
||||
&'a T
|
||||
&'a mut T
|
||||
()
|
||||
(T,)
|
||||
(T0, T1)
|
||||
(T0, T1, T2)
|
||||
(T0, T1, T2, T3)
|
||||
(T0, T1, T2, T3, T4)
|
||||
and $N others
|
||||
note: required by a bound in `to_string`
|
||||
--> tests/ui/on_unimplemented.rs:6:8
|
||||
|
|
||||
4 | fn to_string<T>(_: &T) -> String
|
||||
| --------- required by a bound in this function
|
||||
5 | where
|
||||
6 | T: Serialize,
|
||||
| ^^^^^^^^^ required by this bound in `to_string`
|
||||
|
||||
error[E0277]: the trait bound `MyStruct: Deserialize<'_>` is not satisfied
|
||||
--> tests/ui/on_unimplemented.rs:22:23
|
||||
|
|
||||
22 | let _: MyStruct = from_str("");
|
||||
| ^^^^^^^^^^^^ the trait `Deserialize<'_>` is not implemented for `MyStruct`
|
||||
|
|
||||
= note: for local types consider adding `#[derive(serde::Deserialize)]` to your `MyStruct` type
|
||||
= note: for types from other crates check whether the crate offers a `serde` feature flag
|
||||
= help: the following other types implement trait `Deserialize<'de>`:
|
||||
&'a Path
|
||||
&'a [u8]
|
||||
&'a str
|
||||
()
|
||||
(T,)
|
||||
(T0, T1)
|
||||
(T0, T1, T2)
|
||||
(T0, T1, T2, T3)
|
||||
and $N others
|
||||
note: required by a bound in `from_str`
|
||||
--> tests/ui/on_unimplemented.rs:13:8
|
||||
|
|
||||
11 | fn from_str<'de, T>(_: &'de str) -> T
|
||||
| -------- required by a bound in this function
|
||||
12 | where
|
||||
13 | T: Deserialize<'de>,
|
||||
| ^^^^^^^^^^^^^^^^ required by this bound in `from_str`
|
||||
@@ -2,10 +2,17 @@ error[E0609]: no field `b` on type `&remote::S`
|
||||
--> tests/ui/remote/unknown_field.rs:12:5
|
||||
|
|
||||
12 | b: u8,
|
||||
| ^ help: a field with a similar name exists: `a`
|
||||
| ^ unknown field
|
||||
|
|
||||
help: a field with a similar name exists
|
||||
|
|
||||
12 | a: u8,
|
||||
| ~
|
||||
|
||||
error[E0560]: struct `remote::S` has no field named `b`
|
||||
--> tests/ui/remote/unknown_field.rs:12:5
|
||||
|
|
||||
12 | b: u8,
|
||||
| ^ help: a field with a similar name exists: `a`
|
||||
| ^ `remote::S` does not have this field
|
||||
|
|
||||
= note: all struct fields are already assigned
|
||||
|
||||
@@ -12,7 +12,3 @@ note: tuple struct defined here
|
||||
4 | pub struct S(pub u16);
|
||||
| ^
|
||||
= note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: you can convert a `u8` to a `u16`
|
||||
|
|
||||
7 | #[derive(Deserialize.into())]
|
||||
| +++++++
|
||||
|
||||
Reference in New Issue
Block a user