From 4e665a71bdf8aa3cc367a6c6d4aab56d7be7631e Mon Sep 17 00:00:00 2001 From: Michael Mokrysz Date: Wed, 22 Feb 2017 22:54:48 +0000 Subject: [PATCH] Attempt to port serde_json::Value::deserialize_enum for ContentDeserializer is being derailed by what error types should be used. --- serde/src/de/content.rs | 233 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 229 insertions(+), 4 deletions(-) diff --git a/serde/src/de/content.rs b/serde/src/de/content.rs index 5ba2a169..a9b8fc62 100644 --- a/serde/src/de/content.rs +++ b/serde/src/de/content.rs @@ -14,6 +14,8 @@ use core::cmp; use core::fmt; use core::marker::PhantomData; +use std::collections::BTreeMap; + #[cfg(all(not(feature = "std"), feature = "collections"))] use collections::{String, Vec}; @@ -607,10 +609,40 @@ impl Deserializer for ContentDeserializer visitor.visit_newtype_struct(self) } + fn deserialize_enum(self, _name: &str, _variants: &'static [&'static str], visitor: V) -> Result + where V: Visitor, + { + let (variant, value) = match self { + Content::Map(value) => { + let mut iter = value.into_iter(); + let (variant, value) = match iter.next() { + Some(v) => v, + None => { + return Err(de::Error::invalid_value(de::Unexpected::Map, &"map with a single key")); + } + }; + // enums are encoded in json as maps with a single key:value pair + if iter.next().is_some() { + return Err(de::Error::invalid_value(de::Unexpected::Map, &"map with a single key")); + } + (variant, Some(value)) + } + Content::String(variant) => (variant, None), + other => { + return Err(de::Error::invalid_type(other.unexpected(), &"string or map")); + } + }; + + visitor.visit_enum(EnumDeserializer { + variant: variant, + value: value, + }) + } + forward_to_deserialize! { bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq seq_fixed_size bytes byte_buf map unit_struct tuple_struct struct - struct_field tuple enum ignored_any + struct_field tuple ignored_any } } @@ -624,6 +656,199 @@ impl ContentDeserializer { } } +struct EnumDeserializer where E: de::Error { + variant: String, + value: Option, + err: PhantomData, +} + +impl de::EnumVisitor for EnumDeserializer where E: de::Error { + type Error = E; + type Variant = VariantDeserializer; + + fn visit_variant_seed(self, seed: V) -> Result<(V::Value, VariantDeserializer), Self::Error> + where V: de::DeserializeSeed + { + let variant = self.variant.into_deserializer(); + let visitor = VariantDeserializer { value: self.value }; + seed.deserialize(variant).map(|v| (v, visitor)) + } +} + +struct VariantDeserializer { + value: Option, +} + +impl de::VariantVisitor for VariantDeserializer { + type Error = de::Error; + + fn visit_unit(self) -> Result<(), de::Error> { + match self.value { + Some(value) => de::Deserialize::deserialize(value), + None => Ok(()), + } + } + + fn visit_newtype_seed(self, seed: T) -> Result + where T: de::DeserializeSeed, E: de::Error + { + match self.value { + Some(value) => seed.deserialize(value), + None => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"newtype variant")), + } + } + + fn visit_tuple( + self, + _len: usize, + visitor: V + ) -> Result + where V: de::Visitor, E: de::Error + { + match self.value { + Some(Content::Array(v)) => { + de::Deserializer::deserialize(SeqDeserializer::new(v), visitor) + } + Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"tuple variant")), + None => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"tuple variant")) + } + } + + fn visit_struct( + self, + _fields: &'static [&'static str], + visitor: V + ) -> Result + where V: de::Visitor, E: de::Error + { + match self.value { + Some(Content::Map(v)) => { + de::Deserializer::deserialize(MapDeserializer::new(v), visitor) + } + Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"struct variant")), + _ => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"struct variant")) + } + } +} + +struct SeqDeserializer { + iter: ::std::vec::IntoIter, +} + +impl SeqDeserializer { + fn new(vec: Vec) -> Self { + SeqDeserializer { + iter: vec.into_iter(), + } + } +} + +impl de::Deserializer for SeqDeserializer { + type Error = de::Error; + + #[inline] + fn deserialize(mut self, visitor: V) -> Result + where V: de::Visitor, E: de::Error, + { + let len = self.iter.len(); + if len == 0 { + visitor.visit_unit() + } else { + let ret = try!(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! { + bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option + seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct + tuple_struct struct struct_field tuple enum ignored_any + } +} + +impl de::SeqVisitor for SeqDeserializer { + type Error = de::Error; + + fn visit_seed(&mut self, seed: T) -> Result, E> + where T: de::DeserializeSeed, E: de::Error, + { + match self.iter.next() { + Some(value) => seed.deserialize(value).map(Some), + None => Ok(None), + } + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +struct MapDeserializer { + iter: as IntoIterator>::IntoIter, + value: Option, +} + +impl MapDeserializer { + fn new(map: BTreeMap) -> Self { + MapDeserializer { + iter: map.into_iter(), + value: None, + } + } +} + +impl de::MapVisitor for MapDeserializer { + type Error = de::Error; + + fn visit_key_seed(&mut self, seed: T) -> Result, E> + where T: de::DeserializeSeed, E: de::Error, + { + match self.iter.next() { + Some((key, value)) => { + self.value = Some(value); + seed.deserialize(Content::String(key)).map(Some) + } + None => Ok(None), + } + } + + fn visit_value_seed(&mut self, seed: T) -> Result + where T: de::DeserializeSeed, E: de::Error, + { + match self.value.take() { + Some(value) => seed.deserialize(value), + None => Err(de::Error::custom("value is missing")), + } + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +impl de::Deserializer for MapDeserializer { + type Error = de::Error; + + #[inline] + fn deserialize(self, visitor: V) -> Result + where V: de::Visitor, E: de::Error, + { + visitor.visit_map(self) + } + + forward_to_deserialize! { + bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option + seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct + tuple_struct struct struct_field tuple enum ignored_any + } +} + + /// Not public API. pub struct ContentRefDeserializer<'a, E> { content: &'a Content, @@ -637,7 +862,7 @@ impl<'a, E> Deserializer for ContentRefDeserializer<'a, E> { type Error = E; - fn deserialize(self, visitor: V) -> Result + fn deserialize(self, visitor: V) -> Result where V: Visitor { match *self.content { @@ -678,7 +903,7 @@ impl<'a, E> Deserializer for ContentRefDeserializer<'a, E> } } - fn deserialize_option(self, visitor: V) -> Result + fn deserialize_option(self, visitor: V) -> Result where V: Visitor { match *self.content { @@ -689,7 +914,7 @@ impl<'a, E> Deserializer for ContentRefDeserializer<'a, E> } } - fn deserialize_newtype_struct(self, _name: &str, visitor: V) -> Result + fn deserialize_newtype_struct(self, _name: &str, visitor: V) -> Result where V: Visitor { visitor.visit_newtype_struct(self)