diff --git a/serde/src/de/content.rs b/serde/src/de/content.rs index 5ba2a169..2d657d92 100644 --- a/serde/src/de/content.rs +++ b/serde/src/de/content.rs @@ -58,6 +58,32 @@ pub enum Content { Map(Vec<(Content, Content)>), } +impl Content { + fn unexpected(&self) -> Unexpected { + match *self { + Content::Bool(b) => Unexpected::Bool(b), + Content::U8(n) => Unexpected::Unsigned(n as u64), + Content::U16(n) => Unexpected::Unsigned(n as u64), + Content::U32(n) => Unexpected::Unsigned(n as u64), + Content::U64(n) => Unexpected::Unsigned(n), + Content::I8(n) => Unexpected::Signed(n as i64), + Content::I16(n) => Unexpected::Signed(n as i64), + Content::I32(n) => Unexpected::Signed(n as i64), + Content::I64(n) => Unexpected::Signed(n), + Content::F32(f) => Unexpected::Float(f as f64), + Content::F64(f) => Unexpected::Float(f), + Content::Char(c) => Unexpected::Char(c), + Content::String(ref s) => Unexpected::Str(s), + Content::Bytes(ref b) => Unexpected::Bytes(b), + Content::None | Content::Some(_) => Unexpected::Option, + Content::Unit => Unexpected::Unit, + Content::Newtype(_) => Unexpected::NewtypeStruct, + Content::Seq(_) => Unexpected::Seq, + Content::Map(_) => Unexpected::Map, + } + } +} + impl Deserialize for Content { fn deserialize(deserializer: D) -> Result { // Untagged and internally tagged enums are only supported in @@ -607,10 +633,41 @@ 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 { + 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) => (Content::String(variant), None), + other => { + return Err(de::Error::invalid_type(other.unexpected(), &"string or map")); + } + }; + + visitor.visit_enum(EnumDeserializer { + 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 } } @@ -624,6 +681,203 @@ impl ContentDeserializer { } } +struct EnumDeserializer where E: de::Error { + variant: Content, + 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 visitor = VariantDeserializer { value: self.value, err: PhantomData, }; + seed.deserialize(ContentDeserializer::new(self.variant)).map(|v| (v, visitor)) + } +} + +struct VariantDeserializer where E: de::Error { + value: Option, + err: PhantomData, +} + +impl de::VariantVisitor for VariantDeserializer where E: de::Error { + type Error = E; + + fn visit_unit(self) -> Result<(), E> { + match self.value { + Some(value) => de::Deserialize::deserialize(ContentDeserializer::new(value)), + None => Ok(()), + } + } + + fn visit_newtype_seed(self, seed: T) -> Result + where T: de::DeserializeSeed + { + match self.value { + Some(value) => seed.deserialize(ContentDeserializer::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(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 + { + 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 where E: de::Error { + iter: as IntoIterator>::IntoIter, + err: PhantomData, +} + +impl SeqDeserializer where E: de::Error { + fn new(vec: Vec) -> Self { + SeqDeserializer { + iter: vec.into_iter(), + err: PhantomData, + } + } +} + +impl de::Deserializer for SeqDeserializer 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 de::SeqVisitor for SeqDeserializer 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(ContentDeserializer::new(value)).map(Some), + None => Ok(None), + } + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +struct MapDeserializer where E: de::Error { + iter: as IntoIterator>::IntoIter, + value: Option, + err: PhantomData, +} + +impl MapDeserializer where E: de::Error { + fn new(map: Vec<(Content, Content)>) -> Self { + MapDeserializer { + iter: map.into_iter(), + value: None, + err: PhantomData, + } + } +} + +impl de::MapVisitor for MapDeserializer 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((key, value)) => { + self.value = Some(value); + seed.deserialize(ContentDeserializer::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(ContentDeserializer::new(value)), + None => Err(de::Error::custom("value is missing")), + } + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +impl de::Deserializer for MapDeserializer 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 + } +} + + /// Not public API. pub struct ContentRefDeserializer<'a, E> { content: &'a Content, @@ -637,7 +891,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 +932,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 +943,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)