From acc8640c1e1d4095c05a7a7c6efddfa5a8d89801 Mon Sep 17 00:00:00 2001 From: Jake Kiesel Date: Sat, 7 Sep 2019 02:43:28 -0600 Subject: [PATCH] Fix (de)serialization of new types where the internal type is skipped --- serde_derive/src/de.rs | 18 ++++++++++++++++++ serde_derive/src/ser.rs | 21 +++++++++++++++++++++ test_suite/tests/test_de.rs | 17 +++++++++++++---- test_suite/tests/test_ser.rs | 5 +++++ 4 files changed, 57 insertions(+), 4 deletions(-) diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index acc6dfb7..9f3b0319 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -1689,6 +1689,24 @@ fn deserialize_externally_tagged_variant( } } Style::Newtype => { + if variant.fields[0].attrs.skip_deserializing() { + let this = ¶ms.this; + let let_default = match variant.fields[0].attrs.default() { + attr::Default::Default => quote!( + _serde::export::Default::default() + ), + attr::Default::Path(ref path) => quote!( + #path() + ), + _ => unimplemented!(), + }; + + + return quote_block! { + try!(_serde::de::VariantAccess::unit_variant(__variant)); + _serde::export::Ok(#this::#variant_ident(#let_default)) + }; + } deserialize_externally_tagged_newtype_variant(variant_ident, params, &variant.fields[0]) } Style::Tuple => { diff --git a/serde_derive/src/ser.rs b/serde_derive/src/ser.rs index 57caaaff..9b532beb 100644 --- a/serde_derive/src/ser.rs +++ b/serde_derive/src/ser.rs @@ -522,6 +522,16 @@ fn serialize_externally_tagged_variant( } Style::Newtype => { let field = &variant.fields[0]; + if field.attrs.skip_serializing() { + return quote_expr! { + _serde::Serializer::serialize_unit_variant( + __serializer, + #type_name, + #variant_index, + #variant_name, + ) + } + } let mut field_expr = quote!(__field0); if let Some(path) = field.attrs.serialize_with() { field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); @@ -825,6 +835,12 @@ fn serialize_tuple_variant( variant_index, variant_name, } => { + if len.to_string() == "0" { + return quote_expr! { + _serde::Serializer::serialize_unit_variant(__serializer, #type_name, #variant_index, #variant_name) + } + } + quote_block! { let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_variant( __serializer, @@ -837,6 +853,11 @@ fn serialize_tuple_variant( } } TupleVariant::Untagged => { + if len.to_string() == "0" { + return quote_expr! { + _serde::Serializer::serialize_unit(__serializer) + } + } quote_block! { let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple( __serializer, diff --git a/test_suite/tests/test_de.rs b/test_suite/tests/test_de.rs index 3946865b..16628efd 100644 --- a/test_suite/tests/test_de.rs +++ b/test_suite/tests/test_de.rs @@ -104,6 +104,9 @@ struct StructSkipAllDenyUnknown { a: i32, } +#[derive(Default, PartialEq, Debug)] +struct NotDeserializable; + #[derive(PartialEq, Debug, Deserialize)] enum Enum { #[allow(dead_code)] @@ -117,6 +120,7 @@ enum Enum { b: i32, c: i32, }, + SimpleWithSkipped(#[serde(skip_deserializing)] NotDeserializable), } #[derive(PartialEq, Debug, Deserialize)] @@ -728,6 +732,11 @@ declare_tests! { Token::I32(1), ], } + test_enum_simple_with_skipped { + Enum::SimpleWithSkipped(NotDeserializable) => &[ + Token::UnitVariant { name: "Enum", variant: "SimpleWithSkipped" }, + ], + } test_enum_seq { Enum::Seq(1, 2, 3) => &[ Token::TupleVariant { name: "Enum", variant: "Seq", len: 3 }, @@ -1217,13 +1226,13 @@ declare_error_tests! { &[ Token::UnitVariant { name: "Enum", variant: "Foo" }, ], - "unknown variant `Foo`, expected one of `Unit`, `Simple`, `Seq`, `Map`", + "unknown variant `Foo`, expected one of `Unit`, `Simple`, `Seq`, `Map`, `SimpleWithSkipped`", } test_enum_skipped_variant { &[ Token::UnitVariant { name: "Enum", variant: "Skipped" }, ], - "unknown variant `Skipped`, expected one of `Unit`, `Simple`, `Seq`, `Map`", + "unknown variant `Skipped`, expected one of `Unit`, `Simple`, `Seq`, `Map`, `SimpleWithSkipped`", } test_enum_skip_all { &[ @@ -1254,10 +1263,10 @@ declare_error_tests! { test_enum_out_of_range { &[ Token::Enum { name: "Enum" }, - Token::U32(4), + Token::U32(5), Token::Unit, ], - "invalid value: integer `4`, expected variant index 0 <= i < 4", + "invalid value: integer `5`, expected variant index 0 <= i < 5", } test_short_tuple<(u8, u8, u8)> { &[ diff --git a/test_suite/tests/test_ser.rs b/test_suite/tests/test_ser.rs index 719e987d..68293f5a 100644 --- a/test_suite/tests/test_ser.rs +++ b/test_suite/tests/test_ser.rs @@ -44,6 +44,9 @@ struct Struct { c: i32, } +#[derive(PartialEq, Debug)] +struct NotSerializable; + #[derive(Serialize, PartialEq, Debug)] enum Enum { Unit, @@ -64,6 +67,7 @@ enum Enum { _a: i32, _b: i32, }, + OneWithSkipped(#[serde(skip_serializing)] NotSerializable), } ////////////////////////////////////////////////////////////////////////// @@ -326,6 +330,7 @@ declare_tests! { Token::I32(2), Token::StructVariantEnd, ], + Enum::OneWithSkipped(NotSerializable) => &[Token::UnitVariant {name: "Enum", variant: "OneWithSkipped" }], } test_box { Box::new(0i32) => &[Token::I32(0)],