fix(codegen): Take into account default=... when skip_deserializing

This commit is contained in:
David Tolnay 2016-04-12 23:42:24 -07:00
parent 6b3958d5fc
commit ff02b0c741
3 changed files with 48 additions and 11 deletions

View File

@ -249,6 +249,13 @@ impl FieldAttrs {
// Parse `#[serde(skip_deserializing)]` // Parse `#[serde(skip_deserializing)]`
ast::MetaItemKind::Word(ref name) if name == &"skip_deserializing" => { ast::MetaItemKind::Word(ref name) if name == &"skip_deserializing" => {
field_attrs.skip_deserializing_field = true; field_attrs.skip_deserializing_field = true;
// Initialize field to Default::default() unless a different
// default is specified by `#[serde(default="...")]`
if field_attrs.default_expr_if_missing.is_none() {
let default_expr = builder.expr().default();
field_attrs.default_expr_if_missing = Some(default_expr);
}
} }
// Parse `#[serde(skip_serializing_if="...")]` // Parse `#[serde(skip_serializing_if="...")]`

View File

@ -437,7 +437,7 @@ fn deserialize_struct_as_seq(
.map(|(i, &(_, ref attrs))| { .map(|(i, &(_, ref attrs))| {
let name = builder.id(format!("__field{}", i)); let name = builder.id(format!("__field{}", i));
if attrs.skip_deserializing_field() { if attrs.skip_deserializing_field() {
let default = builder.expr().default(); let default = attrs.expr_is_missing();
quote_stmt!(cx, quote_stmt!(cx,
let $name = $default; let $name = $default;
).unwrap() ).unwrap()
@ -1103,7 +1103,7 @@ fn deserialize_map(
} }
}, },
if attrs.skip_deserializing_field() { if attrs.skip_deserializing_field() {
builder.expr().default() attrs.expr_is_missing()
} else { } else {
builder.expr().id(name) builder.expr().id(name)
} }

View File

@ -61,18 +61,25 @@ impl DeserializeWith for i32 {
} }
#[derive(Debug, PartialEq, Serialize, Deserialize)] #[derive(Debug, PartialEq, Serialize, Deserialize)]
struct DefaultStruct<A, B: Default, C> where C: MyDefault { struct DefaultStruct<A, B: Default, C, D: Default, E>
where C: MyDefault,
E: MyDefault,
{
a1: A, a1: A,
#[serde(default)] #[serde(default)]
a2: B, a2: B,
#[serde(default="MyDefault::my_default")] #[serde(default="MyDefault::my_default")]
a3: C, a3: C,
#[serde(skip_deserializing)]
a4: D,
#[serde(skip_deserializing, default="MyDefault::my_default")]
a5: E,
} }
#[test] #[test]
fn test_default_struct() { fn test_default_struct() {
assert_de_tokens( assert_de_tokens(
&DefaultStruct { a1: 1, a2: 2, a3: 3 }, &DefaultStruct { a1: 1, a2: 2, a3: 3, a4: 0, a5: 123 },
vec![ vec![
Token::StructStart("DefaultStruct", Some(3)), Token::StructStart("DefaultStruct", Some(3)),
@ -88,12 +95,20 @@ fn test_default_struct() {
Token::Str("a3"), Token::Str("a3"),
Token::I32(3), Token::I32(3),
Token::StructSep,
Token::Str("a4"),
Token::I32(4),
Token::StructSep,
Token::Str("a5"),
Token::I32(5),
Token::StructEnd, Token::StructEnd,
] ]
); );
assert_de_tokens( assert_de_tokens(
&DefaultStruct { a1: 1, a2: 0, a3: 123 }, &DefaultStruct { a1: 1, a2: 0, a3: 123, a4: 0, a5: 123 },
vec![ vec![
Token::StructStart("DefaultStruct", Some(1)), Token::StructStart("DefaultStruct", Some(1)),
@ -107,22 +122,29 @@ fn test_default_struct() {
} }
#[derive(Debug, PartialEq, Serialize, Deserialize)] #[derive(Debug, PartialEq, Serialize, Deserialize)]
enum DefaultEnum<A, B: Default, C> where C: MyDefault { enum DefaultEnum<A, B: Default, C, D: Default, E>
where C: MyDefault,
E: MyDefault
{
Struct { Struct {
a1: A, a1: A,
#[serde(default)] #[serde(default)]
a2: B, a2: B,
#[serde(default="MyDefault::my_default")] #[serde(default="MyDefault::my_default")]
a3: C, a3: C,
#[serde(skip_deserializing)]
a4: D,
#[serde(skip_deserializing, default="MyDefault::my_default")]
a5: E,
} }
} }
#[test] #[test]
fn test_default_enum() { fn test_default_enum() {
assert_de_tokens( assert_de_tokens(
&DefaultEnum::Struct { a1: 1, a2: 2, a3: 3 }, &DefaultEnum::Struct { a1: 1, a2: 2, a3: 3, a4: 0, a5: 123 },
vec![ vec![
Token::EnumMapStart("DefaultEnum", "Struct", Some(3)), Token::EnumMapStart("DefaultEnum", "Struct", Some(5)),
Token::EnumMapSep, Token::EnumMapSep,
Token::Str("a1"), Token::Str("a1"),
@ -136,14 +158,22 @@ fn test_default_enum() {
Token::Str("a3"), Token::Str("a3"),
Token::I32(3), Token::I32(3),
Token::EnumMapSep,
Token::Str("a4"),
Token::I32(4),
Token::EnumMapSep,
Token::Str("a5"),
Token::I32(5),
Token::EnumMapEnd, Token::EnumMapEnd,
] ]
); );
assert_de_tokens( assert_de_tokens(
&DefaultEnum::Struct { a1: 1, a2: 0, a3: 123 }, &DefaultEnum::Struct { a1: 1, a2: 0, a3: 123, a4: 0, a5: 123 },
vec![ vec![
Token::EnumMapStart("DefaultEnum", "Struct", Some(3)), Token::EnumMapStart("DefaultEnum", "Struct", Some(5)),
Token::EnumMapSep, Token::EnumMapSep,
Token::Str("a1"), Token::Str("a1"),
@ -164,7 +194,7 @@ struct DenyUnknown {
fn test_ignore_unknown() { fn test_ignore_unknown() {
// 'Default' allows unknown. Basic smoke test of ignore... // 'Default' allows unknown. Basic smoke test of ignore...
assert_de_tokens( assert_de_tokens(
&DefaultStruct { a1: 1, a2: 2, a3: 3 }, &DefaultStruct { a1: 1, a2: 2, a3: 3, a4: 0, a5: 123 },
vec![ vec![
Token::StructStart("DefaultStruct", Some(5)), Token::StructStart("DefaultStruct", Some(5)),