Add deserializer type hinting hooks

Formats like xml have trouble knowing if they should deserialize
tags into a sequence from the stream they are deserializing from.
This PR adds hooks so the deserializee can inform the deserializer
to provide them a sequence if possible.

Closes #38.
This commit is contained in:
Erick Tryzelaar 2015-03-20 08:32:33 -07:00
parent 5378d22708
commit d17846eff1
4 changed files with 200 additions and 138 deletions

View File

@ -30,7 +30,7 @@ pub struct Outer {
//////////////////////////////////////////////////////////////////////////////
#[derive(Debug)]
#[derive(Debug, PartialEq)]
pub enum Error {
EndOfStream,
SyntaxError,
@ -366,30 +366,6 @@ mod deserializer {
where V: de::Visitor,
{
match self.stack.pop() {
Some(State::OuterState(Outer { inner })) => {
self.stack.push(State::VecState(inner));
self.stack.push(State::StrState("inner"));
visitor.visit_named_map("Outer", OuterMapVisitor {
de: self,
state: 0,
})
}
Some(State::InnerState(Inner { a: (), b, c })) => {
self.stack.push(State::MapState(c));
self.stack.push(State::StrState("c"));
self.stack.push(State::UsizeState(b));
self.stack.push(State::StrState("b"));
self.stack.push(State::NullState);
self.stack.push(State::StrState("a"));
visitor.visit_named_map("Inner", InnerMapVisitor {
de: self,
state: 0,
})
}
Some(State::VecState(value)) => {
visitor.visit_seq(OuterSeqVisitor {
de: self,
@ -423,9 +399,52 @@ mod deserializer {
Some(State::OptionState(true)) => {
visitor.visit_some(self)
}
Some(token) => Err(Error::SyntaxError),
None => Err(Error::EndOfStream),
}
}
fn visit_named_map<V>(&mut self, name: &str, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.stack.pop() {
Some(State::OuterState(Outer { inner })) => {
if name != "Outer" {
return Err(Error::SyntaxError);
}
self.stack.push(State::VecState(inner));
self.stack.push(State::StrState("inner"));
visitor.visit_map(OuterMapVisitor {
de: self,
state: 0,
})
}
Some(State::InnerState(Inner { a: (), b, c })) => {
if name != "Inner" {
return Err(Error::SyntaxError);
}
self.stack.push(State::MapState(c));
self.stack.push(State::StrState("c"));
self.stack.push(State::UsizeState(b));
self.stack.push(State::StrState("b"));
self.stack.push(State::NullState);
self.stack.push(State::StrState("a"));
visitor.visit_map(InnerMapVisitor {
de: self,
state: 0,
})
}
_ => {
Err(Error::SyntaxError)
}
}
}
}
struct OuterMapVisitor<'a> {
@ -605,9 +624,9 @@ fn bench_decoder_0_0(b: &mut Bencher) {
};
let mut d = decoder::OuterDecoder::new(outer.clone());
let value: Outer = Decodable::decode(&mut d).unwrap();
let value: Result<Outer, Error> = Decodable::decode(&mut d);
assert_eq!(value, outer);
assert_eq!(value, Ok(outer));
})
}
@ -627,9 +646,9 @@ fn bench_decoder_1_0(b: &mut Bencher) {
};
let mut d = decoder::OuterDecoder::new(outer.clone());
let value: Outer = Decodable::decode(&mut d).unwrap();
let value: Result<Outer, Error> = Decodable::decode(&mut d);
assert_eq!(value, outer);
assert_eq!(value, Ok(outer));
})
}
@ -654,9 +673,9 @@ fn bench_decoder_1_5(b: &mut Bencher) {
};
let mut d = decoder::OuterDecoder::new(outer.clone());
let value: Outer = Decodable::decode(&mut d).unwrap();
let value: Result<Outer, Error> = Decodable::decode(&mut d);
assert_eq!(value, outer);
assert_eq!(value, Ok(outer));
})
}
@ -668,9 +687,9 @@ fn bench_deserializer_0_0(b: &mut Bencher) {
};
let mut d = deserializer::OuterDeserializer::new(outer.clone());
let value: Outer = Deserialize::deserialize(&mut d).unwrap();
let value: Result<Outer, Error> = Deserialize::deserialize(&mut d);
assert_eq!(value, outer);
assert_eq!(value, Ok(outer));
})
}
@ -690,9 +709,9 @@ fn bench_deserializer_1_0(b: &mut Bencher) {
};
let mut d = deserializer::OuterDeserializer::new(outer.clone());
let value: Outer = Deserialize::deserialize(&mut d).unwrap();
let value: Result<Outer, Error> = Deserialize::deserialize(&mut d);
assert_eq!(value, outer);
assert_eq!(value, Ok(outer));
})
}
@ -717,8 +736,8 @@ fn bench_deserializer_1_5(b: &mut Bencher) {
};
let mut d = deserializer::OuterDeserializer::new(outer.clone());
let value: Outer = Deserialize::deserialize(&mut d).unwrap();
let value: Result<Outer, Error> = Deserialize::deserialize(&mut d);
assert_eq!(value, outer);
assert_eq!(value, Ok(outer));
})
}

