Skip to content

Commit

Permalink
Serialize and deserialize a tagged newtype variant over unit () as if…
Browse files Browse the repository at this point in the history
… it was a unit variant.
  • Loading branch information
tage64 committed Oct 20, 2022
1 parent 55cf0ac commit 90d28fc
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 3 deletions.
11 changes: 11 additions & 0 deletions serde/src/private/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T> {
// Success(T),
// }
//
// We want {"result": "Success"} to deserialize into `Response<T>`.
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)),
}
}
Expand Down
6 changes: 3 additions & 3 deletions serde/src/private/ser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ enum Unsupported {
String,
ByteArray,
Optional,
Unit,
#[cfg(any(feature = "std", feature = "alloc"))]
UnitStruct,
Sequence,
Expand All @@ -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"),
Expand Down Expand Up @@ -184,7 +182,9 @@ where
}

fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
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<Self::Ok, Self::Error> {
Expand Down
28 changes: 28 additions & 0 deletions test_suite/tests/test_annotations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down

0 comments on commit 90d28fc

Please sign in to comment.