mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-04-26 01:37:55 +00:00
Add support for option handling
This commit is contained in:
+91
-59
@@ -25,14 +25,17 @@ pub trait Deserializer {
|
|||||||
V: Visitor,
|
V: Visitor,
|
||||||
>(&mut self, visitor: &mut V) -> Result<V::Value, Self::Error>;
|
>(&mut self, visitor: &mut V) -> Result<V::Value, Self::Error>;
|
||||||
|
|
||||||
/*
|
/// 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<
|
fn visit_option<
|
||||||
R,
|
V: Visitor,
|
||||||
V: Visitor<Self, R, E>,
|
>(&mut self, visitor: &mut V) -> Result<V::Value, Self::Error> {
|
||||||
>(&mut self, visitor: &mut V) -> Result<R, S::Error> {
|
|
||||||
self.visit(visitor)
|
self.visit(visitor)
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Visitor {
|
pub trait Visitor {
|
||||||
@@ -152,22 +155,17 @@ pub trait Visitor {
|
|||||||
self.visit_unit()
|
self.visit_unit()
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
fn visit_none<
|
||||||
#[inline]
|
|
||||||
fn visit_enum_unit<
|
|
||||||
E: Error,
|
E: Error,
|
||||||
>(&mut self, _name: &str, _variant: &str) -> Result<Self::Value, E> {
|
>(&mut self) -> Result<Self::Value, E> {
|
||||||
self.visit_unit()
|
Err(Error::syntax_error())
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
fn visit_some<
|
||||||
/*
|
S: Deserializer,
|
||||||
fn visit_option<
|
>(&mut self, _state: &mut S) -> Result<Self::Value, S::Error> {
|
||||||
V: OptionVisitor<S, E>,
|
|
||||||
>(&mut self, _visitor: V) -> Result<Self::Value, E> {
|
|
||||||
Err(Error::syntax_error())
|
Err(Error::syntax_error())
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
fn visit_seq<
|
fn visit_seq<
|
||||||
V: SeqVisitor,
|
V: SeqVisitor,
|
||||||
@@ -203,14 +201,6 @@ pub trait Visitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
pub trait OptionVisitor<S, E> {
|
|
||||||
fn visit<
|
|
||||||
T: Deserialize<S, E>,
|
|
||||||
>(&mut self) -> Result<Option<T>, E>;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
pub trait SeqVisitor {
|
pub trait SeqVisitor {
|
||||||
type Error: Error;
|
type Error: Error;
|
||||||
|
|
||||||
@@ -476,35 +466,39 @@ impl Deserialize for String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
struct OptionVisitor<T>;
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
T: Deserialize<S, E>,
|
T: Deserialize,
|
||||||
S: Deserializer<E>,
|
> Visitor for OptionVisitor<T> {
|
||||||
E: Error,
|
type Value = Option<T>;
|
||||||
> Deserialize<S, E> for Option<T> {
|
|
||||||
fn deserialize(state: &mut S) -> Result<Option<T>, E> {
|
|
||||||
struct Visitor;
|
|
||||||
|
|
||||||
impl<
|
#[inline]
|
||||||
T: Deserialize<S, E>,
|
fn visit_none<
|
||||||
S: Deserializer<E>,
|
E: Error,
|
||||||
E: Error,
|
>(&mut self) -> Result<Option<T>, E> {
|
||||||
> self::Visitor<S, Option<T>, E> for Visitor {
|
Ok(None)
|
||||||
fn visit_option<
|
}
|
||||||
V: OptionVisitor<S, E>,
|
|
||||||
>(&mut self, mut visitor: V) -> Result<Option<T>, E> {
|
|
||||||
visitor.visit()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
state.visit_option(&mut Visitor)
|
#[inline]
|
||||||
|
fn visit_some<
|
||||||
|
S: Deserializer,
|
||||||
|
>(&mut self, state: &mut S) -> Result<Option<T>, S::Error> {
|
||||||
|
Ok(Some(try!(Deserialize::deserialize(state))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Deserialize for Option<T> where T: Deserialize {
|
||||||
|
fn deserialize<
|
||||||
|
S: Deserializer,
|
||||||
|
>(state: &mut S) -> Result<Option<T>, S::Error> {
|
||||||
|
state.visit_option(&mut OptionVisitor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
*/
|
|
||||||
|
|
||||||
struct VecVisitor<T>;
|
struct VecVisitor<T>;
|
||||||
|
|
||||||
@@ -668,6 +662,7 @@ impl<
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::{Deserialize, Deserializer, Visitor};
|
use super::{Deserialize, Deserializer, Visitor};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
use std::iter;
|
||||||
use std::vec;
|
use std::vec;
|
||||||
|
|
||||||
#[derive(Show)]
|
#[derive(Show)]
|
||||||
@@ -689,6 +684,8 @@ mod tests {
|
|||||||
Str(&'a str),
|
Str(&'a str),
|
||||||
String(String),
|
String(String),
|
||||||
|
|
||||||
|
Option(bool),
|
||||||
|
|
||||||
Unit,
|
Unit,
|
||||||
NamedUnit(&'a str),
|
NamedUnit(&'a str),
|
||||||
|
|
||||||
@@ -707,13 +704,13 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct TokenDeserializer<'a> {
|
struct TokenDeserializer<'a> {
|
||||||
tokens: vec::IntoIter<Token<'a>>,
|
tokens: iter::Peekable<Token<'a>, vec::IntoIter<Token<'a>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> TokenDeserializer<'a> {
|
impl<'a> TokenDeserializer<'a> {
|
||||||
fn new(tokens: Vec<Token<'a>>) -> TokenDeserializer<'a> {
|
fn new(tokens: Vec<Token<'a>>) -> TokenDeserializer<'a> {
|
||||||
TokenDeserializer {
|
TokenDeserializer {
|
||||||
tokens: tokens.into_iter(),
|
tokens: tokens.into_iter().peekable(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -753,6 +750,8 @@ mod tests {
|
|||||||
Some(Token::Char(v)) => visitor.visit_char(v),
|
Some(Token::Char(v)) => visitor.visit_char(v),
|
||||||
Some(Token::Str(v)) => visitor.visit_str(v),
|
Some(Token::Str(v)) => visitor.visit_str(v),
|
||||||
Some(Token::String(v)) => visitor.visit_string(v),
|
Some(Token::String(v)) => visitor.visit_string(v),
|
||||||
|
Some(Token::Option(false)) => visitor.visit_none(),
|
||||||
|
Some(Token::Option(true)) => visitor.visit_some(self),
|
||||||
Some(Token::Unit) => visitor.visit_unit(),
|
Some(Token::Unit) => visitor.visit_unit(),
|
||||||
Some(Token::NamedUnit(name)) => visitor.visit_named_unit(name),
|
Some(Token::NamedUnit(name)) => visitor.visit_named_unit(name),
|
||||||
Some(Token::SeqStart(len)) => {
|
Some(Token::SeqStart(len)) => {
|
||||||
@@ -792,6 +791,30 @@ mod tests {
|
|||||||
None => Err(Error::EndOfStreamError),
|
None => Err(Error::EndOfStreamError),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Hook into `Option` deserializing so we can treat `Unit` as a
|
||||||
|
/// `None`, or a regular value as `Some(value)`.
|
||||||
|
#[inline]
|
||||||
|
fn visit_option<
|
||||||
|
V: Visitor,
|
||||||
|
>(&mut self, visitor: &mut V) -> Result<V::Value, Error> {
|
||||||
|
match self.tokens.peek() {
|
||||||
|
Some(&Token::Option(false)) => {
|
||||||
|
self.tokens.next();
|
||||||
|
visitor.visit_none()
|
||||||
|
}
|
||||||
|
Some(&Token::Option(true)) => {
|
||||||
|
self.tokens.next();
|
||||||
|
visitor.visit_some(self)
|
||||||
|
}
|
||||||
|
Some(&Token::Unit) => {
|
||||||
|
self.tokens.next();
|
||||||
|
visitor.visit_none()
|
||||||
|
}
|
||||||
|
Some(_) => visitor.visit_some(self),
|
||||||
|
None => Err(Error::EndOfStreamError),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@@ -1294,17 +1317,6 @@ mod tests {
|
|||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
declare_tests! {
|
declare_tests! {
|
||||||
test_unit {
|
|
||||||
() => vec![Token::Unit],
|
|
||||||
() => vec![
|
|
||||||
Token::SeqStart(0),
|
|
||||||
Token::SeqEnd,
|
|
||||||
],
|
|
||||||
() => vec![
|
|
||||||
Token::NamedSeqStart("Anything", 0),
|
|
||||||
Token::SeqEnd,
|
|
||||||
],
|
|
||||||
}
|
|
||||||
test_bool {
|
test_bool {
|
||||||
true => vec![Token::Bool(true)],
|
true => vec![Token::Bool(true)],
|
||||||
false => vec![Token::Bool(false)],
|
false => vec![Token::Bool(false)],
|
||||||
@@ -1351,6 +1363,26 @@ mod tests {
|
|||||||
"abc".to_string() => vec![Token::String("abc".to_string())],
|
"abc".to_string() => vec![Token::String("abc".to_string())],
|
||||||
"a".to_string() => vec![Token::Char('a')],
|
"a".to_string() => vec![Token::Char('a')],
|
||||||
}
|
}
|
||||||
|
test_option {
|
||||||
|
None::<i32> => vec![Token::Unit],
|
||||||
|
None::<i32> => vec![Token::Option(false)],
|
||||||
|
Some(1) => vec![Token::I32(1)],
|
||||||
|
Some(1) => vec![
|
||||||
|
Token::Option(true),
|
||||||
|
Token::I32(1),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
test_unit {
|
||||||
|
() => vec![Token::Unit],
|
||||||
|
() => vec![
|
||||||
|
Token::SeqStart(0),
|
||||||
|
Token::SeqEnd,
|
||||||
|
],
|
||||||
|
() => vec![
|
||||||
|
Token::NamedSeqStart("Anything", 0),
|
||||||
|
Token::SeqEnd,
|
||||||
|
],
|
||||||
|
}
|
||||||
test_named_unit {
|
test_named_unit {
|
||||||
NamedUnit => vec![Token::Unit],
|
NamedUnit => vec![Token::Unit],
|
||||||
NamedUnit => vec![Token::NamedUnit("NamedUnit")],
|
NamedUnit => vec![Token::NamedUnit("NamedUnit")],
|
||||||
|
|||||||
+47
-11
@@ -109,6 +109,12 @@ pub trait Visitor {
|
|||||||
|
|
||||||
fn visit_str(&mut self, value: &str) -> Result<Self::Value, Self::Error>;
|
fn visit_str(&mut self, value: &str) -> Result<Self::Value, Self::Error>;
|
||||||
|
|
||||||
|
fn visit_none(&mut self) -> Result<Self::Value, Self::Error>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_some<V>(&mut self, value: V) -> Result<Self::Value, Self::Error>
|
||||||
|
where V: Serialize;
|
||||||
|
|
||||||
fn visit_seq<V>(&mut self, visitor: V) -> Result<Self::Value, Self::Error>
|
fn visit_seq<V>(&mut self, visitor: V) -> Result<Self::Value, Self::Error>
|
||||||
where V: SeqVisitor;
|
where V: SeqVisitor;
|
||||||
|
|
||||||
@@ -240,6 +246,20 @@ impl Serialize for String {
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
impl<T> Serialize for Option<T> where T: Serialize {
|
||||||
|
#[inline]
|
||||||
|
fn visit<
|
||||||
|
V: Visitor,
|
||||||
|
>(&self, visitor: &mut V) -> Result<V::Value, V::Error> {
|
||||||
|
match *self {
|
||||||
|
Some(ref value) => visitor.visit_some(value),
|
||||||
|
None => visitor.visit_none(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
pub struct SeqIteratorVisitor<Iter> {
|
pub struct SeqIteratorVisitor<Iter> {
|
||||||
iter: Iter,
|
iter: Iter,
|
||||||
first: bool,
|
first: bool,
|
||||||
@@ -306,9 +326,7 @@ impl<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<T> Serialize for BTreeSet<T> where T: Serialize {
|
||||||
T: Serialize,
|
|
||||||
> Serialize for BTreeSet<T> {
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit<
|
fn visit<
|
||||||
V: Visitor,
|
V: Visitor,
|
||||||
@@ -323,9 +341,7 @@ impl<T, S, H> Serialize for HashSet<T, S>
|
|||||||
H: Hasher<Output=u64>,
|
H: Hasher<Output=u64>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit<
|
fn visit<V: Visitor>(&self, visitor: &mut V) -> Result<V::Value, V::Error> {
|
||||||
V: Visitor,
|
|
||||||
>(&self, visitor: &mut V) -> Result<V::Value, V::Error> {
|
|
||||||
visitor.visit_seq(SeqIteratorVisitor::new(self.iter()))
|
visitor.visit_seq(SeqIteratorVisitor::new(self.iter()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -533,11 +549,11 @@ impl<K, V, Iter: Iterator<Item=(K, V)>> MapIteratorVisitor<Iter> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<K, V, I> MapVisitor for MapIteratorVisitor<I>
|
||||||
K: Serialize,
|
where K: Serialize,
|
||||||
V: Serialize,
|
V: Serialize,
|
||||||
Iter: Iterator<Item=(K, V)>,
|
I: Iterator<Item=(K, V)>,
|
||||||
> MapVisitor for MapIteratorVisitor<Iter> {
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit<
|
fn visit<
|
||||||
V_: Visitor,
|
V_: Visitor,
|
||||||
@@ -808,6 +824,19 @@ mod tests {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_none(&mut self) -> Result<(), ()> {
|
||||||
|
assert_eq!(self.iter.next(), Some(Token::Option(false)));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_some<V>(&mut self, value: V) -> Result<(), ()>
|
||||||
|
where V: Serialize,
|
||||||
|
{
|
||||||
|
assert_eq!(self.iter.next(), Some(Token::Option(true)));
|
||||||
|
value.visit(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fn visit_seq<V>(&mut self, visitor: V) -> Result<(), ()>
|
fn visit_seq<V>(&mut self, visitor: V) -> Result<(), ()>
|
||||||
where V: SeqVisitor
|
where V: SeqVisitor
|
||||||
{
|
{
|
||||||
@@ -1107,6 +1136,13 @@ mod tests {
|
|||||||
"abc" => vec![Token::Str("abc")],
|
"abc" => vec![Token::Str("abc")],
|
||||||
"abc".to_string() => vec![Token::Str("abc")],
|
"abc".to_string() => vec![Token::Str("abc")],
|
||||||
}
|
}
|
||||||
|
test_option {
|
||||||
|
None::<i32> => vec![Token::Option(false)],
|
||||||
|
Some(1) => vec![
|
||||||
|
Token::Option(true),
|
||||||
|
Token::I32(1),
|
||||||
|
],
|
||||||
|
}
|
||||||
test_slice {
|
test_slice {
|
||||||
&[0][..0] => vec![
|
&[0][..0] => vec![
|
||||||
Token::SeqStart(0),
|
Token::SeqStart(0),
|
||||||
|
|||||||
Reference in New Issue
Block a user