From 4dccf8cdeca34cf582c2d6bda7f5f0e25a767844 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Fri, 13 Feb 2015 10:26:13 -0800 Subject: [PATCH] Clean up warnings in serde --- benches/bench_enum.rs | 6 +- benches/bench_log.rs | 6 +- benches/bench_map.rs | 6 +- benches/bench_struct.rs | 6 +- benches/bench_vec.rs | 6 +- benches/json.rs | 311 +++++++ serde_macros/src/lib.rs | 4 +- src/de.rs | 370 --------- src/json/mod.rs | 1712 +-------------------------------------- src/lib.rs | 16 +- src/ser.rs | 521 ------------ tests/de.rs | 368 +++++++++ tests/json.rs | 1384 +++++++++++++++++++++++++++++++ tests/json_struct.rs | 3 +- tests/ser.rs | 517 ++++++++++++ 15 files changed, 2607 insertions(+), 2629 deletions(-) create mode 100644 benches/json.rs create mode 100644 tests/de.rs create mode 100644 tests/json.rs create mode 100644 tests/ser.rs diff --git a/benches/bench_enum.rs b/benches/bench_enum.rs index 0af19c3a..7964229f 100644 --- a/benches/bench_enum.rs +++ b/benches/bench_enum.rs @@ -1,7 +1,5 @@ -#![feature(plugin)] - -#[plugin] -extern crate serde_macros; +#![feature(plugin, test)] +#![plugin(serde_macros)] extern crate serde; extern crate "rustc-serialize" as rustc_serialize; diff --git a/benches/bench_log.rs b/benches/bench_log.rs index 6194bcae..e35c53cb 100755 --- a/benches/bench_log.rs +++ b/benches/bench_log.rs @@ -1,8 +1,6 @@ -#![feature(plugin, io)] +#![feature(collections, core, io, plugin, test)] #![allow(non_camel_case_types)] - -#[plugin] -extern crate serde_macros; +#![plugin(serde_macros)] extern crate serde; extern crate "rustc-serialize" as rustc_serialize; diff --git a/benches/bench_map.rs b/benches/bench_map.rs index 3c0e60da..3017cbc3 100644 --- a/benches/bench_map.rs +++ b/benches/bench_map.rs @@ -1,7 +1,5 @@ -#![feature(plugin)] - -#[plugin] -extern crate serde_macros; +#![feature(core, plugin, test)] +#![plugin(serde_macros)] extern crate serde; extern crate "rustc-serialize" as rustc_serialize; diff --git a/benches/bench_struct.rs b/benches/bench_struct.rs index edc71000..1803de44 100644 --- a/benches/bench_struct.rs +++ b/benches/bench_struct.rs @@ -1,7 +1,5 @@ -#![feature(plugin)] - -#[plugin] -extern crate serde_macros; +#![feature(plugin, test)] +#![plugin(serde_macros)] extern crate serde; extern crate "rustc-serialize" as rustc_serialize; diff --git a/benches/bench_vec.rs b/benches/bench_vec.rs index 31910356..1b24f194 100644 --- a/benches/bench_vec.rs +++ b/benches/bench_vec.rs @@ -1,7 +1,5 @@ -#![feature(plugin)] - -#[plugin] -extern crate serde_macros; +#![feature(core, plugin, test)] +#![plugin(serde_macros)] extern crate serde; extern crate "rustc-serialize" as rustc_serialize; diff --git a/benches/json.rs b/benches/json.rs new file mode 100644 index 00000000..ab819d5b --- /dev/null +++ b/benches/json.rs @@ -0,0 +1,311 @@ +#![feature(core, plugin, test)] +#![plugin(serde_macros)] + +extern crate serde; +extern crate "rustc-serialize" as rustc_serialize; +extern crate test; + +use std::collections::BTreeMap; +use std::string; +use rustc_serialize as serialize; +use test::Bencher; + +use serde::de::Token; + +use serde::json::{Parser, Value, from_str}; + +macro_rules! treemap { + ($($k:expr => $v:expr),*) => ({ + let mut _m = ::std::collections::BTreeMap::new(); + $(_m.insert($k, $v);)* + _m + }) +} + +fn json_str(count: usize) -> string::String { + let mut src = "[".to_string(); + for _ in range(0, count) { + src.push_str(r#"{"a":true,"b":null,"c":3.1415,"d":"Hello world","e":[1,2,3]},"#); + } + src.push_str("{}]"); + src +} + +fn pretty_json_str(count: usize) -> string::String { + let mut src = "[\n".to_string(); + for _ in range(0, count) { + src.push_str( + concat!( + " {\n", + " \"a\": true,\n", + " \"b\": null,\n", + " \"c\": 3.1415,\n", + " \"d\": \"Hello world\",\n", + " \"e\": [\n", + " 1,\n", + " 2,\n", + " 3\n", + " ]\n", + " },\n" + ) + ); + } + src.push_str(" {}\n]"); + src +} + +fn encoder_json(count: usize) -> serialize::json::Json { + use rustc_serialize::json::Json; + + let mut list = vec!(); + for _ in range(0, count) { + list.push(Json::Object(treemap!( + "a".to_string() => Json::Boolean(true), + "b".to_string() => Json::Null, + "c".to_string() => Json::F64(3.1415), + "d".to_string() => Json::String("Hello world".to_string()), + "e".to_string() => Json::Array(vec!( + Json::U64(1), + Json::U64(2), + Json::U64(3) + )) + ))); + } + list.push(Json::Object(BTreeMap::new())); + Json::Array(list) +} + +fn serializer_json(count: usize) -> Value { + let mut list = vec!(); + for _ in range(0, count) { + list.push(Value::Object(treemap!( + "a".to_string() => Value::Boolean(true), + "b".to_string() => Value::Null, + "c".to_string() => Value::Floating(3.1415), + "d".to_string() => Value::String("Hello world".to_string()), + "e".to_string() => Value::Array(vec!( + Value::Integer(1), + Value::Integer(2), + Value::Integer(3) + )) + ))); + } + list.push(Value::Object(BTreeMap::new())); + Value::Array(list) +} + +fn bench_encoder(b: &mut Bencher, count: usize) { + let src = json_str(count); + let json = encoder_json(count); + + b.iter(|| { + assert_eq!(json.to_string(), src); + }); +} + +fn bench_encoder_pretty(b: &mut Bencher, count: usize) { + let src = pretty_json_str(count); + let json = encoder_json(count); + + b.iter(|| { + assert_eq!(json.pretty().to_string(), src); + }); +} + +fn bench_serializer(b: &mut Bencher, count: usize) { + let src = json_str(count); + let json = serializer_json(count); + + b.iter(|| { + assert_eq!(json.to_string(), src); + }); +} + +fn bench_serializer_pretty(b: &mut Bencher, count: usize) { + let src = pretty_json_str(count); + let json = serializer_json(count); + + b.iter(|| { + assert_eq!(json.to_pretty_string(), src); + }); +} + +fn bench_decoder(b: &mut Bencher, count: usize) { + let src = json_str(count); + let json = encoder_json(count); + b.iter(|| { + assert_eq!(json, serialize::json::Json::from_str(&src).unwrap()); + }); +} + +fn bench_deserializer(b: &mut Bencher, count: usize) { + let src = json_str(count); + let json = encoder_json(count); + b.iter(|| { + assert_eq!(json, serialize::json::Json::from_str(&src).unwrap()); + }); +} + +fn bench_decoder_streaming(b: &mut Bencher, count: usize) { + let src = json_str(count); + + b.iter( || { + use rustc_serialize::json::{Parser, JsonEvent, StackElement}; + + let mut parser = Parser::new(src.chars()); + assert_eq!(parser.next(), Some(JsonEvent::ArrayStart)); + for _ in range(0, count) { + assert_eq!(parser.next(), Some(JsonEvent::ObjectStart)); + + assert_eq!(parser.next(), Some(JsonEvent::BooleanValue(true))); + assert_eq!(parser.stack().top(), Some(StackElement::Key("a"))); + + assert_eq!(parser.next(), Some(JsonEvent::NullValue)); + assert_eq!(parser.stack().top(), Some(StackElement::Key("b"))); + + assert_eq!(parser.next(), Some(JsonEvent::F64Value(3.1415))); + assert_eq!(parser.stack().top(), Some(StackElement::Key("c"))); + + assert_eq!(parser.next(), Some(JsonEvent::StringValue("Hello world".to_string()))); + assert_eq!(parser.stack().top(), Some(StackElement::Key("d"))); + + assert_eq!(parser.next(), Some(JsonEvent::ArrayStart)); + assert_eq!(parser.stack().top(), Some(StackElement::Key("e"))); + assert_eq!(parser.next(), Some(JsonEvent::U64Value(1))); + assert_eq!(parser.next(), Some(JsonEvent::U64Value(2))); + assert_eq!(parser.next(), Some(JsonEvent::U64Value(3))); + assert_eq!(parser.next(), Some(JsonEvent::ArrayEnd)); + + assert_eq!(parser.next(), Some(JsonEvent::ObjectEnd)); + } + assert_eq!(parser.next(), Some(JsonEvent::ObjectStart)); + assert_eq!(parser.next(), Some(JsonEvent::ObjectEnd)); + assert_eq!(parser.next(), Some(JsonEvent::ArrayEnd)); + assert_eq!(parser.next(), None); + }); +} + +fn bench_deserializer_streaming(b: &mut Bencher, count: usize) { + let src = json_str(count); + + b.iter( || { + let mut parser = Parser::new(src.bytes()); + + assert_eq!(parser.next(), Some(Ok(Token::SeqStart(0)))); + for _ in range(0, count) { + assert_eq!(parser.next(), Some(Ok(Token::MapStart(0)))); + + assert_eq!(parser.next(), Some(Ok(Token::String("a".to_string())))); + assert_eq!(parser.next(), Some(Ok(Token::Bool(true)))); + + assert_eq!(parser.next(), Some(Ok(Token::String("b".to_string())))); + assert_eq!(parser.next(), Some(Ok(Token::Null))); + + assert_eq!(parser.next(), Some(Ok(Token::String("c".to_string())))); + assert_eq!(parser.next(), Some(Ok(Token::F64(3.1415)))); + + assert_eq!(parser.next(), Some(Ok(Token::String("d".to_string())))); + assert_eq!(parser.next(), Some(Ok(Token::String("Hello world".to_string())))); + + assert_eq!(parser.next(), Some(Ok(Token::String("e".to_string())))); + assert_eq!(parser.next(), Some(Ok(Token::SeqStart(0)))); + assert_eq!(parser.next(), Some(Ok(Token::I64(1)))); + assert_eq!(parser.next(), Some(Ok(Token::I64(2)))); + assert_eq!(parser.next(), Some(Ok(Token::I64(3)))); + assert_eq!(parser.next(), Some(Ok(Token::End))); + + assert_eq!(parser.next(), Some(Ok(Token::End))); + } + assert_eq!(parser.next(), Some(Ok(Token::MapStart(0)))); + assert_eq!(parser.next(), Some(Ok(Token::End))); + assert_eq!(parser.next(), Some(Ok(Token::End))); + assert_eq!(parser.next(), None); + + loop { + match parser.next() { + None => return, + Some(Ok(_)) => { } + Some(Err(err)) => { panic!("error: {:?}", err); } + } + } + }); +} + +#[bench] +fn bench_encoder_001(b: &mut Bencher) { + bench_encoder(b, 1) +} + +#[bench] +fn bench_encoder_500(b: &mut Bencher) { + bench_encoder(b, 500) +} + +#[bench] +fn bench_encoder_001_pretty(b: &mut Bencher) { + bench_encoder_pretty(b, 1) +} + +#[bench] +fn bench_encoder_500_pretty(b: &mut Bencher) { + bench_encoder_pretty(b, 500) +} + +#[bench] +fn bench_serializer_001(b: &mut Bencher) { + bench_serializer(b, 1) +} + +#[bench] +fn bench_serializer_500(b: &mut Bencher) { + bench_serializer(b, 500) +} +#[bench] +fn bench_serializer_001_pretty(b: &mut Bencher) { + bench_serializer_pretty(b, 1) +} + +#[bench] +fn bench_serializer_500_pretty(b: &mut Bencher) { + bench_serializer_pretty(b, 500) +} + +#[bench] +fn bench_decoder_001(b: &mut Bencher) { + bench_decoder(b, 1) +} + +#[bench] +fn bench_decoder_500(b: &mut Bencher) { + bench_decoder(b, 500) +} + +#[bench] +fn bench_deserializer_001(b: &mut Bencher) { + bench_deserializer(b, 1) +} + +#[bench] +fn bench_deserializer_500(b: &mut Bencher) { + bench_deserializer(b, 500) +} + +#[bench] +fn bench_decoder_001_streaming(b: &mut Bencher) { + bench_decoder_streaming(b, 1) +} + +#[bench] +fn bench_decoder_500_streaming(b: &mut Bencher) { + bench_decoder_streaming(b, 500) +} + +#[bench] +fn bench_deserializer_001_streaming(b: &mut Bencher) { + bench_deserializer_streaming(b, 1) +} + +#[bench] +fn bench_deserializer_500_streaming(b: &mut Bencher) { + bench_deserializer_streaming(b, 500) +} diff --git a/serde_macros/src/lib.rs b/serde_macros/src/lib.rs index 5ec348eb..9dacb721 100644 --- a/serde_macros/src/lib.rs +++ b/serde_macros/src/lib.rs @@ -488,13 +488,13 @@ fn deserialize_static_fields( } } -fn find_serial_name<'a, I>(mut iterator: I) -> Option where +fn find_serial_name<'a, I>(iterator: I) -> Option where I: Iterator { for at in iterator { match at.node.value.node { MetaNameValue(ref at_name, ref value) => { - match (at_name.get(), &value.node) { + match (&at_name[], &value.node) { ("serial_name", &LitStr(ref string, _)) => { attr::mark_used(at); return Some(string.clone()); diff --git a/src/de.rs b/src/de.rs index 1d8f215f..6a5668b9 100644 --- a/src/de.rs +++ b/src/de.rs @@ -1070,373 +1070,3 @@ impl, E> Deserialize for GatherTokens { Ok(tokens) } } - -////////////////////////////////////////////////////////////////////////////// - -#[cfg(test)] -mod tests { - use std::collections::BTreeMap; - use std::{option, string}; - use serialize::Decoder; - - use super::{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, RustcDecodable)] - struct Inner { - a: (), - b: usize, - c: BTreeMap>, - } - - impl< - D: Deserializer, - E - > Deserialize for Inner { - #[inline] - fn deserialize_token(d: &mut D, token: Token) -> Result { - 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, RustcDecodable)] - struct Outer { - inner: Vec, - } - - impl, E> Deserialize for Outer { - #[inline] - fn deserialize_token(d: &mut D, token: Token) -> Result { - 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, RustcDecodable)] - enum Animal { - Dog, - Frog(string::String, isize) - } - - impl, E> Deserialize for Animal { - #[inline] - fn deserialize_token(d: &mut D, token: Token) -> Result { - 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), - UnexpectedName, - ConversionError, - MissingField(&'static str), - } - - ////////////////////////////////////////////////////////////////////////////// - - struct TokenDeserializer { - tokens: Iter, - } - - impl> TokenDeserializer { - #[inline] - fn new(tokens: Iter) -> TokenDeserializer { - TokenDeserializer { - tokens: tokens, - } - } - } - - impl> Iterator for TokenDeserializer { - type Item = Result; - - #[inline] - fn next(&mut self) -> option::Option> { - self.tokens.next().map(|token| Ok(token)) - } - } - - impl> Deserializer for TokenDeserializer { - 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, Error> - >(&mut self, field: &'static str) -> Result { - 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, - - vec!( - Token::Option(true), - Token::Isize(5), - ) => Some(5), option::Option - ]); - - 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, - - vec!( - Token::SeqStart(3), - Token::Isize(5), - - Token::Isize(6), - - Token::Isize(7), - Token::End, - ) => vec!(5, 6, 7), Vec, - - - 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> - ]); - - test_value!(test_treemaps, [ - vec!( - Token::MapStart(0), - Token::End, - ) => treemap!(), BTreeMap, - - 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 - ]); -} diff --git a/src/json/mod.rs b/src/json/mod.rs index 256bdc8c..dc387734 100644 --- a/src/json/mod.rs +++ b/src/json/mod.rs @@ -61,8 +61,8 @@ To serialize using `Serialize`: ```rust #![feature(plugin)] -#[plugin] -extern crate serde_macros; +#![plugin(serde_macros)] + extern crate serde; use std::old_io::ByRefWriter; @@ -111,8 +111,8 @@ A basic `ToJson` example using a BTreeMap of attribute name / attribute value: ```rust #![feature(plugin)] -#[plugin] -extern crate serde_macros; +#![plugin(serde_macros)] + extern crate serde; use std::collections::BTreeMap; @@ -143,8 +143,8 @@ Or you can use the helper type `ObjectBuilder`: ```rust #![feature(plugin)] -#[plugin] -extern crate serde_macros; +#![plugin(serde_macros)] + extern crate serde; use serde::json::{ObjectBuilder, ToJson, Value}; @@ -174,8 +174,8 @@ To deserialize a JSON string using `Deserialize` trait: ```rust #![feature(plugin)] -#[plugin] -extern crate serde_macros; +#![plugin(serde_macros)] + extern crate serde; use serde::json; @@ -206,8 +206,8 @@ using the serialization API, using the derived serialization code. ```rust #![feature(plugin)] -#[plugin] -extern crate serde_macros; +#![plugin(serde_macros)] + extern crate serde; use serde::json; @@ -246,8 +246,8 @@ Example of `ToJson` trait implementation for TestStruct1. ```rust #![feature(plugin)] -#[plugin] -extern crate serde_macros; +#![plugin(serde_macros)] + extern crate serde; use serde::json::ToJson; @@ -315,1691 +315,3 @@ pub mod de; pub mod ser; pub mod value; pub mod error; - -#[cfg(test)] -mod tests { - use std::fmt::Debug; - use std::old_io; - use std::str; - use std::string; - use std::collections::BTreeMap; - - use de; - use ser::{Serialize, Serializer}; - use ser; - - use super::{Error, Parser, ToJson, Value, value, from_str, from_json}; - - use super::error::Error::{ - SyntaxError, - }; - - use super::error::ErrorCode::{ - EOFWhileParsingList, - EOFWhileParsingObject, - EOFWhileParsingString, - EOFWhileParsingValue, - ExpectedColon, - ExpectedListCommaOrEnd, - ExpectedObjectCommaOrEnd, - ExpectedSomeIdent, - ExpectedSomeValue, - InvalidNumber, - KeyMustBeAString, - TrailingCharacters, - }; - - macro_rules! treemap { - ($($k:expr => $v:expr),*) => ({ - let mut _m = ::std::collections::BTreeMap::new(); - $(_m.insert($k, $v);)* - _m - }) - } - - #[derive(PartialEq, Debug)] - #[derive_serialize] - #[derive_deserialize] - enum Animal { - Dog, - Frog(String, Vec) - } - - impl ToJson for Animal { - fn to_json(&self) -> Value { - match *self { - Animal::Dog => { - Value::Object( - treemap!( - "Dog".to_string() => Value::Array(vec!()) - ) - ) - } - Animal::Frog(ref x0, ref x1) => { - Value::Object( - treemap!( - "Frog".to_string() => Value::Array(vec!(x0.to_json(), x1.to_json())) - ) - ) - } - } - } - } - - #[derive(PartialEq, Debug)] - #[derive_serialize] - #[derive_deserialize] - struct Inner { - a: (), - b: usize, - c: Vec, - } - - impl ToJson for Inner { - fn to_json(&self) -> Value { - Value::Object( - treemap!( - "a".to_string() => self.a.to_json(), - "b".to_string() => self.b.to_json(), - "c".to_string() => self.c.to_json() - ) - ) - } - } - - #[derive(PartialEq, Debug)] - #[derive_serialize] - #[derive_deserialize] - struct Outer { - inner: Vec, - } - - impl ToJson for Outer { - fn to_json(&self) -> Value { - Value::Object( - treemap!( - "inner".to_string() => self.inner.to_json() - ) - ) - } - } - - fn test_encode_ok< - T: PartialEq + Debug + ToJson + ser::Serialize>, old_io::IoError> - >(errors: &[(T, &str)]) { - for &(ref value, out) in errors { - let out = out.to_string(); - - let s = super::to_string(value).unwrap(); - assert_eq!(s, out); - - let s = super::to_string(&value.to_json()).unwrap(); - assert_eq!(s, out); - } - } - - fn test_pretty_encode_ok< - T: PartialEq + Debug + ToJson + ser::Serialize>, old_io::IoError> - >(errors: &[(T, &str)]) { - for &(ref value, out) in errors { - let out = out.to_string(); - - let s = super::to_pretty_string(value).unwrap(); - assert_eq!(s, out); - - let s = super::to_pretty_string(&value.to_json()).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 = &[ - (3is, "3"), - (-2is, "-2"), - (-1234is, "-1234"), - ]; - test_encode_ok(tests); - test_pretty_encode_ok(tests); - } - - #[test] - fn test_write_f64() { - let tests = &[ - (3.0f64, "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::Boolean(false), - Value::Null, - Value::Array(vec![Value::String("foo\nbar".to_string()), Value::Floating(3.5)])]); - - test_encode_ok(&[ - (long_test_list, "[false,null,[\"foo\\nbar\",3.5]]"), - ]); - - let long_test_list = Value::Array(vec![ - Value::Boolean(false), - Value::Null, - Value::Array(vec![Value::String("foo\nbar".to_string()), Value::Floating(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(&[ - ( - (5is,), - "[5]", - ), - ]); - - test_pretty_encode_ok(&[ - ( - (5is,), - concat!( - "[\n", - " 5\n", - "]" - ), - ), - ]); - - test_encode_ok(&[ - ( - (5is, (6is, "abc")), - "[5,[6,\"abc\"]]", - ), - ]); - - test_pretty_encode_ok(&[ - ( - (5is, (6is, "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]]}"), - ]); - - 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", - "]" - ), - ), - ]); - - } - - // FIXME (#5527): these could be merged once UFCS is finished. - fn test_parse_err< - 'a, - T: Debug + de::Deserialize>, Error> - >(errors: &[(&'a str, Error)]) { - for &(s, ref err) in errors { - let v: Result = from_str(s); - assert_eq!(v.unwrap_err(), *err); - } - } - - fn test_parse_ok< - 'a, - T: PartialEq + Debug + ToJson + de::Deserialize>, Error> - >(errors: &[(&'a str, T)]) { - for &(s, ref value) in errors { - let v: T = from_str(s).unwrap(); - assert_eq!(v, *value); - - let v: Value = from_str(s).unwrap(); - assert_eq!(v, value.to_json()); - } - } - - fn test_json_deserialize_ok< - T: PartialEq + Debug + ToJson + de::Deserialize - >(errors: &[T]) { - for value in errors { - let v: T = from_json(value.to_json()).unwrap(); - assert_eq!(v, *value); - - // Make sure we can round trip back to `Json`. - let v: Value = from_json(value.to_json()).unwrap(); - assert_eq!(v, value.to_json()); - } - } - - #[test] - fn test_parse_null() { - test_parse_err::<()>(&[ - ("n", SyntaxError(ExpectedSomeIdent, 1, 2)), - ("nul", SyntaxError(ExpectedSomeIdent, 1, 4)), - ("nulla", SyntaxError(TrailingCharacters, 1, 5)), - ]); - - test_parse_ok(&[ - ("null", ()), - ]); - } - - #[test] - fn test_json_deserialize_null() { - test_json_deserialize_ok(&[ - (), - ]); - } - - #[test] - fn test_parse_bool() { - test_parse_err::(&[ - ("t", SyntaxError(ExpectedSomeIdent, 1, 2)), - ("truz", SyntaxError(ExpectedSomeIdent, 1, 4)), - ("f", SyntaxError(ExpectedSomeIdent, 1, 2)), - ("faz", SyntaxError(ExpectedSomeIdent, 1, 3)), - ("truea", SyntaxError(TrailingCharacters, 1, 5)), - ("falsea", SyntaxError(TrailingCharacters, 1, 6)), - ]); - - test_parse_ok(&[ - ("true", true), - ("false", false), - ]); - } - - #[test] - fn test_json_deserialize_bool() { - test_json_deserialize_ok(&[ - true, - false, - ]); - } - - #[test] - fn test_parse_number_errors() { - test_parse_err::(&[ - ("+", SyntaxError(ExpectedSomeValue, 1, 1)), - (".", SyntaxError(ExpectedSomeValue, 1, 1)), - ("-", SyntaxError(InvalidNumber, 1, 2)), - ("00", SyntaxError(InvalidNumber, 1, 2)), - ("1.", SyntaxError(InvalidNumber, 1, 3)), - ("1e", SyntaxError(InvalidNumber, 1, 3)), - ("1e+", SyntaxError(InvalidNumber, 1, 4)), - ("1a", SyntaxError(TrailingCharacters, 1, 2)), - ]); - } - - #[test] - fn test_parse_i64() { - test_parse_ok(&[ - ("3", 3i64), - ("-2", -2), - ("-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), - ]); - } - - #[test] - fn test_json_deserialize_numbers() { - test_json_deserialize_ok(&[ - 3.0f64, - 3.1, - -1.2, - 0.4, - 0.4e5, - 0.4e15, - 0.4e-01, - ]); - } - - #[test] - fn test_parse_string() { - test_parse_err::(&[ - ("\"", SyntaxError(EOFWhileParsingString, 1, 2)), - ("\"lol", SyntaxError(EOFWhileParsingString, 1, 5)), - ("\"lol\"a", SyntaxError(TrailingCharacters, 1, 6)), - ]); - - test_parse_ok(&[ - ("\"\"", "".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_json_deserialize_str() { - test_json_deserialize_ok(&[ - "".to_string(), - "foo".to_string(), - "\"".to_string(), - "\x08".to_string(), - "\n".to_string(), - "\r".to_string(), - "\t".to_string(), - "\u{12ab}".to_string(), - "\u{AB12}".to_string(), - ]); - } - - #[test] - fn test_parse_list() { - test_parse_err::>(&[ - ("[", SyntaxError(EOFWhileParsingValue, 1, 2)), - ("[ ", SyntaxError(EOFWhileParsingValue, 1, 3)), - ("[1", SyntaxError(EOFWhileParsingList, 1, 3)), - ("[1,", SyntaxError(EOFWhileParsingValue, 1, 4)), - ("[1,]", SyntaxError(ExpectedSomeValue, 1, 4)), - ("[1 2]", SyntaxError(ExpectedListCommaOrEnd, 1, 4)), - ("[]a", SyntaxError(TrailingCharacters, 1, 3)), - ]); - - test_parse_ok(&[ - ("[]", vec!()), - ("[ ]", vec!()), - ("[null]", vec!(())), - ("[ null ]", vec!(())), - ]); - - test_parse_ok(&[ - ("[true]", vec!(true)), - ]); - - test_parse_ok(&[ - ("[3,1]", vec!(3is, 1)), - ("[ 3 , 1 ]", vec!(3is, 1)), - ]); - - test_parse_ok(&[ - ("[[3], [1, 2]]", vec!(vec!(3is), vec!(1, 2))), - ]); - - let v: () = from_str("[]").unwrap(); - assert_eq!(v, ()); - - test_parse_ok(&[ - ("[1, 2, 3]", (1us, 2us, 3us)), - ]); - } - - #[test] - fn test_json_deserialize_list() { - test_json_deserialize_ok(&[ - vec!(), - vec!(()), - ]); - - test_json_deserialize_ok(&[ - vec!(true), - ]); - - test_json_deserialize_ok(&[ - vec!(3is, 1), - ]); - - test_json_deserialize_ok(&[ - vec!(vec!(3is), vec!(1, 2)), - ]); - } - - #[test] - fn test_parse_object() { - test_parse_err::>(&[ - ("{", SyntaxError(EOFWhileParsingString, 1, 2)), - ("{ ", SyntaxError(EOFWhileParsingString, 1, 3)), - ("{1", SyntaxError(KeyMustBeAString, 1, 2)), - ("{ \"a\"", SyntaxError(EOFWhileParsingObject, 1, 6)), - ("{\"a\"", SyntaxError(EOFWhileParsingObject, 1, 5)), - ("{\"a\" ", SyntaxError(EOFWhileParsingObject, 1, 6)), - ("{\"a\" 1", SyntaxError(ExpectedColon, 1, 6)), - ("{\"a\":", SyntaxError(EOFWhileParsingValue, 1, 6)), - ("{\"a\":1", SyntaxError(EOFWhileParsingObject, 1, 7)), - ("{\"a\":1 1", SyntaxError(ExpectedObjectCommaOrEnd, 1, 8)), - ("{\"a\":1,", SyntaxError(EOFWhileParsingString, 1, 8)), - ("{}a", SyntaxError(TrailingCharacters, 1, 3)), - ]); - - test_parse_ok(&[ - ("{}", treemap!()), - ("{ }", treemap!()), - ( - "{\"a\":3}", - treemap!("a".to_string() => 3is) - ), - ( - "{ \"a\" : 3 }", - treemap!("a".to_string() => 3is) - ), - ( - "{\"a\":3,\"b\":4}", - treemap!("a".to_string() => 3is, "b".to_string() => 4) - ), - ( - "{ \"a\" : 3 , \"b\" : 4 }", - treemap!("a".to_string() => 3is, "b".to_string() => 4), - ), - ]); - - test_parse_ok(&[ - ( - "{\"a\": {\"b\": 3, \"c\": 4}}", - treemap!("a".to_string() => treemap!("b".to_string() => 3is, "c".to_string() => 4is)), - ), - ]); - } - - #[test] - fn test_json_deserialize_object() { - test_json_deserialize_ok(&[ - treemap!(), - treemap!("a".to_string() => 3is), - treemap!("a".to_string() => 3is, "b".to_string() => 4), - ]); - - test_json_deserialize_ok(&[ - treemap!("a".to_string() => treemap!("b".to_string() => 3is, "c".to_string() => 4)), - ]); - } - - #[test] - fn test_parse_struct() { - 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_json_deserialize_struct() { - test_json_deserialize_ok(&[ - 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), - ("\"jodhpurs\"", Some("jodhpurs".to_string())), - ]); - - #[derive(PartialEq, Debug)] - #[derive_serialize] - #[derive_deserialize] - struct Foo { - x: Option, - } - - let value: Foo = from_str("{}").unwrap(); - assert_eq!(value, Foo { x: None }); - - let value: Foo = from_str("{ \"x\": 5 }").unwrap(); - assert_eq!(value, Foo { x: Some(5) }); - } - - #[test] - fn test_json_deserialize_option() { - test_json_deserialize_ok(&[ - None, - Some("jodhpurs".to_string()), - ]); - } - - #[test] - fn test_parse_enum() { - test_parse_ok(&[ - ("{\"Dog\": []}", Animal::Dog), - ( - "{\"Frog\": [\"Henry\", []]}", - Animal::Frog("Henry".to_string(), vec!()), - ), - ( - "{\"Frog\": [\"Henry\", [349]]}", - Animal::Frog("Henry".to_string(), vec!(349)), - ), - ( - "{\"Frog\": [\"Henry\", [349, 102]]}", - Animal::Frog("Henry".to_string(), vec!(349, 102)), - ), - ]); - - 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_json_deserialize_enum() { - test_json_deserialize_ok(&[ - Animal::Dog, - Animal::Frog("Henry".to_string(), vec!()), - Animal::Frog("Henry".to_string(), vec!(349)), - Animal::Frog("Henry".to_string(), vec!(349, 102)), - ]); - } - - #[test] - fn test_multiline_errors() { - test_parse_err::>(&[ - ("{\n \"foo\":\n \"bar\"", SyntaxError(EOFWhileParsingObject, 3us, 8us)), - ]); - } - - /* - #[derive(Decodable)] - struct DecodeStruct { - x: f64, - y: bool, - z: String, - w: Vec - } - #[derive(Decodable)] - enum DecodeEnum { - A(f64), - B(String) - } - fn check_err>(to_parse: &'static str, - expected: DecoderError) { - let res: DecodeResult = match from_str(to_parse) { - Err(e) => Err(ParseError(e)), - Ok(json) => RustcDecodable::decode(&mut Decoder::new(json)) - }; - match res { - Ok(_) => panic!("`{}` parsed & decoded ok, expecting error `{}`", - to_parse, expected), - Err(ParseError(e)) => panic!("`{}` is not valid json: {}", - to_parse, e), - Err(e) => { - assert_eq!(e, expected); - } - } - } - #[test] - fn test_decode_errors_struct() { - check_err::("[]", ExpectedError("Object".to_string(), "[]".to_string())); - check_err::("{\"x\": true, \"y\": true, \"z\": \"\", \"w\": []}", - ExpectedError("Number".to_string(), "true".to_string())); - check_err::("{\"x\": 1, \"y\": [], \"z\": \"\", \"w\": []}", - ExpectedError("Boolean".to_string(), "[]".to_string())); - check_err::("{\"x\": 1, \"y\": true, \"z\": {}, \"w\": []}", - ExpectedError("String".to_string(), "{}".to_string())); - check_err::("{\"x\": 1, \"y\": true, \"z\": \"\", \"w\": null}", - ExpectedError("List".to_string(), "null".to_string())); - check_err::("{\"x\": 1, \"y\": true, \"z\": \"\"}", - MissingFieldError("w".to_string())); - } - #[test] - fn test_decode_errors_enum() { - check_err::("{}", - MissingFieldError("variant".to_string())); - check_err::("{\"variant\": 1}", - ExpectedError("String".to_string(), "1".to_string())); - check_err::("{\"variant\": \"A\"}", - MissingFieldError("fields".to_string())); - check_err::("{\"variant\": \"A\", \"fields\": null}", - ExpectedError("List".to_string(), "null".to_string())); - check_err::("{\"variant\": \"C\", \"fields\": []}", - UnknownVariantError("C".to_string())); - } - */ - - #[test] - fn test_find(){ - let json_value: Value = from_str("{\"dog\" : \"cat\"}").unwrap(); - let found_str = json_value.find(&"dog".to_string()); - assert!(found_str.is_some() && found_str.unwrap().as_string().unwrap() == "cat"); - } - - #[test] - fn test_find_path(){ - let json_value: Value = from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap(); - let found_str = json_value.find_path(&[&"dog".to_string(), - &"cat".to_string(), &"mouse".to_string()]); - assert!(found_str.is_some() && found_str.unwrap().as_string().unwrap() == "cheese"); - } - - #[test] - fn test_search(){ - let json_value: Value = from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap(); - let found_str = json_value.search(&"mouse".to_string()).and_then(|j| j.as_string()); - assert!(found_str.is_some()); - assert!(found_str.unwrap() == "cheese"); - } - - #[test] - fn test_is_object() { - let json_value: Value = from_str("{}").unwrap(); - assert!(json_value.is_object()); - } - - #[test] - fn test_as_object() { - let json_value: Value = from_str("{}").unwrap(); - let map = BTreeMap::::new(); - let json_object = json_value.as_object(); - assert_eq!(json_object, Some(&map)); - } - - #[test] - fn test_is_array() { - let json_value: Value = from_str("[1, 2, 3]").unwrap(); - assert!(json_value.is_array()); - } - - #[test] - fn test_as_array() { - let json_value: Value = from_str("[1, 2, 3]").unwrap(); - let json_list = json_value.as_array(); - let expected_length = 3; - assert!(json_list.is_some() && json_list.unwrap().len() == expected_length); - } - - #[test] - fn test_is_string() { - let json_value: Value = from_str("\"dog\"").unwrap(); - assert!(json_value.is_string()); - } - - #[test] - fn test_as_string() { - let json_value: Value = from_str("\"dog\"").unwrap(); - let json_str = json_value.as_string(); - let expected_str = "dog"; - assert_eq!(json_str, Some(expected_str)); - } - - #[test] - fn test_is_number() { - let json_value: Value = from_str("12").unwrap(); - assert!(json_value.is_number()); - - let json_value: Value = from_str("12.0").unwrap(); - assert!(json_value.is_number()); - } - - #[test] - fn test_is_i64() { - let json_value: Value = from_str("12").unwrap(); - assert!(json_value.is_i64()); - - let json_value: Value = from_str("12.0").unwrap(); - assert!(!json_value.is_i64()); - } - - #[test] - fn test_is_f64() { - let json_value: Value = from_str("12").unwrap(); - assert!(!json_value.is_f64()); - - let json_value: Value = from_str("12.0").unwrap(); - assert!(json_value.is_f64()); - } - - #[test] - fn test_as_i64() { - let json_value: Value = from_str("12").unwrap(); - assert_eq!(json_value.as_i64(), Some(12)); - } - - #[test] - fn test_as_f64() { - let json_value: Value = from_str("12").unwrap(); - assert_eq!(json_value.as_f64(), Some(12.0)); - } - - #[test] - fn test_is_boolean() { - let json_value: Value = from_str("false").unwrap(); - assert!(json_value.is_boolean()); - } - - #[test] - fn test_as_boolean() { - let json_value: Value = from_str("false").unwrap(); - let json_bool = json_value.as_boolean(); - let expected_bool = false; - assert!(json_bool.is_some() && json_bool.unwrap() == expected_bool); - } - - #[test] - fn test_is_null() { - let json_value: Value = from_str("null").unwrap(); - assert!(json_value.is_null()); - } - - #[test] - fn test_as_null() { - let json_value: Value = from_str("null").unwrap(); - let json_null = json_value.as_null(); - let expected_null = (); - assert!(json_null.is_some() && json_null.unwrap() == expected_null); - } - - /* - #[test] - fn test_encode_hashmap_with_numeric_key() { - use std::str::from_utf8; - use std::collections::HashMap; - let mut hm: HashMap = HashMap::new(); - hm.insert(1, true); - let mut mem_buf = MemWriter::new(); - { - let mut serializer = Serializer::new(&mut mem_buf as &mut Writer); - hm.serialize(&mut serializer).unwrap(); - } - let bytes = mem_buf.unwrap(); - let json_str = from_utf8(&bytes).unwrap(); - let _json_value: Value = from_str(json_str).unwrap(); - } - #[test] - fn test_prettyencode_hashmap_with_numeric_key() { - use std::str::from_utf8; - use std::collections::HashMap; - let mut hm: HashMap = HashMap::new(); - hm.insert(1, true); - let mut mem_buf = MemWriter::new(); - { - let mut serializer = PrettySerializer::new(&mut mem_buf as &mut Writer); - hm.serialize(&mut serializer).unwrap() - } - let bytes = mem_buf.unwrap(); - let json_str = from_utf8(&bytes).unwrap(); - let _json_value: Value = from_str(json_str).unwrap(); - } - - #[test] - fn test_hashmap_with_numeric_key_can_handle_double_quote_delimited_key() { - use std::collections::HashMap; - let json_str = "{\"1\":true}"; - let map: HashMap = from_str(json_str).unwrap(); - let mut m = HashMap::new(); - m.insert(1u, true); - assert_eq!(map, m); - } - */ - - /* - fn assert_stream_equal(src: &str, expected: ~[(JsonEvent, ~[StackElement])]) { - let mut parser = Parser::new(src.chars()); - let mut i = 0; - loop { - let evt = match parser.next() { - Some(e) => e, - None => { break; } - }; - let (ref expected_evt, ref expected_stack) = expected[i]; - if !parser.stack().is_equal_to(&expected_stack) { - panic!("Parser stack is not equal to {}", expected_stack); - } - assert_eq!(&evt, expected_evt); - i+=1; - } - } - #[test] - fn test_streaming_parser() { - assert_stream_equal( - r#"{ "foo":"bar", "array" : [0, 1, 2,3 ,4,5], "idents":[null,true,false]}"#, - ~[ - (ObjectStart, ~[]), - (StringValue("bar".to_string()), ~[Key("foo")]), - (ListStart, ~[Key("array")]), - (NumberValue(0.0), ~[Key("array"), Index(0)]), - (NumberValue(1.0), ~[Key("array"), Index(1)]), - (NumberValue(2.0), ~[Key("array"), Index(2)]), - (NumberValue(3.0), ~[Key("array"), Index(3)]), - (NumberValue(4.0), ~[Key("array"), Index(4)]), - (NumberValue(5.0), ~[Key("array"), Index(5)]), - (ListEnd, ~[Key("array")]), - (ListStart, ~[Key("idents")]), - (NullValue, ~[Key("idents"), Index(0)]), - (BooleanValue(true), ~[Key("idents"), Index(1)]), - (BooleanValue(false), ~[Key("idents"), Index(2)]), - (ListEnd, ~[Key("idents")]), - (ObjectEnd, ~[]), - ] - ); - } - fn last_event(src: &str) -> JsonEvent { - let mut parser = Parser::new(src.chars()); - let mut evt = NullValue; - loop { - evt = match parser.next() { - Some(e) => e, - None => return evt, - } - } - } - #[test] - #[ignore(cfg(target_word_size = "32"))] // FIXME(#14064) - fn test_read_object_streaming() { - assert_eq!(last_event("{ "), Error(SyntaxError(EOFWhileParsingObject, 1, 3))); - assert_eq!(last_event("{1"), Error(SyntaxError(KeyMustBeAString, 1, 2))); - assert_eq!(last_event("{ \"a\""), Error(SyntaxError(EOFWhileParsingObject, 1, 6))); - assert_eq!(last_event("{\"a\""), Error(SyntaxError(EOFWhileParsingObject, 1, 5))); - assert_eq!(last_event("{\"a\" "), Error(SyntaxError(EOFWhileParsingObject, 1, 6))); - - assert_eq!(last_event("{\"a\" 1"), Error(SyntaxError(ExpectedColon, 1, 6))); - assert_eq!(last_event("{\"a\":"), Error(SyntaxError(EOFWhileParsingValue, 1, 6))); - assert_eq!(last_event("{\"a\":1"), Error(SyntaxError(EOFWhileParsingObject, 1, 7))); - assert_eq!(last_event("{\"a\":1 1"), Error(SyntaxError(InvalidSyntax, 1, 8))); - assert_eq!(last_event("{\"a\":1,"), Error(SyntaxError(EOFWhileParsingObject, 1, 8))); - - assert_stream_equal( - "{}", - box [(ObjectStart, box []), (ObjectEnd, box [])] - ); - assert_stream_equal( - "{\"a\": 3}", - box [ - (ObjectStart, box []), - (F64Value(3.0), box [Key("a")]), - (ObjectEnd, box []), - ] - ); - assert_stream_equal( - "{ \"a\": null, \"b\" : true }", - box [ - (ObjectStart, box []), - (NullValue, box [Key("a")]), - (BooleanValue(true), box [Key("b")]), - (ObjectEnd, box []), - ] - ); - assert_stream_equal( - "{\"a\" : 1.0 ,\"b\": [ true ]}", - box [ - (ObjectStart, box []), - (F64Value(1.0), box [Key("a")]), - (ListStart, box [Key("b")]), - (BooleanValue(true),box [Key("b"), Index(0)]), - (ListEnd, box [Key("b")]), - (ObjectEnd, box []), - ] - ); - assert_stream_equal( - r#"{ - "a": 1.0, - "b": [ - true, - "foo\nbar", - { "c": {"d": null} } - ] - }"#, - ~[ - (ObjectStart, ~[]), - (F64Value(1.0), ~[Key("a")]), - (ListStart, ~[Key("b")]), - (BooleanValue(true), ~[Key("b"), Index(0)]), - (StringValue("foo\nbar".to_string()), ~[Key("b"), Index(1)]), - (ObjectStart, ~[Key("b"), Index(2)]), - (ObjectStart, ~[Key("b"), Index(2), Key("c")]), - (NullValue, ~[Key("b"), Index(2), Key("c"), Key("d")]), - (ObjectEnd, ~[Key("b"), Index(2), Key("c")]), - (ObjectEnd, ~[Key("b"), Index(2)]), - (ListEnd, ~[Key("b")]), - (ObjectEnd, ~[]), - ] - ); - } - #[test] - #[ignore(cfg(target_word_size = "32"))] // FIXME(#14064) - fn test_read_list_streaming() { - assert_stream_equal( - "[]", - box [ - (ListStart, box []), - (ListEnd, box []), - ] - ); - assert_stream_equal( - "[ ]", - box [ - (ListStart, box []), - (ListEnd, box []), - ] - ); - assert_stream_equal( - "[true]", - box [ - (ListStart, box []), - (BooleanValue(true), box [Index(0)]), - (ListEnd, box []), - ] - ); - assert_stream_equal( - "[ false ]", - box [ - (ListStart, box []), - (BooleanValue(false), box [Index(0)]), - (ListEnd, box []), - ] - ); - assert_stream_equal( - "[null]", - box [ - (ListStart, box []), - (NullValue, box [Index(0)]), - (ListEnd, box []), - ] - ); - assert_stream_equal( - "[3, 1]", - box [ - (ListStart, box []), - (F64Value(3.0), box [Index(0)]), - (F64Value(1.0), box [Index(1)]), - (ListEnd, box []), - ] - ); - assert_stream_equal( - "\n[3, 2]\n", - box [ - (ListStart, box []), - (F64Value(3.0), box [Index(0)]), - (F64Value(2.0), box [Index(1)]), - (ListEnd, box []), - ] - ); - assert_stream_equal( - "[2, [4, 1]]", - box [ - (ListStart, box []), - (F64Value(2.0), box [Index(0)]), - (ListStart, box [Index(1)]), - (F64Value(4.0), box [Index(1), Index(0)]), - (F64Value(1.0), box [Index(1), Index(1)]), - (ListEnd, box [Index(1)]), - (ListEnd, box []), - ] - ); - - assert_eq!(last_event("["), Error(SyntaxError(EOFWhileParsingValue, 1, 2))); - - assert_eq!(from_str("["), Err(SyntaxError(EOFWhileParsingValue, 1, 2))); - assert_eq!(from_str("[1"), Err(SyntaxError(EOFWhileParsingList, 1, 3))); - assert_eq!(from_str("[1,"), Err(SyntaxError(EOFWhileParsingValue, 1, 4))); - assert_eq!(from_str("[1,]"), Err(SyntaxError(InvalidSyntax, 1, 4))); - assert_eq!(from_str("[6 7]"), Err(SyntaxError(InvalidSyntax, 1, 4))); - - } - #[test] - fn test_trailing_characters_streaming() { - assert_eq!(last_event("nulla"), Error(SyntaxError(TrailingCharacters, 1, 5))); - assert_eq!(last_event("truea"), Error(SyntaxError(TrailingCharacters, 1, 5))); - assert_eq!(last_event("falsea"), Error(SyntaxError(TrailingCharacters, 1, 6))); - assert_eq!(last_event("1a"), Error(SyntaxError(TrailingCharacters, 1, 2))); - assert_eq!(last_event("[]a"), Error(SyntaxError(TrailingCharacters, 1, 3))); - assert_eq!(last_event("{}a"), Error(SyntaxError(TrailingCharacters, 1, 3))); - } - #[test] - fn test_read_identifiers_streaming() { - assert_eq!(Parser::new("null".chars()).next(), Some(NullValue)); - assert_eq!(Parser::new("true".chars()).next(), Some(BooleanValue(true))); - assert_eq!(Parser::new("false".chars()).next(), Some(BooleanValue(false))); - - assert_eq!(last_event("n"), Error(SyntaxError(InvalidSyntax, 1, 2))); - assert_eq!(last_event("nul"), Error(SyntaxError(InvalidSyntax, 1, 4))); - assert_eq!(last_event("t"), Error(SyntaxError(InvalidSyntax, 1, 2))); - assert_eq!(last_event("truz"), Error(SyntaxError(InvalidSyntax, 1, 4))); - assert_eq!(last_event("f"), Error(SyntaxError(InvalidSyntax, 1, 2))); - assert_eq!(last_event("faz"), Error(SyntaxError(InvalidSyntax, 1, 3))); - } - - #[test] - fn test_stack() { - let mut stack = Stack::new(); - - assert!(stack.is_empty()); - assert!(stack.len() == 0); - assert!(!stack.last_is_index()); - - stack.push_index(0); - stack.bump_index(); - - assert!(stack.len() == 1); - assert!(stack.is_equal_to(&[Index(1)])); - assert!(stack.starts_with(&[Index(1)])); - assert!(stack.ends_with(&[Index(1)])); - assert!(stack.last_is_index()); - assert!(stack.get(0) == Index(1)); - - stack.push_key("foo".to_string()); - - assert!(stack.len() == 2); - assert!(stack.is_equal_to(&[Index(1), Key("foo")])); - assert!(stack.starts_with(&[Index(1), Key("foo")])); - assert!(stack.starts_with(&[Index(1)])); - assert!(stack.ends_with(&[Index(1), Key("foo")])); - assert!(stack.ends_with(&[Key("foo")])); - assert!(!stack.last_is_index()); - assert!(stack.get(0) == Index(1)); - assert!(stack.get(1) == Key("foo")); - - stack.push_key("bar".to_string()); - - assert!(stack.len() == 3); - assert!(stack.is_equal_to(&[Index(1), Key("foo"), Key("bar")])); - assert!(stack.starts_with(&[Index(1)])); - assert!(stack.starts_with(&[Index(1), Key("foo")])); - assert!(stack.starts_with(&[Index(1), Key("foo"), Key("bar")])); - assert!(stack.ends_with(&[Key("bar")])); - assert!(stack.ends_with(&[Key("foo"), Key("bar")])); - assert!(stack.ends_with(&[Index(1), Key("foo"), Key("bar")])); - assert!(!stack.last_is_index()); - assert!(stack.get(0) == Index(1)); - assert!(stack.get(1) == Key("foo")); - assert!(stack.get(2) == Key("bar")); - - stack.pop(); - - assert!(stack.len() == 2); - assert!(stack.is_equal_to(&[Index(1), Key("foo")])); - assert!(stack.starts_with(&[Index(1), Key("foo")])); - assert!(stack.starts_with(&[Index(1)])); - assert!(stack.ends_with(&[Index(1), Key("foo")])); - assert!(stack.ends_with(&[Key("foo")])); - assert!(!stack.last_is_index()); - assert!(stack.get(0) == Index(1)); - assert!(stack.get(1) == Key("foo")); - } -*/ -} - -#[cfg(test)] -mod bench { - use std::collections::BTreeMap; - use std::string; - use rustc_serialize as serialize; - use test::Bencher; - - use de::Token; - - use super::{Parser, Value, from_str}; - - macro_rules! treemap { - ($($k:expr => $v:expr),*) => ({ - let mut _m = ::std::collections::BTreeMap::new(); - $(_m.insert($k, $v);)* - _m - }) - } - - fn json_str(count: usize) -> string::String { - let mut src = "[".to_string(); - for _ in range(0, count) { - src.push_str(r#"{"a":true,"b":null,"c":3.1415,"d":"Hello world","e":[1,2,3]},"#); - } - src.push_str("{}]"); - src - } - - fn pretty_json_str(count: usize) -> string::String { - let mut src = "[\n".to_string(); - for _ in range(0, count) { - src.push_str( - concat!( - " {\n", - " \"a\": true,\n", - " \"b\": null,\n", - " \"c\": 3.1415,\n", - " \"d\": \"Hello world\",\n", - " \"e\": [\n", - " 1,\n", - " 2,\n", - " 3\n", - " ]\n", - " },\n" - ) - ); - } - src.push_str(" {}\n]"); - src - } - - fn encoder_json(count: usize) -> serialize::json::Json { - use rustc_serialize::json::Json; - - let mut list = vec!(); - for _ in range(0, count) { - list.push(Json::Object(treemap!( - "a".to_string() => Json::Boolean(true), - "b".to_string() => Json::Null, - "c".to_string() => Json::F64(3.1415), - "d".to_string() => Json::String("Hello world".to_string()), - "e".to_string() => Json::Array(vec!( - Json::U64(1), - Json::U64(2), - Json::U64(3) - )) - ))); - } - list.push(Json::Object(BTreeMap::new())); - Json::Array(list) - } - - fn serializer_json(count: usize) -> Value { - let mut list = vec!(); - for _ in range(0, count) { - list.push(Value::Object(treemap!( - "a".to_string() => Value::Boolean(true), - "b".to_string() => Value::Null, - "c".to_string() => Value::Floating(3.1415), - "d".to_string() => Value::String("Hello world".to_string()), - "e".to_string() => Value::Array(vec!( - Value::Integer(1), - Value::Integer(2), - Value::Integer(3) - )) - ))); - } - list.push(Value::Object(BTreeMap::new())); - Value::Array(list) - } - - fn bench_encoder(b: &mut Bencher, count: usize) { - let src = json_str(count); - let json = encoder_json(count); - - b.iter(|| { - assert_eq!(json.to_string(), src); - }); - } - - fn bench_encoder_pretty(b: &mut Bencher, count: usize) { - let src = pretty_json_str(count); - let json = encoder_json(count); - - b.iter(|| { - assert_eq!(json.pretty().to_string(), src); - }); - } - - fn bench_serializer(b: &mut Bencher, count: usize) { - let src = json_str(count); - let json = serializer_json(count); - - b.iter(|| { - assert_eq!(json.to_string(), src); - }); - } - - fn bench_serializer_pretty(b: &mut Bencher, count: usize) { - let src = pretty_json_str(count); - let json = serializer_json(count); - - b.iter(|| { - assert_eq!(json.to_pretty_string(), src); - }); - } - - fn bench_decoder(b: &mut Bencher, count: usize) { - let src = json_str(count); - let json = encoder_json(count); - b.iter(|| { - assert_eq!(json, serialize::json::Json::from_str(&src).unwrap()); - }); - } - - fn bench_deserializer(b: &mut Bencher, count: usize) { - let src = json_str(count); - let json = encoder_json(count); - b.iter(|| { - assert_eq!(json, serialize::json::Json::from_str(&src).unwrap()); - }); - } - - fn bench_decoder_streaming(b: &mut Bencher, count: usize) { - let src = json_str(count); - - b.iter( || { - use rustc_serialize::json::{Parser, JsonEvent, StackElement}; - - let mut parser = Parser::new(src.chars()); - assert_eq!(parser.next(), Some(JsonEvent::ArrayStart)); - for _ in range(0, count) { - assert_eq!(parser.next(), Some(JsonEvent::ObjectStart)); - - assert_eq!(parser.next(), Some(JsonEvent::BooleanValue(true))); - assert_eq!(parser.stack().top(), Some(StackElement::Key("a"))); - - assert_eq!(parser.next(), Some(JsonEvent::NullValue)); - assert_eq!(parser.stack().top(), Some(StackElement::Key("b"))); - - assert_eq!(parser.next(), Some(JsonEvent::F64Value(3.1415))); - assert_eq!(parser.stack().top(), Some(StackElement::Key("c"))); - - assert_eq!(parser.next(), Some(JsonEvent::StringValue("Hello world".to_string()))); - assert_eq!(parser.stack().top(), Some(StackElement::Key("d"))); - - assert_eq!(parser.next(), Some(JsonEvent::ArrayStart)); - assert_eq!(parser.stack().top(), Some(StackElement::Key("e"))); - assert_eq!(parser.next(), Some(JsonEvent::U64Value(1))); - assert_eq!(parser.next(), Some(JsonEvent::U64Value(2))); - assert_eq!(parser.next(), Some(JsonEvent::U64Value(3))); - assert_eq!(parser.next(), Some(JsonEvent::ArrayEnd)); - - assert_eq!(parser.next(), Some(JsonEvent::ObjectEnd)); - } - assert_eq!(parser.next(), Some(JsonEvent::ObjectStart)); - assert_eq!(parser.next(), Some(JsonEvent::ObjectEnd)); - assert_eq!(parser.next(), Some(JsonEvent::ArrayEnd)); - assert_eq!(parser.next(), None); - }); - } - - fn bench_deserializer_streaming(b: &mut Bencher, count: usize) { - let src = json_str(count); - - b.iter( || { - let mut parser = Parser::new(src.bytes()); - - assert_eq!(parser.next(), Some(Ok(Token::SeqStart(0)))); - for _ in range(0, count) { - assert_eq!(parser.next(), Some(Ok(Token::MapStart(0)))); - - assert_eq!(parser.next(), Some(Ok(Token::String("a".to_string())))); - assert_eq!(parser.next(), Some(Ok(Token::Bool(true)))); - - assert_eq!(parser.next(), Some(Ok(Token::String("b".to_string())))); - assert_eq!(parser.next(), Some(Ok(Token::Null))); - - assert_eq!(parser.next(), Some(Ok(Token::String("c".to_string())))); - assert_eq!(parser.next(), Some(Ok(Token::F64(3.1415)))); - - assert_eq!(parser.next(), Some(Ok(Token::String("d".to_string())))); - assert_eq!(parser.next(), Some(Ok(Token::String("Hello world".to_string())))); - - assert_eq!(parser.next(), Some(Ok(Token::String("e".to_string())))); - assert_eq!(parser.next(), Some(Ok(Token::SeqStart(0)))); - assert_eq!(parser.next(), Some(Ok(Token::I64(1)))); - assert_eq!(parser.next(), Some(Ok(Token::I64(2)))); - assert_eq!(parser.next(), Some(Ok(Token::I64(3)))); - assert_eq!(parser.next(), Some(Ok(Token::End))); - - assert_eq!(parser.next(), Some(Ok(Token::End))); - } - assert_eq!(parser.next(), Some(Ok(Token::MapStart(0)))); - assert_eq!(parser.next(), Some(Ok(Token::End))); - assert_eq!(parser.next(), Some(Ok(Token::End))); - assert_eq!(parser.next(), None); - - loop { - match parser.next() { - None => return, - Some(Ok(_)) => { } - Some(Err(err)) => { panic!("error: {:?}", err); } - } - } - }); - } - - #[bench] - fn bench_encoder_001(b: &mut Bencher) { - bench_encoder(b, 1) - } - - #[bench] - fn bench_encoder_500(b: &mut Bencher) { - bench_encoder(b, 500) - } - - #[bench] - fn bench_encoder_001_pretty(b: &mut Bencher) { - bench_encoder_pretty(b, 1) - } - - #[bench] - fn bench_encoder_500_pretty(b: &mut Bencher) { - bench_encoder_pretty(b, 500) - } - - #[bench] - fn bench_serializer_001(b: &mut Bencher) { - bench_serializer(b, 1) - } - - #[bench] - fn bench_serializer_500(b: &mut Bencher) { - bench_serializer(b, 500) - } - #[bench] - fn bench_serializer_001_pretty(b: &mut Bencher) { - bench_serializer_pretty(b, 1) - } - - #[bench] - fn bench_serializer_500_pretty(b: &mut Bencher) { - bench_serializer_pretty(b, 500) - } - - #[bench] - fn bench_decoder_001(b: &mut Bencher) { - bench_decoder(b, 1) - } - - #[bench] - fn bench_decoder_500(b: &mut Bencher) { - bench_decoder(b, 500) - } - - #[bench] - fn bench_deserializer_001(b: &mut Bencher) { - bench_deserializer(b, 1) - } - - #[bench] - fn bench_deserializer_500(b: &mut Bencher) { - bench_deserializer(b, 500) - } - - #[bench] - fn bench_decoder_001_streaming(b: &mut Bencher) { - bench_decoder_streaming(b, 1) - } - - #[bench] - fn bench_decoder_500_streaming(b: &mut Bencher) { - bench_decoder_streaming(b, 500) - } - - #[bench] - fn bench_deserializer_001_streaming(b: &mut Bencher) { - bench_deserializer_streaming(b, 1) - } - - #[bench] - fn bench_deserializer_500_streaming(b: &mut Bencher) { - bench_deserializer_streaming(b, 500) - } -} diff --git a/src/lib.rs b/src/lib.rs index c6b6b089..fe023da9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,18 +1,6 @@ -#![feature(plugin, io)] -#![crate_type = "dylib"] -#![crate_type = "rlib"] +#![feature(collections, core, hash, io, std_misc, plugin, unicode)] +#![plugin(serde_macros)] -// test harness access -#[cfg(test)] -extern crate test; - -#[plugin] -extern crate serde_macros; - -#[cfg(test)] -extern crate serialize; - -extern crate "rustc-serialize" as rustc_serialize; extern crate unicode; pub use de::{Deserializer, Deserialize}; diff --git a/src/ser.rs b/src/ser.rs index 1aec3dd6..43fa8035 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -313,524 +313,3 @@ macro_rules! impl_serialize_tuple { } impl_serialize_tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, } - -////////////////////////////////////////////////////////////////////////////// - -#[cfg(test)] -mod tests { - use std::collections::{HashMap, BTreeMap}; - - use std::{option, string}; - - use serialize::Decoder; - - use super::{Serializer, Serialize}; - - ////////////////////////////////////////////////////////////////////////////// - - #[derive(Clone, PartialEq, Debug, RustcDecodable)] - #[derive_serialize] - struct Inner { - a: (), - b: usize, - c: HashMap>, - } - - ////////////////////////////////////////////////////////////////////////////// - - #[derive(Clone, PartialEq, Debug, RustcDecodable)] - #[derive_serialize] - struct Outer { - inner: Vec, - } - - ////////////////////////////////////////////////////////////////////////////// - - #[derive(Clone, PartialEq, Debug, RustcDecodable)] - #[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, - } - - impl<'a, Iter: Iterator>> AssertSerializer { - fn new(iter: Iter) -> AssertSerializer { - 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>> Serializer for AssertSerializer { - 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, 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, 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, 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, Error> - >(&mut self, v: &option::Option) -> 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, Error>, - SeqIter: Iterator - >(&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, Error>, - V: Serialize, Error>, - MapIter: Iterator - >(&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::.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 = 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); - } -} diff --git a/tests/de.rs b/tests/de.rs new file mode 100644 index 00000000..bd992c6f --- /dev/null +++ b/tests/de.rs @@ -0,0 +1,368 @@ +#![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>, +} + +impl< + D: Deserializer, + E +> Deserialize for Inner { + #[inline] + fn deserialize_token(d: &mut D, token: Token) -> Result { + 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, +} + +impl, E> Deserialize for Outer { + #[inline] + fn deserialize_token(d: &mut D, token: Token) -> Result { + 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, E> Deserialize for Animal { + #[inline] + fn deserialize_token(d: &mut D, token: Token) -> Result { + 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), + UnexpectedName, + ConversionError, + MissingField(&'static str), +} + +////////////////////////////////////////////////////////////////////////////// + +struct TokenDeserializer { + tokens: Iter, +} + +impl> TokenDeserializer { + #[inline] + fn new(tokens: Iter) -> TokenDeserializer { + TokenDeserializer { + tokens: tokens, + } + } +} + +impl> Iterator for TokenDeserializer { + type Item = Result; + + #[inline] + fn next(&mut self) -> option::Option> { + self.tokens.next().map(|token| Ok(token)) + } +} + +impl> Deserializer for TokenDeserializer { + 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, Error> + >(&mut self, field: &'static str) -> Result { + 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, + + vec!( + Token::Option(true), + Token::Isize(5), + ) => Some(5), option::Option +]); + +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, + + vec!( + Token::SeqStart(3), + Token::Isize(5), + + Token::Isize(6), + + Token::Isize(7), + Token::End, + ) => vec!(5, 6, 7), Vec, + + + 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> +]); + +test_value!(test_treemaps, [ + vec!( + Token::MapStart(0), + Token::End, + ) => treemap!(), BTreeMap, + + 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 +]); diff --git a/tests/json.rs b/tests/json.rs new file mode 100644 index 00000000..5131fb06 --- /dev/null +++ b/tests/json.rs @@ -0,0 +1,1384 @@ +#![feature(io, plugin, test)] +#![plugin(serde_macros)] + +extern crate "rustc-serialize" as rustc_serialize; + +extern crate test; +extern crate serde; + +use std::fmt::Debug; +use std::old_io; +use std::str; +use std::string; +use std::collections::BTreeMap; + +use serde::de; +use serde::ser::{Serialize, Serializer}; +use serde::ser; + +use serde::json::{self, Error, Parser, ToJson, Value, value, from_str, from_json}; + +use serde::json::error::Error::{ + SyntaxError, +}; + +use serde::json::error::ErrorCode::{ + EOFWhileParsingList, + EOFWhileParsingObject, + EOFWhileParsingString, + EOFWhileParsingValue, + ExpectedColon, + ExpectedListCommaOrEnd, + ExpectedObjectCommaOrEnd, + ExpectedSomeIdent, + ExpectedSomeValue, + InvalidNumber, + KeyMustBeAString, + TrailingCharacters, +}; + +macro_rules! treemap { + ($($k:expr => $v:expr),*) => ({ + let mut _m = ::std::collections::BTreeMap::new(); + $(_m.insert($k, $v);)* + _m + }) +} + +#[derive(PartialEq, Debug)] +#[derive_serialize] +#[derive_deserialize] +enum Animal { + Dog, + Frog(String, Vec) +} + +impl ToJson for Animal { + fn to_json(&self) -> Value { + match *self { + Animal::Dog => { + Value::Object( + treemap!( + "Dog".to_string() => Value::Array(vec!()) + ) + ) + } + Animal::Frog(ref x0, ref x1) => { + Value::Object( + treemap!( + "Frog".to_string() => Value::Array(vec!(x0.to_json(), x1.to_json())) + ) + ) + } + } + } +} + +#[derive(PartialEq, Debug)] +#[derive_serialize] +#[derive_deserialize] +struct Inner { + a: (), + b: usize, + c: Vec, +} + +impl ToJson for Inner { + fn to_json(&self) -> Value { + Value::Object( + treemap!( + "a".to_string() => self.a.to_json(), + "b".to_string() => self.b.to_json(), + "c".to_string() => self.c.to_json() + ) + ) + } +} + +#[derive(PartialEq, Debug)] +#[derive_serialize] +#[derive_deserialize] +struct Outer { + inner: Vec, +} + +impl ToJson for Outer { + fn to_json(&self) -> Value { + Value::Object( + treemap!( + "inner".to_string() => self.inner.to_json() + ) + ) + } +} + +fn test_encode_ok< + T: PartialEq + Debug + ToJson + ser::Serialize>, old_io::IoError> +>(errors: &[(T, &str)]) { + for &(ref value, out) in errors { + let out = out.to_string(); + + let s = json::to_string(value).unwrap(); + assert_eq!(s, out); + + let s = json::to_string(&value.to_json()).unwrap(); + assert_eq!(s, out); + } +} + +fn test_pretty_encode_ok< + T: PartialEq + Debug + ToJson + ser::Serialize>, old_io::IoError> +>(errors: &[(T, &str)]) { + for &(ref value, out) in errors { + let out = out.to_string(); + + let s = json::to_pretty_string(value).unwrap(); + assert_eq!(s, out); + + let s = json::to_pretty_string(&value.to_json()).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 = &[ + (3is, "3"), + (-2is, "-2"), + (-1234is, "-1234"), + ]; + test_encode_ok(tests); + test_pretty_encode_ok(tests); +} + +#[test] +fn test_write_f64() { + let tests = &[ + (3.0f64, "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::Boolean(false), + Value::Null, + Value::Array(vec![Value::String("foo\nbar".to_string()), Value::Floating(3.5)])]); + + test_encode_ok(&[ + (long_test_list, "[false,null,[\"foo\\nbar\",3.5]]"), + ]); + + let long_test_list = Value::Array(vec![ + Value::Boolean(false), + Value::Null, + Value::Array(vec![Value::String("foo\nbar".to_string()), Value::Floating(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(&[ + ( + (5is,), + "[5]", + ), + ]); + + test_pretty_encode_ok(&[ + ( + (5is,), + concat!( + "[\n", + " 5\n", + "]" + ), + ), + ]); + + test_encode_ok(&[ + ( + (5is, (6is, "abc")), + "[5,[6,\"abc\"]]", + ), + ]); + + test_pretty_encode_ok(&[ + ( + (5is, (6is, "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]]}"), + ]); + + 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", + "]" + ), + ), + ]); + +} + +// FIXME (#5527): these could be merged once UFCS is finished. +fn test_parse_err< + 'a, + T: Debug + de::Deserialize>, Error> +>(errors: &[(&'a str, Error)]) { + for &(s, ref err) in errors { + let v: Result = from_str(s); + assert_eq!(v.unwrap_err(), *err); + } +} + +fn test_parse_ok< + 'a, + T: PartialEq + Debug + ToJson + de::Deserialize>, Error> +>(errors: &[(&'a str, T)]) { + for &(s, ref value) in errors { + let v: T = from_str(s).unwrap(); + assert_eq!(v, *value); + + let v: Value = from_str(s).unwrap(); + assert_eq!(v, value.to_json()); + } +} + +fn test_json_deserialize_ok< + T: PartialEq + Debug + ToJson + de::Deserialize +>(errors: &[T]) { + for value in errors { + let v: T = from_json(value.to_json()).unwrap(); + assert_eq!(v, *value); + + // Make sure we can round trip back to `Json`. + let v: Value = from_json(value.to_json()).unwrap(); + assert_eq!(v, value.to_json()); + } +} + +#[test] +fn test_parse_null() { + test_parse_err::<()>(&[ + ("n", SyntaxError(ExpectedSomeIdent, 1, 2)), + ("nul", SyntaxError(ExpectedSomeIdent, 1, 4)), + ("nulla", SyntaxError(TrailingCharacters, 1, 5)), + ]); + + test_parse_ok(&[ + ("null", ()), + ]); +} + +#[test] +fn test_json_deserialize_null() { + test_json_deserialize_ok(&[ + (), + ]); +} + +#[test] +fn test_parse_bool() { + test_parse_err::(&[ + ("t", SyntaxError(ExpectedSomeIdent, 1, 2)), + ("truz", SyntaxError(ExpectedSomeIdent, 1, 4)), + ("f", SyntaxError(ExpectedSomeIdent, 1, 2)), + ("faz", SyntaxError(ExpectedSomeIdent, 1, 3)), + ("truea", SyntaxError(TrailingCharacters, 1, 5)), + ("falsea", SyntaxError(TrailingCharacters, 1, 6)), + ]); + + test_parse_ok(&[ + ("true", true), + ("false", false), + ]); +} + +#[test] +fn test_json_deserialize_bool() { + test_json_deserialize_ok(&[ + true, + false, + ]); +} + +#[test] +fn test_parse_number_errors() { + test_parse_err::(&[ + ("+", SyntaxError(ExpectedSomeValue, 1, 1)), + (".", SyntaxError(ExpectedSomeValue, 1, 1)), + ("-", SyntaxError(InvalidNumber, 1, 2)), + ("00", SyntaxError(InvalidNumber, 1, 2)), + ("1.", SyntaxError(InvalidNumber, 1, 3)), + ("1e", SyntaxError(InvalidNumber, 1, 3)), + ("1e+", SyntaxError(InvalidNumber, 1, 4)), + ("1a", SyntaxError(TrailingCharacters, 1, 2)), + ]); +} + +#[test] +fn test_parse_i64() { + test_parse_ok(&[ + ("3", 3i64), + ("-2", -2), + ("-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), + ]); +} + +#[test] +fn test_json_deserialize_numbers() { + test_json_deserialize_ok(&[ + 3.0f64, + 3.1, + -1.2, + 0.4, + 0.4e5, + 0.4e15, + 0.4e-01, + ]); +} + +#[test] +fn test_parse_string() { + test_parse_err::(&[ + ("\"", SyntaxError(EOFWhileParsingString, 1, 2)), + ("\"lol", SyntaxError(EOFWhileParsingString, 1, 5)), + ("\"lol\"a", SyntaxError(TrailingCharacters, 1, 6)), + ]); + + test_parse_ok(&[ + ("\"\"", "".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_json_deserialize_str() { + test_json_deserialize_ok(&[ + "".to_string(), + "foo".to_string(), + "\"".to_string(), + "\x08".to_string(), + "\n".to_string(), + "\r".to_string(), + "\t".to_string(), + "\u{12ab}".to_string(), + "\u{AB12}".to_string(), + ]); +} + +#[test] +fn test_parse_list() { + test_parse_err::>(&[ + ("[", SyntaxError(EOFWhileParsingValue, 1, 2)), + ("[ ", SyntaxError(EOFWhileParsingValue, 1, 3)), + ("[1", SyntaxError(EOFWhileParsingList, 1, 3)), + ("[1,", SyntaxError(EOFWhileParsingValue, 1, 4)), + ("[1,]", SyntaxError(ExpectedSomeValue, 1, 4)), + ("[1 2]", SyntaxError(ExpectedListCommaOrEnd, 1, 4)), + ("[]a", SyntaxError(TrailingCharacters, 1, 3)), + ]); + + test_parse_ok(&[ + ("[]", vec!()), + ("[ ]", vec!()), + ("[null]", vec!(())), + ("[ null ]", vec!(())), + ]); + + test_parse_ok(&[ + ("[true]", vec!(true)), + ]); + + test_parse_ok(&[ + ("[3,1]", vec!(3is, 1)), + ("[ 3 , 1 ]", vec!(3is, 1)), + ]); + + test_parse_ok(&[ + ("[[3], [1, 2]]", vec!(vec!(3is), vec!(1, 2))), + ]); + + let v: () = from_str("[]").unwrap(); + assert_eq!(v, ()); + + test_parse_ok(&[ + ("[1, 2, 3]", (1us, 2us, 3us)), + ]); +} + +#[test] +fn test_json_deserialize_list() { + test_json_deserialize_ok(&[ + vec!(), + vec!(()), + ]); + + test_json_deserialize_ok(&[ + vec!(true), + ]); + + test_json_deserialize_ok(&[ + vec!(3is, 1), + ]); + + test_json_deserialize_ok(&[ + vec!(vec!(3is), vec!(1, 2)), + ]); +} + +#[test] +fn test_parse_object() { + test_parse_err::>(&[ + ("{", SyntaxError(EOFWhileParsingString, 1, 2)), + ("{ ", SyntaxError(EOFWhileParsingString, 1, 3)), + ("{1", SyntaxError(KeyMustBeAString, 1, 2)), + ("{ \"a\"", SyntaxError(EOFWhileParsingObject, 1, 6)), + ("{\"a\"", SyntaxError(EOFWhileParsingObject, 1, 5)), + ("{\"a\" ", SyntaxError(EOFWhileParsingObject, 1, 6)), + ("{\"a\" 1", SyntaxError(ExpectedColon, 1, 6)), + ("{\"a\":", SyntaxError(EOFWhileParsingValue, 1, 6)), + ("{\"a\":1", SyntaxError(EOFWhileParsingObject, 1, 7)), + ("{\"a\":1 1", SyntaxError(ExpectedObjectCommaOrEnd, 1, 8)), + ("{\"a\":1,", SyntaxError(EOFWhileParsingString, 1, 8)), + ("{}a", SyntaxError(TrailingCharacters, 1, 3)), + ]); + + test_parse_ok(&[ + ("{}", treemap!()), + ("{ }", treemap!()), + ( + "{\"a\":3}", + treemap!("a".to_string() => 3is) + ), + ( + "{ \"a\" : 3 }", + treemap!("a".to_string() => 3is) + ), + ( + "{\"a\":3,\"b\":4}", + treemap!("a".to_string() => 3is, "b".to_string() => 4) + ), + ( + "{ \"a\" : 3 , \"b\" : 4 }", + treemap!("a".to_string() => 3is, "b".to_string() => 4), + ), + ]); + + test_parse_ok(&[ + ( + "{\"a\": {\"b\": 3, \"c\": 4}}", + treemap!("a".to_string() => treemap!("b".to_string() => 3is, "c".to_string() => 4is)), + ), + ]); +} + +#[test] +fn test_json_deserialize_object() { + test_json_deserialize_ok(&[ + treemap!(), + treemap!("a".to_string() => 3is), + treemap!("a".to_string() => 3is, "b".to_string() => 4), + ]); + + test_json_deserialize_ok(&[ + treemap!("a".to_string() => treemap!("b".to_string() => 3is, "c".to_string() => 4)), + ]); +} + +#[test] +fn test_parse_struct() { + 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_json_deserialize_struct() { + test_json_deserialize_ok(&[ + 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), + ("\"jodhpurs\"", Some("jodhpurs".to_string())), + ]); + + #[derive(PartialEq, Debug)] + #[derive_serialize] + #[derive_deserialize] + struct Foo { + x: Option, + } + + let value: Foo = from_str("{}").unwrap(); + assert_eq!(value, Foo { x: None }); + + let value: Foo = from_str("{ \"x\": 5 }").unwrap(); + assert_eq!(value, Foo { x: Some(5) }); +} + +#[test] +fn test_json_deserialize_option() { + test_json_deserialize_ok(&[ + None, + Some("jodhpurs".to_string()), + ]); +} + +#[test] +fn test_parse_enum() { + test_parse_ok(&[ + ("{\"Dog\": []}", Animal::Dog), + ( + "{\"Frog\": [\"Henry\", []]}", + Animal::Frog("Henry".to_string(), vec!()), + ), + ( + "{\"Frog\": [\"Henry\", [349]]}", + Animal::Frog("Henry".to_string(), vec!(349)), + ), + ( + "{\"Frog\": [\"Henry\", [349, 102]]}", + Animal::Frog("Henry".to_string(), vec!(349, 102)), + ), + ]); + + 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_json_deserialize_enum() { + test_json_deserialize_ok(&[ + Animal::Dog, + Animal::Frog("Henry".to_string(), vec!()), + Animal::Frog("Henry".to_string(), vec!(349)), + Animal::Frog("Henry".to_string(), vec!(349, 102)), + ]); +} + +#[test] +fn test_multiline_errors() { + test_parse_err::>(&[ + ("{\n \"foo\":\n \"bar\"", SyntaxError(EOFWhileParsingObject, 3us, 8us)), + ]); +} + +/* +#[derive(Decodable)] +struct DecodeStruct { + x: f64, + y: bool, + z: String, + w: Vec +} +#[derive(Decodable)] +enum DecodeEnum { + A(f64), + B(String) +} +fn check_err>(to_parse: &'static str, + expected: DecoderError) { + let res: DecodeResult = match from_str(to_parse) { + Err(e) => Err(ParseError(e)), + Ok(json) => RustcDecodable::decode(&mut Decoder::new(json)) + }; + match res { + Ok(_) => panic!("`{}` parsed & decoded ok, expecting error `{}`", + to_parse, expected), + Err(ParseError(e)) => panic!("`{}` is not valid json: {}", + to_parse, e), + Err(e) => { + assert_eq!(e, expected); + } + } +} +#[test] +fn test_decode_errors_struct() { + check_err::("[]", ExpectedError("Object".to_string(), "[]".to_string())); + check_err::("{\"x\": true, \"y\": true, \"z\": \"\", \"w\": []}", + ExpectedError("Number".to_string(), "true".to_string())); + check_err::("{\"x\": 1, \"y\": [], \"z\": \"\", \"w\": []}", + ExpectedError("Boolean".to_string(), "[]".to_string())); + check_err::("{\"x\": 1, \"y\": true, \"z\": {}, \"w\": []}", + ExpectedError("String".to_string(), "{}".to_string())); + check_err::("{\"x\": 1, \"y\": true, \"z\": \"\", \"w\": null}", + ExpectedError("List".to_string(), "null".to_string())); + check_err::("{\"x\": 1, \"y\": true, \"z\": \"\"}", + MissingFieldError("w".to_string())); +} +#[test] +fn test_decode_errors_enum() { + check_err::("{}", + MissingFieldError("variant".to_string())); + check_err::("{\"variant\": 1}", + ExpectedError("String".to_string(), "1".to_string())); + check_err::("{\"variant\": \"A\"}", + MissingFieldError("fields".to_string())); + check_err::("{\"variant\": \"A\", \"fields\": null}", + ExpectedError("List".to_string(), "null".to_string())); + check_err::("{\"variant\": \"C\", \"fields\": []}", + UnknownVariantError("C".to_string())); +} +*/ + +#[test] +fn test_find(){ + let json_value: Value = from_str("{\"dog\" : \"cat\"}").unwrap(); + let found_str = json_value.find(&"dog".to_string()); + assert!(found_str.is_some() && found_str.unwrap().as_string().unwrap() == "cat"); +} + +#[test] +fn test_find_path(){ + let json_value: Value = from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap(); + let found_str = json_value.find_path(&[&"dog".to_string(), + &"cat".to_string(), &"mouse".to_string()]); + assert!(found_str.is_some() && found_str.unwrap().as_string().unwrap() == "cheese"); +} + +#[test] +fn test_search(){ + let json_value: Value = from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap(); + let found_str = json_value.search(&"mouse".to_string()).and_then(|j| j.as_string()); + assert!(found_str.is_some()); + assert!(found_str.unwrap() == "cheese"); +} + +#[test] +fn test_is_object() { + let json_value: Value = from_str("{}").unwrap(); + assert!(json_value.is_object()); +} + +#[test] +fn test_as_object() { + let json_value: Value = from_str("{}").unwrap(); + let map = BTreeMap::::new(); + let json_object = json_value.as_object(); + assert_eq!(json_object, Some(&map)); +} + +#[test] +fn test_is_array() { + let json_value: Value = from_str("[1, 2, 3]").unwrap(); + assert!(json_value.is_array()); +} + +#[test] +fn test_as_array() { + let json_value: Value = from_str("[1, 2, 3]").unwrap(); + let json_list = json_value.as_array(); + let expected_length = 3; + assert!(json_list.is_some() && json_list.unwrap().len() == expected_length); +} + +#[test] +fn test_is_string() { + let json_value: Value = from_str("\"dog\"").unwrap(); + assert!(json_value.is_string()); +} + +#[test] +fn test_as_string() { + let json_value: Value = from_str("\"dog\"").unwrap(); + let json_str = json_value.as_string(); + let expected_str = "dog"; + assert_eq!(json_str, Some(expected_str)); +} + +#[test] +fn test_is_number() { + let json_value: Value = from_str("12").unwrap(); + assert!(json_value.is_number()); + + let json_value: Value = from_str("12.0").unwrap(); + assert!(json_value.is_number()); +} + +#[test] +fn test_is_i64() { + let json_value: Value = from_str("12").unwrap(); + assert!(json_value.is_i64()); + + let json_value: Value = from_str("12.0").unwrap(); + assert!(!json_value.is_i64()); +} + +#[test] +fn test_is_f64() { + let json_value: Value = from_str("12").unwrap(); + assert!(!json_value.is_f64()); + + let json_value: Value = from_str("12.0").unwrap(); + assert!(json_value.is_f64()); +} + +#[test] +fn test_as_i64() { + let json_value: Value = from_str("12").unwrap(); + assert_eq!(json_value.as_i64(), Some(12)); +} + +#[test] +fn test_as_f64() { + let json_value: Value = from_str("12").unwrap(); + assert_eq!(json_value.as_f64(), Some(12.0)); +} + +#[test] +fn test_is_boolean() { + let json_value: Value = from_str("false").unwrap(); + assert!(json_value.is_boolean()); +} + +#[test] +fn test_as_boolean() { + let json_value: Value = from_str("false").unwrap(); + let json_bool = json_value.as_boolean(); + let expected_bool = false; + assert!(json_bool.is_some() && json_bool.unwrap() == expected_bool); +} + +#[test] +fn test_is_null() { + let json_value: Value = from_str("null").unwrap(); + assert!(json_value.is_null()); +} + +#[test] +fn test_as_null() { + let json_value: Value = from_str("null").unwrap(); + let json_null = json_value.as_null(); + let expected_null = (); + assert!(json_null.is_some() && json_null.unwrap() == expected_null); +} + +/* +#[test] +fn test_encode_hashmap_with_numeric_key() { + use std::str::from_utf8; + use std::collections::HashMap; + let mut hm: HashMap = HashMap::new(); + hm.insert(1, true); + let mut mem_buf = MemWriter::new(); + { + let mut serializer = Serializer::new(&mut mem_buf as &mut Writer); + hm.serialize(&mut serializer).unwrap(); + } + let bytes = mem_buf.unwrap(); + let json_str = from_utf8(&bytes).unwrap(); + let _json_value: Value = from_str(json_str).unwrap(); +} +#[test] +fn test_prettyencode_hashmap_with_numeric_key() { + use std::str::from_utf8; + use std::collections::HashMap; + let mut hm: HashMap = HashMap::new(); + hm.insert(1, true); + let mut mem_buf = MemWriter::new(); + { + let mut serializer = PrettySerializer::new(&mut mem_buf as &mut Writer); + hm.serialize(&mut serializer).unwrap() + } + let bytes = mem_buf.unwrap(); + let json_str = from_utf8(&bytes).unwrap(); + let _json_value: Value = from_str(json_str).unwrap(); +} + +#[test] +fn test_hashmap_with_numeric_key_can_handle_double_quote_delimited_key() { + use std::collections::HashMap; + let json_str = "{\"1\":true}"; + let map: HashMap = from_str(json_str).unwrap(); + let mut m = HashMap::new(); + m.insert(1u, true); + assert_eq!(map, m); +} +*/ + +/* +fn assert_stream_equal(src: &str, expected: ~[(JsonEvent, ~[StackElement])]) { + let mut parser = Parser::new(src.chars()); + let mut i = 0; + loop { + let evt = match parser.next() { + Some(e) => e, + None => { break; } + }; + let (ref expected_evt, ref expected_stack) = expected[i]; + if !parser.stack().is_equal_to(&expected_stack) { + panic!("Parser stack is not equal to {}", expected_stack); + } + assert_eq!(&evt, expected_evt); + i+=1; + } +} +#[test] +fn test_streaming_parser() { + assert_stream_equal( + r#"{ "foo":"bar", "array" : [0, 1, 2,3 ,4,5], "idents":[null,true,false]}"#, + ~[ + (ObjectStart, ~[]), + (StringValue("bar".to_string()), ~[Key("foo")]), + (ListStart, ~[Key("array")]), + (NumberValue(0.0), ~[Key("array"), Index(0)]), + (NumberValue(1.0), ~[Key("array"), Index(1)]), + (NumberValue(2.0), ~[Key("array"), Index(2)]), + (NumberValue(3.0), ~[Key("array"), Index(3)]), + (NumberValue(4.0), ~[Key("array"), Index(4)]), + (NumberValue(5.0), ~[Key("array"), Index(5)]), + (ListEnd, ~[Key("array")]), + (ListStart, ~[Key("idents")]), + (NullValue, ~[Key("idents"), Index(0)]), + (BooleanValue(true), ~[Key("idents"), Index(1)]), + (BooleanValue(false), ~[Key("idents"), Index(2)]), + (ListEnd, ~[Key("idents")]), + (ObjectEnd, ~[]), + ] + ); +} +fn last_event(src: &str) -> JsonEvent { + let mut parser = Parser::new(src.chars()); + let mut evt = NullValue; + loop { + evt = match parser.next() { + Some(e) => e, + None => return evt, + } + } +} +#[test] +#[ignore(cfg(target_word_size = "32"))] // FIXME(#14064) +fn test_read_object_streaming() { + assert_eq!(last_event("{ "), Error(SyntaxError(EOFWhileParsingObject, 1, 3))); + assert_eq!(last_event("{1"), Error(SyntaxError(KeyMustBeAString, 1, 2))); + assert_eq!(last_event("{ \"a\""), Error(SyntaxError(EOFWhileParsingObject, 1, 6))); + assert_eq!(last_event("{\"a\""), Error(SyntaxError(EOFWhileParsingObject, 1, 5))); + assert_eq!(last_event("{\"a\" "), Error(SyntaxError(EOFWhileParsingObject, 1, 6))); + + assert_eq!(last_event("{\"a\" 1"), Error(SyntaxError(ExpectedColon, 1, 6))); + assert_eq!(last_event("{\"a\":"), Error(SyntaxError(EOFWhileParsingValue, 1, 6))); + assert_eq!(last_event("{\"a\":1"), Error(SyntaxError(EOFWhileParsingObject, 1, 7))); + assert_eq!(last_event("{\"a\":1 1"), Error(SyntaxError(InvalidSyntax, 1, 8))); + assert_eq!(last_event("{\"a\":1,"), Error(SyntaxError(EOFWhileParsingObject, 1, 8))); + + assert_stream_equal( + "{}", + box [(ObjectStart, box []), (ObjectEnd, box [])] + ); + assert_stream_equal( + "{\"a\": 3}", + box [ + (ObjectStart, box []), + (F64Value(3.0), box [Key("a")]), + (ObjectEnd, box []), + ] + ); + assert_stream_equal( + "{ \"a\": null, \"b\" : true }", + box [ + (ObjectStart, box []), + (NullValue, box [Key("a")]), + (BooleanValue(true), box [Key("b")]), + (ObjectEnd, box []), + ] + ); + assert_stream_equal( + "{\"a\" : 1.0 ,\"b\": [ true ]}", + box [ + (ObjectStart, box []), + (F64Value(1.0), box [Key("a")]), + (ListStart, box [Key("b")]), + (BooleanValue(true),box [Key("b"), Index(0)]), + (ListEnd, box [Key("b")]), + (ObjectEnd, box []), + ] + ); + assert_stream_equal( + r#"{ + "a": 1.0, + "b": [ + true, + "foo\nbar", + { "c": {"d": null} } + ] + }"#, + ~[ + (ObjectStart, ~[]), + (F64Value(1.0), ~[Key("a")]), + (ListStart, ~[Key("b")]), + (BooleanValue(true), ~[Key("b"), Index(0)]), + (StringValue("foo\nbar".to_string()), ~[Key("b"), Index(1)]), + (ObjectStart, ~[Key("b"), Index(2)]), + (ObjectStart, ~[Key("b"), Index(2), Key("c")]), + (NullValue, ~[Key("b"), Index(2), Key("c"), Key("d")]), + (ObjectEnd, ~[Key("b"), Index(2), Key("c")]), + (ObjectEnd, ~[Key("b"), Index(2)]), + (ListEnd, ~[Key("b")]), + (ObjectEnd, ~[]), + ] + ); +} +#[test] +#[ignore(cfg(target_word_size = "32"))] // FIXME(#14064) +fn test_read_list_streaming() { + assert_stream_equal( + "[]", + box [ + (ListStart, box []), + (ListEnd, box []), + ] + ); + assert_stream_equal( + "[ ]", + box [ + (ListStart, box []), + (ListEnd, box []), + ] + ); + assert_stream_equal( + "[true]", + box [ + (ListStart, box []), + (BooleanValue(true), box [Index(0)]), + (ListEnd, box []), + ] + ); + assert_stream_equal( + "[ false ]", + box [ + (ListStart, box []), + (BooleanValue(false), box [Index(0)]), + (ListEnd, box []), + ] + ); + assert_stream_equal( + "[null]", + box [ + (ListStart, box []), + (NullValue, box [Index(0)]), + (ListEnd, box []), + ] + ); + assert_stream_equal( + "[3, 1]", + box [ + (ListStart, box []), + (F64Value(3.0), box [Index(0)]), + (F64Value(1.0), box [Index(1)]), + (ListEnd, box []), + ] + ); + assert_stream_equal( + "\n[3, 2]\n", + box [ + (ListStart, box []), + (F64Value(3.0), box [Index(0)]), + (F64Value(2.0), box [Index(1)]), + (ListEnd, box []), + ] + ); + assert_stream_equal( + "[2, [4, 1]]", + box [ + (ListStart, box []), + (F64Value(2.0), box [Index(0)]), + (ListStart, box [Index(1)]), + (F64Value(4.0), box [Index(1), Index(0)]), + (F64Value(1.0), box [Index(1), Index(1)]), + (ListEnd, box [Index(1)]), + (ListEnd, box []), + ] + ); + + assert_eq!(last_event("["), Error(SyntaxError(EOFWhileParsingValue, 1, 2))); + + assert_eq!(from_str("["), Err(SyntaxError(EOFWhileParsingValue, 1, 2))); + assert_eq!(from_str("[1"), Err(SyntaxError(EOFWhileParsingList, 1, 3))); + assert_eq!(from_str("[1,"), Err(SyntaxError(EOFWhileParsingValue, 1, 4))); + assert_eq!(from_str("[1,]"), Err(SyntaxError(InvalidSyntax, 1, 4))); + assert_eq!(from_str("[6 7]"), Err(SyntaxError(InvalidSyntax, 1, 4))); + +} +#[test] +fn test_trailing_characters_streaming() { + assert_eq!(last_event("nulla"), Error(SyntaxError(TrailingCharacters, 1, 5))); + assert_eq!(last_event("truea"), Error(SyntaxError(TrailingCharacters, 1, 5))); + assert_eq!(last_event("falsea"), Error(SyntaxError(TrailingCharacters, 1, 6))); + assert_eq!(last_event("1a"), Error(SyntaxError(TrailingCharacters, 1, 2))); + assert_eq!(last_event("[]a"), Error(SyntaxError(TrailingCharacters, 1, 3))); + assert_eq!(last_event("{}a"), Error(SyntaxError(TrailingCharacters, 1, 3))); +} +#[test] +fn test_read_identifiers_streaming() { + assert_eq!(Parser::new("null".chars()).next(), Some(NullValue)); + assert_eq!(Parser::new("true".chars()).next(), Some(BooleanValue(true))); + assert_eq!(Parser::new("false".chars()).next(), Some(BooleanValue(false))); + + assert_eq!(last_event("n"), Error(SyntaxError(InvalidSyntax, 1, 2))); + assert_eq!(last_event("nul"), Error(SyntaxError(InvalidSyntax, 1, 4))); + assert_eq!(last_event("t"), Error(SyntaxError(InvalidSyntax, 1, 2))); + assert_eq!(last_event("truz"), Error(SyntaxError(InvalidSyntax, 1, 4))); + assert_eq!(last_event("f"), Error(SyntaxError(InvalidSyntax, 1, 2))); + assert_eq!(last_event("faz"), Error(SyntaxError(InvalidSyntax, 1, 3))); +} + +#[test] +fn test_stack() { + let mut stack = Stack::new(); + + assert!(stack.is_empty()); + assert!(stack.len() == 0); + assert!(!stack.last_is_index()); + + stack.push_index(0); + stack.bump_index(); + + assert!(stack.len() == 1); + assert!(stack.is_equal_to(&[Index(1)])); + assert!(stack.starts_with(&[Index(1)])); + assert!(stack.ends_with(&[Index(1)])); + assert!(stack.last_is_index()); + assert!(stack.get(0) == Index(1)); + + stack.push_key("foo".to_string()); + + assert!(stack.len() == 2); + assert!(stack.is_equal_to(&[Index(1), Key("foo")])); + assert!(stack.starts_with(&[Index(1), Key("foo")])); + assert!(stack.starts_with(&[Index(1)])); + assert!(stack.ends_with(&[Index(1), Key("foo")])); + assert!(stack.ends_with(&[Key("foo")])); + assert!(!stack.last_is_index()); + assert!(stack.get(0) == Index(1)); + assert!(stack.get(1) == Key("foo")); + + stack.push_key("bar".to_string()); + + assert!(stack.len() == 3); + assert!(stack.is_equal_to(&[Index(1), Key("foo"), Key("bar")])); + assert!(stack.starts_with(&[Index(1)])); + assert!(stack.starts_with(&[Index(1), Key("foo")])); + assert!(stack.starts_with(&[Index(1), Key("foo"), Key("bar")])); + assert!(stack.ends_with(&[Key("bar")])); + assert!(stack.ends_with(&[Key("foo"), Key("bar")])); + assert!(stack.ends_with(&[Index(1), Key("foo"), Key("bar")])); + assert!(!stack.last_is_index()); + assert!(stack.get(0) == Index(1)); + assert!(stack.get(1) == Key("foo")); + assert!(stack.get(2) == Key("bar")); + + stack.pop(); + + assert!(stack.len() == 2); + assert!(stack.is_equal_to(&[Index(1), Key("foo")])); + assert!(stack.starts_with(&[Index(1), Key("foo")])); + assert!(stack.starts_with(&[Index(1)])); + assert!(stack.ends_with(&[Index(1), Key("foo")])); + assert!(stack.ends_with(&[Key("foo")])); + assert!(!stack.last_is_index()); + assert!(stack.get(0) == Index(1)); + assert!(stack.get(1) == Key("foo")); +} +*/ diff --git a/tests/json_struct.rs b/tests/json_struct.rs index a53a1428..bcd5998b 100644 --- a/tests/json_struct.rs +++ b/tests/json_struct.rs @@ -1,8 +1,7 @@ #![feature(plugin)] +#![plugin(serde_macros)] extern crate serde; -#[plugin] -extern crate serde_macros; #[derive(PartialEq, Debug)] #[derive_serialize] diff --git a/tests/ser.rs b/tests/ser.rs new file mode 100644 index 00000000..c70ca3b7 --- /dev/null +++ b/tests/ser.rs @@ -0,0 +1,517 @@ +#![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>, +} + +////////////////////////////////////////////////////////////////////////////// + +#[derive(Clone, PartialEq, Debug)] +#[derive_serialize] +struct Outer { + inner: Vec, +} + +////////////////////////////////////////////////////////////////////////////// + +#[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, +} + +impl<'a, Iter: Iterator>> AssertSerializer { + fn new(iter: Iter) -> AssertSerializer { + 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>> Serializer for AssertSerializer { + 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, 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, 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, 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, Error> + >(&mut self, v: &option::Option) -> 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, Error>, + SeqIter: Iterator + >(&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, Error>, + V: Serialize, Error>, + MapIter: Iterator + >(&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::.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 = 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); +}