View File

@ -205,18 +205,6 @@ fn deserialize_unit_struct(
Ok($type_ident)
}
#[inline]
fn visit_named_unit<
E: ::serde::de::Error,
>(&mut self, name: &str) -> Result<$type_ident, E> {
if name == $type_name {
self.visit_unit()
} else {
Err(::serde::de::Error::syntax_error())
}
}
#[inline]
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<$type_ident, V::Error>
where V: ::serde::de::SeqVisitor,
@ -226,7 +214,7 @@ fn deserialize_unit_struct(
}
}
deserializer.visit(__Visitor)
deserializer.visit_named_unit($type_name, __Visitor)
})
}
@ -265,21 +253,9 @@ fn deserialize_tuple_struct(
{
$visit_seq_expr
}
fn visit_named_seq<__V>(&mut self,
name: &str,
visitor: __V) -> Result<$ty, __V::Error>
where __V: ::serde::de::SeqVisitor,
{
if name == $type_name {
self.visit_seq(visitor)
} else {
Err(::serde::de::Error::syntax_error())
}
}
}
deserializer.visit($visitor_expr)
deserializer.visit_named_seq($type_name, $visitor_expr)
})
}
@ -355,22 +331,9 @@ fn deserialize_struct(
{
$visit_map_expr
}
#[inline]
fn visit_named_map<__V>(&mut self,
name: &str,
visitor: __V) -> Result<$ty, __V::Error>
where __V: ::serde::de::MapVisitor,
{
if name == $type_name {
self.visit_map(visitor)
} else {
Err(::serde::de::Error::syntax_error())
}
}
}
deserializer.visit($visitor_expr)
deserializer.visit_named_map($type_name, $visitor_expr)
})
}

View File

