Fix (de)serialization of new types where the internal type is skipped

This commit is contained in:
Jake Kiesel 2019-09-07 02:43:28 -06:00
parent 4cea81f93f
commit acc8640c1e
4 changed files with 57 additions and 4 deletions

View File

@ -1689,6 +1689,24 @@ fn deserialize_externally_tagged_variant(
} }
} }
Style::Newtype => { Style::Newtype => {
if variant.fields[0].attrs.skip_deserializing() {
let this = &params.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]) deserialize_externally_tagged_newtype_variant(variant_ident, params, &variant.fields[0])
} }
Style::Tuple => { Style::Tuple => {

View File

@ -522,6 +522,16 @@ fn serialize_externally_tagged_variant(
} }
Style::Newtype => { Style::Newtype => {
let field = &variant.fields[0]; 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); let mut field_expr = quote!(__field0);
if let Some(path) = field.attrs.serialize_with() { if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
@ -825,6 +835,12 @@ fn serialize_tuple_variant(
variant_index, variant_index,
variant_name, variant_name,
} => { } => {
if len.to_string() == "0" {
return quote_expr! {
_serde::Serializer::serialize_unit_variant(__serializer, #type_name, #variant_index, #variant_name)
}
}
quote_block! { quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_variant( let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_variant(
__serializer, __serializer,
@ -837,6 +853,11 @@ fn serialize_tuple_variant(
} }
} }
TupleVariant::Untagged => { TupleVariant::Untagged => {
if len.to_string() == "0" {
return quote_expr! {
_serde::Serializer::serialize_unit(__serializer)
}
}
quote_block! { quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple( let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple(
__serializer, __serializer,

View File

@ -104,6 +104,9 @@ struct StructSkipAllDenyUnknown {
a: i32, a: i32,
} }
#[derive(Default, PartialEq, Debug)]
struct NotDeserializable;
#[derive(PartialEq, Debug, Deserialize)] #[derive(PartialEq, Debug, Deserialize)]
enum Enum { enum Enum {
#[allow(dead_code)] #[allow(dead_code)]
@ -117,6 +120,7 @@ enum Enum {
b: i32, b: i32,
c: i32, c: i32,
}, },
SimpleWithSkipped(#[serde(skip_deserializing)] NotDeserializable),
} }
#[derive(PartialEq, Debug, Deserialize)] #[derive(PartialEq, Debug, Deserialize)]
@ -728,6 +732,11 @@ declare_tests! {
Token::I32(1), Token::I32(1),
], ],
} }
test_enum_simple_with_skipped {
Enum::SimpleWithSkipped(NotDeserializable) => &[
Token::UnitVariant { name: "Enum", variant: "SimpleWithSkipped" },
],
}
test_enum_seq { test_enum_seq {
Enum::Seq(1, 2, 3) => &[ Enum::Seq(1, 2, 3) => &[
Token::TupleVariant { name: "Enum", variant: "Seq", len: 3 }, Token::TupleVariant { name: "Enum", variant: "Seq", len: 3 },
@ -1217,13 +1226,13 @@ declare_error_tests! {
&[ &[
Token::UnitVariant { name: "Enum", variant: "Foo" }, 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<Enum> { test_enum_skipped_variant<Enum> {
&[ &[
Token::UnitVariant { name: "Enum", variant: "Skipped" }, 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<EnumSkipAll> { test_enum_skip_all<EnumSkipAll> {
&[ &[
@ -1254,10 +1263,10 @@ declare_error_tests! {
test_enum_out_of_range<Enum> { test_enum_out_of_range<Enum> {
&[ &[
Token::Enum { name: "Enum" }, Token::Enum { name: "Enum" },
Token::U32(4), Token::U32(5),
Token::Unit, 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)> { test_short_tuple<(u8, u8, u8)> {
&[ &[

View File

@ -44,6 +44,9 @@ struct Struct {
c: i32, c: i32,
} }
#[derive(PartialEq, Debug)]
struct NotSerializable;
#[derive(Serialize, PartialEq, Debug)] #[derive(Serialize, PartialEq, Debug)]
enum Enum { enum Enum {
Unit, Unit,
@ -64,6 +67,7 @@ enum Enum {
_a: i32, _a: i32,
_b: i32, _b: i32,
}, },
OneWithSkipped(#[serde(skip_serializing)] NotSerializable),
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -326,6 +330,7 @@ declare_tests! {
Token::I32(2), Token::I32(2),
Token::StructVariantEnd, Token::StructVariantEnd,
], ],
Enum::OneWithSkipped(NotSerializable) => &[Token::UnitVariant {name: "Enum", variant: "OneWithSkipped" }],
} }
test_box { test_box {
Box::new(0i32) => &[Token::I32(0)], Box::new(0i32) => &[Token::I32(0)],