From 8a4d271c3c99b3c0d05e1a5d501ec6885180538e Mon Sep 17 00:00:00 2001 From: Mingun Date: Sun, 23 Apr 2023 01:12:51 +0500 Subject: [PATCH] Implement deserialization of enum from sequence using SeqAccessDeserializer --- serde/src/de/value.rs | 111 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 109 insertions(+), 2 deletions(-) diff --git a/serde/src/de/value.rs b/serde/src/de/value.rs index 6711a329c..b0d13b4d6 100644 --- a/serde/src/de/value.rs +++ b/serde/src/de/value.rs @@ -1070,10 +1070,43 @@ where visitor.visit_seq(self.seq) } + fn deserialize_enum( + self, + _name: &str, + _variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + visitor.visit_enum(self) + } + 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 + tuple_struct map struct identifier ignored_any + } +} + +impl<'de, A> de::EnumAccess<'de> for SeqAccessDeserializer +where + A: de::SeqAccess<'de>, +{ + type Error = A::Error; + type Variant = private::SeqAsEnum; + + fn variant_seed(mut self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error> + where + T: de::DeserializeSeed<'de>, + { + match try!(self.seq.next_element_seed(seed)) { + Some(key) => Ok((key, private::seq_as_enum(self.seq))), + None => Err(de::Error::invalid_length( + self.seq.size_hint().unwrap_or(0), + &"enum tag", + )), + } } } @@ -1551,7 +1584,10 @@ where mod private { use lib::*; - use de::{self, DeserializeSeed, Deserializer, MapAccess, Unexpected, VariantAccess, Visitor}; + use de::{ + self, DeserializeSeed, Deserializer, MapAccess, SeqAccess, Unexpected, VariantAccess, + Visitor, + }; pub struct UnitOnly { marker: PhantomData, @@ -1659,6 +1695,77 @@ mod private { } } + pub struct SeqAsEnum { + seq: A, + } + + pub fn seq_as_enum(seq: A) -> SeqAsEnum { + SeqAsEnum { seq: seq } + } + + impl<'de, A> VariantAccess<'de> for SeqAsEnum + where + A: SeqAccess<'de>, + { + type Error = A::Error; + + fn unit_variant(mut self) -> Result<(), Self::Error> { + // Even when content is missing, it is also acceptable + // So both ["Unit"] and ["Unit", ()] is acceptable + try!(self.seq.next_element::<()>()); + Ok(()) + } + + fn newtype_variant_seed(mut self, seed: T) -> Result + where + T: DeserializeSeed<'de>, + { + match try!(self.seq.next_element_seed(seed)) { + Some(value) => Ok(value), + None => Err(de::Error::invalid_length( + self.seq.size_hint().unwrap_or(0) + 1, + &"content of newtype variant", + )), + } + } + + fn tuple_variant(mut self, len: usize, visitor: V) -> Result + where + V: Visitor<'de>, + { + match try!(self.seq.next_element_seed(SeedTupleVariant { + len: len, + visitor: visitor, + })) { + Some(value) => Ok(value), + None => Err(de::Error::invalid_length( + self.seq.size_hint().unwrap_or(0) + 1, + &"content of tuple variant", + )), + } + } + + fn struct_variant( + mut self, + _fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + match try!(self + .seq + .next_element_seed(SeedStructVariant { visitor: visitor })) + { + Some(value) => Ok(value), + None => Err(de::Error::invalid_length( + self.seq.size_hint().unwrap_or(0) + 1, + &"content of struct variant", + )), + } + } + } + struct SeedTupleVariant { len: usize, visitor: V,