@ -18,22 +18,24 @@ pub trait Error {
///////////////////////////////////////////////////////////////////////////////
pub trait Deserialize {
/// Deserialize this value given this `Deserializer`.
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
where D: Deserializer;
}
///////////////////////////////////////////////////////////////////////////////
/// `Deserializer` is an abstract trait that can deserialize values into a `Visitor`.
pub trait Deserializer {
type Error: Error;
/// The `visit` method walks a visitor through a value as it is being deserialized.
fn visit<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
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
/// 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)`.
#[inline]
fn visit_option<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
@ -42,10 +44,59 @@ pub trait Deserializer {
self.visit(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.
/// 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.
#[inline]
fn visit_seq<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
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.
#[inline]
fn visit_map<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
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.
#[inline]
fn visit_named_unit<V>(&mut self, _name: &str, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
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.
#[inline]
fn visit_named_seq<V>(&mut self, _name: &str, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
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.
#[inline]
fn visit_named_map<V>(&mut self, _name: &str, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
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.
#[inline]
fn visit_enum<V>(&mut self, _enum: &str, _visitor: V) -> Result<V::Value, Self::Error>
where V: EnumVisitor,
@ -191,25 +242,11 @@ pub trait Visitor {
Err(Error::syntax_error())
}
#[inline]
fn visit_named_seq<V>(&mut self, _name: &str, visitor: V) -> Result<Self::Value, V::Error>
where V: SeqVisitor,
{
self.visit_seq(visitor)
}
fn visit_map<V>(&mut self, _visitor: V) -> Result<Self::Value, V::Error>
where V: MapVisitor,
{
Err(Error::syntax_error())
}
#[inline]
fn visit_named_map<V>(&mut self, _name: &str, visitor: V) -> Result<Self::Value, V::Error>
where V: MapVisitor,
{
self.visit_map(visitor)
}
}
///////////////////////////////////////////////////////////////////////////////

View File

@ -11,7 +11,7 @@ use std::vec;
use serde::de::{self, Deserialize, Deserializer, Visitor};
#[derive(Debug)]
enum Token<'a> {
enum Token {
Bool(bool),
Isize(isize),
I8(i8),
@ -26,34 +26,33 @@ enum Token<'a> {
F32(f32),
F64(f64),
Char(char),
Str(&'a str),
Str(&'static str),
String(String),
Option(bool),
Name(&'static str),
Unit,
NamedUnit(&'a str),
SeqStart(usize),
NamedSeqStart(&'a str, usize),
SeqSep(bool),
SeqEnd,
MapStart(usize),
NamedMapStart(&'a str, usize),
MapSep(bool),
MapEnd,
EnumStart(&'a str),
EnumStart(&'static str),
EnumEnd,
}
struct TokenDeserializer<'a> {
tokens: iter::Peekable<vec::IntoIter<Token<'a>>>,
struct TokenDeserializer {
tokens: iter::Peekable<vec::IntoIter<Token>>,
}
impl<'a> TokenDeserializer<'a> {
fn new(tokens: Vec<Token<'a>>) -> TokenDeserializer<'a> {
impl<'a> TokenDeserializer {
fn new(tokens: Vec<Token>) -> TokenDeserializer {
TokenDeserializer {
tokens: tokens.into_iter().peekable(),
}
@ -65,6 +64,7 @@ enum Error {
SyntaxError,
EndOfStreamError,
MissingFieldError(&'static str),
InvalidName(&'static str),
}
impl de::Error for Error {
@ -77,7 +77,7 @@ impl de::Error for Error {
}
}
impl<'a> Deserializer for TokenDeserializer<'a> {
impl Deserializer for TokenDeserializer {
type Error = Error;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
@ -103,7 +103,6 @@ impl<'a> Deserializer for TokenDeserializer<'a> {
Some(Token::Option(false)) => visitor.visit_none(),
Some(Token::Option(true)) => visitor.visit_some(self),
Some(Token::Unit) => visitor.visit_unit(),
Some(Token::NamedUnit(name)) => visitor.visit_named_unit(name),
Some(Token::SeqStart(len)) => {
visitor.visit_seq(TokenDeserializerSeqVisitor {
de: self,
@ -111,13 +110,6 @@ impl<'a> Deserializer for TokenDeserializer<'a> {
first: true,
})
}
Some(Token::NamedSeqStart(name, len)) => {
visitor.visit_named_seq(name, TokenDeserializerSeqVisitor {
de: self,
len: len,
first: true,
})
}
Some(Token::MapStart(len)) => {
visitor.visit_map(TokenDeserializerMapVisitor {
de: self,
@ -125,13 +117,7 @@ impl<'a> Deserializer for TokenDeserializer<'a> {
first: true,
})
}
Some(Token::NamedMapStart(name, len)) => {
visitor.visit_named_map(name, TokenDeserializerMapVisitor {
de: self,
len: len,
first: true,
})
}
Some(Token::Name(_)) => self.visit(visitor),
Some(_) => Err(Error::SyntaxError),
None => Err(Error::EndOfStreamError),
}
@ -177,17 +163,68 @@ impl<'a> Deserializer for TokenDeserializer<'a> {
None => Err(Error::EndOfStreamError),
}
}
fn visit_named_unit<V>(&mut self, name: &str, visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.tokens.peek() {
Some(&Token::Name(n)) => {
if name == n {
self.tokens.next();
self.visit_seq(visitor)
} else {
Err(Error::InvalidName(n))
}
}
Some(_) => self.visit(visitor),
None => Err(Error::EndOfStreamError),
}
}
fn visit_named_seq<V>(&mut self, name: &str, visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.tokens.peek() {
Some(&Token::Name(n)) => {
if name == n {
self.tokens.next();
self.visit_seq(visitor)
} else {
Err(Error::InvalidName(n))
}
}
Some(_) => self.visit_seq(visitor),
None => Err(Error::EndOfStreamError),
}
}
fn visit_named_map<V>(&mut self, name: &str, visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.tokens.peek() {
Some(&Token::Name(n)) => {
if name == n {
self.tokens.next();
self.visit_map(visitor)
} else {
Err(Error::InvalidName(n))
}
}
Some(_) => self.visit_map(visitor),
None => Err(Error::EndOfStreamError),
}
}
}
//////////////////////////////////////////////////////////////////////////
struct TokenDeserializerSeqVisitor<'a, 'b: 'a> {
de: &'a mut TokenDeserializer<'b>,
struct TokenDeserializerSeqVisitor<'a> {
de: &'a mut TokenDeserializer,
len: usize,
first: bool,
}
impl<'a, 'b> de::SeqVisitor for TokenDeserializerSeqVisitor<'a, 'b> {
impl<'a> de::SeqVisitor for TokenDeserializerSeqVisitor<'a> {
type Error = Error;
fn visit<T>(&mut self) -> Result<Option<T>, Error>
@ -226,13 +263,13 @@ impl<'a, 'b> de::SeqVisitor for TokenDeserializerSeqVisitor<'a, 'b> {
//////////////////////////////////////////////////////////////////////////
struct TokenDeserializerMapVisitor<'a, 'b: 'a> {
de: &'a mut TokenDeserializer<'b>,
struct TokenDeserializerMapVisitor<'a> {
de: &'a mut TokenDeserializer,
len: usize,
first: bool,
}
impl<'a, 'b> de::MapVisitor for TokenDeserializerMapVisitor<'a, 'b> {
impl<'a> de::MapVisitor for TokenDeserializerMapVisitor<'a> {
type Error = Error;
fn visit_key<K>(&mut self) -> Result<Option<K>, Error>
@ -275,11 +312,11 @@ impl<'a, 'b> de::MapVisitor for TokenDeserializerMapVisitor<'a, 'b> {
//////////////////////////////////////////////////////////////////////////
struct TokenDeserializerVariantVisitor<'a, 'b: 'a> {
de: &'a mut TokenDeserializer<'b>,
struct TokenDeserializerVariantVisitor<'a> {
de: &'a mut TokenDeserializer,
}
impl<'a, 'b> de::VariantVisitor for TokenDeserializerVariantVisitor<'a, 'b> {
impl<'a> de::VariantVisitor for TokenDeserializerVariantVisitor<'a> {
type Error = Error;
fn visit_variant<V>(&mut self) -> Result<V, Error>
@ -418,13 +455,17 @@ declare_tests! {
Token::SeqEnd,
],
() => vec![
Token::NamedSeqStart("Anything", 0),
Token::Name("Anything"),
Token::SeqStart(0),
Token::SeqEnd,
],
}
test_named_unit {
NamedUnit => vec![Token::Unit],
NamedUnit => vec![Token::NamedUnit("NamedUnit")],
NamedUnit => vec![
Token::Name("NamedUnit"),
Token::Unit,
],
NamedUnit => vec![
Token::SeqStart(0),
Token::SeqEnd,
@ -444,7 +485,8 @@ declare_tests! {
Token::SeqEnd,
],
NamedSeq(1, 2, 3) => vec![
Token::NamedSeqStart("NamedSeq", 3),
Token::Name("NamedSeq"),
Token::SeqStart(3),
Token::SeqSep(true),
Token::I32(1),
@ -561,7 +603,8 @@ declare_tests! {
Token::MapEnd,
],
NamedMap { a: 1, b: 2, c: 3 } => vec![
Token::NamedMapStart("NamedMap", 3),
Token::Name("NamedMap"),
Token::MapStart(3),
Token::MapSep(true),
Token::Str("a"),
Token::I32(1),