mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-04-27 05:17:56 +00:00
Compare commits
81 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 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 |
+25
-44
@@ -18,7 +18,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 45
|
timeout-minutes: 45
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- uses: dtolnay/rust-toolchain@nightly
|
- uses: dtolnay/rust-toolchain@nightly
|
||||||
- run: cd test_suite && cargo test --features unstable
|
- run: cd test_suite && cargo test --features unstable
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ jobs:
|
|||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
timeout-minutes: 45
|
timeout-minutes: 45
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- uses: dtolnay/rust-toolchain@nightly
|
- uses: dtolnay/rust-toolchain@nightly
|
||||||
- run: cd test_suite && cargo test --features unstable -- --skip ui --exact
|
- run: cd test_suite && cargo test --features unstable -- --skip ui --exact
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ jobs:
|
|||||||
rust: [stable, beta]
|
rust: [stable, beta]
|
||||||
timeout-minutes: 45
|
timeout-minutes: 45
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- uses: dtolnay/rust-toolchain@master
|
- uses: dtolnay/rust-toolchain@master
|
||||||
with:
|
with:
|
||||||
toolchain: ${{matrix.rust}}
|
toolchain: ${{matrix.rust}}
|
||||||
@@ -56,7 +56,7 @@ jobs:
|
|||||||
os: [ubuntu, windows]
|
os: [ubuntu, windows]
|
||||||
timeout-minutes: 45
|
timeout-minutes: 45
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- uses: dtolnay/rust-toolchain@nightly
|
- uses: dtolnay/rust-toolchain@nightly
|
||||||
- run: cd serde && cargo build
|
- run: cd serde && cargo build
|
||||||
- run: cd serde && cargo build --no-default-features
|
- run: cd serde && cargo build --no-default-features
|
||||||
@@ -80,7 +80,7 @@ jobs:
|
|||||||
rust: [1.31.0, 1.34.0]
|
rust: [1.31.0, 1.34.0]
|
||||||
timeout-minutes: 45
|
timeout-minutes: 45
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- uses: dtolnay/rust-toolchain@master
|
- uses: dtolnay/rust-toolchain@master
|
||||||
with:
|
with:
|
||||||
toolchain: ${{matrix.rust}}
|
toolchain: ${{matrix.rust}}
|
||||||
@@ -93,71 +93,52 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 45
|
timeout-minutes: 45
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- uses: dtolnay/rust-toolchain@1.56.0
|
- uses: dtolnay/rust-toolchain@1.56.0
|
||||||
- run: cd serde && cargo check --no-default-features
|
- run: cd serde && cargo check --no-default-features
|
||||||
- run: cd serde && cargo check
|
- run: cd serde && cargo check
|
||||||
- run: cd serde_derive && cargo check
|
- run: cd serde_derive && cargo check
|
||||||
- run: cd precompiled/serde_derive && cargo check
|
|
||||||
|
|
||||||
alloc:
|
alloc:
|
||||||
name: Rust 1.36.0
|
name: Rust 1.36.0
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 45
|
timeout-minutes: 45
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- uses: dtolnay/rust-toolchain@1.36.0
|
- uses: dtolnay/rust-toolchain@1.36.0
|
||||||
- run: cd serde && cargo build --no-default-features --features alloc
|
- 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:
|
minimal:
|
||||||
name: Minimal versions
|
name: Minimal versions
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 45
|
timeout-minutes: 45
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- uses: dtolnay/rust-toolchain@nightly
|
- uses: dtolnay/rust-toolchain@nightly
|
||||||
- run: cargo generate-lockfile -Z minimal-versions
|
- run: cargo generate-lockfile -Z minimal-versions
|
||||||
- run: cargo check --locked --workspace
|
- 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:
|
clippy:
|
||||||
name: Clippy
|
name: Clippy
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: github.event_name != 'pull_request'
|
if: github.event_name != 'pull_request'
|
||||||
timeout-minutes: 45
|
timeout-minutes: 45
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- uses: dtolnay/rust-toolchain@clippy
|
- uses: dtolnay/rust-toolchain@clippy
|
||||||
- run: cd serde && cargo clippy --features rc,unstable -- -Dclippy::all -Dclippy::pedantic
|
- run: cd serde && cargo clippy --features rc,unstable -- -Dclippy::all -Dclippy::pedantic
|
||||||
- run: cd serde_derive && cargo clippy -- -Dclippy::all -Dclippy::pedantic
|
- run: cd serde_derive && cargo clippy -- -Dclippy::all -Dclippy::pedantic
|
||||||
@@ -170,7 +151,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 45
|
timeout-minutes: 45
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- uses: dtolnay/rust-toolchain@miri
|
- uses: dtolnay/rust-toolchain@miri
|
||||||
- run: cargo miri setup
|
- run: cargo miri setup
|
||||||
- run: cd serde && cargo miri test --features derive,rc,unstable
|
- run: cd serde && cargo miri test --features derive,rc,unstable
|
||||||
@@ -186,6 +167,6 @@ jobs:
|
|||||||
if: github.event_name != 'pull_request'
|
if: github.event_name != 'pull_request'
|
||||||
timeout-minutes: 45
|
timeout-minutes: 45
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- uses: dtolnay/install@cargo-outdated
|
- uses: dtolnay/install@cargo-outdated
|
||||||
- run: cargo outdated --workspace --exit-code 1
|
- run: cargo outdated --workspace --exit-code 1
|
||||||
|
|||||||
@@ -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.183"
|
|
||||||
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.183"
|
|
||||||
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.183")]
|
|
||||||
|
|
||||||
#[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
|
|
||||||
+12
-4
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.183" # remember to update html_root_url and serde_derive dependency
|
version = "1.0.193"
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
categories = ["encoding", "no-std", "no-std::no-alloc"]
|
categories = ["encoding", "no-std", "no-std::no-alloc"]
|
||||||
@@ -15,7 +15,7 @@ repository = "https://github.com/serde-rs/serde"
|
|||||||
rust-version = "1.31"
|
rust-version = "1.31"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde_derive = { version = "=1.0.183", optional = true, path = "../serde_derive" }
|
serde_derive = { version = "1", optional = true, path = "../serde_derive" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
serde_derive = { version = "1", path = "../serde_derive" }
|
serde_derive = { version = "1", path = "../serde_derive" }
|
||||||
@@ -27,9 +27,17 @@ doc-scrape-examples = false
|
|||||||
features = ["derive", "rc"]
|
features = ["derive", "rc"]
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
features = ["derive"]
|
features = ["derive", "rc", "unstable"]
|
||||||
targets = ["x86_64-unknown-linux-gnu"]
|
targets = ["x86_64-unknown-linux-gnu"]
|
||||||
rustdoc-args = ["--generate-link-to-definition"]
|
rustdoc-args = ["--cfg", "doc_cfg", "--generate-link-to-definition"]
|
||||||
|
|
||||||
|
# This cfg cannot be enabled, but it still forces Cargo to keep serde_derive's
|
||||||
|
# version in lockstep with serde's, even if someone depends on the two crates
|
||||||
|
# separately with serde's "derive" feature disabled. Every serde_derive release
|
||||||
|
# is compatible with exactly one serde release because the generated code
|
||||||
|
# involves nonpublic APIs which are not bound by semver.
|
||||||
|
[target.'cfg(any())'.dependencies]
|
||||||
|
serde_derive = { version = "=1.0.193", path = "../serde_derive" }
|
||||||
|
|
||||||
|
|
||||||
### FEATURES #################################################################
|
### FEATURES #################################################################
|
||||||
|
|||||||
+4
-5
@@ -27,11 +27,10 @@ fn main() {
|
|||||||
println!("cargo:rustc-cfg=no_relaxed_trait_bounds");
|
println!("cargo:rustc-cfg=no_relaxed_trait_bounds");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disabled on Emscripten targets before Rust 1.40 since
|
// f32::copysign and f64::copysign stabilized in Rust 1.35.
|
||||||
// Emscripten did not support 128-bit integers until Rust 1.40
|
// https://blog.rust-lang.org/2019/05/23/Rust-1.35.0.html#copy-the-sign-of-a-floating-point-number-onto-another
|
||||||
// (https://github.com/rust-lang/rust/pull/65251)
|
if minor < 35 {
|
||||||
if emscripten && minor < 40 {
|
println!("cargo:rustc-cfg=no_float_copysign");
|
||||||
println!("cargo:rustc-cfg=no_integer128");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Current minimum supported version of serde_derive crate is Rust 1.56.
|
// Current minimum supported version of serde_derive crate is Rust 1.56.
|
||||||
|
|||||||
@@ -129,12 +129,10 @@ impl<'de> Visitor<'de> for IgnoredAny {
|
|||||||
Ok(IgnoredAny)
|
Ok(IgnoredAny)
|
||||||
}
|
}
|
||||||
|
|
||||||
serde_if_integer128! {
|
#[inline]
|
||||||
#[inline]
|
fn visit_i128<E>(self, x: i128) -> Result<Self::Value, E> {
|
||||||
fn visit_i128<E>(self, x: i128) -> Result<Self::Value, E> {
|
let _ = x;
|
||||||
let _ = x;
|
Ok(IgnoredAny)
|
||||||
Ok(IgnoredAny)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -143,12 +141,10 @@ impl<'de> Visitor<'de> for IgnoredAny {
|
|||||||
Ok(IgnoredAny)
|
Ok(IgnoredAny)
|
||||||
}
|
}
|
||||||
|
|
||||||
serde_if_integer128! {
|
#[inline]
|
||||||
#[inline]
|
fn visit_u128<E>(self, x: u128) -> Result<Self::Value, E> {
|
||||||
fn visit_u128<E>(self, x: u128) -> Result<Self::Value, E> {
|
let _ = x;
|
||||||
let _ = x;
|
Ok(IgnoredAny)
|
||||||
Ok(IgnoredAny)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|||||||
+348
-245
@@ -39,6 +39,7 @@ impl<'de> Deserialize<'de> for () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "unstable")]
|
#[cfg(feature = "unstable")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "unstable")))]
|
||||||
impl<'de> Deserialize<'de> for ! {
|
impl<'de> Deserialize<'de> for ! {
|
||||||
fn deserialize<D>(_deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(_deserializer: D) -> Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
@@ -180,6 +181,28 @@ macro_rules! num_as_self {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! num_as_copysign_self {
|
||||||
|
($ty:ident : $visit:ident) => {
|
||||||
|
#[inline]
|
||||||
|
fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: Error,
|
||||||
|
{
|
||||||
|
#[cfg(any(no_float_copysign, not(feature = "std")))]
|
||||||
|
{
|
||||||
|
Ok(v as Self::Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(not(no_float_copysign), feature = "std"))]
|
||||||
|
{
|
||||||
|
// Preserve sign of NaN. The `as` produces a nondeterministic sign.
|
||||||
|
let sign = if v.is_sign_positive() { 1.0 } else { -1.0 };
|
||||||
|
Ok((v as Self::Value).copysign(sign))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! int_to_int {
|
macro_rules! int_to_int {
|
||||||
($ty:ident : $visit:ident) => {
|
($ty:ident : $visit:ident) => {
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -351,7 +374,7 @@ impl_deserialize_num! {
|
|||||||
impl_deserialize_num! {
|
impl_deserialize_num! {
|
||||||
f32, deserialize_f32
|
f32, deserialize_f32
|
||||||
num_self!(f32:visit_f32);
|
num_self!(f32:visit_f32);
|
||||||
num_as_self!(f64:visit_f64);
|
num_as_copysign_self!(f64:visit_f64);
|
||||||
num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
|
num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
|
||||||
num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
|
num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
|
||||||
}
|
}
|
||||||
@@ -359,69 +382,67 @@ impl_deserialize_num! {
|
|||||||
impl_deserialize_num! {
|
impl_deserialize_num! {
|
||||||
f64, deserialize_f64
|
f64, deserialize_f64
|
||||||
num_self!(f64:visit_f64);
|
num_self!(f64:visit_f64);
|
||||||
num_as_self!(f32:visit_f32);
|
num_as_copysign_self!(f32:visit_f32);
|
||||||
num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
|
num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
|
||||||
num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
|
num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
|
||||||
}
|
}
|
||||||
|
|
||||||
serde_if_integer128! {
|
macro_rules! num_128 {
|
||||||
macro_rules! num_128 {
|
($ty:ident : $visit:ident) => {
|
||||||
($ty:ident : $visit:ident) => {
|
fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
|
||||||
fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
|
where
|
||||||
where
|
E: Error,
|
||||||
E: Error,
|
{
|
||||||
|
if v as i128 >= Self::Value::min_value() as i128
|
||||||
|
&& v as u128 <= Self::Value::max_value() as u128
|
||||||
{
|
{
|
||||||
if v as i128 >= Self::Value::min_value() as i128
|
Ok(v as Self::Value)
|
||||||
&& v as u128 <= Self::Value::max_value() as u128
|
} else {
|
||||||
{
|
Err(Error::invalid_value(
|
||||||
Ok(v as Self::Value)
|
Unexpected::Other(stringify!($ty)),
|
||||||
} else {
|
&self,
|
||||||
Err(Error::invalid_value(
|
))
|
||||||
Unexpected::Other(stringify!($ty)),
|
|
||||||
&self,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
|
||||||
(nonzero $primitive:ident $ty:ident : $visit:ident) => {
|
(nonzero $primitive:ident $ty:ident : $visit:ident) => {
|
||||||
fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
|
fn $visit<E>(self, v: $ty) -> Result<Self::Value, E>
|
||||||
where
|
where
|
||||||
E: Error,
|
E: Error,
|
||||||
|
{
|
||||||
|
if v as i128 >= $primitive::min_value() as i128
|
||||||
|
&& v as u128 <= $primitive::max_value() as u128
|
||||||
{
|
{
|
||||||
if v as i128 >= $primitive::min_value() as i128
|
if let Some(nonzero) = Self::Value::new(v as $primitive) {
|
||||||
&& v as u128 <= $primitive::max_value() as u128
|
Ok(nonzero)
|
||||||
{
|
|
||||||
if let Some(nonzero) = Self::Value::new(v as $primitive) {
|
|
||||||
Ok(nonzero)
|
|
||||||
} else {
|
|
||||||
Err(Error::invalid_value(Unexpected::Unsigned(0), &self))
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Err(Error::invalid_value(
|
Err(Error::invalid_value(Unexpected::Unsigned(0), &self))
|
||||||
Unexpected::Other(stringify!($ty)),
|
|
||||||
&self,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Err(Error::invalid_value(
|
||||||
|
Unexpected::Other(stringify!($ty)),
|
||||||
|
&self,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
}
|
};
|
||||||
|
}
|
||||||
|
|
||||||
impl_deserialize_num! {
|
impl_deserialize_num! {
|
||||||
i128, NonZeroI128 cfg(not(no_num_nonzero_signed)), deserialize_i128
|
i128, NonZeroI128 cfg(not(no_num_nonzero_signed)), deserialize_i128
|
||||||
num_self!(i128:visit_i128);
|
num_self!(i128:visit_i128);
|
||||||
num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
|
num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
|
||||||
num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
|
num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
|
||||||
num_128!(u128:visit_u128);
|
num_128!(u128:visit_u128);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_deserialize_num! {
|
impl_deserialize_num! {
|
||||||
u128, NonZeroU128, deserialize_u128
|
u128, NonZeroU128, deserialize_u128
|
||||||
num_self!(u128:visit_u128);
|
num_self!(u128:visit_u128);
|
||||||
num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
|
num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64);
|
||||||
int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
|
int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64);
|
||||||
num_128!(i128:visit_i128);
|
num_128!(i128:visit_i128);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -576,6 +597,7 @@ impl<'a, 'de> Visitor<'de> for StringInPlaceVisitor<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
impl<'de> Deserialize<'de> for String {
|
impl<'de> Deserialize<'de> for String {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
@@ -719,6 +741,7 @@ impl<'de> Visitor<'de> for CStringVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", all(not(no_core_cstr), feature = "alloc")))]
|
#[cfg(any(feature = "std", all(not(no_core_cstr), feature = "alloc")))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
impl<'de> Deserialize<'de> for CString {
|
impl<'de> Deserialize<'de> for CString {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
@@ -730,10 +753,10 @@ impl<'de> Deserialize<'de> for CString {
|
|||||||
|
|
||||||
macro_rules! forwarded_impl {
|
macro_rules! forwarded_impl {
|
||||||
(
|
(
|
||||||
$(#[doc = $doc:tt])*
|
$(#[$attr:meta])*
|
||||||
($($id:ident),*), $ty:ty, $func:expr
|
($($id:ident),*), $ty:ty, $func:expr
|
||||||
) => {
|
) => {
|
||||||
$(#[doc = $doc])*
|
$(#[$attr])*
|
||||||
impl<'de $(, $id : Deserialize<'de>,)*> Deserialize<'de> for $ty {
|
impl<'de $(, $id : Deserialize<'de>,)*> Deserialize<'de> for $ty {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
@@ -745,10 +768,15 @@ macro_rules! forwarded_impl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", all(not(no_core_cstr), feature = "alloc")))]
|
forwarded_impl! {
|
||||||
forwarded_impl!((), Box<CStr>, CString::into_boxed_c_str);
|
#[cfg(any(feature = "std", all(not(no_core_cstr), feature = "alloc")))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
|
(), Box<CStr>, CString::into_boxed_c_str
|
||||||
|
}
|
||||||
|
|
||||||
forwarded_impl!((T), Reverse<T>, Reverse);
|
forwarded_impl! {
|
||||||
|
(T), Reverse<T>, Reverse
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -854,9 +882,9 @@ impl<'de, T: ?Sized> Deserialize<'de> for PhantomData<T> {
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
|
||||||
macro_rules! seq_impl {
|
macro_rules! seq_impl {
|
||||||
(
|
(
|
||||||
|
$(#[$attr:meta])*
|
||||||
$ty:ident <T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)*>,
|
$ty:ident <T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)*>,
|
||||||
$access:ident,
|
$access:ident,
|
||||||
$clear:expr,
|
$clear:expr,
|
||||||
@@ -864,6 +892,7 @@ macro_rules! seq_impl {
|
|||||||
$reserve:expr,
|
$reserve:expr,
|
||||||
$insert:expr
|
$insert:expr
|
||||||
) => {
|
) => {
|
||||||
|
$(#[$attr])*
|
||||||
impl<'de, T $(, $typaram)*> Deserialize<'de> for $ty<T $(, $typaram)*>
|
impl<'de, T $(, $typaram)*> Deserialize<'de> for $ty<T $(, $typaram)*>
|
||||||
where
|
where
|
||||||
T: Deserialize<'de> $(+ $tbound1 $(+ $tbound2)*)*,
|
T: Deserialize<'de> $(+ $tbound1 $(+ $tbound2)*)*,
|
||||||
@@ -951,8 +980,9 @@ macro_rules! seq_impl {
|
|||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
fn nop_reserve<T>(_seq: T, _n: usize) {}
|
fn nop_reserve<T>(_seq: T, _n: usize) {}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
|
||||||
seq_impl!(
|
seq_impl!(
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
BinaryHeap<T: Ord>,
|
BinaryHeap<T: Ord>,
|
||||||
seq,
|
seq,
|
||||||
BinaryHeap::clear,
|
BinaryHeap::clear,
|
||||||
@@ -961,8 +991,9 @@ seq_impl!(
|
|||||||
BinaryHeap::push
|
BinaryHeap::push
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
|
||||||
seq_impl!(
|
seq_impl!(
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
BTreeSet<T: Eq + Ord>,
|
BTreeSet<T: Eq + Ord>,
|
||||||
seq,
|
seq,
|
||||||
BTreeSet::clear,
|
BTreeSet::clear,
|
||||||
@@ -971,8 +1002,9 @@ seq_impl!(
|
|||||||
BTreeSet::insert
|
BTreeSet::insert
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
|
||||||
seq_impl!(
|
seq_impl!(
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
LinkedList<T>,
|
LinkedList<T>,
|
||||||
seq,
|
seq,
|
||||||
LinkedList::clear,
|
LinkedList::clear,
|
||||||
@@ -981,8 +1013,9 @@ seq_impl!(
|
|||||||
LinkedList::push_back
|
LinkedList::push_back
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
seq_impl!(
|
seq_impl!(
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
HashSet<T: Eq + Hash, S: BuildHasher + Default>,
|
HashSet<T: Eq + Hash, S: BuildHasher + Default>,
|
||||||
seq,
|
seq,
|
||||||
HashSet::clear,
|
HashSet::clear,
|
||||||
@@ -991,8 +1024,9 @@ seq_impl!(
|
|||||||
HashSet::insert
|
HashSet::insert
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
|
||||||
seq_impl!(
|
seq_impl!(
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
VecDeque<T>,
|
VecDeque<T>,
|
||||||
seq,
|
seq,
|
||||||
VecDeque::clear,
|
VecDeque::clear,
|
||||||
@@ -1004,6 +1038,7 @@ seq_impl!(
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
impl<'de, T> Deserialize<'de> for Vec<T>
|
impl<'de, T> Deserialize<'de> for Vec<T>
|
||||||
where
|
where
|
||||||
T: Deserialize<'de>,
|
T: Deserialize<'de>,
|
||||||
@@ -1349,13 +1384,14 @@ tuple_impls! {
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
|
||||||
macro_rules! map_impl {
|
macro_rules! map_impl {
|
||||||
(
|
(
|
||||||
|
$(#[$attr:meta])*
|
||||||
$ty:ident <K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)*>,
|
$ty:ident <K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)*>,
|
||||||
$access:ident,
|
$access:ident,
|
||||||
$with_capacity:expr
|
$with_capacity:expr,
|
||||||
) => {
|
) => {
|
||||||
|
$(#[$attr])*
|
||||||
impl<'de, K, V $(, $typaram)*> Deserialize<'de> for $ty<K, V $(, $typaram)*>
|
impl<'de, K, V $(, $typaram)*> Deserialize<'de> for $ty<K, V $(, $typaram)*>
|
||||||
where
|
where
|
||||||
K: Deserialize<'de> $(+ $kbound1 $(+ $kbound2)*)*,
|
K: Deserialize<'de> $(+ $kbound1 $(+ $kbound2)*)*,
|
||||||
@@ -1404,21 +1440,30 @@ macro_rules! map_impl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
map_impl! {
|
||||||
map_impl!(BTreeMap<K: Ord, V>, map, BTreeMap::new());
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
|
BTreeMap<K: Ord, V>,
|
||||||
|
map,
|
||||||
|
BTreeMap::new(),
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
map_impl! {
|
||||||
map_impl!(
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
HashMap<K: Eq + Hash, V, S: BuildHasher + Default>,
|
HashMap<K: Eq + Hash, V, S: BuildHasher + Default>,
|
||||||
map,
|
map,
|
||||||
HashMap::with_capacity_and_hasher(size_hint::cautious::<(K, V)>(map.size_hint()), S::default())
|
HashMap::with_capacity_and_hasher(size_hint::cautious::<(K, V)>(map.size_hint()), S::default()),
|
||||||
);
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
macro_rules! parse_ip_impl {
|
macro_rules! parse_ip_impl {
|
||||||
($expecting:tt $ty:ty; $size:tt) => {
|
(
|
||||||
|
$(#[$attr:meta])*
|
||||||
|
$ty:ty, $expecting:expr, $size:tt
|
||||||
|
) => {
|
||||||
|
$(#[$attr])*
|
||||||
impl<'de> Deserialize<'de> for $ty {
|
impl<'de> Deserialize<'de> for $ty {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
@@ -1547,6 +1592,7 @@ macro_rules! deserialize_enum {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
impl<'de> Deserialize<'de> for net::IpAddr {
|
impl<'de> Deserialize<'de> for net::IpAddr {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
@@ -1565,15 +1611,25 @@ impl<'de> Deserialize<'de> for net::IpAddr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
parse_ip_impl! {
|
||||||
parse_ip_impl!("IPv4 address" net::Ipv4Addr; 4);
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
|
net::Ipv4Addr, "IPv4 address", 4
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
parse_ip_impl! {
|
||||||
parse_ip_impl!("IPv6 address" net::Ipv6Addr; 16);
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
|
net::Ipv6Addr, "IPv6 address", 16
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
macro_rules! parse_socket_impl {
|
macro_rules! parse_socket_impl {
|
||||||
($expecting:tt $ty:ty, $new:expr) => {
|
(
|
||||||
|
$(#[$attr:meta])*
|
||||||
|
$ty:ty, $expecting:tt,
|
||||||
|
$new:expr,
|
||||||
|
) => {
|
||||||
|
$(#[$attr])*
|
||||||
impl<'de> Deserialize<'de> for $ty {
|
impl<'de> Deserialize<'de> for $ty {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
@@ -1590,6 +1646,7 @@ macro_rules! parse_socket_impl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
impl<'de> Deserialize<'de> for net::SocketAddr {
|
impl<'de> Deserialize<'de> for net::SocketAddr {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
@@ -1608,11 +1665,19 @@ impl<'de> Deserialize<'de> for net::SocketAddr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
parse_socket_impl! {
|
||||||
parse_socket_impl!("IPv4 socket address" net::SocketAddrV4, |(ip, port)| net::SocketAddrV4::new(ip, port));
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
|
net::SocketAddrV4, "IPv4 socket address",
|
||||||
|
|(ip, port)| net::SocketAddrV4::new(ip, port),
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
parse_socket_impl! {
|
||||||
parse_socket_impl!("IPv6 socket address" net::SocketAddrV6, |(ip, port)| net::SocketAddrV6::new(ip, port, 0, 0));
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
|
net::SocketAddrV6, "IPv6 socket address",
|
||||||
|
|(ip, port)| net::SocketAddrV6::new(ip, port, 0, 0),
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -1645,6 +1710,7 @@ impl<'a> Visitor<'a> for PathVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
impl<'de: 'a, 'a> Deserialize<'de> for &'a Path {
|
impl<'de: 'a, 'a> Deserialize<'de> for &'a Path {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
@@ -1699,6 +1765,7 @@ impl<'de> Visitor<'de> for PathBufVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
impl<'de> Deserialize<'de> for PathBuf {
|
impl<'de> Deserialize<'de> for PathBuf {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
@@ -1708,8 +1775,11 @@ impl<'de> Deserialize<'de> for PathBuf {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
forwarded_impl! {
|
||||||
forwarded_impl!((), Box<Path>, PathBuf::into_boxed_path);
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
|
(), Box<Path>, PathBuf::into_boxed_path
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -1769,6 +1839,7 @@ impl<'de> Visitor<'de> for OsStringVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "std", any(unix, windows)))]
|
#[cfg(all(feature = "std", any(unix, windows)))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", any(unix, windows)))))]
|
||||||
impl<'de> Deserialize<'de> for OsString {
|
impl<'de> Deserialize<'de> for OsString {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
@@ -1780,19 +1851,32 @@ impl<'de> Deserialize<'de> for OsString {
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
forwarded_impl! {
|
||||||
forwarded_impl!((T), Box<T>, Box::new);
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
(T), Box<T>, Box::new
|
||||||
forwarded_impl!((T), Box<[T]>, Vec::into_boxed_slice);
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
forwarded_impl! {
|
||||||
forwarded_impl!((), Box<str>, String::into_boxed_str);
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
#[cfg(all(feature = "std", any(unix, windows)))]
|
(T), Box<[T]>, Vec::into_boxed_slice
|
||||||
forwarded_impl!((), Box<OsStr>, OsString::into_boxed_os_str);
|
}
|
||||||
|
|
||||||
|
forwarded_impl! {
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
|
(), Box<str>, String::into_boxed_str
|
||||||
|
}
|
||||||
|
|
||||||
|
forwarded_impl! {
|
||||||
|
#[cfg(all(feature = "std", any(unix, windows)))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", any(unix, windows)))))]
|
||||||
|
(), Box<OsStr>, OsString::into_boxed_os_str
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T>
|
impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T>
|
||||||
where
|
where
|
||||||
T: ToOwned,
|
T: ToOwned,
|
||||||
@@ -1814,6 +1898,10 @@ where
|
|||||||
///
|
///
|
||||||
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
||||||
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||||
|
#[cfg_attr(
|
||||||
|
doc_cfg,
|
||||||
|
doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc"))))
|
||||||
|
)]
|
||||||
impl<'de, T: ?Sized> Deserialize<'de> for RcWeak<T>
|
impl<'de, T: ?Sized> Deserialize<'de> for RcWeak<T>
|
||||||
where
|
where
|
||||||
T: Deserialize<'de>,
|
T: Deserialize<'de>,
|
||||||
@@ -1832,6 +1920,10 @@ where
|
|||||||
///
|
///
|
||||||
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
||||||
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||||
|
#[cfg_attr(
|
||||||
|
doc_cfg,
|
||||||
|
doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc"))))
|
||||||
|
)]
|
||||||
impl<'de, T: ?Sized> Deserialize<'de> for ArcWeak<T>
|
impl<'de, T: ?Sized> Deserialize<'de> for ArcWeak<T>
|
||||||
where
|
where
|
||||||
T: Deserialize<'de>,
|
T: Deserialize<'de>,
|
||||||
@@ -1847,13 +1939,12 @@ where
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
|
||||||
macro_rules! box_forwarded_impl {
|
macro_rules! box_forwarded_impl {
|
||||||
(
|
(
|
||||||
$(#[doc = $doc:tt])*
|
$(#[$attr:meta])*
|
||||||
$t:ident
|
$t:ident
|
||||||
) => {
|
) => {
|
||||||
$(#[doc = $doc])*
|
$(#[$attr])*
|
||||||
impl<'de, T: ?Sized> Deserialize<'de> for $t<T>
|
impl<'de, T: ?Sized> Deserialize<'de> for $t<T>
|
||||||
where
|
where
|
||||||
Box<T>: Deserialize<'de>,
|
Box<T>: Deserialize<'de>,
|
||||||
@@ -1868,7 +1959,6 @@ macro_rules! box_forwarded_impl {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
|
||||||
box_forwarded_impl! {
|
box_forwarded_impl! {
|
||||||
/// This impl requires the [`"rc"`] Cargo feature of Serde.
|
/// This impl requires the [`"rc"`] Cargo feature of Serde.
|
||||||
///
|
///
|
||||||
@@ -1877,10 +1967,11 @@ box_forwarded_impl! {
|
|||||||
/// will end up with a strong count of 1.
|
/// will end up with a strong count of 1.
|
||||||
///
|
///
|
||||||
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
||||||
|
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))]
|
||||||
Rc
|
Rc
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
|
||||||
box_forwarded_impl! {
|
box_forwarded_impl! {
|
||||||
/// This impl requires the [`"rc"`] Cargo feature of Serde.
|
/// This impl requires the [`"rc"`] Cargo feature of Serde.
|
||||||
///
|
///
|
||||||
@@ -1889,6 +1980,8 @@ box_forwarded_impl! {
|
|||||||
/// will end up with a strong count of 1.
|
/// will end up with a strong count of 1.
|
||||||
///
|
///
|
||||||
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
||||||
|
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))]
|
||||||
Arc
|
Arc
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1906,13 +1999,21 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
forwarded_impl!((T), RefCell<T>, RefCell::new);
|
forwarded_impl! {
|
||||||
|
(T), RefCell<T>, RefCell::new
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
forwarded_impl! {
|
||||||
forwarded_impl!((T), Mutex<T>, Mutex::new);
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
|
(T), Mutex<T>, Mutex::new
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
forwarded_impl! {
|
||||||
forwarded_impl!((T), RwLock<T>, RwLock::new);
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
|
(T), RwLock<T>, RwLock::new
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -2065,6 +2166,7 @@ impl<'de> Deserialize<'de> for Duration {
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
impl<'de> Deserialize<'de> for SystemTime {
|
impl<'de> Deserialize<'de> for SystemTime {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
@@ -2424,144 +2526,6 @@ mod range_from {
|
|||||||
|
|
||||||
use crate::de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
|
use crate::de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
|
||||||
|
|
||||||
pub const FIELDS: &[&str] = &["end"];
|
|
||||||
|
|
||||||
// If this were outside of the serde crate, it would just use:
|
|
||||||
//
|
|
||||||
// #[derive(Deserialize)]
|
|
||||||
// #[serde(field_identifier, rename_all = "lowercase")]
|
|
||||||
enum Field {
|
|
||||||
End,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for Field {
|
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
struct FieldVisitor;
|
|
||||||
|
|
||||||
impl<'de> Visitor<'de> for FieldVisitor {
|
|
||||||
type Value = Field;
|
|
||||||
|
|
||||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
formatter.write_str("`end`")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
match value {
|
|
||||||
"end" => Ok(Field::End),
|
|
||||||
_ => Err(Error::unknown_field(value, FIELDS)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
match value {
|
|
||||||
b"end" => Ok(Field::End),
|
|
||||||
_ => {
|
|
||||||
let value = crate::__private::from_utf8_lossy(value);
|
|
||||||
Err(Error::unknown_field(&*value, FIELDS))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deserializer.deserialize_identifier(FieldVisitor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct RangeFromVisitor<Idx> {
|
|
||||||
pub expecting: &'static str,
|
|
||||||
pub phantom: PhantomData<Idx>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, Idx> Visitor<'de> for RangeFromVisitor<Idx>
|
|
||||||
where
|
|
||||||
Idx: Deserialize<'de>,
|
|
||||||
{
|
|
||||||
type Value = Idx;
|
|
||||||
|
|
||||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
formatter.write_str(self.expecting)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
|
||||||
where
|
|
||||||
A: SeqAccess<'de>,
|
|
||||||
{
|
|
||||||
let end: Idx = match tri!(seq.next_element()) {
|
|
||||||
Some(value) => value,
|
|
||||||
None => {
|
|
||||||
return Err(Error::invalid_length(0, &self));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Ok(end)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
|
|
||||||
where
|
|
||||||
A: MapAccess<'de>,
|
|
||||||
{
|
|
||||||
let mut end: Option<Idx> = None;
|
|
||||||
while let Some(key) = tri!(map.next_key()) {
|
|
||||||
match key {
|
|
||||||
Field::End => {
|
|
||||||
if end.is_some() {
|
|
||||||
return Err(<A::Error as Error>::duplicate_field("end"));
|
|
||||||
}
|
|
||||||
end = Some(tri!(map.next_value()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let end = match end {
|
|
||||||
Some(end) => end,
|
|
||||||
None => return Err(<A::Error as Error>::missing_field("end")),
|
|
||||||
};
|
|
||||||
Ok(end)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Similar to:
|
|
||||||
//
|
|
||||||
// #[derive(Deserialize)]
|
|
||||||
// #[serde(deny_unknown_fields)]
|
|
||||||
// struct RangeTo<Idx> {
|
|
||||||
// start: Idx,
|
|
||||||
// }
|
|
||||||
impl<'de, Idx> Deserialize<'de> for RangeTo<Idx>
|
|
||||||
where
|
|
||||||
Idx: Deserialize<'de>,
|
|
||||||
{
|
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
let end = tri!(deserializer.deserialize_struct(
|
|
||||||
"RangeTo",
|
|
||||||
range_to::FIELDS,
|
|
||||||
range_to::RangeToVisitor {
|
|
||||||
expecting: "struct RangeTo",
|
|
||||||
phantom: PhantomData,
|
|
||||||
},
|
|
||||||
));
|
|
||||||
Ok(..end)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod range_to {
|
|
||||||
use crate::lib::*;
|
|
||||||
|
|
||||||
use crate::de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
|
|
||||||
|
|
||||||
pub const FIELDS: &[&str] = &["start"];
|
pub const FIELDS: &[&str] = &["start"];
|
||||||
|
|
||||||
// If this were outside of the serde crate, it would just use:
|
// If this were outside of the serde crate, it would just use:
|
||||||
@@ -2614,12 +2578,12 @@ mod range_to {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RangeToVisitor<Idx> {
|
pub struct RangeFromVisitor<Idx> {
|
||||||
pub expecting: &'static str,
|
pub expecting: &'static str,
|
||||||
pub phantom: PhantomData<Idx>,
|
pub phantom: PhantomData<Idx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, Idx> Visitor<'de> for RangeToVisitor<Idx>
|
impl<'de, Idx> Visitor<'de> for RangeFromVisitor<Idx>
|
||||||
where
|
where
|
||||||
Idx: Deserialize<'de>,
|
Idx: Deserialize<'de>,
|
||||||
{
|
{
|
||||||
@@ -2668,6 +2632,144 @@ mod range_to {
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Similar to:
|
||||||
|
//
|
||||||
|
// #[derive(Deserialize)]
|
||||||
|
// #[serde(deny_unknown_fields)]
|
||||||
|
// struct RangeTo<Idx> {
|
||||||
|
// end: Idx,
|
||||||
|
// }
|
||||||
|
impl<'de, Idx> Deserialize<'de> for RangeTo<Idx>
|
||||||
|
where
|
||||||
|
Idx: Deserialize<'de>,
|
||||||
|
{
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let end = tri!(deserializer.deserialize_struct(
|
||||||
|
"RangeTo",
|
||||||
|
range_to::FIELDS,
|
||||||
|
range_to::RangeToVisitor {
|
||||||
|
expecting: "struct RangeTo",
|
||||||
|
phantom: PhantomData,
|
||||||
|
},
|
||||||
|
));
|
||||||
|
Ok(..end)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod range_to {
|
||||||
|
use crate::lib::*;
|
||||||
|
|
||||||
|
use crate::de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
|
||||||
|
|
||||||
|
pub const FIELDS: &[&str] = &["end"];
|
||||||
|
|
||||||
|
// If this were outside of the serde crate, it would just use:
|
||||||
|
//
|
||||||
|
// #[derive(Deserialize)]
|
||||||
|
// #[serde(field_identifier, rename_all = "lowercase")]
|
||||||
|
enum Field {
|
||||||
|
End,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for Field {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
struct FieldVisitor;
|
||||||
|
|
||||||
|
impl<'de> Visitor<'de> for FieldVisitor {
|
||||||
|
type Value = Field;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
formatter.write_str("`end`")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: Error,
|
||||||
|
{
|
||||||
|
match value {
|
||||||
|
"end" => Ok(Field::End),
|
||||||
|
_ => Err(Error::unknown_field(value, FIELDS)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: Error,
|
||||||
|
{
|
||||||
|
match value {
|
||||||
|
b"end" => Ok(Field::End),
|
||||||
|
_ => {
|
||||||
|
let value = crate::__private::from_utf8_lossy(value);
|
||||||
|
Err(Error::unknown_field(&*value, FIELDS))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deserializer.deserialize_identifier(FieldVisitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RangeToVisitor<Idx> {
|
||||||
|
pub expecting: &'static str,
|
||||||
|
pub phantom: PhantomData<Idx>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de, Idx> Visitor<'de> for RangeToVisitor<Idx>
|
||||||
|
where
|
||||||
|
Idx: Deserialize<'de>,
|
||||||
|
{
|
||||||
|
type Value = Idx;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
formatter.write_str(self.expecting)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||||
|
where
|
||||||
|
A: SeqAccess<'de>,
|
||||||
|
{
|
||||||
|
let end: Idx = match tri!(seq.next_element()) {
|
||||||
|
Some(value) => value,
|
||||||
|
None => {
|
||||||
|
return Err(Error::invalid_length(0, &self));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok(end)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
|
||||||
|
where
|
||||||
|
A: MapAccess<'de>,
|
||||||
|
{
|
||||||
|
let mut end: Option<Idx> = None;
|
||||||
|
while let Some(key) = tri!(map.next_key()) {
|
||||||
|
match key {
|
||||||
|
Field::End => {
|
||||||
|
if end.is_some() {
|
||||||
|
return Err(<A::Error as Error>::duplicate_field("end"));
|
||||||
|
}
|
||||||
|
end = Some(tri!(map.next_value()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let end = match end {
|
||||||
|
Some(end) => end,
|
||||||
|
None => return Err(<A::Error as Error>::missing_field("end")),
|
||||||
|
};
|
||||||
|
Ok(end)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
impl<'de, T> Deserialize<'de> for Bound<T>
|
impl<'de, T> Deserialize<'de> for Bound<T>
|
||||||
where
|
where
|
||||||
T: Deserialize<'de>,
|
T: Deserialize<'de>,
|
||||||
@@ -2900,6 +3002,7 @@ macro_rules! atomic_impl {
|
|||||||
($($ty:ident $size:expr)*) => {
|
($($ty:ident $size:expr)*) => {
|
||||||
$(
|
$(
|
||||||
#[cfg(any(no_target_has_atomic, target_has_atomic = $size))]
|
#[cfg(any(no_target_has_atomic, target_has_atomic = $size))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", target_has_atomic = $size))))]
|
||||||
impl<'de> Deserialize<'de> for $ty {
|
impl<'de> Deserialize<'de> for $ty {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
|
|||||||
+49
-56
@@ -118,12 +118,10 @@ use crate::lib::*;
|
|||||||
|
|
||||||
pub mod value;
|
pub mod value;
|
||||||
|
|
||||||
#[cfg(not(no_integer128))]
|
|
||||||
mod format;
|
mod format;
|
||||||
mod ignored_any;
|
mod ignored_any;
|
||||||
mod impls;
|
mod impls;
|
||||||
pub(crate) mod size_hint;
|
pub(crate) mod size_hint;
|
||||||
mod utf8;
|
|
||||||
|
|
||||||
pub use self::ignored_any::IgnoredAny;
|
pub use self::ignored_any::IgnoredAny;
|
||||||
|
|
||||||
@@ -950,18 +948,15 @@ pub trait Deserializer<'de>: Sized {
|
|||||||
where
|
where
|
||||||
V: Visitor<'de>;
|
V: Visitor<'de>;
|
||||||
|
|
||||||
serde_if_integer128! {
|
/// Hint that the `Deserialize` type is expecting an `i128` value.
|
||||||
/// Hint that the `Deserialize` type is expecting an `i128` value.
|
///
|
||||||
///
|
/// The default behavior unconditionally returns an error.
|
||||||
/// This method is available only on Rust compiler versions >=1.26. The
|
fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
/// default behavior unconditionally returns an error.
|
where
|
||||||
fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
V: Visitor<'de>,
|
||||||
where
|
{
|
||||||
V: Visitor<'de>
|
let _ = visitor;
|
||||||
{
|
Err(Error::custom("i128 is not supported"))
|
||||||
let _ = visitor;
|
|
||||||
Err(Error::custom("i128 is not supported"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Hint that the `Deserialize` type is expecting a `u8` value.
|
/// Hint that the `Deserialize` type is expecting a `u8` value.
|
||||||
@@ -984,18 +979,15 @@ pub trait Deserializer<'de>: Sized {
|
|||||||
where
|
where
|
||||||
V: Visitor<'de>;
|
V: Visitor<'de>;
|
||||||
|
|
||||||
serde_if_integer128! {
|
/// Hint that the `Deserialize` type is expecting an `u128` value.
|
||||||
/// Hint that the `Deserialize` type is expecting an `u128` value.
|
///
|
||||||
///
|
/// The default behavior unconditionally returns an error.
|
||||||
/// This method is available only on Rust compiler versions >=1.26. The
|
fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
/// default behavior unconditionally returns an error.
|
where
|
||||||
fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
V: Visitor<'de>,
|
||||||
where
|
{
|
||||||
V: Visitor<'de>
|
let _ = visitor;
|
||||||
{
|
Err(Error::custom("u128 is not supported"))
|
||||||
let _ = visitor;
|
|
||||||
Err(Error::custom("u128 is not supported"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Hint that the `Deserialize` type is expecting a `f32` value.
|
/// Hint that the `Deserialize` type is expecting a `f32` value.
|
||||||
@@ -1367,20 +1359,20 @@ pub trait Visitor<'de>: Sized {
|
|||||||
Err(Error::invalid_type(Unexpected::Signed(v), &self))
|
Err(Error::invalid_type(Unexpected::Signed(v), &self))
|
||||||
}
|
}
|
||||||
|
|
||||||
serde_if_integer128! {
|
/// The input contains a `i128`.
|
||||||
/// The input contains a `i128`.
|
///
|
||||||
///
|
/// The default implementation fails with a type error.
|
||||||
/// This method is available only on Rust compiler versions >=1.26. The
|
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
|
||||||
/// default implementation fails with a type error.
|
where
|
||||||
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
|
E: Error,
|
||||||
where
|
{
|
||||||
E: Error,
|
let mut buf = [0u8; 58];
|
||||||
{
|
let mut writer = format::Buf::new(&mut buf);
|
||||||
let mut buf = [0u8; 58];
|
fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as i128", v)).unwrap();
|
||||||
let mut writer = format::Buf::new(&mut buf);
|
Err(Error::invalid_type(
|
||||||
fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as i128", v)).unwrap();
|
Unexpected::Other(writer.as_str()),
|
||||||
Err(Error::invalid_type(Unexpected::Other(writer.as_str()), &self))
|
&self,
|
||||||
}
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The input contains a `u8`.
|
/// The input contains a `u8`.
|
||||||
@@ -1429,20 +1421,20 @@ pub trait Visitor<'de>: Sized {
|
|||||||
Err(Error::invalid_type(Unexpected::Unsigned(v), &self))
|
Err(Error::invalid_type(Unexpected::Unsigned(v), &self))
|
||||||
}
|
}
|
||||||
|
|
||||||
serde_if_integer128! {
|
/// The input contains a `u128`.
|
||||||
/// The input contains a `u128`.
|
///
|
||||||
///
|
/// The default implementation fails with a type error.
|
||||||
/// This method is available only on Rust compiler versions >=1.26. The
|
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
|
||||||
/// default implementation fails with a type error.
|
where
|
||||||
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
|
E: Error,
|
||||||
where
|
{
|
||||||
E: Error,
|
let mut buf = [0u8; 57];
|
||||||
{
|
let mut writer = format::Buf::new(&mut buf);
|
||||||
let mut buf = [0u8; 57];
|
fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as u128", v)).unwrap();
|
||||||
let mut writer = format::Buf::new(&mut buf);
|
Err(Error::invalid_type(
|
||||||
fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as u128", v)).unwrap();
|
Unexpected::Other(writer.as_str()),
|
||||||
Err(Error::invalid_type(Unexpected::Other(writer.as_str()), &self))
|
&self,
|
||||||
}
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The input contains an `f32`.
|
/// The input contains an `f32`.
|
||||||
@@ -1478,7 +1470,7 @@ pub trait Visitor<'de>: Sized {
|
|||||||
where
|
where
|
||||||
E: Error,
|
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
|
/// The input contains a string. The lifetime of the string is ephemeral and
|
||||||
@@ -1533,6 +1525,7 @@ pub trait Visitor<'de>: Sized {
|
|||||||
/// `String`.
|
/// `String`.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
|
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
|
||||||
where
|
where
|
||||||
E: Error,
|
E: Error,
|
||||||
@@ -1555,7 +1548,6 @@ pub trait Visitor<'de>: Sized {
|
|||||||
where
|
where
|
||||||
E: Error,
|
E: Error,
|
||||||
{
|
{
|
||||||
let _ = v;
|
|
||||||
Err(Error::invalid_type(Unexpected::Bytes(v), &self))
|
Err(Error::invalid_type(Unexpected::Bytes(v), &self))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1592,6 +1584,7 @@ pub trait Visitor<'de>: Sized {
|
|||||||
/// The default implementation forwards to `visit_bytes` and then drops the
|
/// The default implementation forwards to `visit_bytes` and then drops the
|
||||||
/// `Vec<u8>`.
|
/// `Vec<u8>`.
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
|
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
|
||||||
where
|
where
|
||||||
E: Error,
|
E: Error,
|
||||||
|
|||||||
@@ -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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+14
-5
@@ -112,6 +112,7 @@ impl Debug for Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
impl error::Error for Error {
|
impl error::Error for Error {
|
||||||
fn description(&self) -> &str {
|
fn description(&self) -> &str {
|
||||||
&self.err
|
&self.err
|
||||||
@@ -184,12 +185,14 @@ impl<E> Debug for UnitDeserializer<E> {
|
|||||||
|
|
||||||
/// A deserializer that cannot be instantiated.
|
/// A deserializer that cannot be instantiated.
|
||||||
#[cfg(feature = "unstable")]
|
#[cfg(feature = "unstable")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "unstable")))]
|
||||||
pub struct NeverDeserializer<E> {
|
pub struct NeverDeserializer<E> {
|
||||||
never: !,
|
never: !,
|
||||||
marker: PhantomData<E>,
|
marker: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "unstable")]
|
#[cfg(feature = "unstable")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "unstable")))]
|
||||||
impl<'de, E> IntoDeserializer<'de, E> for !
|
impl<'de, E> IntoDeserializer<'de, E> for !
|
||||||
where
|
where
|
||||||
E: de::Error,
|
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!(i16, "an `i16`.", I16Deserializer, visit_i16);
|
||||||
primitive_deserializer!(i32, "an `i32`.", I32Deserializer, visit_i32);
|
primitive_deserializer!(i32, "an `i32`.", I32Deserializer, visit_i32);
|
||||||
primitive_deserializer!(i64, "an `i64`.", I64Deserializer, visit_i64);
|
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!(isize, "an `isize`.", IsizeDeserializer, visit_i64 as i64);
|
||||||
primitive_deserializer!(u8, "a `u8`.", U8Deserializer, visit_u8);
|
primitive_deserializer!(u8, "a `u8`.", U8Deserializer, visit_u8);
|
||||||
primitive_deserializer!(u16, "a `u16`.", U16Deserializer, visit_u16);
|
primitive_deserializer!(u16, "a `u16`.", U16Deserializer, visit_u16);
|
||||||
primitive_deserializer!(u64, "a `u64`.", U64Deserializer, visit_u64);
|
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!(usize, "a `usize`.", UsizeDeserializer, visit_u64 as u64);
|
||||||
primitive_deserializer!(f32, "an `f32`.", F32Deserializer, visit_f32);
|
primitive_deserializer!(f32, "an `f32`.", F32Deserializer, visit_f32);
|
||||||
primitive_deserializer!(f64, "an `f64`.", F64Deserializer, visit_f64);
|
primitive_deserializer!(f64, "an `f64`.", F64Deserializer, visit_f64);
|
||||||
primitive_deserializer!(char, "a `char`.", CharDeserializer, visit_char);
|
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`.
|
/// A deserializer holding a `u32`.
|
||||||
pub struct U32Deserializer<E> {
|
pub struct U32Deserializer<E> {
|
||||||
value: u32,
|
value: u32,
|
||||||
@@ -565,6 +565,7 @@ impl<'de, E> Debug for BorrowedStrDeserializer<'de, E> {
|
|||||||
|
|
||||||
/// A deserializer holding a `String`.
|
/// A deserializer holding a `String`.
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
pub struct StringDeserializer<E> {
|
pub struct StringDeserializer<E> {
|
||||||
value: String,
|
value: String,
|
||||||
marker: PhantomData<E>,
|
marker: PhantomData<E>,
|
||||||
@@ -581,6 +582,7 @@ impl<E> Clone for StringDeserializer<E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
impl<'de, E> IntoDeserializer<'de, E> for String
|
impl<'de, E> IntoDeserializer<'de, E> for String
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
@@ -668,6 +670,7 @@ impl<E> Debug for StringDeserializer<E> {
|
|||||||
|
|
||||||
/// A deserializer holding a `Cow<str>`.
|
/// A deserializer holding a `Cow<str>`.
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
pub struct CowStrDeserializer<'a, E> {
|
pub struct CowStrDeserializer<'a, E> {
|
||||||
value: Cow<'a, str>,
|
value: Cow<'a, str>,
|
||||||
marker: PhantomData<E>,
|
marker: PhantomData<E>,
|
||||||
@@ -684,6 +687,7 @@ impl<'a, E> Clone for CowStrDeserializer<'a, E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
impl<'de, 'a, E> IntoDeserializer<'de, E> for Cow<'a, str>
|
impl<'de, 'a, E> IntoDeserializer<'de, E> for Cow<'a, str>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
@@ -1002,6 +1006,7 @@ where
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
impl<'de, T, E> IntoDeserializer<'de, E> for Vec<T>
|
impl<'de, T, E> IntoDeserializer<'de, E> for Vec<T>
|
||||||
where
|
where
|
||||||
T: IntoDeserializer<'de, E>,
|
T: IntoDeserializer<'de, E>,
|
||||||
@@ -1015,6 +1020,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
impl<'de, T, E> IntoDeserializer<'de, E> for BTreeSet<T>
|
impl<'de, T, E> IntoDeserializer<'de, E> for BTreeSet<T>
|
||||||
where
|
where
|
||||||
T: IntoDeserializer<'de, E> + Eq + Ord,
|
T: IntoDeserializer<'de, E> + Eq + Ord,
|
||||||
@@ -1028,6 +1034,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
impl<'de, T, S, E> IntoDeserializer<'de, E> for HashSet<T, S>
|
impl<'de, T, S, E> IntoDeserializer<'de, E> for HashSet<T, S>
|
||||||
where
|
where
|
||||||
T: IntoDeserializer<'de, E> + Eq + Hash,
|
T: IntoDeserializer<'de, E> + Eq + Hash,
|
||||||
@@ -1414,6 +1421,7 @@ impl Expected for ExpectedInMap {
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
impl<'de, K, V, E> IntoDeserializer<'de, E> for BTreeMap<K, V>
|
impl<'de, K, V, E> IntoDeserializer<'de, E> for BTreeMap<K, V>
|
||||||
where
|
where
|
||||||
K: IntoDeserializer<'de, E> + Eq + Ord,
|
K: IntoDeserializer<'de, E> + Eq + Ord,
|
||||||
@@ -1428,6 +1436,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
impl<'de, K, V, S, E> IntoDeserializer<'de, E> for HashMap<K, V, S>
|
impl<'de, K, V, S, E> IntoDeserializer<'de, E> for HashMap<K, V, S>
|
||||||
where
|
where
|
||||||
K: IntoDeserializer<'de, E> + Eq + Hash,
|
K: IntoDeserializer<'de, E> + Eq + Hash,
|
||||||
|
|||||||
+3
-76
@@ -1,82 +1,9 @@
|
|||||||
/// Conditional compilation depending on whether Serde is built with support for
|
// No longer used. Old versions of serde used this macro for supporting targets
|
||||||
/// 128-bit integers.
|
// that did not yet have 128-bit integer support.
|
||||||
///
|
|
||||||
/// 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))]
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
#[doc(hidden)]
|
||||||
macro_rules! serde_if_integer128 {
|
macro_rules! serde_if_integer128 {
|
||||||
($($tt:tt)*) => {
|
($($tt:tt)*) => {
|
||||||
$($tt)*
|
$($tt)*
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(no_integer128)]
|
|
||||||
#[macro_export]
|
|
||||||
#[doc(hidden)]
|
|
||||||
macro_rules! serde_if_integer128 {
|
|
||||||
($($tt:tt)*) => {};
|
|
||||||
}
|
|
||||||
|
|||||||
+10
-2
@@ -63,6 +63,7 @@
|
|||||||
//! and from DynamoDB.
|
//! and from DynamoDB.
|
||||||
//! - [Hjson], a syntax extension to JSON designed around human reading and
|
//! - [Hjson], a syntax extension to JSON designed around human reading and
|
||||||
//! editing. *(deserialization only)*
|
//! editing. *(deserialization only)*
|
||||||
|
//! - [CSV], Comma-separated values is a tabular text file format.
|
||||||
//!
|
//!
|
||||||
//! [JSON]: https://github.com/serde-rs/json
|
//! [JSON]: https://github.com/serde-rs/json
|
||||||
//! [Postcard]: https://github.com/jamesmunns/postcard
|
//! [Postcard]: https://github.com/jamesmunns/postcard
|
||||||
@@ -89,13 +90,16 @@
|
|||||||
//! [DynamoDB Items]: https://docs.rs/serde_dynamo
|
//! [DynamoDB Items]: https://docs.rs/serde_dynamo
|
||||||
//! [rusoto_dynamodb]: https://docs.rs/rusoto_dynamodb
|
//! [rusoto_dynamodb]: https://docs.rs/rusoto_dynamodb
|
||||||
//! [Hjson]: https://github.com/Canop/deser-hjson
|
//! [Hjson]: https://github.com/Canop/deser-hjson
|
||||||
|
//! [CSV]: https://docs.rs/csv
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Serde types in rustdoc of other crates get linked to here.
|
// Serde types in rustdoc of other crates get linked to here.
|
||||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.183")]
|
#![doc(html_root_url = "https://docs.rs/serde/1.0.193")]
|
||||||
// Support using Serde without the standard library!
|
// Support using Serde without the standard library!
|
||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
// Show which crate feature enables conditionally compiled APIs in documentation.
|
||||||
|
#![cfg_attr(doc_cfg, feature(doc_cfg))]
|
||||||
// Unstable functionality only if the user asks for it. For tracking and
|
// Unstable functionality only if the user asks for it. For tracking and
|
||||||
// discussion of these features please refer to this issue:
|
// discussion of these features please refer to this issue:
|
||||||
//
|
//
|
||||||
@@ -166,11 +170,14 @@ mod lib {
|
|||||||
pub use std::*;
|
pub use std::*;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use self::core::{cmp, iter, mem, num, ptr, slice, str};
|
|
||||||
pub use self::core::{f32, f64};
|
pub use self::core::{f32, f64};
|
||||||
pub use self::core::{i16, i32, i64, i8, isize};
|
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};
|
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::cell::{Cell, RefCell};
|
||||||
pub use self::core::clone::{self, Clone};
|
pub use self::core::clone::{self, Clone};
|
||||||
pub use self::core::cmp::Reverse;
|
pub use self::core::cmp::Reverse;
|
||||||
@@ -319,6 +326,7 @@ extern crate serde_derive;
|
|||||||
|
|
||||||
/// Derive macro available if serde is built with `features = ["derive"]`.
|
/// Derive macro available if serde is built with `features = ["derive"]`.
|
||||||
#[cfg(feature = "serde_derive")]
|
#[cfg(feature = "serde_derive")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
|
||||||
pub use serde_derive::{Deserialize, Serialize};
|
pub use serde_derive::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))]
|
#[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))]
|
||||||
|
|||||||
+2
-6
@@ -154,9 +154,7 @@ macro_rules! forward_to_deserialize_any_helper {
|
|||||||
forward_to_deserialize_any_method!{deserialize_i64<$l, $v>()}
|
forward_to_deserialize_any_method!{deserialize_i64<$l, $v>()}
|
||||||
};
|
};
|
||||||
(i128<$l:tt, $v:ident>) => {
|
(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>) => {
|
(u8<$l:tt, $v:ident>) => {
|
||||||
forward_to_deserialize_any_method!{deserialize_u8<$l, $v>()}
|
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>()}
|
forward_to_deserialize_any_method!{deserialize_u64<$l, $v>()}
|
||||||
};
|
};
|
||||||
(u128<$l:tt, $v:ident>) => {
|
(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>) => {
|
(f32<$l:tt, $v:ident>) => {
|
||||||
forward_to_deserialize_any_method!{deserialize_f32<$l, $v>()}
|
forward_to_deserialize_any_method!{deserialize_f32<$l, $v>()}
|
||||||
|
|||||||
@@ -1370,3 +1370,16 @@ impl Serialize for AdjacentlyTaggedEnumVariant {
|
|||||||
serializer.serialize_unit_variant(self.enum_name, self.variant_index, self.variant_name)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -52,10 +52,12 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
|
|||||||
serialize_i16: i16,
|
serialize_i16: i16,
|
||||||
serialize_i32: i32,
|
serialize_i32: i32,
|
||||||
serialize_i64: i64,
|
serialize_i64: i64,
|
||||||
|
serialize_i128: i128,
|
||||||
serialize_u8: u8,
|
serialize_u8: u8,
|
||||||
serialize_u16: u16,
|
serialize_u16: u16,
|
||||||
serialize_u32: u32,
|
serialize_u32: u32,
|
||||||
serialize_u64: u64,
|
serialize_u64: u64,
|
||||||
|
serialize_u128: u128,
|
||||||
serialize_f32: f32,
|
serialize_f32: f32,
|
||||||
serialize_f64: f64,
|
serialize_f64: f64,
|
||||||
serialize_char: char,
|
serialize_char: char,
|
||||||
@@ -63,13 +65,6 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
|
|||||||
serialize_unit_struct: &'static str,
|
serialize_unit_struct: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
serde_if_integer128! {
|
|
||||||
fmt_primitives! {
|
|
||||||
serialize_i128: i128,
|
|
||||||
serialize_u128: u128,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_unit_variant(
|
fn serialize_unit_variant(
|
||||||
self,
|
self,
|
||||||
_name: &'static str,
|
_name: &'static str,
|
||||||
|
|||||||
+117
-52
@@ -24,20 +24,17 @@ primitive_impl!(i8, serialize_i8);
|
|||||||
primitive_impl!(i16, serialize_i16);
|
primitive_impl!(i16, serialize_i16);
|
||||||
primitive_impl!(i32, serialize_i32);
|
primitive_impl!(i32, serialize_i32);
|
||||||
primitive_impl!(i64, serialize_i64);
|
primitive_impl!(i64, serialize_i64);
|
||||||
|
primitive_impl!(i128, serialize_i128);
|
||||||
primitive_impl!(usize, serialize_u64 as u64);
|
primitive_impl!(usize, serialize_u64 as u64);
|
||||||
primitive_impl!(u8, serialize_u8);
|
primitive_impl!(u8, serialize_u8);
|
||||||
primitive_impl!(u16, serialize_u16);
|
primitive_impl!(u16, serialize_u16);
|
||||||
primitive_impl!(u32, serialize_u32);
|
primitive_impl!(u32, serialize_u32);
|
||||||
primitive_impl!(u64, serialize_u64);
|
primitive_impl!(u64, serialize_u64);
|
||||||
|
primitive_impl!(u128, serialize_u128);
|
||||||
primitive_impl!(f32, serialize_f32);
|
primitive_impl!(f32, serialize_f32);
|
||||||
primitive_impl!(f64, serialize_f64);
|
primitive_impl!(f64, serialize_f64);
|
||||||
primitive_impl!(char, serialize_char);
|
primitive_impl!(char, serialize_char);
|
||||||
|
|
||||||
serde_if_integer128! {
|
|
||||||
primitive_impl!(i128, serialize_i128);
|
|
||||||
primitive_impl!(u128, serialize_u128);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
impl Serialize for str {
|
impl Serialize for str {
|
||||||
@@ -51,6 +48,7 @@ impl Serialize for str {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
impl Serialize for String {
|
impl Serialize for String {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
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(any(feature = "std", not(no_core_cstr)))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
impl Serialize for CStr {
|
impl Serialize for CStr {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
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(any(feature = "std", all(not(no_core_cstr), feature = "alloc")))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
impl Serialize for CString {
|
impl Serialize for CString {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
@@ -182,9 +182,13 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(any(feature = "std", feature = "alloc"), not(no_relaxed_trait_bounds)))]
|
#[cfg(not(no_relaxed_trait_bounds))]
|
||||||
macro_rules! seq_impl {
|
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)*>
|
impl<T $(, $typaram)*> Serialize for $ty<T $(, $typaram)*>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: Serialize,
|
||||||
@@ -200,9 +204,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 {
|
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)*>
|
impl<T $(, $typaram)*> Serialize for $ty<T $(, $typaram)*>
|
||||||
where
|
where
|
||||||
T: Serialize $(+ $tbound1 $(+ $tbound2)*)*,
|
T: Serialize $(+ $tbound1 $(+ $tbound2)*)*,
|
||||||
@@ -219,23 +227,41 @@ macro_rules! seq_impl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
seq_impl! {
|
||||||
seq_impl!(BinaryHeap<T: Ord>);
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
|
BinaryHeap<T: Ord>
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
seq_impl! {
|
||||||
seq_impl!(BTreeSet<T: Ord>);
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
|
BTreeSet<T: Ord>
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
seq_impl! {
|
||||||
seq_impl!(HashSet<T: Eq + Hash, H: BuildHasher>);
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
|
HashSet<T: Eq + Hash, H: BuildHasher>
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
seq_impl! {
|
||||||
seq_impl!(LinkedList<T>);
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
|
LinkedList<T>
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
seq_impl! {
|
||||||
seq_impl!(Vec<T>);
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
|
Vec<T>
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
seq_impl! {
|
||||||
seq_impl!(VecDeque<T>);
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
|
VecDeque<T>
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -342,6 +368,7 @@ impl Serialize for () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "unstable")]
|
#[cfg(feature = "unstable")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "unstable")))]
|
||||||
impl Serialize for ! {
|
impl Serialize for ! {
|
||||||
fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -397,9 +424,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 {
|
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)*>
|
impl<K, V $(, $typaram)*> Serialize for $ty<K, V $(, $typaram)*>
|
||||||
where
|
where
|
||||||
K: Serialize,
|
K: Serialize,
|
||||||
@@ -416,9 +447,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 {
|
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)*>
|
impl<K, V $(, $typaram)*> Serialize for $ty<K, V $(, $typaram)*>
|
||||||
where
|
where
|
||||||
K: Serialize $(+ $kbound1 $(+ $kbound2)*)*,
|
K: Serialize $(+ $kbound1 $(+ $kbound2)*)*,
|
||||||
@@ -436,20 +471,26 @@ macro_rules! map_impl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
map_impl! {
|
||||||
map_impl!(BTreeMap<K: Ord, V>);
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
|
BTreeMap<K: Ord, V>
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
map_impl! {
|
||||||
map_impl!(HashMap<K: Eq + Hash, V, H: BuildHasher>);
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
|
HashMap<K: Eq + Hash, V, H: BuildHasher>
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
macro_rules! deref_impl {
|
macro_rules! deref_impl {
|
||||||
(
|
(
|
||||||
$(#[doc = $doc:tt])*
|
$(#[$attr:meta])*
|
||||||
<$($desc:tt)+
|
<$($desc:tt)+
|
||||||
) => {
|
) => {
|
||||||
$(#[doc = $doc])*
|
$(#[$attr])*
|
||||||
impl <$($desc)+ {
|
impl <$($desc)+ {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
@@ -462,13 +503,20 @@ macro_rules! deref_impl {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
deref_impl!(<'a, T: ?Sized> Serialize for &'a T where T: Serialize);
|
deref_impl! {
|
||||||
deref_impl!(<'a, T: ?Sized> Serialize for &'a mut T where T: Serialize);
|
<'a, T: ?Sized> Serialize for &'a T where T: Serialize
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
deref_impl! {
|
||||||
deref_impl!(<T: ?Sized> Serialize for Box<T> where T: Serialize);
|
<'a, T: ?Sized> Serialize for &'a mut T where T: Serialize
|
||||||
|
}
|
||||||
|
|
||||||
|
deref_impl! {
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
|
<T: ?Sized> Serialize for Box<T> where T: Serialize
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
|
||||||
deref_impl! {
|
deref_impl! {
|
||||||
/// This impl requires the [`"rc"`] Cargo feature of Serde.
|
/// This impl requires the [`"rc"`] Cargo feature of Serde.
|
||||||
///
|
///
|
||||||
@@ -478,10 +526,11 @@ deref_impl! {
|
|||||||
/// repeated data.
|
/// repeated data.
|
||||||
///
|
///
|
||||||
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
||||||
|
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))]
|
||||||
<T: ?Sized> Serialize for Rc<T> where T: Serialize
|
<T: ?Sized> Serialize for Rc<T> where T: Serialize
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
|
||||||
deref_impl! {
|
deref_impl! {
|
||||||
/// This impl requires the [`"rc"`] Cargo feature of Serde.
|
/// This impl requires the [`"rc"`] Cargo feature of Serde.
|
||||||
///
|
///
|
||||||
@@ -491,11 +540,16 @@ deref_impl! {
|
|||||||
/// repeated data.
|
/// repeated data.
|
||||||
///
|
///
|
||||||
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
||||||
|
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))]
|
||||||
<T: ?Sized> Serialize for Arc<T> where T: Serialize
|
<T: ?Sized> Serialize for Arc<T> where T: Serialize
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
deref_impl! {
|
||||||
deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned);
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))]
|
||||||
|
<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -503,6 +557,10 @@ deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwne
|
|||||||
///
|
///
|
||||||
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
||||||
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||||
|
#[cfg_attr(
|
||||||
|
doc_cfg,
|
||||||
|
doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc"))))
|
||||||
|
)]
|
||||||
impl<T: ?Sized> Serialize for RcWeak<T>
|
impl<T: ?Sized> Serialize for RcWeak<T>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: Serialize,
|
||||||
@@ -519,6 +577,10 @@ where
|
|||||||
///
|
///
|
||||||
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
||||||
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||||
|
#[cfg_attr(
|
||||||
|
doc_cfg,
|
||||||
|
doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc"))))
|
||||||
|
)]
|
||||||
impl<T: ?Sized> Serialize for ArcWeak<T>
|
impl<T: ?Sized> Serialize for ArcWeak<T>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: Serialize,
|
||||||
@@ -553,6 +615,7 @@ nonzero_integers! {
|
|||||||
NonZeroU16,
|
NonZeroU16,
|
||||||
NonZeroU32,
|
NonZeroU32,
|
||||||
NonZeroU64,
|
NonZeroU64,
|
||||||
|
NonZeroU128,
|
||||||
NonZeroUsize,
|
NonZeroUsize,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -562,22 +625,10 @@ nonzero_integers! {
|
|||||||
NonZeroI16,
|
NonZeroI16,
|
||||||
NonZeroI32,
|
NonZeroI32,
|
||||||
NonZeroI64,
|
NonZeroI64,
|
||||||
|
NonZeroI128,
|
||||||
NonZeroIsize,
|
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>
|
impl<T> Serialize for Cell<T>
|
||||||
where
|
where
|
||||||
T: Serialize + Copy,
|
T: Serialize + Copy,
|
||||||
@@ -606,6 +657,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
impl<T: ?Sized> Serialize for Mutex<T>
|
impl<T: ?Sized> Serialize for Mutex<T>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: Serialize,
|
||||||
@@ -622,6 +674,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
impl<T: ?Sized> Serialize for RwLock<T>
|
impl<T: ?Sized> Serialize for RwLock<T>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: Serialize,
|
||||||
@@ -675,6 +728,7 @@ impl Serialize for Duration {
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
impl Serialize for SystemTime {
|
impl Serialize for SystemTime {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -719,6 +773,7 @@ macro_rules! serialize_display_bounded_length {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
impl Serialize for net::IpAddr {
|
impl Serialize for net::IpAddr {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -789,6 +844,7 @@ fn test_format_u8() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
impl Serialize for net::Ipv4Addr {
|
impl Serialize for net::Ipv4Addr {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -813,6 +869,7 @@ impl Serialize for net::Ipv4Addr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
impl Serialize for net::Ipv6Addr {
|
impl Serialize for net::Ipv6Addr {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -829,6 +886,7 @@ impl Serialize for net::Ipv6Addr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
impl Serialize for net::SocketAddr {
|
impl Serialize for net::SocketAddr {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -853,6 +911,7 @@ impl Serialize for net::SocketAddr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
impl Serialize for net::SocketAddrV4 {
|
impl Serialize for net::SocketAddrV4 {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -869,6 +928,7 @@ impl Serialize for net::SocketAddrV4 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
impl Serialize for net::SocketAddrV6 {
|
impl Serialize for net::SocketAddrV6 {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -890,6 +950,7 @@ impl Serialize for net::SocketAddrV6 {
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
impl Serialize for Path {
|
impl Serialize for Path {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -903,6 +964,7 @@ impl Serialize for Path {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
||||||
impl Serialize for PathBuf {
|
impl Serialize for PathBuf {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -913,6 +975,7 @@ impl Serialize for PathBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "std", any(unix, windows)))]
|
#[cfg(all(feature = "std", any(unix, windows)))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", any(unix, windows)))))]
|
||||||
impl Serialize for OsStr {
|
impl Serialize for OsStr {
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
@@ -935,6 +998,7 @@ impl Serialize for OsStr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "std", any(unix, windows)))]
|
#[cfg(all(feature = "std", any(unix, windows)))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", any(unix, windows)))))]
|
||||||
impl Serialize for OsString {
|
impl Serialize for OsString {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -979,6 +1043,7 @@ macro_rules! atomic_impl {
|
|||||||
($($ty:ident $size:expr)*) => {
|
($($ty:ident $size:expr)*) => {
|
||||||
$(
|
$(
|
||||||
#[cfg(any(no_target_has_atomic, target_has_atomic = $size))]
|
#[cfg(any(no_target_has_atomic, target_has_atomic = $size))]
|
||||||
|
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", target_has_atomic = $size))))]
|
||||||
impl Serialize for $ty {
|
impl Serialize for $ty {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
|
|||||||
+42
-48
@@ -488,30 +488,27 @@ pub trait Serializer: Sized {
|
|||||||
/// ```
|
/// ```
|
||||||
fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error>;
|
fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error>;
|
||||||
|
|
||||||
serde_if_integer128! {
|
/// Serialize an `i128` value.
|
||||||
/// Serialize an `i128` value.
|
///
|
||||||
///
|
/// ```edition2021
|
||||||
/// ```edition2021
|
/// # use serde::Serializer;
|
||||||
/// # use serde::Serializer;
|
/// #
|
||||||
/// #
|
/// # serde::__private_serialize!();
|
||||||
/// # serde::__private_serialize!();
|
/// #
|
||||||
/// #
|
/// impl Serialize for i128 {
|
||||||
/// impl Serialize for i128 {
|
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
/// where
|
||||||
/// where
|
/// S: Serializer,
|
||||||
/// S: Serializer,
|
/// {
|
||||||
/// {
|
/// serializer.serialize_i128(*self)
|
||||||
/// serializer.serialize_i128(*self)
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// ```
|
||||||
/// ```
|
///
|
||||||
///
|
/// The default behavior unconditionally returns an error.
|
||||||
/// This method is available only on Rust compiler versions >=1.26. The
|
fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> {
|
||||||
/// default behavior unconditionally returns an error.
|
let _ = v;
|
||||||
fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> {
|
Err(Error::custom("i128 is not supported"))
|
||||||
let _ = v;
|
|
||||||
Err(Error::custom("i128 is not supported"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serialize a `u8` value.
|
/// Serialize a `u8` value.
|
||||||
@@ -598,30 +595,27 @@ pub trait Serializer: Sized {
|
|||||||
/// ```
|
/// ```
|
||||||
fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error>;
|
fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error>;
|
||||||
|
|
||||||
serde_if_integer128! {
|
/// Serialize a `u128` value.
|
||||||
/// Serialize a `u128` value.
|
///
|
||||||
///
|
/// ```edition2021
|
||||||
/// ```edition2021
|
/// # use serde::Serializer;
|
||||||
/// # use serde::Serializer;
|
/// #
|
||||||
/// #
|
/// # serde::__private_serialize!();
|
||||||
/// # serde::__private_serialize!();
|
/// #
|
||||||
/// #
|
/// impl Serialize for u128 {
|
||||||
/// impl Serialize for u128 {
|
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
/// where
|
||||||
/// where
|
/// S: Serializer,
|
||||||
/// S: Serializer,
|
/// {
|
||||||
/// {
|
/// serializer.serialize_u128(*self)
|
||||||
/// serializer.serialize_u128(*self)
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// ```
|
||||||
/// ```
|
///
|
||||||
///
|
/// The default behavior unconditionally returns an error.
|
||||||
/// This method is available only on Rust compiler versions >=1.26. The
|
fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
|
||||||
/// default behavior unconditionally returns an error.
|
let _ = v;
|
||||||
fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
|
Err(Error::custom("u128 is not supported"))
|
||||||
let _ = v;
|
|
||||||
Err(Error::custom("u128 is not supported"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serialize an `f32` value.
|
/// Serialize an `f32` value.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.183" # remember to update html_root_url
|
version = "1.0.193"
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||||
categories = ["no-std", "no-std::no-alloc"]
|
categories = ["no-std", "no-std::no-alloc"]
|
||||||
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
||||||
|
|||||||
+15
-10
@@ -6,8 +6,6 @@ use proc_macro2::{Literal, Span, TokenStream};
|
|||||||
use quote::{quote, quote_spanned, ToTokens};
|
use quote::{quote, quote_spanned, ToTokens};
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
#[cfg(precompiled)]
|
|
||||||
use std::sync::atomic::Ordering;
|
|
||||||
use syn::punctuated::Punctuated;
|
use syn::punctuated::Punctuated;
|
||||||
use syn::spanned::Spanned;
|
use syn::spanned::Spanned;
|
||||||
use syn::{parse_quote, Ident, Index, Member};
|
use syn::{parse_quote, Ident, Index, Member};
|
||||||
@@ -301,11 +299,6 @@ fn deserialize_body(cont: &Container, params: &Parameters) -> Fragment {
|
|||||||
|
|
||||||
#[cfg(feature = "deserialize_in_place")]
|
#[cfg(feature = "deserialize_in_place")]
|
||||||
fn deserialize_in_place_body(cont: &Container, params: &Parameters) -> Option<Stmts> {
|
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
|
// Only remote derives have getters, and we do not generate
|
||||||
// deserialize_in_place for remote derives.
|
// deserialize_in_place for remote derives.
|
||||||
assert!(!params.has_getter);
|
assert!(!params.has_getter);
|
||||||
@@ -1744,7 +1737,6 @@ fn deserialize_untagged_enum_after(
|
|||||||
quote!(__deserializer),
|
quote!(__deserializer),
|
||||||
))
|
))
|
||||||
});
|
});
|
||||||
let attempts = first_attempt.into_iter().chain(attempts);
|
|
||||||
// TODO this message could be better by saving the errors from the failed
|
// 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
|
// 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
|
// processed before an error, and use the error that happened after the
|
||||||
@@ -1757,10 +1749,23 @@ fn deserialize_untagged_enum_after(
|
|||||||
);
|
);
|
||||||
let fallthrough_msg = cattrs.expecting().unwrap_or(&fallthrough_msg);
|
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! {
|
quote_block! {
|
||||||
let __content = <_serde::__private::de::Content as _serde::Deserialize>::deserialize(__deserializer)?;
|
let __content = <_serde::__private::de::Content as _serde::Deserialize>::deserialize(__deserializer)?;
|
||||||
let __deserializer = _serde::__private::de::ContentRefDeserializer::<__D::Error>::new(&__content);
|
let __deserializer = _serde::__private::de::ContentRefDeserializer::<__D::Error>::new(&__content);
|
||||||
|
|
||||||
|
#first_attempt
|
||||||
|
|
||||||
#(
|
#(
|
||||||
if let _serde::__private::Ok(__ok) = #attempts {
|
if let _serde::__private::Ok(__ok) = #attempts {
|
||||||
return _serde::__private::Ok(__ok);
|
return _serde::__private::Ok(__ok);
|
||||||
@@ -1835,7 +1840,7 @@ fn deserialize_internally_tagged_variant(
|
|||||||
let this_value = ¶ms.this_value;
|
let this_value = ¶ms.this_value;
|
||||||
let type_name = params.type_name();
|
let type_name = params.type_name();
|
||||||
let variant_name = variant.ident.to_string();
|
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));
|
let default = Expr(expr_is_missing(field, cattrs));
|
||||||
quote!((#default))
|
quote!((#default))
|
||||||
});
|
});
|
||||||
@@ -1880,7 +1885,7 @@ fn deserialize_untagged_variant(
|
|||||||
let this_value = ¶ms.this_value;
|
let this_value = ¶ms.this_value;
|
||||||
let type_name = params.type_name();
|
let type_name = params.type_name();
|
||||||
let variant_name = variant.ident.to_string();
|
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));
|
let default = Expr(expr_is_missing(field, cattrs));
|
||||||
quote!((#default))
|
quote!((#default))
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -221,6 +221,7 @@ pub struct Container {
|
|||||||
is_packed: bool,
|
is_packed: bool,
|
||||||
/// Error message generated when type can't be deserialized
|
/// Error message generated when type can't be deserialized
|
||||||
expecting: Option<String>,
|
expecting: Option<String>,
|
||||||
|
non_exhaustive: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Styles of representing an enum.
|
/// Styles of representing an enum.
|
||||||
@@ -306,9 +307,12 @@ impl Container {
|
|||||||
let mut variant_identifier = BoolAttr::none(cx, VARIANT_IDENTIFIER);
|
let mut variant_identifier = BoolAttr::none(cx, VARIANT_IDENTIFIER);
|
||||||
let mut serde_path = Attr::none(cx, CRATE);
|
let mut serde_path = Attr::none(cx, CRATE);
|
||||||
let mut expecting = Attr::none(cx, EXPECTING);
|
let mut expecting = Attr::none(cx, EXPECTING);
|
||||||
|
let mut non_exhaustive = false;
|
||||||
|
|
||||||
for attr in &item.attrs {
|
for attr in &item.attrs {
|
||||||
if attr.path() != SERDE {
|
if attr.path() != SERDE {
|
||||||
|
non_exhaustive |=
|
||||||
|
matches!(&attr.meta, syn::Meta::Path(path) if path == NON_EXHAUSTIVE);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -587,6 +591,7 @@ impl Container {
|
|||||||
serde_path: serde_path.get(),
|
serde_path: serde_path.get(),
|
||||||
is_packed,
|
is_packed,
|
||||||
expecting: expecting.get(),
|
expecting: expecting.get(),
|
||||||
|
non_exhaustive,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -672,6 +677,10 @@ impl Container {
|
|||||||
pub fn expecting(&self) -> Option<&str> {
|
pub fn expecting(&self) -> Option<&str> {
|
||||||
self.expecting.as_ref().map(String::as_ref)
|
self.expecting.as_ref().map(String::as_ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn non_exhaustive(&self) -> bool {
|
||||||
|
self.non_exhaustive
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decide_tag(
|
fn decide_tag(
|
||||||
@@ -707,7 +716,7 @@ fn decide_tag(
|
|||||||
}
|
}
|
||||||
TagType::Internal { 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";
|
let msg = "enum cannot be both untagged and internally tagged";
|
||||||
cx.error_spanned_by(untagged_tokens, msg);
|
cx.error_spanned_by(untagged_tokens, msg);
|
||||||
cx.error_spanned_by(tag_tokens, msg);
|
cx.error_spanned_by(tag_tokens, msg);
|
||||||
@@ -718,14 +727,14 @@ fn decide_tag(
|
|||||||
cx.error_spanned_by(content_tokens, msg);
|
cx.error_spanned_by(content_tokens, msg);
|
||||||
TagType::External
|
TagType::External
|
||||||
}
|
}
|
||||||
(Some((untagged_tokens, _)), None, Some((content_tokens, _))) => {
|
(Some((untagged_tokens, ())), None, Some((content_tokens, _))) => {
|
||||||
let msg = "untagged enum cannot have #[serde(content = \"...\")]";
|
let msg = "untagged enum cannot have #[serde(content = \"...\")]";
|
||||||
cx.error_spanned_by(untagged_tokens, msg);
|
cx.error_spanned_by(untagged_tokens, msg);
|
||||||
cx.error_spanned_by(content_tokens, msg);
|
cx.error_spanned_by(content_tokens, msg);
|
||||||
TagType::External
|
TagType::External
|
||||||
}
|
}
|
||||||
(None, Some((_, tag)), Some((_, content))) => TagType::Adjacent { tag, content },
|
(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 = \"...\")]";
|
let msg = "untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]";
|
||||||
cx.error_spanned_by(untagged_tokens, msg);
|
cx.error_spanned_by(untagged_tokens, msg);
|
||||||
cx.error_spanned_by(tag_tokens, msg);
|
cx.error_spanned_by(tag_tokens, msg);
|
||||||
@@ -747,7 +756,7 @@ fn decide_identifier(
|
|||||||
variant_identifier.0.get_with_tokens(),
|
variant_identifier.0.get_with_tokens(),
|
||||||
) {
|
) {
|
||||||
(_, None, None) => Identifier::No,
|
(_, None, None) => Identifier::No,
|
||||||
(_, Some((field_identifier_tokens, _)), Some((variant_identifier_tokens, _))) => {
|
(_, Some((field_identifier_tokens, ())), Some((variant_identifier_tokens, ()))) => {
|
||||||
let msg =
|
let msg =
|
||||||
"#[serde(field_identifier)] and #[serde(variant_identifier)] cannot both be set";
|
"#[serde(field_identifier)] and #[serde(variant_identifier)] cannot both be set";
|
||||||
cx.error_spanned_by(field_identifier_tokens, msg);
|
cx.error_spanned_by(field_identifier_tokens, msg);
|
||||||
|
|||||||
@@ -318,6 +318,9 @@ fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) {
|
|||||||
for variant in variants {
|
for variant in variants {
|
||||||
match variant.style {
|
match variant.style {
|
||||||
Style::Struct => {
|
Style::Struct => {
|
||||||
|
if variant.attrs.untagged() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
for field in &variant.fields {
|
for field in &variant.fields {
|
||||||
let check_ser =
|
let check_ser =
|
||||||
!(field.attrs.skip_serializing() || variant.attrs.skip_serializing());
|
!(field.attrs.skip_serializing() || variant.attrs.skip_serializing());
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ pub const FLATTEN: Symbol = Symbol("flatten");
|
|||||||
pub const FROM: Symbol = Symbol("from");
|
pub const FROM: Symbol = Symbol("from");
|
||||||
pub const GETTER: Symbol = Symbol("getter");
|
pub const GETTER: Symbol = Symbol("getter");
|
||||||
pub const INTO: Symbol = Symbol("into");
|
pub const INTO: Symbol = Symbol("into");
|
||||||
|
pub const NON_EXHAUSTIVE: Symbol = Symbol("non_exhaustive");
|
||||||
pub const OTHER: Symbol = Symbol("other");
|
pub const OTHER: Symbol = Symbol("other");
|
||||||
pub const REMOTE: Symbol = Symbol("remote");
|
pub const REMOTE: Symbol = Symbol("remote");
|
||||||
pub const RENAME: Symbol = Symbol("rename");
|
pub const RENAME: Symbol = Symbol("rename");
|
||||||
|
|||||||
+3
-22
@@ -13,7 +13,7 @@
|
|||||||
//!
|
//!
|
||||||
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
|
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
|
||||||
|
|
||||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.183")]
|
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.193")]
|
||||||
// Ignored clippy lints
|
// Ignored clippy lints
|
||||||
#![allow(
|
#![allow(
|
||||||
// clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054
|
// clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054
|
||||||
@@ -66,17 +66,11 @@ extern crate proc_macro2;
|
|||||||
extern crate quote;
|
extern crate quote;
|
||||||
extern crate syn;
|
extern crate syn;
|
||||||
|
|
||||||
#[cfg(not(precompiled))]
|
|
||||||
extern crate proc_macro;
|
extern crate proc_macro;
|
||||||
#[cfg(precompiled)]
|
|
||||||
extern crate proc_macro2 as proc_macro;
|
|
||||||
|
|
||||||
mod internals;
|
mod internals;
|
||||||
|
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
#[cfg(precompiled)]
|
|
||||||
use std::sync::atomic::AtomicBool;
|
|
||||||
#[cfg(not(precompiled))]
|
|
||||||
use syn::parse_macro_input;
|
use syn::parse_macro_input;
|
||||||
use syn::DeriveInput;
|
use syn::DeriveInput;
|
||||||
|
|
||||||
@@ -91,20 +85,7 @@ mod pretend;
|
|||||||
mod ser;
|
mod ser;
|
||||||
mod this;
|
mod this;
|
||||||
|
|
||||||
#[cfg(precompiled)]
|
#[proc_macro_derive(Serialize, attributes(serde))]
|
||||||
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)))]
|
|
||||||
pub fn derive_serialize(input: TokenStream) -> TokenStream {
|
pub fn derive_serialize(input: TokenStream) -> TokenStream {
|
||||||
let mut input = parse_macro_input!(input as DeriveInput);
|
let mut input = parse_macro_input!(input as DeriveInput);
|
||||||
ser::expand_derive_serialize(&mut input)
|
ser::expand_derive_serialize(&mut input)
|
||||||
@@ -112,7 +93,7 @@ pub fn derive_serialize(input: TokenStream) -> TokenStream {
|
|||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(not(precompiled), proc_macro_derive(Deserialize, attributes(serde)))]
|
#[proc_macro_derive(Deserialize, attributes(serde))]
|
||||||
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
|
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
|
||||||
let mut input = parse_macro_input!(input as DeriveInput);
|
let mut input = parse_macro_input!(input as DeriveInput);
|
||||||
de::expand_derive_deserialize(&mut input)
|
de::expand_derive_deserialize(&mut input)
|
||||||
|
|||||||
@@ -401,7 +401,7 @@ fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Cont
|
|||||||
|
|
||||||
let self_var = ¶ms.self_var;
|
let self_var = ¶ms.self_var;
|
||||||
|
|
||||||
let arms: Vec<_> = variants
|
let mut arms: Vec<_> = variants
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(variant_index, variant)| {
|
.map(|(variant_index, variant)| {
|
||||||
@@ -409,6 +409,12 @@ fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Cont
|
|||||||
})
|
})
|
||||||
.collect();
|
.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! {
|
quote_expr! {
|
||||||
match *#self_var {
|
match *#self_var {
|
||||||
#(#arms)*
|
#(#arms)*
|
||||||
@@ -704,7 +710,7 @@ fn serialize_adjacently_tagged_variant(
|
|||||||
});
|
});
|
||||||
|
|
||||||
let fields_ty = variant.fields.iter().map(|f| &f.ty);
|
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 => {
|
Style::Unit => {
|
||||||
if variant.attrs.serialize_with().is_some() {
|
if variant.attrs.serialize_with().is_some() {
|
||||||
vec![]
|
vec![]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde_derive_internals"
|
name = "serde_derive_internals"
|
||||||
version = "0.28.0" # remember to update html_root_url
|
version = "0.29.0"
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||||
description = "AST representation used by Serde derive macros. Unstable."
|
description = "AST representation used by Serde derive macros. Unstable."
|
||||||
documentation = "https://docs.rs/serde_derive_internals"
|
documentation = "https://docs.rs/serde_derive_internals"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#![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.0")]
|
||||||
// Ignored clippy lints
|
// Ignored clippy lints
|
||||||
#![allow(
|
#![allow(
|
||||||
clippy::cognitive_complexity,
|
clippy::cognitive_complexity,
|
||||||
|
|||||||
@@ -2380,6 +2380,68 @@ fn test_partially_untagged_enum_desugared() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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]
|
#[test]
|
||||||
fn test_flatten_option() {
|
fn test_flatten_option() {
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||||
@@ -2719,7 +2781,7 @@ fn test_expecting_message_externally_tagged_enum() {
|
|||||||
// Check that #[serde(expecting = "...")] doesn't affect variant identifier error message
|
// Check that #[serde(expecting = "...")] doesn't affect variant identifier error message
|
||||||
assert_de_tokens_error::<Enum>(
|
assert_de_tokens_error::<Enum>(
|
||||||
&[Token::Enum { name: "Enum" }, Token::Unit],
|
&[Token::Enum { name: "Enum" }, Token::Unit],
|
||||||
r#"invalid type: unit value, expected variant identifier"#,
|
"invalid type: unit value, expected variant identifier",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2740,7 +2802,7 @@ fn test_expecting_message_internally_tagged_enum() {
|
|||||||
// Check that #[serde(expecting = "...")] doesn't affect variant identifier error message
|
// Check that #[serde(expecting = "...")] doesn't affect variant identifier error message
|
||||||
assert_de_tokens_error::<Enum>(
|
assert_de_tokens_error::<Enum>(
|
||||||
&[Token::Map { len: None }, Token::Str("tag"), Token::Unit],
|
&[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 +2828,7 @@ fn test_expecting_message_adjacently_tagged_enum() {
|
|||||||
// Check that #[serde(expecting = "...")] doesn't affect variant identifier error message
|
// Check that #[serde(expecting = "...")] doesn't affect variant identifier error message
|
||||||
assert_de_tokens_error::<Enum>(
|
assert_de_tokens_error::<Enum>(
|
||||||
&[Token::Map { len: None }, Token::Str("tag"), Token::Unit],
|
&[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 +2841,7 @@ fn test_expecting_message_untagged_tagged_enum() {
|
|||||||
Untagged,
|
Untagged,
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_de_tokens_error::<Enum>(&[Token::Str("Untagged")], r#"something strange..."#);
|
assert_de_tokens_error::<Enum>(&[Token::Str("Untagged")], "something strange...");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -2800,7 +2862,7 @@ fn test_expecting_message_identifier_enum() {
|
|||||||
|
|
||||||
assert_de_tokens_error::<FieldEnum>(
|
assert_de_tokens_error::<FieldEnum>(
|
||||||
&[Token::Unit],
|
&[Token::Unit],
|
||||||
r#"invalid type: unit value, expected something strange..."#,
|
"invalid type: unit value, expected something strange...",
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_de_tokens_error::<FieldEnum>(
|
assert_de_tokens_error::<FieldEnum>(
|
||||||
@@ -2809,12 +2871,12 @@ fn test_expecting_message_identifier_enum() {
|
|||||||
Token::Str("Unknown"),
|
Token::Str("Unknown"),
|
||||||
Token::None,
|
Token::None,
|
||||||
],
|
],
|
||||||
r#"invalid type: map, expected something strange..."#,
|
"invalid type: map, expected something strange...",
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_de_tokens_error::<VariantEnum>(
|
assert_de_tokens_error::<VariantEnum>(
|
||||||
&[Token::Unit],
|
&[Token::Unit],
|
||||||
r#"invalid type: unit value, expected something strange..."#,
|
"invalid type: unit value, expected something strange...",
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_de_tokens_error::<VariantEnum>(
|
assert_de_tokens_error::<VariantEnum>(
|
||||||
@@ -2825,7 +2887,7 @@ fn test_expecting_message_identifier_enum() {
|
|||||||
Token::Str("Unknown"),
|
Token::Str("Unknown"),
|
||||||
Token::None,
|
Token::None,
|
||||||
],
|
],
|
||||||
r#"invalid type: map, expected something strange..."#,
|
"invalid type: map, expected something strange...",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#![cfg_attr(feature = "unstable", feature(never_type))]
|
#![cfg_attr(feature = "unstable", feature(never_type))]
|
||||||
|
|
||||||
use fnv::FnvHasher;
|
use fnv::FnvHasher;
|
||||||
|
use serde::de::value::{F32Deserializer, F64Deserializer};
|
||||||
use serde::de::{Deserialize, DeserializeOwned, Deserializer, IntoDeserializer};
|
use serde::de::{Deserialize, DeserializeOwned, Deserializer, IntoDeserializer};
|
||||||
use serde_derive::Deserialize;
|
use serde_derive::Deserialize;
|
||||||
use serde_test::{assert_de_tokens, Configure, Token};
|
use serde_test::{assert_de_tokens, Configure, Token};
|
||||||
@@ -832,6 +833,26 @@ fn test_f64() {
|
|||||||
test(1.11, &[Token::F64(1.11)]);
|
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]
|
#[test]
|
||||||
fn test_char() {
|
fn test_char() {
|
||||||
test('a', &[Token::Char('a')]);
|
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]
|
#[test]
|
||||||
fn test_bound() {
|
fn test_bound() {
|
||||||
test(
|
test(
|
||||||
|
|||||||
@@ -843,7 +843,7 @@ pub fn is_zero(n: &u8) -> bool {
|
|||||||
*n == 0
|
*n == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn vec_first_element<T, S>(vec: &Vec<T>, serializer: S) -> StdResult<S::Ok, S::Error>
|
fn vec_first_element<T, S>(vec: &[T], serializer: S) -> StdResult<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: Serialize,
|
||||||
S: Serializer,
|
S: Serializer,
|
||||||
|
|||||||
@@ -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]
|
#[test]
|
||||||
fn test_internally_tagged_bytes() {
|
fn test_internally_tagged_bytes() {
|
||||||
#[derive(Debug, PartialEq, Deserialize)]
|
#[derive(Debug, PartialEq, Deserialize)]
|
||||||
|
|||||||
@@ -125,6 +125,9 @@ struct Test {
|
|||||||
|
|
||||||
#[serde(with = "EnumConcrete")]
|
#[serde(with = "EnumConcrete")]
|
||||||
enum_concrete: remote::EnumGeneric<u8>,
|
enum_concrete: remote::EnumGeneric<u8>,
|
||||||
|
|
||||||
|
#[serde(with = "ErrorKindDef")]
|
||||||
|
io_error_kind: ErrorKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
@@ -197,6 +200,23 @@ enum EnumConcrete {
|
|||||||
Variant(u8),
|
Variant(u8),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum ErrorKind {
|
||||||
|
NotFound,
|
||||||
|
PermissionDenied,
|
||||||
|
#[allow(dead_code)]
|
||||||
|
ConnectionRefused,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
#[serde(remote = "ErrorKind")]
|
||||||
|
#[non_exhaustive]
|
||||||
|
enum ErrorKindDef {
|
||||||
|
NotFound,
|
||||||
|
PermissionDenied,
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
impl From<PrimitivePrivDef> for remote::PrimitivePriv {
|
impl From<PrimitivePrivDef> for remote::PrimitivePriv {
|
||||||
fn from(def: PrimitivePrivDef) -> Self {
|
fn from(def: PrimitivePrivDef) -> Self {
|
||||||
remote::PrimitivePriv::new(def.0)
|
remote::PrimitivePriv::new(def.0)
|
||||||
|
|||||||
@@ -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]
|
#[test]
|
||||||
fn test_bound() {
|
fn test_bound() {
|
||||||
assert_ser_tokens(
|
assert_ser_tokens(
|
||||||
|
|||||||
@@ -2,10 +2,17 @@ error[E0609]: no field `b` on type `&remote::S`
|
|||||||
--> tests/ui/remote/unknown_field.rs:12:5
|
--> tests/ui/remote/unknown_field.rs:12:5
|
||||||
|
|
|
|
||||||
12 | b: u8,
|
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`
|
error[E0560]: struct `remote::S` has no field named `b`
|
||||||
--> tests/ui/remote/unknown_field.rs:12:5
|
--> tests/ui/remote/unknown_field.rs:12:5
|
||||||
|
|
|
|
||||||
12 | b: u8,
|
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
|
||||||
|
|||||||
Reference in New Issue
Block a user