mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-04-28 02:17:55 +00:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b7eb42aa6b | |||
| 750f8ba299 | |||
| 49cdef074d | |||
| aa86b04714 | |||
| c887a0b472 | |||
| 0c34e06e51 | |||
| 4a0c4e0c25 | |||
| 8c34e0940f | |||
| eb6bf16a51 | |||
| 797d049db5 | |||
| d61a373f12 | |||
| e0eea551b4 | |||
| c650a92bf7 | |||
| f218f4d7bf | |||
| 8c0a2015be | |||
| 4773863e3a | |||
| 80cd9c7617 | |||
| 436cafb0a3 | |||
| 98bb02e9b4 | |||
| 142439088c | |||
| ce81288235 |
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.19" # remember to update html_root_url
|
version = "1.0.24" # remember to update html_root_url
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
description = "A generic serialization/deserialization framework"
|
description = "A generic serialization/deserialization framework"
|
||||||
|
|||||||
+1
-1
@@ -79,7 +79,7 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Serde types in rustdoc of other crates get linked to here.
|
// Serde types in rustdoc of other crates get linked to here.
|
||||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.19")]
|
#![doc(html_root_url = "https://docs.rs/serde/1.0.24")]
|
||||||
|
|
||||||
// Support using Serde without the standard library!
|
// Support using Serde without the standard library!
|
||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
|||||||
@@ -198,6 +198,7 @@ pub mod size_hint {
|
|||||||
helper(iter.size_hint())
|
helper(iter.size_hint())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn cautious(hint: Option<usize>) -> usize {
|
pub fn cautious(hint: Option<usize>) -> usize {
|
||||||
cmp::min(hint.unwrap_or(0), 4096)
|
cmp::min(hint.unwrap_or(0), 4096)
|
||||||
}
|
}
|
||||||
@@ -1246,6 +1247,9 @@ mod content {
|
|||||||
Some(Content::Map(v)) => {
|
Some(Content::Map(v)) => {
|
||||||
de::Deserializer::deserialize_any(MapDeserializer::new(v), visitor)
|
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"),),
|
Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"struct variant"),),
|
||||||
_ => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"struct variant"),),
|
_ => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"struct variant"),),
|
||||||
}
|
}
|
||||||
@@ -1640,6 +1644,9 @@ mod content {
|
|||||||
Some(&Content::Map(ref v)) => {
|
Some(&Content::Map(ref v)) => {
|
||||||
de::Deserializer::deserialize_any(MapRefDeserializer::new(v), visitor)
|
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"),),
|
Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"struct variant"),),
|
||||||
_ => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"struct variant"),),
|
_ => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"struct variant"),),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.19" # remember to update html_root_url
|
version = "1.0.24" # remember to update html_root_url
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
||||||
@@ -20,7 +20,7 @@ proc-macro = true
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
quote = "0.3.8"
|
quote = "0.3.8"
|
||||||
serde_derive_internals = { version = "=0.17.0", default-features = false, path = "../serde_derive_internals" }
|
serde_derive_internals = { version = "=0.18.0", default-features = false, path = "../serde_derive_internals" }
|
||||||
syn = { version = "0.11", features = ["visit"] }
|
syn = { version = "0.11", features = ["visit"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|||||||
+29
-6
@@ -418,8 +418,8 @@ fn deserialize_seq(
|
|||||||
};
|
};
|
||||||
let assign = quote! {
|
let assign = quote! {
|
||||||
let #var = match #visit {
|
let #var = match #visit {
|
||||||
Some(__value) => __value,
|
_serde::export::Some(__value) => __value,
|
||||||
None => {
|
_serde::export::None => {
|
||||||
return _serde::export::Err(_serde::de::Error::invalid_length(#index_in_seq, &#expecting));
|
return _serde::export::Err(_serde::de::Error::invalid_length(#index_in_seq, &#expecting));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -447,7 +447,30 @@ fn deserialize_seq(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let let_default = match *cattrs.default() {
|
||||||
|
attr::Default::Default => {
|
||||||
|
Some(
|
||||||
|
quote!(
|
||||||
|
let __default: Self::Value = _serde::export::Default::default();
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
attr::Default::Path(ref path) => {
|
||||||
|
Some(
|
||||||
|
quote!(
|
||||||
|
let __default: Self::Value = #path();
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
attr::Default::None => {
|
||||||
|
// We don't need the default value, to prevent an unused variable warning
|
||||||
|
// we'll leave the line empty.
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
quote_block! {
|
quote_block! {
|
||||||
|
#let_default
|
||||||
#(#let_values)*
|
#(#let_values)*
|
||||||
_serde::export::Ok(#result)
|
_serde::export::Ok(#result)
|
||||||
}
|
}
|
||||||
@@ -1701,15 +1724,15 @@ fn deserialize_map(
|
|||||||
attr::Default::Default => {
|
attr::Default::Default => {
|
||||||
Some(
|
Some(
|
||||||
quote!(
|
quote!(
|
||||||
let __default: Self::Value = _serde::export::Default::default();
|
let __default: Self::Value = _serde::export::Default::default();
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
attr::Default::Path(ref path) => {
|
attr::Default::Path(ref path) => {
|
||||||
Some(
|
Some(
|
||||||
quote!(
|
quote!(
|
||||||
let __default: Self::Value = #path();
|
let __default: Self::Value = #path();
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
attr::Default::None => {
|
attr::Default::None => {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
//!
|
//!
|
||||||
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
|
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
|
||||||
|
|
||||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.19")]
|
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.24")]
|
||||||
|
|
||||||
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
|
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
|
||||||
#![cfg_attr(feature = "cargo-clippy", allow(used_underscore_binding))]
|
#![cfg_attr(feature = "cargo-clippy", allow(used_underscore_binding))]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde_derive_internals"
|
name = "serde_derive_internals"
|
||||||
version = "0.17.0" # remember to update html_root_url
|
version = "0.18.0" # remember to update html_root_url
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
description = "AST representation used by Serde derive macros. Unstable."
|
description = "AST representation used by Serde derive macros. Unstable."
|
||||||
|
|||||||
@@ -49,9 +49,11 @@ impl<'a> Container<'a> {
|
|||||||
let attrs = attr::Container::from_ast(cx, item);
|
let attrs = attr::Container::from_ast(cx, item);
|
||||||
|
|
||||||
let mut body = match item.body {
|
let mut body = match item.body {
|
||||||
syn::Body::Enum(ref variants) => Body::Enum(enum_from_ast(cx, variants)),
|
syn::Body::Enum(ref variants) => {
|
||||||
|
Body::Enum(enum_from_ast(cx, variants, &attrs.default()))
|
||||||
|
}
|
||||||
syn::Body::Struct(ref variant_data) => {
|
syn::Body::Struct(ref variant_data) => {
|
||||||
let (style, fields) = struct_from_ast(cx, variant_data, None);
|
let (style, fields) = struct_from_ast(cx, variant_data, None, &attrs.default());
|
||||||
Body::Struct(style, fields)
|
Body::Struct(style, fields)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -98,36 +100,54 @@ impl<'a> Body<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enum_from_ast<'a>(cx: &Ctxt, variants: &'a [syn::Variant]) -> Vec<Variant<'a>> {
|
fn enum_from_ast<'a>(
|
||||||
|
cx: &Ctxt,
|
||||||
|
variants: &'a [syn::Variant],
|
||||||
|
container_default: &attr::Default,
|
||||||
|
) -> Vec<Variant<'a>> {
|
||||||
variants
|
variants
|
||||||
.iter()
|
.iter()
|
||||||
.map(
|
.map(|variant| {
|
||||||
|variant| {
|
let attrs = attr::Variant::from_ast(cx, variant);
|
||||||
let attrs = attr::Variant::from_ast(cx, variant);
|
let (style, fields) =
|
||||||
let (style, fields) = struct_from_ast(cx, &variant.data, Some(&attrs));
|
struct_from_ast(cx, &variant.data, Some(&attrs), container_default);
|
||||||
Variant {
|
Variant {
|
||||||
ident: variant.ident.clone(),
|
ident: variant.ident.clone(),
|
||||||
attrs: attrs,
|
attrs: attrs,
|
||||||
style: style,
|
style: style,
|
||||||
fields: fields,
|
fields: fields,
|
||||||
}
|
}
|
||||||
},
|
})
|
||||||
)
|
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn struct_from_ast<'a>(cx: &Ctxt, data: &'a syn::VariantData, attrs: Option<&attr::Variant>) -> (Style, Vec<Field<'a>>) {
|
fn struct_from_ast<'a>(
|
||||||
|
cx: &Ctxt,
|
||||||
|
data: &'a syn::VariantData,
|
||||||
|
attrs: Option<&attr::Variant>,
|
||||||
|
container_default: &attr::Default,
|
||||||
|
) -> (Style, Vec<Field<'a>>) {
|
||||||
match *data {
|
match *data {
|
||||||
syn::VariantData::Struct(ref fields) => (Style::Struct, fields_from_ast(cx, fields, attrs)),
|
syn::VariantData::Struct(ref fields) => {
|
||||||
syn::VariantData::Tuple(ref fields) if fields.len() == 1 => {
|
(Style::Struct, fields_from_ast(cx, fields, attrs, container_default))
|
||||||
(Style::Newtype, fields_from_ast(cx, fields, attrs))
|
}
|
||||||
|
syn::VariantData::Tuple(ref fields) if fields.len() == 1 => (
|
||||||
|
Style::Newtype,
|
||||||
|
fields_from_ast(cx, fields, attrs, container_default),
|
||||||
|
),
|
||||||
|
syn::VariantData::Tuple(ref fields) => {
|
||||||
|
(Style::Tuple, fields_from_ast(cx, fields, attrs, container_default))
|
||||||
}
|
}
|
||||||
syn::VariantData::Tuple(ref fields) => (Style::Tuple, fields_from_ast(cx, fields, attrs)),
|
|
||||||
syn::VariantData::Unit => (Style::Unit, Vec::new()),
|
syn::VariantData::Unit => (Style::Unit, Vec::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fields_from_ast<'a>(cx: &Ctxt, fields: &'a [syn::Field], attrs: Option<&attr::Variant>) -> Vec<Field<'a>> {
|
fn fields_from_ast<'a>(
|
||||||
|
cx: &Ctxt,
|
||||||
|
fields: &'a [syn::Field],
|
||||||
|
attrs: Option<&attr::Variant>,
|
||||||
|
container_default: &attr::Default,
|
||||||
|
) -> Vec<Field<'a>> {
|
||||||
fields
|
fields
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
@@ -135,7 +155,7 @@ fn fields_from_ast<'a>(cx: &Ctxt, fields: &'a [syn::Field], attrs: Option<&attr:
|
|||||||
|(i, field)| {
|
|(i, field)| {
|
||||||
Field {
|
Field {
|
||||||
ident: field.ident.clone(),
|
ident: field.ident.clone(),
|
||||||
attrs: attr::Field::from_ast(cx, i, field, attrs),
|
attrs: attr::Field::from_ast(cx, i, field, attrs, container_default),
|
||||||
ty: &field.ty,
|
ty: &field.ty,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -714,7 +714,13 @@ pub enum Default {
|
|||||||
|
|
||||||
impl Field {
|
impl Field {
|
||||||
/// Extract out the `#[serde(...)]` attributes from a struct field.
|
/// Extract out the `#[serde(...)]` attributes from a struct field.
|
||||||
pub fn from_ast(cx: &Ctxt, index: usize, field: &syn::Field, attrs: Option<&Variant>) -> Self {
|
pub fn from_ast(
|
||||||
|
cx: &Ctxt,
|
||||||
|
index: usize,
|
||||||
|
field: &syn::Field,
|
||||||
|
attrs: Option<&Variant>,
|
||||||
|
container_default: &Default,
|
||||||
|
) -> Self {
|
||||||
let mut ser_name = Attr::none(cx, "rename");
|
let mut ser_name = Attr::none(cx, "rename");
|
||||||
let mut de_name = Attr::none(cx, "rename");
|
let mut de_name = Attr::none(cx, "rename");
|
||||||
let mut skip_serializing = BoolAttr::none(cx, "skip_serializing");
|
let mut skip_serializing = BoolAttr::none(cx, "skip_serializing");
|
||||||
@@ -881,9 +887,10 @@ impl Field {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is skip_deserializing, initialize the field to Default::default()
|
// Is skip_deserializing, initialize the field to Default::default() unless a different
|
||||||
// unless a different default is specified by `#[serde(default = "...")]`
|
// default is specified by `#[serde(default = "...")]` on ourselves or our container (e.g.
|
||||||
if skip_deserializing.0.value.is_some() {
|
// the struct we are in).
|
||||||
|
if container_default == &Default::None && skip_deserializing.0.value.is_some() {
|
||||||
default.set_if_none(Default::Default);
|
default.set_if_none(Default::Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.17.0")]
|
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.18.0")]
|
||||||
|
|
||||||
extern crate syn;
|
extern crate syn;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde_test"
|
name = "serde_test"
|
||||||
version = "1.0.19" # remember to update html_root_url
|
version = "1.0.24" # remember to update html_root_url
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
description = "Token De/Serializer for testing De/Serialize implementations"
|
description = "Token De/Serializer for testing De/Serialize implementations"
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ where
|
|||||||
///
|
///
|
||||||
/// assert_de_tokens_error::<S>(
|
/// assert_de_tokens_error::<S>(
|
||||||
/// &[
|
/// &[
|
||||||
/// Token::Struct { name: "S", len: 1 },
|
/// Token::Struct { name: "S", len: 2 },
|
||||||
/// Token::Str("x"),
|
/// Token::Str("x"),
|
||||||
/// ],
|
/// ],
|
||||||
/// "unknown field `x`, expected `a` or `b`",
|
/// "unknown field `x`, expected `a` or `b`",
|
||||||
|
|||||||
@@ -11,17 +11,17 @@ pub struct Compact<T: ?Sized>(T);
|
|||||||
|
|
||||||
/// Trait to determine whether a value is represented in human-readable or
|
/// Trait to determine whether a value is represented in human-readable or
|
||||||
/// compact form.
|
/// compact form.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// extern crate serde;
|
/// extern crate serde;
|
||||||
/// extern crate serde_test;
|
/// extern crate serde_test;
|
||||||
///
|
///
|
||||||
/// use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
/// use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
/// use serde_test::{Configure, Token, assert_tokens};
|
/// use serde_test::{Configure, Token, assert_tokens};
|
||||||
///
|
///
|
||||||
/// #[derive(Debug, PartialEq)]
|
/// #[derive(Debug, PartialEq)]
|
||||||
/// struct Example(u8, u8);
|
/// struct Example(u8, u8);
|
||||||
///
|
///
|
||||||
/// impl Serialize for Example {
|
/// impl Serialize for Example {
|
||||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
/// where S: Serializer,
|
/// where S: Serializer,
|
||||||
@@ -33,7 +33,7 @@ pub struct Compact<T: ?Sized>(T);
|
|||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// impl<'de> Deserialize<'de> for Example {
|
/// impl<'de> Deserialize<'de> for Example {
|
||||||
/// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
/// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
/// where D: Deserializer<'de>,
|
/// where D: Deserializer<'de>,
|
||||||
@@ -52,7 +52,7 @@ pub struct Compact<T: ?Sized>(T);
|
|||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// fn main() {
|
/// fn main() {
|
||||||
/// assert_tokens(
|
/// assert_tokens(
|
||||||
/// &Example(1, 0).compact(),
|
/// &Example(1, 0).compact(),
|
||||||
|
|||||||
@@ -155,7 +155,7 @@
|
|||||||
//! # }
|
//! # }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.19")]
|
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.24")]
|
||||||
|
|
||||||
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
|
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
|
||||||
// Whitelisted clippy lints
|
// Whitelisted clippy lints
|
||||||
@@ -164,6 +164,7 @@
|
|||||||
#![cfg_attr(feature = "cargo-clippy", allow(
|
#![cfg_attr(feature = "cargo-clippy", allow(
|
||||||
missing_docs_in_private_items,
|
missing_docs_in_private_items,
|
||||||
stutter,
|
stutter,
|
||||||
|
use_debug,
|
||||||
use_self,
|
use_self,
|
||||||
))]
|
))]
|
||||||
|
|
||||||
|
|||||||
+24
-6
@@ -40,25 +40,43 @@ impl<'a> Serializer<'a> {
|
|||||||
|
|
||||||
macro_rules! assert_next_token {
|
macro_rules! assert_next_token {
|
||||||
($ser:expr, $expected:ident) => {
|
($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)) => {
|
($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),* }) => {
|
($ser:expr, $expected:ident { $($k:ident),* }) => {
|
||||||
let compare = ($($k,)*);
|
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() {
|
match $ser.next_token() {
|
||||||
Some($pat) if $guard => {}
|
Some($pat) if $guard => {}
|
||||||
Some(other) => {
|
Some(other) => {
|
||||||
panic!("expected Token::{} but serialized as {}",
|
panic!("expected Token::{} but serialized as {}",
|
||||||
stringify!($expected), other);
|
$expected, other);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
panic!("expected Token::{} after end of serialized tokens",
|
panic!("expected Token::{} after end of serialized tokens",
|
||||||
stringify!($expected));
|
$expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,4 +15,4 @@ serde_derive = { path = "../serde_derive" }
|
|||||||
serde_test = { path = "../serde_test" }
|
serde_test = { path = "../serde_test" }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
compiletest_rs = { version = "0.2", optional = true }
|
compiletest_rs = { version = "0.3", optional = true }
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ fn test_default_struct() {
|
|||||||
a5: 123,
|
a5: 123,
|
||||||
},
|
},
|
||||||
&[
|
&[
|
||||||
Token::Struct { name: "DefaultStruct", len: 1 },
|
Token::Struct { name: "DefaultStruct", len: 3 },
|
||||||
|
|
||||||
Token::Str("a1"),
|
Token::Str("a1"),
|
||||||
Token::I32(1),
|
Token::I32(1),
|
||||||
@@ -309,7 +309,7 @@ fn test_elt_not_deserialize() {
|
|||||||
c: NotDeserializeStruct(123),
|
c: NotDeserializeStruct(123),
|
||||||
e: NotDeserializeEnum::Trouble,
|
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,
|
a5: 123,
|
||||||
},
|
},
|
||||||
&[
|
&[
|
||||||
Token::Struct { name: "DefaultStruct", len: 5 },
|
Token::Struct { name: "DefaultStruct", len: 3 },
|
||||||
|
|
||||||
Token::Str("whoops1"),
|
Token::Str("whoops1"),
|
||||||
Token::I32(2),
|
Token::I32(2),
|
||||||
@@ -359,7 +359,7 @@ fn test_ignore_unknown() {
|
|||||||
|
|
||||||
assert_de_tokens_error::<DenyUnknown>(
|
assert_de_tokens_error::<DenyUnknown>(
|
||||||
&[
|
&[
|
||||||
Token::Struct { name: "DenyUnknown", len: 2 },
|
Token::Struct { name: "DenyUnknown", len: 1 },
|
||||||
|
|
||||||
Token::Str("a1"),
|
Token::Str("a1"),
|
||||||
Token::I32(1),
|
Token::I32(1),
|
||||||
|
|||||||
@@ -80,6 +80,20 @@ struct StructSkipAll {
|
|||||||
#[serde(skip_deserializing)] a: i32,
|
#[serde(skip_deserializing)] a: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Debug, Deserialize)]
|
||||||
|
#[serde(default)]
|
||||||
|
struct StructSkipDefault {
|
||||||
|
#[serde(skip_deserializing)] a: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for StructSkipDefault {
|
||||||
|
fn default() -> Self {
|
||||||
|
StructSkipDefault {
|
||||||
|
a: 16,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, Deserialize)]
|
#[derive(PartialEq, Debug, Deserialize)]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
struct StructSkipAllDenyUnknown {
|
struct StructSkipAllDenyUnknown {
|
||||||
@@ -538,7 +552,7 @@ declare_tests! {
|
|||||||
Token::MapEnd,
|
Token::MapEnd,
|
||||||
],
|
],
|
||||||
Struct { a: 1, b: 2, c: 0 } => &[
|
Struct { a: 1, b: 2, c: 0 } => &[
|
||||||
Token::Struct { name: "Struct", len: 3 },
|
Token::Struct { name: "Struct", len: 2 },
|
||||||
Token::Str("a"),
|
Token::Str("a"),
|
||||||
Token::I32(1),
|
Token::I32(1),
|
||||||
|
|
||||||
@@ -570,7 +584,7 @@ declare_tests! {
|
|||||||
Token::MapEnd,
|
Token::MapEnd,
|
||||||
],
|
],
|
||||||
Struct { a: 1, b: 2, c: 0 } => &[
|
Struct { a: 1, b: 2, c: 0 } => &[
|
||||||
Token::Struct { name: "Struct", len: 3 },
|
Token::Struct { name: "Struct", len: 2 },
|
||||||
Token::Str("a"),
|
Token::Str("a"),
|
||||||
Token::I32(1),
|
Token::I32(1),
|
||||||
|
|
||||||
@@ -591,7 +605,7 @@ declare_tests! {
|
|||||||
Token::StructEnd,
|
Token::StructEnd,
|
||||||
],
|
],
|
||||||
StructSkipAll { a: 0 } => &[
|
StructSkipAll { a: 0 } => &[
|
||||||
Token::Struct { name: "StructSkipAll", len: 1 },
|
Token::Struct { name: "StructSkipAll", len: 0 },
|
||||||
Token::Str("a"),
|
Token::Str("a"),
|
||||||
Token::I32(1),
|
Token::I32(1),
|
||||||
|
|
||||||
@@ -600,6 +614,12 @@ declare_tests! {
|
|||||||
Token::StructEnd,
|
Token::StructEnd,
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
test_struct_skip_default {
|
||||||
|
StructSkipDefault { a: 16 } => &[
|
||||||
|
Token::Struct { name: "StructSkipDefault", len: 0 },
|
||||||
|
Token::StructEnd,
|
||||||
|
],
|
||||||
|
}
|
||||||
test_struct_skip_all_deny_unknown {
|
test_struct_skip_all_deny_unknown {
|
||||||
StructSkipAllDenyUnknown { a: 0 } => &[
|
StructSkipAllDenyUnknown { a: 0 } => &[
|
||||||
Token::Struct { name: "StructSkipAllDenyUnknown", len: 0 },
|
Token::Struct { name: "StructSkipAllDenyUnknown", len: 0 },
|
||||||
@@ -608,7 +628,7 @@ declare_tests! {
|
|||||||
}
|
}
|
||||||
test_struct_default {
|
test_struct_default {
|
||||||
StructDefault { a: 50, b: "overwritten".to_string() } => &[
|
StructDefault { a: 50, b: "overwritten".to_string() } => &[
|
||||||
Token::Struct { name: "StructDefault", len: 1 },
|
Token::Struct { name: "StructDefault", len: 2 },
|
||||||
Token::Str("a"),
|
Token::Str("a"),
|
||||||
Token::I32(50),
|
Token::I32(50),
|
||||||
|
|
||||||
@@ -617,7 +637,7 @@ declare_tests! {
|
|||||||
Token::StructEnd,
|
Token::StructEnd,
|
||||||
],
|
],
|
||||||
StructDefault { a: 100, b: "default".to_string() } => &[
|
StructDefault { a: 100, b: "default".to_string() } => &[
|
||||||
Token::Struct { name: "StructDefault", len: 0 },
|
Token::Struct { name: "StructDefault", len: 2 },
|
||||||
Token::StructEnd,
|
Token::StructEnd,
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
@@ -954,7 +974,7 @@ fn test_cstr_internal_null_end() {
|
|||||||
declare_error_tests! {
|
declare_error_tests! {
|
||||||
test_unknown_field<StructDenyUnknown> {
|
test_unknown_field<StructDenyUnknown> {
|
||||||
&[
|
&[
|
||||||
Token::Struct { name: "StructDenyUnknown", len: 2 },
|
Token::Struct { name: "StructDenyUnknown", len: 1 },
|
||||||
Token::Str("a"),
|
Token::Str("a"),
|
||||||
Token::I32(0),
|
Token::I32(0),
|
||||||
|
|
||||||
@@ -964,14 +984,14 @@ declare_error_tests! {
|
|||||||
}
|
}
|
||||||
test_skipped_field_is_unknown<StructDenyUnknown> {
|
test_skipped_field_is_unknown<StructDenyUnknown> {
|
||||||
&[
|
&[
|
||||||
Token::Struct { name: "StructDenyUnknown", len: 2 },
|
Token::Struct { name: "StructDenyUnknown", len: 1 },
|
||||||
Token::Str("b"),
|
Token::Str("b"),
|
||||||
],
|
],
|
||||||
"unknown field `b`, expected `a`",
|
"unknown field `b`, expected `a`",
|
||||||
}
|
}
|
||||||
test_skip_all_deny_unknown<StructSkipAllDenyUnknown> {
|
test_skip_all_deny_unknown<StructSkipAllDenyUnknown> {
|
||||||
&[
|
&[
|
||||||
Token::Struct { name: "StructSkipAllDenyUnknown", len: 1 },
|
Token::Struct { name: "StructSkipAllDenyUnknown", len: 0 },
|
||||||
Token::Str("a"),
|
Token::Str("a"),
|
||||||
],
|
],
|
||||||
"unknown field `a`, there are no fields",
|
"unknown field `a`, there are no fields",
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ use self::serde::de::{DeserializeOwned, Deserializer};
|
|||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
use std::option::Option as StdOption;
|
||||||
use std::result::Result as StdResult;
|
use std::result::Result as StdResult;
|
||||||
|
|
||||||
// Try to trip up the generated code if it fails to use fully qualified paths.
|
// Try to trip up the generated code if it fails to use fully qualified paths.
|
||||||
@@ -32,6 +33,12 @@ struct Result;
|
|||||||
struct Ok;
|
struct Ok;
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
struct Err;
|
struct Err;
|
||||||
|
#[allow(dead_code)]
|
||||||
|
struct Option;
|
||||||
|
#[allow(dead_code)]
|
||||||
|
struct Some;
|
||||||
|
#[allow(dead_code)]
|
||||||
|
struct None;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -56,7 +63,7 @@ fn test_gen() {
|
|||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct WithRef<'a, T: 'a> {
|
struct WithRef<'a, T: 'a> {
|
||||||
#[serde(skip_deserializing)]
|
#[serde(skip_deserializing)]
|
||||||
t: Option<&'a T>,
|
t: StdOption<&'a T>,
|
||||||
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
|
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
|
||||||
x: X,
|
x: X,
|
||||||
}
|
}
|
||||||
@@ -77,9 +84,9 @@ fn test_gen() {
|
|||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct NoBounds<T> {
|
struct NoBounds<T> {
|
||||||
t: T,
|
t: T,
|
||||||
option: Option<T>,
|
option: StdOption<T>,
|
||||||
boxed: Box<T>,
|
boxed: Box<T>,
|
||||||
option_boxed: Option<Box<T>>,
|
option_boxed: StdOption<Box<T>>,
|
||||||
}
|
}
|
||||||
assert::<NoBounds<i32>>();
|
assert::<NoBounds<i32>>();
|
||||||
|
|
||||||
@@ -175,8 +182,8 @@ fn test_gen() {
|
|||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct OptionStatic<'a> {
|
struct OptionStatic<'a> {
|
||||||
a: Option<&'a str>,
|
a: StdOption<&'a str>,
|
||||||
b: Option<&'static str>,
|
b: StdOption<&'static str>,
|
||||||
}
|
}
|
||||||
assert_ser::<OptionStatic>();
|
assert_ser::<OptionStatic>();
|
||||||
|
|
||||||
|
|||||||
@@ -786,7 +786,7 @@ fn test_adjacently_tagged_enum() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// unit with no content
|
// unit with no content
|
||||||
assert_tokens(
|
assert_ser_tokens(
|
||||||
&AdjacentlyTagged::Unit::<u8>,
|
&AdjacentlyTagged::Unit::<u8>,
|
||||||
&[
|
&[
|
||||||
Token::Struct { name: "AdjacentlyTagged", len: 1 },
|
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
|
// unit with tag first
|
||||||
assert_de_tokens(
|
assert_de_tokens(
|
||||||
&AdjacentlyTagged::Unit::<u8>,
|
&AdjacentlyTagged::Unit::<u8>,
|
||||||
&[
|
&[
|
||||||
Token::Struct { name: "AdjacentlyTagged", len: 1 },
|
Token::Struct { name: "AdjacentlyTagged", len: 2 },
|
||||||
|
|
||||||
Token::Str("t"),
|
Token::Str("t"),
|
||||||
Token::Str("Unit"),
|
Token::Str("Unit"),
|
||||||
@@ -818,7 +831,7 @@ fn test_adjacently_tagged_enum() {
|
|||||||
assert_de_tokens(
|
assert_de_tokens(
|
||||||
&AdjacentlyTagged::Unit::<u8>,
|
&AdjacentlyTagged::Unit::<u8>,
|
||||||
&[
|
&[
|
||||||
Token::Struct { name: "AdjacentlyTagged", len: 1 },
|
Token::Struct { name: "AdjacentlyTagged", len: 2 },
|
||||||
|
|
||||||
Token::Str("c"),
|
Token::Str("c"),
|
||||||
Token::Unit,
|
Token::Unit,
|
||||||
@@ -834,7 +847,7 @@ fn test_adjacently_tagged_enum() {
|
|||||||
assert_de_tokens(
|
assert_de_tokens(
|
||||||
&AdjacentlyTagged::Unit::<u8>,
|
&AdjacentlyTagged::Unit::<u8>,
|
||||||
&[
|
&[
|
||||||
Token::Struct { name: "AdjacentlyTagged", len: 3 },
|
Token::Struct { name: "AdjacentlyTagged", len: 2 },
|
||||||
|
|
||||||
Token::Str("f"),
|
Token::Str("f"),
|
||||||
Token::Unit,
|
Token::Unit,
|
||||||
@@ -975,7 +988,7 @@ fn test_adjacently_tagged_enum_deny_unknown_fields() {
|
|||||||
assert_de_tokens(
|
assert_de_tokens(
|
||||||
&AdjacentlyTagged::Unit,
|
&AdjacentlyTagged::Unit,
|
||||||
&[
|
&[
|
||||||
Token::Struct { name: "AdjacentlyTagged", len: 2},
|
Token::Struct { name: "AdjacentlyTagged", len: 2 },
|
||||||
|
|
||||||
Token::Str("t"),
|
Token::Str("t"),
|
||||||
Token::Str("Unit"),
|
Token::Str("Unit"),
|
||||||
@@ -989,7 +1002,7 @@ fn test_adjacently_tagged_enum_deny_unknown_fields() {
|
|||||||
|
|
||||||
assert_de_tokens_error::<AdjacentlyTagged>(
|
assert_de_tokens_error::<AdjacentlyTagged>(
|
||||||
&[
|
&[
|
||||||
Token::Struct { name: "AdjacentlyTagged", len: 3},
|
Token::Struct { name: "AdjacentlyTagged", len: 2 },
|
||||||
|
|
||||||
Token::Str("t"),
|
Token::Str("t"),
|
||||||
Token::Str("Unit"),
|
Token::Str("Unit"),
|
||||||
@@ -1004,7 +1017,7 @@ fn test_adjacently_tagged_enum_deny_unknown_fields() {
|
|||||||
|
|
||||||
assert_de_tokens_error::<AdjacentlyTagged>(
|
assert_de_tokens_error::<AdjacentlyTagged>(
|
||||||
&[
|
&[
|
||||||
Token::Struct { name: "AdjacentlyTagged", len: 3},
|
Token::Struct { name: "AdjacentlyTagged", len: 2 },
|
||||||
|
|
||||||
Token::Str("h"),
|
Token::Str("h"),
|
||||||
],
|
],
|
||||||
@@ -1013,7 +1026,7 @@ fn test_adjacently_tagged_enum_deny_unknown_fields() {
|
|||||||
|
|
||||||
assert_de_tokens_error::<AdjacentlyTagged>(
|
assert_de_tokens_error::<AdjacentlyTagged>(
|
||||||
&[
|
&[
|
||||||
Token::Struct { name: "AdjacentlyTagged", len: 3},
|
Token::Struct { name: "AdjacentlyTagged", len: 2 },
|
||||||
|
|
||||||
Token::Str("c"),
|
Token::Str("c"),
|
||||||
Token::Unit,
|
Token::Unit,
|
||||||
|
|||||||
Reference in New Issue
Block a user