diff --git a/serde/src/de/content.rs b/serde/src/de/content.rs index 2d657d92..8fd9e6ec 100644 --- a/serde/src/de/content.rs +++ b/serde/src/de/content.rs @@ -949,10 +949,41 @@ impl<'a, E> Deserializer for ContentRefDeserializer<'a, E> 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 { + Content::Map(ref value) => { + let mut iter = value.into_iter(); + let &(ref variant, ref 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)) + } + ref s @ Content::String(_) => (s, None), + ref other => { + return Err(de::Error::invalid_type(other.unexpected(), &"string or map")); + } + }; + + visitor.visit_enum(EnumRefDeserializer { + variant: variant, + value: value, + err: PhantomData, + }) + } + 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 } } @@ -966,6 +997,202 @@ impl<'a, E> ContentRefDeserializer<'a, E> { } } +struct EnumRefDeserializer<'a, E> where E: de::Error { + variant: &'a Content, + value: Option<&'a Content>, + err: PhantomData, +} + +impl<'a, E> de::EnumVisitor for EnumRefDeserializer<'a, E> where E: de::Error { + type Error = E; + type Variant = VariantRefDeserializer<'a, Self::Error>; + + fn visit_variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> + where V: de::DeserializeSeed, + { + let visitor = VariantRefDeserializer { value: self.value, err: PhantomData, }; + seed.deserialize(ContentRefDeserializer::new(self.variant)).map(|v| (v, visitor)) + } +} + +struct VariantRefDeserializer<'a, E> where E: de::Error { + value: Option<&'a Content>, + err: PhantomData, +} + +impl<'a, E> de::VariantVisitor for VariantRefDeserializer<'a, E> where E: de::Error { + type Error = E; + + fn visit_unit(self) -> Result<(), E> { + match self.value { + Some(value) => de::Deserialize::deserialize(ContentRefDeserializer::new(value)), + None => Ok(()), + } + } + + fn visit_newtype_seed(self, seed: T) -> Result + where T: de::DeserializeSeed + { + match self.value { + Some(value) => seed.deserialize(ContentRefDeserializer::new(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 + { + match self.value { + Some(&Content::Seq(ref v)) => { + de::Deserializer::deserialize(SeqRefDeserializer::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 + { + match self.value { + Some(&Content::Map(ref v)) => { + de::Deserializer::deserialize(MapRefDeserializer::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 SeqRefDeserializer<'a, E> where E: de::Error { + iter: <&'a [Content] as IntoIterator>::IntoIter, + err: PhantomData, +} + +impl<'a, E> SeqRefDeserializer<'a, E> where E: de::Error { + fn new(vec: &'a [Content]) -> Self { + SeqRefDeserializer { + iter: vec.into_iter(), + err: PhantomData, + } + } +} + +impl<'a, E> de::Deserializer for SeqRefDeserializer<'a, E> where E: de::Error { + type Error = E; + + #[inline] + fn deserialize(mut self, visitor: V) -> Result + where V: de::Visitor, + { + 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<'a, E> de::SeqVisitor for SeqRefDeserializer<'a, E> where E: de::Error { + type Error = E; + + fn visit_seed(&mut self, seed: T) -> Result, Self::Error> + where T: de::DeserializeSeed, + { + match self.iter.next() { + Some(value) => seed.deserialize(ContentRefDeserializer::new(value)).map(Some), + None => Ok(None), + } + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +struct MapRefDeserializer<'a, E> where E: de::Error { + iter: <&'a [(Content, Content)] as IntoIterator>::IntoIter, + value: Option<&'a Content>, + err: PhantomData, +} + +impl<'a, E> MapRefDeserializer<'a, E> where E: de::Error { + fn new(map: &'a [(Content, Content)]) -> Self { + MapRefDeserializer { + iter: map.into_iter(), + value: None, + err: PhantomData, + } + } +} + +impl<'a, E> de::MapVisitor for MapRefDeserializer<'a, E> where E: de::Error { + type Error = E; + + fn visit_key_seed(&mut self, seed: T) -> Result, Self::Error> + where T: de::DeserializeSeed, + { + match self.iter.next() { + Some(&(ref key, ref value)) => { + self.value = Some(value); + seed.deserialize(ContentRefDeserializer::new(key)).map(Some) + } + None => Ok(None), + } + } + + fn visit_value_seed(&mut self, seed: T) -> Result + where T: de::DeserializeSeed, + { + match self.value.take() { + Some(value) => seed.deserialize(ContentRefDeserializer::new(value)), + None => Err(de::Error::custom("value is missing")), + } + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +impl<'a, E> de::Deserializer for MapRefDeserializer<'a, E> where E: de::Error { + type Error = E; + + #[inline] + fn deserialize(self, visitor: V) -> Result + where V: de::Visitor, + { + 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 + } +} + impl de::value::ValueDeserializer for ContentDeserializer where E: de::Error {