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::{ use de::{
Deserialize, Deserialize,
Deserializer, Deserializer,
EnumVisitor,
Error, Error,
MapVisitor, MapVisitor,
SeqVisitor, SeqVisitor,
@ -1122,7 +1121,7 @@ impl<T, E> Deserialize for Result<T, E> where T: Deserialize, E: Deserialize {
{ {
struct FieldVisitor; struct FieldVisitor;
impl ::de::Visitor for FieldVisitor { impl Visitor for FieldVisitor {
type Value = Field; type Value = Field;
#[cfg(any(feature = "std", feature = "collections"))] #[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, where T: Deserialize,
E: Deserialize E: Deserialize
{ {
type Value = Result<T, E>; 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 where V: VariantVisitor
{ {
match try!(visitor.visit_variant()) { 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"]; 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. /// Represents a unit variant.
UnitVariant, UnitVariant,
/// Represents a newtype variant.
NewtypeVariant,
/// Represents a `&[u8]` type. /// Represents a `&[u8]` type.
Bytes, Bytes,
} }
@ -207,6 +210,7 @@ impl fmt::Display for Type {
Type::StructVariant => "struct variant", Type::StructVariant => "struct variant",
Type::TupleVariant => "tuple variant", Type::TupleVariant => "tuple variant",
Type::UnitVariant => "unit variant", Type::UnitVariant => "unit variant",
Type::NewtypeVariant => "newtype variant",
Type::Bytes => "bytes", Type::Bytes => "bytes",
}; };
display.fmt(formatter) display.fmt(formatter)
@ -399,7 +403,7 @@ pub trait Deserializer {
name: &'static str, name: &'static str,
variants: &'static [&'static str], variants: &'static [&'static str],
visitor: V) -> Result<V::Value, Self::Error> 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 /// This method hints that the `Deserialize` type needs to deserialize a value whose type
/// doesn't matter because it is ignored. /// doesn't matter because it is ignored.
@ -591,6 +595,14 @@ pub trait Visitor {
Err(Error::invalid_type(Type::Map)) 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`. /// `visit_bytes` deserializes a `&[u8]` into a `Value`.
fn visit_bytes<E>(&mut self, v: &[u8]) -> Result<Self::Value, E> fn visit_bytes<E>(&mut self, v: &[u8]) -> Result<Self::Value, E>
where E: Error, 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 /// `VariantVisitor` is a visitor that is created by the `Deserializer` and passed to the
/// `Deserialize` in order to deserialize a specific enum variant. /// `Deserialize` in order to deserialize a specific enum variant.
pub trait VariantVisitor { pub trait VariantVisitor {
@ -767,9 +766,7 @@ pub trait VariantVisitor {
where V: Deserialize; where V: Deserialize;
/// `visit_unit` is called when deserializing a variant with no values. /// `visit_unit` is called when deserializing a variant with no values.
fn visit_unit(&mut self) -> Result<(), Self::Error> { fn visit_unit(&mut self) -> Result<(), Self::Error>;
Err(Error::invalid_type(Type::UnitVariant))
}
/// `visit_newtype` is called when deserializing a variant with a single value. /// `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,)`. /// 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, _name: &str,
_variants: &'static [&'static str], _variants: &'static [&'static str],
mut visitor: V) -> Result<V::Value, Self::Error> 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! { 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> fn visit_newtype<T>(&mut self) -> Result<T, Self::Error>
where T: super::Deserialize, where T: super::Deserialize,
{ {
let (value,) = try!(self.visit_tuple(1, super::impls::TupleVisitor1::new())); Err(super::Error::invalid_type(super::Type::NewtypeVariant))
Ok(value)
} }
fn visit_tuple<V>(&mut self, fn visit_tuple<V>(&mut self,
@ -373,9 +372,9 @@ impl<E> de::Deserializer for StringDeserializer<E>
_name: &str, _name: &str,
_variants: &'static [&'static str], _variants: &'static [&'static str],
mut visitor: V) -> Result<V::Value, Self::Error> 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! { 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> fn visit_newtype<T>(&mut self) -> Result<T, Self::Error>
where T: super::Deserialize, where T: super::Deserialize,
{ {
let (value,) = try!(self.visit_tuple(1, super::impls::TupleVisitor1::new())); Err(super::Error::invalid_type(super::Type::NewtypeVariant))
Ok(value)
} }
fn visit_tuple<V>(&mut self, fn visit_tuple<V>(&mut self,
@ -462,9 +460,9 @@ impl<'a, E> de::Deserializer for CowStrDeserializer<'a, E>
_name: &str, _name: &str,
_variants: &'static [&'static str], _variants: &'static [&'static str],
mut visitor: V) -> Result<V::Value, Self::Error> 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! { 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> fn visit_newtype<T>(&mut self) -> Result<T, Self::Error>
where T: super::Deserialize, where T: super::Deserialize,
{ {
let (value,) = try!(self.visit_tuple(1, super::impls::TupleVisitor1::new())); Err(super::Error::invalid_type(super::Type::NewtypeVariant))
Ok(value)
} }
fn visit_tuple<V>(&mut self, 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)] #[doc(hidden)]
#[macro_export] #[macro_export]
macro_rules! forward_to_deserialize_helper { macro_rules! forward_to_deserialize_helper {
@ -141,12 +113,12 @@ macro_rules! forward_to_deserialize_helper {
(tuple) => { (tuple) => {
forward_to_deserialize_method!{deserialize_tuple(usize)} forward_to_deserialize_method!{deserialize_tuple(usize)}
}; };
(enum) => {
forward_to_deserialize_method!{deserialize_enum(&'static str, &'static [&'static str])}
};
(ignored_any) => { (ignored_any) => {
forward_to_deserialize_method!{deserialize_ignored_any()} forward_to_deserialize_method!{deserialize_ignored_any()}
}; };
(enum) => {
forward_to_deserialize_enum!();
};
} }
/// Helper to forward `Deserializer` methods to `Deserializer::deserialize`. /// Helper to forward `Deserializer` methods to `Deserializer::deserialize`.

View File

@ -545,10 +545,10 @@ fn deserialize_item_enum(
#visitor_item #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; 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, where __V: _serde::de::VariantVisitor,
{ {
match try!(visitor.visit_variant()) { match try!(visitor.visit_variant()) {

View File

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