mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-04-23 09:28:04 +00:00
Compare commits
43 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f218f4d7bf | |||
| 8c0a2015be | |||
| 4773863e3a | |||
| 80cd9c7617 | |||
| 436cafb0a3 | |||
| 98bb02e9b4 | |||
| 142439088c | |||
| ce81288235 | |||
| 88d5fe6bfd | |||
| 9a2c352025 | |||
| 61c90cb8cb | |||
| 66e8b0a0cd | |||
| 9e7a3437d9 | |||
| 7ac8d4f9ae | |||
| 501bae42f5 | |||
| 7a0397451e | |||
| 16787318d1 | |||
| f4ae0888c8 | |||
| 213071fe5c | |||
| cfd26c6fda | |||
| 23fa83941e | |||
| 88f5b9511d | |||
| d537f1e1f0 | |||
| f6ac232580 | |||
| aad7a7987f | |||
| b24ad76880 | |||
| 5796f1a0f5 | |||
| 6437167930 | |||
| f98daaa250 | |||
| b8a40551a2 | |||
| 40db31691a | |||
| ab68132b1f | |||
| e70bbd9dde | |||
| d5e5c520ac | |||
| 1b9a096fa7 | |||
| 39e05ffad2 | |||
| 78fab25c5c | |||
| 2a557a1e36 | |||
| ab0848f780 | |||
| 2b1303f59c | |||
| 7f9ba155cb | |||
| a4e0c2f055 | |||
| 3bbf70575b |
@@ -20,9 +20,30 @@ You may be looking for:
|
||||
|
||||
## Serde in action
|
||||
|
||||
<a href="http://play.integer32.com/?gist=9003c5b88c1f4989941925d7190c6eec" target="_blank">
|
||||
<img align="right" width="50" src="https://raw.githubusercontent.com/serde-rs/serde-rs.github.io/master/img/run.png">
|
||||
</a>
|
||||
<details>
|
||||
<summary>
|
||||
Click to show Cargo.toml.
|
||||
<a href="http://play.integer32.com/?gist=9003c5b88c1f4989941925d7190c6eec" target="_blank">Run this code in the playground.</a>
|
||||
</summary>
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
|
||||
# The core APIs, including the Serialize and Deserialize traits. Always
|
||||
# required when using Serde.
|
||||
serde = "1.0"
|
||||
|
||||
# Support for #[derive(Serialize, Deserialize)]. Required if you want Serde
|
||||
# to work for structs and enums defined in your crate.
|
||||
serde_derive = "1.0"
|
||||
|
||||
# Each data format lives in its own crate; the sample code below uses JSON
|
||||
# but you may be using a different one.
|
||||
serde_json = "1.0"
|
||||
```
|
||||
|
||||
</details>
|
||||
<p></p>
|
||||
|
||||
```rust
|
||||
#[macro_use]
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde"
|
||||
version = "1.0.17" # remember to update html_root_url
|
||||
version = "1.0.21" # remember to update html_root_url
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
license = "MIT/Apache-2.0"
|
||||
description = "A generic serialization/deserialization framework"
|
||||
|
||||
+3
-1
@@ -79,7 +79,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Serde types in rustdoc of other crates get linked to here.
|
||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.17")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.21")]
|
||||
|
||||
// Support using Serde without the standard library!
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
@@ -95,8 +95,10 @@
|
||||
// Whitelisted clippy lints
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(
|
||||
cast_lossless,
|
||||
const_static_lifetime,
|
||||
doc_markdown,
|
||||
linkedlist,
|
||||
needless_pass_by_value,
|
||||
type_complexity,
|
||||
unreadable_literal,
|
||||
zero_prefixed_literal,
|
||||
|
||||
+36
-2
@@ -1114,10 +1114,38 @@ mod content {
|
||||
)
|
||||
}
|
||||
|
||||
fn deserialize_unit_struct<V>(
|
||||
self,
|
||||
_name: &'static str,
|
||||
visitor: V
|
||||
) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
match self.content {
|
||||
// As a special case, allow deserializing untagged newtype
|
||||
// variant containing unit struct.
|
||||
//
|
||||
// #[derive(Deserialize)]
|
||||
// struct Info;
|
||||
//
|
||||
// #[derive(Deserialize)]
|
||||
// #[serde(tag = "topic")]
|
||||
// enum Message {
|
||||
// Info(Info),
|
||||
// }
|
||||
//
|
||||
// We want {"topic":"Info"} to deserialize even though
|
||||
// ordinarily unit structs do not deserialize from empty map.
|
||||
Content::Map(ref v) if v.is_empty() => visitor.visit_unit(),
|
||||
_ => self.deserialize_any(visitor),
|
||||
}
|
||||
}
|
||||
|
||||
forward_to_deserialize_any! {
|
||||
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
|
||||
byte_buf unit unit_struct seq tuple tuple_struct map struct
|
||||
identifier ignored_any
|
||||
byte_buf unit seq tuple tuple_struct map struct identifier
|
||||
ignored_any
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1218,6 +1246,9 @@ mod content {
|
||||
Some(Content::Map(v)) => {
|
||||
de::Deserializer::deserialize_any(MapDeserializer::new(v), visitor)
|
||||
}
|
||||
Some(Content::Seq(v)) => {
|
||||
de::Deserializer::deserialize_any(SeqDeserializer::new(v), visitor)
|
||||
}
|
||||
Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"struct variant"),),
|
||||
_ => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"struct variant"),),
|
||||
}
|
||||
@@ -1612,6 +1643,9 @@ mod content {
|
||||
Some(&Content::Map(ref v)) => {
|
||||
de::Deserializer::deserialize_any(MapRefDeserializer::new(v), visitor)
|
||||
}
|
||||
Some(&Content::Seq(ref v)) => {
|
||||
de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor)
|
||||
}
|
||||
Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"struct variant"),),
|
||||
_ => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"struct variant"),),
|
||||
}
|
||||
|
||||
@@ -60,7 +60,6 @@ enum Unsupported {
|
||||
ByteArray,
|
||||
Optional,
|
||||
Unit,
|
||||
UnitStruct,
|
||||
Sequence,
|
||||
Tuple,
|
||||
TupleStruct,
|
||||
@@ -79,7 +78,6 @@ impl Display for Unsupported {
|
||||
Unsupported::ByteArray => formatter.write_str("a byte array"),
|
||||
Unsupported::Optional => formatter.write_str("an optional"),
|
||||
Unsupported::Unit => formatter.write_str("unit"),
|
||||
Unsupported::UnitStruct => formatter.write_str("a unit struct"),
|
||||
Unsupported::Sequence => formatter.write_str("a sequence"),
|
||||
Unsupported::Tuple => formatter.write_str("a tuple"),
|
||||
Unsupported::TupleStruct => formatter.write_str("a tuple struct"),
|
||||
@@ -199,7 +197,9 @@ where
|
||||
}
|
||||
|
||||
fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
|
||||
Err(self.bad_type(Unsupported::UnitStruct))
|
||||
let mut map = try!(self.delegate.serialize_map(Some(1)));
|
||||
try!(map.serialize_entry(self.tag, self.variant_name));
|
||||
map.end()
|
||||
}
|
||||
|
||||
fn serialize_unit_variant(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde_derive"
|
||||
version = "1.0.17" # remember to update html_root_url
|
||||
version = "1.0.21" # remember to update html_root_url
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
license = "MIT/Apache-2.0"
|
||||
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
||||
@@ -20,7 +20,7 @@ proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
quote = "0.3.8"
|
||||
serde_derive_internals = { version = "=0.16.0", default-features = false, path = "../serde_derive_internals" }
|
||||
serde_derive_internals = { version = "=0.17.0", default-features = false, path = "../serde_derive_internals" }
|
||||
syn = { version = "0.11", features = ["visit"] }
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
@@ -116,6 +116,14 @@ where
|
||||
}
|
||||
visit::walk_path(self, path);
|
||||
}
|
||||
|
||||
// Type parameter should not be considered used by a macro path.
|
||||
//
|
||||
// struct TypeMacro<T> {
|
||||
// mac: T!(),
|
||||
// marker: PhantomData<T>,
|
||||
// }
|
||||
fn visit_mac(&mut self, _mac: &syn::Mac) {}
|
||||
}
|
||||
|
||||
let all_ty_params: HashSet<_> = generics
|
||||
|
||||
@@ -203,7 +203,9 @@ impl BorrowedLifetimes {
|
||||
fn borrowed_lifetimes(cont: &Container) -> BorrowedLifetimes {
|
||||
let mut lifetimes = BTreeSet::new();
|
||||
for field in cont.body.all_fields() {
|
||||
lifetimes.extend(field.attrs.borrowed_lifetimes().iter().cloned());
|
||||
if !field.attrs.skip_deserializing() {
|
||||
lifetimes.extend(field.attrs.borrowed_lifetimes().iter().cloned());
|
||||
}
|
||||
}
|
||||
if lifetimes.iter().any(|b| b.ident == "'static") {
|
||||
BorrowedLifetimes::Static
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
//!
|
||||
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.17")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.21")]
|
||||
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(used_underscore_binding))]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde_derive_internals"
|
||||
version = "0.16.0" # remember to update html_root_url
|
||||
version = "0.17.0" # remember to update html_root_url
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
license = "MIT/Apache-2.0"
|
||||
description = "AST representation used by Serde derive macros. Unstable."
|
||||
|
||||
@@ -51,7 +51,7 @@ impl<'a> Container<'a> {
|
||||
let mut body = match item.body {
|
||||
syn::Body::Enum(ref variants) => Body::Enum(enum_from_ast(cx, variants)),
|
||||
syn::Body::Struct(ref variant_data) => {
|
||||
let (style, fields) = struct_from_ast(cx, variant_data);
|
||||
let (style, fields) = struct_from_ast(cx, variant_data, None);
|
||||
Body::Struct(style, fields)
|
||||
}
|
||||
};
|
||||
@@ -103,10 +103,11 @@ fn enum_from_ast<'a>(cx: &Ctxt, variants: &'a [syn::Variant]) -> Vec<Variant<'a>
|
||||
.iter()
|
||||
.map(
|
||||
|variant| {
|
||||
let (style, fields) = struct_from_ast(cx, &variant.data);
|
||||
let attrs = attr::Variant::from_ast(cx, variant);
|
||||
let (style, fields) = struct_from_ast(cx, &variant.data, Some(&attrs));
|
||||
Variant {
|
||||
ident: variant.ident.clone(),
|
||||
attrs: attr::Variant::from_ast(cx, variant),
|
||||
attrs: attrs,
|
||||
style: style,
|
||||
fields: fields,
|
||||
}
|
||||
@@ -115,18 +116,18 @@ fn enum_from_ast<'a>(cx: &Ctxt, variants: &'a [syn::Variant]) -> Vec<Variant<'a>
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn struct_from_ast<'a>(cx: &Ctxt, data: &'a syn::VariantData) -> (Style, Vec<Field<'a>>) {
|
||||
fn struct_from_ast<'a>(cx: &Ctxt, data: &'a syn::VariantData, attrs: Option<&attr::Variant>) -> (Style, Vec<Field<'a>>) {
|
||||
match *data {
|
||||
syn::VariantData::Struct(ref fields) => (Style::Struct, fields_from_ast(cx, fields)),
|
||||
syn::VariantData::Struct(ref fields) => (Style::Struct, fields_from_ast(cx, fields, attrs)),
|
||||
syn::VariantData::Tuple(ref fields) if fields.len() == 1 => {
|
||||
(Style::Newtype, fields_from_ast(cx, fields))
|
||||
(Style::Newtype, fields_from_ast(cx, fields, attrs))
|
||||
}
|
||||
syn::VariantData::Tuple(ref fields) => (Style::Tuple, fields_from_ast(cx, fields)),
|
||||
syn::VariantData::Tuple(ref fields) => (Style::Tuple, fields_from_ast(cx, fields, attrs)),
|
||||
syn::VariantData::Unit => (Style::Unit, Vec::new()),
|
||||
}
|
||||
}
|
||||
|
||||
fn fields_from_ast<'a>(cx: &Ctxt, fields: &'a [syn::Field]) -> Vec<Field<'a>> {
|
||||
fn fields_from_ast<'a>(cx: &Ctxt, fields: &'a [syn::Field], attrs: Option<&attr::Variant>) -> Vec<Field<'a>> {
|
||||
fields
|
||||
.iter()
|
||||
.enumerate()
|
||||
@@ -134,7 +135,7 @@ fn fields_from_ast<'a>(cx: &Ctxt, fields: &'a [syn::Field]) -> Vec<Field<'a>> {
|
||||
|(i, field)| {
|
||||
Field {
|
||||
ident: field.ident.clone(),
|
||||
attrs: attr::Field::from_ast(cx, i, field),
|
||||
attrs: attr::Field::from_ast(cx, i, field, attrs),
|
||||
ty: &field.ty,
|
||||
}
|
||||
},
|
||||
|
||||
@@ -512,6 +512,7 @@ pub struct Variant {
|
||||
other: bool,
|
||||
serialize_with: Option<syn::Path>,
|
||||
deserialize_with: Option<syn::Path>,
|
||||
borrow: Option<syn::MetaItem>,
|
||||
}
|
||||
|
||||
impl Variant {
|
||||
@@ -524,6 +525,7 @@ impl Variant {
|
||||
let mut other = BoolAttr::none(cx, "other");
|
||||
let mut serialize_with = Attr::none(cx, "serialize_with");
|
||||
let mut deserialize_with = Attr::none(cx, "deserialize_with");
|
||||
let mut borrow = Attr::none(cx, "borrow");
|
||||
|
||||
for meta_items in variant.attrs.iter().filter_map(get_serde_meta_items) {
|
||||
for meta_item in meta_items {
|
||||
@@ -599,6 +601,18 @@ impl Variant {
|
||||
}
|
||||
}
|
||||
|
||||
// Defer `#[serde(borrow)]` and `#[serde(borrow = "'a + 'b")]`
|
||||
MetaItem(ref mi) if mi.name() == "borrow" => {
|
||||
match variant.data {
|
||||
syn::VariantData::Tuple(ref fields) if fields.len() == 1 => {
|
||||
borrow.set(mi.clone());
|
||||
}
|
||||
_ => {
|
||||
cx.error("#[serde(borrow)] may only be used on newtype variants");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MetaItem(ref meta_item) => {
|
||||
cx.error(format!("unknown serde variant attribute `{}`", meta_item.name()));
|
||||
}
|
||||
@@ -627,6 +641,7 @@ impl Variant {
|
||||
other: other.get(),
|
||||
serialize_with: serialize_with.get(),
|
||||
deserialize_with: deserialize_with.get(),
|
||||
borrow: borrow.get(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -699,7 +714,7 @@ pub enum Default {
|
||||
|
||||
impl Field {
|
||||
/// Extract out the `#[serde(...)]` attributes from a struct field.
|
||||
pub fn from_ast(cx: &Ctxt, index: usize, field: &syn::Field) -> Self {
|
||||
pub fn from_ast(cx: &Ctxt, index: usize, field: &syn::Field, attrs: Option<&Variant>) -> Self {
|
||||
let mut ser_name = Attr::none(cx, "rename");
|
||||
let mut de_name = Attr::none(cx, "rename");
|
||||
let mut skip_serializing = BoolAttr::none(cx, "skip_serializing");
|
||||
@@ -718,7 +733,13 @@ impl Field {
|
||||
None => index.to_string(),
|
||||
};
|
||||
|
||||
for meta_items in field.attrs.iter().filter_map(get_serde_meta_items) {
|
||||
let variant_borrow = attrs
|
||||
.map(|variant| &variant.borrow)
|
||||
.unwrap_or(&None)
|
||||
.as_ref()
|
||||
.map(|borrow| vec![MetaItem(borrow.clone())]);
|
||||
|
||||
for meta_items in field.attrs.iter().filter_map(get_serde_meta_items).chain(variant_borrow) {
|
||||
for meta_item in meta_items {
|
||||
match meta_item {
|
||||
// Parse `#[serde(rename = "foo")]`
|
||||
|
||||
@@ -6,7 +6,10 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// See https://users.rust-lang.org/t/psa-dealing-with-warning-unused-import-std-ascii-asciiext-in-today-s-nightly/13726
|
||||
#[allow(unused_imports)]
|
||||
use std::ascii::AsciiExt;
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
use self::RenameRule::*;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.16.0")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.17.0")]
|
||||
|
||||
extern crate syn;
|
||||
#[macro_use]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde_test"
|
||||
version = "1.0.17" # remember to update html_root_url
|
||||
version = "1.0.21" # remember to update html_root_url
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
license = "MIT/Apache-2.0"
|
||||
description = "Token De/Serializer for testing De/Serialize implementations"
|
||||
@@ -12,10 +12,10 @@ readme = "README.md"
|
||||
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1.0", path = "../serde" }
|
||||
serde = { version = "1.0.16", path = "../serde" }
|
||||
|
||||
[dev-dependencies]
|
||||
serde = { version = "1.0", path = "../serde", features = ["rc"] }
|
||||
serde = { version = "1.0.16", path = "../serde", features = ["rc"] }
|
||||
serde_derive = { version = "1.0", path = "../serde_derive" }
|
||||
|
||||
[badges]
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use serde::{Serialize, Deserialize};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use de::Deserializer;
|
||||
use ser::Serializer;
|
||||
@@ -47,20 +47,8 @@ pub fn assert_tokens<'de, T>(value: &T, tokens: &'de [Token])
|
||||
where
|
||||
T: Serialize + Deserialize<'de> + PartialEq + Debug,
|
||||
{
|
||||
assert_tokens_readable(value, tokens, None);
|
||||
}
|
||||
|
||||
// Not public API
|
||||
#[doc(hidden)]
|
||||
/// Runs both `assert_ser_tokens` and `assert_de_tokens`.
|
||||
///
|
||||
/// See: `assert_tokens`
|
||||
pub fn assert_tokens_readable<'de, T>(value: &T, tokens: &'de [Token], human_readable: Option<bool>)
|
||||
where
|
||||
T: Serialize + Deserialize<'de> + PartialEq + Debug,
|
||||
{
|
||||
assert_ser_tokens_readable(value, tokens, human_readable);
|
||||
assert_de_tokens_readable(value, tokens, human_readable);
|
||||
assert_ser_tokens(value, tokens);
|
||||
assert_de_tokens(value, tokens);
|
||||
}
|
||||
|
||||
/// Asserts that `value` serializes to the given `tokens`.
|
||||
@@ -96,19 +84,7 @@ pub fn assert_ser_tokens<T>(value: &T, tokens: &[Token])
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
assert_ser_tokens_readable(value, tokens, None)
|
||||
}
|
||||
|
||||
// Not public API
|
||||
#[doc(hidden)]
|
||||
/// Asserts that `value` serializes to the given `tokens`.
|
||||
///
|
||||
/// See: `assert_ser_tokens`
|
||||
pub fn assert_ser_tokens_readable<T>(value: &T, tokens: &[Token], human_readable: Option<bool>)
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
let mut ser = Serializer::readable(tokens, human_readable);
|
||||
let mut ser = Serializer::new(tokens);
|
||||
match value.serialize(&mut ser) {
|
||||
Ok(_) => {}
|
||||
Err(err) => panic!("value failed to serialize: {}", err),
|
||||
@@ -207,16 +183,7 @@ pub fn assert_de_tokens<'de, T>(value: &T, tokens: &'de [Token])
|
||||
where
|
||||
T: Deserialize<'de> + PartialEq + Debug,
|
||||
{
|
||||
assert_de_tokens_readable(value, tokens, None)
|
||||
}
|
||||
|
||||
// Not public API
|
||||
#[doc(hidden)]
|
||||
pub fn assert_de_tokens_readable<'de, T>(value: &T, tokens: &'de [Token], human_readable: Option<bool>)
|
||||
where
|
||||
T: Deserialize<'de> + PartialEq + Debug,
|
||||
{
|
||||
let mut de = Deserializer::readable(tokens, human_readable);
|
||||
let mut de = Deserializer::new(tokens);
|
||||
match T::deserialize(&mut de) {
|
||||
Ok(v) => assert_eq!(v, *value),
|
||||
Err(e) => panic!("tokens failed to deserialize: {}", e),
|
||||
@@ -248,7 +215,7 @@ where
|
||||
///
|
||||
/// assert_de_tokens_error::<S>(
|
||||
/// &[
|
||||
/// Token::Struct { name: "S", len: 1 },
|
||||
/// Token::Struct { name: "S", len: 2 },
|
||||
/// Token::Str("x"),
|
||||
/// ],
|
||||
/// "unknown field `x`, expected `a` or `b`",
|
||||
|
||||
@@ -0,0 +1,661 @@
|
||||
use std::fmt;
|
||||
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use serde::ser::{SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
|
||||
SerializeTuple, SerializeTupleStruct, SerializeTupleVariant};
|
||||
|
||||
#[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.
|
||||
///
|
||||
/// ```
|
||||
/// extern crate serde;
|
||||
/// extern crate serde_test;
|
||||
///
|
||||
/// use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
/// use serde_test::{Configure, Token, assert_tokens};
|
||||
///
|
||||
/// #[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::{Visitor, EnumAccess, VariantAccess, MapAccess, DeserializeSeed, SeqAccess, Error};
|
||||
|
||||
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 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);
|
||||
+41
-54
@@ -16,7 +16,6 @@ use token::Token;
|
||||
#[derive(Debug)]
|
||||
pub struct Deserializer<'de> {
|
||||
tokens: &'de [Token],
|
||||
is_human_readable: Option<bool>,
|
||||
}
|
||||
|
||||
macro_rules! assert_next_token {
|
||||
@@ -49,13 +48,7 @@ macro_rules! end_of_tokens {
|
||||
|
||||
impl<'de> Deserializer<'de> {
|
||||
pub fn new(tokens: &'de [Token]) -> Self {
|
||||
Deserializer::readable(tokens, None)
|
||||
}
|
||||
|
||||
// Not public API
|
||||
#[doc(hidden)]
|
||||
pub fn readable(tokens: &'de [Token], is_human_readable: Option<bool>) -> Self {
|
||||
Deserializer { tokens: tokens, is_human_readable: is_human_readable }
|
||||
Deserializer { tokens: tokens }
|
||||
}
|
||||
|
||||
fn peek_token_opt(&self) -> Option<Token> {
|
||||
@@ -107,7 +100,7 @@ impl<'de> Deserializer<'de> {
|
||||
DeserializerSeqVisitor {
|
||||
de: self,
|
||||
len: len,
|
||||
end: end.clone(),
|
||||
end: end,
|
||||
},
|
||||
)
|
||||
);
|
||||
@@ -129,7 +122,7 @@ impl<'de> Deserializer<'de> {
|
||||
DeserializerMapVisitor {
|
||||
de: self,
|
||||
len: len,
|
||||
end: end.clone(),
|
||||
end: end,
|
||||
},
|
||||
)
|
||||
);
|
||||
@@ -172,15 +165,14 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
||||
Token::ByteBuf(v) => visitor.visit_byte_buf(v.to_vec()),
|
||||
Token::None => visitor.visit_none(),
|
||||
Token::Some => visitor.visit_some(self),
|
||||
Token::Unit => visitor.visit_unit(),
|
||||
Token::UnitStruct { name: _ } => visitor.visit_unit(),
|
||||
Token::NewtypeStruct { name: _ } => visitor.visit_newtype_struct(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 { name: _, len } => self.visit_seq(Some(len), Token::TupleStructEnd, visitor),
|
||||
Token::TupleStruct { len, .. } => self.visit_seq(Some(len), Token::TupleStructEnd, visitor),
|
||||
Token::Map { len } => self.visit_map(len, Token::MapEnd, visitor),
|
||||
Token::Struct { name: _, len } => self.visit_map(Some(len), Token::StructEnd, visitor),
|
||||
Token::Enum { name: _ } => {
|
||||
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) {
|
||||
@@ -202,14 +194,14 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
||||
}
|
||||
}
|
||||
}
|
||||
Token::UnitVariant { name: _, variant } => visitor.visit_str(variant),
|
||||
Token::NewtypeVariant { name: _, variant } => {
|
||||
Token::UnitVariant { variant, .. } => visitor.visit_str(variant),
|
||||
Token::NewtypeVariant { variant, .. } => {
|
||||
visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant), EnumFormat::Any),)
|
||||
}
|
||||
Token::TupleVariant { name: _, variant, len: _ } => {
|
||||
Token::TupleVariant { variant, .. } => {
|
||||
visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant), EnumFormat::Seq),)
|
||||
}
|
||||
Token::StructVariant { name: _, variant, len: _ } => {
|
||||
Token::StructVariant { variant, .. } => {
|
||||
visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant), EnumFormat::Map),)
|
||||
}
|
||||
Token::SeqEnd | Token::TupleEnd | Token::TupleStructEnd | Token::MapEnd |
|
||||
@@ -252,10 +244,10 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
||||
|
||||
visitor.visit_enum(DeserializerEnumVisitor { de: self })
|
||||
}
|
||||
Token::UnitVariant { name: n, variant: _ } |
|
||||
Token::NewtypeVariant { name: n, variant: _ } |
|
||||
Token::TupleVariant { name: n, variant: _, len: _ } |
|
||||
Token::StructVariant { name: n, variant: _, len: _ } if name == n => {
|
||||
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 })
|
||||
}
|
||||
_ => {
|
||||
@@ -269,7 +261,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
match self.peek_token() {
|
||||
Token::UnitStruct { name: _ } => {
|
||||
Token::UnitStruct { .. } => {
|
||||
assert_next_token!(self, Token::UnitStruct { name: name });
|
||||
visitor.visit_unit()
|
||||
}
|
||||
@@ -282,7 +274,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
match self.peek_token() {
|
||||
Token::NewtypeStruct { name: _ } => {
|
||||
Token::NewtypeStruct { .. } => {
|
||||
assert_next_token!(self, Token::NewtypeStruct { name: name });
|
||||
visitor.visit_newtype_struct(self)
|
||||
}
|
||||
@@ -296,19 +288,19 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
||||
{
|
||||
match self.peek_token() {
|
||||
Token::Unit |
|
||||
Token::UnitStruct { name: _ } => {
|
||||
Token::UnitStruct { .. } => {
|
||||
self.next_token();
|
||||
visitor.visit_unit()
|
||||
}
|
||||
Token::Seq { len: _ } => {
|
||||
Token::Seq { .. } => {
|
||||
self.next_token();
|
||||
self.visit_seq(Some(len), Token::SeqEnd, visitor)
|
||||
}
|
||||
Token::Tuple { len: _ } => {
|
||||
Token::Tuple { .. } => {
|
||||
self.next_token();
|
||||
self.visit_seq(Some(len), Token::TupleEnd, visitor)
|
||||
}
|
||||
Token::TupleStruct { name: _, len: _ } => {
|
||||
Token::TupleStruct { .. } => {
|
||||
self.next_token();
|
||||
self.visit_seq(Some(len), Token::TupleStructEnd, visitor)
|
||||
}
|
||||
@@ -330,19 +322,19 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
||||
self.next_token();
|
||||
visitor.visit_unit()
|
||||
}
|
||||
Token::UnitStruct { name: _ } => {
|
||||
Token::UnitStruct { .. } => {
|
||||
assert_next_token!(self, Token::UnitStruct { name: name });
|
||||
visitor.visit_unit()
|
||||
}
|
||||
Token::Seq { len: _ } => {
|
||||
Token::Seq { .. } => {
|
||||
self.next_token();
|
||||
self.visit_seq(Some(len), Token::SeqEnd, visitor)
|
||||
}
|
||||
Token::Tuple { len: _ } => {
|
||||
Token::Tuple { .. } => {
|
||||
self.next_token();
|
||||
self.visit_seq(Some(len), Token::TupleEnd, visitor)
|
||||
}
|
||||
Token::TupleStruct { name: _, len: n } => {
|
||||
Token::TupleStruct { len: n, .. } => {
|
||||
assert_next_token!(self, Token::TupleStruct { name: name, len: n });
|
||||
self.visit_seq(Some(len), Token::TupleStructEnd, visitor)
|
||||
}
|
||||
@@ -360,11 +352,11 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
match self.peek_token() {
|
||||
Token::Struct { name: _, len: n } => {
|
||||
assert_next_token!(self, Token::Struct { name: name, len: n });
|
||||
Token::Struct { .. } => {
|
||||
assert_next_token!(self, Token::Struct { name: name, len: fields.len() });
|
||||
self.visit_map(Some(fields.len()), Token::StructEnd, visitor)
|
||||
}
|
||||
Token::Map { len: _ } => {
|
||||
Token::Map { .. } => {
|
||||
self.next_token();
|
||||
self.visit_map(Some(fields.len()), Token::MapEnd, visitor)
|
||||
}
|
||||
@@ -373,15 +365,10 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
||||
}
|
||||
|
||||
fn is_human_readable(&self) -> bool {
|
||||
match self.is_human_readable {
|
||||
Some(is) => is,
|
||||
None => {
|
||||
panic!("There is no serde_test API currently for testing types \
|
||||
that have different human-readable and compact \
|
||||
representation. See \
|
||||
https://github.com/serde-rs/serde/issues/1065.");
|
||||
}
|
||||
}
|
||||
panic!(
|
||||
"Types which have different human-readable and compact representations \
|
||||
must explicitly mark their test cases with `serde_test::Configure`"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -461,10 +448,10 @@ impl<'de, 'a> EnumAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
|
||||
V: DeserializeSeed<'de>,
|
||||
{
|
||||
match self.de.peek_token() {
|
||||
Token::UnitVariant { name: _, variant: v } |
|
||||
Token::NewtypeVariant { name: _, variant: v } |
|
||||
Token::TupleVariant { name: _, variant: v, len: _ } |
|
||||
Token::StructVariant { name: _, variant: v, len: _ } => {
|
||||
Token::UnitVariant { variant: v, .. } |
|
||||
Token::NewtypeVariant { variant: v, .. } |
|
||||
Token::TupleVariant { variant: v, .. } |
|
||||
Token::StructVariant { variant: v, .. } => {
|
||||
let de = v.into_deserializer();
|
||||
let value = try!(seed.deserialize(de));
|
||||
Ok((value, self))
|
||||
@@ -482,7 +469,7 @@ impl<'de, 'a> VariantAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
|
||||
|
||||
fn unit_variant(self) -> Result<(), Error> {
|
||||
match self.de.peek_token() {
|
||||
Token::UnitVariant { name: _, variant: _ } => {
|
||||
Token::UnitVariant { .. } => {
|
||||
self.de.next_token();
|
||||
Ok(())
|
||||
}
|
||||
@@ -495,7 +482,7 @@ impl<'de, 'a> VariantAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
|
||||
T: DeserializeSeed<'de>,
|
||||
{
|
||||
match self.de.peek_token() {
|
||||
Token::NewtypeVariant { name: _, variant: _ } => {
|
||||
Token::NewtypeVariant { .. } => {
|
||||
self.de.next_token();
|
||||
seed.deserialize(self.de)
|
||||
}
|
||||
@@ -508,7 +495,7 @@ impl<'de, 'a> VariantAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
match self.de.peek_token() {
|
||||
Token::TupleVariant { name: _, variant: _, len: enum_len } => {
|
||||
Token::TupleVariant { len: enum_len, .. } => {
|
||||
let token = self.de.next_token();
|
||||
|
||||
if len == enum_len {
|
||||
@@ -536,7 +523,7 @@ impl<'de, 'a> VariantAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
match self.de.peek_token() {
|
||||
Token::StructVariant { name: _, variant: _, len: enum_len } => {
|
||||
Token::StructVariant { len: enum_len, .. } => {
|
||||
let token = self.de.next_token();
|
||||
|
||||
if fields.len() == enum_len {
|
||||
|
||||
@@ -17,13 +17,13 @@ pub struct Error {
|
||||
}
|
||||
|
||||
impl ser::Error for Error {
|
||||
fn custom<T: Display>(msg: T) -> Error {
|
||||
fn custom<T: Display>(msg: T) -> Self {
|
||||
Error { msg: msg.to_string() }
|
||||
}
|
||||
}
|
||||
|
||||
impl de::Error for Error {
|
||||
fn custom<T: Display>(msg: T) -> Error {
|
||||
fn custom<T: Display>(msg: T) -> Self {
|
||||
Error { msg: msg.to_string() }
|
||||
}
|
||||
}
|
||||
|
||||
+16
-6
@@ -155,7 +155,18 @@
|
||||
//! # }
|
||||
//! ```
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.17")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.21")]
|
||||
|
||||
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
|
||||
// Whitelisted clippy lints
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(float_cmp))]
|
||||
// Whitelisted clippy_pedantic lints
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(
|
||||
missing_docs_in_private_items,
|
||||
stutter,
|
||||
use_debug,
|
||||
use_self,
|
||||
))]
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde;
|
||||
@@ -164,16 +175,15 @@ mod ser;
|
||||
mod de;
|
||||
mod error;
|
||||
|
||||
mod configure;
|
||||
mod token;
|
||||
mod assert;
|
||||
|
||||
pub use token::Token;
|
||||
pub use assert::{assert_tokens, assert_ser_tokens, assert_ser_tokens_error,
|
||||
assert_de_tokens, assert_de_tokens_error};
|
||||
pub use assert::{assert_de_tokens, assert_de_tokens_error, assert_ser_tokens,
|
||||
assert_ser_tokens_error, assert_tokens};
|
||||
|
||||
// Not public API.
|
||||
#[doc(hidden)]
|
||||
pub use assert::{assert_tokens_readable, assert_de_tokens_readable, assert_ser_tokens_readable};
|
||||
pub use configure::{Compact, Configure, Readable};
|
||||
|
||||
// Not public API.
|
||||
#[doc(hidden)]
|
||||
|
||||
+45
-27
@@ -15,19 +15,12 @@ use token::Token;
|
||||
#[derive(Debug)]
|
||||
pub struct Serializer<'a> {
|
||||
tokens: &'a [Token],
|
||||
is_human_readable: Option<bool>,
|
||||
}
|
||||
|
||||
impl<'a> Serializer<'a> {
|
||||
/// Creates the serializer.
|
||||
pub fn new(tokens: &'a [Token]) -> Self {
|
||||
Serializer::readable(tokens, None)
|
||||
}
|
||||
|
||||
// Not public API
|
||||
#[doc(hidden)]
|
||||
pub fn readable(tokens: &'a [Token], is_human_readable: Option<bool>) -> Self {
|
||||
Serializer { tokens: tokens, is_human_readable: is_human_readable }
|
||||
Serializer { tokens: tokens }
|
||||
}
|
||||
|
||||
/// Pulls the next token off of the serializer, ignoring it.
|
||||
@@ -47,25 +40,43 @@ impl<'a> Serializer<'a> {
|
||||
|
||||
macro_rules! assert_next_token {
|
||||
($ser:expr, $expected:ident) => {
|
||||
assert_next_token!($ser, $expected, Token::$expected, true);
|
||||
assert_next_token!($ser, stringify!($expected), Token::$expected, true);
|
||||
};
|
||||
($ser:expr, $expected:ident($v:expr)) => {
|
||||
assert_next_token!($ser, $expected, Token::$expected(v), v == $v);
|
||||
assert_next_token!(
|
||||
$ser,
|
||||
format_args!("{}({:?})", stringify!($expected), $v),
|
||||
Token::$expected(v),
|
||||
v == $v
|
||||
);
|
||||
};
|
||||
($ser:expr, $expected:ident { $($k:ident),* }) => {
|
||||
let compare = ($($k,)*);
|
||||
assert_next_token!($ser, $expected, Token::$expected { $($k),* }, ($($k,)*) == compare);
|
||||
let field_format = || {
|
||||
use std::fmt::Write;
|
||||
let mut buffer = String::new();
|
||||
$(
|
||||
write!(&mut buffer, "{}: {:?}, ", stringify!($k), $k).unwrap();
|
||||
)*
|
||||
buffer
|
||||
};
|
||||
assert_next_token!(
|
||||
$ser,
|
||||
format_args!("{} {{ {}}}", stringify!($expected), field_format()),
|
||||
Token::$expected { $($k),* },
|
||||
($($k,)*) == compare
|
||||
);
|
||||
};
|
||||
($ser:expr, $expected:ident, $pat:pat, $guard:expr) => {
|
||||
($ser:expr, $expected:expr, $pat:pat, $guard:expr) => {
|
||||
match $ser.next_token() {
|
||||
Some($pat) if $guard => {}
|
||||
Some(other) => {
|
||||
panic!("expected Token::{} but serialized as {}",
|
||||
stringify!($expected), other);
|
||||
$expected, other);
|
||||
}
|
||||
None => {
|
||||
panic!("expected Token::{} after end of serialized tokens",
|
||||
stringify!($expected));
|
||||
$expected);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -254,10 +265,16 @@ impl<'s, 'a> ser::Serializer for &'s mut Serializer<'a> {
|
||||
assert_next_token!(self, Str(variant));
|
||||
let len = Some(len);
|
||||
assert_next_token!(self, Seq { len });
|
||||
Ok(Variant { ser: self, end: Token::SeqEnd })
|
||||
Ok(Variant {
|
||||
ser: self,
|
||||
end: Token::SeqEnd,
|
||||
})
|
||||
} else {
|
||||
assert_next_token!(self, TupleVariant { name, variant, len });
|
||||
Ok(Variant { ser: self, end: Token::TupleVariantEnd })
|
||||
Ok(Variant {
|
||||
ser: self,
|
||||
end: Token::TupleVariantEnd,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,23 +300,24 @@ impl<'s, 'a> ser::Serializer for &'s mut Serializer<'a> {
|
||||
assert_next_token!(self, Str(variant));
|
||||
let len = Some(len);
|
||||
assert_next_token!(self, Map { len });
|
||||
Ok(Variant { ser: self, end: Token::MapEnd })
|
||||
Ok(Variant {
|
||||
ser: self,
|
||||
end: Token::MapEnd,
|
||||
})
|
||||
} else {
|
||||
assert_next_token!(self, StructVariant { name, variant, len });
|
||||
Ok(Variant { ser: self, end: Token::StructVariantEnd })
|
||||
Ok(Variant {
|
||||
ser: self,
|
||||
end: Token::StructVariantEnd,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn is_human_readable(&self) -> bool {
|
||||
match self.is_human_readable {
|
||||
Some(is) => is,
|
||||
None => {
|
||||
panic!("There is no serde_test API currently for testing types \
|
||||
that have different human-readable and compact \
|
||||
representation. See \
|
||||
https://github.com/serde-rs/serde/issues/1065.");
|
||||
}
|
||||
}
|
||||
panic!(
|
||||
"Types which have different human-readable and compact representations \
|
||||
must explicitly mark their test cases with `serde_test::Configure`"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -425,6 +425,10 @@ pub enum Token {
|
||||
|
||||
/// The header of a struct.
|
||||
///
|
||||
/// When testing deserialization, the `len` field must match the number of
|
||||
/// fields that the struct expects to deserialize. This may be different
|
||||
/// from the number of fields contained in the input tokens.
|
||||
///
|
||||
/// After this header are the fields of the struct, followed by `StructEnd`.
|
||||
///
|
||||
/// ```rust
|
||||
@@ -461,6 +465,10 @@ pub enum Token {
|
||||
|
||||
/// The header of a struct variant of an enum.
|
||||
///
|
||||
/// When testing deserialization, the `len` field must match the number of
|
||||
/// fields that the struct variant expects to deserialize. This may be
|
||||
/// different from the number of fields contained in the input tokens.
|
||||
///
|
||||
/// After this header are the fields of the struct variant, followed by
|
||||
/// `StructVariantEnd`.
|
||||
///
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright 2017 Serde Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct Str<'a>(&'a str);
|
||||
|
||||
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
|
||||
enum Test<'a> {
|
||||
#[serde(borrow)] //~^^ HELP: duplicate serde attribute `borrow`
|
||||
S(#[serde(borrow)] Str<'a>)
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright 2017 Serde Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct Str<'a>(&'a str);
|
||||
|
||||
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
|
||||
enum Test<'a> {
|
||||
#[serde(borrow)] //~^^ HELP: #[serde(borrow)] may only be used on newtype variants
|
||||
S { s: Str<'a> }
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -135,7 +135,7 @@ fn test_default_struct() {
|
||||
a5: 123,
|
||||
},
|
||||
&[
|
||||
Token::Struct { name: "DefaultStruct", len: 1 },
|
||||
Token::Struct { name: "DefaultStruct", len: 3 },
|
||||
|
||||
Token::Str("a1"),
|
||||
Token::I32(1),
|
||||
@@ -309,7 +309,7 @@ fn test_elt_not_deserialize() {
|
||||
c: NotDeserializeStruct(123),
|
||||
e: NotDeserializeEnum::Trouble,
|
||||
},
|
||||
&[Token::Struct { name: "ContainsNotDeserialize", len: 3 }, Token::StructEnd],
|
||||
&[Token::Struct { name: "ContainsNotDeserialize", len: 1 }, Token::StructEnd],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -331,7 +331,7 @@ fn test_ignore_unknown() {
|
||||
a5: 123,
|
||||
},
|
||||
&[
|
||||
Token::Struct { name: "DefaultStruct", len: 5 },
|
||||
Token::Struct { name: "DefaultStruct", len: 3 },
|
||||
|
||||
Token::Str("whoops1"),
|
||||
Token::I32(2),
|
||||
@@ -359,7 +359,7 @@ fn test_ignore_unknown() {
|
||||
|
||||
assert_de_tokens_error::<DenyUnknown>(
|
||||
&[
|
||||
Token::Struct { name: "DenyUnknown", len: 2 },
|
||||
Token::Struct { name: "DenyUnknown", len: 1 },
|
||||
|
||||
Token::Str("a1"),
|
||||
Token::I32(1),
|
||||
|
||||
+24
-28
@@ -29,7 +29,7 @@ extern crate fnv;
|
||||
use self::fnv::FnvHasher;
|
||||
|
||||
extern crate serde_test;
|
||||
use self::serde_test::{Token, assert_de_tokens, assert_de_tokens_error, assert_de_tokens_readable};
|
||||
use self::serde_test::{assert_de_tokens, assert_de_tokens_error, Configure, Token};
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
@@ -49,16 +49,14 @@ struct TupleStruct(i32, i32, i32);
|
||||
struct Struct {
|
||||
a: i32,
|
||||
b: i32,
|
||||
#[serde(skip_deserializing)]
|
||||
c: i32,
|
||||
#[serde(skip_deserializing)] c: i32,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct StructDenyUnknown {
|
||||
a: i32,
|
||||
#[serde(skip_deserializing)]
|
||||
b: i32,
|
||||
#[serde(skip_deserializing)] b: i32,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Deserialize)]
|
||||
@@ -79,15 +77,13 @@ impl Default for StructDefault<String> {
|
||||
|
||||
#[derive(PartialEq, Debug, Deserialize)]
|
||||
struct StructSkipAll {
|
||||
#[serde(skip_deserializing)]
|
||||
a: i32,
|
||||
#[serde(skip_deserializing)] a: i32,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct StructSkipAllDenyUnknown {
|
||||
#[serde(skip_deserializing)]
|
||||
a: i32,
|
||||
#[serde(skip_deserializing)] a: i32,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Deserialize)]
|
||||
@@ -112,7 +108,7 @@ enum EnumSkipAll {
|
||||
|
||||
macro_rules! declare_tests {
|
||||
(
|
||||
readable: $readable:tt
|
||||
$readable:tt
|
||||
$($name:ident { $($value:expr => $tokens:expr,)+ })+
|
||||
) => {
|
||||
$(
|
||||
@@ -120,7 +116,7 @@ macro_rules! declare_tests {
|
||||
fn $name() {
|
||||
$(
|
||||
// Test ser/de roundtripping
|
||||
assert_de_tokens_readable(&$value, $tokens, Some($readable));
|
||||
assert_de_tokens(&$value.$readable(), $tokens);
|
||||
|
||||
// Test that the tokens are ignorable
|
||||
assert_de_tokens_ignore($tokens);
|
||||
@@ -168,13 +164,11 @@ fn assert_de_tokens_ignore(ignorable_tokens: &[Token]) {
|
||||
Token::Map { len: Some(2) },
|
||||
Token::Str("a"),
|
||||
Token::I32(1),
|
||||
|
||||
Token::Str("ignored"),
|
||||
]
|
||||
.into_iter()
|
||||
.chain(ignorable_tokens.to_vec().into_iter())
|
||||
.chain(vec![Token::MapEnd].into_iter())
|
||||
.collect();
|
||||
].into_iter()
|
||||
.chain(ignorable_tokens.to_vec().into_iter())
|
||||
.chain(vec![Token::MapEnd].into_iter())
|
||||
.collect();
|
||||
|
||||
let mut de = serde_test::Deserializer::new(&concated_tokens);
|
||||
let base = IgnoreBase::deserialize(&mut de).unwrap();
|
||||
@@ -544,7 +538,7 @@ declare_tests! {
|
||||
Token::MapEnd,
|
||||
],
|
||||
Struct { a: 1, b: 2, c: 0 } => &[
|
||||
Token::Struct { name: "Struct", len: 3 },
|
||||
Token::Struct { name: "Struct", len: 2 },
|
||||
Token::Str("a"),
|
||||
Token::I32(1),
|
||||
|
||||
@@ -576,7 +570,7 @@ declare_tests! {
|
||||
Token::MapEnd,
|
||||
],
|
||||
Struct { a: 1, b: 2, c: 0 } => &[
|
||||
Token::Struct { name: "Struct", len: 3 },
|
||||
Token::Struct { name: "Struct", len: 2 },
|
||||
Token::Str("a"),
|
||||
Token::I32(1),
|
||||
|
||||
@@ -597,7 +591,7 @@ declare_tests! {
|
||||
Token::StructEnd,
|
||||
],
|
||||
StructSkipAll { a: 0 } => &[
|
||||
Token::Struct { name: "StructSkipAll", len: 1 },
|
||||
Token::Struct { name: "StructSkipAll", len: 0 },
|
||||
Token::Str("a"),
|
||||
Token::I32(1),
|
||||
|
||||
@@ -614,7 +608,7 @@ declare_tests! {
|
||||
}
|
||||
test_struct_default {
|
||||
StructDefault { a: 50, b: "overwritten".to_string() } => &[
|
||||
Token::Struct { name: "StructDefault", len: 1 },
|
||||
Token::Struct { name: "StructDefault", len: 2 },
|
||||
Token::Str("a"),
|
||||
Token::I32(50),
|
||||
|
||||
@@ -623,7 +617,7 @@ declare_tests! {
|
||||
Token::StructEnd,
|
||||
],
|
||||
StructDefault { a: 100, b: "default".to_string() } => &[
|
||||
Token::Struct { name: "StructDefault", len: 0 },
|
||||
Token::Struct { name: "StructDefault", len: 2 },
|
||||
Token::StructEnd,
|
||||
],
|
||||
}
|
||||
@@ -774,7 +768,8 @@ declare_tests! {
|
||||
}
|
||||
|
||||
declare_tests! {
|
||||
readable: true
|
||||
readable
|
||||
|
||||
test_net_ipv4addr_readable {
|
||||
"1.2.3.4".parse::<net::Ipv4Addr>().unwrap() => &[Token::Str("1.2.3.4")],
|
||||
}
|
||||
@@ -792,7 +787,8 @@ declare_tests! {
|
||||
}
|
||||
|
||||
declare_tests! {
|
||||
readable: false
|
||||
compact
|
||||
|
||||
test_net_ipv4addr_compact {
|
||||
net::Ipv4Addr::from(*b"1234") => &seq![
|
||||
Token::Tuple { len: 4 },
|
||||
@@ -958,7 +954,7 @@ fn test_cstr_internal_null_end() {
|
||||
declare_error_tests! {
|
||||
test_unknown_field<StructDenyUnknown> {
|
||||
&[
|
||||
Token::Struct { name: "StructDenyUnknown", len: 2 },
|
||||
Token::Struct { name: "StructDenyUnknown", len: 1 },
|
||||
Token::Str("a"),
|
||||
Token::I32(0),
|
||||
|
||||
@@ -968,14 +964,14 @@ declare_error_tests! {
|
||||
}
|
||||
test_skipped_field_is_unknown<StructDenyUnknown> {
|
||||
&[
|
||||
Token::Struct { name: "StructDenyUnknown", len: 2 },
|
||||
Token::Struct { name: "StructDenyUnknown", len: 1 },
|
||||
Token::Str("b"),
|
||||
],
|
||||
"unknown field `b`, expected `a`",
|
||||
}
|
||||
test_skip_all_deny_unknown<StructSkipAllDenyUnknown> {
|
||||
&[
|
||||
Token::Struct { name: "StructSkipAllDenyUnknown", len: 1 },
|
||||
Token::Struct { name: "StructSkipAllDenyUnknown", len: 0 },
|
||||
Token::Str("a"),
|
||||
],
|
||||
"unknown field `a`, there are no fields",
|
||||
@@ -1180,7 +1176,7 @@ declare_error_tests! {
|
||||
}
|
||||
test_wrapping_overflow<Wrapping<u16>> {
|
||||
&[
|
||||
Token::U32(65536),
|
||||
Token::U32(65_536),
|
||||
],
|
||||
"invalid value: integer `65536`, expected u16",
|
||||
}
|
||||
|
||||
@@ -14,10 +14,6 @@
|
||||
|
||||
#![cfg_attr(feature = "unstable", feature(non_ascii_idents))]
|
||||
|
||||
// Clippy false positive
|
||||
// https://github.com/Manishearth/rust-clippy/issues/292
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(needless_lifetimes))]
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
@@ -361,6 +357,12 @@ fn test_gen() {
|
||||
s: Str<'a>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum BorrowVariant<'a> {
|
||||
#[serde(borrow, with = "StrDef")]
|
||||
S(Str<'a>),
|
||||
}
|
||||
|
||||
mod vis {
|
||||
pub struct S;
|
||||
|
||||
@@ -515,6 +517,25 @@ fn test_gen() {
|
||||
Tuple(&'a str, &'static str),
|
||||
Newtype(&'static str),
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct SkippedStaticStr {
|
||||
#[serde(skip_deserializing)]
|
||||
skipped: &'static str,
|
||||
other: isize,
|
||||
}
|
||||
assert::<SkippedStaticStr>();
|
||||
|
||||
macro_rules! T {
|
||||
() => { () }
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct TypeMacro<T> {
|
||||
mac: T!(),
|
||||
marker: PhantomData<T>,
|
||||
}
|
||||
assert::<TypeMacro<X>>();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -9,10 +9,8 @@
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
extern crate serde;
|
||||
|
||||
extern crate serde_test;
|
||||
use serde_test::{Token, assert_de_tokens};
|
||||
use serde_test::{assert_de_tokens, Token};
|
||||
|
||||
#[test]
|
||||
fn test_variant_identifier() {
|
||||
@@ -51,8 +49,7 @@ fn test_unit_fallthrough() {
|
||||
enum F {
|
||||
Aaa,
|
||||
Bbb,
|
||||
#[serde(other)]
|
||||
Other,
|
||||
#[serde(other)] Other,
|
||||
}
|
||||
|
||||
assert_de_tokens(&F::Other, &[Token::Str("x")]);
|
||||
|
||||
@@ -786,7 +786,7 @@ fn test_adjacently_tagged_enum() {
|
||||
}
|
||||
|
||||
// unit with no content
|
||||
assert_tokens(
|
||||
assert_ser_tokens(
|
||||
&AdjacentlyTagged::Unit::<u8>,
|
||||
&[
|
||||
Token::Struct { name: "AdjacentlyTagged", len: 1 },
|
||||
@@ -798,11 +798,24 @@ fn test_adjacently_tagged_enum() {
|
||||
],
|
||||
);
|
||||
|
||||
// unit with no content
|
||||
assert_de_tokens(
|
||||
&AdjacentlyTagged::Unit::<u8>,
|
||||
&[
|
||||
Token::Struct { name: "AdjacentlyTagged", len: 2 },
|
||||
|
||||
Token::Str("t"),
|
||||
Token::Str("Unit"),
|
||||
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
// unit with tag first
|
||||
assert_de_tokens(
|
||||
&AdjacentlyTagged::Unit::<u8>,
|
||||
&[
|
||||
Token::Struct { name: "AdjacentlyTagged", len: 1 },
|
||||
Token::Struct { name: "AdjacentlyTagged", len: 2 },
|
||||
|
||||
Token::Str("t"),
|
||||
Token::Str("Unit"),
|
||||
@@ -818,7 +831,7 @@ fn test_adjacently_tagged_enum() {
|
||||
assert_de_tokens(
|
||||
&AdjacentlyTagged::Unit::<u8>,
|
||||
&[
|
||||
Token::Struct { name: "AdjacentlyTagged", len: 1 },
|
||||
Token::Struct { name: "AdjacentlyTagged", len: 2 },
|
||||
|
||||
Token::Str("c"),
|
||||
Token::Unit,
|
||||
@@ -834,7 +847,7 @@ fn test_adjacently_tagged_enum() {
|
||||
assert_de_tokens(
|
||||
&AdjacentlyTagged::Unit::<u8>,
|
||||
&[
|
||||
Token::Struct { name: "AdjacentlyTagged", len: 3 },
|
||||
Token::Struct { name: "AdjacentlyTagged", len: 2 },
|
||||
|
||||
Token::Str("f"),
|
||||
Token::Unit,
|
||||
@@ -975,7 +988,7 @@ fn test_adjacently_tagged_enum_deny_unknown_fields() {
|
||||
assert_de_tokens(
|
||||
&AdjacentlyTagged::Unit,
|
||||
&[
|
||||
Token::Struct { name: "AdjacentlyTagged", len: 2},
|
||||
Token::Struct { name: "AdjacentlyTagged", len: 2 },
|
||||
|
||||
Token::Str("t"),
|
||||
Token::Str("Unit"),
|
||||
@@ -989,7 +1002,7 @@ fn test_adjacently_tagged_enum_deny_unknown_fields() {
|
||||
|
||||
assert_de_tokens_error::<AdjacentlyTagged>(
|
||||
&[
|
||||
Token::Struct { name: "AdjacentlyTagged", len: 3},
|
||||
Token::Struct { name: "AdjacentlyTagged", len: 2 },
|
||||
|
||||
Token::Str("t"),
|
||||
Token::Str("Unit"),
|
||||
@@ -1004,7 +1017,7 @@ fn test_adjacently_tagged_enum_deny_unknown_fields() {
|
||||
|
||||
assert_de_tokens_error::<AdjacentlyTagged>(
|
||||
&[
|
||||
Token::Struct { name: "AdjacentlyTagged", len: 3},
|
||||
Token::Struct { name: "AdjacentlyTagged", len: 2 },
|
||||
|
||||
Token::Str("h"),
|
||||
],
|
||||
@@ -1013,7 +1026,7 @@ fn test_adjacently_tagged_enum_deny_unknown_fields() {
|
||||
|
||||
assert_de_tokens_error::<AdjacentlyTagged>(
|
||||
&[
|
||||
Token::Struct { name: "AdjacentlyTagged", len: 3},
|
||||
Token::Struct { name: "AdjacentlyTagged", len: 2 },
|
||||
|
||||
Token::Str("c"),
|
||||
Token::Unit,
|
||||
@@ -1267,3 +1280,48 @@ fn test_rename_all() {
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_untagged_newtype_variant_containing_unit_struct_not_map() {
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
struct Unit;
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum Message {
|
||||
Unit(Unit),
|
||||
Map(BTreeMap<String, String>),
|
||||
}
|
||||
|
||||
assert_tokens(
|
||||
&Message::Map(BTreeMap::new()),
|
||||
&[
|
||||
Token::Map { len: Some(0) },
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_internally_tagged_newtype_variant_containing_unit_struct() {
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
struct Info;
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(tag = "topic")]
|
||||
enum Message {
|
||||
Info(Info),
|
||||
}
|
||||
|
||||
assert_tokens(
|
||||
&Message::Info(Info),
|
||||
&[
|
||||
Token::Map { len: Some(1) },
|
||||
|
||||
Token::Str("topic"),
|
||||
Token::Str("Info"),
|
||||
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
extern crate serde;
|
||||
|
||||
mod remote {
|
||||
pub struct Unit;
|
||||
|
||||
@@ -87,32 +85,23 @@ mod remote {
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Test {
|
||||
#[serde(with = "UnitDef")]
|
||||
unit: remote::Unit,
|
||||
#[serde(with = "UnitDef")] unit: remote::Unit,
|
||||
|
||||
#[serde(with = "PrimitivePrivDef")]
|
||||
primitive_priv: remote::PrimitivePriv,
|
||||
#[serde(with = "PrimitivePrivDef")] primitive_priv: remote::PrimitivePriv,
|
||||
|
||||
#[serde(with = "PrimitivePubDef")]
|
||||
primitive_pub: remote::PrimitivePub,
|
||||
#[serde(with = "PrimitivePubDef")] primitive_pub: remote::PrimitivePub,
|
||||
|
||||
#[serde(with = "NewtypePrivDef")]
|
||||
newtype_priv: remote::NewtypePriv,
|
||||
#[serde(with = "NewtypePrivDef")] newtype_priv: remote::NewtypePriv,
|
||||
|
||||
#[serde(with = "NewtypePubDef")]
|
||||
newtype_pub: remote::NewtypePub,
|
||||
#[serde(with = "NewtypePubDef")] newtype_pub: remote::NewtypePub,
|
||||
|
||||
#[serde(with = "TuplePrivDef")]
|
||||
tuple_priv: remote::TuplePriv,
|
||||
#[serde(with = "TuplePrivDef")] tuple_priv: remote::TuplePriv,
|
||||
|
||||
#[serde(with = "TuplePubDef")]
|
||||
tuple_pub: remote::TuplePub,
|
||||
#[serde(with = "TuplePubDef")] tuple_pub: remote::TuplePub,
|
||||
|
||||
#[serde(with = "StructPrivDef")]
|
||||
struct_priv: remote::StructPriv,
|
||||
#[serde(with = "StructPrivDef")] struct_priv: remote::StructPriv,
|
||||
|
||||
#[serde(with = "StructPubDef")]
|
||||
struct_pub: remote::StructPub,
|
||||
#[serde(with = "StructPubDef")] struct_pub: remote::StructPub,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
@@ -121,10 +110,7 @@ struct UnitDef;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "remote::PrimitivePriv")]
|
||||
struct PrimitivePrivDef(
|
||||
#[serde(getter = "remote::PrimitivePriv::get")]
|
||||
u8
|
||||
);
|
||||
struct PrimitivePrivDef(#[serde(getter = "remote::PrimitivePriv::get")] u8);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "remote::PrimitivePub")]
|
||||
@@ -133,53 +119,41 @@ struct PrimitivePubDef(u8);
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "remote::NewtypePriv")]
|
||||
struct NewtypePrivDef(
|
||||
#[serde(getter = "remote::NewtypePriv::get", with = "UnitDef")]
|
||||
remote::Unit
|
||||
#[serde(getter = "remote::NewtypePriv::get", with = "UnitDef")] remote::Unit,
|
||||
);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "remote::NewtypePub")]
|
||||
struct NewtypePubDef(
|
||||
#[serde(with = "UnitDef")]
|
||||
remote::Unit
|
||||
);
|
||||
struct NewtypePubDef(#[serde(with = "UnitDef")] remote::Unit);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "remote::TuplePriv")]
|
||||
struct TuplePrivDef(
|
||||
#[serde(getter = "remote::TuplePriv::first")]
|
||||
u8,
|
||||
#[serde(getter = "remote::TuplePriv::second", with = "UnitDef")]
|
||||
remote::Unit
|
||||
#[serde(getter = "remote::TuplePriv::first")] u8,
|
||||
#[serde(getter = "remote::TuplePriv::second", with = "UnitDef")] remote::Unit,
|
||||
);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "remote::TuplePub")]
|
||||
struct TuplePubDef(
|
||||
u8,
|
||||
#[serde(with = "UnitDef")]
|
||||
remote::Unit
|
||||
);
|
||||
struct TuplePubDef(u8, #[serde(with = "UnitDef")] remote::Unit);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "remote::StructPriv")]
|
||||
struct StructPrivDef {
|
||||
#[serde(getter = "remote::StructPriv::a")]
|
||||
a: u8,
|
||||
#[serde(getter = "remote::StructPriv::a")] a: u8,
|
||||
|
||||
#[serde(getter = "remote::StructPriv::b")]
|
||||
#[serde(with= "UnitDef")]
|
||||
#[serde(with = "UnitDef")]
|
||||
b: remote::Unit,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "remote::StructPub")]
|
||||
struct StructPubDef {
|
||||
#[allow(dead_code)]
|
||||
a: u8,
|
||||
#[allow(dead_code)] a: u8,
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[serde(with= "UnitDef")]
|
||||
#[serde(with = "UnitDef")]
|
||||
b: remote::Unit,
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
extern crate serde_test;
|
||||
use self::serde_test::{Token, assert_tokens_readable};
|
||||
use self::serde_test::{assert_tokens, Configure, Token};
|
||||
|
||||
use std::net;
|
||||
|
||||
@@ -17,9 +17,8 @@ mod macros;
|
||||
|
||||
#[test]
|
||||
fn ip_addr_roundtrip() {
|
||||
|
||||
assert_tokens_readable(
|
||||
&net::IpAddr::from(*b"1234"),
|
||||
assert_tokens(
|
||||
&net::IpAddr::from(*b"1234").compact(),
|
||||
&seq![
|
||||
Token::NewtypeVariant { name: "IpAddr", variant: "V4" },
|
||||
|
||||
@@ -27,15 +26,13 @@ fn ip_addr_roundtrip() {
|
||||
seq b"1234".iter().map(|&b| Token::U8(b)),
|
||||
Token::TupleEnd,
|
||||
],
|
||||
Some(false),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn socked_addr_roundtrip() {
|
||||
|
||||
assert_tokens_readable(
|
||||
&net::SocketAddr::from((*b"1234567890123456", 1234)),
|
||||
assert_tokens(
|
||||
&net::SocketAddr::from((*b"1234567890123456", 1234)).compact(),
|
||||
&seq![
|
||||
Token::NewtypeVariant { name: "SocketAddr", variant: "V6" },
|
||||
|
||||
@@ -48,6 +45,5 @@ fn socked_addr_roundtrip() {
|
||||
Token::U16(1234),
|
||||
Token::TupleEnd,
|
||||
],
|
||||
Some(false),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -21,11 +21,8 @@ use std::num::Wrapping;
|
||||
#[cfg(unix)]
|
||||
use std::str;
|
||||
|
||||
extern crate serde;
|
||||
|
||||
extern crate serde_test;
|
||||
use self::serde_test::{Token, assert_ser_tokens, assert_ser_tokens_error,
|
||||
assert_ser_tokens_readable};
|
||||
use self::serde_test::{assert_ser_tokens, assert_ser_tokens_error, Configure, Token};
|
||||
|
||||
extern crate fnv;
|
||||
use self::fnv::FnvHasher;
|
||||
@@ -54,28 +51,24 @@ enum Enum {
|
||||
One(i32),
|
||||
Seq(i32, i32),
|
||||
Map { a: i32, b: i32 },
|
||||
#[serde(skip_serializing)]
|
||||
SkippedUnit,
|
||||
#[serde(skip_serializing)]
|
||||
SkippedOne(i32),
|
||||
#[serde(skip_serializing)]
|
||||
SkippedSeq(i32, i32),
|
||||
#[serde(skip_serializing)]
|
||||
SkippedMap { _a: i32, _b: i32 },
|
||||
#[serde(skip_serializing)] SkippedUnit,
|
||||
#[serde(skip_serializing)] SkippedOne(i32),
|
||||
#[serde(skip_serializing)] SkippedSeq(i32, i32),
|
||||
#[serde(skip_serializing)] SkippedMap { _a: i32, _b: i32 },
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
macro_rules! declare_tests {
|
||||
(
|
||||
readable: $readable:tt
|
||||
$readable:tt
|
||||
$($name:ident { $($value:expr => $tokens:expr,)+ })+
|
||||
) => {
|
||||
$(
|
||||
#[test]
|
||||
fn $name() {
|
||||
$(
|
||||
assert_ser_tokens_readable(&$value, $tokens, Some($readable));
|
||||
assert_ser_tokens(&$value.$readable(), $tokens);
|
||||
)+
|
||||
}
|
||||
)+
|
||||
@@ -408,7 +401,8 @@ declare_tests! {
|
||||
}
|
||||
|
||||
declare_tests! {
|
||||
readable: true
|
||||
readable
|
||||
|
||||
test_net_ipv4addr_readable {
|
||||
"1.2.3.4".parse::<net::Ipv4Addr>().unwrap() => &[Token::Str("1.2.3.4")],
|
||||
}
|
||||
@@ -426,7 +420,8 @@ declare_tests! {
|
||||
}
|
||||
|
||||
declare_tests! {
|
||||
readable: false
|
||||
compact
|
||||
|
||||
test_net_ipv4addr_compact {
|
||||
net::Ipv4Addr::from(*b"1234") => &seq![
|
||||
Token::Tuple { len: 4 },
|
||||
@@ -524,11 +519,7 @@ fn test_cannot_serialize_paths() {
|
||||
let mut path_buf = PathBuf::new();
|
||||
path_buf.push(path);
|
||||
|
||||
assert_ser_tokens_error(
|
||||
&path_buf,
|
||||
&[],
|
||||
"path contains invalid UTF-8 characters",
|
||||
);
|
||||
assert_ser_tokens_error(&path_buf, &[], "path contains invalid UTF-8 characters");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user