From 85f1bf0259d2c62ba677a63fb3f616d33dcbdd02 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 23 Aug 2016 21:30:48 -0400 Subject: [PATCH] Enum deserialization API --- serde/src/de/impls.rs | 11 ++-- serde/src/de/mod.rs | 101 +++++++++++++++++------------------- serde/src/de/value.rs | 21 ++++---- serde_codegen/src/de.rs | 4 +- serde_test/src/de.rs | 7 ++- testing/tests/test_bytes.rs | 2 +- 6 files changed, 69 insertions(+), 77 deletions(-) diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index 83a8f2c5..6289e921 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -65,7 +65,6 @@ use core::num::Zero; use de::{ Deserialize, Deserializer, - EnumVisitor, Error, MapVisitor, SeqVisitor, @@ -1145,7 +1144,7 @@ impl Deserialize for Result where T: Deserialize, E: Deserialize { { struct FieldVisitor; - impl ::de::Visitor for FieldVisitor { + impl Visitor for FieldVisitor { type Value = Field; #[cfg(any(feature = "std", feature = "collections"))] @@ -1194,15 +1193,15 @@ impl Deserialize for Result where T: Deserialize, E: Deserialize { } } - struct Visitor(PhantomData>); + struct ResultVisitor(PhantomData>); - impl EnumVisitor for Visitor + impl Visitor for ResultVisitor where T: Deserialize, E: Deserialize { type Value = Result; - fn visit(&mut self, mut visitor: V) -> Result, V::Error> + fn visit_enum(&mut self, mut visitor: V) -> Result, V::Error> where V: VariantVisitor { match try!(visitor.visit_variant()) { @@ -1220,7 +1219,7 @@ impl Deserialize for Result where T: Deserialize, E: Deserialize { const VARIANTS: &'static [&'static str] = &["Ok", "Err"]; - deserializer.deserialize_enum("Result", VARIANTS, Visitor(PhantomData)) + deserializer.deserialize_enum("Result", VARIANTS, ResultVisitor(PhantomData)) } } diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index 571c73b7..5241d372 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -46,9 +46,9 @@ macro_rules! de_forward_to_deserialize { }; (func: deserialize_enum) => { #[inline] - fn deserialize_enum<__V>(&mut self, _: &str, _: &[&str], _: __V) -> Result<__V::Value, Self::Error> - where __V: $crate::de::EnumVisitor { - Err($crate::de::Error::invalid_type($crate::de::Type::Enum)) + fn deserialize_enum<__V>(&mut self, _: &str, _: &[&str], visitor: __V) -> Result<__V::Value, Self::Error> + where __V: $crate::de::Visitor { + self.deserialize(visitor) } }; (named: $func:ident) => { @@ -234,6 +234,9 @@ pub enum Type { /// Represents a unit variant. UnitVariant, + /// Represents a newtype variant. + NewtypeVariant, + /// Represents a `&[u8]` type. Bytes, } @@ -241,38 +244,39 @@ pub enum Type { impl fmt::Display for Type { fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { let display = match *self { - Type::Bool => "bool", - Type::Usize => "usize", - Type::U8 => "u8", - Type::U16 => "u16", - Type::U32 => "u32", - Type::U64 => "u64", - Type::Isize => "isize", - Type::I8 => "i8", - Type::I16 => "i16", - Type::I32 => "i32", - Type::I64 => "i64", - Type::F32 => "f32", - Type::F64 => "f64", - Type::Char => "char", - Type::Str => "str", - Type::String => "string", - Type::Unit => "unit", - Type::Option => "option", - Type::Seq => "seq", - Type::Map => "map", - Type::UnitStruct => "unit struct", - Type::NewtypeStruct => "newtype struct", - Type::TupleStruct => "tuple struct", - Type::Struct => "struct", - Type::FieldName => "field name", - Type::Tuple => "tuple", - Type::Enum => "enum", - Type::VariantName => "variant name", - Type::StructVariant => "struct variant", - Type::TupleVariant => "tuple variant", - Type::UnitVariant => "unit variant", - Type::Bytes => "bytes", + Type::Bool => "bool", + Type::Usize => "usize", + Type::U8 => "u8", + Type::U16 => "u16", + Type::U32 => "u32", + Type::U64 => "u64", + Type::Isize => "isize", + Type::I8 => "i8", + Type::I16 => "i16", + Type::I32 => "i32", + Type::I64 => "i64", + Type::F32 => "f32", + Type::F64 => "f64", + Type::Char => "char", + Type::Str => "str", + Type::String => "string", + Type::Unit => "unit", + Type::Option => "option", + Type::Seq => "seq", + Type::Map => "map", + Type::UnitStruct => "unit struct", + Type::NewtypeStruct => "newtype struct", + Type::TupleStruct => "tuple struct", + Type::Struct => "struct", + Type::FieldName => "field name", + Type::Tuple => "tuple", + Type::Enum => "enum", + Type::VariantName => "variant name", + Type::StructVariant => "struct variant", + Type::TupleVariant => "tuple variant", + Type::UnitVariant => "unit variant", + Type::NewtypeVariant => "newtype variant", + Type::Bytes => "bytes", }; display.fmt(formatter) } @@ -464,7 +468,7 @@ pub trait Deserializer { name: &'static str, variants: &'static [&'static str], visitor: V) -> Result - where V: EnumVisitor; + where V: Visitor; /// This method hints that the `Deserialize` type needs to deserialize a value whose type /// doesn't matter because it is ignored. @@ -656,6 +660,14 @@ pub trait Visitor { Err(Error::invalid_type(Type::Map)) } + /// `visit_enum` deserializes a `VariantVisitor` into a `Value`. + fn visit_enum(&mut self, visitor: V) -> Result + where V: VariantVisitor, + { + let _ = visitor; + Err(Error::invalid_type(Type::Enum)) + } + /// `visit_bytes` deserializes a `&[u8]` into a `Value`. fn visit_bytes(&mut self, v: &[u8]) -> Result where E: Error, @@ -808,19 +820,6 @@ impl<'a, V_> MapVisitor for &'a mut V_ where V_: MapVisitor { /////////////////////////////////////////////////////////////////////////////// -/// `EnumVisitor` is a visitor that is created by the `Deserialize` and passed to the -/// `Deserializer` in order to deserialize enums. -pub trait EnumVisitor { - /// The value produced by this visitor. - type Value; - - /// Visit the specific variant with the `VariantVisitor`. - fn visit(&mut self, visitor: V) -> Result - where V: VariantVisitor; -} - -/////////////////////////////////////////////////////////////////////////////// - /// `VariantVisitor` is a visitor that is created by the `Deserializer` and passed to the /// `Deserialize` in order to deserialize a specific enum variant. pub trait VariantVisitor { @@ -832,9 +831,7 @@ pub trait VariantVisitor { where V: Deserialize; /// `visit_unit` is called when deserializing a variant with no values. - fn visit_unit(&mut self) -> Result<(), Self::Error> { - Err(Error::invalid_type(Type::UnitVariant)) - } + fn visit_unit(&mut self) -> Result<(), Self::Error>; /// `visit_newtype` is called when deserializing a variant with a single value. /// A good default is often to use the `visit_tuple` method to deserialize a `(value,)`. diff --git a/serde/src/de/value.rs b/serde/src/de/value.rs index bf3e0631..b51de8f7 100644 --- a/serde/src/de/value.rs +++ b/serde/src/de/value.rs @@ -306,9 +306,9 @@ impl<'a, E> de::Deserializer for StrDeserializer<'a, E> _name: &str, _variants: &'static [&'static str], mut visitor: V) -> Result - where V: de::EnumVisitor, + where V: de::Visitor, { - visitor.visit(self) + visitor.visit_enum(self) } de_forward_to_deserialize!{ @@ -346,8 +346,7 @@ impl<'a, E> de::VariantVisitor for StrDeserializer<'a, E> fn visit_newtype(&mut self) -> Result where T: super::Deserialize, { - let (value,) = try!(self.visit_tuple(1, super::impls::TupleVisitor1::new())); - Ok(value) + Err(super::Error::invalid_type(super::Type::NewtypeVariant)) } fn visit_tuple(&mut self, @@ -403,9 +402,9 @@ impl de::Deserializer for StringDeserializer _name: &str, _variants: &'static [&'static str], mut visitor: V) -> Result - where V: de::EnumVisitor, + where V: de::Visitor, { - visitor.visit(self) + visitor.visit_enum(self) } de_forward_to_deserialize!{ @@ -444,8 +443,7 @@ impl<'a, E> de::VariantVisitor for StringDeserializer fn visit_newtype(&mut self) -> Result where T: super::Deserialize, { - let (value,) = try!(self.visit_tuple(1, super::impls::TupleVisitor1::new())); - Ok(value) + Err(super::Error::invalid_type(super::Type::NewtypeVariant)) } fn visit_tuple(&mut self, @@ -502,9 +500,9 @@ impl<'a, E> de::Deserializer for CowStrDeserializer<'a, E> _name: &str, _variants: &'static [&'static str], mut visitor: V) -> Result - where V: de::EnumVisitor, + where V: de::Visitor, { - visitor.visit(self) + visitor.visit_enum(self) } de_forward_to_deserialize!{ @@ -543,8 +541,7 @@ impl<'a, E> de::VariantVisitor for CowStrDeserializer<'a, E> fn visit_newtype(&mut self) -> Result where T: super::Deserialize, { - let (value,) = try!(self.visit_tuple(1, super::impls::TupleVisitor1::new())); - Ok(value) + Err(super::Error::invalid_type(super::Type::NewtypeVariant)) } fn visit_tuple(&mut self, diff --git a/serde_codegen/src/de.rs b/serde_codegen/src/de.rs index b630ede0..336d2f56 100644 --- a/serde_codegen/src/de.rs +++ b/serde_codegen/src/de.rs @@ -622,10 +622,10 @@ fn deserialize_item_enum( $visitor_item - impl $impl_generics _serde::de::EnumVisitor for $visitor_ty $where_clause { + impl $impl_generics _serde::de::Visitor for $visitor_ty $where_clause { type Value = $ty; - fn visit<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<$ty, __V::Error> + fn visit_enum<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<$ty, __V::Error> where __V: _serde::de::VariantVisitor, { match try!(visitor.visit_variant()) { diff --git a/serde_test/src/de.rs b/serde_test/src/de.rs index 121dcd3d..30180943 100644 --- a/serde_test/src/de.rs +++ b/serde_test/src/de.rs @@ -3,7 +3,6 @@ use std::iter; use serde::de::{ self, Deserialize, - EnumVisitor, MapVisitor, SeqVisitor, VariantVisitor, @@ -268,13 +267,13 @@ impl de::Deserializer for Deserializer name: &str, _variants: &'static [&'static str], mut visitor: V) -> Result - where V: EnumVisitor, + where V: Visitor, { match self.tokens.peek() { Some(&Token::EnumStart(n)) if name == n => { self.tokens.next(); - visitor.visit(DeserializerVariantVisitor { + visitor.visit_enum(DeserializerVariantVisitor { de: self, }) } @@ -282,7 +281,7 @@ impl de::Deserializer for Deserializer | Some(&Token::EnumNewType(n, _)) | Some(&Token::EnumSeqStart(n, _, _)) | Some(&Token::EnumMapStart(n, _, _)) if name == n => { - visitor.visit(DeserializerVariantVisitor { + visitor.visit_enum(DeserializerVariantVisitor { de: self, }) } diff --git a/testing/tests/test_bytes.rs b/testing/tests/test_bytes.rs index fd707e21..000aa091 100644 --- a/testing/tests/test_bytes.rs +++ b/testing/tests/test_bytes.rs @@ -426,7 +426,7 @@ impl Deserializer for BytesDeserializer { self.deserialize(visitor) } fn deserialize_enum<__V>(&mut self, _: &str, _: &[&str], _visitor: __V) - -> Result<__V::Value, Self::Error> where __V: de::EnumVisitor { + -> Result<__V::Value, Self::Error> where __V: de::Visitor { Err(Error) } }