From da7fc795ee654252effa232a62a5a1e6d4f551ee Mon Sep 17 00:00:00 2001 From: Mingun Date: Sat, 17 Aug 2024 16:32:36 +0500 Subject: [PATCH] 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 --- serde/src/private/de.rs | 83 +---------------------------------------- 1 file changed, 2 insertions(+), 81 deletions(-) diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index cb34f1c31..be2b119d2 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -2190,9 +2190,7 @@ mod content { // Covered by tests/test_enum_untagged.rs // newtype_enum::tuple0 // newtype_enum::tuple2 - Some(Content::Seq(v)) => { - de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor) - } + Some(Content::Seq(v)) => visit_content_seq_ref(v, visitor), Some(other) => Err(de::Error::invalid_type( other.unexpected(), &"tuple variant", @@ -2221,9 +2219,7 @@ mod content { // Covered by tests/test_enum_untagged.rs // newtype_enum::struct_from_seq // newtype_enum::empty_struct_from_seq - Some(Content::Seq(v)) => { - de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor) - } + Some(Content::Seq(v)) => visit_content_seq_ref(v, visitor), Some(other) => Err(de::Error::invalid_type( other.unexpected(), &"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, - } - - 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(mut self, visitor: V) -> Result - 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(&mut self, seed: T) -> Result, 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 { - size_hint::from_bounds(&self.iter) - } - } - struct MapRefDeserializer<'a, 'de: 'a, E> where E: de::Error,