Enum deserialization API

This commit is contained in:
David Tolnay 2016-08-23 21:30:48 -04:00
parent 123e040189
commit 85f1bf0259
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
6 changed files with 69 additions and 77 deletions

View File

@ -65,7 +65,6 @@ use core::num::Zero;
use de::{
Deserialize,
Deserializer,
EnumVisitor,
Error,
MapVisitor,
SeqVisitor,
@ -1145,7 +1144,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"))]
@ -1194,15 +1193,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()) {
@ -1220,7 +1219,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

@ -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<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.
@ -656,6 +660,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,
@ -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<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 {
@ -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,)`.

View File

@ -306,9 +306,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)
}
de_forward_to_deserialize!{
@ -346,8 +346,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,
@ -403,9 +402,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)
}
de_forward_to_deserialize!{
@ -444,8 +443,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,
@ -502,9 +500,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)
}
de_forward_to_deserialize!{
@ -543,8 +541,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

@ -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()) {

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,
})
}

View File

@ -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)
}
}