feat(codegen): Allow #[serde(default="123")]

This feature adds support for the default to be specified to be
some expression (which unfortunately needs to be parsed from
a string) without needing this value to have an implementation
of `Default`, or for a new-type wrapper in order to provide an
alternative implementation. This expression is run in a function,
and therefore has no access to any of the internal state of
the deserializer.
This commit is contained in:
Erick Tryzelaar
2016-02-12 21:53:35 -08:00
parent 8ea6c66cf7
commit 9812a4c9c6
4 changed files with 184 additions and 41 deletions
+76 -10
View File
@@ -7,19 +7,29 @@ use token::{
assert_de_tokens_error
};
trait Trait {
fn my_default() -> Self;
}
impl Trait for i32 {
fn my_default() -> Self { 123 }
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Default {
a1: i32,
struct DefaultStruct<A, B: Default, C> where C: Trait {
a1: A,
#[serde(default)]
a2: i32,
a2: B,
#[serde(default="Trait::my_default()")]
a3: C,
}
#[test]
fn test_default() {
fn test_default_struct() {
assert_de_tokens(
&Default { a1: 1, a2: 2 },
&DefaultStruct { a1: 1, a2: 2, a3: 3 },
vec![
Token::StructStart("Default", Some(2)),
Token::StructStart("DefaultStruct", Some(3)),
Token::MapSep,
Token::Str("a1"),
@@ -29,14 +39,66 @@ fn test_default() {
Token::Str("a2"),
Token::I32(2),
Token::MapSep,
Token::Str("a3"),
Token::I32(3),
Token::MapEnd,
]
);
assert_de_tokens(
&Default { a1: 1, a2: 0 },
&DefaultStruct { a1: 1, a2: 0, a3: 123 },
vec![
Token::StructStart("Default", Some(1)),
Token::StructStart("DefaultStruct", Some(1)),
Token::MapSep,
Token::Str("a1"),
Token::I32(1),
Token::MapEnd,
]
);
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
enum DefaultEnum<A, B: Default, C> where C: Trait {
Struct {
a1: A,
#[serde(default)]
a2: B,
#[serde(default="Trait::my_default()")]
a3: C,
}
}
#[test]
fn test_default_enum() {
assert_de_tokens(
&DefaultEnum::Struct { a1: 1, a2: 2, a3: 3 },
vec![
Token::EnumMapStart("DefaultEnum", "Struct", Some(3)),
Token::MapSep,
Token::Str("a1"),
Token::I32(1),
Token::MapSep,
Token::Str("a2"),
Token::I32(2),
Token::MapSep,
Token::Str("a3"),
Token::I32(3),
Token::MapEnd,
]
);
assert_de_tokens(
&DefaultEnum::Struct { a1: 1, a2: 0, a3: 123 },
vec![
Token::EnumMapStart("DefaultEnum", "Struct", Some(3)),
Token::MapSep,
Token::Str("a1"),
@@ -57,9 +119,9 @@ struct DenyUnknown {
fn test_ignore_unknown() {
// 'Default' allows unknown. Basic smoke test of ignore...
assert_de_tokens(
&Default { a1: 1, a2: 2},
&DefaultStruct { a1: 1, a2: 2, a3: 3 },
vec![
Token::StructStart("Default", Some(5)),
Token::StructStart("DefaultStruct", Some(5)),
Token::MapSep,
Token::Str("whoops1"),
@@ -84,6 +146,10 @@ fn test_ignore_unknown() {
Token::Str("whoops3"),
Token::I32(2),
Token::MapSep,
Token::Str("a3"),
Token::I32(3),
Token::MapEnd,
]
);