diff --git a/src/de/mod.rs b/src/de/mod.rs index 02dc6cda..5b426d22 100644 --- a/src/de/mod.rs +++ b/src/de/mod.rs @@ -1,6 +1,7 @@ use std::str; pub mod impls; +pub mod value; /////////////////////////////////////////////////////////////////////////////// diff --git a/src/de/value.rs b/src/de/value.rs new file mode 100644 index 00000000..288ebea7 --- /dev/null +++ b/src/de/value.rs @@ -0,0 +1,413 @@ +use std::collections::{ + BTreeMap, + BTreeSet, + HashMap, + HashSet, + btree_map, + btree_set, + hash_map, + hash_set, +}; +use std::hash::Hash; +use std::vec; + +use de; + +/////////////////////////////////////////////////////////////////////////////// + +pub enum Error { + SyntaxError, + EndOfStreamError, + MissingFieldError(&'static str), +} + +impl de::Error for Error { + fn syntax_error() -> Self { Error::SyntaxError } + fn end_of_stream_error() -> Self { Error::EndOfStreamError } + fn missing_field_error(field: &'static str) -> Self { Error::MissingFieldError(field) } +} + +/////////////////////////////////////////////////////////////////////////////// + +pub trait ValueDeserializer { + type Deserializer: de::Deserializer; + + fn deserializer(self) -> Self::Deserializer; +} + +/////////////////////////////////////////////////////////////////////////////// + +impl ValueDeserializer for () { + type Deserializer = UnitDeserializer; + + fn deserializer(self) -> UnitDeserializer { + UnitDeserializer + } +} + +/// A helper deserializer that deserializes a `()`. +pub struct UnitDeserializer; + +impl de::Deserializer for UnitDeserializer { + type Error = Error; + + fn visit(&mut self, mut visitor: V) -> Result + where V: de::Visitor, + { + visitor.visit_unit() + } + + fn visit_option(&mut self, mut visitor: V) -> Result + where V: de::Visitor, + { + visitor.visit_none() + } +} + +/////////////////////////////////////////////////////////////////////////////// + +macro_rules! primitive_deserializer { + ($ty:ty, $name:ident, $method:ident) => { + pub struct $name(Option<$ty>); + + impl ValueDeserializer for $ty { + type Deserializer = $name; + + fn deserializer(self) -> $name { + $name(Some(self)) + } + } + + impl de::Deserializer for $name { + type Error = Error; + + fn visit(&mut self, mut visitor: V) -> Result + where V: de::Visitor, + { + match self.0.take() { + Some(v) => visitor.$method(v), + None => Err(de::Error::end_of_stream_error()), + } + } + } + } +} + +primitive_deserializer!(bool, BoolDeserializer, visit_bool); +primitive_deserializer!(i8, I8Deserializer, visit_i8); +primitive_deserializer!(i16, I16Deserializer, visit_i16); +primitive_deserializer!(i32, I32Deserializer, visit_i32); +primitive_deserializer!(i64, I64Deserializer, visit_i64); +primitive_deserializer!(isize, IsizeDeserializer, visit_isize); +primitive_deserializer!(u8, U8Deserializer, visit_u8); +primitive_deserializer!(u16, U16Deserializer, visit_u16); +primitive_deserializer!(u32, U32Deserializer, visit_u32); +primitive_deserializer!(u64, U64Deserializer, visit_u64); +primitive_deserializer!(usize, UsizeDeserializer, visit_usize); +primitive_deserializer!(f32, F32Deserializer, visit_f32); +primitive_deserializer!(f64, F64Deserializer, visit_f64); +primitive_deserializer!(char, CharDeserializer, visit_char); + +/////////////////////////////////////////////////////////////////////////////// + +/// A helper deserializer that deserializes a `&str`. +pub struct StrDeserializer<'a>(Option<&'a str>); + +impl<'a> ValueDeserializer for &'a str { + type Deserializer = StrDeserializer<'a>; + + fn deserializer(self) -> StrDeserializer<'a> { + StrDeserializer(Some(self)) + } +} + +impl<'a> de::Deserializer for StrDeserializer<'a> { + type Error = Error; + + fn visit(&mut self, mut visitor: V) -> Result + where V: de::Visitor, + { + match self.0.take() { + Some(v) => visitor.visit_str(v), + None => Err(de::Error::end_of_stream_error()), + } + } + + fn visit_enum(&mut self, _name: &str, mut visitor: V) -> Result + where V: de::EnumVisitor, + { + visitor.visit(self) + } +} + +impl<'a> de::VariantVisitor for StrDeserializer<'a> { + type Error = Error; + + fn visit_variant(&mut self) -> Result + where T: de::Deserialize, + { + de::Deserialize::deserialize(self) + } + + fn visit_value(&mut self, mut visitor: V) -> Result + where V: de::Visitor, + { + visitor.visit_unit() + } +} + +/////////////////////////////////////////////////////////////////////////////// + +/// A helper deserializer that deserializes a `String`. +pub struct StringDeserializer(Option); + +impl ValueDeserializer for String { + type Deserializer = StringDeserializer; + + fn deserializer(self) -> StringDeserializer { + StringDeserializer(Some(self)) + } +} + +impl de::Deserializer for StringDeserializer { + type Error = Error; + + fn visit(&mut self, mut visitor: V) -> Result + where V: de::Visitor, + { + match self.0.take() { + Some(string) => visitor.visit_string(string), + None => Err(de::Error::end_of_stream_error()), + } + } + + fn visit_enum(&mut self, _name: &str, mut visitor: V) -> Result + where V: de::EnumVisitor, + { + visitor.visit(self) + } +} + +impl<'a> de::VariantVisitor for StringDeserializer { + type Error = Error; + + fn visit_variant(&mut self) -> Result + where T: de::Deserialize, + { + de::Deserialize::deserialize(self) + } + + fn visit_value(&mut self, mut visitor: V) -> Result + where V: de::Visitor, + { + visitor.visit_unit() + } +} + +/////////////////////////////////////////////////////////////////////////////// + +pub struct SeqDeserializer { + iter: I, + len: usize, +} + +impl SeqDeserializer { + pub fn new(iter: I, len: usize) -> Self { + SeqDeserializer { + iter: iter, + len: len, + } + } +} + +impl de::Deserializer for SeqDeserializer + where I: Iterator, + T: ValueDeserializer, +{ + type Error = Error; + + fn visit(&mut self, mut visitor: V) -> Result + where V: de::Visitor, + { + visitor.visit_seq(self) + } +} + +impl de::SeqVisitor for SeqDeserializer + where I: Iterator, + T: ValueDeserializer, +{ + type Error = Error; + + fn visit(&mut self) -> Result, Error> + where V: de::Deserialize + { + match self.iter.next() { + Some(value) => { + self.len -= 1; + let mut de = value.deserializer(); + Ok(Some(try!(de::Deserialize::deserialize(&mut de)))) + } + None => Ok(None), + } + } + + fn end(&mut self) -> Result<(), Error> { + if self.len == 0 { + Ok(()) + } else { + Err(de::Error::end_of_stream_error()) + } + } + + fn size_hint(&self) -> (usize, Option) { + (self.len, Some(self.len)) + } +} + +/////////////////////////////////////////////////////////////////////////////// + +impl ValueDeserializer for Vec + where T: ValueDeserializer, +{ + type Deserializer = SeqDeserializer>; + + fn deserializer(self) -> SeqDeserializer> { + let len = self.len(); + SeqDeserializer::new(self.into_iter(), len) + } +} + +impl ValueDeserializer for BTreeSet + where T: ValueDeserializer + Eq + Ord, +{ + type Deserializer = SeqDeserializer>; + + fn deserializer(self) -> SeqDeserializer> { + let len = self.len(); + SeqDeserializer::new(self.into_iter(), len) + } +} + +impl ValueDeserializer for HashSet + where T: ValueDeserializer + Eq + Hash, +{ + type Deserializer = SeqDeserializer>; + + fn deserializer(self) -> SeqDeserializer> { + let len = self.len(); + SeqDeserializer::new(self.into_iter(), len) + } +} + +/////////////////////////////////////////////////////////////////////////////// + +pub struct MapDeserializer + where I: Iterator, + K: ValueDeserializer, + V: ValueDeserializer, +{ + iter: I, + value: Option, + len: usize, +} + +impl MapDeserializer + where I: Iterator, + K: ValueDeserializer, + V: ValueDeserializer, +{ + pub fn new(iter: I, len: usize) -> Self { + MapDeserializer { + iter: iter, + value: None, + len: len, + } + } +} + +impl de::Deserializer for MapDeserializer + where I: Iterator, + K: ValueDeserializer, + V: ValueDeserializer, +{ + type Error = Error; + + fn visit(&mut self, mut visitor: V_) -> Result + where V_: de::Visitor, + { + visitor.visit_map(self) + } +} + +impl de::MapVisitor for MapDeserializer + where I: Iterator, + K: ValueDeserializer, + V: ValueDeserializer, +{ + type Error = Error; + + fn visit_key(&mut self) -> Result, Error> + where T: de::Deserialize, + { + match self.iter.next() { + Some((key, value)) => { + self.len -= 1; + self.value = Some(value); + let mut de = key.deserializer(); + Ok(Some(try!(de::Deserialize::deserialize(&mut de)))) + } + None => Ok(None), + } + } + + fn visit_value(&mut self) -> Result + where T: de::Deserialize, + { + match self.value.take() { + Some(value) => { + let mut de = value.deserializer(); + de::Deserialize::deserialize(&mut de) + } + None => Err(de::Error::syntax_error()) + } + } + + fn end(&mut self) -> Result<(), Error> { + if self.len == 0 { + Ok(()) + } else { + Err(de::Error::end_of_stream_error()) + } + } + + fn size_hint(&self) -> (usize, Option) { + (self.len, Some(self.len)) + } +} + +/////////////////////////////////////////////////////////////////////////////// + +impl ValueDeserializer for BTreeMap + where K: ValueDeserializer + Eq + Ord, + V: ValueDeserializer, +{ + type Deserializer = MapDeserializer, K, V>; + + fn deserializer(self) -> MapDeserializer, K, V> { + let len = self.len(); + MapDeserializer::new(self.into_iter(), len) + } +} + +impl ValueDeserializer for HashMap + where K: ValueDeserializer + Eq + Hash, + V: ValueDeserializer, +{ + type Deserializer = MapDeserializer, K, V>; + + fn deserializer(self) -> MapDeserializer, K, V> { + let len = self.len(); + MapDeserializer::new(self.into_iter(), len) + } +} diff --git a/src/json/de.rs b/src/json/de.rs index ef89807b..5ea8f57c 100644 --- a/src/json/de.rs +++ b/src/json/de.rs @@ -603,26 +603,8 @@ impl<'a, Iter> de::MapVisitor for MapVisitor<'a, Iter> fn missing_field(&mut self, _field: &'static str) -> Result where V: de::Deserialize, { - // See if the type can deserialize from a unit. - struct UnitDeserializer; - - impl de::Deserializer for UnitDeserializer { - type Error = Error; - - fn visit(&mut self, mut visitor: V) -> Result - where V: de::Visitor, - { - visitor.visit_unit() - } - - fn visit_option(&mut self, mut visitor: V) -> Result - where V: de::Visitor, - { - visitor.visit_none() - } - } - - Ok(try!(de::Deserialize::deserialize(&mut UnitDeserializer))) + let mut de = de::value::ValueDeserializer::deserializer(()); + Ok(try!(de::Deserialize::deserialize(&mut de))) } } diff --git a/src/json/error.rs b/src/json/error.rs index 63601666..53a9b0e1 100644 --- a/src/json/error.rs +++ b/src/json/error.rs @@ -145,6 +145,22 @@ impl error::FromError for Error { } } +impl error::FromError for Error { + fn from_error(error: de::value::Error) -> Error { + match error { + de::value::Error::SyntaxError => { + de::Error::syntax_error() + } + de::value::Error::EndOfStreamError => { + de::Error::end_of_stream_error() + } + de::value::Error::MissingFieldError(field) => { + de::Error::missing_field_error(field) + } + } + } +} + impl de::Error for Error { fn syntax_error() -> Error { Error::SyntaxError(ErrorCode::ExpectedSomeValue, 0, 0)