Merge pull request #2533 from dtolnay/test
Move serde_test out to serde-rs/test
This commit is contained in:
commit
11677ad926
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@ -46,8 +46,6 @@ jobs:
|
|||||||
toolchain: ${{matrix.rust}}
|
toolchain: ${{matrix.rust}}
|
||||||
- run: cd serde && cargo build --features rc
|
- run: cd serde && cargo build --features rc
|
||||||
- run: cd serde && cargo build --no-default-features
|
- run: cd serde && cargo build --no-default-features
|
||||||
- run: cd serde_test && cargo build
|
|
||||||
- run: cd serde_test && cargo test --features serde/derive,serde/rc
|
|
||||||
|
|
||||||
nightly:
|
nightly:
|
||||||
name: Rust nightly ${{matrix.os == 'windows' && '(windows)' || ''}}
|
name: Rust nightly ${{matrix.os == 'windows' && '(windows)' || ''}}
|
||||||
@ -88,7 +86,6 @@ jobs:
|
|||||||
- run: cd serde && cargo build --features rc
|
- run: cd serde && cargo build --features rc
|
||||||
- run: cd serde && cargo build --no-default-features
|
- run: cd serde && cargo build --no-default-features
|
||||||
- run: cd serde && cargo build
|
- run: cd serde && cargo build
|
||||||
- run: cd serde_test && cargo build
|
|
||||||
|
|
||||||
more:
|
more:
|
||||||
name: Rust ${{matrix.rust}}
|
name: Rust ${{matrix.rust}}
|
||||||
@ -149,7 +146,6 @@ jobs:
|
|||||||
- 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
|
||||||
- run: cd serde_derive_internals && cargo clippy -- -Dclippy::all -Dclippy::pedantic
|
- run: cd serde_derive_internals && cargo clippy -- -Dclippy::all -Dclippy::pedantic
|
||||||
- run: cd serde_test && cargo clippy -- -Dclippy::all -Dclippy::pedantic
|
|
||||||
- run: cd test_suite && cargo clippy --tests --features unstable -- -Dclippy::all -Dclippy::pedantic
|
- run: cd test_suite && cargo clippy --tests --features unstable -- -Dclippy::all -Dclippy::pedantic
|
||||||
- run: cd test_suite/no_std && cargo clippy -- -Dclippy::all -Dclippy::pedantic
|
- run: cd test_suite/no_std && cargo clippy -- -Dclippy::all -Dclippy::pedantic
|
||||||
|
|
||||||
|
@ -3,6 +3,8 @@ members = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_derive_internals",
|
"serde_derive_internals",
|
||||||
"serde_test",
|
|
||||||
"test_suite",
|
"test_suite",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[patch.crates-io]
|
||||||
|
serde = { path = "serde" }
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "serde_test"
|
|
||||||
version = "1.0.175" # remember to update html_root_url
|
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
|
||||||
build = "build.rs"
|
|
||||||
categories = ["development-tools::testing"]
|
|
||||||
description = "Token De/Serializer for testing De/Serialize implementations"
|
|
||||||
documentation = "https://docs.rs/serde_test"
|
|
||||||
homepage = "https://serde.rs"
|
|
||||||
keywords = ["serde", "serialization", "testing", "dev-dependencies"]
|
|
||||||
license = "MIT OR Apache-2.0"
|
|
||||||
readme = "crates-io.md"
|
|
||||||
repository = "https://github.com/serde-rs/serde"
|
|
||||||
rust-version = "1.19"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
serde = { version = "1.0.60", path = "../serde" }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
serde = { version = "1", path = "../serde", features = ["rc"] }
|
|
||||||
serde_derive = { version = "1", path = "../serde_derive" }
|
|
||||||
|
|
||||||
[lib]
|
|
||||||
doc-scrape-examples = false
|
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
|
||||||
targets = ["x86_64-unknown-linux-gnu"]
|
|
||||||
rustdoc-args = ["--generate-link-to-definition"]
|
|
@ -1 +0,0 @@
|
|||||||
../LICENSE-APACHE
|
|
@ -1 +0,0 @@
|
|||||||
../LICENSE-MIT
|
|
@ -1 +0,0 @@
|
|||||||
../README.md
|
|
@ -1,50 +0,0 @@
|
|||||||
use std::env;
|
|
||||||
use std::process::Command;
|
|
||||||
use std::str::{self, FromStr};
|
|
||||||
|
|
||||||
// The rustc-cfg strings below are *not* public API. Please let us know by
|
|
||||||
// opening a GitHub issue if your build environment requires some way to enable
|
|
||||||
// these cfgs other than by executing our build script.
|
|
||||||
fn main() {
|
|
||||||
println!("cargo:rerun-if-changed=build.rs");
|
|
||||||
|
|
||||||
let minor = match rustc_minor_version() {
|
|
||||||
Some(minor) => minor,
|
|
||||||
None => return,
|
|
||||||
};
|
|
||||||
|
|
||||||
// #[track_caller] stabilized in Rust 1.46:
|
|
||||||
// https://blog.rust-lang.org/2020/08/27/Rust-1.46.0.html#track_caller
|
|
||||||
if minor < 46 {
|
|
||||||
println!("cargo:rustc-cfg=no_track_caller");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn rustc_minor_version() -> Option<u32> {
|
|
||||||
let rustc = match env::var_os("RUSTC") {
|
|
||||||
Some(rustc) => rustc,
|
|
||||||
None => return None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let output = match Command::new(rustc).arg("--version").output() {
|
|
||||||
Ok(output) => output,
|
|
||||||
Err(_) => return None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let version = match str::from_utf8(&output.stdout) {
|
|
||||||
Ok(version) => version,
|
|
||||||
Err(_) => return None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut pieces = version.split('.');
|
|
||||||
if pieces.next() != Some("rustc 1") {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let next = match pieces.next() {
|
|
||||||
Some(next) => next,
|
|
||||||
None => return None,
|
|
||||||
};
|
|
||||||
|
|
||||||
u32::from_str(next).ok()
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
../crates-io.md
|
|
@ -1,237 +0,0 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use de::Deserializer;
|
|
||||||
use ser::Serializer;
|
|
||||||
use token::Token;
|
|
||||||
|
|
||||||
use std::fmt::Debug;
|
|
||||||
|
|
||||||
/// Runs both `assert_ser_tokens` and `assert_de_tokens`.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_derive::{Deserialize, Serialize};
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
/// struct S {
|
|
||||||
/// a: u8,
|
|
||||||
/// b: u8,
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// let s = S { a: 0, b: 0 };
|
|
||||||
/// assert_tokens(
|
|
||||||
/// &s,
|
|
||||||
/// &[
|
|
||||||
/// Token::Struct { name: "S", len: 2 },
|
|
||||||
/// Token::Str("a"),
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::Str("b"),
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::StructEnd,
|
|
||||||
/// ],
|
|
||||||
/// );
|
|
||||||
/// ```
|
|
||||||
#[cfg_attr(not(no_track_caller), track_caller)]
|
|
||||||
pub fn assert_tokens<'de, T>(value: &T, tokens: &'de [Token])
|
|
||||||
where
|
|
||||||
T: Serialize + Deserialize<'de> + PartialEq + Debug,
|
|
||||||
{
|
|
||||||
assert_ser_tokens(value, tokens);
|
|
||||||
assert_de_tokens(value, tokens);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Asserts that `value` serializes to the given `tokens`.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_derive::{Deserialize, Serialize};
|
|
||||||
/// # use serde_test::{assert_ser_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
/// struct S {
|
|
||||||
/// a: u8,
|
|
||||||
/// b: u8,
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// let s = S { a: 0, b: 0 };
|
|
||||||
/// assert_ser_tokens(
|
|
||||||
/// &s,
|
|
||||||
/// &[
|
|
||||||
/// Token::Struct { name: "S", len: 2 },
|
|
||||||
/// Token::Str("a"),
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::Str("b"),
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::StructEnd,
|
|
||||||
/// ],
|
|
||||||
/// );
|
|
||||||
/// ```
|
|
||||||
#[cfg_attr(not(no_track_caller), track_caller)]
|
|
||||||
pub fn assert_ser_tokens<T: ?Sized>(value: &T, tokens: &[Token])
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
let mut ser = Serializer::new(tokens);
|
|
||||||
match value.serialize(&mut ser) {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(err) => panic!("value failed to serialize: {}", err),
|
|
||||||
}
|
|
||||||
|
|
||||||
if ser.remaining() > 0 {
|
|
||||||
panic!("{} remaining tokens", ser.remaining());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Asserts that `value` serializes to the given `tokens`, and then yields
|
|
||||||
/// `error`.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// use serde_derive::Serialize;
|
|
||||||
/// use serde_test::{assert_ser_tokens_error, Token};
|
|
||||||
/// use std::sync::{Arc, Mutex};
|
|
||||||
/// use std::thread;
|
|
||||||
///
|
|
||||||
/// #[derive(Serialize)]
|
|
||||||
/// struct Example {
|
|
||||||
/// lock: Arc<Mutex<u32>>,
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn main() {
|
|
||||||
/// let example = Example {
|
|
||||||
/// lock: Arc::new(Mutex::new(0)),
|
|
||||||
/// };
|
|
||||||
/// let lock = example.lock.clone();
|
|
||||||
///
|
|
||||||
/// let thread = thread::spawn(move || {
|
|
||||||
/// // This thread will acquire the mutex first, unwrapping the result
|
|
||||||
/// // of `lock` because the lock has not been poisoned.
|
|
||||||
/// let _guard = lock.lock().unwrap();
|
|
||||||
///
|
|
||||||
/// // This panic while holding the lock (`_guard` is in scope) will
|
|
||||||
/// // poison the mutex.
|
|
||||||
/// panic!()
|
|
||||||
/// });
|
|
||||||
/// thread.join();
|
|
||||||
///
|
|
||||||
/// let expected = &[
|
|
||||||
/// Token::Struct {
|
|
||||||
/// name: "Example",
|
|
||||||
/// len: 1,
|
|
||||||
/// },
|
|
||||||
/// Token::Str("lock"),
|
|
||||||
/// ];
|
|
||||||
/// let error = "lock poison error while serializing";
|
|
||||||
/// assert_ser_tokens_error(&example, expected, error);
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
#[cfg_attr(not(no_track_caller), track_caller)]
|
|
||||||
pub fn assert_ser_tokens_error<T: ?Sized>(value: &T, tokens: &[Token], error: &str)
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
let mut ser = Serializer::new(tokens);
|
|
||||||
match value.serialize(&mut ser) {
|
|
||||||
Ok(_) => panic!("value serialized successfully"),
|
|
||||||
Err(e) => assert_eq!(e, *error),
|
|
||||||
}
|
|
||||||
|
|
||||||
if ser.remaining() > 0 {
|
|
||||||
panic!("{} remaining tokens", ser.remaining());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Asserts that the given `tokens` deserialize into `value`.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_derive::{Deserialize, Serialize};
|
|
||||||
/// # use serde_test::{assert_de_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
/// struct S {
|
|
||||||
/// a: u8,
|
|
||||||
/// b: u8,
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// let s = S { a: 0, b: 0 };
|
|
||||||
/// assert_de_tokens(
|
|
||||||
/// &s,
|
|
||||||
/// &[
|
|
||||||
/// Token::Struct { name: "S", len: 2 },
|
|
||||||
/// Token::Str("a"),
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::Str("b"),
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::StructEnd,
|
|
||||||
/// ],
|
|
||||||
/// );
|
|
||||||
/// ```
|
|
||||||
#[cfg_attr(not(no_track_caller), track_caller)]
|
|
||||||
pub fn assert_de_tokens<'de, T>(value: &T, tokens: &'de [Token])
|
|
||||||
where
|
|
||||||
T: Deserialize<'de> + PartialEq + Debug,
|
|
||||||
{
|
|
||||||
let mut de = Deserializer::new(tokens);
|
|
||||||
let mut deserialized_val = match T::deserialize(&mut de) {
|
|
||||||
Ok(v) => {
|
|
||||||
assert_eq!(v, *value);
|
|
||||||
v
|
|
||||||
}
|
|
||||||
Err(e) => panic!("tokens failed to deserialize: {}", e),
|
|
||||||
};
|
|
||||||
if de.remaining() > 0 {
|
|
||||||
panic!("{} remaining tokens", de.remaining());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do the same thing for deserialize_in_place. This isn't *great* because a
|
|
||||||
// no-op impl of deserialize_in_place can technically succeed here. Still,
|
|
||||||
// this should catch a lot of junk.
|
|
||||||
let mut de = Deserializer::new(tokens);
|
|
||||||
match T::deserialize_in_place(&mut de, &mut deserialized_val) {
|
|
||||||
Ok(()) => {
|
|
||||||
assert_eq!(deserialized_val, *value);
|
|
||||||
}
|
|
||||||
Err(e) => panic!("tokens failed to deserialize_in_place: {}", e),
|
|
||||||
}
|
|
||||||
if de.remaining() > 0 {
|
|
||||||
panic!("{} remaining tokens", de.remaining());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Asserts that the given `tokens` yield `error` when deserializing.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_derive::{Deserialize, Serialize};
|
|
||||||
/// # use serde_test::{assert_de_tokens_error, Token};
|
|
||||||
/// #
|
|
||||||
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
/// #[serde(deny_unknown_fields)]
|
|
||||||
/// struct S {
|
|
||||||
/// a: u8,
|
|
||||||
/// b: u8,
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// assert_de_tokens_error::<S>(
|
|
||||||
/// &[
|
|
||||||
/// Token::Struct { name: "S", len: 2 },
|
|
||||||
/// Token::Str("x"),
|
|
||||||
/// ],
|
|
||||||
/// "unknown field `x`, expected `a` or `b`",
|
|
||||||
/// );
|
|
||||||
/// ```
|
|
||||||
#[cfg_attr(not(no_track_caller), track_caller)]
|
|
||||||
pub fn assert_de_tokens_error<'de, T>(tokens: &'de [Token], error: &str)
|
|
||||||
where
|
|
||||||
T: Deserialize<'de>,
|
|
||||||
{
|
|
||||||
let mut de = Deserializer::new(tokens);
|
|
||||||
match T::deserialize(&mut de) {
|
|
||||||
Ok(_) => panic!("tokens deserialized successfully"),
|
|
||||||
Err(e) => assert_eq!(e, *error),
|
|
||||||
}
|
|
||||||
|
|
||||||
// There may be one token left if a peek caused the error
|
|
||||||
de.next_token_opt();
|
|
||||||
|
|
||||||
if de.remaining() > 0 {
|
|
||||||
panic!("{} remaining tokens", de.remaining());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,847 +0,0 @@
|
|||||||
use std::fmt;
|
|
||||||
|
|
||||||
use serde::ser::{
|
|
||||||
SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeTuple,
|
|
||||||
SerializeTupleStruct, SerializeTupleVariant,
|
|
||||||
};
|
|
||||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
|
||||||
pub struct Readable<T: ?Sized>(T);
|
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
|
||||||
pub struct Compact<T: ?Sized>(T);
|
|
||||||
|
|
||||||
/// Trait to determine whether a value is represented in human-readable or
|
|
||||||
/// compact form.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
|
||||||
/// use serde_test::{assert_tokens, Configure, Token};
|
|
||||||
///
|
|
||||||
/// #[derive(Debug, PartialEq)]
|
|
||||||
/// struct Example(u8, u8);
|
|
||||||
///
|
|
||||||
/// impl Serialize for Example {
|
|
||||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
/// where
|
|
||||||
/// S: Serializer,
|
|
||||||
/// {
|
|
||||||
/// if serializer.is_human_readable() {
|
|
||||||
/// format!("{}.{}", self.0, self.1).serialize(serializer)
|
|
||||||
/// } else {
|
|
||||||
/// (self.0, self.1).serialize(serializer)
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// impl<'de> Deserialize<'de> for Example {
|
|
||||||
/// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
||||||
/// where
|
|
||||||
/// D: Deserializer<'de>,
|
|
||||||
/// {
|
|
||||||
/// use serde::de::Error;
|
|
||||||
/// if deserializer.is_human_readable() {
|
|
||||||
/// let s = String::deserialize(deserializer)?;
|
|
||||||
/// let parts: Vec<_> = s.split('.').collect();
|
|
||||||
/// Ok(Example(
|
|
||||||
/// parts[0].parse().map_err(D::Error::custom)?,
|
|
||||||
/// parts[1].parse().map_err(D::Error::custom)?,
|
|
||||||
/// ))
|
|
||||||
/// } else {
|
|
||||||
/// let (x, y) = Deserialize::deserialize(deserializer)?;
|
|
||||||
/// Ok(Example(x, y))
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn main() {
|
|
||||||
/// assert_tokens(
|
|
||||||
/// &Example(1, 0).compact(),
|
|
||||||
/// &[
|
|
||||||
/// Token::Tuple { len: 2 },
|
|
||||||
/// Token::U8(1),
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::TupleEnd,
|
|
||||||
/// ],
|
|
||||||
/// );
|
|
||||||
/// assert_tokens(&Example(1, 0).readable(), &[Token::Str("1.0")]);
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub trait Configure {
|
|
||||||
/// Marks `self` as using `is_human_readable == true`
|
|
||||||
fn readable(self) -> Readable<Self>
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
Readable(self)
|
|
||||||
}
|
|
||||||
/// Marks `self` as using `is_human_readable == false`
|
|
||||||
fn compact(self) -> Compact<Self>
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
Compact(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: ?Sized> Configure for T {}
|
|
||||||
|
|
||||||
impl<T: ?Sized> Serialize for Readable<T>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
S: Serializer,
|
|
||||||
{
|
|
||||||
self.0.serialize(Readable(serializer))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<T: ?Sized> Serialize for Compact<T>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
S: Serializer,
|
|
||||||
{
|
|
||||||
self.0.serialize(Compact(serializer))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<'de, T> Deserialize<'de> for Readable<T>
|
|
||||||
where
|
|
||||||
T: Deserialize<'de>,
|
|
||||||
{
|
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
T::deserialize(Readable(deserializer)).map(Readable)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<'de, T> Deserialize<'de> for Compact<T>
|
|
||||||
where
|
|
||||||
T: Deserialize<'de>,
|
|
||||||
{
|
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
T::deserialize(Compact(deserializer)).map(Compact)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, T> DeserializeSeed<'de> for Readable<T>
|
|
||||||
where
|
|
||||||
T: DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
type Value = T::Value;
|
|
||||||
|
|
||||||
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
self.0.deserialize(Readable(deserializer))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<'de, T> DeserializeSeed<'de> for Compact<T>
|
|
||||||
where
|
|
||||||
T: DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
type Value = T::Value;
|
|
||||||
|
|
||||||
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
self.0.deserialize(Compact(deserializer))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! forward_method {
|
|
||||||
($name: ident (self $(, $arg: ident : $arg_type: ty)* ) -> $return_type: ty) => {
|
|
||||||
fn $name (self $(, $arg : $arg_type)* ) -> $return_type {
|
|
||||||
(self.0).$name( $($arg),* )
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! forward_serialize_methods {
|
|
||||||
( $( $name: ident $arg_type: ty ),* ) => {
|
|
||||||
$(
|
|
||||||
forward_method!($name(self, v : $arg_type) -> Result<Self::Ok, Self::Error>);
|
|
||||||
)*
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_serializer {
|
|
||||||
($wrapper:ident, $is_human_readable:expr) => {
|
|
||||||
impl<S> Serializer for $wrapper<S>
|
|
||||||
where
|
|
||||||
S: Serializer,
|
|
||||||
{
|
|
||||||
type Ok = S::Ok;
|
|
||||||
type Error = S::Error;
|
|
||||||
|
|
||||||
type SerializeSeq = $wrapper<S::SerializeSeq>;
|
|
||||||
type SerializeTuple = $wrapper<S::SerializeTuple>;
|
|
||||||
type SerializeTupleStruct = $wrapper<S::SerializeTupleStruct>;
|
|
||||||
type SerializeTupleVariant = $wrapper<S::SerializeTupleVariant>;
|
|
||||||
type SerializeMap = $wrapper<S::SerializeMap>;
|
|
||||||
type SerializeStruct = $wrapper<S::SerializeStruct>;
|
|
||||||
type SerializeStructVariant = $wrapper<S::SerializeStructVariant>;
|
|
||||||
|
|
||||||
fn is_human_readable(&self) -> bool {
|
|
||||||
$is_human_readable
|
|
||||||
}
|
|
||||||
|
|
||||||
forward_serialize_methods! {
|
|
||||||
serialize_bool bool,
|
|
||||||
serialize_i8 i8,
|
|
||||||
serialize_i16 i16,
|
|
||||||
serialize_i32 i32,
|
|
||||||
serialize_i64 i64,
|
|
||||||
serialize_u8 u8,
|
|
||||||
serialize_u16 u16,
|
|
||||||
serialize_u32 u32,
|
|
||||||
serialize_u64 u64,
|
|
||||||
serialize_f32 f32,
|
|
||||||
serialize_f64 f64,
|
|
||||||
serialize_char char,
|
|
||||||
serialize_str &str,
|
|
||||||
serialize_bytes &[u8],
|
|
||||||
serialize_unit_struct &'static str
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_unit(self) -> Result<S::Ok, S::Error> {
|
|
||||||
self.0.serialize_unit()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_unit_variant(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
variant_index: u32,
|
|
||||||
variant: &'static str,
|
|
||||||
) -> Result<S::Ok, S::Error> {
|
|
||||||
self.0.serialize_unit_variant(name, variant_index, variant)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_newtype_struct<T: ?Sized>(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
value: &T,
|
|
||||||
) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
self.0.serialize_newtype_struct(name, &$wrapper(value))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_newtype_variant<T: ?Sized>(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
variant_index: u32,
|
|
||||||
variant: &'static str,
|
|
||||||
value: &T,
|
|
||||||
) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
self.0
|
|
||||||
.serialize_newtype_variant(name, variant_index, variant, &$wrapper(value))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_none(self) -> Result<S::Ok, Self::Error> {
|
|
||||||
self.0.serialize_none()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<S::Ok, Self::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
self.0.serialize_some(&$wrapper(value))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
|
|
||||||
self.0.serialize_seq(len).map($wrapper)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
|
|
||||||
self.0.serialize_tuple(len).map($wrapper)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_tuple_struct(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
len: usize,
|
|
||||||
) -> Result<Self::SerializeTupleStruct, Self::Error> {
|
|
||||||
self.0.serialize_tuple_struct(name, len).map($wrapper)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_tuple_variant(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
variant_index: u32,
|
|
||||||
variant: &'static str,
|
|
||||||
len: usize,
|
|
||||||
) -> Result<Self::SerializeTupleVariant, Self::Error> {
|
|
||||||
self.0
|
|
||||||
.serialize_tuple_variant(name, variant_index, variant, len)
|
|
||||||
.map($wrapper)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
|
|
||||||
self.0.serialize_map(len).map($wrapper)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_struct(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
len: usize,
|
|
||||||
) -> Result<Self::SerializeStruct, Self::Error> {
|
|
||||||
self.0.serialize_struct(name, len).map($wrapper)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_struct_variant(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
variant_index: u32,
|
|
||||||
variant: &'static str,
|
|
||||||
len: usize,
|
|
||||||
) -> Result<Self::SerializeStructVariant, Self::Error> {
|
|
||||||
self.0
|
|
||||||
.serialize_struct_variant(name, variant_index, variant, len)
|
|
||||||
.map($wrapper)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S> SerializeSeq for $wrapper<S>
|
|
||||||
where
|
|
||||||
S: SerializeSeq,
|
|
||||||
{
|
|
||||||
type Ok = S::Ok;
|
|
||||||
type Error = S::Error;
|
|
||||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), S::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
self.0.serialize_element(&$wrapper(value))
|
|
||||||
}
|
|
||||||
fn end(self) -> Result<S::Ok, S::Error> {
|
|
||||||
self.0.end()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S> SerializeTuple for $wrapper<S>
|
|
||||||
where
|
|
||||||
S: SerializeTuple,
|
|
||||||
{
|
|
||||||
type Ok = S::Ok;
|
|
||||||
type Error = S::Error;
|
|
||||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), S::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
self.0.serialize_element(&$wrapper(value))
|
|
||||||
}
|
|
||||||
fn end(self) -> Result<S::Ok, S::Error> {
|
|
||||||
self.0.end()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S> SerializeTupleStruct for $wrapper<S>
|
|
||||||
where
|
|
||||||
S: SerializeTupleStruct,
|
|
||||||
{
|
|
||||||
type Ok = S::Ok;
|
|
||||||
type Error = S::Error;
|
|
||||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), S::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
self.0.serialize_field(&$wrapper(value))
|
|
||||||
}
|
|
||||||
fn end(self) -> Result<S::Ok, S::Error> {
|
|
||||||
self.0.end()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S> SerializeTupleVariant for $wrapper<S>
|
|
||||||
where
|
|
||||||
S: SerializeTupleVariant,
|
|
||||||
{
|
|
||||||
type Ok = S::Ok;
|
|
||||||
type Error = S::Error;
|
|
||||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), S::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
self.0.serialize_field(&$wrapper(value))
|
|
||||||
}
|
|
||||||
fn end(self) -> Result<S::Ok, S::Error> {
|
|
||||||
self.0.end()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S> SerializeMap for $wrapper<S>
|
|
||||||
where
|
|
||||||
S: SerializeMap,
|
|
||||||
{
|
|
||||||
type Ok = S::Ok;
|
|
||||||
type Error = S::Error;
|
|
||||||
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), S::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
self.0.serialize_key(&$wrapper(key))
|
|
||||||
}
|
|
||||||
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), S::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
self.0.serialize_value(&$wrapper(value))
|
|
||||||
}
|
|
||||||
fn serialize_entry<K: ?Sized, V: ?Sized>(
|
|
||||||
&mut self,
|
|
||||||
key: &K,
|
|
||||||
value: &V,
|
|
||||||
) -> Result<(), S::Error>
|
|
||||||
where
|
|
||||||
K: Serialize,
|
|
||||||
V: Serialize,
|
|
||||||
{
|
|
||||||
self.0.serialize_entry(key, &$wrapper(value))
|
|
||||||
}
|
|
||||||
fn end(self) -> Result<S::Ok, S::Error> {
|
|
||||||
self.0.end()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S> SerializeStruct for $wrapper<S>
|
|
||||||
where
|
|
||||||
S: SerializeStruct,
|
|
||||||
{
|
|
||||||
type Ok = S::Ok;
|
|
||||||
type Error = S::Error;
|
|
||||||
fn serialize_field<T: ?Sized>(
|
|
||||||
&mut self,
|
|
||||||
name: &'static str,
|
|
||||||
field: &T,
|
|
||||||
) -> Result<(), S::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
self.0.serialize_field(name, &$wrapper(field))
|
|
||||||
}
|
|
||||||
fn end(self) -> Result<S::Ok, S::Error> {
|
|
||||||
self.0.end()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S> SerializeStructVariant for $wrapper<S>
|
|
||||||
where
|
|
||||||
S: SerializeStructVariant,
|
|
||||||
{
|
|
||||||
type Ok = S::Ok;
|
|
||||||
type Error = S::Error;
|
|
||||||
fn serialize_field<T: ?Sized>(
|
|
||||||
&mut self,
|
|
||||||
name: &'static str,
|
|
||||||
field: &T,
|
|
||||||
) -> Result<(), S::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
self.0.serialize_field(name, &$wrapper(field))
|
|
||||||
}
|
|
||||||
fn end(self) -> Result<S::Ok, S::Error> {
|
|
||||||
self.0.end()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_serializer!(Readable, true);
|
|
||||||
impl_serializer!(Compact, false);
|
|
||||||
|
|
||||||
use serde::de::{DeserializeSeed, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor};
|
|
||||||
|
|
||||||
macro_rules! forward_deserialize_methods {
|
|
||||||
( $wrapper : ident ( $( $name: ident ),* ) ) => {
|
|
||||||
$(
|
|
||||||
fn $name<V>(self, visitor: V) -> Result<V::Value, D::Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
(self.0).$name($wrapper(visitor))
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_deserializer {
|
|
||||||
($wrapper:ident, $is_human_readable:expr) => {
|
|
||||||
impl<'de, D> Deserializer<'de> for $wrapper<D>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
type Error = D::Error;
|
|
||||||
|
|
||||||
forward_deserialize_methods! {
|
|
||||||
$wrapper (
|
|
||||||
deserialize_any,
|
|
||||||
deserialize_bool,
|
|
||||||
deserialize_u8,
|
|
||||||
deserialize_u16,
|
|
||||||
deserialize_u32,
|
|
||||||
deserialize_u64,
|
|
||||||
deserialize_i8,
|
|
||||||
deserialize_i16,
|
|
||||||
deserialize_i32,
|
|
||||||
deserialize_i64,
|
|
||||||
deserialize_f32,
|
|
||||||
deserialize_f64,
|
|
||||||
deserialize_char,
|
|
||||||
deserialize_str,
|
|
||||||
deserialize_string,
|
|
||||||
deserialize_bytes,
|
|
||||||
deserialize_byte_buf,
|
|
||||||
deserialize_option,
|
|
||||||
deserialize_unit,
|
|
||||||
deserialize_seq,
|
|
||||||
deserialize_map,
|
|
||||||
deserialize_identifier,
|
|
||||||
deserialize_ignored_any
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_unit_struct<V>(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
visitor: V,
|
|
||||||
) -> Result<V::Value, D::Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
self.0.deserialize_unit_struct(name, $wrapper(visitor))
|
|
||||||
}
|
|
||||||
fn deserialize_newtype_struct<V>(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
visitor: V,
|
|
||||||
) -> Result<V::Value, D::Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
self.0.deserialize_newtype_struct(name, $wrapper(visitor))
|
|
||||||
}
|
|
||||||
fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, D::Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
self.0.deserialize_tuple(len, $wrapper(visitor))
|
|
||||||
}
|
|
||||||
fn deserialize_tuple_struct<V>(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
len: usize,
|
|
||||||
visitor: V,
|
|
||||||
) -> Result<V::Value, D::Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
self.0
|
|
||||||
.deserialize_tuple_struct(name, len, $wrapper(visitor))
|
|
||||||
}
|
|
||||||
fn deserialize_struct<V>(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
fields: &'static [&'static str],
|
|
||||||
visitor: V,
|
|
||||||
) -> Result<V::Value, D::Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
self.0.deserialize_struct(name, fields, $wrapper(visitor))
|
|
||||||
}
|
|
||||||
fn deserialize_enum<V>(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
variants: &'static [&'static str],
|
|
||||||
visitor: V,
|
|
||||||
) -> Result<V::Value, D::Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
self.0.deserialize_enum(name, variants, $wrapper(visitor))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_human_readable(&self) -> bool {
|
|
||||||
$is_human_readable
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, D> Visitor<'de> for $wrapper<D>
|
|
||||||
where
|
|
||||||
D: Visitor<'de>,
|
|
||||||
{
|
|
||||||
type Value = D::Value;
|
|
||||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
self.0.expecting(formatter)
|
|
||||||
}
|
|
||||||
fn visit_bool<E>(self, v: bool) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_bool(v)
|
|
||||||
}
|
|
||||||
fn visit_i8<E>(self, v: i8) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_i8(v)
|
|
||||||
}
|
|
||||||
fn visit_i16<E>(self, v: i16) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_i16(v)
|
|
||||||
}
|
|
||||||
fn visit_i32<E>(self, v: i32) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_i32(v)
|
|
||||||
}
|
|
||||||
fn visit_i64<E>(self, v: i64) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_i64(v)
|
|
||||||
}
|
|
||||||
fn visit_u8<E>(self, v: u8) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_u8(v)
|
|
||||||
}
|
|
||||||
fn visit_u16<E>(self, v: u16) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_u16(v)
|
|
||||||
}
|
|
||||||
fn visit_u32<E>(self, v: u32) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_u32(v)
|
|
||||||
}
|
|
||||||
fn visit_u64<E>(self, v: u64) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_u64(v)
|
|
||||||
}
|
|
||||||
fn visit_f32<E>(self, v: f32) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_f32(v)
|
|
||||||
}
|
|
||||||
fn visit_f64<E>(self, v: f64) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_f64(v)
|
|
||||||
}
|
|
||||||
fn visit_char<E>(self, v: char) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_char(v)
|
|
||||||
}
|
|
||||||
fn visit_str<E>(self, v: &str) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_str(v)
|
|
||||||
}
|
|
||||||
fn visit_borrowed_str<E>(self, v: &'de str) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_borrowed_str(v)
|
|
||||||
}
|
|
||||||
fn visit_string<E>(self, v: String) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_string(v)
|
|
||||||
}
|
|
||||||
fn visit_bytes<E>(self, v: &[u8]) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_bytes(v)
|
|
||||||
}
|
|
||||||
fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_borrowed_bytes(v)
|
|
||||||
}
|
|
||||||
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_byte_buf(v)
|
|
||||||
}
|
|
||||||
fn visit_none<E>(self) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_none()
|
|
||||||
}
|
|
||||||
fn visit_some<D2>(self, deserializer: D2) -> Result<Self::Value, D2::Error>
|
|
||||||
where
|
|
||||||
D2: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
self.0.visit_some($wrapper(deserializer))
|
|
||||||
}
|
|
||||||
fn visit_unit<E>(self) -> Result<D::Value, E>
|
|
||||||
where
|
|
||||||
E: Error,
|
|
||||||
{
|
|
||||||
self.0.visit_unit()
|
|
||||||
}
|
|
||||||
fn visit_newtype_struct<D2>(self, deserializer: D2) -> Result<Self::Value, D2::Error>
|
|
||||||
where
|
|
||||||
D2: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
self.0.visit_newtype_struct($wrapper(deserializer))
|
|
||||||
}
|
|
||||||
fn visit_seq<V>(self, seq: V) -> Result<D::Value, V::Error>
|
|
||||||
where
|
|
||||||
V: SeqAccess<'de>,
|
|
||||||
{
|
|
||||||
self.0.visit_seq($wrapper(seq))
|
|
||||||
}
|
|
||||||
fn visit_map<V>(self, map: V) -> Result<D::Value, V::Error>
|
|
||||||
where
|
|
||||||
V: MapAccess<'de>,
|
|
||||||
{
|
|
||||||
self.0.visit_map($wrapper(map))
|
|
||||||
}
|
|
||||||
fn visit_enum<V>(self, data: V) -> Result<D::Value, V::Error>
|
|
||||||
where
|
|
||||||
V: EnumAccess<'de>,
|
|
||||||
{
|
|
||||||
self.0.visit_enum($wrapper(data))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, D> SeqAccess<'de> for $wrapper<D>
|
|
||||||
where
|
|
||||||
D: SeqAccess<'de>,
|
|
||||||
{
|
|
||||||
type Error = D::Error;
|
|
||||||
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, D::Error>
|
|
||||||
where
|
|
||||||
T: DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
self.0.next_element_seed($wrapper(seed))
|
|
||||||
}
|
|
||||||
fn size_hint(&self) -> Option<usize> {
|
|
||||||
self.0.size_hint()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, D> MapAccess<'de> for $wrapper<D>
|
|
||||||
where
|
|
||||||
D: MapAccess<'de>,
|
|
||||||
{
|
|
||||||
type Error = D::Error;
|
|
||||||
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, D::Error>
|
|
||||||
where
|
|
||||||
K: DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
self.0.next_key_seed($wrapper(seed))
|
|
||||||
}
|
|
||||||
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, D::Error>
|
|
||||||
where
|
|
||||||
V: DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
self.0.next_value_seed($wrapper(seed))
|
|
||||||
}
|
|
||||||
fn next_entry_seed<K, V>(
|
|
||||||
&mut self,
|
|
||||||
kseed: K,
|
|
||||||
vseed: V,
|
|
||||||
) -> Result<Option<(K::Value, V::Value)>, D::Error>
|
|
||||||
where
|
|
||||||
K: DeserializeSeed<'de>,
|
|
||||||
V: DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
self.0.next_entry_seed($wrapper(kseed), $wrapper(vseed))
|
|
||||||
}
|
|
||||||
fn size_hint(&self) -> Option<usize> {
|
|
||||||
self.0.size_hint()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, D> EnumAccess<'de> for $wrapper<D>
|
|
||||||
where
|
|
||||||
D: EnumAccess<'de>,
|
|
||||||
{
|
|
||||||
type Error = D::Error;
|
|
||||||
type Variant = $wrapper<D::Variant>;
|
|
||||||
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
|
|
||||||
where
|
|
||||||
V: DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
self.0
|
|
||||||
.variant_seed($wrapper(seed))
|
|
||||||
.map(|(value, variant)| (value, $wrapper(variant)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, D> VariantAccess<'de> for $wrapper<D>
|
|
||||||
where
|
|
||||||
D: VariantAccess<'de>,
|
|
||||||
{
|
|
||||||
type Error = D::Error;
|
|
||||||
fn unit_variant(self) -> Result<(), D::Error> {
|
|
||||||
self.0.unit_variant()
|
|
||||||
}
|
|
||||||
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, D::Error>
|
|
||||||
where
|
|
||||||
T: DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
self.0.newtype_variant_seed($wrapper(seed))
|
|
||||||
}
|
|
||||||
fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value, D::Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
self.0.tuple_variant(len, $wrapper(visitor))
|
|
||||||
}
|
|
||||||
fn struct_variant<V>(
|
|
||||||
self,
|
|
||||||
fields: &'static [&'static str],
|
|
||||||
visitor: V,
|
|
||||||
) -> Result<V::Value, D::Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
self.0.struct_variant(fields, $wrapper(visitor))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_deserializer!(Readable, true);
|
|
||||||
impl_deserializer!(Compact, false);
|
|
@ -1,671 +0,0 @@
|
|||||||
use serde::de::value::{MapAccessDeserializer, SeqAccessDeserializer};
|
|
||||||
use serde::de::{
|
|
||||||
self, Deserialize, DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess, SeqAccess,
|
|
||||||
VariantAccess, Visitor,
|
|
||||||
};
|
|
||||||
|
|
||||||
use error::Error;
|
|
||||||
use token::Token;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Deserializer<'de> {
|
|
||||||
tokens: &'de [Token],
|
|
||||||
}
|
|
||||||
|
|
||||||
fn assert_next_token(de: &mut Deserializer, expected: Token) -> Result<(), Error> {
|
|
||||||
match de.next_token_opt() {
|
|
||||||
Some(token) if token == expected => Ok(()),
|
|
||||||
Some(other) => Err(de::Error::custom(format!(
|
|
||||||
"expected Token::{} but deserialization wants Token::{}",
|
|
||||||
other, expected,
|
|
||||||
))),
|
|
||||||
None => Err(de::Error::custom(format!(
|
|
||||||
"end of tokens but deserialization wants Token::{}",
|
|
||||||
expected,
|
|
||||||
))),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn unexpected(token: Token) -> Error {
|
|
||||||
de::Error::custom(format!(
|
|
||||||
"deserialization did not expect this token: {}",
|
|
||||||
token,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end_of_tokens() -> Error {
|
|
||||||
de::Error::custom("ran out of tokens to deserialize")
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de> Deserializer<'de> {
|
|
||||||
pub fn new(tokens: &'de [Token]) -> Self {
|
|
||||||
Deserializer { tokens: tokens }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn peek_token_opt(&self) -> Option<Token> {
|
|
||||||
self.tokens.first().cloned()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn peek_token(&self) -> Result<Token, Error> {
|
|
||||||
self.peek_token_opt().ok_or_else(end_of_tokens)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn next_token_opt(&mut self) -> Option<Token> {
|
|
||||||
match self.tokens.split_first() {
|
|
||||||
Some((&first, rest)) => {
|
|
||||||
self.tokens = rest;
|
|
||||||
Some(first)
|
|
||||||
}
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn next_token(&mut self) -> Result<Token, Error> {
|
|
||||||
let (&first, rest) = self.tokens.split_first().ok_or_else(end_of_tokens)?;
|
|
||||||
self.tokens = rest;
|
|
||||||
Ok(first)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn remaining(&self) -> usize {
|
|
||||||
self.tokens.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_seq<V>(
|
|
||||||
&mut self,
|
|
||||||
len: Option<usize>,
|
|
||||||
end: Token,
|
|
||||||
visitor: V,
|
|
||||||
) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
let value = visitor.visit_seq(DeserializerSeqVisitor {
|
|
||||||
de: self,
|
|
||||||
len: len,
|
|
||||||
end: end,
|
|
||||||
})?;
|
|
||||||
assert_next_token(self, end)?;
|
|
||||||
Ok(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_map<V>(
|
|
||||||
&mut self,
|
|
||||||
len: Option<usize>,
|
|
||||||
end: Token,
|
|
||||||
visitor: V,
|
|
||||||
) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
let value = visitor.visit_map(DeserializerMapVisitor {
|
|
||||||
de: self,
|
|
||||||
len: len,
|
|
||||||
end: end,
|
|
||||||
})?;
|
|
||||||
assert_next_token(self, end)?;
|
|
||||||
Ok(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
forward_to_deserialize_any! {
|
|
||||||
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
|
|
||||||
bytes byte_buf unit seq map identifier ignored_any
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
let token = self.next_token()?;
|
|
||||||
match token {
|
|
||||||
Token::Bool(v) => visitor.visit_bool(v),
|
|
||||||
Token::I8(v) => visitor.visit_i8(v),
|
|
||||||
Token::I16(v) => visitor.visit_i16(v),
|
|
||||||
Token::I32(v) => visitor.visit_i32(v),
|
|
||||||
Token::I64(v) => visitor.visit_i64(v),
|
|
||||||
Token::U8(v) => visitor.visit_u8(v),
|
|
||||||
Token::U16(v) => visitor.visit_u16(v),
|
|
||||||
Token::U32(v) => visitor.visit_u32(v),
|
|
||||||
Token::U64(v) => visitor.visit_u64(v),
|
|
||||||
Token::F32(v) => visitor.visit_f32(v),
|
|
||||||
Token::F64(v) => visitor.visit_f64(v),
|
|
||||||
Token::Char(v) => visitor.visit_char(v),
|
|
||||||
Token::Str(v) => visitor.visit_str(v),
|
|
||||||
Token::BorrowedStr(v) => visitor.visit_borrowed_str(v),
|
|
||||||
Token::String(v) => visitor.visit_string(v.to_owned()),
|
|
||||||
Token::Bytes(v) => visitor.visit_bytes(v),
|
|
||||||
Token::BorrowedBytes(v) => visitor.visit_borrowed_bytes(v),
|
|
||||||
Token::ByteBuf(v) => visitor.visit_byte_buf(v.to_vec()),
|
|
||||||
Token::None => visitor.visit_none(),
|
|
||||||
Token::Some => visitor.visit_some(self),
|
|
||||||
Token::Unit | Token::UnitStruct { .. } => visitor.visit_unit(),
|
|
||||||
Token::NewtypeStruct { .. } => visitor.visit_newtype_struct(self),
|
|
||||||
Token::Seq { len } => self.visit_seq(len, Token::SeqEnd, visitor),
|
|
||||||
Token::Tuple { len } => self.visit_seq(Some(len), Token::TupleEnd, visitor),
|
|
||||||
Token::TupleStruct { len, .. } => {
|
|
||||||
self.visit_seq(Some(len), Token::TupleStructEnd, visitor)
|
|
||||||
}
|
|
||||||
Token::Map { len } => self.visit_map(len, Token::MapEnd, visitor),
|
|
||||||
Token::Struct { len, .. } => self.visit_map(Some(len), Token::StructEnd, visitor),
|
|
||||||
Token::Enum { .. } => {
|
|
||||||
let variant = self.next_token()?;
|
|
||||||
let next = self.peek_token()?;
|
|
||||||
match (variant, next) {
|
|
||||||
(Token::Str(variant), Token::Unit) => {
|
|
||||||
self.next_token()?;
|
|
||||||
visitor.visit_str(variant)
|
|
||||||
}
|
|
||||||
(Token::BorrowedStr(variant), Token::Unit) => {
|
|
||||||
self.next_token()?;
|
|
||||||
visitor.visit_borrowed_str(variant)
|
|
||||||
}
|
|
||||||
(Token::String(variant), Token::Unit) => {
|
|
||||||
self.next_token()?;
|
|
||||||
visitor.visit_string(variant.to_string())
|
|
||||||
}
|
|
||||||
(Token::Bytes(variant), Token::Unit) => {
|
|
||||||
self.next_token()?;
|
|
||||||
visitor.visit_bytes(variant)
|
|
||||||
}
|
|
||||||
(Token::BorrowedBytes(variant), Token::Unit) => {
|
|
||||||
self.next_token()?;
|
|
||||||
visitor.visit_borrowed_bytes(variant)
|
|
||||||
}
|
|
||||||
(Token::ByteBuf(variant), Token::Unit) => {
|
|
||||||
self.next_token()?;
|
|
||||||
visitor.visit_byte_buf(variant.to_vec())
|
|
||||||
}
|
|
||||||
(Token::U8(variant), Token::Unit) => {
|
|
||||||
self.next_token()?;
|
|
||||||
visitor.visit_u8(variant)
|
|
||||||
}
|
|
||||||
(Token::U16(variant), Token::Unit) => {
|
|
||||||
self.next_token()?;
|
|
||||||
visitor.visit_u16(variant)
|
|
||||||
}
|
|
||||||
(Token::U32(variant), Token::Unit) => {
|
|
||||||
self.next_token()?;
|
|
||||||
visitor.visit_u32(variant)
|
|
||||||
}
|
|
||||||
(Token::U64(variant), Token::Unit) => {
|
|
||||||
self.next_token()?;
|
|
||||||
visitor.visit_u64(variant)
|
|
||||||
}
|
|
||||||
(variant, Token::Unit) => Err(unexpected(variant)),
|
|
||||||
(variant, _) => {
|
|
||||||
visitor.visit_map(EnumMapVisitor::new(self, variant, EnumFormat::Any))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Token::UnitVariant { variant, .. } => visitor.visit_str(variant),
|
|
||||||
Token::NewtypeVariant { variant, .. } => visitor.visit_map(EnumMapVisitor::new(
|
|
||||||
self,
|
|
||||||
Token::Str(variant),
|
|
||||||
EnumFormat::Any,
|
|
||||||
)),
|
|
||||||
Token::TupleVariant { variant, .. } => visitor.visit_map(EnumMapVisitor::new(
|
|
||||||
self,
|
|
||||||
Token::Str(variant),
|
|
||||||
EnumFormat::Seq,
|
|
||||||
)),
|
|
||||||
Token::StructVariant { variant, .. } => visitor.visit_map(EnumMapVisitor::new(
|
|
||||||
self,
|
|
||||||
Token::Str(variant),
|
|
||||||
EnumFormat::Map,
|
|
||||||
)),
|
|
||||||
Token::SeqEnd
|
|
||||||
| Token::TupleEnd
|
|
||||||
| Token::TupleStructEnd
|
|
||||||
| Token::MapEnd
|
|
||||||
| Token::StructEnd
|
|
||||||
| Token::TupleVariantEnd
|
|
||||||
| Token::StructVariantEnd => Err(unexpected(token)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
match self.peek_token()? {
|
|
||||||
Token::Unit | Token::None => {
|
|
||||||
self.next_token()?;
|
|
||||||
visitor.visit_none()
|
|
||||||
}
|
|
||||||
Token::Some => {
|
|
||||||
self.next_token()?;
|
|
||||||
visitor.visit_some(self)
|
|
||||||
}
|
|
||||||
_ => self.deserialize_any(visitor),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_enum<V>(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
_variants: &'static [&'static str],
|
|
||||||
visitor: V,
|
|
||||||
) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
match self.peek_token()? {
|
|
||||||
Token::Enum { name: n } if name == n => {
|
|
||||||
self.next_token()?;
|
|
||||||
|
|
||||||
visitor.visit_enum(DeserializerEnumVisitor { de: self })
|
|
||||||
}
|
|
||||||
Token::UnitVariant { name: n, .. }
|
|
||||||
| Token::NewtypeVariant { name: n, .. }
|
|
||||||
| Token::TupleVariant { name: n, .. }
|
|
||||||
| Token::StructVariant { name: n, .. }
|
|
||||||
if name == n =>
|
|
||||||
{
|
|
||||||
visitor.visit_enum(DeserializerEnumVisitor { de: self })
|
|
||||||
}
|
|
||||||
_ => self.deserialize_any(visitor),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_unit_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
match self.peek_token()? {
|
|
||||||
Token::UnitStruct { .. } => {
|
|
||||||
assert_next_token(self, Token::UnitStruct { name: name })?;
|
|
||||||
visitor.visit_unit()
|
|
||||||
}
|
|
||||||
_ => self.deserialize_any(visitor),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_newtype_struct<V>(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
visitor: V,
|
|
||||||
) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
match self.peek_token()? {
|
|
||||||
Token::NewtypeStruct { .. } => {
|
|
||||||
assert_next_token(self, Token::NewtypeStruct { name: name })?;
|
|
||||||
visitor.visit_newtype_struct(self)
|
|
||||||
}
|
|
||||||
_ => self.deserialize_any(visitor),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
match self.peek_token()? {
|
|
||||||
Token::Unit | Token::UnitStruct { .. } => {
|
|
||||||
self.next_token()?;
|
|
||||||
visitor.visit_unit()
|
|
||||||
}
|
|
||||||
Token::Seq { .. } => {
|
|
||||||
self.next_token()?;
|
|
||||||
self.visit_seq(Some(len), Token::SeqEnd, visitor)
|
|
||||||
}
|
|
||||||
Token::Tuple { .. } => {
|
|
||||||
self.next_token()?;
|
|
||||||
self.visit_seq(Some(len), Token::TupleEnd, visitor)
|
|
||||||
}
|
|
||||||
Token::TupleStruct { .. } => {
|
|
||||||
self.next_token()?;
|
|
||||||
self.visit_seq(Some(len), Token::TupleStructEnd, visitor)
|
|
||||||
}
|
|
||||||
_ => self.deserialize_any(visitor),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_tuple_struct<V>(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
len: usize,
|
|
||||||
visitor: V,
|
|
||||||
) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
match self.peek_token()? {
|
|
||||||
Token::Unit => {
|
|
||||||
self.next_token()?;
|
|
||||||
visitor.visit_unit()
|
|
||||||
}
|
|
||||||
Token::UnitStruct { .. } => {
|
|
||||||
assert_next_token(self, Token::UnitStruct { name: name })?;
|
|
||||||
visitor.visit_unit()
|
|
||||||
}
|
|
||||||
Token::Seq { .. } => {
|
|
||||||
self.next_token()?;
|
|
||||||
self.visit_seq(Some(len), Token::SeqEnd, visitor)
|
|
||||||
}
|
|
||||||
Token::Tuple { .. } => {
|
|
||||||
self.next_token()?;
|
|
||||||
self.visit_seq(Some(len), Token::TupleEnd, visitor)
|
|
||||||
}
|
|
||||||
Token::TupleStruct { len: n, .. } => {
|
|
||||||
assert_next_token(self, Token::TupleStruct { name: name, len: n })?;
|
|
||||||
self.visit_seq(Some(len), Token::TupleStructEnd, visitor)
|
|
||||||
}
|
|
||||||
_ => self.deserialize_any(visitor),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_struct<V>(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
fields: &'static [&'static str],
|
|
||||||
visitor: V,
|
|
||||||
) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
match self.peek_token()? {
|
|
||||||
Token::Struct { len: n, .. } => {
|
|
||||||
assert_next_token(self, Token::Struct { name: name, len: n })?;
|
|
||||||
self.visit_map(Some(fields.len()), Token::StructEnd, visitor)
|
|
||||||
}
|
|
||||||
Token::Map { .. } => {
|
|
||||||
self.next_token()?;
|
|
||||||
self.visit_map(Some(fields.len()), Token::MapEnd, visitor)
|
|
||||||
}
|
|
||||||
_ => self.deserialize_any(visitor),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_human_readable(&self) -> bool {
|
|
||||||
panic!(
|
|
||||||
"Types which have different human-readable and compact representations \
|
|
||||||
must explicitly mark their test cases with `serde_test::Configure`"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
struct DeserializerSeqVisitor<'a, 'de: 'a> {
|
|
||||||
de: &'a mut Deserializer<'de>,
|
|
||||||
len: Option<usize>,
|
|
||||||
end: Token,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, 'a> SeqAccess<'de> for DeserializerSeqVisitor<'a, 'de> {
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
|
|
||||||
where
|
|
||||||
T: DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
if self.de.peek_token_opt() == Some(self.end) {
|
|
||||||
return Ok(None);
|
|
||||||
}
|
|
||||||
self.len = self.len.map(|len| len.saturating_sub(1));
|
|
||||||
seed.deserialize(&mut *self.de).map(Some)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn size_hint(&self) -> Option<usize> {
|
|
||||||
self.len
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
struct DeserializerMapVisitor<'a, 'de: 'a> {
|
|
||||||
de: &'a mut Deserializer<'de>,
|
|
||||||
len: Option<usize>,
|
|
||||||
end: Token,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, 'a> MapAccess<'de> for DeserializerMapVisitor<'a, 'de> {
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
|
|
||||||
where
|
|
||||||
K: DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
if self.de.peek_token_opt() == Some(self.end) {
|
|
||||||
return Ok(None);
|
|
||||||
}
|
|
||||||
self.len = self.len.map(|len| len.saturating_sub(1));
|
|
||||||
seed.deserialize(&mut *self.de).map(Some)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
seed.deserialize(&mut *self.de)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn size_hint(&self) -> Option<usize> {
|
|
||||||
self.len
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
struct DeserializerEnumVisitor<'a, 'de: 'a> {
|
|
||||||
de: &'a mut Deserializer<'de>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, 'a> EnumAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
|
|
||||||
type Error = Error;
|
|
||||||
type Variant = Self;
|
|
||||||
|
|
||||||
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self), Error>
|
|
||||||
where
|
|
||||||
V: DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
match self.de.peek_token()? {
|
|
||||||
Token::UnitVariant { variant: v, .. }
|
|
||||||
| Token::NewtypeVariant { variant: v, .. }
|
|
||||||
| Token::TupleVariant { variant: v, .. }
|
|
||||||
| Token::StructVariant { variant: v, .. } => {
|
|
||||||
let de = v.into_deserializer();
|
|
||||||
let value = seed.deserialize(de)?;
|
|
||||||
Ok((value, self))
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
let value = seed.deserialize(&mut *self.de)?;
|
|
||||||
Ok((value, self))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, 'a> VariantAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn unit_variant(self) -> Result<(), Error> {
|
|
||||||
match self.de.peek_token()? {
|
|
||||||
Token::UnitVariant { .. } => {
|
|
||||||
self.de.next_token()?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
_ => Deserialize::deserialize(self.de),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
|
|
||||||
where
|
|
||||||
T: DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
match self.de.peek_token()? {
|
|
||||||
Token::NewtypeVariant { .. } => {
|
|
||||||
self.de.next_token()?;
|
|
||||||
seed.deserialize(self.de)
|
|
||||||
}
|
|
||||||
_ => seed.deserialize(self.de),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
match self.de.peek_token()? {
|
|
||||||
Token::TupleVariant { len: enum_len, .. } => {
|
|
||||||
let token = self.de.next_token()?;
|
|
||||||
|
|
||||||
if len == enum_len {
|
|
||||||
self.de
|
|
||||||
.visit_seq(Some(len), Token::TupleVariantEnd, visitor)
|
|
||||||
} else {
|
|
||||||
Err(unexpected(token))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Token::Seq {
|
|
||||||
len: Some(enum_len),
|
|
||||||
} => {
|
|
||||||
let token = self.de.next_token()?;
|
|
||||||
|
|
||||||
if len == enum_len {
|
|
||||||
self.de.visit_seq(Some(len), Token::SeqEnd, visitor)
|
|
||||||
} else {
|
|
||||||
Err(unexpected(token))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => de::Deserializer::deserialize_any(self.de, visitor),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn struct_variant<V>(
|
|
||||||
self,
|
|
||||||
fields: &'static [&'static str],
|
|
||||||
visitor: V,
|
|
||||||
) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: Visitor<'de>,
|
|
||||||
{
|
|
||||||
match self.de.peek_token()? {
|
|
||||||
Token::StructVariant { len: enum_len, .. } => {
|
|
||||||
let token = self.de.next_token()?;
|
|
||||||
|
|
||||||
if fields.len() == enum_len {
|
|
||||||
self.de
|
|
||||||
.visit_map(Some(fields.len()), Token::StructVariantEnd, visitor)
|
|
||||||
} else {
|
|
||||||
Err(unexpected(token))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Token::Map {
|
|
||||||
len: Some(enum_len),
|
|
||||||
} => {
|
|
||||||
let token = self.de.next_token()?;
|
|
||||||
|
|
||||||
if fields.len() == enum_len {
|
|
||||||
self.de
|
|
||||||
.visit_map(Some(fields.len()), Token::MapEnd, visitor)
|
|
||||||
} else {
|
|
||||||
Err(unexpected(token))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => de::Deserializer::deserialize_any(self.de, visitor),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
struct EnumMapVisitor<'a, 'de: 'a> {
|
|
||||||
de: &'a mut Deserializer<'de>,
|
|
||||||
variant: Option<Token>,
|
|
||||||
format: EnumFormat,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum EnumFormat {
|
|
||||||
Seq,
|
|
||||||
Map,
|
|
||||||
Any,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'de> EnumMapVisitor<'a, 'de> {
|
|
||||||
fn new(de: &'a mut Deserializer<'de>, variant: Token, format: EnumFormat) -> Self {
|
|
||||||
EnumMapVisitor {
|
|
||||||
de: de,
|
|
||||||
variant: Some(variant),
|
|
||||||
format: format,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, 'a> MapAccess<'de> for EnumMapVisitor<'a, 'de> {
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
|
|
||||||
where
|
|
||||||
K: DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
match self.variant.take() {
|
|
||||||
Some(Token::Str(variant)) => seed.deserialize(variant.into_deserializer()).map(Some),
|
|
||||||
Some(Token::Bytes(variant)) => seed
|
|
||||||
.deserialize(BytesDeserializer { value: variant })
|
|
||||||
.map(Some),
|
|
||||||
Some(Token::U32(variant)) => seed.deserialize(variant.into_deserializer()).map(Some),
|
|
||||||
Some(other) => Err(unexpected(other)),
|
|
||||||
None => Ok(None),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
|
|
||||||
where
|
|
||||||
V: DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
match self.format {
|
|
||||||
EnumFormat::Seq => {
|
|
||||||
let value = {
|
|
||||||
let visitor = DeserializerSeqVisitor {
|
|
||||||
de: self.de,
|
|
||||||
len: None,
|
|
||||||
end: Token::TupleVariantEnd,
|
|
||||||
};
|
|
||||||
seed.deserialize(SeqAccessDeserializer::new(visitor))?
|
|
||||||
};
|
|
||||||
assert_next_token(self.de, Token::TupleVariantEnd)?;
|
|
||||||
Ok(value)
|
|
||||||
}
|
|
||||||
EnumFormat::Map => {
|
|
||||||
let value = {
|
|
||||||
let visitor = DeserializerMapVisitor {
|
|
||||||
de: self.de,
|
|
||||||
len: None,
|
|
||||||
end: Token::StructVariantEnd,
|
|
||||||
};
|
|
||||||
seed.deserialize(MapAccessDeserializer::new(visitor))?
|
|
||||||
};
|
|
||||||
assert_next_token(self.de, Token::StructVariantEnd)?;
|
|
||||||
Ok(value)
|
|
||||||
}
|
|
||||||
EnumFormat::Any => seed.deserialize(&mut *self.de),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct BytesDeserializer {
|
|
||||||
value: &'static [u8],
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de> de::Deserializer<'de> for BytesDeserializer {
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
|
||||||
where
|
|
||||||
V: de::Visitor<'de>,
|
|
||||||
{
|
|
||||||
visitor.visit_bytes(self.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
forward_to_deserialize_any! {
|
|
||||||
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
|
|
||||||
bytes byte_buf option unit unit_struct newtype_struct seq tuple
|
|
||||||
tuple_struct map struct enum identifier ignored_any
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
use std::error;
|
|
||||||
use std::fmt::{self, Display};
|
|
||||||
|
|
||||||
use serde::{de, ser};
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct Error {
|
|
||||||
msg: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ser::Error for Error {
|
|
||||||
fn custom<T: Display>(msg: T) -> Self {
|
|
||||||
Error {
|
|
||||||
msg: msg.to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl de::Error for Error {
|
|
||||||
fn custom<T: Display>(msg: T) -> Self {
|
|
||||||
Error {
|
|
||||||
msg: msg.to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
|
||||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
formatter.write_str(&self.msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl error::Error for Error {
|
|
||||||
fn description(&self) -> &str {
|
|
||||||
&self.msg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialEq<str> for Error {
|
|
||||||
fn eq(&self, other: &str) -> bool {
|
|
||||||
self.msg == other
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,188 +0,0 @@
|
|||||||
//! This crate provides a convenient concise way to write unit tests for
|
|
||||||
//! implementations of [`Serialize`] and [`Deserialize`].
|
|
||||||
//!
|
|
||||||
//! [`Serialize`]: serde::ser::Serialize
|
|
||||||
//! [`Deserialize`]: serde::de::Deserialize
|
|
||||||
//!
|
|
||||||
//! The `Serialize` impl for a value can be characterized by the sequence of
|
|
||||||
//! [`Serializer`] calls that are made in the course of serializing the value,
|
|
||||||
//! so `serde_test` provides a [`Token`] abstraction which corresponds roughly
|
|
||||||
//! to `Serializer` method calls. There is an [`assert_ser_tokens`] function to
|
|
||||||
//! test that a value serializes to a particular sequence of method calls, an
|
|
||||||
//! [`assert_de_tokens`] function to test that a value can be deserialized from
|
|
||||||
//! a particular sequence of method calls, and an [`assert_tokens`] function to
|
|
||||||
//! test both directions. There are also functions to test expected failure
|
|
||||||
//! conditions.
|
|
||||||
//!
|
|
||||||
//! [`Serializer`]: serde::ser::Serializer
|
|
||||||
//!
|
|
||||||
//! Here is an example from the [`linked-hash-map`] crate.
|
|
||||||
//!
|
|
||||||
//! [`linked-hash-map`]: https://github.com/contain-rs/linked-hash-map
|
|
||||||
//!
|
|
||||||
//! ```edition2021
|
|
||||||
//! # const IGNORE: &str = stringify! {
|
|
||||||
//! use linked_hash_map::LinkedHashMap;
|
|
||||||
//! # };
|
|
||||||
//! use serde_test::{assert_tokens, Token};
|
|
||||||
//!
|
|
||||||
//! # use std::fmt;
|
|
||||||
//! # use std::marker::PhantomData;
|
|
||||||
//! #
|
|
||||||
//! # use serde::ser::{Serialize, Serializer, SerializeMap};
|
|
||||||
//! # use serde::de::{Deserialize, Deserializer, Visitor, MapAccess};
|
|
||||||
//! #
|
|
||||||
//! # // Dumb imitation of LinkedHashMap.
|
|
||||||
//! # #[derive(PartialEq, Debug)]
|
|
||||||
//! # struct LinkedHashMap<K, V>(Vec<(K, V)>);
|
|
||||||
//! #
|
|
||||||
//! # impl<K, V> LinkedHashMap<K, V> {
|
|
||||||
//! # fn new() -> Self {
|
|
||||||
//! # LinkedHashMap(Vec::new())
|
|
||||||
//! # }
|
|
||||||
//! #
|
|
||||||
//! # fn insert(&mut self, k: K, v: V) {
|
|
||||||
//! # self.0.push((k, v));
|
|
||||||
//! # }
|
|
||||||
//! # }
|
|
||||||
//! #
|
|
||||||
//! # impl<K, V> Serialize for LinkedHashMap<K, V>
|
|
||||||
//! # where
|
|
||||||
//! # K: Serialize,
|
|
||||||
//! # V: Serialize,
|
|
||||||
//! # {
|
|
||||||
//! # fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
//! # where
|
|
||||||
//! # S: Serializer,
|
|
||||||
//! # {
|
|
||||||
//! # let mut map = serializer.serialize_map(Some(self.0.len()))?;
|
|
||||||
//! # for &(ref k, ref v) in &self.0 {
|
|
||||||
//! # map.serialize_entry(k, v)?;
|
|
||||||
//! # }
|
|
||||||
//! # map.end()
|
|
||||||
//! # }
|
|
||||||
//! # }
|
|
||||||
//! #
|
|
||||||
//! # struct LinkedHashMapVisitor<K, V>(PhantomData<(K, V)>);
|
|
||||||
//! #
|
|
||||||
//! # impl<'de, K, V> Visitor<'de> for LinkedHashMapVisitor<K, V>
|
|
||||||
//! # where
|
|
||||||
//! # K: Deserialize<'de>,
|
|
||||||
//! # V: Deserialize<'de>,
|
|
||||||
//! # {
|
|
||||||
//! # type Value = LinkedHashMap<K, V>;
|
|
||||||
//! #
|
|
||||||
//! # fn expecting(&self, _: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
//! # unimplemented!()
|
|
||||||
//! # }
|
|
||||||
//! #
|
|
||||||
//! # fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
|
|
||||||
//! # where
|
|
||||||
//! # M: MapAccess<'de>,
|
|
||||||
//! # {
|
|
||||||
//! # let mut map = LinkedHashMap::new();
|
|
||||||
//! # while let Some((key, value)) = access.next_entry()? {
|
|
||||||
//! # map.insert(key, value);
|
|
||||||
//! # }
|
|
||||||
//! # Ok(map)
|
|
||||||
//! # }
|
|
||||||
//! # }
|
|
||||||
//! #
|
|
||||||
//! # impl<'de, K, V> Deserialize<'de> for LinkedHashMap<K, V>
|
|
||||||
//! # where
|
|
||||||
//! # K: Deserialize<'de>,
|
|
||||||
//! # V: Deserialize<'de>,
|
|
||||||
//! # {
|
|
||||||
//! # fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
||||||
//! # where
|
|
||||||
//! # D: Deserializer<'de>,
|
|
||||||
//! # {
|
|
||||||
//! # deserializer.deserialize_map(LinkedHashMapVisitor(PhantomData))
|
|
||||||
//! # }
|
|
||||||
//! # }
|
|
||||||
//! #
|
|
||||||
//! #[test]
|
|
||||||
//! # fn not_a_test_ser_de_empty() {}
|
|
||||||
//! fn test_ser_de_empty() {
|
|
||||||
//! let map = LinkedHashMap::<char, u32>::new();
|
|
||||||
//!
|
|
||||||
//! assert_tokens(
|
|
||||||
//! &map,
|
|
||||||
//! &[
|
|
||||||
//! Token::Map { len: Some(0) },
|
|
||||||
//! Token::MapEnd,
|
|
||||||
//! ],
|
|
||||||
//! );
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! #[test]
|
|
||||||
//! # fn not_a_test_ser_de() {}
|
|
||||||
//! fn test_ser_de() {
|
|
||||||
//! let mut map = LinkedHashMap::new();
|
|
||||||
//! map.insert('b', 20);
|
|
||||||
//! map.insert('a', 10);
|
|
||||||
//! map.insert('c', 30);
|
|
||||||
//!
|
|
||||||
//! assert_tokens(
|
|
||||||
//! &map,
|
|
||||||
//! &[
|
|
||||||
//! Token::Map { len: Some(3) },
|
|
||||||
//! Token::Char('b'),
|
|
||||||
//! Token::I32(20),
|
|
||||||
//! Token::Char('a'),
|
|
||||||
//! Token::I32(10),
|
|
||||||
//! Token::Char('c'),
|
|
||||||
//! Token::I32(30),
|
|
||||||
//! Token::MapEnd,
|
|
||||||
//! ],
|
|
||||||
//! );
|
|
||||||
//! }
|
|
||||||
//! #
|
|
||||||
//! # fn main() {
|
|
||||||
//! # test_ser_de_empty();
|
|
||||||
//! # test_ser_de();
|
|
||||||
//! # }
|
|
||||||
//! ```
|
|
||||||
|
|
||||||
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.175")]
|
|
||||||
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
|
|
||||||
// Ignored clippy lints
|
|
||||||
#![cfg_attr(feature = "cargo-clippy", allow(float_cmp, needless_doctest_main))]
|
|
||||||
// Ignored clippy_pedantic lints
|
|
||||||
#![cfg_attr(
|
|
||||||
feature = "cargo-clippy",
|
|
||||||
allow(
|
|
||||||
cloned_instead_of_copied,
|
|
||||||
doc_link_with_quotes, // https://github.com/rust-lang/rust-clippy/issues/8961
|
|
||||||
empty_line_after_outer_attr,
|
|
||||||
manual_assert,
|
|
||||||
missing_docs_in_private_items,
|
|
||||||
missing_panics_doc,
|
|
||||||
module_name_repetitions,
|
|
||||||
must_use_candidate,
|
|
||||||
redundant_field_names,
|
|
||||||
too_many_lines,
|
|
||||||
type_repetition_in_bounds, // https://github.com/rust-lang/rust-clippy/issues/8772
|
|
||||||
use_debug,
|
|
||||||
use_self
|
|
||||||
)
|
|
||||||
)]
|
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate serde;
|
|
||||||
|
|
||||||
mod de;
|
|
||||||
mod error;
|
|
||||||
mod ser;
|
|
||||||
|
|
||||||
mod assert;
|
|
||||||
mod configure;
|
|
||||||
mod token;
|
|
||||||
|
|
||||||
pub use assert::{
|
|
||||||
assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_ser_tokens_error,
|
|
||||||
assert_tokens,
|
|
||||||
};
|
|
||||||
pub use token::Token;
|
|
||||||
|
|
||||||
pub use configure::{Compact, Configure, Readable};
|
|
@ -1,462 +0,0 @@
|
|||||||
use serde::{ser, Serialize};
|
|
||||||
|
|
||||||
use error::Error;
|
|
||||||
use token::Token;
|
|
||||||
|
|
||||||
/// A `Serializer` that ensures that a value serializes to a given list of
|
|
||||||
/// tokens.
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Serializer<'a> {
|
|
||||||
tokens: &'a [Token],
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Serializer<'a> {
|
|
||||||
/// Creates the serializer.
|
|
||||||
pub fn new(tokens: &'a [Token]) -> Self {
|
|
||||||
Serializer { tokens: tokens }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Pulls the next token off of the serializer, ignoring it.
|
|
||||||
fn next_token(&mut self) -> Option<Token> {
|
|
||||||
if let Some((&first, rest)) = self.tokens.split_first() {
|
|
||||||
self.tokens = rest;
|
|
||||||
Some(first)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn remaining(&self) -> usize {
|
|
||||||
self.tokens.len()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! assert_next_token {
|
|
||||||
($ser:expr, $actual:ident) => {{
|
|
||||||
assert_next_token!($ser, stringify!($actual), Token::$actual, true);
|
|
||||||
}};
|
|
||||||
($ser:expr, $actual:ident($v:expr)) => {{
|
|
||||||
assert_next_token!(
|
|
||||||
$ser,
|
|
||||||
format_args!(concat!(stringify!($actual), "({:?})"), $v),
|
|
||||||
Token::$actual(v),
|
|
||||||
v == $v
|
|
||||||
);
|
|
||||||
}};
|
|
||||||
($ser:expr, $actual:ident { $($k:ident),* }) => {{
|
|
||||||
let compare = ($($k,)*);
|
|
||||||
let field_format = || {
|
|
||||||
use std::fmt::Write;
|
|
||||||
let mut buffer = String::new();
|
|
||||||
$(
|
|
||||||
write!(&mut buffer, concat!(stringify!($k), ": {:?}, "), $k).unwrap();
|
|
||||||
)*
|
|
||||||
buffer
|
|
||||||
};
|
|
||||||
assert_next_token!(
|
|
||||||
$ser,
|
|
||||||
format_args!(concat!(stringify!($actual), " {{ {}}}"), field_format()),
|
|
||||||
Token::$actual { $($k),* },
|
|
||||||
($($k,)*) == compare
|
|
||||||
);
|
|
||||||
}};
|
|
||||||
($ser:expr, $actual:expr, $pat:pat, $guard:expr) => {
|
|
||||||
match $ser.next_token() {
|
|
||||||
Some($pat) if $guard => {}
|
|
||||||
Some(expected) => return Err(ser::Error::custom(
|
|
||||||
format!("expected Token::{} but serialized as {}", expected, $actual)
|
|
||||||
)),
|
|
||||||
None => return Err(ser::Error::custom(
|
|
||||||
format!("expected end of tokens, but {} was serialized", $actual)
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'s, 'a> ser::Serializer for &'s mut Serializer<'a> {
|
|
||||||
type Ok = ();
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
type SerializeSeq = Self;
|
|
||||||
type SerializeTuple = Self;
|
|
||||||
type SerializeTupleStruct = Self;
|
|
||||||
type SerializeTupleVariant = Variant<'s, 'a>;
|
|
||||||
type SerializeMap = Self;
|
|
||||||
type SerializeStruct = Self;
|
|
||||||
type SerializeStructVariant = Variant<'s, 'a>;
|
|
||||||
|
|
||||||
fn serialize_bool(self, v: bool) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, Bool(v));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_i8(self, v: i8) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, I8(v));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_i16(self, v: i16) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, I16(v));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_i32(self, v: i32) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, I32(v));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_i64(self, v: i64) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, I64(v));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_u8(self, v: u8) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, U8(v));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_u16(self, v: u16) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, U16(v));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_u32(self, v: u32) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, U32(v));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_u64(self, v: u64) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, U64(v));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_f32(self, v: f32) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, F32(v));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_f64(self, v: f64) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, F64(v));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_char(self, v: char) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, Char(v));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_str(self, v: &str) -> Result<(), Error> {
|
|
||||||
match self.tokens.first() {
|
|
||||||
Some(&Token::BorrowedStr(_)) => assert_next_token!(self, BorrowedStr(v)),
|
|
||||||
Some(&Token::String(_)) => assert_next_token!(self, String(v)),
|
|
||||||
_ => assert_next_token!(self, Str(v)),
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_bytes(self, v: &[u8]) -> Result<(), Self::Error> {
|
|
||||||
match self.tokens.first() {
|
|
||||||
Some(&Token::BorrowedBytes(_)) => assert_next_token!(self, BorrowedBytes(v)),
|
|
||||||
Some(&Token::ByteBuf(_)) => assert_next_token!(self, ByteBuf(v)),
|
|
||||||
_ => assert_next_token!(self, Bytes(v)),
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_unit(self) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, Unit);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_unit_struct(self, name: &'static str) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, UnitStruct { name });
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_unit_variant(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
_variant_index: u32,
|
|
||||||
variant: &'static str,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
if self.tokens.first() == Some(&Token::Enum { name: name }) {
|
|
||||||
self.next_token();
|
|
||||||
assert_next_token!(self, Str(variant));
|
|
||||||
assert_next_token!(self, Unit);
|
|
||||||
} else {
|
|
||||||
assert_next_token!(self, UnitVariant { name, variant });
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_newtype_struct<T: ?Sized>(self, name: &'static str, value: &T) -> Result<(), Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
assert_next_token!(self, NewtypeStruct { name });
|
|
||||||
value.serialize(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_newtype_variant<T: ?Sized>(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
_variant_index: u32,
|
|
||||||
variant: &'static str,
|
|
||||||
value: &T,
|
|
||||||
) -> Result<(), Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
if self.tokens.first() == Some(&Token::Enum { name: name }) {
|
|
||||||
self.next_token();
|
|
||||||
assert_next_token!(self, Str(variant));
|
|
||||||
} else {
|
|
||||||
assert_next_token!(self, NewtypeVariant { name, variant });
|
|
||||||
}
|
|
||||||
value.serialize(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_none(self) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, None);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<(), Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
assert_next_token!(self, Some);
|
|
||||||
value.serialize(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_seq(self, len: Option<usize>) -> Result<Self, Error> {
|
|
||||||
assert_next_token!(self, Seq { len });
|
|
||||||
Ok(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_tuple(self, len: usize) -> Result<Self, Error> {
|
|
||||||
assert_next_token!(self, Tuple { len });
|
|
||||||
Ok(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_tuple_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
|
|
||||||
assert_next_token!(self, TupleStruct { name, len });
|
|
||||||
Ok(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_tuple_variant(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
_variant_index: u32,
|
|
||||||
variant: &'static str,
|
|
||||||
len: usize,
|
|
||||||
) -> Result<Self::SerializeTupleVariant, Error> {
|
|
||||||
if self.tokens.first() == Some(&Token::Enum { name: name }) {
|
|
||||||
self.next_token();
|
|
||||||
assert_next_token!(self, Str(variant));
|
|
||||||
let len = Some(len);
|
|
||||||
assert_next_token!(self, Seq { len });
|
|
||||||
Ok(Variant {
|
|
||||||
ser: self,
|
|
||||||
end: Token::SeqEnd,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
assert_next_token!(self, TupleVariant { name, variant, len });
|
|
||||||
Ok(Variant {
|
|
||||||
ser: self,
|
|
||||||
end: Token::TupleVariantEnd,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_map(self, len: Option<usize>) -> Result<Self, Error> {
|
|
||||||
assert_next_token!(self, Map { len });
|
|
||||||
Ok(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
|
|
||||||
assert_next_token!(self, Struct { name, len });
|
|
||||||
Ok(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_struct_variant(
|
|
||||||
self,
|
|
||||||
name: &'static str,
|
|
||||||
_variant_index: u32,
|
|
||||||
variant: &'static str,
|
|
||||||
len: usize,
|
|
||||||
) -> Result<Self::SerializeStructVariant, Error> {
|
|
||||||
if self.tokens.first() == Some(&Token::Enum { name: name }) {
|
|
||||||
self.next_token();
|
|
||||||
assert_next_token!(self, Str(variant));
|
|
||||||
let len = Some(len);
|
|
||||||
assert_next_token!(self, Map { len });
|
|
||||||
Ok(Variant {
|
|
||||||
ser: self,
|
|
||||||
end: Token::MapEnd,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
assert_next_token!(self, StructVariant { name, variant, len });
|
|
||||||
Ok(Variant {
|
|
||||||
ser: self,
|
|
||||||
end: Token::StructVariantEnd,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_human_readable(&self) -> bool {
|
|
||||||
panic!(
|
|
||||||
"Types which have different human-readable and compact representations \
|
|
||||||
must explicitly mark their test cases with `serde_test::Configure`"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Variant<'s, 'a: 's> {
|
|
||||||
ser: &'s mut Serializer<'a>,
|
|
||||||
end: Token,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'s, 'a> ser::SerializeSeq for &'s mut Serializer<'a> {
|
|
||||||
type Ok = ();
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
value.serialize(&mut **self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end(self) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, SeqEnd);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'s, 'a> ser::SerializeTuple for &'s mut Serializer<'a> {
|
|
||||||
type Ok = ();
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
value.serialize(&mut **self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end(self) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, TupleEnd);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'s, 'a> ser::SerializeTupleStruct for &'s mut Serializer<'a> {
|
|
||||||
type Ok = ();
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
value.serialize(&mut **self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end(self) -> Result<(), Error> {
|
|
||||||
assert_next_token!(self, TupleStructEnd);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'s, 'a> ser::SerializeTupleVariant for Variant<'s, 'a> {
|
|
||||||
type Ok = ();
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
value.serialize(&mut *self.ser)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end(self) -> Result<(), Error> {
|
|
||||||
match self.end {
|
|
||||||
Token::TupleVariantEnd => assert_next_token!(self.ser, TupleVariantEnd),
|
|
||||||
Token::SeqEnd => assert_next_token!(self.ser, SeqEnd),
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'s, 'a> ser::SerializeMap for &'s mut Serializer<'a> {
|
|
||||||
type Ok = ();
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
key.serialize(&mut **self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
value.serialize(&mut **self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end(self) -> Result<(), Self::Error> {
|
|
||||||
assert_next_token!(self, MapEnd);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'s, 'a> ser::SerializeStruct for &'s mut Serializer<'a> {
|
|
||||||
type Ok = ();
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn serialize_field<T: ?Sized>(
|
|
||||||
&mut self,
|
|
||||||
key: &'static str,
|
|
||||||
value: &T,
|
|
||||||
) -> Result<(), Self::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
key.serialize(&mut **self)?;
|
|
||||||
value.serialize(&mut **self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end(self) -> Result<(), Self::Error> {
|
|
||||||
assert_next_token!(self, StructEnd);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'s, 'a> ser::SerializeStructVariant for Variant<'s, 'a> {
|
|
||||||
type Ok = ();
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn serialize_field<T: ?Sized>(
|
|
||||||
&mut self,
|
|
||||||
key: &'static str,
|
|
||||||
value: &T,
|
|
||||||
) -> Result<(), Self::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
{
|
|
||||||
key.serialize(&mut *self.ser)?;
|
|
||||||
value.serialize(&mut *self.ser)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end(self) -> Result<(), Self::Error> {
|
|
||||||
match self.end {
|
|
||||||
Token::StructVariantEnd => assert_next_token!(self.ser, StructVariantEnd),
|
|
||||||
Token::MapEnd => assert_next_token!(self.ser, MapEnd),
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,561 +0,0 @@
|
|||||||
use std::fmt::{self, Debug, Display};
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
|
||||||
pub enum Token {
|
|
||||||
/// A serialized `bool`.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// assert_tokens(&true, &[Token::Bool(true)]);
|
|
||||||
/// ```
|
|
||||||
Bool(bool),
|
|
||||||
|
|
||||||
/// A serialized `i8`.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// assert_tokens(&0i8, &[Token::I8(0)]);
|
|
||||||
/// ```
|
|
||||||
I8(i8),
|
|
||||||
|
|
||||||
/// A serialized `i16`.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// assert_tokens(&0i16, &[Token::I16(0)]);
|
|
||||||
/// ```
|
|
||||||
I16(i16),
|
|
||||||
|
|
||||||
/// A serialized `i32`.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// assert_tokens(&0i32, &[Token::I32(0)]);
|
|
||||||
/// ```
|
|
||||||
I32(i32),
|
|
||||||
|
|
||||||
/// A serialized `i64`.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// assert_tokens(&0i64, &[Token::I64(0)]);
|
|
||||||
/// ```
|
|
||||||
I64(i64),
|
|
||||||
|
|
||||||
/// A serialized `u8`.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// assert_tokens(&0u8, &[Token::U8(0)]);
|
|
||||||
/// ```
|
|
||||||
U8(u8),
|
|
||||||
|
|
||||||
/// A serialized `u16`.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// assert_tokens(&0u16, &[Token::U16(0)]);
|
|
||||||
/// ```
|
|
||||||
U16(u16),
|
|
||||||
|
|
||||||
/// A serialized `u32`.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// assert_tokens(&0u32, &[Token::U32(0)]);
|
|
||||||
/// ```
|
|
||||||
U32(u32),
|
|
||||||
|
|
||||||
/// A serialized `u64`.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// assert_tokens(&0u64, &[Token::U64(0)]);
|
|
||||||
/// ```
|
|
||||||
U64(u64),
|
|
||||||
|
|
||||||
/// A serialized `f32`.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// assert_tokens(&0f32, &[Token::F32(0.0)]);
|
|
||||||
/// ```
|
|
||||||
F32(f32),
|
|
||||||
|
|
||||||
/// A serialized `f64`.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// assert_tokens(&0f64, &[Token::F64(0.0)]);
|
|
||||||
/// ```
|
|
||||||
F64(f64),
|
|
||||||
|
|
||||||
/// A serialized `char`.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// assert_tokens(&'\n', &[Token::Char('\n')]);
|
|
||||||
/// ```
|
|
||||||
Char(char),
|
|
||||||
|
|
||||||
/// A serialized `str`.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// let s = String::from("transient");
|
|
||||||
/// assert_tokens(&s, &[Token::Str("transient")]);
|
|
||||||
/// ```
|
|
||||||
Str(&'static str),
|
|
||||||
|
|
||||||
/// A borrowed `str`.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// let s: &str = "borrowed";
|
|
||||||
/// assert_tokens(&s, &[Token::BorrowedStr("borrowed")]);
|
|
||||||
/// ```
|
|
||||||
BorrowedStr(&'static str),
|
|
||||||
|
|
||||||
/// A serialized `String`.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// let s = String::from("owned");
|
|
||||||
/// assert_tokens(&s, &[Token::String("owned")]);
|
|
||||||
/// ```
|
|
||||||
String(&'static str),
|
|
||||||
|
|
||||||
/// A serialized `[u8]`
|
|
||||||
Bytes(&'static [u8]),
|
|
||||||
|
|
||||||
/// A borrowed `[u8]`.
|
|
||||||
BorrowedBytes(&'static [u8]),
|
|
||||||
|
|
||||||
/// A serialized `ByteBuf`
|
|
||||||
ByteBuf(&'static [u8]),
|
|
||||||
|
|
||||||
/// A serialized `Option<T>` containing none.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// let opt = None::<char>;
|
|
||||||
/// assert_tokens(&opt, &[Token::None]);
|
|
||||||
/// ```
|
|
||||||
None,
|
|
||||||
|
|
||||||
/// The header to a serialized `Option<T>` containing some value.
|
|
||||||
///
|
|
||||||
/// The tokens of the value follow after this header.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// let opt = Some('c');
|
|
||||||
/// assert_tokens(&opt, &[Token::Some, Token::Char('c')]);
|
|
||||||
/// ```
|
|
||||||
Some,
|
|
||||||
|
|
||||||
/// A serialized `()`.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// assert_tokens(&(), &[Token::Unit]);
|
|
||||||
/// ```
|
|
||||||
Unit,
|
|
||||||
|
|
||||||
/// A serialized unit struct of the given name.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_derive::{Deserialize, Serialize};
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// # fn main() {
|
|
||||||
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
/// struct X;
|
|
||||||
///
|
|
||||||
/// assert_tokens(&X, &[Token::UnitStruct { name: "X" }]);
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
UnitStruct { name: &'static str },
|
|
||||||
|
|
||||||
/// A unit variant of an enum.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_derive::{Deserialize, Serialize};
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// # fn main() {
|
|
||||||
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
/// enum E {
|
|
||||||
/// A,
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// let a = E::A;
|
|
||||||
/// assert_tokens(
|
|
||||||
/// &a,
|
|
||||||
/// &[Token::UnitVariant {
|
|
||||||
/// name: "E",
|
|
||||||
/// variant: "A",
|
|
||||||
/// }],
|
|
||||||
/// );
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
UnitVariant {
|
|
||||||
name: &'static str,
|
|
||||||
variant: &'static str,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// The header to a serialized newtype struct of the given name.
|
|
||||||
///
|
|
||||||
/// After this header is the value contained in the newtype struct.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_derive::{Deserialize, Serialize};
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// # fn main() {
|
|
||||||
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
/// struct N(String);
|
|
||||||
///
|
|
||||||
/// let n = N("newtype".to_owned());
|
|
||||||
/// assert_tokens(
|
|
||||||
/// &n,
|
|
||||||
/// &[Token::NewtypeStruct { name: "N" }, Token::String("newtype")],
|
|
||||||
/// );
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
NewtypeStruct { name: &'static str },
|
|
||||||
|
|
||||||
/// The header to a newtype variant of an enum.
|
|
||||||
///
|
|
||||||
/// After this header is the value contained in the newtype variant.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_derive::{Deserialize, Serialize};
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// # fn main() {
|
|
||||||
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
/// enum E {
|
|
||||||
/// B(u8),
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// let b = E::B(0);
|
|
||||||
/// assert_tokens(
|
|
||||||
/// &b,
|
|
||||||
/// &[
|
|
||||||
/// Token::NewtypeVariant {
|
|
||||||
/// name: "E",
|
|
||||||
/// variant: "B",
|
|
||||||
/// },
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// ],
|
|
||||||
/// );
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
NewtypeVariant {
|
|
||||||
name: &'static str,
|
|
||||||
variant: &'static str,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// The header to a sequence.
|
|
||||||
///
|
|
||||||
/// After this header are the elements of the sequence, followed by
|
|
||||||
/// `SeqEnd`.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// let vec = vec!['a', 'b', 'c'];
|
|
||||||
/// assert_tokens(
|
|
||||||
/// &vec,
|
|
||||||
/// &[
|
|
||||||
/// Token::Seq { len: Some(3) },
|
|
||||||
/// Token::Char('a'),
|
|
||||||
/// Token::Char('b'),
|
|
||||||
/// Token::Char('c'),
|
|
||||||
/// Token::SeqEnd,
|
|
||||||
/// ],
|
|
||||||
/// );
|
|
||||||
/// ```
|
|
||||||
Seq { len: Option<usize> },
|
|
||||||
|
|
||||||
/// An indicator of the end of a sequence.
|
|
||||||
SeqEnd,
|
|
||||||
|
|
||||||
/// The header to a tuple.
|
|
||||||
///
|
|
||||||
/// After this header are the elements of the tuple, followed by `TupleEnd`.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// let tuple = ('a', 100);
|
|
||||||
/// assert_tokens(
|
|
||||||
/// &tuple,
|
|
||||||
/// &[
|
|
||||||
/// Token::Tuple { len: 2 },
|
|
||||||
/// Token::Char('a'),
|
|
||||||
/// Token::I32(100),
|
|
||||||
/// Token::TupleEnd,
|
|
||||||
/// ],
|
|
||||||
/// );
|
|
||||||
/// ```
|
|
||||||
Tuple { len: usize },
|
|
||||||
|
|
||||||
/// An indicator of the end of a tuple.
|
|
||||||
TupleEnd,
|
|
||||||
|
|
||||||
/// The header to a tuple struct.
|
|
||||||
///
|
|
||||||
/// After this header are the fields of the tuple struct, followed by
|
|
||||||
/// `TupleStructEnd`.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_derive::{Deserialize, Serialize};
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// # fn main() {
|
|
||||||
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
/// struct T(u8, u8);
|
|
||||||
///
|
|
||||||
/// let t = T(0, 0);
|
|
||||||
/// assert_tokens(
|
|
||||||
/// &t,
|
|
||||||
/// &[
|
|
||||||
/// Token::TupleStruct { name: "T", len: 2 },
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::TupleStructEnd,
|
|
||||||
/// ],
|
|
||||||
/// );
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
TupleStruct { name: &'static str, len: usize },
|
|
||||||
|
|
||||||
/// An indicator of the end of a tuple struct.
|
|
||||||
TupleStructEnd,
|
|
||||||
|
|
||||||
/// The header to a tuple variant of an enum.
|
|
||||||
///
|
|
||||||
/// After this header are the fields of the tuple variant, followed by
|
|
||||||
/// `TupleVariantEnd`.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_derive::{Deserialize, Serialize};
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// # fn main() {
|
|
||||||
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
/// enum E {
|
|
||||||
/// C(u8, u8),
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// let c = E::C(0, 0);
|
|
||||||
/// assert_tokens(
|
|
||||||
/// &c,
|
|
||||||
/// &[
|
|
||||||
/// Token::TupleVariant {
|
|
||||||
/// name: "E",
|
|
||||||
/// variant: "C",
|
|
||||||
/// len: 2,
|
|
||||||
/// },
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::TupleVariantEnd,
|
|
||||||
/// ],
|
|
||||||
/// );
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
TupleVariant {
|
|
||||||
name: &'static str,
|
|
||||||
variant: &'static str,
|
|
||||||
len: usize,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// An indicator of the end of a tuple variant.
|
|
||||||
TupleVariantEnd,
|
|
||||||
|
|
||||||
/// The header to a map.
|
|
||||||
///
|
|
||||||
/// After this header are the entries of the map, followed by `MapEnd`.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// use std::collections::BTreeMap;
|
|
||||||
///
|
|
||||||
/// let mut map = BTreeMap::new();
|
|
||||||
/// map.insert('A', 65);
|
|
||||||
/// map.insert('Z', 90);
|
|
||||||
///
|
|
||||||
/// assert_tokens(
|
|
||||||
/// &map,
|
|
||||||
/// &[
|
|
||||||
/// Token::Map { len: Some(2) },
|
|
||||||
/// Token::Char('A'),
|
|
||||||
/// Token::I32(65),
|
|
||||||
/// Token::Char('Z'),
|
|
||||||
/// Token::I32(90),
|
|
||||||
/// Token::MapEnd,
|
|
||||||
/// ],
|
|
||||||
/// );
|
|
||||||
/// ```
|
|
||||||
Map { len: Option<usize> },
|
|
||||||
|
|
||||||
/// An indicator of the end of a map.
|
|
||||||
MapEnd,
|
|
||||||
|
|
||||||
/// The header of a struct.
|
|
||||||
///
|
|
||||||
/// After this header are the fields of the struct, followed by `StructEnd`.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_derive::{Deserialize, Serialize};
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// # fn main() {
|
|
||||||
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
/// struct S {
|
|
||||||
/// a: u8,
|
|
||||||
/// b: u8,
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// let s = S { a: 0, b: 0 };
|
|
||||||
/// assert_tokens(
|
|
||||||
/// &s,
|
|
||||||
/// &[
|
|
||||||
/// Token::Struct { name: "S", len: 2 },
|
|
||||||
/// Token::Str("a"),
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::Str("b"),
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::StructEnd,
|
|
||||||
/// ],
|
|
||||||
/// );
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
Struct { name: &'static str, len: usize },
|
|
||||||
|
|
||||||
/// An indicator of the end of a struct.
|
|
||||||
StructEnd,
|
|
||||||
|
|
||||||
/// The header of a struct variant of an enum.
|
|
||||||
///
|
|
||||||
/// After this header are the fields of the struct variant, followed by
|
|
||||||
/// `StructVariantEnd`.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_derive::{Deserialize, Serialize};
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// # fn main() {
|
|
||||||
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
/// enum E {
|
|
||||||
/// D { d: u8 },
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// let d = E::D { d: 0 };
|
|
||||||
/// assert_tokens(
|
|
||||||
/// &d,
|
|
||||||
/// &[
|
|
||||||
/// Token::StructVariant {
|
|
||||||
/// name: "E",
|
|
||||||
/// variant: "D",
|
|
||||||
/// len: 1,
|
|
||||||
/// },
|
|
||||||
/// Token::Str("d"),
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::StructVariantEnd,
|
|
||||||
/// ],
|
|
||||||
/// );
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
StructVariant {
|
|
||||||
name: &'static str,
|
|
||||||
variant: &'static str,
|
|
||||||
len: usize,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// An indicator of the end of a struct variant.
|
|
||||||
StructVariantEnd,
|
|
||||||
|
|
||||||
/// The header to an enum of the given name.
|
|
||||||
///
|
|
||||||
/// ```edition2021
|
|
||||||
/// # use serde_derive::{Deserialize, Serialize};
|
|
||||||
/// # use serde_test::{assert_tokens, Token};
|
|
||||||
/// #
|
|
||||||
/// # fn main() {
|
|
||||||
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
/// enum E {
|
|
||||||
/// A,
|
|
||||||
/// B(u8),
|
|
||||||
/// C(u8, u8),
|
|
||||||
/// D { d: u8 },
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// let a = E::A;
|
|
||||||
/// assert_tokens(
|
|
||||||
/// &a,
|
|
||||||
/// &[Token::Enum { name: "E" }, Token::Str("A"), Token::Unit],
|
|
||||||
/// );
|
|
||||||
///
|
|
||||||
/// let b = E::B(0);
|
|
||||||
/// assert_tokens(
|
|
||||||
/// &b,
|
|
||||||
/// &[Token::Enum { name: "E" }, Token::Str("B"), Token::U8(0)],
|
|
||||||
/// );
|
|
||||||
///
|
|
||||||
/// let c = E::C(0, 0);
|
|
||||||
/// assert_tokens(
|
|
||||||
/// &c,
|
|
||||||
/// &[
|
|
||||||
/// Token::Enum { name: "E" },
|
|
||||||
/// Token::Str("C"),
|
|
||||||
/// Token::Seq { len: Some(2) },
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::SeqEnd,
|
|
||||||
/// ],
|
|
||||||
/// );
|
|
||||||
///
|
|
||||||
/// let d = E::D { d: 0 };
|
|
||||||
/// assert_tokens(
|
|
||||||
/// &d,
|
|
||||||
/// &[
|
|
||||||
/// Token::Enum { name: "E" },
|
|
||||||
/// Token::Str("D"),
|
|
||||||
/// Token::Map { len: Some(1) },
|
|
||||||
/// Token::Str("d"),
|
|
||||||
/// Token::U8(0),
|
|
||||||
/// Token::MapEnd,
|
|
||||||
/// ],
|
|
||||||
/// );
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
Enum { name: &'static str },
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for Token {
|
|
||||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
Debug::fmt(self, formatter)
|
|
||||||
}
|
|
||||||
}
|
|
@ -17,5 +17,5 @@ fnv = "1.0"
|
|||||||
rustversion = "1.0"
|
rustversion = "1.0"
|
||||||
serde = { path = "../serde", features = ["rc"] }
|
serde = { path = "../serde", features = ["rc"] }
|
||||||
serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] }
|
serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] }
|
||||||
serde_test = { path = "../serde_test" }
|
serde_test = "1.0.176"
|
||||||
trybuild = { version = "1.0.66", features = ["diff"] }
|
trybuild = { version = "1.0.66", features = ["diff"] }
|
||||||
|
Loading…
Reference in New Issue
Block a user