Merge pull request #1085 from serde-rs/internally-unit-struct
Allow internally tagged newtype variant containing unit struct
This commit is contained in:
commit
66e8b0a0cd
@ -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! {
|
forward_to_deserialize_any! {
|
||||||
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
|
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
|
byte_buf unit seq tuple tuple_struct map struct identifier
|
||||||
identifier ignored_any
|
ignored_any
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +60,6 @@ enum Unsupported {
|
|||||||
ByteArray,
|
ByteArray,
|
||||||
Optional,
|
Optional,
|
||||||
Unit,
|
Unit,
|
||||||
UnitStruct,
|
|
||||||
Sequence,
|
Sequence,
|
||||||
Tuple,
|
Tuple,
|
||||||
TupleStruct,
|
TupleStruct,
|
||||||
@ -79,7 +78,6 @@ impl Display for Unsupported {
|
|||||||
Unsupported::ByteArray => formatter.write_str("a byte array"),
|
Unsupported::ByteArray => formatter.write_str("a byte array"),
|
||||||
Unsupported::Optional => formatter.write_str("an optional"),
|
Unsupported::Optional => formatter.write_str("an optional"),
|
||||||
Unsupported::Unit => formatter.write_str("unit"),
|
Unsupported::Unit => formatter.write_str("unit"),
|
||||||
Unsupported::UnitStruct => formatter.write_str("a unit struct"),
|
|
||||||
Unsupported::Sequence => formatter.write_str("a sequence"),
|
Unsupported::Sequence => formatter.write_str("a sequence"),
|
||||||
Unsupported::Tuple => formatter.write_str("a tuple"),
|
Unsupported::Tuple => formatter.write_str("a tuple"),
|
||||||
Unsupported::TupleStruct => formatter.write_str("a tuple struct"),
|
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> {
|
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(
|
fn serialize_unit_variant(
|
||||||
|
@ -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,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user