From 92029a05c6831904da38051a21522cbf0fce9776 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Thu, 16 Jul 2015 10:50:54 -0400 Subject: [PATCH] Add `Deserializer` type hints This allows file formats like bincode, which do not encode it's values with a type tag, to deserialize values. --- serde/src/de/impls.rs | 48 +++++----- serde/src/de/mod.rs | 204 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 201 insertions(+), 51 deletions(-) diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index 615654c4..55d6e8d4 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -62,7 +62,7 @@ impl Deserialize for () { fn deserialize(deserializer: &mut D) -> Result<(), D::Error> where D: Deserializer, { - deserializer.visit(UnitVisitor) + deserializer.visit_unit(UnitVisitor) } } @@ -94,7 +94,7 @@ impl Deserialize for bool { fn deserialize(deserializer: &mut D) -> Result where D: Deserializer, { - deserializer.visit(BoolVisitor) + deserializer.visit_bool(BoolVisitor) } } @@ -154,30 +154,30 @@ impl< } macro_rules! impl_deserialize_num { - ($ty:ty) => { + ($ty:ty, $method:ident) => { impl Deserialize for $ty { #[inline] fn deserialize(deserializer: &mut D) -> Result<$ty, D::Error> where D: Deserializer, { - deserializer.visit(PrimitiveVisitor::new()) + deserializer.$method(PrimitiveVisitor::new()) } } } } -impl_deserialize_num!(isize); -impl_deserialize_num!(i8); -impl_deserialize_num!(i16); -impl_deserialize_num!(i32); -impl_deserialize_num!(i64); -impl_deserialize_num!(usize); -impl_deserialize_num!(u8); -impl_deserialize_num!(u16); -impl_deserialize_num!(u32); -impl_deserialize_num!(u64); -impl_deserialize_num!(f32); -impl_deserialize_num!(f64); +impl_deserialize_num!(isize, visit_isize); +impl_deserialize_num!(i8, visit_i8); +impl_deserialize_num!(i16, visit_i16); +impl_deserialize_num!(i32, visit_i32); +impl_deserialize_num!(i64, visit_i64); +impl_deserialize_num!(usize, visit_usize); +impl_deserialize_num!(u8, visit_u8); +impl_deserialize_num!(u16, visit_u16); +impl_deserialize_num!(u32, visit_u32); +impl_deserialize_num!(u64, visit_u64); +impl_deserialize_num!(f32, visit_f32); +impl_deserialize_num!(f64, visit_f64); /////////////////////////////////////////////////////////////////////////////// @@ -215,7 +215,7 @@ impl Deserialize for char { fn deserialize(deserializer: &mut D) -> Result where D: Deserializer, { - deserializer.visit(CharVisitor) + deserializer.visit_char(CharVisitor) } } @@ -261,7 +261,7 @@ impl Deserialize for String { fn deserialize(deserializer: &mut D) -> Result where D: Deserializer, { - deserializer.visit(StringVisitor) + deserializer.visit_string(StringVisitor) } } @@ -357,7 +357,7 @@ macro_rules! set_impl { fn deserialize(deserializer: &mut D) -> Result<$ty, D::Error> where D: Deserializer, { - deserializer.visit($visitor_name::new()) + deserializer.visit_seq($visitor_name::new()) } } } @@ -466,7 +466,7 @@ impl Deserialize for [T; 0] fn deserialize(deserializer: &mut D) -> Result<[T; 0], D::Error> where D: Deserializer, { - deserializer.visit(ArrayVisitor0::new()) + deserializer.visit_seq(ArrayVisitor0::new()) } } @@ -511,7 +511,7 @@ macro_rules! array_impls { fn deserialize(deserializer: &mut D) -> Result<[T; $len], D::Error> where D: Deserializer, { - deserializer.visit($visitor::new()) + deserializer.visit_seq($visitor::new()) } } )+ @@ -601,7 +601,7 @@ macro_rules! tuple_impls { fn deserialize(deserializer: &mut D) -> Result<($($name,)+), D::Error> where D: Deserializer, { - deserializer.visit_seq($visitor { marker: PhantomData }) + deserializer.visit_tuple($visitor { marker: PhantomData }) } } )+ @@ -683,7 +683,7 @@ macro_rules! map_impl { fn deserialize(deserializer: &mut D) -> Result<$ty, D::Error> where D: Deserializer, { - deserializer.visit($visitor_name::new()) + deserializer.visit_map($visitor_name::new()) } } } @@ -761,7 +761,7 @@ impl Deserialize for VecMap fn deserialize(deserializer: &mut D) -> Result, D::Error> where D: Deserializer, { - deserializer.visit(VecMapVisitor::new()) + deserializer.visit_map(VecMapVisitor::new()) } } diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index 56911ad7..253be30e 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -25,18 +25,164 @@ pub trait Deserialize { /////////////////////////////////////////////////////////////////////////////// -/// `Deserializer` is an abstract trait that can deserialize values into a `Visitor`. +/// `Deserializer` is a trait that can deserialize values by threading a `Visitor` trait through a +/// value. It supports two entry point styles which enables different kinds of deserialization. +/// +/// 1) The `visit` method. File formats like JSON embed the type of it's construct in it's file +/// format. This allows the `Deserializer` to deserialize into a generic type like +/// `json::Value`, which can represent all JSON types. +/// +/// 2) The `visit_*` methods. File formats like bincode do not embed in it's format how to decode +/// it's values. It relies instead on the `Deserialize` type to hint to the `Deserializer` with +/// the `visit_*` methods how it should parse the next value. One downside though to only +/// supporting the `visit_*` types is that it does not allow for deserializing into a generic +/// `json::Value`-esque type. pub trait Deserializer { type Error: Error; - /// The `visit` method walks a visitor through a value as it is being deserialized. + /// This method walks a visitor through a value as it is being deserialized. fn visit(&mut self, visitor: V) -> Result where V: Visitor; - /// The `visit_option` method allows a `Deserialize` type to inform the `Deserializer` that - /// it's expecting an optional value. This allows deserializers that encode an optional value - /// as a nullable value to convert the null value into a `None`, and a regular value as - /// `Some(value)`. + /// This method hints that the `Deserialize` type is expecting a `bool` value. + #[inline] + fn visit_bool(&mut self, visitor: V) -> Result + where V: Visitor, + { + self.visit(visitor) + } + + /// This method hints that the `Deserialize` type is expecting an `usize` value. + #[inline] + fn visit_usize(&mut self, visitor: V) -> Result + where V: Visitor, + { + self.visit(visitor) + } + + /// This method hints that the `Deserialize` type is expecting an `u8` value. + #[inline] + fn visit_u8(&mut self, visitor: V) -> Result + where V: Visitor, + { + self.visit(visitor) + } + + /// This method hints that the `Deserialize` type is expecting an `u16` value. + #[inline] + fn visit_u16(&mut self, visitor: V) -> Result + where V: Visitor, + { + self.visit(visitor) + } + + /// This method hints that the `Deserialize` type is expecting an `u32` value. + #[inline] + fn visit_u32(&mut self, visitor: V) -> Result + where V: Visitor, + { + self.visit(visitor) + } + + /// This method hints that the `Deserialize` type is expecting an `u64` value. + #[inline] + fn visit_u64(&mut self, visitor: V) -> Result + where V: Visitor, + { + self.visit(visitor) + } + + /// This method hints that the `Deserialize` type is expecting an `isize` value. + #[inline] + fn visit_isize(&mut self, visitor: V) -> Result + where V: Visitor, + { + self.visit(visitor) + } + + /// This method hints that the `Deserialize` type is expecting an `i8` value. + #[inline] + fn visit_i8(&mut self, visitor: V) -> Result + where V: Visitor, + { + self.visit(visitor) + } + + /// This method hints that the `Deserialize` type is expecting an `i16` value. + #[inline] + fn visit_i16(&mut self, visitor: V) -> Result + where V: Visitor, + { + self.visit(visitor) + } + + /// This method hints that the `Deserialize` type is expecting an `i32` value. + #[inline] + fn visit_i32(&mut self, visitor: V) -> Result + where V: Visitor, + { + self.visit(visitor) + } + + /// This method hints that the `Deserialize` type is expecting an `i64` value. + #[inline] + fn visit_i64(&mut self, visitor: V) -> Result + where V: Visitor, + { + self.visit(visitor) + } + + /// This method hints that the `Deserialize` type is expecting a `f32` value. + #[inline] + fn visit_f32(&mut self, visitor: V) -> Result + where V: Visitor, + { + self.visit(visitor) + } + + /// This method hints that the `Deserialize` type is expecting a `f64` value. + #[inline] + fn visit_f64(&mut self, visitor: V) -> Result + where V: Visitor, + { + self.visit(visitor) + } + + /// This method hints that the `Deserialize` type is expecting a `char` value. + #[inline] + fn visit_char(&mut self, visitor: V) -> Result + where V: Visitor, + { + self.visit(visitor) + } + + /// This method hints that the `Deserialize` type is expecting a `&str` value. + #[inline] + fn visit_str(&mut self, visitor: V) -> Result + where V: Visitor, + { + self.visit(visitor) + } + + /// This method hints that the `Deserialize` type is expecting a `String` value. + #[inline] + fn visit_string(&mut self, visitor: V) -> Result + where V: Visitor, + { + self.visit_str(visitor) + } + + /// This method hints that the `Deserialize` type is expecting an `unit` value. + #[inline] + fn visit_unit(&mut self, visitor: V) -> Result + where V: Visitor, + { + self.visit(visitor) + } + + /// This method hints that the `Deserialize` type is expecting an `Option` value. This allows + /// deserializers that encode an optional value as a nullable value to convert the null value + /// into a `None`, and a regular value as `Some(value)`. #[inline] fn visit_option(&mut self, visitor: V) -> Result where V: Visitor, @@ -44,9 +190,8 @@ pub trait Deserializer { self.visit(visitor) } - /// The `visit_seq` method allows a `Deserialize` type to inform the `Deserializer` that it's - /// expecting a sequence of values. This allows deserializers to parse sequences that aren't - /// tagged as sequences. + /// This method hints that the `Deserialize` type is expecting a sequence value. This allows + /// deserializers to parse sequences that aren't tagged as sequences. #[inline] fn visit_seq(&mut self, visitor: V) -> Result where V: Visitor, @@ -54,9 +199,8 @@ pub trait Deserializer { self.visit(visitor) } - /// The `visit_map` method allows a `Deserialize` type to inform the `Deserializer` that it's - /// expecting a map of values. This allows deserializers to parse sequences that aren't tagged - /// as maps. + /// This method hints that the `Deserialize` type is expecting a map of values. This allows + /// deserializers to parse sequences that aren't tagged as maps. #[inline] fn visit_map(&mut self, visitor: V) -> Result where V: Visitor, @@ -64,9 +208,8 @@ pub trait Deserializer { self.visit(visitor) } - /// The `visit_named_unit` method allows a `Deserialize` type to inform the `Deserializer` that - /// it's expecting a named unit. This allows deserializers to a named unit that aren't tagged - /// as a named unit. + /// This method hints that the `Deserialize` type is expecting a named unit. This allows + /// deserializers to a named unit that aren't tagged as a named unit. #[inline] fn visit_named_unit(&mut self, _name: &str, visitor: V) -> Result where V: Visitor, @@ -74,9 +217,8 @@ pub trait Deserializer { self.visit(visitor) } - /// The `visit_named_seq` method allows a `Deserialize` type to inform the `Deserializer` that - /// it's expecting a named sequence of values. This allows deserializers to parse sequences - /// that aren't tagged as sequences. + /// This method hints that the `Deserialize` type is expecting a named sequence. + /// This allows deserializers to parse sequences that aren't tagged as sequences. #[inline] fn visit_named_seq(&mut self, _name: &str, visitor: V) -> Result where V: Visitor, @@ -84,9 +226,8 @@ pub trait Deserializer { self.visit_seq(visitor) } - /// The `visit_named_map` method allows a `Deserialize` type to inform the `Deserializer` that - /// it's expecting a map of values. This allows deserializers to parse sequences that aren't - /// tagged as maps. + /// This method hints that the `Deserialize` type is expecting a named map. This allows + /// deserializers to parse sequences that aren't tagged as maps. #[inline] fn visit_named_map(&mut self, _name: &str, visitor: V) -> Result where V: Visitor, @@ -94,9 +235,18 @@ pub trait Deserializer { self.visit_map(visitor) } - /// The `visit_enum` method allows a `Deserialize` type to inform the `Deserializer` that it's - /// expecting an enum value. This allows deserializers that provide a custom enumeration - /// serialization to properly deserialize the type. + /// This method hints that the `Deserialize` type is expecting a tuple value. This allows + /// deserializers that provide a custom tuple serialization to properly deserialize the type. + #[inline] + fn visit_tuple(&mut self, visitor: V) -> Result + where V: Visitor, + { + self.visit(visitor) + } + + /// This method hints that the `Deserialize` type is expecting an enum value. This allows + /// deserializers that provide a custom enumeration serialization to properly deserialize the + /// type. #[inline] fn visit_enum(&mut self, _enum: &str, _visitor: V) -> Result where V: EnumVisitor, @@ -104,9 +254,9 @@ pub trait Deserializer { Err(Error::syntax_error()) } - /// The `visit_bytes` method allows a `Deserialize` type to inform the `Deserializer` that it's - /// expecting a `Vec`. This allows deserializers that provide a custom byte vector - /// serialization to properly deserialize the type. + /// This method hints that the `Deserialize` type is expecting a `Vec`. This allows + /// deserializers that provide a custom byte vector serialization to properly deserialize the + /// type. #[inline] fn visit_bytes(&mut self, visitor: V) -> Result where V: Visitor,