Compare commits

...

21 Commits

Author SHA1 Message Date
David Tolnay b7eb42aa6b Release 1.0.24 2017-12-09 14:43:55 -08:00
David Tolnay 750f8ba299 Clean up trailing whitespace 2017-12-09 14:42:59 -08:00
David Tolnay 49cdef074d Merge pull request #1115 from Binero/master
Solved #1105.
2017-12-08 08:57:31 -08:00
Jeroen Bollen aa86b04714 Adressed concerns raised by @oli-obk.
Specifically:
 - Change identation in `de.rs`.
 - Make `attr::Field` take a `attr::Default` as opposed to the entire parent `attr::Container`.
2017-12-08 15:13:05 +01:00
Jeroen Bollen c887a0b472 Solved #1105.
When a field should be skipped during deserialization, it will not use its own Default implementation
when the container structure has `#[serde(default)]` set.
2017-12-06 21:14:02 +01:00
David Tolnay 0c34e06e51 Merge pull request #1106 from khuey/inlines
Inline various deserialization helper methods.
2017-12-02 15:57:07 -08:00
Kyle Huey 4a0c4e0c25 Mark size_hint::cautious as inline. 2017-12-01 14:31:52 -08:00
David Tolnay 8c34e0940f Release 1.0.23 2017-11-29 22:26:32 -08:00
David Tolnay eb6bf16a51 Revert "Catch wrong field names length in serde_test"
There are at least two reasonable things to expect the len field to
check: the length of the fields array passed to deserialize_struct, or
the number of field tokens. Even beyond these, in some cases it can be
useful to test deserialization with a bogus len to test how the
Deserialize impl reacts to an incorrect size_hint.

This reverts commit 436cafb0a3 which was
released in serde_test 1.0.20.
2017-11-29 22:21:05 -08:00
David Tolnay 797d049db5 Release 1.0.22 2017-11-29 20:01:43 -08:00
David Tolnay d61a373f12 Merge pull request #1104 from serde-rs/abs
Fix missing absolute paths in deserialize_seq
2017-11-29 19:58:21 -08:00
David Tolnay e0eea551b4 Fix missing absolute paths in deserialize_seq 2017-11-29 19:45:22 -08:00
David Tolnay c650a92bf7 Update to compiletest-rs 0.3 to fix "every suggestion should have at least one span" 2017-11-24 17:12:58 -08:00
David Tolnay f218f4d7bf Release 1.0.21 2017-11-15 22:24:18 -08:00
Alex Shapiro 8c0a2015be Fix error when deserializing untagged enum
Serde's `ContentDeserializer` and `ContentRefDeserializer`
cannot deserialize struct enum variant associated data when
that data is encoded as a sequence. This failure leads to
errors when decoding an enum nested in another untagged
enum. For example:

    #[derive(Serialize, Deserialize)]
    #[serde(untagged)]
    enum Foo {
        A(Bar),
    }

    #[derive(Serialize, Deserialize)]
    enum Bar {
        B{f1: String},
    }

    let data1 = Foo::A(Bar::B{f1: "Hello".into()});
    let bytes = rmp_serde::to_vec(&data1).unwrap();
    let data2 = rmp_serde::from_slice::<Foo>(&bytes).unwrap();

Deserializing fails with the error `Syntax("data did not
match any variant of untagged enum Foo")`, but the
underlying failure occurs when decoding the associated data
of `Bar::B`.

This pull request fixes the issue by allowing
`ContentDeserializer` and `ContentRefDeserializer` to
deserialize sequence-encoded struct enum variant data.
2017-11-15 21:56:33 -08:00
David Tolnay 4773863e3a Release 1.0.20 2017-11-12 10:29:08 -08:00
David Tolnay 80cd9c7617 Merge pull request #1091 from serde-rs/fields-len
Catch wrong field names length in serde_test
2017-11-12 10:28:26 -08:00
David Tolnay 436cafb0a3 Catch wrong field names length in serde_test 2017-11-12 10:16:43 -08:00
David Tolnay 98bb02e9b4 Whitelist use of Debug in serde_test 2017-11-07 10:00:18 -08:00
David Tolnay 142439088c Merge pull request #1086 from Marwes/better_errors
Print the contents of the expected token when a serialize assert fails
2017-11-07 09:53:58 -08:00
Markus Westerlind ce81288235 Print the contents of the expected token when a serialize assert fails
Before
```
expected Token::Str but serialized as Str(“F9168C5E-CEB2-4FAA-B6BF-329BF39FA1E4")
```
After
```
expected Token::Str(“f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4”) but serialized as Str(“F9168C5E-CEB2-4FAA-B6BF-329BF39FA1E4")
```
2017-11-07 14:22:42 +01:00
20 changed files with 196 additions and 80 deletions
+1 -1
View File
@@ -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
View File
@@ -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)]
+7
View File
@@ -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"),),
} }
+2 -2
View File
@@ -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
View File
@@ -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 => {
+1 -1
View File
@@ -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 -1
View File
@@ -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."
+42 -22
View File
@@ -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,
} }
}, },
+11 -4
View File
@@ -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);
} }
+1 -1
View File
@@ -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 -1
View File
@@ -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"
+1 -1
View File
@@ -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`",
+6 -6
View File
@@ -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(),
+2 -1
View File
@@ -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
View File
@@ -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);
} }
} }
}; };
+1 -1
View File
@@ -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 }
+4 -4
View File
@@ -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),
+28 -8
View File
@@ -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",
+12 -5
View File
@@ -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>();
+21 -8
View File
@@ -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,