Allow internally tagged newtype variant containing unit struct

This commit is contained in:
David Tolnay 2017-11-06 23:32:26 -08:00
parent 7ac8d4f9ae
commit 9e7a3437d9
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
3 changed files with 78 additions and 5 deletions

View File

@ -1114,10 +1114,38 @@ mod content {
)
}
fn deserialize_unit_struct<V>(
self,
_name: &'static str,
visitor: V
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self.content {
// As a special case, allow deserializing untagged newtype
// variant containing unit struct.
//
// #[derive(Deserialize)]
// struct Info;
//
// #[derive(Deserialize)]
// #[serde(tag = "topic")]
// enum Message {
// Info(Info),
// }
//
// We want {"topic":"Info"} to deserialize even though
// ordinarily unit structs do not deserialize from empty map.
Content::Map(ref v) if v.is_empty() => visitor.visit_unit(),
_ => self.deserialize_any(visitor),
}
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
byte_buf unit unit_struct seq tuple tuple_struct map struct
identifier ignored_any
byte_buf unit seq tuple tuple_struct map struct identifier
ignored_any
}
}

View File

@ -60,7 +60,6 @@ enum Unsupported {
ByteArray,
Optional,
Unit,
UnitStruct,
Sequence,
Tuple,
TupleStruct,
@ -79,7 +78,6 @@ impl Display for Unsupported {
Unsupported::ByteArray => formatter.write_str("a byte array"),
Unsupported::Optional => formatter.write_str("an optional"),
Unsupported::Unit => formatter.write_str("unit"),
Unsupported::UnitStruct => formatter.write_str("a unit struct"),
Unsupported::Sequence => formatter.write_str("a sequence"),
Unsupported::Tuple => formatter.write_str("a tuple"),
Unsupported::TupleStruct => formatter.write_str("a tuple struct"),
@ -199,7 +197,9 @@ where
}
fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::UnitStruct))
let mut map = try!(self.delegate.serialize_map(Some(1)));
try!(map.serialize_entry(self.tag, self.variant_name));
map.end()
}
fn serialize_unit_variant(

View File

@ -1267,3 +1267,48 @@ fn test_rename_all() {
]
);
}
#[test]
fn test_untagged_newtype_variant_containing_unit_struct_not_map() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Unit;
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
enum Message {
Unit(Unit),
Map(BTreeMap<String, String>),
}
assert_tokens(
&Message::Map(BTreeMap::new()),
&[
Token::Map { len: Some(0) },
Token::MapEnd,
],
);
}
#[test]
fn test_internally_tagged_newtype_variant_containing_unit_struct() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Info;
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "topic")]
enum Message {
Info(Info),
}
assert_tokens(
&Message::Info(Info),
&[
Token::Map { len: Some(1) },
Token::Str("topic"),
Token::Str("Info"),
Token::MapEnd,
],
);
}