mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-06-12 20:11:02 +00:00
Fix deserialization of empty struct variant in untagged enums
SeqRefDeserializer::deserialize_any has a special condition for empty sequence, which emits visit_unit. That condition assumes that type would be able to deserialized from unit, but: 1) struct variants was never able to deserialize from it (they expect only visit_map or visit_seq) 2) tuple variants even with zero fields expect visit_seq only. The suggestion to accept visit_unit instead was rejected in #2520 Fixes (2): newtype_enum::tuple0 newtype_enum::empty_struct_from_seq
This commit is contained in:
+2
-81
@@ -2190,9 +2190,7 @@ mod content {
|
|||||||
// Covered by tests/test_enum_untagged.rs
|
// Covered by tests/test_enum_untagged.rs
|
||||||
// newtype_enum::tuple0
|
// newtype_enum::tuple0
|
||||||
// newtype_enum::tuple2
|
// newtype_enum::tuple2
|
||||||
Some(Content::Seq(v)) => {
|
Some(Content::Seq(v)) => visit_content_seq_ref(v, visitor),
|
||||||
de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor)
|
|
||||||
}
|
|
||||||
Some(other) => Err(de::Error::invalid_type(
|
Some(other) => Err(de::Error::invalid_type(
|
||||||
other.unexpected(),
|
other.unexpected(),
|
||||||
&"tuple variant",
|
&"tuple variant",
|
||||||
@@ -2221,9 +2219,7 @@ mod content {
|
|||||||
// Covered by tests/test_enum_untagged.rs
|
// Covered by tests/test_enum_untagged.rs
|
||||||
// newtype_enum::struct_from_seq
|
// newtype_enum::struct_from_seq
|
||||||
// newtype_enum::empty_struct_from_seq
|
// newtype_enum::empty_struct_from_seq
|
||||||
Some(Content::Seq(v)) => {
|
Some(Content::Seq(v)) => visit_content_seq_ref(v, visitor),
|
||||||
de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor)
|
|
||||||
}
|
|
||||||
Some(other) => Err(de::Error::invalid_type(
|
Some(other) => Err(de::Error::invalid_type(
|
||||||
other.unexpected(),
|
other.unexpected(),
|
||||||
&"struct variant",
|
&"struct variant",
|
||||||
@@ -2236,81 +2232,6 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SeqRefDeserializer<'a, 'de: 'a, E>
|
|
||||||
where
|
|
||||||
E: de::Error,
|
|
||||||
{
|
|
||||||
iter: <&'a [Content<'de>] as IntoIterator>::IntoIter,
|
|
||||||
err: PhantomData<E>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'de, E> SeqRefDeserializer<'a, 'de, E>
|
|
||||||
where
|
|
||||||
E: de::Error,
|
|
||||||
{
|
|
||||||
fn new(slice: &'a [Content<'de>]) -> Self {
|
|
||||||
SeqRefDeserializer {
|
|
||||||
iter: slice.iter(),
|
|
||||||
err: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, 'a, E> de::Deserializer<'de> for SeqRefDeserializer<'a, 'de, E>
|
|
||||||
where
|
|
||||||
E: de::Error,
|
|
||||||
{
|
|
||||||
type Error = E;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn deserialize_any<V>(mut self, visitor: V) -> Result<V::Value, Self::Error>
|
|
||||||
where
|
|
||||||
V: de::Visitor<'de>,
|
|
||||||
{
|
|
||||||
let len = self.iter.len();
|
|
||||||
if len == 0 {
|
|
||||||
visitor.visit_unit()
|
|
||||||
} else {
|
|
||||||
let ret = tri!(visitor.visit_seq(&mut self));
|
|
||||||
let remaining = self.iter.len();
|
|
||||||
if remaining == 0 {
|
|
||||||
Ok(ret)
|
|
||||||
} else {
|
|
||||||
Err(de::Error::invalid_length(len, &"fewer elements in array"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
forward_to_deserialize_any! {
|
|
||||||
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
|
|
||||||
bytes byte_buf option unit unit_struct newtype_struct seq tuple
|
|
||||||
tuple_struct map struct enum identifier ignored_any
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, 'a, E> de::SeqAccess<'de> for SeqRefDeserializer<'a, 'de, E>
|
|
||||||
where
|
|
||||||
E: de::Error,
|
|
||||||
{
|
|
||||||
type Error = E;
|
|
||||||
|
|
||||||
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
|
|
||||||
where
|
|
||||||
T: de::DeserializeSeed<'de>,
|
|
||||||
{
|
|
||||||
match self.iter.next() {
|
|
||||||
Some(value) => seed
|
|
||||||
.deserialize(ContentRefDeserializer::new(value))
|
|
||||||
.map(Some),
|
|
||||||
None => Ok(None),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn size_hint(&self) -> Option<usize> {
|
|
||||||
size_hint::from_bounds(&self.iter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MapRefDeserializer<'a, 'de: 'a, E>
|
struct MapRefDeserializer<'a, 'de: 'a, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
|
|||||||
Reference in New Issue
Block a user