Merge pull request #523 from serde-rs/enum

Enum deserialization API
This commit is contained in:
David Tolnay 2017-01-08 00:45:50 -08:00 committed by GitHub
commit eb6fb1d40e
6 changed files with 68 additions and 104 deletions

View File

@ -65,7 +65,6 @@ use core::num::Zero;
use de::{
Deserialize,
Deserializer,
EnumVisitor,
Error,
MapVisitor,
SeqVisitor,
@ -1122,7 +1121,7 @@ impl<T, E> Deserialize for Result<T, E> 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"))]
@ -1171,15 +1170,15 @@ impl<T, E> Deserialize for Result<T, E> where T: Deserialize, E: Deserialize {
}
}
struct Visitor<T, E>(PhantomData<Result<T, E>>);
struct ResultVisitor<T, E>(PhantomData<Result<T, E>>);
impl<T, E> EnumVisitor for Visitor<T, E>
impl<T, E> Visitor for ResultVisitor<T, E>
where T: Deserialize,
E: Deserialize
{
type Value = Result<T, E>;
fn visit<V>(&mut self, mut visitor: V) -> Result<Result<T, E>, V::Error>
fn visit_enum<V>(&mut self, mut visitor: V) -> Result<Result<T, E>, V::Error>
where V: VariantVisitor
{
match try!(visitor.visit_variant()) {
@ -1197,7 +1196,7 @@ impl<T, E> Deserialize for Result<T, E> 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))
}
}

View File

@ -169,6 +169,9 @@ pub enum Type {
/// Represents a unit variant.
UnitVariant,
/// Represents a newtype variant.
NewtypeVariant,
/// Represents a `&[u8]` type.
Bytes,
}
@ -176,38 +179,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)
}
@ -399,7 +403,7 @@ pub trait Deserializer {
name: &'static str,
variants: &'static [&'static str],
visitor: V) -> Result<V::Value, Self::Error>
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.
@ -591,6 +595,14 @@ pub trait Visitor {
Err(Error::invalid_type(Type::Map))
}
/// `visit_enum` deserializes a `VariantVisitor` into a `Value`.
fn visit_enum<V>(&mut self, visitor: V) -> Result<Self::Value, V::Error>
where V: VariantVisitor,
{
let _ = visitor;
Err(Error::invalid_type(Type::Enum))
}
/// `visit_bytes` deserializes a `&[u8]` into a `Value`.
fn visit_bytes<E>(&mut self, v: &[u8]) -> Result<Self::Value, E>
where E: Error,
@ -743,19 +755,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<V>(&mut self, visitor: V) -> Result<Self::Value, V::Error>
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 {
@ -767,9 +766,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,)`.

View File

@ -286,9 +286,9 @@ impl<'a, E> de::Deserializer for StrDeserializer<'a, E>
_name: &str,
_variants: &'static [&'static str],
mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::EnumVisitor,
where V: de::Visitor,
{
visitor.visit(self)
visitor.visit_enum(self)
}
forward_to_deserialize! {
@ -316,8 +316,7 @@ impl<'a, E> de::VariantVisitor for StrDeserializer<'a, E>
fn visit_newtype<T>(&mut self) -> Result<T, Self::Error>
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<V>(&mut self,
@ -373,9 +372,9 @@ impl<E> de::Deserializer for StringDeserializer<E>
_name: &str,
_variants: &'static [&'static str],
mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::EnumVisitor,
where V: de::Visitor,
{
visitor.visit(self)
visitor.visit_enum(self)
}
forward_to_deserialize! {
@ -404,8 +403,7 @@ impl<'a, E> de::VariantVisitor for StringDeserializer<E>
fn visit_newtype<T>(&mut self) -> Result<T, Self::Error>
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<V>(&mut self,
@ -462,9 +460,9 @@ impl<'a, E> de::Deserializer for CowStrDeserializer<'a, E>
_name: &str,
_variants: &'static [&'static str],
mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::EnumVisitor,
where V: de::Visitor,
{
visitor.visit(self)
visitor.visit_enum(self)
}
forward_to_deserialize! {
@ -493,8 +491,7 @@ impl<'a, E> de::VariantVisitor for CowStrDeserializer<'a, E>
fn visit_newtype<T>(&mut self) -> Result<T, Self::Error>
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<V>(&mut self,

View File

@ -26,34 +26,6 @@ macro_rules! forward_to_deserialize_method {
};
}
#[cfg(feature = "std")]
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_enum {
() => {
#[inline]
fn deserialize_enum<__V>(&mut self, _: &str, _: &[&str], _: __V) -> ::std::result::Result<__V::Value, Self::Error>
where __V: $crate::de::EnumVisitor
{
Err($crate::de::Error::invalid_type($crate::de::Type::Enum))
}
};
}
#[cfg(not(feature = "std"))]
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_enum {
() => {
#[inline]
fn deserialize_enum<__V>(&mut self, _: &str, _: &[&str], _: __V) -> ::core::result::Result<__V::Value, Self::Error>
where __V: $crate::de::EnumVisitor
{
Err($crate::de::Error::invalid_type($crate::de::Type::Enum))
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_helper {
@ -141,12 +113,12 @@ macro_rules! forward_to_deserialize_helper {
(tuple) => {
forward_to_deserialize_method!{deserialize_tuple(usize)}
};
(enum) => {
forward_to_deserialize_method!{deserialize_enum(&'static str, &'static [&'static str])}
};
(ignored_any) => {
forward_to_deserialize_method!{deserialize_ignored_any()}
};
(enum) => {
forward_to_deserialize_enum!();
};
}
/// Helper to forward `Deserializer` methods to `Deserializer::deserialize`.

View File

@ -545,10 +545,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()) {

View File

@ -3,7 +3,6 @@ use std::iter;
use serde::de::{
self,
Deserialize,
EnumVisitor,
MapVisitor,
SeqVisitor,
VariantVisitor,
@ -268,13 +267,13 @@ impl<I> de::Deserializer for Deserializer<I>
name: &str,
_variants: &'static [&'static str],
mut visitor: V) -> Result<V::Value, Error>
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<I> de::Deserializer for Deserializer<I>
| Some(&Token::EnumNewType(n, _))
| Some(&Token::EnumSeqStart(n, _, _))
| Some(&Token::EnumMapStart(n, _, _)) if name == n => {
visitor.visit(DeserializerVariantVisitor {
visitor.visit_enum(DeserializerVariantVisitor {
de: self,
})
}