mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-06-12 07:21:03 +00:00
Split out multiple collection types: 153ns vs 194ns
This allows a consumer of a deserializer stream to know what type it might be dealing with.
This commit is contained in:
@@ -24,10 +24,15 @@ pub enum Token {
|
|||||||
Char(char),
|
Char(char),
|
||||||
Str(&'static str),
|
Str(&'static str),
|
||||||
StrBuf(StrBuf),
|
StrBuf(StrBuf),
|
||||||
|
|
||||||
Option(bool),
|
Option(bool),
|
||||||
CollectionStart(uint),
|
|
||||||
CollectionSep,
|
TupleStart(uint),
|
||||||
CollectionEnd,
|
SeqStart(uint),
|
||||||
|
MapStart(uint),
|
||||||
|
|
||||||
|
Sep,
|
||||||
|
End,
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! expect_token {
|
macro_rules! expect_token {
|
||||||
@@ -40,9 +45,9 @@ macro_rules! expect_token {
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! match_token {
|
macro_rules! match_token {
|
||||||
($( $Variant:pat => $E:expr ),+) => {
|
($( $variant:pat => $expr:expr ),+) => {
|
||||||
match expect_token!() {
|
match expect_token!() {
|
||||||
$( Ok($Variant) => $E ),+,
|
$( Ok($variant) => $expr ),+,
|
||||||
Ok(_) => { return Err(self.syntax_error()); }
|
Ok(_) => { return Err(self.syntax_error()); }
|
||||||
Err(err) => { return Err(err); }
|
Err(err) => { return Err(err); }
|
||||||
}
|
}
|
||||||
@@ -67,7 +72,11 @@ pub trait Deserializer<E>: Iterator<Result<Token, E>> {
|
|||||||
fn expect_null(&mut self) -> Result<(), E> {
|
fn expect_null(&mut self) -> Result<(), E> {
|
||||||
match_token! {
|
match_token! {
|
||||||
Null => Ok(()),
|
Null => Ok(()),
|
||||||
CollectionStart(_) => self.expect_collection_end()
|
TupleStart(_) => {
|
||||||
|
match_token! {
|
||||||
|
End => Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,11 +141,33 @@ pub trait Deserializer<E>: Iterator<Result<Token, E>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn expect_collection<
|
fn expect_tuple_start(&mut self, len: uint) -> Result<(), E> {
|
||||||
|
match_token! {
|
||||||
|
TupleStart(l) => {
|
||||||
|
if len == l {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(self.syntax_error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn expect_tuple_elt<T: Deserializable<E, Self>>(&mut self) -> Result<T, E> {
|
||||||
|
match_token! {
|
||||||
|
Sep => Deserializable::deserialize(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn expect_seq<
|
||||||
T: Deserializable<E, Self>,
|
T: Deserializable<E, Self>,
|
||||||
C: FromIterator<T>
|
C: FromIterator<T>
|
||||||
>(&mut self) -> Result<C, E> {
|
>(&mut self) -> Result<C, E> {
|
||||||
let len = try!(self.expect_collection_start());
|
let len = match_token! {
|
||||||
|
SeqStart(len) => len
|
||||||
|
};
|
||||||
|
|
||||||
let iter = self.by_ref().batch(|d| {
|
let iter = self.by_ref().batch(|d| {
|
||||||
let d = d.iter();
|
let d = d.iter();
|
||||||
@@ -147,11 +178,11 @@ pub trait Deserializer<E>: Iterator<Result<Token, E>> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
match token {
|
match token {
|
||||||
Ok(CollectionEnd) => None,
|
Ok(Sep) => {
|
||||||
Ok(CollectionSep) => {
|
|
||||||
let value: Result<T, E> = Deserializable::deserialize(d);
|
let value: Result<T, E> = Deserializable::deserialize(d);
|
||||||
Some(value)
|
Some(value)
|
||||||
}
|
}
|
||||||
|
Ok(End) => None,
|
||||||
Ok(_) => Some(Err(d.syntax_error())),
|
Ok(_) => Some(Err(d.syntax_error())),
|
||||||
Err(e) => Some(Err(e)),
|
Err(e) => Some(Err(e)),
|
||||||
}
|
}
|
||||||
@@ -161,23 +192,41 @@ pub trait Deserializer<E>: Iterator<Result<Token, E>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn expect_collection_start(&mut self) -> Result<uint, E> {
|
fn expect_map<
|
||||||
match_token! {
|
K: Deserializable<E, Self>,
|
||||||
CollectionStart(len) => Ok(len)
|
V: Deserializable<E, Self>,
|
||||||
}
|
C: FromIterator<(K, V)>
|
||||||
|
>(&mut self) -> Result<C, E> {
|
||||||
|
let len = match_token! {
|
||||||
|
MapStart(len) => len
|
||||||
|
};
|
||||||
|
|
||||||
|
let iter = self.by_ref().batch(|d| {
|
||||||
|
let d = d.iter();
|
||||||
|
|
||||||
|
let token = match d.next() {
|
||||||
|
Some(token) => token,
|
||||||
|
None => { return None; }
|
||||||
|
};
|
||||||
|
|
||||||
|
match token {
|
||||||
|
Ok(Sep) => {
|
||||||
|
let kv: Result<(K, V), E> = Deserializable::deserialize(d);
|
||||||
|
Some(kv)
|
||||||
|
}
|
||||||
|
Ok(End) => None,
|
||||||
|
Ok(_) => Some(Err(d.syntax_error())),
|
||||||
|
Err(e) => Some(Err(e)),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
result::collect_with_capacity(iter, len)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn expect_collection_sep(&mut self) -> Result<(), E> {
|
fn expect_end(&mut self) -> Result<(), E> {
|
||||||
match_token! {
|
match_token! {
|
||||||
CollectionSep => Ok(())
|
End => Ok(())
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn expect_collection_end(&mut self) -> Result<(), E> {
|
|
||||||
match_token! {
|
|
||||||
CollectionEnd => Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -243,7 +292,7 @@ impl<
|
|||||||
> Deserializable<E, D> for Vec<T> {
|
> Deserializable<E, D> for Vec<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn deserialize(d: &mut D) -> Result<Vec<T>, E> {
|
fn deserialize(d: &mut D) -> Result<Vec<T>, E> {
|
||||||
d.expect_collection()
|
d.expect_seq()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,7 +304,7 @@ impl<
|
|||||||
> Deserializable<E, D> for HashMap<K, V> {
|
> Deserializable<E, D> for HashMap<K, V> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn deserialize(d: &mut D) -> Result<HashMap<K, V>, E> {
|
fn deserialize(d: &mut D) -> Result<HashMap<K, V>, E> {
|
||||||
d.expect_collection()
|
d.expect_map()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,17 +335,20 @@ macro_rules! deserialize_tuple (
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[allow(uppercase_variables)]
|
#[allow(uppercase_variables)]
|
||||||
fn deserialize(d: &mut D) -> Result<($($name,)*), E> {
|
fn deserialize(d: &mut D) -> Result<($($name,)*), E> {
|
||||||
try!(d.expect_collection_start());
|
// FIXME: how can we count macro args?
|
||||||
|
let mut len = 0;
|
||||||
|
$({ let $name = 1; len += $name; })*;
|
||||||
|
|
||||||
|
try!(d.expect_tuple_start(len));
|
||||||
|
|
||||||
let result = ($(
|
let result = ($(
|
||||||
{
|
{
|
||||||
try!(d.expect_collection_sep());
|
let $name = try!(d.expect_tuple_elt());
|
||||||
let $name = try!(Deserializable::deserialize(d));
|
|
||||||
$name
|
$name
|
||||||
}
|
}
|
||||||
,)*);
|
,)*);
|
||||||
|
|
||||||
try!(d.expect_collection_end());
|
try!(d.expect_end());
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
@@ -320,7 +372,8 @@ mod tests {
|
|||||||
|
|
||||||
use self::serialize::{Decoder, Decodable};
|
use self::serialize::{Decoder, Decodable};
|
||||||
|
|
||||||
use super::{Token, Int, StrBuf, CollectionStart, CollectionSep, CollectionEnd};
|
use super::{Token, Null, Int, StrBuf};
|
||||||
|
use super::{TupleStart, SeqStart, MapStart, Sep, End};
|
||||||
use super::{Deserializer, Deserializable};
|
use super::{Deserializer, Deserializable};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -372,10 +425,10 @@ mod tests {
|
|||||||
|
|
||||||
#[deriving(Eq, Show)]
|
#[deriving(Eq, Show)]
|
||||||
enum IntsDeserializerState {
|
enum IntsDeserializerState {
|
||||||
Start,
|
StartState,
|
||||||
SepOrEnd,
|
SepOrEndState,
|
||||||
Value,
|
ValueState,
|
||||||
End,
|
EndState,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct IntsDeserializer {
|
struct IntsDeserializer {
|
||||||
@@ -389,7 +442,7 @@ mod tests {
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn new(values: Vec<int>) -> IntsDeserializer {
|
fn new(values: Vec<int>) -> IntsDeserializer {
|
||||||
IntsDeserializer {
|
IntsDeserializer {
|
||||||
state: Start,
|
state: StartState,
|
||||||
len: values.len(),
|
len: values.len(),
|
||||||
iter: values.move_iter(),
|
iter: values.move_iter(),
|
||||||
value: None,
|
value: None,
|
||||||
@@ -401,31 +454,31 @@ mod tests {
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn next(&mut self) -> Option<Result<Token, Error>> {
|
fn next(&mut self) -> Option<Result<Token, Error>> {
|
||||||
match self.state {
|
match self.state {
|
||||||
Start => {
|
StartState => {
|
||||||
self.state = SepOrEnd;
|
self.state = SepOrEndState;
|
||||||
Some(Ok(CollectionStart(self.len)))
|
Some(Ok(SeqStart(self.len)))
|
||||||
}
|
}
|
||||||
SepOrEnd => {
|
SepOrEndState => {
|
||||||
match self.iter.next() {
|
match self.iter.next() {
|
||||||
Some(value) => {
|
Some(value) => {
|
||||||
self.state = Value;
|
self.state = ValueState;
|
||||||
self.value = Some(value);
|
self.value = Some(value);
|
||||||
Some(Ok(CollectionSep))
|
Some(Ok(Sep))
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
self.state = End;
|
self.state = EndState;
|
||||||
Some(Ok(CollectionEnd))
|
Some(Ok(End))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Value => {
|
ValueState => {
|
||||||
self.state = SepOrEnd;
|
self.state = SepOrEndState;
|
||||||
match self.value.take() {
|
match self.value.take() {
|
||||||
Some(value) => Some(Ok(Int(value))),
|
Some(value) => Some(Ok(Int(value))),
|
||||||
None => Some(Err(self.end_of_stream_error())),
|
None => Some(Err(self.end_of_stream_error())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
End => {
|
EndState => {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -445,9 +498,9 @@ mod tests {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn expect_num<T: NumCast>(&mut self) -> Result<T, Error> {
|
fn expect_num<T: NumCast>(&mut self) -> Result<T, Error> {
|
||||||
assert_eq!(self.state, Value);
|
assert_eq!(self.state, ValueState);
|
||||||
|
|
||||||
self.state = SepOrEnd;
|
self.state = SepOrEndState;
|
||||||
|
|
||||||
match self.value.take() {
|
match self.value.take() {
|
||||||
Some(value) => {
|
Some(value) => {
|
||||||
@@ -583,11 +636,23 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_tokens_null() {
|
||||||
|
let tokens = vec!(
|
||||||
|
Null,
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut deserializer = TokenDeserializer::new(tokens);
|
||||||
|
let value: Result<(), Error> = Deserializable::deserialize(&mut deserializer);
|
||||||
|
|
||||||
|
assert_eq!(value.unwrap(), ());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_tokens_tuple_empty() {
|
fn test_tokens_tuple_empty() {
|
||||||
let tokens = vec!(
|
let tokens = vec!(
|
||||||
CollectionStart(0),
|
TupleStart(0),
|
||||||
CollectionEnd,
|
End,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut deserializer = TokenDeserializer::new(tokens);
|
let mut deserializer = TokenDeserializer::new(tokens);
|
||||||
@@ -599,13 +664,13 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_tokens_tuple() {
|
fn test_tokens_tuple() {
|
||||||
let tokens = vec!(
|
let tokens = vec!(
|
||||||
CollectionStart(2),
|
TupleStart(2),
|
||||||
CollectionSep,
|
Sep,
|
||||||
Int(5),
|
Int(5),
|
||||||
|
|
||||||
CollectionSep,
|
Sep,
|
||||||
StrBuf("a".to_strbuf()),
|
StrBuf("a".to_strbuf()),
|
||||||
CollectionEnd,
|
End,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut deserializer = TokenDeserializer::new(tokens);
|
let mut deserializer = TokenDeserializer::new(tokens);
|
||||||
@@ -617,33 +682,36 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_tokens_tuple_compound() {
|
fn test_tokens_tuple_compound() {
|
||||||
let tokens = vec!(
|
let tokens = vec!(
|
||||||
CollectionStart(2),
|
TupleStart(3),
|
||||||
CollectionSep,
|
Sep,
|
||||||
CollectionStart(0),
|
Null,
|
||||||
CollectionEnd,
|
|
||||||
|
Sep,
|
||||||
|
TupleStart(0),
|
||||||
|
End,
|
||||||
|
|
||||||
CollectionSep,
|
Sep,
|
||||||
CollectionStart(2),
|
TupleStart(2),
|
||||||
CollectionSep,
|
Sep,
|
||||||
Int(5),
|
Int(5),
|
||||||
|
|
||||||
CollectionSep,
|
Sep,
|
||||||
StrBuf("a".to_strbuf()),
|
StrBuf("a".to_strbuf()),
|
||||||
CollectionEnd,
|
End,
|
||||||
CollectionEnd,
|
End,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut deserializer = TokenDeserializer::new(tokens);
|
let mut deserializer = TokenDeserializer::new(tokens);
|
||||||
let value: Result<((), (int, StrBuf)), Error> = Deserializable::deserialize(&mut deserializer);
|
let value: Result<((), (), (int, StrBuf)), Error> = Deserializable::deserialize(&mut deserializer);
|
||||||
|
|
||||||
assert_eq!(value.unwrap(), ((), (5, "a".to_strbuf())));
|
assert_eq!(value.unwrap(), ((), (), (5, "a".to_strbuf())));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_tokens_vec_empty() {
|
fn test_tokens_vec_empty() {
|
||||||
let tokens = vec!(
|
let tokens = vec!(
|
||||||
CollectionStart(0),
|
SeqStart(0),
|
||||||
CollectionEnd,
|
End,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut deserializer = TokenDeserializer::new(tokens);
|
let mut deserializer = TokenDeserializer::new(tokens);
|
||||||
@@ -655,16 +723,16 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_tokens_vec() {
|
fn test_tokens_vec() {
|
||||||
let tokens = vec!(
|
let tokens = vec!(
|
||||||
CollectionStart(3),
|
SeqStart(3),
|
||||||
CollectionSep,
|
Sep,
|
||||||
Int(5),
|
Int(5),
|
||||||
|
|
||||||
CollectionSep,
|
Sep,
|
||||||
Int(6),
|
Int(6),
|
||||||
|
|
||||||
CollectionSep,
|
Sep,
|
||||||
Int(7),
|
Int(7),
|
||||||
CollectionEnd,
|
End,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut deserializer = TokenDeserializer::new(tokens);
|
let mut deserializer = TokenDeserializer::new(tokens);
|
||||||
@@ -676,34 +744,34 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_tokens_vec_compound() {
|
fn test_tokens_vec_compound() {
|
||||||
let tokens = vec!(
|
let tokens = vec!(
|
||||||
CollectionStart(0),
|
SeqStart(0),
|
||||||
CollectionSep,
|
Sep,
|
||||||
CollectionStart(1),
|
SeqStart(1),
|
||||||
CollectionSep,
|
Sep,
|
||||||
Int(1),
|
Int(1),
|
||||||
CollectionEnd,
|
End,
|
||||||
|
|
||||||
CollectionSep,
|
Sep,
|
||||||
CollectionStart(2),
|
SeqStart(2),
|
||||||
CollectionSep,
|
Sep,
|
||||||
Int(2),
|
Int(2),
|
||||||
|
|
||||||
CollectionSep,
|
Sep,
|
||||||
Int(3),
|
Int(3),
|
||||||
CollectionEnd,
|
End,
|
||||||
|
|
||||||
CollectionSep,
|
Sep,
|
||||||
CollectionStart(3),
|
SeqStart(3),
|
||||||
CollectionSep,
|
Sep,
|
||||||
Int(4),
|
Int(4),
|
||||||
|
|
||||||
CollectionSep,
|
Sep,
|
||||||
Int(5),
|
Int(5),
|
||||||
|
|
||||||
CollectionSep,
|
Sep,
|
||||||
Int(6),
|
Int(6),
|
||||||
CollectionEnd,
|
End,
|
||||||
CollectionEnd,
|
End,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut deserializer = TokenDeserializer::new(tokens);
|
let mut deserializer = TokenDeserializer::new(tokens);
|
||||||
@@ -715,25 +783,25 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_tokens_hashmap() {
|
fn test_tokens_hashmap() {
|
||||||
let tokens = vec!(
|
let tokens = vec!(
|
||||||
CollectionStart(2),
|
MapStart(2),
|
||||||
CollectionSep,
|
Sep,
|
||||||
CollectionStart(2),
|
TupleStart(2),
|
||||||
CollectionSep,
|
Sep,
|
||||||
Int(5),
|
Int(5),
|
||||||
|
|
||||||
CollectionSep,
|
Sep,
|
||||||
StrBuf("a".to_strbuf()),
|
StrBuf("a".to_strbuf()),
|
||||||
CollectionEnd,
|
End,
|
||||||
|
|
||||||
CollectionSep,
|
Sep,
|
||||||
CollectionStart(2),
|
TupleStart(2),
|
||||||
CollectionSep,
|
Sep,
|
||||||
Int(6),
|
Int(6),
|
||||||
|
|
||||||
CollectionSep,
|
Sep,
|
||||||
StrBuf("b".to_strbuf()),
|
StrBuf("b".to_strbuf()),
|
||||||
CollectionEnd,
|
End,
|
||||||
CollectionEnd,
|
End,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut deserializer = TokenDeserializer::new(tokens);
|
let mut deserializer = TokenDeserializer::new(tokens);
|
||||||
@@ -750,16 +818,16 @@ mod tests {
|
|||||||
fn bench_dummy_deserializer(b: &mut Bencher) {
|
fn bench_dummy_deserializer(b: &mut Bencher) {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let tokens = vec!(
|
let tokens = vec!(
|
||||||
CollectionStart(3),
|
SeqStart(3),
|
||||||
CollectionSep,
|
Sep,
|
||||||
Int(5),
|
Int(5),
|
||||||
|
|
||||||
CollectionSep,
|
Sep,
|
||||||
Int(6),
|
Int(6),
|
||||||
|
|
||||||
CollectionSep,
|
Sep,
|
||||||
Int(7),
|
Int(7),
|
||||||
CollectionEnd,
|
End,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut d = TokenDeserializer::new(tokens);
|
let mut d = TokenDeserializer::new(tokens);
|
||||||
|
|||||||
Reference in New Issue
Block a user