2016-04-24 12:59:57 -05:00
|
|
|
extern crate serde;
|
|
|
|
use self::serde::{Serialize, Serializer, Deserialize, Deserializer};
|
2016-02-15 19:39:46 -06:00
|
|
|
|
2016-06-28 23:47:54 -05:00
|
|
|
extern crate serde_test;
|
|
|
|
use self::serde_test::{
|
2016-01-10 21:34:48 -06:00
|
|
|
Error,
|
|
|
|
Token,
|
|
|
|
assert_tokens,
|
|
|
|
assert_ser_tokens,
|
|
|
|
assert_de_tokens,
|
|
|
|
assert_de_tokens_error
|
|
|
|
};
|
2015-04-02 00:14:28 -05:00
|
|
|
|
feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:
struct Test<A, B, C> {
a: X<A>
#[serde(skip_serializing)]
b: B
#[serde(serialize_with="...")]
c: C
}
Used to be:
impl<A, B, C> Serialize for Test<A, B, C>
where A: Serialize,
B: Serialize,
C: Serialize,
{ ... }
Now it is:
impl<A, B, C> Serialize for Test<A, B, C>
where X<A>: Serialize,
{ ... }
Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 14:17:29 -06:00
|
|
|
trait MyDefault: Sized {
|
2016-02-12 23:53:35 -06:00
|
|
|
fn my_default() -> Self;
|
feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:
struct Test<A, B, C> {
a: X<A>
#[serde(skip_serializing)]
b: B
#[serde(serialize_with="...")]
c: C
}
Used to be:
impl<A, B, C> Serialize for Test<A, B, C>
where A: Serialize,
B: Serialize,
C: Serialize,
{ ... }
Now it is:
impl<A, B, C> Serialize for Test<A, B, C>
where X<A>: Serialize,
{ ... }
Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 14:17:29 -06:00
|
|
|
}
|
2016-02-13 00:05:02 -06:00
|
|
|
|
feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:
struct Test<A, B, C> {
a: X<A>
#[serde(skip_serializing)]
b: B
#[serde(serialize_with="...")]
c: C
}
Used to be:
impl<A, B, C> Serialize for Test<A, B, C>
where A: Serialize,
B: Serialize,
C: Serialize,
{ ... }
Now it is:
impl<A, B, C> Serialize for Test<A, B, C>
where X<A>: Serialize,
{ ... }
Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 14:17:29 -06:00
|
|
|
trait ShouldSkip: Sized {
|
2016-02-13 00:05:02 -06:00
|
|
|
fn should_skip(&self) -> bool;
|
feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:
struct Test<A, B, C> {
a: X<A>
#[serde(skip_serializing)]
b: B
#[serde(serialize_with="...")]
c: C
}
Used to be:
impl<A, B, C> Serialize for Test<A, B, C>
where A: Serialize,
B: Serialize,
C: Serialize,
{ ... }
Now it is:
impl<A, B, C> Serialize for Test<A, B, C>
where X<A>: Serialize,
{ ... }
Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 14:17:29 -06:00
|
|
|
}
|
2016-02-15 19:39:46 -06:00
|
|
|
|
feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:
struct Test<A, B, C> {
a: X<A>
#[serde(skip_serializing)]
b: B
#[serde(serialize_with="...")]
c: C
}
Used to be:
impl<A, B, C> Serialize for Test<A, B, C>
where A: Serialize,
B: Serialize,
C: Serialize,
{ ... }
Now it is:
impl<A, B, C> Serialize for Test<A, B, C>
where X<A>: Serialize,
{ ... }
Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 14:17:29 -06:00
|
|
|
trait SerializeWith: Sized {
|
2016-02-15 19:39:46 -06:00
|
|
|
fn serialize_with<S>(&self, ser: &mut S) -> Result<(), S::Error>
|
|
|
|
where S: Serializer;
|
feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:
struct Test<A, B, C> {
a: X<A>
#[serde(skip_serializing)]
b: B
#[serde(serialize_with="...")]
c: C
}
Used to be:
impl<A, B, C> Serialize for Test<A, B, C>
where A: Serialize,
B: Serialize,
C: Serialize,
{ ... }
Now it is:
impl<A, B, C> Serialize for Test<A, B, C>
where X<A>: Serialize,
{ ... }
Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 14:17:29 -06:00
|
|
|
}
|
2016-02-15 22:43:11 -06:00
|
|
|
|
feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:
struct Test<A, B, C> {
a: X<A>
#[serde(skip_serializing)]
b: B
#[serde(serialize_with="...")]
c: C
}
Used to be:
impl<A, B, C> Serialize for Test<A, B, C>
where A: Serialize,
B: Serialize,
C: Serialize,
{ ... }
Now it is:
impl<A, B, C> Serialize for Test<A, B, C>
where X<A>: Serialize,
{ ... }
Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 14:17:29 -06:00
|
|
|
trait DeserializeWith: Sized {
|
2016-02-15 22:43:11 -06:00
|
|
|
fn deserialize_with<D>(de: &mut D) -> Result<Self, D::Error>
|
|
|
|
where D: Deserializer;
|
2016-02-12 23:53:35 -06:00
|
|
|
}
|
|
|
|
|
feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:
struct Test<A, B, C> {
a: X<A>
#[serde(skip_serializing)]
b: B
#[serde(serialize_with="...")]
c: C
}
Used to be:
impl<A, B, C> Serialize for Test<A, B, C>
where A: Serialize,
B: Serialize,
C: Serialize,
{ ... }
Now it is:
impl<A, B, C> Serialize for Test<A, B, C>
where X<A>: Serialize,
{ ... }
Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 14:17:29 -06:00
|
|
|
impl MyDefault for i32 {
|
2016-02-12 23:53:35 -06:00
|
|
|
fn my_default() -> Self { 123 }
|
feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:
struct Test<A, B, C> {
a: X<A>
#[serde(skip_serializing)]
b: B
#[serde(serialize_with="...")]
c: C
}
Used to be:
impl<A, B, C> Serialize for Test<A, B, C>
where A: Serialize,
B: Serialize,
C: Serialize,
{ ... }
Now it is:
impl<A, B, C> Serialize for Test<A, B, C>
where X<A>: Serialize,
{ ... }
Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 14:17:29 -06:00
|
|
|
}
|
2016-02-13 00:05:02 -06:00
|
|
|
|
feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:
struct Test<A, B, C> {
a: X<A>
#[serde(skip_serializing)]
b: B
#[serde(serialize_with="...")]
c: C
}
Used to be:
impl<A, B, C> Serialize for Test<A, B, C>
where A: Serialize,
B: Serialize,
C: Serialize,
{ ... }
Now it is:
impl<A, B, C> Serialize for Test<A, B, C>
where X<A>: Serialize,
{ ... }
Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 14:17:29 -06:00
|
|
|
impl ShouldSkip for i32 {
|
2016-02-13 00:05:02 -06:00
|
|
|
fn should_skip(&self) -> bool { *self == 123 }
|
feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:
struct Test<A, B, C> {
a: X<A>
#[serde(skip_serializing)]
b: B
#[serde(serialize_with="...")]
c: C
}
Used to be:
impl<A, B, C> Serialize for Test<A, B, C>
where A: Serialize,
B: Serialize,
C: Serialize,
{ ... }
Now it is:
impl<A, B, C> Serialize for Test<A, B, C>
where X<A>: Serialize,
{ ... }
Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 14:17:29 -06:00
|
|
|
}
|
2016-02-15 19:39:46 -06:00
|
|
|
|
feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:
struct Test<A, B, C> {
a: X<A>
#[serde(skip_serializing)]
b: B
#[serde(serialize_with="...")]
c: C
}
Used to be:
impl<A, B, C> Serialize for Test<A, B, C>
where A: Serialize,
B: Serialize,
C: Serialize,
{ ... }
Now it is:
impl<A, B, C> Serialize for Test<A, B, C>
where X<A>: Serialize,
{ ... }
Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 14:17:29 -06:00
|
|
|
impl SerializeWith for i32 {
|
2016-02-15 19:39:46 -06:00
|
|
|
fn serialize_with<S>(&self, ser: &mut S) -> Result<(), S::Error>
|
|
|
|
where S: Serializer
|
|
|
|
{
|
|
|
|
if *self == 123 {
|
|
|
|
true.serialize(ser)
|
|
|
|
} else {
|
|
|
|
false.serialize(ser)
|
|
|
|
}
|
|
|
|
}
|
feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:
struct Test<A, B, C> {
a: X<A>
#[serde(skip_serializing)]
b: B
#[serde(serialize_with="...")]
c: C
}
Used to be:
impl<A, B, C> Serialize for Test<A, B, C>
where A: Serialize,
B: Serialize,
C: Serialize,
{ ... }
Now it is:
impl<A, B, C> Serialize for Test<A, B, C>
where X<A>: Serialize,
{ ... }
Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 14:17:29 -06:00
|
|
|
}
|
2016-02-15 22:43:11 -06:00
|
|
|
|
feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:
struct Test<A, B, C> {
a: X<A>
#[serde(skip_serializing)]
b: B
#[serde(serialize_with="...")]
c: C
}
Used to be:
impl<A, B, C> Serialize for Test<A, B, C>
where A: Serialize,
B: Serialize,
C: Serialize,
{ ... }
Now it is:
impl<A, B, C> Serialize for Test<A, B, C>
where X<A>: Serialize,
{ ... }
Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 14:17:29 -06:00
|
|
|
impl DeserializeWith for i32 {
|
2016-02-15 22:43:11 -06:00
|
|
|
fn deserialize_with<D>(de: &mut D) -> Result<Self, D::Error>
|
|
|
|
where D: Deserializer
|
|
|
|
{
|
|
|
|
if try!(Deserialize::deserialize(de)) {
|
|
|
|
Ok(123)
|
|
|
|
} else {
|
|
|
|
Ok(2)
|
|
|
|
}
|
|
|
|
}
|
2016-02-12 23:53:35 -06:00
|
|
|
}
|
|
|
|
|
2015-04-02 00:14:28 -05:00
|
|
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
2016-04-13 02:34:29 -05:00
|
|
|
struct DefaultStruct<A, B, C, D, E>
|
2016-04-13 01:42:24 -05:00
|
|
|
where C: MyDefault,
|
|
|
|
E: MyDefault,
|
|
|
|
{
|
2016-02-12 23:53:35 -06:00
|
|
|
a1: A,
|
2015-04-02 00:14:28 -05:00
|
|
|
#[serde(default)]
|
2016-02-12 23:53:35 -06:00
|
|
|
a2: B,
|
feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:
struct Test<A, B, C> {
a: X<A>
#[serde(skip_serializing)]
b: B
#[serde(serialize_with="...")]
c: C
}
Used to be:
impl<A, B, C> Serialize for Test<A, B, C>
where A: Serialize,
B: Serialize,
C: Serialize,
{ ... }
Now it is:
impl<A, B, C> Serialize for Test<A, B, C>
where X<A>: Serialize,
{ ... }
Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 14:17:29 -06:00
|
|
|
#[serde(default="MyDefault::my_default")]
|
2016-02-12 23:53:35 -06:00
|
|
|
a3: C,
|
2016-04-13 01:42:24 -05:00
|
|
|
#[serde(skip_deserializing)]
|
|
|
|
a4: D,
|
|
|
|
#[serde(skip_deserializing, default="MyDefault::my_default")]
|
|
|
|
a5: E,
|
2016-02-12 23:53:35 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_default_struct() {
|
|
|
|
assert_de_tokens(
|
2016-04-13 01:42:24 -05:00
|
|
|
&DefaultStruct { a1: 1, a2: 2, a3: 3, a4: 0, a5: 123 },
|
2016-06-29 01:50:19 -05:00
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::StructStart("DefaultStruct", 3),
|
2016-02-12 23:53:35 -06:00
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::StructSep,
|
2016-02-12 23:53:35 -06:00
|
|
|
Token::Str("a1"),
|
|
|
|
Token::I32(1),
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::StructSep,
|
2016-02-12 23:53:35 -06:00
|
|
|
Token::Str("a2"),
|
|
|
|
Token::I32(2),
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::StructSep,
|
2016-02-12 23:53:35 -06:00
|
|
|
Token::Str("a3"),
|
|
|
|
Token::I32(3),
|
|
|
|
|
2016-04-13 01:42:24 -05:00
|
|
|
Token::StructSep,
|
|
|
|
Token::Str("a4"),
|
|
|
|
Token::I32(4),
|
|
|
|
|
|
|
|
Token::StructSep,
|
|
|
|
Token::Str("a5"),
|
|
|
|
Token::I32(5),
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::StructEnd,
|
2016-02-12 23:53:35 -06:00
|
|
|
]
|
|
|
|
);
|
|
|
|
|
|
|
|
assert_de_tokens(
|
2016-04-13 01:42:24 -05:00
|
|
|
&DefaultStruct { a1: 1, a2: 0, a3: 123, a4: 0, a5: 123 },
|
2016-06-29 01:50:19 -05:00
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::StructStart("DefaultStruct", 1),
|
2016-02-12 23:53:35 -06:00
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::StructSep,
|
2016-02-12 23:53:35 -06:00
|
|
|
Token::Str("a1"),
|
|
|
|
Token::I32(1),
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::StructEnd,
|
2016-02-12 23:53:35 -06:00
|
|
|
]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
2016-04-13 02:34:29 -05:00
|
|
|
enum DefaultEnum<A, B, C, D, E>
|
2016-04-13 01:42:24 -05:00
|
|
|
where C: MyDefault,
|
|
|
|
E: MyDefault
|
|
|
|
{
|
2016-02-12 23:53:35 -06:00
|
|
|
Struct {
|
|
|
|
a1: A,
|
|
|
|
#[serde(default)]
|
|
|
|
a2: B,
|
feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:
struct Test<A, B, C> {
a: X<A>
#[serde(skip_serializing)]
b: B
#[serde(serialize_with="...")]
c: C
}
Used to be:
impl<A, B, C> Serialize for Test<A, B, C>
where A: Serialize,
B: Serialize,
C: Serialize,
{ ... }
Now it is:
impl<A, B, C> Serialize for Test<A, B, C>
where X<A>: Serialize,
{ ... }
Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 14:17:29 -06:00
|
|
|
#[serde(default="MyDefault::my_default")]
|
2016-02-12 23:53:35 -06:00
|
|
|
a3: C,
|
2016-04-13 01:42:24 -05:00
|
|
|
#[serde(skip_deserializing)]
|
|
|
|
a4: D,
|
|
|
|
#[serde(skip_deserializing, default="MyDefault::my_default")]
|
|
|
|
a5: E,
|
2016-02-12 23:53:35 -06:00
|
|
|
}
|
2015-04-02 00:14:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2016-02-12 23:53:35 -06:00
|
|
|
fn test_default_enum() {
|
2015-08-27 22:01:09 -05:00
|
|
|
assert_de_tokens(
|
2016-04-13 01:42:24 -05:00
|
|
|
&DefaultEnum::Struct { a1: 1, a2: 2, a3: 3, a4: 0, a5: 123 },
|
2016-06-29 01:50:19 -05:00
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::EnumMapStart("DefaultEnum", "Struct", 5),
|
2015-08-27 22:01:09 -05:00
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::EnumMapSep,
|
2015-08-27 22:01:09 -05:00
|
|
|
Token::Str("a1"),
|
|
|
|
Token::I32(1),
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::EnumMapSep,
|
2015-08-27 22:01:09 -05:00
|
|
|
Token::Str("a2"),
|
|
|
|
Token::I32(2),
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::EnumMapSep,
|
2016-02-12 23:53:35 -06:00
|
|
|
Token::Str("a3"),
|
|
|
|
Token::I32(3),
|
|
|
|
|
2016-04-13 01:42:24 -05:00
|
|
|
Token::EnumMapSep,
|
|
|
|
Token::Str("a4"),
|
|
|
|
Token::I32(4),
|
|
|
|
|
|
|
|
Token::EnumMapSep,
|
|
|
|
Token::Str("a5"),
|
|
|
|
Token::I32(5),
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::EnumMapEnd,
|
2015-08-27 22:01:09 -05:00
|
|
|
]
|
|
|
|
);
|
|
|
|
|
|
|
|
assert_de_tokens(
|
2016-04-13 01:42:24 -05:00
|
|
|
&DefaultEnum::Struct { a1: 1, a2: 0, a3: 123, a4: 0, a5: 123 },
|
2016-06-29 01:50:19 -05:00
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::EnumMapStart("DefaultEnum", "Struct", 5),
|
2015-04-02 00:14:28 -05:00
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::EnumMapSep,
|
2015-08-27 22:01:09 -05:00
|
|
|
Token::Str("a1"),
|
|
|
|
Token::I32(1),
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::EnumMapEnd,
|
2015-08-27 22:01:09 -05:00
|
|
|
]
|
|
|
|
);
|
2015-04-02 00:14:28 -05:00
|
|
|
}
|
|
|
|
|
2016-04-13 02:34:29 -05:00
|
|
|
// Does not implement std::default::Default.
|
|
|
|
#[derive(Debug, PartialEq, Deserialize)]
|
|
|
|
struct NoStdDefault(i8);
|
|
|
|
|
|
|
|
impl MyDefault for NoStdDefault {
|
|
|
|
fn my_default() -> Self {
|
|
|
|
NoStdDefault(123)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Deserialize)]
|
|
|
|
struct ContainsNoStdDefault<A: MyDefault> {
|
|
|
|
#[serde(default="MyDefault::my_default")]
|
|
|
|
a: A,
|
|
|
|
}
|
|
|
|
|
|
|
|
// Tests that a struct field does not need to implement std::default::Default if
|
|
|
|
// it is annotated with `default=...`.
|
|
|
|
#[test]
|
|
|
|
fn test_no_std_default() {
|
|
|
|
assert_de_tokens(
|
|
|
|
&ContainsNoStdDefault { a: NoStdDefault(123) },
|
2016-06-29 01:50:19 -05:00
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::StructStart("ContainsNoStdDefault", 1),
|
2016-04-13 02:34:29 -05:00
|
|
|
Token::StructEnd,
|
|
|
|
]
|
|
|
|
);
|
|
|
|
|
|
|
|
assert_de_tokens(
|
|
|
|
&ContainsNoStdDefault { a: NoStdDefault(8) },
|
2016-06-29 01:50:19 -05:00
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::StructStart("ContainsNoStdDefault", 1),
|
2016-04-13 02:34:29 -05:00
|
|
|
|
|
|
|
Token::StructSep,
|
|
|
|
Token::Str("a"),
|
|
|
|
Token::StructNewType("NoStdDefault"),
|
|
|
|
Token::I8(8),
|
|
|
|
|
|
|
|
Token::StructEnd,
|
|
|
|
]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Does not implement Deserialize.
|
|
|
|
#[derive(Debug, PartialEq)]
|
|
|
|
struct NotDeserializeStruct(i8);
|
|
|
|
|
|
|
|
impl Default for NotDeserializeStruct {
|
|
|
|
fn default() -> Self {
|
|
|
|
NotDeserializeStruct(123)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-07 21:57:44 -05:00
|
|
|
impl DeserializeWith for NotDeserializeStruct {
|
|
|
|
fn deserialize_with<D>(_: &mut D) -> Result<Self, D::Error>
|
|
|
|
where D: Deserializer
|
|
|
|
{
|
|
|
|
panic!()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-13 02:34:29 -05:00
|
|
|
// Does not implement Deserialize.
|
|
|
|
#[derive(Debug, PartialEq)]
|
|
|
|
enum NotDeserializeEnum { Trouble }
|
|
|
|
|
|
|
|
impl MyDefault for NotDeserializeEnum {
|
|
|
|
fn my_default() -> Self {
|
|
|
|
NotDeserializeEnum::Trouble
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Deserialize)]
|
2016-05-07 21:57:44 -05:00
|
|
|
struct ContainsNotDeserialize<A, B, C: DeserializeWith, E: MyDefault> {
|
2016-04-13 02:34:29 -05:00
|
|
|
#[serde(skip_deserializing)]
|
|
|
|
a: A,
|
|
|
|
#[serde(skip_deserializing, default)]
|
|
|
|
b: B,
|
2016-05-07 21:57:44 -05:00
|
|
|
#[serde(deserialize_with="DeserializeWith::deserialize_with", default)]
|
2016-04-13 02:34:29 -05:00
|
|
|
c: C,
|
2016-05-07 21:57:44 -05:00
|
|
|
#[serde(skip_deserializing, default="MyDefault::my_default")]
|
|
|
|
e: E,
|
2016-04-13 02:34:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Tests that a struct field does not need to implement Deserialize if it is
|
|
|
|
// annotated with skip_deserializing, whether using the std Default or a
|
|
|
|
// custom default.
|
|
|
|
#[test]
|
|
|
|
fn test_elt_not_deserialize() {
|
|
|
|
assert_de_tokens(
|
|
|
|
&ContainsNotDeserialize {
|
|
|
|
a: NotDeserializeStruct(123),
|
|
|
|
b: NotDeserializeStruct(123),
|
2016-05-07 21:57:44 -05:00
|
|
|
c: NotDeserializeStruct(123),
|
|
|
|
e: NotDeserializeEnum::Trouble,
|
2016-04-13 02:34:29 -05:00
|
|
|
},
|
2016-06-29 01:50:19 -05:00
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::StructStart("ContainsNotDeserialize", 3),
|
2016-04-13 02:34:29 -05:00
|
|
|
Token::StructEnd,
|
|
|
|
]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2016-02-15 18:02:09 -06:00
|
|
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
|
|
|
#[serde(deny_unknown_fields)]
|
|
|
|
struct DenyUnknown {
|
|
|
|
a1: i32,
|
|
|
|
}
|
|
|
|
|
2016-01-10 21:34:48 -06:00
|
|
|
#[test]
|
|
|
|
fn test_ignore_unknown() {
|
|
|
|
// 'Default' allows unknown. Basic smoke test of ignore...
|
|
|
|
assert_de_tokens(
|
2016-04-13 01:42:24 -05:00
|
|
|
&DefaultStruct { a1: 1, a2: 2, a3: 3, a4: 0, a5: 123 },
|
2016-06-29 01:50:19 -05:00
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::StructStart("DefaultStruct", 5),
|
2016-01-10 21:34:48 -06:00
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::StructSep,
|
2016-01-10 21:34:48 -06:00
|
|
|
Token::Str("whoops1"),
|
|
|
|
Token::I32(2),
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::StructSep,
|
2016-01-10 21:34:48 -06:00
|
|
|
Token::Str("a1"),
|
|
|
|
Token::I32(1),
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::StructSep,
|
2016-01-10 21:34:48 -06:00
|
|
|
Token::Str("whoops2"),
|
|
|
|
Token::SeqStart(Some(1)),
|
|
|
|
Token::SeqSep,
|
|
|
|
Token::I32(2),
|
|
|
|
Token::SeqEnd,
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::StructSep,
|
2016-01-10 21:34:48 -06:00
|
|
|
Token::Str("a2"),
|
|
|
|
Token::I32(2),
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::StructSep,
|
2016-01-10 21:34:48 -06:00
|
|
|
Token::Str("whoops3"),
|
|
|
|
Token::I32(2),
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::StructSep,
|
2016-02-12 23:53:35 -06:00
|
|
|
Token::Str("a3"),
|
|
|
|
Token::I32(3),
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::StructEnd,
|
2016-01-10 21:34:48 -06:00
|
|
|
]
|
|
|
|
);
|
|
|
|
|
2016-02-15 18:02:09 -06:00
|
|
|
assert_de_tokens_error::<DenyUnknown>(
|
2016-06-29 01:50:19 -05:00
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::StructStart("DenyUnknown", 2),
|
2016-01-10 21:34:48 -06:00
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::StructSep,
|
2016-01-10 21:34:48 -06:00
|
|
|
Token::Str("a1"),
|
|
|
|
Token::I32(1),
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::StructSep,
|
2016-01-10 21:34:48 -06:00
|
|
|
Token::Str("whoops"),
|
|
|
|
],
|
2016-06-29 00:49:13 -05:00
|
|
|
Error::UnknownField("whoops".to_owned())
|
2016-01-10 21:34:48 -06:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2016-02-15 18:02:09 -06:00
|
|
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
|
|
|
#[serde(rename="Superhero")]
|
|
|
|
struct RenameStruct {
|
|
|
|
a1: i32,
|
|
|
|
#[serde(rename="a3")]
|
|
|
|
a2: i32,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
|
|
|
#[serde(rename(serialize="SuperheroSer", deserialize="SuperheroDe"))]
|
|
|
|
struct RenameStructSerializeDeserialize {
|
|
|
|
a1: i32,
|
|
|
|
#[serde(rename(serialize="a4", deserialize="a5"))]
|
|
|
|
a2: i32,
|
|
|
|
}
|
|
|
|
|
2015-04-02 00:14:28 -05:00
|
|
|
#[test]
|
2016-02-08 10:00:38 -06:00
|
|
|
fn test_rename_struct() {
|
2015-08-27 22:01:09 -05:00
|
|
|
assert_tokens(
|
2016-02-08 10:00:38 -06:00
|
|
|
&RenameStruct { a1: 1, a2: 2 },
|
2016-06-29 01:50:19 -05:00
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::StructStart("Superhero", 2),
|
2015-08-27 22:01:09 -05:00
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::StructSep,
|
2015-08-27 22:01:09 -05:00
|
|
|
Token::Str("a1"),
|
|
|
|
Token::I32(1),
|
2015-04-02 00:14:28 -05:00
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::StructSep,
|
2015-08-27 22:01:09 -05:00
|
|
|
Token::Str("a3"),
|
|
|
|
Token::I32(2),
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::StructEnd,
|
2015-08-27 22:01:09 -05:00
|
|
|
]
|
|
|
|
);
|
2015-04-21 09:57:36 -05:00
|
|
|
|
2016-02-08 12:35:42 -06:00
|
|
|
assert_ser_tokens(
|
2016-02-08 10:00:38 -06:00
|
|
|
&RenameStructSerializeDeserialize { a1: 1, a2: 2 },
|
2016-02-08 12:35:42 -06:00
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::StructStart("SuperheroSer", 2),
|
2016-02-08 12:35:42 -06:00
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::StructSep,
|
2016-02-08 12:35:42 -06:00
|
|
|
Token::Str("a1"),
|
|
|
|
Token::I32(1),
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::StructSep,
|
2016-02-08 12:35:42 -06:00
|
|
|
Token::Str("a4"),
|
|
|
|
Token::I32(2),
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::StructEnd,
|
2016-02-08 12:35:42 -06:00
|
|
|
]
|
|
|
|
);
|
|
|
|
|
|
|
|
assert_de_tokens(
|
2016-02-08 10:00:38 -06:00
|
|
|
&RenameStructSerializeDeserialize { a1: 1, a2: 2 },
|
2016-06-29 01:50:19 -05:00
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::StructStart("SuperheroDe", 2),
|
2016-02-08 12:35:42 -06:00
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::StructSep,
|
2016-02-08 12:35:42 -06:00
|
|
|
Token::Str("a1"),
|
|
|
|
Token::I32(1),
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::StructSep,
|
2016-02-08 12:35:42 -06:00
|
|
|
Token::Str("a5"),
|
|
|
|
Token::I32(2),
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::StructEnd,
|
2016-02-08 12:35:42 -06:00
|
|
|
]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2016-02-15 18:02:09 -06:00
|
|
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
|
|
|
#[serde(rename="Superhero")]
|
|
|
|
enum RenameEnum {
|
|
|
|
#[serde(rename="bruce_wayne")]
|
|
|
|
Batman,
|
|
|
|
#[serde(rename="clark_kent")]
|
|
|
|
Superman(i8),
|
|
|
|
#[serde(rename="diana_prince")]
|
|
|
|
WonderWoman(i8, i8),
|
|
|
|
#[serde(rename="barry_allan")]
|
|
|
|
Flash {
|
|
|
|
#[serde(rename="b")]
|
|
|
|
a: i32,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Deserialize, Serialize)]
|
|
|
|
#[serde(rename(serialize="SuperheroSer", deserialize="SuperheroDe"))]
|
|
|
|
enum RenameEnumSerializeDeserialize<A> {
|
|
|
|
#[serde(rename(serialize="dick_grayson", deserialize="jason_todd"))]
|
|
|
|
Robin {
|
|
|
|
a: i8,
|
2016-06-05 13:40:30 -05:00
|
|
|
#[serde(rename(serialize="c"))]
|
|
|
|
#[serde(rename(deserialize="d"))]
|
2016-02-15 18:02:09 -06:00
|
|
|
b: A,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2016-02-08 12:35:42 -06:00
|
|
|
#[test]
|
2016-02-08 10:00:38 -06:00
|
|
|
fn test_rename_enum() {
|
|
|
|
assert_tokens(
|
|
|
|
&RenameEnum::Batman,
|
2016-06-29 01:50:19 -05:00
|
|
|
&[
|
2016-02-08 10:00:38 -06:00
|
|
|
Token::EnumUnit("Superhero", "bruce_wayne"),
|
2016-02-08 12:35:42 -06:00
|
|
|
]
|
|
|
|
);
|
|
|
|
|
2016-02-08 10:00:38 -06:00
|
|
|
assert_tokens(
|
|
|
|
&RenameEnum::Superman(0),
|
2016-06-29 01:50:19 -05:00
|
|
|
&[
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::EnumNewType("Superhero", "clark_kent"),
|
2016-02-08 10:00:38 -06:00
|
|
|
Token::I8(0),
|
|
|
|
]
|
|
|
|
);
|
|
|
|
|
|
|
|
assert_tokens(
|
|
|
|
&RenameEnum::WonderWoman(0, 1),
|
2016-06-29 01:50:19 -05:00
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::EnumSeqStart("Superhero", "diana_prince", 2),
|
2016-02-08 10:00:38 -06:00
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::EnumSeqSep,
|
2016-02-08 10:00:38 -06:00
|
|
|
Token::I8(0),
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::EnumSeqSep,
|
2016-02-08 10:00:38 -06:00
|
|
|
Token::I8(1),
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::EnumSeqEnd,
|
2016-02-08 10:00:38 -06:00
|
|
|
]
|
|
|
|
);
|
|
|
|
|
|
|
|
assert_tokens(
|
|
|
|
&RenameEnum::Flash { a: 1 },
|
2016-06-29 01:50:19 -05:00
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::EnumMapStart("Superhero", "barry_allan", 1),
|
2016-02-08 10:00:38 -06:00
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::EnumMapSep,
|
2016-02-08 10:00:38 -06:00
|
|
|
Token::Str("b"),
|
|
|
|
Token::I32(1),
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::EnumMapEnd,
|
2016-02-08 12:35:42 -06:00
|
|
|
]
|
|
|
|
);
|
|
|
|
|
|
|
|
assert_ser_tokens(
|
2016-02-08 10:00:38 -06:00
|
|
|
&RenameEnumSerializeDeserialize::Robin {
|
2016-02-08 12:35:42 -06:00
|
|
|
a: 0,
|
|
|
|
b: String::new(),
|
|
|
|
},
|
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::EnumMapStart("SuperheroSer", "dick_grayson", 2),
|
2016-02-08 12:35:42 -06:00
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::EnumMapSep,
|
2016-02-08 12:35:42 -06:00
|
|
|
Token::Str("a"),
|
|
|
|
Token::I8(0),
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::EnumMapSep,
|
2016-02-08 12:35:42 -06:00
|
|
|
Token::Str("c"),
|
|
|
|
Token::Str(""),
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::EnumMapEnd,
|
2016-02-08 12:35:42 -06:00
|
|
|
]
|
|
|
|
);
|
|
|
|
|
|
|
|
assert_de_tokens(
|
2016-02-08 10:00:38 -06:00
|
|
|
&RenameEnumSerializeDeserialize::Robin {
|
2016-02-08 12:35:42 -06:00
|
|
|
a: 0,
|
|
|
|
b: String::new(),
|
|
|
|
},
|
2016-06-29 01:50:19 -05:00
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::EnumMapStart("SuperheroDe", "jason_todd", 2),
|
2016-02-08 12:35:42 -06:00
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::EnumMapSep,
|
2016-02-08 12:35:42 -06:00
|
|
|
Token::Str("a"),
|
|
|
|
Token::I8(0),
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::EnumMapSep,
|
2016-02-08 12:35:42 -06:00
|
|
|
Token::Str("d"),
|
|
|
|
Token::Str(""),
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::EnumMapEnd,
|
2016-02-08 10:03:46 -06:00
|
|
|
]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2016-02-15 18:02:09 -06:00
|
|
|
#[derive(Debug, PartialEq, Serialize)]
|
feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:
struct Test<A, B, C> {
a: X<A>
#[serde(skip_serializing)]
b: B
#[serde(serialize_with="...")]
c: C
}
Used to be:
impl<A, B, C> Serialize for Test<A, B, C>
where A: Serialize,
B: Serialize,
C: Serialize,
{ ... }
Now it is:
impl<A, B, C> Serialize for Test<A, B, C>
where X<A>: Serialize,
{ ... }
Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 14:17:29 -06:00
|
|
|
struct SkipSerializingStruct<'a, B, C> where C: ShouldSkip {
|
2016-02-15 18:02:09 -06:00
|
|
|
a: &'a i8,
|
|
|
|
#[serde(skip_serializing)]
|
|
|
|
b: B,
|
feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:
struct Test<A, B, C> {
a: X<A>
#[serde(skip_serializing)]
b: B
#[serde(serialize_with="...")]
c: C
}
Used to be:
impl<A, B, C> Serialize for Test<A, B, C>
where A: Serialize,
B: Serialize,
C: Serialize,
{ ... }
Now it is:
impl<A, B, C> Serialize for Test<A, B, C>
where X<A>: Serialize,
{ ... }
Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 14:17:29 -06:00
|
|
|
#[serde(skip_serializing_if="ShouldSkip::should_skip")]
|
2016-02-13 00:05:02 -06:00
|
|
|
c: C,
|
2015-07-23 10:07:49 -05:00
|
|
|
}
|
2015-09-07 18:44:56 -05:00
|
|
|
|
|
|
|
#[test]
|
2016-02-15 18:02:09 -06:00
|
|
|
fn test_skip_serializing_struct() {
|
|
|
|
let a = 1;
|
2015-09-07 18:44:56 -05:00
|
|
|
assert_ser_tokens(
|
2016-02-15 18:02:09 -06:00
|
|
|
&SkipSerializingStruct {
|
|
|
|
a: &a,
|
|
|
|
b: 2,
|
2016-02-13 00:05:02 -06:00
|
|
|
c: 3,
|
2015-09-07 18:44:56 -05:00
|
|
|
},
|
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::StructStart("SkipSerializingStruct", 2),
|
2015-09-07 18:44:56 -05:00
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::StructSep,
|
2015-09-07 18:44:56 -05:00
|
|
|
Token::Str("a"),
|
|
|
|
Token::I8(1),
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::StructSep,
|
|
|
|
Token::Str("c"),
|
|
|
|
Token::I32(3),
|
|
|
|
|
|
|
|
Token::StructEnd,
|
2015-09-07 18:44:56 -05:00
|
|
|
]
|
|
|
|
);
|
|
|
|
|
2016-02-15 18:02:09 -06:00
|
|
|
assert_ser_tokens(
|
|
|
|
&SkipSerializingStruct {
|
|
|
|
a: &a,
|
|
|
|
b: 2,
|
2016-02-13 00:05:02 -06:00
|
|
|
c: 123,
|
2015-09-07 18:44:56 -05:00
|
|
|
},
|
2016-02-15 18:02:09 -06:00
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::StructStart("SkipSerializingStruct", 1),
|
2015-09-07 18:44:56 -05:00
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::StructSep,
|
2015-09-07 18:44:56 -05:00
|
|
|
Token::Str("a"),
|
|
|
|
Token::I8(1),
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::StructEnd,
|
2015-09-07 18:44:56 -05:00
|
|
|
]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2016-02-15 18:02:09 -06:00
|
|
|
#[derive(Debug, PartialEq, Serialize)]
|
feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:
struct Test<A, B, C> {
a: X<A>
#[serde(skip_serializing)]
b: B
#[serde(serialize_with="...")]
c: C
}
Used to be:
impl<A, B, C> Serialize for Test<A, B, C>
where A: Serialize,
B: Serialize,
C: Serialize,
{ ... }
Now it is:
impl<A, B, C> Serialize for Test<A, B, C>
where X<A>: Serialize,
{ ... }
Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 14:17:29 -06:00
|
|
|
enum SkipSerializingEnum<'a, B, C> where C: ShouldSkip {
|
2016-02-15 18:02:09 -06:00
|
|
|
Struct {
|
|
|
|
a: &'a i8,
|
|
|
|
#[serde(skip_serializing)]
|
|
|
|
_b: B,
|
feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:
struct Test<A, B, C> {
a: X<A>
#[serde(skip_serializing)]
b: B
#[serde(serialize_with="...")]
c: C
}
Used to be:
impl<A, B, C> Serialize for Test<A, B, C>
where A: Serialize,
B: Serialize,
C: Serialize,
{ ... }
Now it is:
impl<A, B, C> Serialize for Test<A, B, C>
where X<A>: Serialize,
{ ... }
Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 14:17:29 -06:00
|
|
|
#[serde(skip_serializing_if="ShouldSkip::should_skip")]
|
2016-02-13 00:05:02 -06:00
|
|
|
c: C,
|
2016-02-15 18:02:09 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-07 18:44:56 -05:00
|
|
|
#[test]
|
2016-02-15 18:02:09 -06:00
|
|
|
fn test_skip_serializing_enum() {
|
|
|
|
let a = 1;
|
2015-09-07 18:44:56 -05:00
|
|
|
assert_ser_tokens(
|
2016-02-15 18:02:09 -06:00
|
|
|
&SkipSerializingEnum::Struct {
|
|
|
|
a: &a,
|
|
|
|
_b: 2,
|
2016-02-13 00:05:02 -06:00
|
|
|
c: 3,
|
2015-09-07 18:44:56 -05:00
|
|
|
},
|
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::EnumMapStart("SkipSerializingEnum", "Struct", 2),
|
2015-09-07 18:44:56 -05:00
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::EnumMapSep,
|
2015-09-07 18:44:56 -05:00
|
|
|
Token::Str("a"),
|
|
|
|
Token::I8(1),
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::EnumMapSep,
|
|
|
|
Token::Str("c"),
|
|
|
|
Token::I32(3),
|
|
|
|
|
|
|
|
Token::EnumMapEnd,
|
2015-09-07 18:44:56 -05:00
|
|
|
]
|
|
|
|
);
|
|
|
|
|
|
|
|
assert_ser_tokens(
|
2016-02-15 18:02:09 -06:00
|
|
|
&SkipSerializingEnum::Struct {
|
|
|
|
a: &a,
|
|
|
|
_b: 2,
|
2016-02-13 00:05:02 -06:00
|
|
|
c: 123,
|
2015-09-07 18:44:56 -05:00
|
|
|
},
|
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::EnumMapStart("SkipSerializingEnum", "Struct", 1),
|
2015-09-07 18:44:56 -05:00
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::EnumMapSep,
|
2015-09-07 18:44:56 -05:00
|
|
|
Token::Str("a"),
|
|
|
|
Token::I8(1),
|
|
|
|
|
2016-02-13 00:05:02 -06:00
|
|
|
Token::EnumMapEnd,
|
2015-09-07 18:44:56 -05:00
|
|
|
]
|
|
|
|
);
|
|
|
|
}
|
2016-02-15 19:39:46 -06:00
|
|
|
|
feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:
struct Test<A, B, C> {
a: X<A>
#[serde(skip_serializing)]
b: B
#[serde(serialize_with="...")]
c: C
}
Used to be:
impl<A, B, C> Serialize for Test<A, B, C>
where A: Serialize,
B: Serialize,
C: Serialize,
{ ... }
Now it is:
impl<A, B, C> Serialize for Test<A, B, C>
where X<A>: Serialize,
{ ... }
Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 14:17:29 -06:00
|
|
|
#[derive(Debug, PartialEq)]
|
|
|
|
struct NotSerializeStruct(i8);
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq)]
|
|
|
|
enum NotSerializeEnum { Trouble }
|
|
|
|
|
|
|
|
impl SerializeWith for NotSerializeEnum {
|
|
|
|
fn serialize_with<S>(&self, ser: &mut S) -> Result<(), S::Error>
|
|
|
|
where S: Serializer
|
|
|
|
{
|
|
|
|
"trouble".serialize(ser)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Serialize)]
|
|
|
|
struct ContainsNotSerialize<'a, B, C, D> where B: 'a, D: SerializeWith {
|
|
|
|
a: &'a Option<i8>,
|
|
|
|
#[serde(skip_serializing)]
|
|
|
|
b: &'a B,
|
|
|
|
#[serde(skip_serializing)]
|
|
|
|
c: Option<C>,
|
|
|
|
#[serde(serialize_with="SerializeWith::serialize_with")]
|
|
|
|
d: D,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_elt_not_serialize() {
|
|
|
|
let a = 1;
|
|
|
|
assert_ser_tokens(
|
|
|
|
&ContainsNotSerialize {
|
|
|
|
a: &Some(a),
|
|
|
|
b: &NotSerializeStruct(2),
|
|
|
|
c: Some(NotSerializeEnum::Trouble),
|
|
|
|
d: NotSerializeEnum::Trouble,
|
|
|
|
},
|
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::StructStart("ContainsNotSerialize", 2),
|
feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:
struct Test<A, B, C> {
a: X<A>
#[serde(skip_serializing)]
b: B
#[serde(serialize_with="...")]
c: C
}
Used to be:
impl<A, B, C> Serialize for Test<A, B, C>
where A: Serialize,
B: Serialize,
C: Serialize,
{ ... }
Now it is:
impl<A, B, C> Serialize for Test<A, B, C>
where X<A>: Serialize,
{ ... }
Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 14:17:29 -06:00
|
|
|
|
|
|
|
Token::StructSep,
|
|
|
|
Token::Str("a"),
|
|
|
|
Token::Option(true),
|
|
|
|
Token::I8(1),
|
|
|
|
|
|
|
|
Token::StructSep,
|
|
|
|
Token::Str("d"),
|
|
|
|
Token::Str("trouble"),
|
|
|
|
|
|
|
|
Token::StructEnd,
|
|
|
|
]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2016-02-15 19:39:46 -06:00
|
|
|
#[derive(Debug, PartialEq, Serialize)]
|
feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:
struct Test<A, B, C> {
a: X<A>
#[serde(skip_serializing)]
b: B
#[serde(serialize_with="...")]
c: C
}
Used to be:
impl<A, B, C> Serialize for Test<A, B, C>
where A: Serialize,
B: Serialize,
C: Serialize,
{ ... }
Now it is:
impl<A, B, C> Serialize for Test<A, B, C>
where X<A>: Serialize,
{ ... }
Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 14:17:29 -06:00
|
|
|
struct SerializeWithStruct<'a, B> where B: SerializeWith {
|
2016-02-15 19:39:46 -06:00
|
|
|
a: &'a i8,
|
feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:
struct Test<A, B, C> {
a: X<A>
#[serde(skip_serializing)]
b: B
#[serde(serialize_with="...")]
c: C
}
Used to be:
impl<A, B, C> Serialize for Test<A, B, C>
where A: Serialize,
B: Serialize,
C: Serialize,
{ ... }
Now it is:
impl<A, B, C> Serialize for Test<A, B, C>
where X<A>: Serialize,
{ ... }
Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 14:17:29 -06:00
|
|
|
#[serde(serialize_with="SerializeWith::serialize_with")]
|
2016-02-15 19:39:46 -06:00
|
|
|
b: B,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_serialize_with_struct() {
|
|
|
|
let a = 1;
|
|
|
|
assert_ser_tokens(
|
|
|
|
&SerializeWithStruct {
|
|
|
|
a: &a,
|
|
|
|
b: 2,
|
|
|
|
},
|
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::StructStart("SerializeWithStruct", 2),
|
2016-02-15 19:39:46 -06:00
|
|
|
|
|
|
|
Token::StructSep,
|
|
|
|
Token::Str("a"),
|
|
|
|
Token::I8(1),
|
|
|
|
|
|
|
|
Token::StructSep,
|
|
|
|
Token::Str("b"),
|
|
|
|
Token::Bool(false),
|
|
|
|
|
|
|
|
Token::StructEnd,
|
|
|
|
]
|
|
|
|
);
|
|
|
|
|
|
|
|
assert_ser_tokens(
|
|
|
|
&SerializeWithStruct {
|
|
|
|
a: &a,
|
|
|
|
b: 123,
|
|
|
|
},
|
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::StructStart("SerializeWithStruct", 2),
|
2016-02-15 19:39:46 -06:00
|
|
|
|
|
|
|
Token::StructSep,
|
|
|
|
Token::Str("a"),
|
|
|
|
Token::I8(1),
|
|
|
|
|
|
|
|
Token::StructSep,
|
|
|
|
Token::Str("b"),
|
|
|
|
Token::Bool(true),
|
|
|
|
|
|
|
|
Token::StructEnd,
|
|
|
|
]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Serialize)]
|
feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:
struct Test<A, B, C> {
a: X<A>
#[serde(skip_serializing)]
b: B
#[serde(serialize_with="...")]
c: C
}
Used to be:
impl<A, B, C> Serialize for Test<A, B, C>
where A: Serialize,
B: Serialize,
C: Serialize,
{ ... }
Now it is:
impl<A, B, C> Serialize for Test<A, B, C>
where X<A>: Serialize,
{ ... }
Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 14:17:29 -06:00
|
|
|
enum SerializeWithEnum<'a, B> where B: SerializeWith {
|
2016-02-15 19:39:46 -06:00
|
|
|
Struct {
|
|
|
|
a: &'a i8,
|
feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:
struct Test<A, B, C> {
a: X<A>
#[serde(skip_serializing)]
b: B
#[serde(serialize_with="...")]
c: C
}
Used to be:
impl<A, B, C> Serialize for Test<A, B, C>
where A: Serialize,
B: Serialize,
C: Serialize,
{ ... }
Now it is:
impl<A, B, C> Serialize for Test<A, B, C>
where X<A>: Serialize,
{ ... }
Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 14:17:29 -06:00
|
|
|
#[serde(serialize_with="SerializeWith::serialize_with")]
|
2016-02-15 19:39:46 -06:00
|
|
|
b: B,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_serialize_with_enum() {
|
|
|
|
let a = 1;
|
|
|
|
assert_ser_tokens(
|
|
|
|
&SerializeWithEnum::Struct {
|
|
|
|
a: &a,
|
|
|
|
b: 2,
|
|
|
|
},
|
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::EnumMapStart("SerializeWithEnum", "Struct", 2),
|
2016-02-15 19:39:46 -06:00
|
|
|
|
|
|
|
Token::EnumMapSep,
|
|
|
|
Token::Str("a"),
|
|
|
|
Token::I8(1),
|
|
|
|
|
|
|
|
Token::EnumMapSep,
|
|
|
|
Token::Str("b"),
|
|
|
|
Token::Bool(false),
|
|
|
|
|
|
|
|
Token::EnumMapEnd,
|
|
|
|
]
|
|
|
|
);
|
|
|
|
|
|
|
|
assert_ser_tokens(
|
|
|
|
&SerializeWithEnum::Struct {
|
|
|
|
a: &a,
|
|
|
|
b: 123,
|
|
|
|
},
|
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::EnumMapStart("SerializeWithEnum", "Struct", 2),
|
2016-02-15 19:39:46 -06:00
|
|
|
|
|
|
|
Token::EnumMapSep,
|
|
|
|
Token::Str("a"),
|
|
|
|
Token::I8(1),
|
|
|
|
|
|
|
|
Token::EnumMapSep,
|
|
|
|
Token::Str("b"),
|
|
|
|
Token::Bool(true),
|
|
|
|
|
|
|
|
Token::EnumMapEnd,
|
|
|
|
]
|
|
|
|
);
|
|
|
|
}
|
2016-02-15 22:43:11 -06:00
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Deserialize)]
|
feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:
struct Test<A, B, C> {
a: X<A>
#[serde(skip_serializing)]
b: B
#[serde(serialize_with="...")]
c: C
}
Used to be:
impl<A, B, C> Serialize for Test<A, B, C>
where A: Serialize,
B: Serialize,
C: Serialize,
{ ... }
Now it is:
impl<A, B, C> Serialize for Test<A, B, C>
where X<A>: Serialize,
{ ... }
Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 14:17:29 -06:00
|
|
|
struct DeserializeWithStruct<B> where B: DeserializeWith {
|
2016-02-15 22:43:11 -06:00
|
|
|
a: i8,
|
feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:
struct Test<A, B, C> {
a: X<A>
#[serde(skip_serializing)]
b: B
#[serde(serialize_with="...")]
c: C
}
Used to be:
impl<A, B, C> Serialize for Test<A, B, C>
where A: Serialize,
B: Serialize,
C: Serialize,
{ ... }
Now it is:
impl<A, B, C> Serialize for Test<A, B, C>
where X<A>: Serialize,
{ ... }
Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 14:17:29 -06:00
|
|
|
#[serde(deserialize_with="DeserializeWith::deserialize_with")]
|
2016-02-15 22:43:11 -06:00
|
|
|
b: B,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_deserialize_with_struct() {
|
|
|
|
assert_de_tokens(
|
|
|
|
&DeserializeWithStruct {
|
|
|
|
a: 1,
|
|
|
|
b: 2,
|
|
|
|
},
|
2016-06-29 01:50:19 -05:00
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::StructStart("DeserializeWithStruct", 2),
|
2016-02-15 22:43:11 -06:00
|
|
|
|
|
|
|
Token::StructSep,
|
|
|
|
Token::Str("a"),
|
|
|
|
Token::I8(1),
|
|
|
|
|
|
|
|
Token::StructSep,
|
|
|
|
Token::Str("b"),
|
|
|
|
Token::Bool(false),
|
|
|
|
|
|
|
|
Token::StructEnd,
|
|
|
|
]
|
|
|
|
);
|
|
|
|
|
|
|
|
assert_de_tokens(
|
|
|
|
&DeserializeWithStruct {
|
|
|
|
a: 1,
|
|
|
|
b: 123,
|
|
|
|
},
|
2016-06-29 01:50:19 -05:00
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::StructStart("DeserializeWithStruct", 2),
|
2016-02-15 22:43:11 -06:00
|
|
|
|
|
|
|
Token::StructSep,
|
|
|
|
Token::Str("a"),
|
|
|
|
Token::I8(1),
|
|
|
|
|
|
|
|
Token::StructSep,
|
|
|
|
Token::Str("b"),
|
|
|
|
Token::Bool(true),
|
|
|
|
|
|
|
|
Token::StructEnd,
|
|
|
|
]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Deserialize)]
|
feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:
struct Test<A, B, C> {
a: X<A>
#[serde(skip_serializing)]
b: B
#[serde(serialize_with="...")]
c: C
}
Used to be:
impl<A, B, C> Serialize for Test<A, B, C>
where A: Serialize,
B: Serialize,
C: Serialize,
{ ... }
Now it is:
impl<A, B, C> Serialize for Test<A, B, C>
where X<A>: Serialize,
{ ... }
Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 14:17:29 -06:00
|
|
|
enum DeserializeWithEnum<B> where B: DeserializeWith {
|
2016-02-15 22:43:11 -06:00
|
|
|
Struct {
|
|
|
|
a: i8,
|
feat(codegen): Inhibit generic bounds if skip_serializing
The generated code for a struct like:
struct Test<A, B, C> {
a: X<A>
#[serde(skip_serializing)]
b: B
#[serde(serialize_with="...")]
c: C
}
Used to be:
impl<A, B, C> Serialize for Test<A, B, C>
where A: Serialize,
B: Serialize,
C: Serialize,
{ ... }
Now it is:
impl<A, B, C> Serialize for Test<A, B, C>
where X<A>: Serialize,
{ ... }
Both `skip_serializing` and `serialize_with` mean the type does not need to
implement `Serialize`.
2016-02-28 14:17:29 -06:00
|
|
|
#[serde(deserialize_with="DeserializeWith::deserialize_with")]
|
2016-02-15 22:43:11 -06:00
|
|
|
b: B,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_deserialize_with_enum() {
|
|
|
|
assert_de_tokens(
|
|
|
|
&DeserializeWithEnum::Struct {
|
|
|
|
a: 1,
|
|
|
|
b: 2,
|
|
|
|
},
|
2016-06-29 01:50:19 -05:00
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::EnumMapStart("DeserializeWithEnum", "Struct", 2),
|
2016-02-15 22:43:11 -06:00
|
|
|
|
|
|
|
Token::EnumMapSep,
|
|
|
|
Token::Str("a"),
|
|
|
|
Token::I8(1),
|
|
|
|
|
|
|
|
Token::EnumMapSep,
|
|
|
|
Token::Str("b"),
|
|
|
|
Token::Bool(false),
|
|
|
|
|
|
|
|
Token::EnumMapEnd,
|
|
|
|
]
|
|
|
|
);
|
|
|
|
|
|
|
|
assert_de_tokens(
|
|
|
|
&DeserializeWithEnum::Struct {
|
|
|
|
a: 1,
|
|
|
|
b: 123,
|
|
|
|
},
|
2016-06-29 01:50:19 -05:00
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::EnumMapStart("DeserializeWithEnum", "Struct", 2),
|
2016-02-15 22:43:11 -06:00
|
|
|
|
|
|
|
Token::EnumMapSep,
|
|
|
|
Token::Str("a"),
|
|
|
|
Token::I8(1),
|
|
|
|
|
|
|
|
Token::EnumMapSep,
|
|
|
|
Token::Str("b"),
|
|
|
|
Token::Bool(true),
|
|
|
|
|
|
|
|
Token::EnumMapEnd,
|
|
|
|
]
|
|
|
|
);
|
|
|
|
}
|
2016-04-12 05:42:07 -05:00
|
|
|
|
|
|
|
#[test]
|
2016-04-12 10:26:56 -05:00
|
|
|
fn test_missing_renamed_field_struct() {
|
2016-04-12 05:42:07 -05:00
|
|
|
assert_de_tokens_error::<RenameStruct>(
|
2016-06-29 01:50:19 -05:00
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::StructStart("Superhero", 2),
|
2016-04-12 05:42:07 -05:00
|
|
|
|
|
|
|
Token::StructSep,
|
|
|
|
Token::Str("a1"),
|
|
|
|
Token::I32(1),
|
|
|
|
|
|
|
|
Token::StructEnd,
|
|
|
|
],
|
2016-06-29 00:49:13 -05:00
|
|
|
Error::MissingField("a3"),
|
2016-04-12 10:26:56 -05:00
|
|
|
);
|
|
|
|
|
|
|
|
assert_de_tokens_error::<RenameStructSerializeDeserialize>(
|
2016-06-29 01:50:19 -05:00
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::StructStart("SuperheroDe", 2),
|
2016-04-12 10:26:56 -05:00
|
|
|
|
|
|
|
Token::StructSep,
|
|
|
|
Token::Str("a1"),
|
|
|
|
Token::I32(1),
|
|
|
|
|
|
|
|
Token::StructEnd,
|
|
|
|
],
|
2016-06-29 00:49:13 -05:00
|
|
|
Error::MissingField("a5"),
|
2016-04-12 10:26:56 -05:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_missing_renamed_field_enum() {
|
|
|
|
assert_de_tokens_error::<RenameEnum>(
|
2016-06-29 01:50:19 -05:00
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::EnumMapStart("Superhero", "barry_allan", 1),
|
2016-04-12 10:26:56 -05:00
|
|
|
|
|
|
|
Token::EnumMapEnd,
|
|
|
|
],
|
2016-06-29 00:49:13 -05:00
|
|
|
Error::MissingField("b"),
|
2016-04-12 10:26:56 -05:00
|
|
|
);
|
|
|
|
|
|
|
|
assert_de_tokens_error::<RenameEnumSerializeDeserialize<i8>>(
|
2016-06-29 01:50:19 -05:00
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::EnumMapStart("SuperheroDe", "jason_todd", 2),
|
2016-04-12 10:26:56 -05:00
|
|
|
|
|
|
|
Token::EnumMapSep,
|
|
|
|
Token::Str("a"),
|
|
|
|
Token::I8(0),
|
|
|
|
|
|
|
|
Token::EnumMapEnd,
|
|
|
|
],
|
2016-06-29 00:49:13 -05:00
|
|
|
Error::MissingField("d"),
|
2016-04-12 10:26:56 -05:00
|
|
|
);
|
2016-04-12 05:42:07 -05:00
|
|
|
}
|
2016-07-05 02:52:19 -05:00
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Deserialize)]
|
|
|
|
enum InvalidLengthEnum {
|
|
|
|
A(i32, i32, i32),
|
|
|
|
B(#[serde(skip_deserializing)] i32, i32, i32),
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_invalid_length_enum() {
|
|
|
|
assert_de_tokens_error::<InvalidLengthEnum>(
|
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::EnumSeqStart("InvalidLengthEnum", "A", 3),
|
2016-07-05 02:52:19 -05:00
|
|
|
Token::EnumSeqSep,
|
|
|
|
Token::I32(1),
|
|
|
|
Token::EnumSeqEnd,
|
|
|
|
],
|
|
|
|
Error::InvalidLength(1),
|
|
|
|
);
|
|
|
|
assert_de_tokens_error::<InvalidLengthEnum>(
|
|
|
|
&[
|
2016-07-12 08:44:19 -05:00
|
|
|
Token::EnumSeqStart("InvalidLengthEnum", "B", 3),
|
2016-07-05 02:52:19 -05:00
|
|
|
Token::EnumSeqSep,
|
|
|
|
Token::I32(1),
|
|
|
|
Token::EnumSeqEnd,
|
|
|
|
],
|
|
|
|
Error::InvalidLength(1),
|
|
|
|
);
|
|
|
|
}
|