mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-04-30 20:08:02 +00:00
-368
@@ -1,368 +0,0 @@
|
||||
#![feature(plugin)]
|
||||
#![plugin(serde_macros)]
|
||||
|
||||
extern crate serde;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::{option, string};
|
||||
|
||||
use serde::de::{Deserializer, Deserialize, Token, TokenKind, IgnoreTokens};
|
||||
|
||||
macro_rules! treemap {
|
||||
($($k:expr => $v:expr),*) => ({
|
||||
let mut _m = ::std::collections::BTreeMap::new();
|
||||
$(_m.insert($k, $v);)*
|
||||
_m
|
||||
})
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
struct Inner {
|
||||
a: (),
|
||||
b: usize,
|
||||
c: BTreeMap<string::String, option::Option<char>>,
|
||||
}
|
||||
|
||||
impl<
|
||||
D: Deserializer<E>,
|
||||
E
|
||||
> Deserialize<D, E> for Inner {
|
||||
#[inline]
|
||||
fn deserialize_token(d: &mut D, token: Token) -> Result<Inner, E> {
|
||||
try!(d.expect_struct_start(token, "Inner"));
|
||||
|
||||
let mut a = None;
|
||||
let mut b = None;
|
||||
let mut c = None;
|
||||
|
||||
static FIELDS: &'static [&'static str] = &["a", "b", "c"];
|
||||
|
||||
loop {
|
||||
let idx = match try!(d.expect_struct_field_or_end(FIELDS)) {
|
||||
Some(idx) => idx,
|
||||
None => { break; }
|
||||
};
|
||||
|
||||
match idx {
|
||||
Some(0) => { a = Some(try!(d.expect_struct_value())); }
|
||||
Some(1) => { b = Some(try!(d.expect_struct_value())); }
|
||||
Some(2) => { c = Some(try!(d.expect_struct_value())); }
|
||||
Some(_) => unreachable!(),
|
||||
None => { let _: IgnoreTokens = try!(Deserialize::deserialize(d)); }
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Inner { a: a.unwrap(), b: b.unwrap(), c: c.unwrap() })
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
struct Outer {
|
||||
inner: Vec<Inner>,
|
||||
}
|
||||
|
||||
impl<D: Deserializer<E>, E> Deserialize<D, E> for Outer {
|
||||
#[inline]
|
||||
fn deserialize_token(d: &mut D, token: Token) -> Result<Outer, E> {
|
||||
try!(d.expect_struct_start(token, "Outer"));
|
||||
|
||||
static FIELDS: &'static [&'static str] = &["inner"];
|
||||
|
||||
let mut inner = None;
|
||||
|
||||
loop {
|
||||
let idx = match try!(d.expect_struct_field_or_end(FIELDS)) {
|
||||
Some(idx) => idx,
|
||||
None => { break; }
|
||||
};
|
||||
|
||||
match idx {
|
||||
Some(0) => { inner = Some(try!(d.expect_struct_value())); }
|
||||
Some(_) => unreachable!(),
|
||||
None => { let _: IgnoreTokens = try!(Deserialize::deserialize(d)); }
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Outer { inner: inner.unwrap() })
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
enum Animal {
|
||||
Dog,
|
||||
Frog(string::String, isize)
|
||||
}
|
||||
|
||||
impl<D: Deserializer<E>, E> Deserialize<D, E> for Animal {
|
||||
#[inline]
|
||||
fn deserialize_token(d: &mut D, token: Token) -> Result<Animal, E> {
|
||||
match try!(d.expect_enum_start(token, "Animal", &["Dog", "Frog"])) {
|
||||
0 => {
|
||||
try!(d.expect_enum_end());
|
||||
Ok(Animal::Dog)
|
||||
}
|
||||
1 => {
|
||||
let x0 = try!(Deserialize::deserialize(d));
|
||||
let x1 = try!(Deserialize::deserialize(d));
|
||||
try!(d.expect_enum_end());
|
||||
Ok(Animal::Frog(x0, x1))
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Error {
|
||||
EndOfStream,
|
||||
SyntaxError(Vec<TokenKind>),
|
||||
UnexpectedName,
|
||||
ConversionError,
|
||||
MissingField(&'static str),
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct TokenDeserializer<Iter> {
|
||||
tokens: Iter,
|
||||
}
|
||||
|
||||
impl<Iter: Iterator<Item=Token>> TokenDeserializer<Iter> {
|
||||
#[inline]
|
||||
fn new(tokens: Iter) -> TokenDeserializer<Iter> {
|
||||
TokenDeserializer {
|
||||
tokens: tokens,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Iter: Iterator<Item=Token>> Iterator for TokenDeserializer<Iter> {
|
||||
type Item = Result<Token, Error>;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> option::Option<Result<Token, Error>> {
|
||||
self.tokens.next().map(|token| Ok(token))
|
||||
}
|
||||
}
|
||||
|
||||
impl<Iter: Iterator<Item=Token>> Deserializer<Error> for TokenDeserializer<Iter> {
|
||||
fn end_of_stream_error(&mut self) -> Error {
|
||||
Error::EndOfStream
|
||||
}
|
||||
|
||||
fn syntax_error(&mut self, _token: Token, expected: &[TokenKind]) -> Error {
|
||||
Error::SyntaxError(expected.to_vec())
|
||||
}
|
||||
|
||||
fn unexpected_name_error(&mut self, _token: Token) -> Error {
|
||||
Error::UnexpectedName
|
||||
}
|
||||
|
||||
fn conversion_error(&mut self, _token: Token) -> Error {
|
||||
Error::ConversionError
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn missing_field<
|
||||
T: Deserialize<TokenDeserializer<Iter>, Error>
|
||||
>(&mut self, field: &'static str) -> Result<T, Error> {
|
||||
Err(Error::MissingField(field))
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
macro_rules! test_value {
|
||||
($name:ident, [$($tokens:expr => $value:expr, $ty:ty),*]) => {
|
||||
#[test]
|
||||
fn $name() {
|
||||
$(
|
||||
let mut deserializer = TokenDeserializer::new($tokens.into_iter());
|
||||
let value: $ty = Deserialize::deserialize(&mut deserializer).unwrap();
|
||||
|
||||
assert_eq!(value, $value);
|
||||
)+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test_value!(test_primitives, [
|
||||
vec!(Token::Null) => (), (),
|
||||
vec!(Token::Bool(true)) => true, bool,
|
||||
vec!(Token::Bool(false)) => false, bool,
|
||||
vec!(Token::Isize(5)) => 5, isize,
|
||||
vec!(Token::I8(5)) => 5, i8,
|
||||
vec!(Token::I16(5)) => 5, i16,
|
||||
vec!(Token::I32(5)) => 5, i32,
|
||||
vec!(Token::I64(5)) => 5, i64,
|
||||
vec!(Token::Usize(5)) => 5, usize,
|
||||
vec!(Token::U8(5)) => 5, u8,
|
||||
vec!(Token::U16(5)) => 5, u16,
|
||||
vec!(Token::U32(5)) => 5, u32,
|
||||
vec!(Token::U64(5)) => 5, u64,
|
||||
vec!(Token::F32(5.0)) => 5.0, f32,
|
||||
vec!(Token::F64(5.0)) => 5.0, f64,
|
||||
vec!(Token::Char('c')) => 'c', char,
|
||||
vec!(Token::Str("abc")) => "abc", &str,
|
||||
vec!(Token::String("abc".to_string())) => "abc".to_string(), string::String
|
||||
]);
|
||||
|
||||
test_value!(test_tuples, [
|
||||
vec!(
|
||||
Token::TupleStart(0),
|
||||
Token::End,
|
||||
) => (), (),
|
||||
|
||||
vec!(
|
||||
Token::TupleStart(2),
|
||||
Token::Isize(5),
|
||||
|
||||
Token::Str("a"),
|
||||
Token::End,
|
||||
) => (5, "a"), (isize, &'static str),
|
||||
|
||||
vec!(
|
||||
Token::TupleStart(3),
|
||||
Token::Null,
|
||||
|
||||
Token::TupleStart(0),
|
||||
Token::End,
|
||||
|
||||
Token::TupleStart(2),
|
||||
Token::Isize(5),
|
||||
|
||||
Token::Str("a"),
|
||||
Token::End,
|
||||
Token::End,
|
||||
) => ((), (), (5, "a")), ((), (), (isize, &'static str))
|
||||
]);
|
||||
|
||||
test_value!(test_options, [
|
||||
vec!(Token::Option(false)) => None, option::Option<isize>,
|
||||
|
||||
vec!(
|
||||
Token::Option(true),
|
||||
Token::Isize(5),
|
||||
) => Some(5), option::Option<isize>
|
||||
]);
|
||||
|
||||
test_value!(test_structs, [
|
||||
vec!(
|
||||
Token::StructStart("Outer", 1),
|
||||
Token::Str("inner"),
|
||||
Token::SeqStart(0),
|
||||
Token::End,
|
||||
Token::End,
|
||||
) => Outer { inner: vec!() }, Outer,
|
||||
|
||||
vec!(
|
||||
Token::StructStart("Outer", 1),
|
||||
Token::Str("inner"),
|
||||
Token::SeqStart(1),
|
||||
Token::StructStart("Inner", 3),
|
||||
Token::Str("a"),
|
||||
Token::Null,
|
||||
|
||||
Token::Str("b"),
|
||||
Token::Usize(5),
|
||||
|
||||
Token::Str("c"),
|
||||
Token::MapStart(1),
|
||||
Token::String("abc".to_string()),
|
||||
|
||||
Token::Option(true),
|
||||
Token::Char('c'),
|
||||
Token::End,
|
||||
Token::End,
|
||||
Token::End,
|
||||
Token::End,
|
||||
) => Outer {
|
||||
inner: vec!(
|
||||
Inner {
|
||||
a: (),
|
||||
b: 5,
|
||||
c: treemap!("abc".to_string() => Some('c')),
|
||||
},
|
||||
),
|
||||
}, Outer
|
||||
]);
|
||||
|
||||
test_value!(test_enums, [
|
||||
vec!(
|
||||
Token::EnumStart("Animal", "Dog", 0),
|
||||
Token::End,
|
||||
) => Animal::Dog, Animal,
|
||||
|
||||
vec!(
|
||||
Token::EnumStart("Animal", "Frog", 2),
|
||||
Token::String("Henry".to_string()),
|
||||
Token::Isize(349),
|
||||
Token::End,
|
||||
) => Animal::Frog("Henry".to_string(), 349), Animal
|
||||
]);
|
||||
|
||||
test_value!(test_vecs, [
|
||||
vec!(
|
||||
Token::SeqStart(0),
|
||||
Token::End,
|
||||
) => vec!(), Vec<isize>,
|
||||
|
||||
vec!(
|
||||
Token::SeqStart(3),
|
||||
Token::Isize(5),
|
||||
|
||||
Token::Isize(6),
|
||||
|
||||
Token::Isize(7),
|
||||
Token::End,
|
||||
) => vec!(5, 6, 7), Vec<isize>,
|
||||
|
||||
|
||||
vec!(
|
||||
Token::SeqStart(3),
|
||||
Token::SeqStart(1),
|
||||
Token::Isize(1),
|
||||
Token::End,
|
||||
|
||||
Token::SeqStart(2),
|
||||
Token::Isize(2),
|
||||
|
||||
Token::Isize(3),
|
||||
Token::End,
|
||||
|
||||
Token::SeqStart(3),
|
||||
Token::Isize(4),
|
||||
|
||||
Token::Isize(5),
|
||||
|
||||
Token::Isize(6),
|
||||
Token::End,
|
||||
Token::End,
|
||||
) => vec!(vec!(1), vec!(2, 3), vec!(4, 5, 6)), Vec<Vec<isize>>
|
||||
]);
|
||||
|
||||
test_value!(test_treemaps, [
|
||||
vec!(
|
||||
Token::MapStart(0),
|
||||
Token::End,
|
||||
) => treemap!(), BTreeMap<isize, string::String>,
|
||||
|
||||
vec!(
|
||||
Token::MapStart(2),
|
||||
Token::Isize(5),
|
||||
Token::String("a".to_string()),
|
||||
|
||||
Token::Isize(6),
|
||||
Token::String("b".to_string()),
|
||||
Token::End,
|
||||
) => treemap!(5is => "a".to_string(), 6is => "b".to_string()), BTreeMap<isize, string::
|
||||
String>
|
||||
]);
|
||||
-1384
File diff suppressed because it is too large
Load Diff
@@ -1,30 +0,0 @@
|
||||
#![feature(plugin)]
|
||||
#![plugin(serde_macros)]
|
||||
|
||||
extern crate serde;
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
#[derive_serialize]
|
||||
#[derive_deserialize]
|
||||
struct Test {
|
||||
#[serial_name = "$schema"]
|
||||
schema: String,
|
||||
title: String,
|
||||
#[serial_name = "type"]
|
||||
ty: isize
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_json_struct() {
|
||||
let input = Test {
|
||||
schema: "a".to_string(),
|
||||
title: "b".to_string(),
|
||||
ty: 3,
|
||||
};
|
||||
|
||||
let s = serde::json::to_string(&input).unwrap();
|
||||
assert_eq!(&s[], r#"{"$schema":"a","title":"b","type":3}"#);
|
||||
|
||||
let output: Test = serde::json::from_str(&s).unwrap();
|
||||
assert_eq!(input, output);
|
||||
}
|
||||
-517
@@ -1,517 +0,0 @@
|
||||
#![feature(plugin)]
|
||||
#![plugin(serde_macros)]
|
||||
|
||||
extern crate serde;
|
||||
|
||||
use std::collections::{HashMap, BTreeMap};
|
||||
use std::{option, string};
|
||||
|
||||
use serde::ser::{Serializer, Serialize};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
#[derive_serialize]
|
||||
struct Inner {
|
||||
a: (),
|
||||
b: usize,
|
||||
c: HashMap<string::String, option::Option<char>>,
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
#[derive_serialize]
|
||||
struct Outer {
|
||||
inner: Vec<Inner>,
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
#[derive_serialize]
|
||||
enum Animal {
|
||||
Dog,
|
||||
Frog(String, isize)
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
pub enum Token<'a> {
|
||||
Null,
|
||||
Bool(bool),
|
||||
Isize(isize),
|
||||
I8(i8),
|
||||
I16(i16),
|
||||
I32(i32),
|
||||
I64(i64),
|
||||
Usize(usize),
|
||||
U8(u8),
|
||||
U16(u16),
|
||||
U32(u32),
|
||||
U64(u64),
|
||||
F32(f32),
|
||||
F64(f64),
|
||||
Char(char),
|
||||
Str(&'a str),
|
||||
|
||||
TupleStart(usize),
|
||||
TupleSep,
|
||||
TupleEnd,
|
||||
|
||||
StructStart(&'a str, usize),
|
||||
StructSep(&'a str),
|
||||
StructEnd,
|
||||
|
||||
EnumStart(&'a str, &'a str, usize),
|
||||
EnumSep,
|
||||
EnumEnd,
|
||||
|
||||
Option(bool),
|
||||
|
||||
SeqStart(usize),
|
||||
SeqEnd,
|
||||
|
||||
MapStart(usize),
|
||||
MapEnd,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[allow(dead_code)]
|
||||
enum Error {
|
||||
EndOfStream,
|
||||
SyntaxError,
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct AssertSerializer<Iter> {
|
||||
iter: Iter,
|
||||
}
|
||||
|
||||
impl<'a, Iter: Iterator<Item=Token<'a>>> AssertSerializer<Iter> {
|
||||
fn new(iter: Iter) -> AssertSerializer<Iter> {
|
||||
AssertSerializer {
|
||||
iter: iter,
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize<'b>(&mut self, token: Token<'b>) -> Result<(), Error> {
|
||||
let t = match self.iter.next() {
|
||||
Some(t) => t,
|
||||
None => { panic!(); }
|
||||
};
|
||||
|
||||
assert_eq!(t, token);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Iter: Iterator<Item=Token<'a>>> Serializer<Error> for AssertSerializer<Iter> {
|
||||
fn serialize_null(&mut self) -> Result<(), Error> {
|
||||
self.serialize(Token::Null)
|
||||
}
|
||||
fn serialize_bool(&mut self, v: bool) -> Result<(), Error> {
|
||||
self.serialize(Token::Bool(v))
|
||||
}
|
||||
fn serialize_isize(&mut self, v: isize) -> Result<(), Error> {
|
||||
self.serialize(Token::Isize(v))
|
||||
}
|
||||
|
||||
fn serialize_i8(&mut self, v: i8) -> Result<(), Error> {
|
||||
self.serialize(Token::I8(v))
|
||||
}
|
||||
|
||||
fn serialize_i16(&mut self, v: i16) -> Result<(), Error> {
|
||||
self.serialize(Token::I16(v))
|
||||
}
|
||||
|
||||
fn serialize_i32(&mut self, v: i32) -> Result<(), Error> {
|
||||
self.serialize(Token::I32(v))
|
||||
}
|
||||
|
||||
fn serialize_i64(&mut self, v: i64) -> Result<(), Error> {
|
||||
self.serialize(Token::I64(v))
|
||||
}
|
||||
|
||||
fn serialize_usize(&mut self, v: usize) -> Result<(), Error> {
|
||||
self.serialize(Token::Usize(v))
|
||||
}
|
||||
|
||||
fn serialize_u8(&mut self, v: u8) -> Result<(), Error> {
|
||||
self.serialize(Token::U8(v))
|
||||
}
|
||||
|
||||
fn serialize_u16(&mut self, v: u16) -> Result<(), Error> {
|
||||
self.serialize(Token::U16(v))
|
||||
}
|
||||
|
||||
fn serialize_u32(&mut self, v: u32) -> Result<(), Error> {
|
||||
self.serialize(Token::U32(v))
|
||||
}
|
||||
|
||||
fn serialize_u64(&mut self, v: u64) -> Result<(), Error> {
|
||||
self.serialize(Token::U64(v))
|
||||
}
|
||||
|
||||
fn serialize_f32(&mut self, v: f32) -> Result<(), Error> {
|
||||
self.serialize(Token::F32(v))
|
||||
}
|
||||
|
||||
fn serialize_f64(&mut self, v: f64) -> Result<(), Error> {
|
||||
self.serialize(Token::F64(v))
|
||||
}
|
||||
|
||||
fn serialize_char(&mut self, v: char) -> Result<(), Error> {
|
||||
self.serialize(Token::Char(v))
|
||||
}
|
||||
|
||||
fn serialize_str(&mut self, v: &str) -> Result<(), Error> {
|
||||
self.serialize(Token::Str(v))
|
||||
}
|
||||
|
||||
fn serialize_tuple_start(&mut self, len: usize) -> Result<(), Error> {
|
||||
self.serialize(Token::TupleStart(len))
|
||||
}
|
||||
|
||||
fn serialize_tuple_elt<
|
||||
T: Serialize<AssertSerializer<Iter>, Error>
|
||||
>(&mut self, value: &T) -> Result<(), Error> {
|
||||
try!(self.serialize(Token::TupleSep));
|
||||
value.serialize(self)
|
||||
}
|
||||
|
||||
fn serialize_tuple_end(&mut self) -> Result<(), Error> {
|
||||
self.serialize(Token::TupleEnd)
|
||||
}
|
||||
|
||||
fn serialize_struct_start(&mut self, name: &str, len: usize) -> Result<(), Error> {
|
||||
self.serialize(Token::StructStart(name, len))
|
||||
}
|
||||
|
||||
fn serialize_struct_elt<
|
||||
T: Serialize<AssertSerializer<Iter>, Error>
|
||||
>(&mut self, name: &str, value: &T) -> Result<(), Error> {
|
||||
try!(self.serialize(Token::StructSep(name)));
|
||||
value.serialize(self)
|
||||
}
|
||||
|
||||
fn serialize_struct_end(&mut self) -> Result<(), Error> {
|
||||
self.serialize(Token::StructEnd)
|
||||
}
|
||||
|
||||
fn serialize_enum_start(&mut self, name: &str, variant: &str, len: usize) -> Result<(), Error> {
|
||||
self.serialize(Token::EnumStart(name, variant, len))
|
||||
}
|
||||
|
||||
fn serialize_enum_elt<
|
||||
T: Serialize<AssertSerializer<Iter>, Error>
|
||||
>(&mut self, value: &T) -> Result<(), Error> {
|
||||
try!(self.serialize(Token::EnumSep));
|
||||
value.serialize(self)
|
||||
}
|
||||
|
||||
fn serialize_enum_end(&mut self) -> Result<(), Error> {
|
||||
self.serialize(Token::EnumEnd)
|
||||
}
|
||||
|
||||
fn serialize_option<
|
||||
T: Serialize<AssertSerializer<Iter>, Error>
|
||||
>(&mut self, v: &option::Option<T>) -> Result<(), Error> {
|
||||
match *v {
|
||||
Some(ref v) => {
|
||||
try!(self.serialize(Token::Option(true)));
|
||||
v.serialize(self)
|
||||
}
|
||||
None => {
|
||||
self.serialize(Token::Option(false))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_seq<
|
||||
T: Serialize<AssertSerializer<Iter>, Error>,
|
||||
SeqIter: Iterator<Item=T>
|
||||
>(&mut self, iter: SeqIter) -> Result<(), Error> {
|
||||
let (len, _) = iter.size_hint();
|
||||
try!(self.serialize(Token::SeqStart(len)));
|
||||
for elt in iter {
|
||||
try!(elt.serialize(self));
|
||||
}
|
||||
self.serialize(Token::SeqEnd)
|
||||
}
|
||||
|
||||
fn serialize_map<
|
||||
K: Serialize<AssertSerializer<Iter>, Error>,
|
||||
V: Serialize<AssertSerializer<Iter>, Error>,
|
||||
MapIter: Iterator<Item=(K, V)>
|
||||
>(&mut self, iter: MapIter) -> Result<(), Error> {
|
||||
let (len, _) = iter.size_hint();
|
||||
try!(self.serialize(Token::MapStart(len)));
|
||||
for (key, value) in iter {
|
||||
try!(key.serialize(self));
|
||||
try!(value.serialize(self));
|
||||
}
|
||||
self.serialize(Token::MapEnd)
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[test]
|
||||
fn test_tokens_int() {
|
||||
let tokens = vec!(
|
||||
Token::Isize(5)
|
||||
);
|
||||
let mut serializer = AssertSerializer::new(tokens.into_iter());
|
||||
5is.serialize(&mut serializer).unwrap();
|
||||
assert_eq!(serializer.iter.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tokens_str() {
|
||||
let tokens = vec!(
|
||||
Token::Str("a"),
|
||||
);
|
||||
|
||||
let mut serializer = AssertSerializer::new(tokens.into_iter());
|
||||
"a".serialize(&mut serializer).unwrap();
|
||||
assert_eq!(serializer.iter.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tokens_null() {
|
||||
let tokens = vec!(
|
||||
Token::Null,
|
||||
);
|
||||
|
||||
let mut serializer = AssertSerializer::new(tokens.into_iter());
|
||||
().serialize(&mut serializer).unwrap();
|
||||
assert_eq!(serializer.iter.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tokens_option_none() {
|
||||
let tokens = vec!(
|
||||
Token::Option(false),
|
||||
);
|
||||
|
||||
let mut serializer = AssertSerializer::new(tokens.into_iter());
|
||||
None::<isize>.serialize(&mut serializer).unwrap();
|
||||
assert_eq!(serializer.iter.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tokens_option_some() {
|
||||
let tokens = vec!(
|
||||
Token::Option(true),
|
||||
Token::Isize(5),
|
||||
);
|
||||
|
||||
let mut serializer = AssertSerializer::new(tokens.into_iter());
|
||||
Some(5is).serialize(&mut serializer).unwrap();
|
||||
assert_eq!(serializer.iter.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tokens_tuple() {
|
||||
let tokens = vec!(
|
||||
Token::TupleStart(2),
|
||||
Token::TupleSep,
|
||||
Token::Isize(5),
|
||||
|
||||
Token::TupleSep,
|
||||
Token::Str("a"),
|
||||
Token::TupleEnd,
|
||||
);
|
||||
|
||||
let mut serializer = AssertSerializer::new(tokens.into_iter());
|
||||
(5is, "a").serialize(&mut serializer).unwrap();
|
||||
assert_eq!(serializer.iter.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tokens_tuple_compound() {
|
||||
let tokens = vec!(
|
||||
Token::TupleStart(3),
|
||||
Token::TupleSep,
|
||||
Token::Null,
|
||||
|
||||
Token::TupleSep,
|
||||
Token::Null,
|
||||
|
||||
Token::TupleSep,
|
||||
Token::TupleStart(2),
|
||||
Token::TupleSep,
|
||||
Token::Isize(5),
|
||||
|
||||
Token::TupleSep,
|
||||
Token::Str("a"),
|
||||
Token::TupleEnd,
|
||||
Token::TupleEnd,
|
||||
);
|
||||
|
||||
let mut serializer = AssertSerializer::new(tokens.into_iter());
|
||||
((), (), (5is, "a")).serialize(&mut serializer).unwrap();
|
||||
assert_eq!(serializer.iter.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tokens_struct_empty() {
|
||||
let tokens = vec!(
|
||||
Token::StructStart("Outer", 1),
|
||||
Token::StructSep("inner"),
|
||||
Token::SeqStart(0),
|
||||
Token::SeqEnd,
|
||||
Token::StructEnd,
|
||||
);
|
||||
|
||||
let mut serializer = AssertSerializer::new(tokens.into_iter());
|
||||
Outer { inner: vec!() }.serialize(&mut serializer).unwrap();
|
||||
assert_eq!(serializer.iter.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tokens_struct() {
|
||||
let tokens = vec!(
|
||||
Token::StructStart("Outer", 1),
|
||||
Token::StructSep("inner"),
|
||||
Token::SeqStart(1),
|
||||
Token::StructStart("Inner", 3),
|
||||
Token::StructSep("a"),
|
||||
Token::Null,
|
||||
|
||||
Token::StructSep("b"),
|
||||
Token::Usize(5),
|
||||
|
||||
Token::StructSep("c"),
|
||||
Token::MapStart(1),
|
||||
Token::Str("abc"),
|
||||
Token::Option(true),
|
||||
Token::Char('c'),
|
||||
Token::MapEnd,
|
||||
Token::StructEnd,
|
||||
Token::SeqEnd,
|
||||
Token::StructEnd,
|
||||
);
|
||||
|
||||
let mut serializer = AssertSerializer::new(tokens.into_iter());
|
||||
|
||||
let mut map = HashMap::new();
|
||||
map.insert("abc".to_string(), Some('c'));
|
||||
|
||||
Outer {
|
||||
inner: vec!(
|
||||
Inner {
|
||||
a: (),
|
||||
b: 5,
|
||||
c: map,
|
||||
},
|
||||
)
|
||||
}.serialize(&mut serializer).unwrap();
|
||||
assert_eq!(serializer.iter.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tokens_enum() {
|
||||
let tokens = vec!(
|
||||
Token::EnumStart("Animal", "Dog", 0),
|
||||
Token::EnumEnd,
|
||||
);
|
||||
|
||||
let mut serializer = AssertSerializer::new(tokens.into_iter());
|
||||
Animal::Dog.serialize(&mut serializer).unwrap();
|
||||
assert_eq!(serializer.iter.next(), None);
|
||||
|
||||
let tokens = vec!(
|
||||
Token::EnumStart("Animal", "Frog", 2),
|
||||
Token::EnumSep,
|
||||
Token::Str("Henry"),
|
||||
|
||||
Token::EnumSep,
|
||||
Token::Isize(349),
|
||||
Token::EnumEnd,
|
||||
);
|
||||
|
||||
let mut serializer = AssertSerializer::new(tokens.into_iter());
|
||||
Animal::Frog("Henry".to_string(), 349).serialize(&mut serializer).unwrap();
|
||||
assert_eq!(serializer.iter.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tokens_vec_empty() {
|
||||
let tokens = vec!(
|
||||
Token::SeqStart(0),
|
||||
Token::SeqEnd,
|
||||
);
|
||||
|
||||
let mut serializer = AssertSerializer::new(tokens.into_iter());
|
||||
let v: Vec<isize> = vec!();
|
||||
v.serialize(&mut serializer).unwrap();
|
||||
assert_eq!(serializer.iter.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tokens_vec() {
|
||||
let tokens = vec!(
|
||||
Token::SeqStart(3),
|
||||
Token::Isize(5),
|
||||
Token::Isize(6),
|
||||
Token::Isize(7),
|
||||
Token::SeqEnd,
|
||||
);
|
||||
|
||||
let mut serializer = AssertSerializer::new(tokens.into_iter());
|
||||
(vec!(5is, 6, 7)).serialize(&mut serializer).unwrap();
|
||||
assert_eq!(serializer.iter.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tokens_vec_compound() {
|
||||
let tokens = vec!(
|
||||
Token::SeqStart(3),
|
||||
Token::SeqStart(1),
|
||||
Token::Isize(1),
|
||||
Token::SeqEnd,
|
||||
|
||||
Token::SeqStart(2),
|
||||
Token::Isize(2),
|
||||
Token::Isize(3),
|
||||
Token::SeqEnd,
|
||||
|
||||
Token::SeqStart(3),
|
||||
Token::Isize(4),
|
||||
Token::Isize(5),
|
||||
Token::Isize(6),
|
||||
Token::SeqEnd,
|
||||
Token::SeqEnd,
|
||||
);
|
||||
|
||||
let mut serializer = AssertSerializer::new(tokens.into_iter());
|
||||
(vec!(vec!(1is), vec!(2, 3), vec!(4, 5, 6))).serialize(&mut serializer).unwrap();
|
||||
assert_eq!(serializer.iter.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tokens_treemap() {
|
||||
let tokens = vec!(
|
||||
Token::MapStart(2),
|
||||
Token::Isize(5),
|
||||
Token::Str("a"),
|
||||
|
||||
Token::Isize(6),
|
||||
Token::Str("b"),
|
||||
Token::MapEnd,
|
||||
);
|
||||
|
||||
let mut serializer = AssertSerializer::new(tokens.into_iter());
|
||||
|
||||
let mut map = BTreeMap::new();
|
||||
map.insert(5is, "a".to_string());
|
||||
map.insert(6is, "b".to_string());
|
||||
|
||||
map.serialize(&mut serializer).unwrap();
|
||||
assert_eq!(serializer.iter.next(), None);
|
||||
}
|
||||
@@ -0,0 +1,651 @@
|
||||
#![feature(custom_derive, plugin, test)]
|
||||
#![plugin(serde_macros)]
|
||||
|
||||
extern crate test;
|
||||
extern crate serde;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::iter;
|
||||
use std::vec;
|
||||
|
||||
use serde::de::{self, Deserialize, Deserializer, Visitor};
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Token<'a> {
|
||||
Bool(bool),
|
||||
Isize(isize),
|
||||
I8(i8),
|
||||
I16(i16),
|
||||
I32(i32),
|
||||
I64(i64),
|
||||
Usize(usize),
|
||||
U8(u8),
|
||||
U16(u16),
|
||||
U32(u32),
|
||||
U64(u64),
|
||||
F32(f32),
|
||||
F64(f64),
|
||||
Char(char),
|
||||
Str(&'a str),
|
||||
String(String),
|
||||
|
||||
Option(bool),
|
||||
|
||||
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, &'a str),
|
||||
EnumEnd,
|
||||
}
|
||||
|
||||
struct TokenDeserializer<'a> {
|
||||
tokens: iter::Peekable<vec::IntoIter<Token<'a>>>,
|
||||
}
|
||||
|
||||
impl<'a> TokenDeserializer<'a> {
|
||||
fn new(tokens: Vec<Token<'a>>) -> TokenDeserializer<'a> {
|
||||
TokenDeserializer {
|
||||
tokens: tokens.into_iter().peekable(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, PartialEq, Debug)]
|
||||
enum Error {
|
||||
SyntaxError,
|
||||
EndOfStreamError,
|
||||
MissingFieldError(&'static str),
|
||||
}
|
||||
|
||||
impl de::Error for Error {
|
||||
fn syntax_error() -> Error { Error::SyntaxError }
|
||||
|
||||
fn end_of_stream_error() -> Error { Error::EndOfStreamError }
|
||||
|
||||
fn missing_field_error(field: &'static str) -> Error {
|
||||
Error::MissingFieldError(field)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Deserializer for TokenDeserializer<'a> {
|
||||
type Error = Error;
|
||||
|
||||
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
|
||||
where V: Visitor,
|
||||
{
|
||||
match self.tokens.next() {
|
||||
Some(Token::Bool(v)) => visitor.visit_bool(v),
|
||||
Some(Token::Isize(v)) => visitor.visit_isize(v),
|
||||
Some(Token::I8(v)) => visitor.visit_i8(v),
|
||||
Some(Token::I16(v)) => visitor.visit_i16(v),
|
||||
Some(Token::I32(v)) => visitor.visit_i32(v),
|
||||
Some(Token::I64(v)) => visitor.visit_i64(v),
|
||||
Some(Token::Usize(v)) => visitor.visit_usize(v),
|
||||
Some(Token::U8(v)) => visitor.visit_u8(v),
|
||||
Some(Token::U16(v)) => visitor.visit_u16(v),
|
||||
Some(Token::U32(v)) => visitor.visit_u32(v),
|
||||
Some(Token::U64(v)) => visitor.visit_u64(v),
|
||||
Some(Token::F32(v)) => visitor.visit_f32(v),
|
||||
Some(Token::F64(v)) => visitor.visit_f64(v),
|
||||
Some(Token::Char(v)) => visitor.visit_char(v),
|
||||
Some(Token::Str(v)) => visitor.visit_str(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::NamedUnit(name)) => visitor.visit_named_unit(name),
|
||||
Some(Token::SeqStart(len)) => {
|
||||
visitor.visit_seq(TokenDeserializerSeqVisitor {
|
||||
de: self,
|
||||
len: len,
|
||||
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,
|
||||
len: len,
|
||||
first: true,
|
||||
})
|
||||
}
|
||||
Some(Token::NamedMapStart(name, len)) => {
|
||||
visitor.visit_named_map(name, TokenDeserializerMapVisitor {
|
||||
de: self,
|
||||
len: len,
|
||||
first: true,
|
||||
})
|
||||
}
|
||||
Some(Token::EnumStart(name, variant)) => {
|
||||
visitor.visit_enum(name, variant, TokenDeserializerEnumVisitor {
|
||||
de: self,
|
||||
})
|
||||
}
|
||||
Some(_) => Err(Error::SyntaxError),
|
||||
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>(&mut self, mut visitor: V) -> Result<V::Value, Error>
|
||||
where V: Visitor,
|
||||
{
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct TokenDeserializerSeqVisitor<'a, 'b: 'a> {
|
||||
de: &'a mut TokenDeserializer<'b>,
|
||||
len: usize,
|
||||
first: bool,
|
||||
}
|
||||
|
||||
impl<'a, 'b> de::SeqVisitor for TokenDeserializerSeqVisitor<'a, 'b> {
|
||||
type Error = Error;
|
||||
|
||||
fn visit<T>(&mut self) -> Result<Option<T>, Error>
|
||||
where T: Deserialize,
|
||||
{
|
||||
let first = self.first;
|
||||
self.first = false;
|
||||
|
||||
match self.de.tokens.next() {
|
||||
Some(Token::SeqSep(first_)) if first_ == first => {
|
||||
self.len -= 1;
|
||||
Ok(Some(try!(Deserialize::deserialize(self.de))))
|
||||
}
|
||||
Some(Token::SeqEnd) => Ok(None),
|
||||
Some(_) => {
|
||||
Err(Error::SyntaxError)
|
||||
}
|
||||
None => Err(Error::EndOfStreamError),
|
||||
}
|
||||
}
|
||||
|
||||
fn end(&mut self) -> Result<(), Error> {
|
||||
match self.de.tokens.next() {
|
||||
Some(Token::SeqEnd) => Ok(()),
|
||||
Some(_) => Err(Error::SyntaxError),
|
||||
None => Err(Error::EndOfStreamError),
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(self.len, Some(self.len))
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct TokenDeserializerMapVisitor<'a, 'b: 'a> {
|
||||
de: &'a mut TokenDeserializer<'b>,
|
||||
len: usize,
|
||||
first: bool,
|
||||
}
|
||||
|
||||
impl<'a, 'b> de::MapVisitor for TokenDeserializerMapVisitor<'a, 'b> {
|
||||
type Error = Error;
|
||||
|
||||
fn visit_key<K>(&mut self) -> Result<Option<K>, Error>
|
||||
where K: Deserialize,
|
||||
{
|
||||
let first = self.first;
|
||||
self.first = false;
|
||||
|
||||
match self.de.tokens.next() {
|
||||
Some(Token::MapSep(first_)) if first_ == first => {
|
||||
Ok(Some(try!(Deserialize::deserialize(self.de))))
|
||||
}
|
||||
Some(Token::MapEnd) => Ok(None),
|
||||
Some(_) => Err(Error::SyntaxError),
|
||||
None => Err(Error::EndOfStreamError),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_value<V>(&mut self) -> Result<V, Error>
|
||||
where V: Deserialize,
|
||||
{
|
||||
Ok(try!(Deserialize::deserialize(self.de)))
|
||||
}
|
||||
|
||||
fn end(&mut self) -> Result<(), Error> {
|
||||
match self.de.tokens.next() {
|
||||
Some(Token::MapEnd) => Ok(()),
|
||||
Some(_) => Err(Error::SyntaxError),
|
||||
None => Err(Error::EndOfStreamError),
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(self.len, Some(self.len))
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct TokenDeserializerEnumVisitor<'a, 'b: 'a> {
|
||||
de: &'a mut TokenDeserializer<'b>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> de::EnumVisitor for TokenDeserializerEnumVisitor<'a, 'b> {
|
||||
type Error = Error;
|
||||
|
||||
fn visit_unit(&mut self) -> Result<(), Error> {
|
||||
let value = try!(Deserialize::deserialize(self.de));
|
||||
|
||||
match self.de.tokens.next() {
|
||||
Some(Token::EnumEnd) => Ok(value),
|
||||
Some(_) => Err(Error::SyntaxError),
|
||||
None => Err(Error::EndOfStreamError),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
|
||||
where V: de::EnumSeqVisitor,
|
||||
{
|
||||
let token = self.de.tokens.next();
|
||||
match token {
|
||||
Some(Token::SeqStart(len)) => {
|
||||
let value = try!(visitor.visit(TokenDeserializerSeqVisitor {
|
||||
de: self.de,
|
||||
len: len,
|
||||
first: true,
|
||||
}));
|
||||
|
||||
match self.de.tokens.next() {
|
||||
Some(Token::EnumEnd) => Ok(value),
|
||||
Some(_) => Err(Error::SyntaxError),
|
||||
None => Err(Error::EndOfStreamError),
|
||||
}
|
||||
}
|
||||
Some(_) => Err(Error::SyntaxError),
|
||||
None => Err(Error::EndOfStreamError),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_map<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
|
||||
where V: de::EnumMapVisitor,
|
||||
{
|
||||
match self.de.tokens.next() {
|
||||
Some(Token::MapStart(len)) => {
|
||||
let value = try!(visitor.visit(TokenDeserializerMapVisitor {
|
||||
de: self.de,
|
||||
len: len,
|
||||
first: true,
|
||||
}));
|
||||
|
||||
match self.de.tokens.next() {
|
||||
Some(Token::EnumEnd) => Ok(value),
|
||||
Some(_) => Err(Error::SyntaxError),
|
||||
None => Err(Error::EndOfStreamError),
|
||||
}
|
||||
}
|
||||
Some(_) => Err(Error::SyntaxError),
|
||||
None => Err(Error::EndOfStreamError),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[derive(Copy, PartialEq, Debug)]
|
||||
#[derive_deserialize]
|
||||
struct NamedUnit;
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
#[derive_deserialize]
|
||||
struct NamedSeq(i32, i32, i32);
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
#[derive_deserialize]
|
||||
struct NamedMap {
|
||||
a: i32,
|
||||
b: i32,
|
||||
c: i32,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
#[derive_deserialize]
|
||||
enum Enum {
|
||||
Unit,
|
||||
Seq(i32, i32, i32),
|
||||
Map { a: i32, b: i32, c: i32 }
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
macro_rules! btreemap {
|
||||
() => {
|
||||
BTreeMap::new()
|
||||
};
|
||||
($($key:expr => $value:expr),+) => {
|
||||
{
|
||||
let mut map = BTreeMap::new();
|
||||
$(map.insert($key, $value);)+
|
||||
map
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! declare_test {
|
||||
($name:ident { $($value:expr => $tokens:expr,)+ }) => {
|
||||
#[test]
|
||||
fn $name() {
|
||||
$(
|
||||
let mut de = TokenDeserializer::new($tokens);
|
||||
let value: Result<_, Error> = Deserialize::deserialize(&mut de);
|
||||
assert_eq!(value, Ok($value));
|
||||
)+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! declare_tests {
|
||||
($($name:ident { $($value:expr => $tokens:expr,)+ })+) => {
|
||||
$(
|
||||
declare_test!($name { $($value => $tokens,)+ });
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
declare_tests! {
|
||||
test_bool {
|
||||
true => vec![Token::Bool(true)],
|
||||
false => vec![Token::Bool(false)],
|
||||
}
|
||||
test_isize {
|
||||
0isize => vec![Token::Isize(0)],
|
||||
0isize => vec![Token::I8(0)],
|
||||
0isize => vec![Token::I16(0)],
|
||||
0isize => vec![Token::I32(0)],
|
||||
0isize => vec![Token::I64(0)],
|
||||
0isize => vec![Token::Usize(0)],
|
||||
0isize => vec![Token::U8(0)],
|
||||
0isize => vec![Token::U16(0)],
|
||||
0isize => vec![Token::U32(0)],
|
||||
0isize => vec![Token::U64(0)],
|
||||
0isize => vec![Token::F32(0.)],
|
||||
0isize => vec![Token::F64(0.)],
|
||||
}
|
||||
test_ints {
|
||||
0isize => vec![Token::Isize(0)],
|
||||
0i8 => vec![Token::I8(0)],
|
||||
0i16 => vec![Token::I16(0)],
|
||||
0i32 => vec![Token::I32(0)],
|
||||
0i64 => vec![Token::I64(0)],
|
||||
}
|
||||
test_uints {
|
||||
0usize => vec![Token::Usize(0)],
|
||||
0u8 => vec![Token::U8(0)],
|
||||
0u16 => vec![Token::U16(0)],
|
||||
0u32 => vec![Token::U32(0)],
|
||||
0u64 => vec![Token::U64(0)],
|
||||
}
|
||||
test_floats {
|
||||
0f32 => vec![Token::F32(0.)],
|
||||
0f64 => vec![Token::F64(0.)],
|
||||
}
|
||||
test_char {
|
||||
'a' => vec![Token::Char('a')],
|
||||
'a' => vec![Token::Str("a")],
|
||||
'a' => vec![Token::String("a".to_string())],
|
||||
}
|
||||
test_string {
|
||||
"abc".to_string() => vec![Token::Str("abc")],
|
||||
"abc".to_string() => vec![Token::String("abc".to_string())],
|
||||
"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 {
|
||||
NamedUnit => vec![Token::Unit],
|
||||
NamedUnit => vec![Token::NamedUnit("NamedUnit")],
|
||||
NamedUnit => vec![
|
||||
Token::SeqStart(0),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
}
|
||||
test_named_seq {
|
||||
NamedSeq(1, 2, 3) => vec![
|
||||
Token::SeqStart(3),
|
||||
Token::SeqSep(true),
|
||||
Token::I32(1),
|
||||
|
||||
Token::SeqSep(false),
|
||||
Token::I32(2),
|
||||
|
||||
Token::SeqSep(false),
|
||||
Token::I32(3),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
NamedSeq(1, 2, 3) => vec![
|
||||
Token::NamedSeqStart("NamedSeq", 3),
|
||||
Token::SeqSep(true),
|
||||
Token::I32(1),
|
||||
|
||||
Token::SeqSep(false),
|
||||
Token::I32(2),
|
||||
|
||||
Token::SeqSep(false),
|
||||
Token::I32(3),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
}
|
||||
test_vec {
|
||||
Vec::<isize>::new() => vec![
|
||||
Token::SeqStart(0),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
vec![vec![], vec![1], vec![2, 3]] => vec![
|
||||
Token::SeqStart(3),
|
||||
Token::SeqSep(true),
|
||||
Token::SeqStart(0),
|
||||
Token::SeqEnd,
|
||||
|
||||
Token::SeqSep(false),
|
||||
Token::SeqStart(1),
|
||||
Token::SeqSep(true),
|
||||
Token::I32(1),
|
||||
Token::SeqEnd,
|
||||
|
||||
Token::SeqSep(false),
|
||||
Token::SeqStart(2),
|
||||
Token::SeqSep(true),
|
||||
Token::I32(2),
|
||||
|
||||
Token::SeqSep(false),
|
||||
Token::I32(3),
|
||||
Token::SeqEnd,
|
||||
Token::SeqEnd,
|
||||
],
|
||||
}
|
||||
test_tuple {
|
||||
(1,) => vec![
|
||||
Token::SeqStart(1),
|
||||
Token::SeqSep(true),
|
||||
Token::I32(1),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
(1, 2, 3) => vec![
|
||||
Token::SeqStart(3),
|
||||
Token::SeqSep(true),
|
||||
Token::I32(1),
|
||||
|
||||
Token::SeqSep(false),
|
||||
Token::I32(2),
|
||||
|
||||
Token::SeqSep(false),
|
||||
Token::I32(3),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
}
|
||||
test_btreemap {
|
||||
btreemap![1 => 2] => vec![
|
||||
Token::MapStart(1),
|
||||
Token::MapSep(true),
|
||||
Token::I32(1),
|
||||
Token::I32(2),
|
||||
Token::MapEnd,
|
||||
],
|
||||
btreemap![1 => 2, 3 => 4] => vec![
|
||||
Token::MapStart(2),
|
||||
Token::MapSep(true),
|
||||
Token::I32(1),
|
||||
Token::I32(2),
|
||||
|
||||
Token::MapSep(false),
|
||||
Token::I32(3),
|
||||
Token::I32(4),
|
||||
Token::MapEnd,
|
||||
],
|
||||
btreemap![1 => btreemap![], 2 => btreemap![3 => 4, 5 => 6]] => vec![
|
||||
Token::MapStart(2),
|
||||
Token::MapSep(true),
|
||||
Token::I32(1),
|
||||
Token::MapStart(0),
|
||||
Token::MapEnd,
|
||||
|
||||
Token::MapSep(false),
|
||||
Token::I32(2),
|
||||
Token::MapStart(2),
|
||||
Token::MapSep(true),
|
||||
Token::I32(3),
|
||||
Token::I32(4),
|
||||
|
||||
Token::MapSep(false),
|
||||
Token::I32(5),
|
||||
Token::I32(6),
|
||||
Token::MapEnd,
|
||||
Token::MapEnd,
|
||||
],
|
||||
}
|
||||
test_named_map {
|
||||
NamedMap { a: 1, b: 2, c: 3 } => vec![
|
||||
Token::MapStart(3),
|
||||
Token::MapSep(true),
|
||||
Token::Str("a"),
|
||||
Token::I32(1),
|
||||
|
||||
Token::MapSep(false),
|
||||
Token::Str("b"),
|
||||
Token::I32(2),
|
||||
|
||||
Token::MapSep(false),
|
||||
Token::Str("c"),
|
||||
Token::I32(3),
|
||||
Token::MapEnd,
|
||||
],
|
||||
NamedMap { a: 1, b: 2, c: 3 } => vec![
|
||||
Token::NamedMapStart("NamedMap", 3),
|
||||
Token::MapSep(true),
|
||||
Token::Str("a"),
|
||||
Token::I32(1),
|
||||
|
||||
Token::MapSep(false),
|
||||
Token::Str("b"),
|
||||
Token::I32(2),
|
||||
|
||||
Token::MapSep(false),
|
||||
Token::Str("c"),
|
||||
Token::I32(3),
|
||||
Token::MapEnd,
|
||||
],
|
||||
}
|
||||
test_enum {
|
||||
Enum::Unit => vec![
|
||||
Token::EnumStart("Enum", "Unit"),
|
||||
Token::Unit,
|
||||
Token::EnumEnd,
|
||||
],
|
||||
}
|
||||
test_enum_seq {
|
||||
Enum::Seq(1, 2, 3) => vec![
|
||||
Token::EnumStart("Enum", "Seq"),
|
||||
Token::SeqStart(3),
|
||||
Token::SeqSep(true),
|
||||
Token::I32(1),
|
||||
|
||||
Token::SeqSep(false),
|
||||
Token::I32(2),
|
||||
|
||||
Token::SeqSep(false),
|
||||
Token::I32(3),
|
||||
Token::SeqEnd,
|
||||
Token::EnumEnd,
|
||||
],
|
||||
}
|
||||
test_enum_map {
|
||||
Enum::Map { a: 1, b: 2, c: 3 } => vec![
|
||||
Token::EnumStart("Enum", "Map"),
|
||||
Token::MapStart(3),
|
||||
Token::MapSep(true),
|
||||
Token::Str("a"),
|
||||
Token::I32(1),
|
||||
|
||||
Token::MapSep(false),
|
||||
Token::Str("b"),
|
||||
Token::I32(2),
|
||||
|
||||
Token::MapSep(false),
|
||||
Token::Str("c"),
|
||||
Token::I32(3),
|
||||
Token::MapEnd,
|
||||
Token::EnumEnd,
|
||||
],
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,761 @@
|
||||
#![feature(custom_derive, plugin, test)]
|
||||
#![plugin(serde_macros)]
|
||||
|
||||
extern crate test;
|
||||
extern crate serde;
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use serde::de;
|
||||
use serde::ser;
|
||||
|
||||
use serde::json::{
|
||||
self,
|
||||
Value,
|
||||
from_str,
|
||||
from_value,
|
||||
to_value,
|
||||
};
|
||||
|
||||
use serde::json::error::{Error, ErrorCode};
|
||||
|
||||
macro_rules! treemap {
|
||||
($($k:expr => $v:expr),*) => ({
|
||||
let mut _m = BTreeMap::new();
|
||||
$(_m.insert($k, $v);)*
|
||||
_m
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
#[derive_serialize]
|
||||
#[derive_deserialize]
|
||||
enum Animal {
|
||||
Dog,
|
||||
Frog(String, Vec<isize>),
|
||||
Cat { age: usize, name: String },
|
||||
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
#[derive_serialize]
|
||||
#[derive_deserialize]
|
||||
struct Inner {
|
||||
a: (),
|
||||
b: usize,
|
||||
c: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
#[derive_serialize]
|
||||
#[derive_deserialize]
|
||||
struct Outer {
|
||||
inner: Vec<Inner>,
|
||||
}
|
||||
|
||||
fn test_encode_ok<T>(errors: &[(T, &str)])
|
||||
where T: PartialEq + Debug + ser::Serialize,
|
||||
{
|
||||
for &(ref value, out) in errors {
|
||||
let out = out.to_string();
|
||||
|
||||
let s = json::to_string(value).unwrap();
|
||||
assert_eq!(s, out);
|
||||
|
||||
let v = to_value(&value);
|
||||
let s = json::to_string(&v).unwrap();
|
||||
assert_eq!(s, out);
|
||||
}
|
||||
}
|
||||
|
||||
fn test_pretty_encode_ok<T>(errors: &[(T, &str)])
|
||||
where T: PartialEq + Debug + ser::Serialize,
|
||||
{
|
||||
for &(ref value, out) in errors {
|
||||
let out = out.to_string();
|
||||
|
||||
let s = json::to_string_pretty(value).unwrap();
|
||||
assert_eq!(s, out);
|
||||
|
||||
let v = to_value(&value);
|
||||
let s = json::to_string_pretty(&v).unwrap();
|
||||
assert_eq!(s, out);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_null() {
|
||||
let tests = &[
|
||||
((), "null"),
|
||||
];
|
||||
test_encode_ok(tests);
|
||||
test_pretty_encode_ok(tests);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_i64() {
|
||||
let tests = &[
|
||||
(3i64, "3"),
|
||||
(-2i64, "-2"),
|
||||
(-1234i64, "-1234"),
|
||||
];
|
||||
test_encode_ok(tests);
|
||||
test_pretty_encode_ok(tests);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_f64() {
|
||||
let tests = &[
|
||||
(3.0, "3"),
|
||||
(3.1, "3.1"),
|
||||
(-1.5, "-1.5"),
|
||||
(0.5, "0.5"),
|
||||
];
|
||||
test_encode_ok(tests);
|
||||
test_pretty_encode_ok(tests);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_str() {
|
||||
let tests = &[
|
||||
("", "\"\""),
|
||||
("foo", "\"foo\""),
|
||||
];
|
||||
test_encode_ok(tests);
|
||||
test_pretty_encode_ok(tests);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_bool() {
|
||||
let tests = &[
|
||||
(true, "true"),
|
||||
(false, "false"),
|
||||
];
|
||||
test_encode_ok(tests);
|
||||
test_pretty_encode_ok(tests);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_list() {
|
||||
test_encode_ok(&[
|
||||
(vec![], "[]"),
|
||||
(vec![true], "[true]"),
|
||||
(vec![true, false], "[true,false]"),
|
||||
]);
|
||||
|
||||
test_pretty_encode_ok(&[
|
||||
(vec![], "[]"),
|
||||
(
|
||||
vec![true],
|
||||
concat!(
|
||||
"[\n",
|
||||
" true\n",
|
||||
"]"
|
||||
),
|
||||
),
|
||||
(
|
||||
vec![true, false],
|
||||
concat!(
|
||||
"[\n",
|
||||
" true,\n",
|
||||
" false\n",
|
||||
"]"
|
||||
),
|
||||
),
|
||||
]);
|
||||
|
||||
let long_test_list = Value::Array(vec![
|
||||
Value::Bool(false),
|
||||
Value::Null,
|
||||
Value::Array(vec![Value::String("foo\nbar".to_string()), Value::F64(3.5)])]);
|
||||
|
||||
test_encode_ok(&[
|
||||
(
|
||||
long_test_list.clone(),
|
||||
"[false,null,[\"foo\\nbar\",3.5]]",
|
||||
),
|
||||
]);
|
||||
|
||||
test_pretty_encode_ok(&[
|
||||
(
|
||||
long_test_list,
|
||||
concat!(
|
||||
"[\n",
|
||||
" false,\n",
|
||||
" null,\n",
|
||||
" [\n",
|
||||
" \"foo\\nbar\",\n",
|
||||
" 3.5\n",
|
||||
" ]\n",
|
||||
"]"
|
||||
),
|
||||
)
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_object() {
|
||||
test_encode_ok(&[
|
||||
(treemap!(), "{}"),
|
||||
(treemap!("a".to_string() => true), "{\"a\":true}"),
|
||||
(
|
||||
treemap!(
|
||||
"a".to_string() => true,
|
||||
"b".to_string() => false
|
||||
),
|
||||
"{\"a\":true,\"b\":false}"),
|
||||
]);
|
||||
|
||||
test_pretty_encode_ok(&[
|
||||
(treemap!(), "{}"),
|
||||
(
|
||||
treemap!("a".to_string() => true),
|
||||
concat!(
|
||||
"{\n",
|
||||
" \"a\": true\n",
|
||||
"}"
|
||||
),
|
||||
),
|
||||
(
|
||||
treemap!(
|
||||
"a".to_string() => true,
|
||||
"b".to_string() => false
|
||||
),
|
||||
concat!(
|
||||
"{\n",
|
||||
" \"a\": true,\n",
|
||||
" \"b\": false\n",
|
||||
"}"
|
||||
),
|
||||
),
|
||||
]);
|
||||
|
||||
let complex_obj = Value::Object(treemap!(
|
||||
"b".to_string() => Value::Array(vec![
|
||||
Value::Object(treemap!("c".to_string() => Value::String("\x0c\r".to_string()))),
|
||||
Value::Object(treemap!("d".to_string() => Value::String("".to_string())))
|
||||
])
|
||||
));
|
||||
|
||||
test_encode_ok(&[
|
||||
(
|
||||
complex_obj.clone(),
|
||||
"{\
|
||||
\"b\":[\
|
||||
{\"c\":\"\\f\\r\"},\
|
||||
{\"d\":\"\"}\
|
||||
]\
|
||||
}"
|
||||
),
|
||||
]);
|
||||
|
||||
test_pretty_encode_ok(&[
|
||||
(
|
||||
complex_obj.clone(),
|
||||
concat!(
|
||||
"{\n",
|
||||
" \"b\": [\n",
|
||||
" {\n",
|
||||
" \"c\": \"\\f\\r\"\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"d\": \"\"\n",
|
||||
" }\n",
|
||||
" ]\n",
|
||||
"}"
|
||||
),
|
||||
)
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_tuple() {
|
||||
test_encode_ok(&[
|
||||
(
|
||||
(5,),
|
||||
"[5]",
|
||||
),
|
||||
]);
|
||||
|
||||
test_pretty_encode_ok(&[
|
||||
(
|
||||
(5,),
|
||||
concat!(
|
||||
"[\n",
|
||||
" 5\n",
|
||||
"]"
|
||||
),
|
||||
),
|
||||
]);
|
||||
|
||||
test_encode_ok(&[
|
||||
(
|
||||
(5, (6, "abc")),
|
||||
"[5,[6,\"abc\"]]",
|
||||
),
|
||||
]);
|
||||
|
||||
test_pretty_encode_ok(&[
|
||||
(
|
||||
(5, (6, "abc")),
|
||||
concat!(
|
||||
"[\n",
|
||||
" 5,\n",
|
||||
" [\n",
|
||||
" 6,\n",
|
||||
" \"abc\"\n",
|
||||
" ]\n",
|
||||
"]"
|
||||
),
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_enum() {
|
||||
test_encode_ok(&[
|
||||
(
|
||||
Animal::Dog,
|
||||
"{\"Dog\":[]}",
|
||||
),
|
||||
(
|
||||
Animal::Frog("Henry".to_string(), vec![]),
|
||||
"{\"Frog\":[\"Henry\",[]]}",
|
||||
),
|
||||
(
|
||||
Animal::Frog("Henry".to_string(), vec![349]),
|
||||
"{\"Frog\":[\"Henry\",[349]]}",
|
||||
),
|
||||
(
|
||||
Animal::Frog("Henry".to_string(), vec![349, 102]),
|
||||
"{\"Frog\":[\"Henry\",[349,102]]}",
|
||||
),
|
||||
(
|
||||
Animal::Cat { age: 5, name: "Kate".to_string() },
|
||||
"{\"Cat\":{\"age\":5,\"name\":\"Kate\"}}"
|
||||
),
|
||||
]);
|
||||
|
||||
test_pretty_encode_ok(&[
|
||||
(
|
||||
Animal::Dog,
|
||||
concat!(
|
||||
"{\n",
|
||||
" \"Dog\": []\n",
|
||||
"}"
|
||||
),
|
||||
),
|
||||
(
|
||||
Animal::Frog("Henry".to_string(), vec![]),
|
||||
concat!(
|
||||
"{\n",
|
||||
" \"Frog\": [\n",
|
||||
" \"Henry\",\n",
|
||||
" []\n",
|
||||
" ]\n",
|
||||
"}"
|
||||
),
|
||||
),
|
||||
(
|
||||
Animal::Frog("Henry".to_string(), vec![349]),
|
||||
concat!(
|
||||
"{\n",
|
||||
" \"Frog\": [\n",
|
||||
" \"Henry\",\n",
|
||||
" [\n",
|
||||
" 349\n",
|
||||
" ]\n",
|
||||
" ]\n",
|
||||
"}"
|
||||
),
|
||||
),
|
||||
(
|
||||
Animal::Frog("Henry".to_string(), vec![349, 102]),
|
||||
concat!(
|
||||
"{\n",
|
||||
" \"Frog\": [\n",
|
||||
" \"Henry\",\n",
|
||||
" [\n",
|
||||
" 349,\n",
|
||||
" 102\n",
|
||||
" ]\n",
|
||||
" ]\n",
|
||||
"}"
|
||||
),
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_option() {
|
||||
test_encode_ok(&[
|
||||
(None, "null"),
|
||||
(Some("jodhpurs"), "\"jodhpurs\""),
|
||||
]);
|
||||
|
||||
test_encode_ok(&[
|
||||
(None, "null"),
|
||||
(Some(vec!["foo", "bar"]), "[\"foo\",\"bar\"]"),
|
||||
]);
|
||||
|
||||
test_pretty_encode_ok(&[
|
||||
(None, "null"),
|
||||
(Some("jodhpurs"), "\"jodhpurs\""),
|
||||
]);
|
||||
|
||||
test_pretty_encode_ok(&[
|
||||
(None, "null"),
|
||||
(
|
||||
Some(vec!["foo", "bar"]),
|
||||
concat!(
|
||||
"[\n",
|
||||
" \"foo\",\n",
|
||||
" \"bar\"\n",
|
||||
"]"
|
||||
),
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
fn test_parse_ok<'a, T>(errors: &[(&'a str, T)])
|
||||
where T: PartialEq + Debug + ser::Serialize + de::Deserialize,
|
||||
{
|
||||
for &(s, ref value) in errors {
|
||||
let v: T = from_str(s).unwrap();
|
||||
assert_eq!(v, *value);
|
||||
|
||||
// Make sure we can deserialize into a `Value`.
|
||||
let json_value: Value = from_str(s).unwrap();
|
||||
assert_eq!(json_value, to_value(&value));
|
||||
|
||||
// Make sure we can deserialize from a `Value`.
|
||||
let v: T = from_value(json_value.clone()).unwrap();
|
||||
assert_eq!(v, *value);
|
||||
|
||||
// Make sure we can round trip back to `Value`.
|
||||
let json_value2: Value = from_value(json_value.clone()).unwrap();
|
||||
assert_eq!(json_value, json_value2);
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME (#5527): these could be merged once UFCS is finished.
|
||||
fn test_parse_err<'a, T>(errors: &[(&'a str, Error)])
|
||||
where T: Debug + de::Deserialize,
|
||||
{
|
||||
for &(s, ref err) in errors {
|
||||
let v: Result<T, Error> = from_str(s);
|
||||
assert_eq!(v.unwrap_err(), *err);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_null() {
|
||||
test_parse_err::<()>(&[
|
||||
("n", Error::SyntaxError(ErrorCode::ExpectedSomeIdent, 1, 2)),
|
||||
("nul", Error::SyntaxError(ErrorCode::ExpectedSomeIdent, 1, 4)),
|
||||
("nulla", Error::SyntaxError(ErrorCode::TrailingCharacters, 1, 5)),
|
||||
]);
|
||||
|
||||
test_parse_ok(&[
|
||||
("null", ()),
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_bool() {
|
||||
test_parse_err::<bool>(&[
|
||||
("t", Error::SyntaxError(ErrorCode::ExpectedSomeIdent, 1, 2)),
|
||||
("truz", Error::SyntaxError(ErrorCode::ExpectedSomeIdent, 1, 4)),
|
||||
("f", Error::SyntaxError(ErrorCode::ExpectedSomeIdent, 1, 2)),
|
||||
("faz", Error::SyntaxError(ErrorCode::ExpectedSomeIdent, 1, 3)),
|
||||
("truea", Error::SyntaxError(ErrorCode::TrailingCharacters, 1, 5)),
|
||||
("falsea", Error::SyntaxError(ErrorCode::TrailingCharacters, 1, 6)),
|
||||
]);
|
||||
|
||||
test_parse_ok(&[
|
||||
("true", true),
|
||||
(" true ", true),
|
||||
("false", false),
|
||||
(" false ", false),
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_number_errors() {
|
||||
test_parse_err::<f64>(&[
|
||||
("+", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 1)),
|
||||
(".", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 1)),
|
||||
("-", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 2)),
|
||||
("00", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 2)),
|
||||
("1.", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 3)),
|
||||
("1e", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 3)),
|
||||
("1e+", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 4)),
|
||||
("1a", Error::SyntaxError(ErrorCode::TrailingCharacters, 1, 2)),
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_i64() {
|
||||
test_parse_ok(&[
|
||||
("3", 3),
|
||||
("-2", -2),
|
||||
("-1234", -1234),
|
||||
(" -1234 ", -1234),
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_f64() {
|
||||
test_parse_ok(&[
|
||||
("3.0", 3.0f64),
|
||||
("3.1", 3.1),
|
||||
("-1.2", -1.2),
|
||||
("0.4", 0.4),
|
||||
("0.4e5", 0.4e5),
|
||||
("0.4e15", 0.4e15),
|
||||
("0.4e-01", 0.4e-01),
|
||||
(" 0.4e-01 ", 0.4e-01),
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_string() {
|
||||
test_parse_err::<String>(&[
|
||||
("\"", Error::SyntaxError(ErrorCode::EOFWhileParsingString, 1, 2)),
|
||||
("\"lol", Error::SyntaxError(ErrorCode::EOFWhileParsingString, 1, 5)),
|
||||
("\"lol\"a", Error::SyntaxError(ErrorCode::TrailingCharacters, 1, 6)),
|
||||
]);
|
||||
|
||||
test_parse_ok(&[
|
||||
("\"\"", "".to_string()),
|
||||
("\"foo\"", "foo".to_string()),
|
||||
(" \"foo\" ", "foo".to_string()),
|
||||
("\"\\\"\"", "\"".to_string()),
|
||||
("\"\\b\"", "\x08".to_string()),
|
||||
("\"\\n\"", "\n".to_string()),
|
||||
("\"\\r\"", "\r".to_string()),
|
||||
("\"\\t\"", "\t".to_string()),
|
||||
("\"\\u12ab\"", "\u{12ab}".to_string()),
|
||||
("\"\\uAB12\"", "\u{AB12}".to_string()),
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_list() {
|
||||
test_parse_err::<Vec<f64>>(&[
|
||||
("[", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 2)),
|
||||
("[ ", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 3)),
|
||||
("[1", Error::SyntaxError(ErrorCode::EOFWhileParsingList, 1, 3)),
|
||||
("[1,", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 4)),
|
||||
("[1,]", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 4)),
|
||||
("[1 2]", Error::SyntaxError(ErrorCode::ExpectedListCommaOrEnd, 1, 4)),
|
||||
("[]a", Error::SyntaxError(ErrorCode::TrailingCharacters, 1, 3)),
|
||||
]);
|
||||
|
||||
test_parse_ok(&[
|
||||
("[]", vec![]),
|
||||
("[ ]", vec![]),
|
||||
("[null]", vec![()]),
|
||||
(" [ null ] ", vec![()]),
|
||||
]);
|
||||
|
||||
test_parse_ok(&[
|
||||
("[true]", vec![true]),
|
||||
]);
|
||||
|
||||
test_parse_ok(&[
|
||||
("[3,1]", vec![3, 1]),
|
||||
(" [ 3 , 1 ] ", vec![3, 1]),
|
||||
]);
|
||||
|
||||
test_parse_ok(&[
|
||||
("[[3], [1, 2]]", vec![vec![3], vec![1, 2]]),
|
||||
]);
|
||||
|
||||
test_parse_ok(&[
|
||||
("[1]", (1,)),
|
||||
]);
|
||||
|
||||
test_parse_ok(&[
|
||||
("[1, 2]", (1, 2)),
|
||||
]);
|
||||
|
||||
test_parse_ok(&[
|
||||
("[1, 2, 3]", (1, 2, 3)),
|
||||
]);
|
||||
|
||||
test_parse_ok(&[
|
||||
("[1, [2, 3]]", (1, (2, 3))),
|
||||
]);
|
||||
|
||||
let v: () = from_str("[]").unwrap();
|
||||
assert_eq!(v, ());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_object() {
|
||||
test_parse_err::<BTreeMap<String, u32>>(&[
|
||||
("{", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 2)),
|
||||
("{ ", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 3)),
|
||||
("{1", Error::SyntaxError(ErrorCode::KeyMustBeAString, 1, 2)),
|
||||
("{ \"a\"", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 1, 6)),
|
||||
("{\"a\"", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 1, 5)),
|
||||
("{\"a\" ", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 1, 6)),
|
||||
("{\"a\" 1", Error::SyntaxError(ErrorCode::ExpectedColon, 1, 6)),
|
||||
("{\"a\":", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 6)),
|
||||
("{\"a\":1", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 1, 7)),
|
||||
("{\"a\":1 1", Error::SyntaxError(ErrorCode::ExpectedObjectCommaOrEnd, 1, 8)),
|
||||
("{\"a\":1,", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 8)),
|
||||
("{}a", Error::SyntaxError(ErrorCode::TrailingCharacters, 1, 3)),
|
||||
]);
|
||||
|
||||
test_parse_ok(&[
|
||||
("{}", treemap!()),
|
||||
("{ }", treemap!()),
|
||||
(
|
||||
"{\"a\":3}",
|
||||
treemap!("a".to_string() => 3)
|
||||
),
|
||||
(
|
||||
"{ \"a\" : 3 }",
|
||||
treemap!("a".to_string() => 3)
|
||||
),
|
||||
(
|
||||
"{\"a\":3,\"b\":4}",
|
||||
treemap!("a".to_string() => 3, "b".to_string() => 4)
|
||||
),
|
||||
(
|
||||
" { \"a\" : 3 , \"b\" : 4 } ",
|
||||
treemap!("a".to_string() => 3, "b".to_string() => 4),
|
||||
),
|
||||
]);
|
||||
|
||||
test_parse_ok(&[
|
||||
(
|
||||
"{\"a\": {\"b\": 3, \"c\": 4}}",
|
||||
treemap!("a".to_string() => treemap!("b".to_string() => 3, "c".to_string() => 4)),
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_struct() {
|
||||
test_parse_err::<Outer>(&[
|
||||
("[]", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 0, 0)),
|
||||
("{}", Error::MissingFieldError("inner")),
|
||||
("{\"inner\": true}", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 0, 0)),
|
||||
]);
|
||||
|
||||
test_parse_ok(&[
|
||||
(
|
||||
"{
|
||||
\"inner\": []
|
||||
}",
|
||||
Outer {
|
||||
inner: vec![]
|
||||
},
|
||||
),
|
||||
(
|
||||
"{
|
||||
\"inner\": [
|
||||
{ \"a\": null, \"b\": 2, \"c\": [\"abc\", \"xyz\"] }
|
||||
]
|
||||
}",
|
||||
Outer {
|
||||
inner: vec![
|
||||
Inner { a: (), b: 2, c: vec!["abc".to_string(), "xyz".to_string()] }
|
||||
]
|
||||
},
|
||||
)
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_option() {
|
||||
test_parse_ok(&[
|
||||
("null", None::<String>),
|
||||
("\"jodhpurs\"", Some("jodhpurs".to_string())),
|
||||
]);
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
#[derive_serialize]
|
||||
#[derive_deserialize]
|
||||
struct Foo {
|
||||
x: Option<isize>,
|
||||
}
|
||||
|
||||
/*
|
||||
let value: Foo = from_str("{}").unwrap();
|
||||
assert_eq!(value, Foo { x: None });
|
||||
*/
|
||||
|
||||
test_parse_ok(&[
|
||||
("{\"x\": null}", Foo { x: None }),
|
||||
("{\"x\": 5}", Foo { x: Some(5) }),
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_enum() {
|
||||
test_parse_err::<Animal>(&[
|
||||
("{}", Error::SyntaxError(ErrorCode::EOFWhileParsingString, 1, 3)),
|
||||
("{\"unknown\":[]}", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 0, 0)),
|
||||
("{\"Dog\":{}}", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 0, 0)),
|
||||
("{\"Frog\":{}}", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 9)),
|
||||
("{\"Cat\":[]}", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 8)),
|
||||
]);
|
||||
|
||||
test_parse_ok(&[
|
||||
("{\"Dog\":[]}", Animal::Dog),
|
||||
(" { \"Dog\" : [ ] } ", Animal::Dog),
|
||||
(
|
||||
"{\"Frog\":[\"Henry\",[]]}",
|
||||
Animal::Frog("Henry".to_string(), vec![]),
|
||||
),
|
||||
(
|
||||
" { \"Frog\": [ \"Henry\" , [ 349, 102 ] ] } ",
|
||||
Animal::Frog("Henry".to_string(), vec![349, 102]),
|
||||
),
|
||||
(
|
||||
"{\"Cat\": {\"age\": 5, \"name\": \"Kate\"}}",
|
||||
Animal::Cat { age: 5, name: "Kate".to_string() },
|
||||
),
|
||||
(
|
||||
" { \"Cat\" : { \"age\" : 5 , \"name\" : \"Kate\" } } ",
|
||||
Animal::Cat { age: 5, name: "Kate".to_string() },
|
||||
),
|
||||
]);
|
||||
|
||||
test_parse_ok(&[
|
||||
(
|
||||
concat!(
|
||||
"{",
|
||||
" \"a\": {\"Dog\": []},",
|
||||
" \"b\": {\"Frog\":[\"Henry\", []]}",
|
||||
"}"
|
||||
),
|
||||
treemap!(
|
||||
"a".to_string() => Animal::Dog,
|
||||
"b".to_string() => Animal::Frog("Henry".to_string(), vec![])
|
||||
)
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_trailing_whitespace() {
|
||||
test_parse_ok(&[
|
||||
("[1, 2] ", vec![1, 2]),
|
||||
("[1, 2]\n", vec![1, 2]),
|
||||
("[1, 2]\t", vec![1, 2]),
|
||||
("[1, 2]\t \n", vec![1, 2]),
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multiline_errors() {
|
||||
test_parse_err::<BTreeMap<String, String>>(&[
|
||||
("{\n \"foo\":\n \"bar\"", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 3, 8)),
|
||||
]);
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
extern crate serde;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use serde::json::value::Value;
|
||||
use serde::json::builder::{ArrayBuilder, ObjectBuilder};
|
||||
|
||||
#[test]
|
||||
fn test_array_builder() {
|
||||
let value = ArrayBuilder::new().unwrap();
|
||||
assert_eq!(value, Value::Array(Vec::new()));
|
||||
|
||||
let value = ArrayBuilder::new()
|
||||
.push(1)
|
||||
.push(2)
|
||||
.push(3)
|
||||
.unwrap();
|
||||
assert_eq!(value, Value::Array(vec!(Value::I64(1), Value::I64(2), Value::I64(3))));
|
||||
|
||||
let value = ArrayBuilder::new()
|
||||
.push_array(|bld| bld.push(1).push(2).push(3))
|
||||
.unwrap();
|
||||
assert_eq!(value, Value::Array(vec!(Value::Array(vec!(Value::I64(1), Value::I64(2), Value::I64(3))))));
|
||||
|
||||
let value = ArrayBuilder::new()
|
||||
.push_object(|bld|
|
||||
bld
|
||||
.insert("a".to_string(), 1)
|
||||
.insert("b".to_string(), 2))
|
||||
.unwrap();
|
||||
|
||||
let mut map = BTreeMap::new();
|
||||
map.insert("a".to_string(), Value::I64(1));
|
||||
map.insert("b".to_string(), Value::I64(2));
|
||||
assert_eq!(value, Value::Array(vec!(Value::Object(map))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_object_builder() {
|
||||
let value = ObjectBuilder::new().unwrap();
|
||||
assert_eq!(value, Value::Object(BTreeMap::new()));
|
||||
|
||||
let value = ObjectBuilder::new()
|
||||
.insert("a".to_string(), 1)
|
||||
.insert("b".to_string(), 2)
|
||||
.unwrap();
|
||||
|
||||
let mut map = BTreeMap::new();
|
||||
map.insert("a".to_string(), Value::I64(1));
|
||||
map.insert("b".to_string(), Value::I64(2));
|
||||
assert_eq!(value, Value::Object(map));
|
||||
}
|
||||
@@ -0,0 +1,406 @@
|
||||
#![feature(custom_derive, plugin)]
|
||||
#![plugin(serde_macros)]
|
||||
|
||||
extern crate serde;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use serde::json::{self, Value};
|
||||
|
||||
macro_rules! btreemap {
|
||||
() => {
|
||||
BTreeMap::new()
|
||||
};
|
||||
($($key:expr => $value:expr),+) => {
|
||||
{
|
||||
let mut map = BTreeMap::new();
|
||||
$(map.insert($key, $value);)+
|
||||
map
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
trait Trait {
|
||||
type Type;
|
||||
}
|
||||
*/
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive_serialize]
|
||||
#[derive_deserialize]
|
||||
struct NamedUnit;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive_serialize]
|
||||
enum SerEnum<'a, B: 'a, C: /* Trait + */ 'a, D> where D: /* Trait + */ 'a {
|
||||
Unit,
|
||||
Seq(
|
||||
i8,
|
||||
B,
|
||||
&'a C,
|
||||
//C::Type,
|
||||
&'a mut D,
|
||||
//<D as Trait>::Type,
|
||||
),
|
||||
Map {
|
||||
a: i8,
|
||||
b: B,
|
||||
c: &'a C,
|
||||
//d: C::Type,
|
||||
e: &'a mut D,
|
||||
//f: <D as Trait>::Type,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive_deserialize]
|
||||
enum DeEnum<B, C: /* Trait */, D> /* where D: Trait */ {
|
||||
Unit,
|
||||
Seq(
|
||||
i8,
|
||||
B,
|
||||
C,
|
||||
//C::Type,
|
||||
D,
|
||||
//<D as Trait>::Type,
|
||||
),
|
||||
Map {
|
||||
a: i8,
|
||||
b: B,
|
||||
c: C,
|
||||
//d: C::Type,
|
||||
e: D,
|
||||
//f: <D as Trait>::Type,
|
||||
},
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_named_unit() {
|
||||
let named_unit = NamedUnit;
|
||||
|
||||
assert_eq!(
|
||||
json::to_string(&named_unit).unwrap(),
|
||||
"null".to_string()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
json::to_value(&named_unit),
|
||||
Value::Null
|
||||
);
|
||||
|
||||
let v = json::from_str("null").unwrap();
|
||||
assert_eq!(v, named_unit);
|
||||
|
||||
let v = json::from_value(Value::Null).unwrap();
|
||||
assert_eq!(v, named_unit);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ser_named_tuple() {
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive_serialize]
|
||||
struct NamedTuple<'a, 'b, A: 'a, B: 'b, C>(&'a A, &'b mut B, C);
|
||||
|
||||
let a = 5;
|
||||
let mut b = 6;
|
||||
let c = 7;
|
||||
let named_tuple = NamedTuple(&a, &mut b, c);
|
||||
|
||||
assert_eq!(
|
||||
json::to_string(&named_tuple).unwrap(),
|
||||
"[5,6,7]"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
json::to_value(&named_tuple),
|
||||
Value::Array(vec![Value::I64(5), Value::I64(6), Value::I64(7)])
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_de_named_tuple() {
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive_deserialize]
|
||||
struct NamedTuple<A, B, C>(A, B, C);
|
||||
|
||||
assert_eq!(
|
||||
json::from_str("[1,2,3]").unwrap(),
|
||||
NamedTuple(1, 2, 3)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
json::from_str("[1,2,3]").unwrap(),
|
||||
Value::Array(vec![
|
||||
Value::I64(1),
|
||||
Value::I64(2),
|
||||
Value::I64(3),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ser_named_map() {
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive_serialize]
|
||||
struct NamedMap<'a, 'b, A: 'a, B: 'b, C> {
|
||||
a: &'a A,
|
||||
b: &'b mut B,
|
||||
c: C,
|
||||
}
|
||||
|
||||
let a = 5;
|
||||
let mut b = 6;
|
||||
let c = 7;
|
||||
let named_map = NamedMap {
|
||||
a: &a,
|
||||
b: &mut b,
|
||||
c: c,
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
json::to_string(&named_map).unwrap(),
|
||||
"{\"a\":5,\"b\":6,\"c\":7}"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
json::to_value(&named_map),
|
||||
Value::Object(btreemap![
|
||||
"a".to_string() => Value::I64(5),
|
||||
"b".to_string() => Value::I64(6),
|
||||
"c".to_string() => Value::I64(7)
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_de_named_map() {
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive_deserialize]
|
||||
struct NamedMap<A, B, C> {
|
||||
a: A,
|
||||
b: B,
|
||||
c: C,
|
||||
}
|
||||
|
||||
let v = NamedMap {
|
||||
a: 5,
|
||||
b: 6,
|
||||
c: 7,
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
json::from_str("{\"a\":5,\"b\":6,\"c\":7}").unwrap(),
|
||||
v
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
json::from_value(Value::Object(btreemap![
|
||||
"a".to_string() => Value::I64(5),
|
||||
"b".to_string() => Value::I64(6),
|
||||
"c".to_string() => Value::I64(7)
|
||||
])).unwrap(),
|
||||
v
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ser_enum_unit() {
|
||||
assert_eq!(
|
||||
json::to_string(&SerEnum::Unit::<u32, u32, u32>).unwrap(),
|
||||
"{\"Unit\":[]}"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
json::to_value(&SerEnum::Unit::<u32, u32, u32>),
|
||||
Value::Object(btreemap!(
|
||||
"Unit".to_string() => Value::Array(vec![]))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ser_enum_seq() {
|
||||
let a = 1;
|
||||
let b = 2;
|
||||
let c = 3;
|
||||
//let d = 4;
|
||||
let mut e = 5;
|
||||
//let f = 6;
|
||||
|
||||
assert_eq!(
|
||||
json::to_string(&SerEnum::Seq(
|
||||
a,
|
||||
b,
|
||||
&c,
|
||||
//d,
|
||||
&mut e,
|
||||
//f,
|
||||
)).unwrap(),
|
||||
"{\"Seq\":[1,2,3,5]}".to_string()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
json::to_value(&SerEnum::Seq(
|
||||
a,
|
||||
b,
|
||||
&c,
|
||||
//d,
|
||||
&mut e,
|
||||
//e,
|
||||
)),
|
||||
Value::Object(btreemap!(
|
||||
"Seq".to_string() => Value::Array(vec![
|
||||
Value::I64(1),
|
||||
Value::I64(2),
|
||||
Value::I64(3),
|
||||
//Value::I64(4),
|
||||
Value::I64(5),
|
||||
//Value::I64(6),
|
||||
])
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ser_enum_map() {
|
||||
let a = 1;
|
||||
let b = 2;
|
||||
let c = 3;
|
||||
//let d = 4;
|
||||
let mut e = 5;
|
||||
//let f = 6;
|
||||
|
||||
assert_eq!(
|
||||
json::to_string(&SerEnum::Map {
|
||||
a: a,
|
||||
b: b,
|
||||
c: &c,
|
||||
//d: d,
|
||||
e: &mut e,
|
||||
//f: f,
|
||||
}).unwrap(),
|
||||
"{\"Map\":{\"a\":1,\"b\":2,\"c\":3,\"e\":5}}".to_string()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
json::to_value(&SerEnum::Map {
|
||||
a: a,
|
||||
b: b,
|
||||
c: &c,
|
||||
//d: d,
|
||||
e: &mut e,
|
||||
//f: f,
|
||||
}),
|
||||
Value::Object(btreemap!(
|
||||
"Map".to_string() => Value::Object(btreemap![
|
||||
"a".to_string() => Value::I64(1),
|
||||
"b".to_string() => Value::I64(2),
|
||||
"c".to_string() => Value::I64(3),
|
||||
//"d".to_string() => Value::I64(4)
|
||||
"e".to_string() => Value::I64(5)
|
||||
//"f".to_string() => Value::I64(6)
|
||||
])
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_de_enum_unit() {
|
||||
assert_eq!(
|
||||
json::from_str("{\"Unit\":[]}").unwrap(),
|
||||
DeEnum::Unit::<u32, u32, u32>
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
json::from_value(Value::Object(btreemap!(
|
||||
"Unit".to_string() => Value::Array(vec![]))
|
||||
)).unwrap(),
|
||||
DeEnum::Unit::<u32, u32, u32>
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_de_enum_seq() {
|
||||
let a = 1;
|
||||
let b = 2;
|
||||
let c = 3;
|
||||
//let d = 4;
|
||||
let e = 5;
|
||||
//let f = 6;
|
||||
|
||||
assert_eq!(
|
||||
json::from_str("{\"Seq\":[1,2,3,5]}").unwrap(),
|
||||
DeEnum::Seq(
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
//d,
|
||||
e,
|
||||
//f,
|
||||
)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
json::from_value(Value::Object(btreemap!(
|
||||
"Seq".to_string() => Value::Array(vec![
|
||||
Value::I64(1),
|
||||
Value::I64(2),
|
||||
Value::I64(3),
|
||||
//Value::I64(4),
|
||||
Value::I64(5),
|
||||
//Value::I64(6),
|
||||
])
|
||||
))).unwrap(),
|
||||
DeEnum::Seq(
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
//d,
|
||||
e,
|
||||
//e,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_de_enum_map() {
|
||||
let a = 1;
|
||||
let b = 2;
|
||||
let c = 3;
|
||||
//let d = 4;
|
||||
let e = 5;
|
||||
//let f = 6;
|
||||
|
||||
assert_eq!(
|
||||
json::from_str("{\"Map\":{\"a\":1,\"b\":2,\"c\":3,\"e\":5}}").unwrap(),
|
||||
DeEnum::Map {
|
||||
a: a,
|
||||
b: b,
|
||||
c: c,
|
||||
//d: d,
|
||||
e: e,
|
||||
//f: f,
|
||||
}
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
json::from_value(Value::Object(btreemap!(
|
||||
"Map".to_string() => Value::Object(btreemap![
|
||||
"a".to_string() => Value::I64(1),
|
||||
"b".to_string() => Value::I64(2),
|
||||
"c".to_string() => Value::I64(3),
|
||||
//"d".to_string() => Value::I64(4)
|
||||
"e".to_string() => Value::I64(5)
|
||||
//"f".to_string() => Value::I64(6)
|
||||
])
|
||||
))).unwrap(),
|
||||
DeEnum::Map {
|
||||
a: a,
|
||||
b: b,
|
||||
c: c,
|
||||
//d: d,
|
||||
e: e,
|
||||
//f: f,
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,544 @@
|
||||
#![feature(custom_derive, plugin, test)]
|
||||
#![plugin(serde_macros)]
|
||||
|
||||
extern crate test;
|
||||
extern crate serde;
|
||||
|
||||
use std::vec;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use serde::ser::{Serialize, Serializer, Visitor, SeqVisitor, MapVisitor};
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
pub enum Token<'a> {
|
||||
Bool(bool),
|
||||
Isize(isize),
|
||||
I8(i8),
|
||||
I16(i16),
|
||||
I32(i32),
|
||||
I64(i64),
|
||||
Usize(usize),
|
||||
U8(u8),
|
||||
U16(u16),
|
||||
U32(u32),
|
||||
U64(u64),
|
||||
F32(f32),
|
||||
F64(f64),
|
||||
Char(char),
|
||||
Str(&'a str),
|
||||
|
||||
Option(bool),
|
||||
|
||||
Unit,
|
||||
NamedUnit(&'a str),
|
||||
EnumUnit(&'a str, &'a str),
|
||||
|
||||
SeqStart(usize),
|
||||
NamedSeqStart(&'a str, usize),
|
||||
EnumSeqStart(&'a str, &'a str, usize),
|
||||
SeqSep(bool),
|
||||
SeqEnd,
|
||||
|
||||
MapStart(usize),
|
||||
NamedMapStart(&'a str, usize),
|
||||
EnumMapStart(&'a str, &'a str, usize),
|
||||
MapSep(bool),
|
||||
MapEnd,
|
||||
}
|
||||
|
||||
struct AssertSerializer<'a> {
|
||||
iter: vec::IntoIter<Token<'a>>,
|
||||
}
|
||||
|
||||
impl<'a> AssertSerializer<'a> {
|
||||
fn new(values: Vec<Token<'a>>) -> AssertSerializer {
|
||||
AssertSerializer {
|
||||
iter: values.into_iter(),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_sequence<V>(&mut self, mut visitor: V) -> Result<(), ()>
|
||||
where V: SeqVisitor
|
||||
{
|
||||
while let Some(()) = try!(visitor.visit(self)) { }
|
||||
|
||||
assert_eq!(self.iter.next(), Some(Token::SeqEnd));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_mapping<V>(&mut self, mut visitor: V) -> Result<(), ()>
|
||||
where V: MapVisitor
|
||||
{
|
||||
while let Some(()) = try!(visitor.visit(self)) { }
|
||||
|
||||
assert_eq!(self.iter.next(), Some(Token::MapEnd));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Serializer for AssertSerializer<'a> {
|
||||
type Value = ();
|
||||
type Error = ();
|
||||
|
||||
fn visit<T: Serialize>(&mut self, value: &T) -> Result<(), ()> {
|
||||
value.visit(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Visitor for AssertSerializer<'a> {
|
||||
type Value = ();
|
||||
type Error = ();
|
||||
|
||||
fn visit_unit(&mut self) -> Result<(), ()> {
|
||||
assert_eq!(self.iter.next(), Some(Token::Unit));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_named_unit(&mut self, name: &str) -> Result<(), ()> {
|
||||
assert_eq!(self.iter.next().unwrap(), Token::NamedUnit(name));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_enum_unit(&mut self, name: &str, variant: &str) -> Result<(), ()> {
|
||||
assert_eq!(self.iter.next().unwrap(), Token::EnumUnit(name, variant));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_bool(&mut self, v: bool) -> Result<(), ()> {
|
||||
assert_eq!(self.iter.next(), Some(Token::Bool(v)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_isize(&mut self, v: isize) -> Result<(), ()> {
|
||||
assert_eq!(self.iter.next(), Some(Token::Isize(v)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_i8(&mut self, v: i8) -> Result<(), ()> {
|
||||
assert_eq!(self.iter.next(), Some(Token::I8(v)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_i16(&mut self, v: i16) -> Result<(), ()> {
|
||||
assert_eq!(self.iter.next(), Some(Token::I16(v)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_i32(&mut self, v: i32) -> Result<(), ()> {
|
||||
assert_eq!(self.iter.next(), Some(Token::I32(v)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_i64(&mut self, v: i64) -> Result<(), ()> {
|
||||
assert_eq!(self.iter.next(), Some(Token::I64(v)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_usize(&mut self, v: usize) -> Result<(), ()> {
|
||||
assert_eq!(self.iter.next(), Some(Token::Usize(v)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_u8(&mut self, v: u8) -> Result<(), ()> {
|
||||
assert_eq!(self.iter.next(), Some(Token::U8(v)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_u16(&mut self, v: u16) -> Result<(), ()> {
|
||||
assert_eq!(self.iter.next(), Some(Token::U16(v)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_u32(&mut self, v: u32) -> Result<(), ()> {
|
||||
assert_eq!(self.iter.next(), Some(Token::U32(v)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_u64(&mut self, v: u64) -> Result<(), ()> {
|
||||
assert_eq!(self.iter.next(), Some(Token::U64(v)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_f32(&mut self, v: f32) -> Result<(), ()> {
|
||||
assert_eq!(self.iter.next(), Some(Token::F32(v)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_f64(&mut self, v: f64) -> Result<(), ()> {
|
||||
assert_eq!(self.iter.next(), Some(Token::F64(v)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_char(&mut self, v: char) -> Result<(), ()> {
|
||||
assert_eq!(self.iter.next(), Some(Token::Char(v)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_str(&mut self, v: &str) -> Result<(), ()> {
|
||||
assert_eq!(self.iter.next().unwrap(), Token::Str(v));
|
||||
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<(), ()>
|
||||
where V: SeqVisitor
|
||||
{
|
||||
let (len, _) = visitor.size_hint();
|
||||
|
||||
assert_eq!(self.iter.next(), Some(Token::SeqStart(len)));
|
||||
|
||||
self.visit_sequence(visitor)
|
||||
}
|
||||
|
||||
fn visit_named_seq<V>(&mut self, name: &str, visitor: V) -> Result<(), ()>
|
||||
where V: SeqVisitor
|
||||
{
|
||||
let (len, _) = visitor.size_hint();
|
||||
|
||||
assert_eq!(self.iter.next().unwrap(), Token::NamedSeqStart(name, len));
|
||||
|
||||
self.visit_sequence(visitor)
|
||||
}
|
||||
|
||||
fn visit_enum_seq<V>(&mut self,
|
||||
name: &str,
|
||||
variant: &str,
|
||||
visitor: V) -> Result<(), ()>
|
||||
where V: SeqVisitor
|
||||
{
|
||||
let (len, _) = visitor.size_hint();
|
||||
|
||||
assert_eq!(self.iter.next().unwrap(), Token::EnumSeqStart(name, variant, len));
|
||||
|
||||
self.visit_sequence(visitor)
|
||||
}
|
||||
|
||||
fn visit_seq_elt<T>(&mut self, first: bool, value: T) -> Result<(), ()>
|
||||
where T: Serialize
|
||||
{
|
||||
assert_eq!(self.iter.next(), Some(Token::SeqSep(first)));
|
||||
value.visit(self)
|
||||
}
|
||||
|
||||
fn visit_map<V>(&mut self, visitor: V) -> Result<(), ()>
|
||||
where V: MapVisitor
|
||||
{
|
||||
let (len, _) = visitor.size_hint();
|
||||
|
||||
assert_eq!(self.iter.next(), Some(Token::MapStart(len)));
|
||||
|
||||
self.visit_mapping(visitor)
|
||||
}
|
||||
|
||||
fn visit_named_map<V>(&mut self, name: &str, visitor: V) -> Result<(), ()>
|
||||
where V: MapVisitor
|
||||
{
|
||||
let (len, _) = visitor.size_hint();
|
||||
|
||||
assert_eq!(self.iter.next().unwrap(), Token::NamedMapStart(name, len));
|
||||
|
||||
self.visit_mapping(visitor)
|
||||
}
|
||||
|
||||
fn visit_enum_map<V>(&mut self,
|
||||
name: &str,
|
||||
variant: &str,
|
||||
visitor: V) -> Result<(), ()>
|
||||
where V: MapVisitor
|
||||
{
|
||||
let (len, _) = visitor.size_hint();
|
||||
|
||||
assert_eq!(self.iter.next().unwrap(), Token::EnumMapStart(name, variant, len));
|
||||
|
||||
self.visit_mapping(visitor)
|
||||
}
|
||||
|
||||
fn visit_map_elt<K, V>(&mut self,
|
||||
first: bool,
|
||||
key: K,
|
||||
value: V) -> Result<(), ()>
|
||||
where K: Serialize,
|
||||
V: Serialize,
|
||||
{
|
||||
assert_eq!(self.iter.next(), Some(Token::MapSep(first)));
|
||||
|
||||
try!(key.visit(self));
|
||||
value.visit(self)
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[derive_serialize]
|
||||
struct NamedUnit;
|
||||
|
||||
#[derive_serialize]
|
||||
struct NamedSeq(i32, i32, i32);
|
||||
|
||||
#[derive_serialize]
|
||||
struct NamedMap {
|
||||
a: i32,
|
||||
b: i32,
|
||||
c: i32,
|
||||
}
|
||||
|
||||
#[derive_serialize]
|
||||
enum Enum {
|
||||
Unit,
|
||||
Seq(i32, i32),
|
||||
Map { a: i32, b: i32 },
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
macro_rules! btreemap {
|
||||
() => {
|
||||
BTreeMap::new()
|
||||
};
|
||||
($($key:expr => $value:expr),+) => {
|
||||
{
|
||||
let mut map = BTreeMap::new();
|
||||
$(map.insert($key, $value);)+
|
||||
map
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! declare_test {
|
||||
($name:ident { $($value:expr => $tokens:expr,)+ }) => {
|
||||
#[test]
|
||||
fn $name() {
|
||||
$(
|
||||
let mut ser = AssertSerializer::new($tokens);
|
||||
assert_eq!(ser.visit(&$value), Ok(()));
|
||||
)+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! declare_tests {
|
||||
($($name:ident { $($value:expr => $tokens:expr,)+ })+) => {
|
||||
$(
|
||||
declare_test!($name { $($value => $tokens,)+ });
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
declare_tests! {
|
||||
test_unit {
|
||||
() => vec![Token::Unit],
|
||||
}
|
||||
test_bool {
|
||||
true => vec![Token::Bool(true)],
|
||||
false => vec![Token::Bool(false)],
|
||||
}
|
||||
test_isizes {
|
||||
0isize => vec![Token::Isize(0)],
|
||||
0i8 => vec![Token::I8(0)],
|
||||
0i16 => vec![Token::I16(0)],
|
||||
0i32 => vec![Token::I32(0)],
|
||||
0i64 => vec![Token::I64(0)],
|
||||
}
|
||||
test_usizes {
|
||||
0usize => vec![Token::Usize(0)],
|
||||
0u8 => vec![Token::U8(0)],
|
||||
0u16 => vec![Token::U16(0)],
|
||||
0u32 => vec![Token::U32(0)],
|
||||
0u64 => vec![Token::U64(0)],
|
||||
}
|
||||
test_floats {
|
||||
0f32 => vec![Token::F32(0.)],
|
||||
0f64 => vec![Token::F64(0.)],
|
||||
}
|
||||
test_char {
|
||||
'a' => vec![Token::Char('a')],
|
||||
}
|
||||
test_str {
|
||||
"abc" => 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 {
|
||||
&[0][..0] => vec![
|
||||
Token::SeqStart(0),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
&[1, 2, 3][..] => vec![
|
||||
Token::SeqStart(3),
|
||||
Token::SeqSep(true),
|
||||
Token::I32(1),
|
||||
|
||||
Token::SeqSep(false),
|
||||
Token::I32(2),
|
||||
|
||||
Token::SeqSep(false),
|
||||
Token::I32(3),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
}
|
||||
test_vec {
|
||||
Vec::<isize>::new() => vec![
|
||||
Token::SeqStart(0),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
vec![vec![], vec![1], vec![2, 3]] => vec![
|
||||
Token::SeqStart(3),
|
||||
Token::SeqSep(true),
|
||||
Token::SeqStart(0),
|
||||
Token::SeqEnd,
|
||||
|
||||
Token::SeqSep(false),
|
||||
Token::SeqStart(1),
|
||||
Token::SeqSep(true),
|
||||
Token::I32(1),
|
||||
Token::SeqEnd,
|
||||
|
||||
Token::SeqSep(false),
|
||||
Token::SeqStart(2),
|
||||
Token::SeqSep(true),
|
||||
Token::I32(2),
|
||||
|
||||
Token::SeqSep(false),
|
||||
Token::I32(3),
|
||||
Token::SeqEnd,
|
||||
Token::SeqEnd,
|
||||
],
|
||||
}
|
||||
test_tuple {
|
||||
(1,) => vec![
|
||||
Token::SeqStart(1),
|
||||
Token::SeqSep(true),
|
||||
Token::I32(1),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
(1, 2, 3) => vec![
|
||||
Token::SeqStart(3),
|
||||
Token::SeqSep(true),
|
||||
Token::I32(1),
|
||||
|
||||
Token::SeqSep(false),
|
||||
Token::I32(2),
|
||||
|
||||
Token::SeqSep(false),
|
||||
Token::I32(3),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
}
|
||||
test_btreemap {
|
||||
btreemap![1 => 2] => vec![
|
||||
Token::MapStart(1),
|
||||
Token::MapSep(true),
|
||||
Token::I32(1),
|
||||
Token::I32(2),
|
||||
Token::MapEnd,
|
||||
],
|
||||
btreemap![1 => 2, 3 => 4] => vec![
|
||||
Token::MapStart(2),
|
||||
Token::MapSep(true),
|
||||
Token::I32(1),
|
||||
Token::I32(2),
|
||||
|
||||
Token::MapSep(false),
|
||||
Token::I32(3),
|
||||
Token::I32(4),
|
||||
Token::MapEnd,
|
||||
],
|
||||
btreemap![1 => btreemap![], 2 => btreemap![3 => 4, 5 => 6]] => vec![
|
||||
Token::MapStart(2),
|
||||
Token::MapSep(true),
|
||||
Token::I32(1),
|
||||
Token::MapStart(0),
|
||||
Token::MapEnd,
|
||||
|
||||
Token::MapSep(false),
|
||||
Token::I32(2),
|
||||
Token::MapStart(2),
|
||||
Token::MapSep(true),
|
||||
Token::I32(3),
|
||||
Token::I32(4),
|
||||
|
||||
Token::MapSep(false),
|
||||
Token::I32(5),
|
||||
Token::I32(6),
|
||||
Token::MapEnd,
|
||||
Token::MapEnd,
|
||||
],
|
||||
}
|
||||
test_named_unit {
|
||||
NamedUnit => vec![Token::NamedUnit("NamedUnit")],
|
||||
}
|
||||
test_named_seq {
|
||||
NamedSeq(1, 2, 3) => vec![
|
||||
Token::NamedSeqStart("NamedSeq", 3),
|
||||
Token::SeqSep(true),
|
||||
Token::I32(1),
|
||||
|
||||
Token::SeqSep(false),
|
||||
Token::I32(2),
|
||||
|
||||
Token::SeqSep(false),
|
||||
Token::I32(3),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
}
|
||||
test_named_map {
|
||||
NamedMap { a: 1, b: 2, c: 3 } => vec![
|
||||
Token::NamedMapStart("NamedMap", 3),
|
||||
Token::MapSep(true),
|
||||
Token::Str("a"),
|
||||
Token::I32(1),
|
||||
|
||||
Token::MapSep(false),
|
||||
Token::Str("b"),
|
||||
Token::I32(2),
|
||||
|
||||
Token::MapSep(false),
|
||||
Token::Str("c"),
|
||||
Token::I32(3),
|
||||
Token::MapEnd,
|
||||
],
|
||||
}
|
||||
test_enum {
|
||||
Enum::Unit => vec![Token::EnumUnit("Enum", "Unit")],
|
||||
Enum::Seq(1, 2) => vec![
|
||||
Token::EnumSeqStart("Enum", "Seq", 2),
|
||||
Token::SeqSep(true),
|
||||
Token::I32(1),
|
||||
|
||||
Token::SeqSep(false),
|
||||
Token::I32(2),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
Enum::Map { a: 1, b: 2 } => vec![
|
||||
Token::EnumMapStart("Enum", "Map", 2),
|
||||
Token::MapSep(true),
|
||||
Token::Str("a"),
|
||||
Token::I32(1),
|
||||
|
||||
Token::MapSep(false),
|
||||
Token::Str("b"),
|
||||
Token::I32(2),
|
||||
Token::MapEnd,
|
||||
],
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user