2014-05-16 09:15:02 -05:00
|
|
|
extern crate collections;
|
|
|
|
|
|
|
|
use std::hash::Hash;
|
2014-05-19 11:48:58 -05:00
|
|
|
use std::num;
|
2014-05-18 00:42:48 -05:00
|
|
|
use std::result;
|
2014-05-16 09:15:02 -05:00
|
|
|
use collections::HashMap;
|
|
|
|
|
|
|
|
#[deriving(Clone, Eq)]
|
|
|
|
pub enum Token {
|
2014-05-16 23:21:05 -05:00
|
|
|
Null,
|
|
|
|
Bool(bool),
|
2014-05-16 09:15:02 -05:00
|
|
|
Int(int),
|
2014-05-19 09:18:35 -05:00
|
|
|
I8(i8),
|
|
|
|
I16(i16),
|
|
|
|
I32(i32),
|
|
|
|
I64(i64),
|
|
|
|
Uint(uint),
|
|
|
|
U8(u8),
|
|
|
|
U16(u16),
|
|
|
|
U32(u32),
|
|
|
|
U64(u64),
|
|
|
|
F32(f32),
|
2014-05-16 23:21:05 -05:00
|
|
|
F64(f64),
|
2014-05-19 09:18:35 -05:00
|
|
|
Char(char),
|
|
|
|
Str(&'static str),
|
2014-05-16 09:15:02 -05:00
|
|
|
StrBuf(StrBuf),
|
2014-05-19 21:41:38 -05:00
|
|
|
Option(bool),
|
2014-05-20 21:22:23 -05:00
|
|
|
|
|
|
|
TupleStart(uint),
|
2014-05-21 10:44:48 -05:00
|
|
|
|
2014-05-21 10:25:28 -05:00
|
|
|
StructStart(&'static str),
|
|
|
|
StructField(&'static str),
|
2014-05-21 10:44:48 -05:00
|
|
|
|
|
|
|
EnumStart(&'static str),
|
|
|
|
EnumVariant(&'static str),
|
|
|
|
|
2014-05-20 21:22:23 -05:00
|
|
|
SeqStart(uint),
|
|
|
|
MapStart(uint),
|
|
|
|
|
|
|
|
Sep,
|
|
|
|
End,
|
2014-05-16 09:15:02 -05:00
|
|
|
}
|
|
|
|
|
2014-05-19 21:41:38 -05:00
|
|
|
macro_rules! expect_token {
|
|
|
|
() => {
|
|
|
|
match self.next() {
|
|
|
|
Some(token) => token,
|
|
|
|
None => { return Err(self.end_of_stream_error()); }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! match_token {
|
2014-05-20 21:22:23 -05:00
|
|
|
($( $variant:pat => $expr:expr ),+) => {
|
2014-05-19 21:41:38 -05:00
|
|
|
match expect_token!() {
|
2014-05-20 21:22:23 -05:00
|
|
|
$( Ok($variant) => $expr ),+,
|
2014-05-19 21:41:38 -05:00
|
|
|
Ok(_) => { return Err(self.syntax_error()); }
|
|
|
|
Err(err) => { return Err(err); }
|
2014-05-19 09:18:35 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! to_result {
|
|
|
|
($expr:expr, $err:expr) => {
|
|
|
|
match $expr {
|
|
|
|
Some(value) => Ok(value),
|
|
|
|
None => Err($err),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-16 09:15:02 -05:00
|
|
|
pub trait Deserializer<E>: Iterator<Result<Token, E>> {
|
|
|
|
fn end_of_stream_error(&self) -> E;
|
|
|
|
|
|
|
|
fn syntax_error(&self) -> E;
|
|
|
|
|
2014-05-19 09:55:05 -05:00
|
|
|
#[inline]
|
2014-05-19 20:44:20 -05:00
|
|
|
fn expect_null(&mut self) -> Result<(), E> {
|
2014-05-19 21:41:38 -05:00
|
|
|
match_token! {
|
2014-05-19 09:18:35 -05:00
|
|
|
Null => Ok(()),
|
2014-05-20 21:22:23 -05:00
|
|
|
TupleStart(_) => {
|
|
|
|
match_token! {
|
|
|
|
End => Ok(())
|
|
|
|
}
|
|
|
|
}
|
2014-05-19 21:41:38 -05:00
|
|
|
}
|
2014-05-16 23:21:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2014-05-19 20:44:20 -05:00
|
|
|
fn expect_bool(&mut self) -> Result<bool, E> {
|
2014-05-19 21:41:38 -05:00
|
|
|
match_token! {
|
|
|
|
Bool(value) => Ok(value)
|
|
|
|
}
|
2014-05-16 23:21:05 -05:00
|
|
|
}
|
|
|
|
|
2014-05-16 09:15:02 -05:00
|
|
|
#[inline]
|
2014-05-19 20:44:20 -05:00
|
|
|
fn expect_num<T: NumCast>(&mut self) -> Result<T, E> {
|
2014-05-19 21:41:38 -05:00
|
|
|
match_token! {
|
2014-05-19 11:48:58 -05:00
|
|
|
Int(x) => to_result!(num::cast(x), self.syntax_error()),
|
|
|
|
I8(x) => to_result!(num::cast(x), self.syntax_error()),
|
|
|
|
I16(x) => to_result!(num::cast(x), self.syntax_error()),
|
|
|
|
I32(x) => to_result!(num::cast(x), self.syntax_error()),
|
|
|
|
I64(x) => to_result!(num::cast(x), self.syntax_error()),
|
|
|
|
Uint(x) => to_result!(num::cast(x), self.syntax_error()),
|
|
|
|
U8(x) => to_result!(num::cast(x), self.syntax_error()),
|
|
|
|
U16(x) => to_result!(num::cast(x), self.syntax_error()),
|
|
|
|
U32(x) => to_result!(num::cast(x), self.syntax_error()),
|
|
|
|
U64(x) => to_result!(num::cast(x), self.syntax_error()),
|
|
|
|
F32(x) => to_result!(num::cast(x), self.syntax_error()),
|
2014-05-19 21:41:38 -05:00
|
|
|
F64(x) => to_result!(num::cast(x), self.syntax_error())
|
2014-05-19 11:48:58 -05:00
|
|
|
}
|
2014-05-16 23:21:05 -05:00
|
|
|
}
|
|
|
|
|
2014-05-16 09:15:02 -05:00
|
|
|
#[inline]
|
2014-05-19 20:44:20 -05:00
|
|
|
fn expect_char(&mut self) -> Result<char, E> {
|
2014-05-19 21:41:38 -05:00
|
|
|
match_token! {
|
|
|
|
Char(value) => Ok(value)
|
|
|
|
}
|
2014-05-19 09:18:35 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2014-05-19 20:44:20 -05:00
|
|
|
fn expect_str(&mut self) -> Result<&'static str, E> {
|
2014-05-19 21:41:38 -05:00
|
|
|
match_token! {
|
|
|
|
Str(value) => Ok(value)
|
|
|
|
}
|
2014-05-19 09:18:35 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2014-05-19 20:44:20 -05:00
|
|
|
fn expect_strbuf(&mut self) -> Result<StrBuf, E> {
|
2014-05-19 21:41:38 -05:00
|
|
|
match_token! {
|
2014-05-19 09:18:35 -05:00
|
|
|
Str(value) => Ok(value.to_strbuf()),
|
|
|
|
StrBuf(value) => Ok(value)
|
2014-05-19 21:41:38 -05:00
|
|
|
}
|
2014-05-16 09:15:02 -05:00
|
|
|
}
|
|
|
|
|
2014-05-19 09:55:05 -05:00
|
|
|
#[inline]
|
|
|
|
fn expect_option<
|
|
|
|
T: Deserializable<E, Self>
|
2014-05-19 20:44:20 -05:00
|
|
|
>(&mut self) -> Result<Option<T>, E> {
|
2014-05-19 21:41:38 -05:00
|
|
|
match_token! {
|
|
|
|
Option(false) => Ok(None),
|
|
|
|
Option(true) => {
|
|
|
|
let value: T = try!(Deserializable::deserialize(self));
|
2014-05-19 11:47:16 -05:00
|
|
|
Ok(Some(value))
|
|
|
|
}
|
2014-05-19 09:55:05 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-16 09:15:02 -05:00
|
|
|
#[inline]
|
2014-05-20 21:22:23 -05:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-21 10:25:28 -05:00
|
|
|
#[inline]
|
|
|
|
fn expect_struct_start(&mut self, name: &str) -> Result<(), E> {
|
|
|
|
match_token! {
|
|
|
|
StructStart(n) => {
|
|
|
|
if name == n {
|
|
|
|
Ok(())
|
|
|
|
} else {
|
|
|
|
Err(self.syntax_error())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn expect_struct_field<
|
|
|
|
T: Deserializable<E, Self>
|
|
|
|
>(&mut self, name: &str) -> Result<T, E> {
|
|
|
|
match_token! {
|
|
|
|
StructField(n) => {
|
|
|
|
if name == n {
|
|
|
|
Deserializable::deserialize(self)
|
|
|
|
} else {
|
|
|
|
Err(self.syntax_error())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-21 10:44:48 -05:00
|
|
|
#[inline]
|
|
|
|
fn expect_enum_start<'a>(&mut self, name: &str, variants: &[&str]) -> Result<uint, E> {
|
|
|
|
match_token! {
|
|
|
|
EnumStart(n) => {
|
|
|
|
if name == n {
|
|
|
|
match_token! {
|
|
|
|
EnumVariant(n) => {
|
|
|
|
match variants.iter().position(|variant| *variant == n) {
|
|
|
|
Some(position) => Ok(position),
|
|
|
|
None => Err(self.syntax_error()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Err(self.syntax_error())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-20 21:22:23 -05:00
|
|
|
#[inline]
|
2014-05-21 08:47:58 -05:00
|
|
|
fn expect_collection<
|
2014-05-16 09:15:02 -05:00
|
|
|
T: Deserializable<E, Self>,
|
|
|
|
C: FromIterator<T>
|
2014-05-19 20:44:20 -05:00
|
|
|
>(&mut self) -> Result<C, E> {
|
2014-05-20 21:38:48 -05:00
|
|
|
// By default we don't care what our source input was. We can take
|
|
|
|
// anything that's a Collection<T>. We'll error out later if the types
|
|
|
|
// are wrong.
|
2014-05-20 21:22:23 -05:00
|
|
|
let len = match_token! {
|
2014-05-20 21:38:48 -05:00
|
|
|
TupleStart(len) => len,
|
|
|
|
SeqStart(len) => len,
|
|
|
|
MapStart(len) => len
|
2014-05-20 21:22:23 -05:00
|
|
|
};
|
2014-05-16 09:15:02 -05:00
|
|
|
|
2014-05-21 08:47:58 -05:00
|
|
|
expect_rest_of_collection(self, len)
|
|
|
|
}
|
2014-05-16 09:15:02 -05:00
|
|
|
|
2014-05-21 08:47:58 -05:00
|
|
|
#[inline]
|
|
|
|
fn expect_seq<
|
|
|
|
T: Deserializable<E, Self>,
|
|
|
|
C: FromIterator<T>
|
|
|
|
>(&mut self) -> Result<C, E> {
|
|
|
|
let len = match_token! {
|
|
|
|
SeqStart(len) => len
|
|
|
|
};
|
2014-05-18 00:42:48 -05:00
|
|
|
|
2014-05-21 08:47:58 -05:00
|
|
|
expect_rest_of_collection(self, len)
|
2014-05-16 09:15:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2014-05-20 21:22:23 -05:00
|
|
|
fn expect_map<
|
|
|
|
K: Deserializable<E, Self>,
|
|
|
|
V: Deserializable<E, Self>,
|
|
|
|
C: FromIterator<(K, V)>
|
|
|
|
>(&mut self) -> Result<C, E> {
|
|
|
|
let len = match_token! {
|
|
|
|
MapStart(len) => len
|
|
|
|
};
|
2014-05-19 20:44:20 -05:00
|
|
|
|
2014-05-21 08:47:58 -05:00
|
|
|
expect_rest_of_collection(self, len)
|
2014-05-16 09:15:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2014-05-20 21:22:23 -05:00
|
|
|
fn expect_end(&mut self) -> Result<(), E> {
|
2014-05-19 21:41:38 -05:00
|
|
|
match_token! {
|
2014-05-20 21:22:23 -05:00
|
|
|
End => Ok(())
|
2014-05-16 09:15:02 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-16 23:21:05 -05:00
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2014-05-21 08:47:58 -05:00
|
|
|
fn expect_rest_of_collection<
|
|
|
|
E,
|
|
|
|
D: Deserializer<E>,
|
|
|
|
T: Deserializable<E, D>,
|
|
|
|
C: FromIterator<T>
|
|
|
|
>(d: &mut D, len: uint) -> Result<C, E> {
|
2014-05-23 22:58:09 -05:00
|
|
|
let mut idx = 0;
|
|
|
|
|
2014-05-21 08:47:58 -05:00
|
|
|
let iter = d.by_ref().batch(|d| {
|
|
|
|
let d = d.iter();
|
|
|
|
|
2014-05-23 22:58:09 -05:00
|
|
|
if idx < len {
|
|
|
|
idx += 1;
|
|
|
|
let value: Result<T, E> = Deserializable::deserialize(d);
|
|
|
|
Some(value)
|
|
|
|
} else {
|
|
|
|
match d.next() {
|
|
|
|
Some(Ok(End)) => None,
|
|
|
|
Some(Ok(_)) => Some(Err(d.syntax_error())),
|
|
|
|
Some(Err(e)) => Some(Err(e)),
|
|
|
|
None => Some(Err(d.end_of_stream_error())),
|
|
|
|
}
|
|
|
|
}
|
2014-05-21 08:47:58 -05:00
|
|
|
|
2014-05-23 22:58:09 -05:00
|
|
|
/*
|
2014-05-21 08:47:58 -05:00
|
|
|
match token {
|
|
|
|
Ok(Sep) => {
|
|
|
|
let value: Result<T, E> = Deserializable::deserialize(d);
|
|
|
|
Some(value)
|
|
|
|
}
|
|
|
|
Ok(End) => None,
|
|
|
|
Ok(_) => Some(Err(d.syntax_error())),
|
|
|
|
Err(e) => Some(Err(e)),
|
|
|
|
}
|
2014-05-23 22:58:09 -05:00
|
|
|
*/
|
2014-05-21 08:47:58 -05:00
|
|
|
});
|
|
|
|
|
|
|
|
result::collect_with_capacity(iter, len)
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2014-05-19 09:18:35 -05:00
|
|
|
pub trait Deserializable<E, D: Deserializer<E>> {
|
2014-05-19 20:44:20 -05:00
|
|
|
fn deserialize(d: &mut D) -> Result<Self, E>;
|
2014-05-16 09:15:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2014-05-19 09:18:35 -05:00
|
|
|
macro_rules! impl_deserializable {
|
2014-05-19 21:41:38 -05:00
|
|
|
($ty:ty, $method:ident) => {
|
2014-05-19 09:18:35 -05:00
|
|
|
impl<
|
|
|
|
E,
|
|
|
|
D: Deserializer<E>
|
|
|
|
> Deserializable<E, D> for $ty {
|
2014-05-19 20:44:20 -05:00
|
|
|
#[inline]
|
|
|
|
fn deserialize(d: &mut D) -> Result<$ty, E> {
|
|
|
|
d.$method()
|
|
|
|
}
|
2014-05-19 09:18:35 -05:00
|
|
|
}
|
2014-05-16 23:21:05 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-19 21:41:38 -05:00
|
|
|
impl_deserializable!(bool, expect_bool)
|
|
|
|
impl_deserializable!(int, expect_num)
|
|
|
|
impl_deserializable!(i8, expect_num)
|
|
|
|
impl_deserializable!(i16, expect_num)
|
|
|
|
impl_deserializable!(i32, expect_num)
|
|
|
|
impl_deserializable!(i64, expect_num)
|
|
|
|
impl_deserializable!(uint, expect_num)
|
|
|
|
impl_deserializable!(u8, expect_num)
|
|
|
|
impl_deserializable!(u16, expect_num)
|
|
|
|
impl_deserializable!(u32, expect_num)
|
|
|
|
impl_deserializable!(u64, expect_num)
|
|
|
|
impl_deserializable!(f32, expect_num)
|
|
|
|
impl_deserializable!(f64, expect_num)
|
|
|
|
impl_deserializable!(char, expect_char)
|
|
|
|
impl_deserializable!(&'static str, expect_str)
|
|
|
|
impl_deserializable!(StrBuf, expect_strbuf)
|
2014-05-16 09:15:02 -05:00
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
impl<
|
|
|
|
E,
|
|
|
|
D: Deserializer<E>,
|
|
|
|
T: Deserializable<E, D>
|
|
|
|
> Deserializable<E, D> for Option<T> {
|
2014-05-19 20:44:20 -05:00
|
|
|
#[inline]
|
|
|
|
fn deserialize(d: &mut D) -> Result<Option<T>, E> {
|
|
|
|
d.expect_option()
|
|
|
|
}
|
2014-05-16 09:15:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
impl<
|
|
|
|
E,
|
|
|
|
D: Deserializer<E>,
|
|
|
|
T: Deserializable<E, D>
|
|
|
|
> Deserializable<E, D> for Vec<T> {
|
2014-05-19 20:44:20 -05:00
|
|
|
#[inline]
|
|
|
|
fn deserialize(d: &mut D) -> Result<Vec<T>, E> {
|
2014-05-20 21:22:23 -05:00
|
|
|
d.expect_seq()
|
2014-05-19 20:44:20 -05:00
|
|
|
}
|
2014-05-16 09:15:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<
|
|
|
|
E,
|
|
|
|
D: Deserializer<E>,
|
|
|
|
K: Deserializable<E, D> + TotalEq + Hash,
|
|
|
|
V: Deserializable<E, D>
|
|
|
|
> Deserializable<E, D> for HashMap<K, V> {
|
2014-05-19 20:44:20 -05:00
|
|
|
#[inline]
|
|
|
|
fn deserialize(d: &mut D) -> Result<HashMap<K, V>, E> {
|
2014-05-20 21:22:23 -05:00
|
|
|
d.expect_map()
|
2014-05-19 20:44:20 -05:00
|
|
|
}
|
2014-05-16 09:15:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
impl<
|
|
|
|
E,
|
|
|
|
D: Deserializer<E>
|
|
|
|
> Deserializable<E, D> for () {
|
2014-05-19 20:44:20 -05:00
|
|
|
#[inline]
|
|
|
|
fn deserialize(d: &mut D) -> Result<(), E> {
|
|
|
|
d.expect_null()
|
|
|
|
}
|
2014-05-16 09:15:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2014-05-19 19:53:24 -05:00
|
|
|
macro_rules! peel(($name:ident, $($other:ident,)*) => (deserialize_tuple!($($other,)*)))
|
2014-05-16 09:15:02 -05:00
|
|
|
|
2014-05-19 19:53:24 -05:00
|
|
|
macro_rules! deserialize_tuple (
|
|
|
|
() => ();
|
|
|
|
( $($name:ident,)+ ) => (
|
|
|
|
impl<
|
|
|
|
E,
|
|
|
|
D: Deserializer<E>,
|
2014-05-19 20:44:20 -05:00
|
|
|
$($name:Deserializable<E, D>),*
|
|
|
|
> Deserializable<E, D> for ($($name,)*) {
|
|
|
|
#[inline]
|
|
|
|
#[allow(uppercase_variables)]
|
|
|
|
fn deserialize(d: &mut D) -> Result<($($name,)*), E> {
|
2014-05-20 21:22:23 -05:00
|
|
|
// FIXME: how can we count macro args?
|
|
|
|
let mut len = 0;
|
|
|
|
$({ let $name = 1; len += $name; })*;
|
|
|
|
|
|
|
|
try!(d.expect_tuple_start(len));
|
2014-05-19 20:44:20 -05:00
|
|
|
|
2014-05-21 08:47:58 -05:00
|
|
|
let result = ($({
|
|
|
|
let $name = try!(d.expect_tuple_elt());
|
|
|
|
$name
|
|
|
|
},)*);
|
2014-05-16 09:15:02 -05:00
|
|
|
|
2014-05-20 21:22:23 -05:00
|
|
|
try!(d.expect_end());
|
2014-05-16 09:15:02 -05:00
|
|
|
|
2014-05-19 19:53:24 -05:00
|
|
|
Ok(result)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
peel!($($name,)*)
|
|
|
|
)
|
|
|
|
)
|
2014-05-16 09:15:02 -05:00
|
|
|
|
2014-05-19 19:53:24 -05:00
|
|
|
deserialize_tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }
|
2014-05-16 09:15:02 -05:00
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2014-05-23 22:58:09 -05:00
|
|
|
/*
|
2014-05-16 09:15:02 -05:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2014-05-16 23:21:05 -05:00
|
|
|
use collections::HashMap;
|
|
|
|
use test::Bencher;
|
|
|
|
|
2014-05-23 22:41:29 -05:00
|
|
|
use serialize::Decoder;
|
2014-05-16 09:15:02 -05:00
|
|
|
|
2014-05-21 10:25:28 -05:00
|
|
|
use super::{Token, Null, Int, Uint, Str, StrBuf, Char, Option};
|
2014-05-21 10:44:48 -05:00
|
|
|
use super::{TupleStart, StructStart, StructField, EnumStart, EnumVariant};
|
|
|
|
use super::{SeqStart, MapStart, Sep, End};
|
2014-05-16 09:15:02 -05:00
|
|
|
use super::{Deserializer, Deserializable};
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2014-05-21 23:48:49 -05:00
|
|
|
#[deriving(Clone, Eq, Show, Decodable)]
|
2014-05-21 10:25:28 -05:00
|
|
|
struct Inner {
|
|
|
|
a: (),
|
|
|
|
b: uint,
|
|
|
|
c: HashMap<StrBuf, Option<char>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<E, D: Deserializer<E>> Deserializable<E, D> for Inner {
|
|
|
|
#[inline]
|
|
|
|
fn deserialize(d: &mut D) -> Result<Inner, E> {
|
|
|
|
try!(d.expect_struct_start("Inner"));
|
|
|
|
let a = try!(d.expect_struct_field("a"));
|
|
|
|
let b = try!(d.expect_struct_field("b"));
|
|
|
|
let c = try!(d.expect_struct_field("c"));
|
|
|
|
try!(d.expect_end());
|
|
|
|
Ok(Inner { a: a, b: b, c: c })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2014-05-21 23:48:49 -05:00
|
|
|
#[deriving(Clone, Eq, Show, Decodable)]
|
2014-05-21 10:25:28 -05:00
|
|
|
struct Outer {
|
|
|
|
inner: Vec<Inner>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<E, D: Deserializer<E>> Deserializable<E, D> for Outer {
|
|
|
|
#[inline]
|
|
|
|
fn deserialize(d: &mut D) -> Result<Outer, E> {
|
|
|
|
try!(d.expect_struct_start("Outer"));
|
|
|
|
let inner = try!(d.expect_struct_field("inner"));
|
|
|
|
try!(d.expect_end());
|
|
|
|
Ok(Outer { inner: inner })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2014-05-21 22:54:10 -05:00
|
|
|
#[deriving(Clone, Eq, Show, Decodable)]
|
2014-05-21 10:44:48 -05:00
|
|
|
enum Animal {
|
|
|
|
Dog,
|
|
|
|
Frog(StrBuf, int)
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<E, D: Deserializer<E>> Deserializable<E, D> for Animal {
|
|
|
|
#[inline]
|
|
|
|
fn deserialize(d: &mut D) -> Result<Animal, E> {
|
|
|
|
match try!(d.expect_enum_start("Animal", ["Dog", "Frog"])) {
|
|
|
|
0 => {
|
|
|
|
try!(d.expect_end());
|
|
|
|
Ok(Dog)
|
|
|
|
}
|
|
|
|
1 => {
|
|
|
|
let x0 = try!(Deserializable::deserialize(d));
|
|
|
|
let x1 = try!(Deserializable::deserialize(d));
|
|
|
|
try!(d.expect_end());
|
|
|
|
Ok(Frog(x0, x1))
|
|
|
|
}
|
|
|
|
_ => unreachable!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2014-05-16 09:15:02 -05:00
|
|
|
#[deriving(Show)]
|
|
|
|
enum Error {
|
|
|
|
EndOfStream,
|
|
|
|
SyntaxError,
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
struct TokenDeserializer {
|
|
|
|
tokens: Vec<Token>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TokenDeserializer {
|
|
|
|
#[inline]
|
|
|
|
fn new(tokens: Vec<Token>) -> TokenDeserializer {
|
|
|
|
TokenDeserializer {
|
|
|
|
tokens: tokens,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Iterator<Result<Token, Error>> for TokenDeserializer {
|
|
|
|
#[inline]
|
|
|
|
fn next(&mut self) -> Option<Result<Token, Error>> {
|
|
|
|
match self.tokens.shift() {
|
|
|
|
None => None,
|
|
|
|
Some(token) => Some(Ok(token)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Deserializer<Error> for TokenDeserializer {
|
|
|
|
#[inline]
|
|
|
|
fn end_of_stream_error(&self) -> Error {
|
|
|
|
EndOfStream
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn syntax_error(&self) -> Error {
|
|
|
|
SyntaxError
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_tokens_int() {
|
|
|
|
let tokens = vec!(
|
|
|
|
Int(5),
|
|
|
|
);
|
|
|
|
|
|
|
|
let mut deserializer = TokenDeserializer::new(tokens);
|
2014-05-21 10:25:28 -05:00
|
|
|
let value: int = Deserializable::deserialize(&mut deserializer).unwrap();
|
2014-05-16 09:15:02 -05:00
|
|
|
|
2014-05-21 10:25:28 -05:00
|
|
|
assert_eq!(value, 5);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_tokens_str() {
|
|
|
|
let tokens = vec!(
|
|
|
|
Str("a"),
|
|
|
|
);
|
|
|
|
|
|
|
|
let mut deserializer = TokenDeserializer::new(tokens);
|
|
|
|
let value: &'static str = Deserializable::deserialize(&mut deserializer).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(value, "a");
|
2014-05-16 09:15:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_tokens_strbuf() {
|
|
|
|
let tokens = vec!(
|
|
|
|
StrBuf("a".to_strbuf()),
|
|
|
|
);
|
|
|
|
|
|
|
|
let mut deserializer = TokenDeserializer::new(tokens);
|
2014-05-21 10:25:28 -05:00
|
|
|
let value: StrBuf = Deserializable::deserialize(&mut deserializer).unwrap();
|
2014-05-16 09:15:02 -05:00
|
|
|
|
2014-05-21 10:25:28 -05:00
|
|
|
assert_eq!(value, "a".to_strbuf());
|
2014-05-16 09:15:02 -05:00
|
|
|
}
|
|
|
|
|
2014-05-20 21:22:23 -05:00
|
|
|
#[test]
|
|
|
|
fn test_tokens_null() {
|
|
|
|
let tokens = vec!(
|
|
|
|
Null,
|
|
|
|
);
|
|
|
|
|
|
|
|
let mut deserializer = TokenDeserializer::new(tokens);
|
2014-05-21 10:25:28 -05:00
|
|
|
let value: () = Deserializable::deserialize(&mut deserializer).unwrap();
|
2014-05-20 21:22:23 -05:00
|
|
|
|
2014-05-21 10:25:28 -05:00
|
|
|
assert_eq!(value, ());
|
2014-05-20 21:22:23 -05:00
|
|
|
}
|
|
|
|
|
2014-05-16 09:15:02 -05:00
|
|
|
#[test]
|
|
|
|
fn test_tokens_tuple_empty() {
|
|
|
|
let tokens = vec!(
|
2014-05-20 21:22:23 -05:00
|
|
|
TupleStart(0),
|
|
|
|
End,
|
2014-05-16 09:15:02 -05:00
|
|
|
);
|
|
|
|
|
|
|
|
let mut deserializer = TokenDeserializer::new(tokens);
|
2014-05-21 10:25:28 -05:00
|
|
|
let value: () = Deserializable::deserialize(&mut deserializer).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(value, ());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_tokens_option_none() {
|
|
|
|
let tokens = vec!(
|
|
|
|
Option(false),
|
|
|
|
);
|
|
|
|
|
|
|
|
let mut deserializer = TokenDeserializer::new(tokens);
|
|
|
|
let value: Option<int> = Deserializable::deserialize(&mut deserializer).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(value, None);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_tokens_option_some() {
|
|
|
|
let tokens = vec!(
|
|
|
|
Option(true),
|
|
|
|
Int(5),
|
|
|
|
);
|
|
|
|
|
|
|
|
let mut deserializer = TokenDeserializer::new(tokens);
|
|
|
|
let value: Option<int> = Deserializable::deserialize(&mut deserializer).unwrap();
|
2014-05-16 09:15:02 -05:00
|
|
|
|
2014-05-21 10:25:28 -05:00
|
|
|
assert_eq!(value, Some(5));
|
2014-05-16 09:15:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_tokens_tuple() {
|
|
|
|
let tokens = vec!(
|
2014-05-20 21:22:23 -05:00
|
|
|
TupleStart(2),
|
|
|
|
Sep,
|
2014-05-16 09:15:02 -05:00
|
|
|
Int(5),
|
|
|
|
|
2014-05-20 21:22:23 -05:00
|
|
|
Sep,
|
2014-05-16 09:15:02 -05:00
|
|
|
StrBuf("a".to_strbuf()),
|
2014-05-20 21:22:23 -05:00
|
|
|
End,
|
2014-05-16 09:15:02 -05:00
|
|
|
);
|
|
|
|
|
|
|
|
let mut deserializer = TokenDeserializer::new(tokens);
|
2014-05-21 10:25:28 -05:00
|
|
|
let value: (int, StrBuf) = Deserializable::deserialize(&mut deserializer).unwrap();
|
2014-05-16 09:15:02 -05:00
|
|
|
|
2014-05-21 10:25:28 -05:00
|
|
|
assert_eq!(value, (5, "a".to_strbuf()));
|
2014-05-16 09:15:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_tokens_tuple_compound() {
|
|
|
|
let tokens = vec!(
|
2014-05-20 21:22:23 -05:00
|
|
|
TupleStart(3),
|
|
|
|
Sep,
|
|
|
|
Null,
|
2014-05-20 21:38:48 -05:00
|
|
|
|
2014-05-20 21:22:23 -05:00
|
|
|
Sep,
|
|
|
|
TupleStart(0),
|
|
|
|
End,
|
|
|
|
|
|
|
|
Sep,
|
|
|
|
TupleStart(2),
|
|
|
|
Sep,
|
2014-05-16 09:15:02 -05:00
|
|
|
Int(5),
|
2014-05-19 21:41:38 -05:00
|
|
|
|
2014-05-20 21:22:23 -05:00
|
|
|
Sep,
|
2014-05-16 09:15:02 -05:00
|
|
|
StrBuf("a".to_strbuf()),
|
2014-05-20 21:22:23 -05:00
|
|
|
End,
|
|
|
|
End,
|
2014-05-16 09:15:02 -05:00
|
|
|
);
|
|
|
|
|
|
|
|
let mut deserializer = TokenDeserializer::new(tokens);
|
2014-05-21 10:25:28 -05:00
|
|
|
let value: ((), (), (int, StrBuf)) = Deserializable::deserialize(&mut deserializer).unwrap();
|
2014-05-16 09:15:02 -05:00
|
|
|
|
2014-05-21 10:25:28 -05:00
|
|
|
assert_eq!(value, ((), (), (5, "a".to_strbuf())));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_tokens_struct_empty() {
|
|
|
|
let tokens = vec!(
|
|
|
|
StructStart("Outer"),
|
|
|
|
StructField("inner"),
|
|
|
|
SeqStart(0),
|
|
|
|
End,
|
|
|
|
End,
|
|
|
|
);
|
2014-05-21 22:54:10 -05:00
|
|
|
|
2014-05-21 10:25:28 -05:00
|
|
|
let mut deserializer = TokenDeserializer::new(tokens);
|
|
|
|
let value: Outer = Deserializable::deserialize(&mut deserializer).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(value, Outer { inner: vec!() });
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_tokens_struct() {
|
|
|
|
let tokens = vec!(
|
|
|
|
StructStart("Outer"),
|
|
|
|
StructField("inner"),
|
|
|
|
SeqStart(1),
|
|
|
|
Sep,
|
|
|
|
StructStart("Inner"),
|
|
|
|
StructField("a"),
|
|
|
|
Null,
|
|
|
|
|
|
|
|
StructField("b"),
|
|
|
|
Uint(5),
|
|
|
|
|
|
|
|
StructField("c"),
|
|
|
|
MapStart(1),
|
|
|
|
Sep,
|
|
|
|
TupleStart(2),
|
|
|
|
Sep,
|
|
|
|
StrBuf("abc".to_strbuf()),
|
|
|
|
|
|
|
|
Sep,
|
|
|
|
Option(true),
|
|
|
|
Char('c'),
|
|
|
|
End,
|
|
|
|
End,
|
|
|
|
End,
|
|
|
|
End,
|
|
|
|
End,
|
|
|
|
);
|
2014-05-21 22:54:10 -05:00
|
|
|
|
2014-05-21 10:25:28 -05:00
|
|
|
let mut deserializer = TokenDeserializer::new(tokens);
|
|
|
|
let value: Outer = Deserializable::deserialize(&mut deserializer).unwrap();
|
|
|
|
|
|
|
|
let mut map = HashMap::new();
|
|
|
|
map.insert("abc".to_strbuf(), Some('c'));
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
value,
|
|
|
|
Outer {
|
|
|
|
inner: vec!(
|
|
|
|
Inner {
|
|
|
|
a: (),
|
|
|
|
b: 5,
|
|
|
|
c: map,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
});
|
2014-05-16 09:15:02 -05:00
|
|
|
}
|
|
|
|
|
2014-05-21 10:44:48 -05:00
|
|
|
#[test]
|
|
|
|
fn test_tokens_enum() {
|
|
|
|
let tokens = vec!(
|
|
|
|
EnumStart("Animal"),
|
|
|
|
EnumVariant("Dog"),
|
|
|
|
End,
|
|
|
|
);
|
2014-05-21 22:54:10 -05:00
|
|
|
|
2014-05-21 10:44:48 -05:00
|
|
|
let mut deserializer = TokenDeserializer::new(tokens);
|
|
|
|
let value: Animal = Deserializable::deserialize(&mut deserializer).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(value, Dog);
|
|
|
|
|
|
|
|
let tokens = vec!(
|
|
|
|
EnumStart("Animal"),
|
|
|
|
EnumVariant("Frog"),
|
|
|
|
StrBuf("Henry".to_strbuf()),
|
|
|
|
Int(349),
|
|
|
|
End,
|
|
|
|
);
|
2014-05-21 22:54:10 -05:00
|
|
|
|
2014-05-21 10:44:48 -05:00
|
|
|
let mut deserializer = TokenDeserializer::new(tokens);
|
|
|
|
let value: Animal = Deserializable::deserialize(&mut deserializer).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(value, Frog("Henry".to_strbuf(), 349));
|
|
|
|
}
|
|
|
|
|
2014-05-16 09:15:02 -05:00
|
|
|
#[test]
|
|
|
|
fn test_tokens_vec_empty() {
|
|
|
|
let tokens = vec!(
|
2014-05-20 21:22:23 -05:00
|
|
|
SeqStart(0),
|
|
|
|
End,
|
2014-05-16 09:15:02 -05:00
|
|
|
);
|
|
|
|
|
|
|
|
let mut deserializer = TokenDeserializer::new(tokens);
|
2014-05-21 10:25:28 -05:00
|
|
|
let value: Vec<int> = Deserializable::deserialize(&mut deserializer).unwrap();
|
2014-05-16 09:15:02 -05:00
|
|
|
|
2014-05-21 10:25:28 -05:00
|
|
|
assert_eq!(value, vec!());
|
2014-05-16 09:15:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_tokens_vec() {
|
|
|
|
let tokens = vec!(
|
2014-05-20 21:22:23 -05:00
|
|
|
SeqStart(3),
|
|
|
|
Sep,
|
2014-05-16 09:15:02 -05:00
|
|
|
Int(5),
|
|
|
|
|
2014-05-20 21:22:23 -05:00
|
|
|
Sep,
|
2014-05-16 09:15:02 -05:00
|
|
|
Int(6),
|
|
|
|
|
2014-05-20 21:22:23 -05:00
|
|
|
Sep,
|
2014-05-16 09:15:02 -05:00
|
|
|
Int(7),
|
2014-05-20 21:22:23 -05:00
|
|
|
End,
|
2014-05-16 09:15:02 -05:00
|
|
|
);
|
|
|
|
|
|
|
|
let mut deserializer = TokenDeserializer::new(tokens);
|
2014-05-21 10:25:28 -05:00
|
|
|
let value: Vec<int> = Deserializable::deserialize(&mut deserializer).unwrap();
|
2014-05-16 09:15:02 -05:00
|
|
|
|
2014-05-21 10:25:28 -05:00
|
|
|
assert_eq!(value, vec!(5, 6, 7));
|
2014-05-16 09:15:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_tokens_vec_compound() {
|
|
|
|
let tokens = vec!(
|
2014-05-20 21:22:23 -05:00
|
|
|
SeqStart(0),
|
|
|
|
Sep,
|
|
|
|
SeqStart(1),
|
|
|
|
Sep,
|
2014-05-16 09:15:02 -05:00
|
|
|
Int(1),
|
2014-05-20 21:22:23 -05:00
|
|
|
End,
|
2014-05-16 09:15:02 -05:00
|
|
|
|
2014-05-20 21:22:23 -05:00
|
|
|
Sep,
|
|
|
|
SeqStart(2),
|
|
|
|
Sep,
|
2014-05-16 09:15:02 -05:00
|
|
|
Int(2),
|
|
|
|
|
2014-05-20 21:22:23 -05:00
|
|
|
Sep,
|
2014-05-16 09:15:02 -05:00
|
|
|
Int(3),
|
2014-05-20 21:22:23 -05:00
|
|
|
End,
|
2014-05-16 09:15:02 -05:00
|
|
|
|
2014-05-20 21:22:23 -05:00
|
|
|
Sep,
|
|
|
|
SeqStart(3),
|
|
|
|
Sep,
|
2014-05-16 09:15:02 -05:00
|
|
|
Int(4),
|
|
|
|
|
2014-05-20 21:22:23 -05:00
|
|
|
Sep,
|
2014-05-16 09:15:02 -05:00
|
|
|
Int(5),
|
|
|
|
|
2014-05-20 21:22:23 -05:00
|
|
|
Sep,
|
2014-05-16 09:15:02 -05:00
|
|
|
Int(6),
|
2014-05-20 21:22:23 -05:00
|
|
|
End,
|
|
|
|
End,
|
2014-05-16 09:15:02 -05:00
|
|
|
);
|
|
|
|
|
|
|
|
let mut deserializer = TokenDeserializer::new(tokens);
|
2014-05-21 10:25:28 -05:00
|
|
|
let value: Vec<Vec<int>> = Deserializable::deserialize(&mut deserializer).unwrap();
|
2014-05-16 09:15:02 -05:00
|
|
|
|
2014-05-21 10:25:28 -05:00
|
|
|
assert_eq!(value, vec!(vec!(1), vec!(2, 3), vec!(4, 5, 6)));
|
2014-05-16 09:15:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_tokens_hashmap() {
|
|
|
|
let tokens = vec!(
|
2014-05-20 21:22:23 -05:00
|
|
|
MapStart(2),
|
|
|
|
Sep,
|
|
|
|
TupleStart(2),
|
|
|
|
Sep,
|
2014-05-16 09:15:02 -05:00
|
|
|
Int(5),
|
|
|
|
|
2014-05-20 21:22:23 -05:00
|
|
|
Sep,
|
2014-05-16 09:15:02 -05:00
|
|
|
StrBuf("a".to_strbuf()),
|
2014-05-20 21:22:23 -05:00
|
|
|
End,
|
2014-05-16 09:15:02 -05:00
|
|
|
|
2014-05-20 21:22:23 -05:00
|
|
|
Sep,
|
|
|
|
TupleStart(2),
|
|
|
|
Sep,
|
2014-05-16 09:15:02 -05:00
|
|
|
Int(6),
|
|
|
|
|
2014-05-20 21:22:23 -05:00
|
|
|
Sep,
|
2014-05-16 09:15:02 -05:00
|
|
|
StrBuf("b".to_strbuf()),
|
2014-05-20 21:22:23 -05:00
|
|
|
End,
|
|
|
|
End,
|
2014-05-16 09:15:02 -05:00
|
|
|
);
|
|
|
|
|
|
|
|
let mut deserializer = TokenDeserializer::new(tokens);
|
2014-05-21 10:25:28 -05:00
|
|
|
let value: HashMap<int, StrBuf> = Deserializable::deserialize(&mut deserializer).unwrap();
|
2014-05-16 09:15:02 -05:00
|
|
|
|
|
|
|
let mut map = HashMap::new();
|
|
|
|
map.insert(5, "a".to_strbuf());
|
|
|
|
map.insert(6, "b".to_strbuf());
|
|
|
|
|
2014-05-21 10:25:28 -05:00
|
|
|
assert_eq!(value, map);
|
2014-05-16 09:15:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
2014-05-22 00:08:59 -05:00
|
|
|
fn bench_token_deserializer(b: &mut Bencher) {
|
2014-05-16 09:15:02 -05:00
|
|
|
b.iter(|| {
|
|
|
|
let tokens = vec!(
|
2014-05-20 21:22:23 -05:00
|
|
|
SeqStart(3),
|
|
|
|
Sep,
|
2014-05-16 09:15:02 -05:00
|
|
|
Int(5),
|
|
|
|
|
2014-05-20 21:22:23 -05:00
|
|
|
Sep,
|
2014-05-16 09:15:02 -05:00
|
|
|
Int(6),
|
|
|
|
|
2014-05-20 21:22:23 -05:00
|
|
|
Sep,
|
2014-05-16 09:15:02 -05:00
|
|
|
Int(7),
|
2014-05-20 21:22:23 -05:00
|
|
|
End,
|
2014-05-16 09:15:02 -05:00
|
|
|
);
|
|
|
|
|
|
|
|
let mut d = TokenDeserializer::new(tokens);
|
2014-05-21 10:25:28 -05:00
|
|
|
let value: Vec<int> = Deserializable::deserialize(&mut d).unwrap();
|
2014-05-16 09:15:02 -05:00
|
|
|
|
2014-05-21 10:25:28 -05:00
|
|
|
assert_eq!(value, vec!(5, 6, 7));
|
2014-05-16 09:15:02 -05:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2014-05-23 22:58:09 -05:00
|
|
|
*/
|