From 90d28fc314747039a710d2561a5ca2007d9378ad Mon Sep 17 00:00:00 2001 From: Tage Johansson Date: Fri, 21 Oct 2022 00:27:46 +0200 Subject: [PATCH 1/3] Serialize and deserialize a tagged newtype variant over unit () as if it was a unit variant. --- serde/src/private/de.rs | 11 +++++++++++ serde/src/private/ser.rs | 6 +++--- test_suite/tests/test_annotations.rs | 28 ++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index f0697d64f..6af958e39 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -1262,6 +1262,17 @@ mod content { { match self.content { Content::Unit => visitor.visit_unit(), + + // As a special case, allow deserializing newtype variant containing unit. E.G: + // #[derive(Deserialize)] + // #[serde(tag = "result")] + // enum Response { + // Success(T), + // } + // + // We want {"result": "Success"} to deserialize into `Response`. + Content::Map(ref v) if v.is_empty() => visitor.visit_unit(), + Content::Seq(ref v) if v.is_empty() => visitor.visit_unit(), _ => Err(self.invalid_type(&visitor)), } } diff --git a/serde/src/private/ser.rs b/serde/src/private/ser.rs index 6ee999389..293d8a865 100644 --- a/serde/src/private/ser.rs +++ b/serde/src/private/ser.rs @@ -51,7 +51,6 @@ enum Unsupported { String, ByteArray, Optional, - Unit, #[cfg(any(feature = "std", feature = "alloc"))] UnitStruct, Sequence, @@ -70,7 +69,6 @@ impl Display for Unsupported { Unsupported::String => formatter.write_str("a string"), Unsupported::ByteArray => formatter.write_str("a byte array"), Unsupported::Optional => formatter.write_str("an optional"), - Unsupported::Unit => formatter.write_str("unit"), #[cfg(any(feature = "std", feature = "alloc"))] Unsupported::UnitStruct => formatter.write_str("unit struct"), Unsupported::Sequence => formatter.write_str("a sequence"), @@ -184,7 +182,9 @@ where } fn serialize_unit(self) -> Result { - Err(self.bad_type(Unsupported::Unit)) + let mut map = try!(self.delegate.serialize_map(Some(1))); + try!(map.serialize_entry(self.tag, self.variant_name)); + map.end() } fn serialize_unit_struct(self, _: &'static str) -> Result { diff --git a/test_suite/tests/test_annotations.rs b/test_suite/tests/test_annotations.rs index 0317def6d..0ad25c88e 100644 --- a/test_suite/tests/test_annotations.rs +++ b/test_suite/tests/test_annotations.rs @@ -2302,6 +2302,34 @@ fn test_internally_tagged_enum_containing_flatten() { ); } +#[test] +fn test_internally_tagged_enum_new_type_with_unit() { + #[derive(Serialize, Deserialize, PartialEq, Debug)] + #[serde(tag = "t")] + enum Data { + A(()), + } + + assert_tokens( + &Data::A(()), + &[ + Token::Map { len: Some(1) }, + Token::Str("t"), + Token::Str("A"), + Token::MapEnd, + ], + ); + assert_ser_tokens( + &Data::A(()), + &[ + Token::Map { len: Some(1) }, + Token::Str("t"), + Token::Str("A"), + Token::MapEnd, + ], + ); +} + #[test] fn test_adjacently_tagged_enum_containing_flatten() { #[derive(Serialize, Deserialize, PartialEq, Debug)] From a07d794f74475677544fdb35b981141ff8284c0b Mon Sep 17 00:00:00 2001 From: tage64 <40422978+tage64@users.noreply.github.com> Date: Fri, 21 Oct 2022 08:53:55 +0200 Subject: [PATCH 2/3] Update test_suite/tests/test_annotations.rs Co-authored-by: David Tolnay --- test_suite/tests/test_annotations.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/test_suite/tests/test_annotations.rs b/test_suite/tests/test_annotations.rs index 0ad25c88e..9f9e2135d 100644 --- a/test_suite/tests/test_annotations.rs +++ b/test_suite/tests/test_annotations.rs @@ -2319,15 +2319,6 @@ fn test_internally_tagged_enum_new_type_with_unit() { Token::MapEnd, ], ); - assert_ser_tokens( - &Data::A(()), - &[ - Token::Map { len: Some(1) }, - Token::Str("t"), - Token::Str("A"), - Token::MapEnd, - ], - ); } #[test] From e2ccfd9ea7f118a29e27037e1da79aa29a7c1be8 Mon Sep 17 00:00:00 2001 From: Tage Johansson Date: Fri, 21 Oct 2022 09:07:27 +0200 Subject: [PATCH 3/3] Remove bad deserialization from sequence to internally tagged newtype variant over . --- serde/src/private/de.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index 6af958e39..7cb540c14 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -1272,7 +1272,6 @@ mod content { // // We want {"result": "Success"} to deserialize into `Response`. Content::Map(ref v) if v.is_empty() => visitor.visit_unit(), - Content::Seq(ref v) if v.is_empty() => visitor.visit_unit(), _ => Err(self.invalid_type(&visitor)), } }