From c17b139a266c89fddec91a6151b442d985bc735a Mon Sep 17 00:00:00 2001 From: Mingun Date: Sat, 3 Aug 2024 15:12:21 +0500 Subject: [PATCH] Fix roundtrip inconsistency: - deserialization of flatten unit variant is possible - serialization of such variant gives Err("can only flatten structs and maps (got an enum)") --- serde/src/private/ser.rs | 6 +++-- test_suite/tests/test_annotations.rs | 35 ++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/serde/src/private/ser.rs b/serde/src/private/ser.rs index ebfeba97e..2f2073901 100644 --- a/serde/src/private/ser.rs +++ b/serde/src/private/ser.rs @@ -54,6 +54,7 @@ enum Unsupported { Sequence, Tuple, TupleStruct, + #[cfg(not(any(feature = "std", feature = "alloc")))] Enum, } @@ -70,6 +71,7 @@ impl Display for Unsupported { Unsupported::Sequence => formatter.write_str("a sequence"), Unsupported::Tuple => formatter.write_str("a tuple"), Unsupported::TupleStruct => formatter.write_str("a tuple struct"), + #[cfg(not(any(feature = "std", feature = "alloc")))] Unsupported::Enum => formatter.write_str("an enum"), } } @@ -1095,9 +1097,9 @@ where self, _: &'static str, _: u32, - _: &'static str, + variant: &'static str, ) -> Result { - Err(Self::bad_type(Unsupported::Enum)) + self.0.serialize_entry(variant, &()) } fn serialize_newtype_struct( diff --git a/test_suite/tests/test_annotations.rs b/test_suite/tests/test_annotations.rs index 685bf329d..878c88981 100644 --- a/test_suite/tests/test_annotations.rs +++ b/test_suite/tests/test_annotations.rs @@ -2655,11 +2655,46 @@ mod flatten { #[derive(Debug, PartialEq, Serialize, Deserialize)] enum Enum { + Unit, Newtype(HashMap), Tuple(u32, u32), Struct { index: u32, value: u32 }, } + #[test] + fn unit() { + let value = Flatten { + data: Enum::Unit, + extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]), + }; + assert_tokens( + &value, + &[ + Token::Map { len: None }, + // data + Token::Str("Unit"), // variant + Token::Unit, + // extra + Token::Str("extra_key"), + Token::Str("extra value"), + Token::MapEnd, + ], + ); + assert_de_tokens( + &value, + &[ + Token::Map { len: None }, + // extra + Token::Str("extra_key"), + Token::Str("extra value"), + // data + Token::Str("Unit"), // variant + Token::Unit, + Token::MapEnd, + ], + ); + } + #[test] fn newtype() { assert_tokens(