diff --git a/src/libserialize/Cargo.toml b/src/libserialize/Cargo.toml index 3e040818d3777..949af0e2b9746 100644 --- a/src/libserialize/Cargo.toml +++ b/src/libserialize/Cargo.toml @@ -2,6 +2,7 @@ authors = ["The Rust Project Developers"] name = "serialize" version = "0.0.0" +edition = "2018" [lib] name = "serialize" diff --git a/src/libserialize/collection_impls.rs b/src/libserialize/collection_impls.rs index f3afc3b53417c..c0a8fa9d0016d 100644 --- a/src/libserialize/collection_impls.rs +++ b/src/libserialize/collection_impls.rs @@ -2,7 +2,7 @@ use std::hash::{Hash, BuildHasher}; -use {Decodable, Encodable, Decoder, Encoder}; +use crate::{Decodable, Encodable, Decoder, Encoder}; use std::collections::{LinkedList, VecDeque, BTreeMap, BTreeSet, HashMap, HashSet}; use std::rc::Rc; use std::sync::Arc; diff --git a/src/libserialize/hex.rs b/src/libserialize/hex.rs index 6127440a6d7d0..73b9122b13cea 100644 --- a/src/libserialize/hex.rs +++ b/src/libserialize/hex.rs @@ -60,7 +60,7 @@ pub enum FromHexError { } impl fmt::Display for FromHexError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { InvalidHexCharacter(ch, idx) => write!(f, "Invalid character '{}' at position {}", ch, idx), @@ -145,8 +145,8 @@ impl FromHex for str { #[cfg(test)] mod tests { extern crate test; - use self::test::Bencher; - use hex::{FromHex, ToHex}; + use test::Bencher; + use crate::hex::{FromHex, ToHex}; #[test] pub fn test_to_hex() { diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index 362b4574ee24e..5b3444b9f456f 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -199,9 +199,8 @@ use std::ops::Index; use std::str::FromStr; use std::string; use std::{char, f64, fmt, str}; -use std; -use Encodable; +use crate::Encodable; /// Represents a json value #[derive(Clone, PartialEq, PartialOrd, Debug)] @@ -221,8 +220,8 @@ pub type Object = BTreeMap; pub struct PrettyJson<'a> { inner: &'a Json } -pub struct AsJson<'a, T: 'a> { inner: &'a T } -pub struct AsPrettyJson<'a, T: 'a> { inner: &'a T, indent: Option } +pub struct AsJson<'a, T> { inner: &'a T } +pub struct AsPrettyJson<'a, T> { inner: &'a T, indent: Option } /// The errors that can arise while parsing a JSON stream. #[derive(Clone, Copy, PartialEq, Debug)] @@ -295,18 +294,18 @@ pub fn error_str(error: ErrorCode) -> &'static str { } /// Shortcut function to decode a JSON `&str` into an object -pub fn decode(s: &str) -> DecodeResult { +pub fn decode(s: &str) -> DecodeResult { let json = match from_str(s) { Ok(x) => x, Err(e) => return Err(ParseError(e)) }; let mut decoder = Decoder::new(json); - ::Decodable::decode(&mut decoder) + crate::Decodable::decode(&mut decoder) } /// Shortcut function to encode a `T` into a JSON `String` -pub fn encode(object: &T) -> Result { +pub fn encode(object: &T) -> Result { let mut s = String::new(); { let mut encoder = Encoder::new(&mut s); @@ -316,7 +315,7 @@ pub fn encode(object: &T) -> Result fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { error_str(*self).fmt(f) } } @@ -326,14 +325,14 @@ fn io_error_to_error(io: io::Error) -> ParserError { } impl fmt::Display for ParserError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // FIXME this should be a nicer error fmt::Debug::fmt(self, f) } } impl fmt::Display for DecoderError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // FIXME this should be a nicer error fmt::Debug::fmt(self, f) } @@ -344,7 +343,7 @@ impl std::error::Error for DecoderError { } impl fmt::Display for EncoderError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // FIXME this should be a nicer error fmt::Debug::fmt(self, f) } @@ -477,7 +476,7 @@ macro_rules! emit_enquoted_if_mapkey { }) } -impl<'a> ::Encoder for Encoder<'a> { +impl<'a> crate::Encoder for Encoder<'a> { type Error = EncoderError; fn emit_unit(&mut self) -> EncodeResult { @@ -727,7 +726,7 @@ impl<'a> PrettyEncoder<'a> { } } -impl<'a> ::Encoder for PrettyEncoder<'a> { +impl<'a> crate::Encoder for PrettyEncoder<'a> { type Error = EncoderError; fn emit_unit(&mut self) -> EncodeResult { @@ -997,7 +996,7 @@ impl<'a> ::Encoder for PrettyEncoder<'a> { } impl Encodable for Json { - fn encode(&self, e: &mut E) -> Result<(), E::Error> { + fn encode(&self, e: &mut E) -> Result<(), E::Error> { match *self { Json::I64(v) => v.encode(e), Json::U64(v) => v.encode(e), @@ -1013,20 +1012,20 @@ impl Encodable for Json { /// Create an `AsJson` wrapper which can be used to print a value as JSON /// on-the-fly via `write!` -pub fn as_json(t: &T) -> AsJson { +pub fn as_json(t: &T) -> AsJson<'_, T> { AsJson { inner: t } } /// Create an `AsPrettyJson` wrapper which can be used to print a value as JSON /// on-the-fly via `write!` -pub fn as_pretty_json(t: &T) -> AsPrettyJson { +pub fn as_pretty_json(t: &T) -> AsPrettyJson<'_, T> { AsPrettyJson { inner: t, indent: None } } impl Json { /// Borrow this json object as a pretty object to generate a pretty /// representation for it via `Display`. - pub fn pretty(&self) -> PrettyJson { + pub fn pretty(&self) -> PrettyJson<'_> { PrettyJson { inner: self } } @@ -1300,7 +1299,7 @@ impl Stack { /// Provides access to the StackElement at a given index. /// lower indices are at the bottom of the stack while higher indices are /// at the top. - pub fn get(&self, idx: usize) -> StackElement { + pub fn get(&self, idx: usize) -> StackElement<'_> { match self.stack[idx] { InternalIndex(i) => StackElement::Index(i), InternalKey(start, size) => { @@ -1311,8 +1310,8 @@ impl Stack { } } - /// Compares this stack with an array of StackElements. - pub fn is_equal_to(&self, rhs: &[StackElement]) -> bool { + /// Compares this stack with an array of StackElement<'_>s. + pub fn is_equal_to(&self, rhs: &[StackElement<'_>]) -> bool { if self.stack.len() != rhs.len() { return false; } for (i, r) in rhs.iter().enumerate() { if self.get(i) != *r { return false; } @@ -1322,7 +1321,7 @@ impl Stack { /// Returns true if the bottom-most elements of this stack are the same as /// the ones passed as parameter. - pub fn starts_with(&self, rhs: &[StackElement]) -> bool { + pub fn starts_with(&self, rhs: &[StackElement<'_>]) -> bool { if self.stack.len() < rhs.len() { return false; } for (i, r) in rhs.iter().enumerate() { if self.get(i) != *r { return false; } @@ -1332,7 +1331,7 @@ impl Stack { /// Returns true if the top-most elements of this stack are the same as /// the ones passed as parameter. - pub fn ends_with(&self, rhs: &[StackElement]) -> bool { + pub fn ends_with(&self, rhs: &[StackElement<'_>]) -> bool { if self.stack.len() < rhs.len() { return false; } let offset = self.stack.len() - rhs.len(); for (i, r) in rhs.iter().enumerate() { @@ -1342,7 +1341,7 @@ impl Stack { } /// Returns the top-most element (if any). - pub fn top(&self) -> Option { + pub fn top(&self) -> Option> { match self.stack.last() { None => None, Some(&InternalIndex(i)) => Some(StackElement::Index(i)), @@ -2115,7 +2114,7 @@ macro_rules! read_primitive { } } -impl ::Decoder for Decoder { +impl crate::Decoder for Decoder { type Error = DecoderError; fn read_nil(&mut self) -> DecodeResult<()> { @@ -2172,7 +2171,7 @@ impl ::Decoder for Decoder { Err(ExpectedError("single character string".to_owned(), s.to_string())) } - fn read_str(&mut self) -> DecodeResult> { + fn read_str(&mut self) -> DecodeResult> { expect!(self.pop(), String).map(Cow::Owned) } @@ -2518,7 +2517,7 @@ impl<'a, 'b> fmt::Write for FormatShim<'a, 'b> { impl fmt::Display for Json { /// Encodes a json value into a string - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut shim = FormatShim { inner: f }; let mut encoder = Encoder::new(&mut shim); match self.encode(&mut encoder) { @@ -2530,7 +2529,7 @@ impl fmt::Display for Json { impl<'a> fmt::Display for PrettyJson<'a> { /// Encodes a json value into a string - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut shim = FormatShim { inner: f }; let mut encoder = PrettyEncoder::new(&mut shim); match self.inner.encode(&mut encoder) { @@ -2542,7 +2541,7 @@ impl<'a> fmt::Display for PrettyJson<'a> { impl<'a, T: Encodable> fmt::Display for AsJson<'a, T> { /// Encodes a json value into a string - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut shim = FormatShim { inner: f }; let mut encoder = Encoder::new(&mut shim); match self.inner.encode(&mut encoder) { @@ -2562,7 +2561,7 @@ impl<'a, T> AsPrettyJson<'a, T> { impl<'a, T: Encodable> fmt::Display for AsPrettyJson<'a, T> { /// Encodes a json value into a string - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut shim = FormatShim { inner: f }; let mut encoder = PrettyEncoder::new(&mut shim); if let Some(n) = self.indent { @@ -2584,1220 +2583,13 @@ impl FromStr for Json { #[cfg(test)] mod tests { + // Benchmarks and tests that require private items + extern crate test; - use self::Animal::*; - use self::test::Bencher; - use {Encodable, Decodable}; - use super::Json::*; - use super::ErrorCode::*; - use super::ParserError::*; - use super::DecoderError::*; - use super::JsonEvent::*; - use super::{Json, from_str, DecodeResult, DecoderError, JsonEvent, Parser, - StackElement, Stack, Decoder, Encoder, EncoderError}; - use std::{i64, u64, f32, f64}; - use std::io::prelude::*; - use std::collections::BTreeMap; + use test::Bencher; + use super::{from_str, Parser, StackElement, Stack}; use std::string; - #[derive(RustcDecodable, Eq, PartialEq, Debug)] - struct OptionData { - opt: Option, - } - - #[test] - fn test_decode_option_none() { - let s ="{}"; - let obj: OptionData = super::decode(s).unwrap(); - assert_eq!(obj, OptionData { opt: None }); - } - - #[test] - fn test_decode_option_some() { - let s = "{ \"opt\": 10 }"; - let obj: OptionData = super::decode(s).unwrap(); - assert_eq!(obj, OptionData { opt: Some(10) }); - } - - #[test] - fn test_decode_option_malformed() { - check_err::("{ \"opt\": [] }", - ExpectedError("Number".to_string(), "[]".to_string())); - check_err::("{ \"opt\": false }", - ExpectedError("Number".to_string(), "false".to_string())); - } - - #[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)] - enum Animal { - Dog, - Frog(string::String, isize) - } - - #[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)] - struct Inner { - a: (), - b: usize, - c: Vec, - } - - #[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)] - struct Outer { - inner: Vec, - } - - fn mk_object(items: &[(string::String, Json)]) -> Json { - let mut d = BTreeMap::new(); - - for item in items { - match *item { - (ref key, ref value) => { d.insert((*key).clone(), (*value).clone()); }, - } - }; - - Object(d) - } - - #[test] - fn test_from_str_trait() { - let s = "null"; - assert!(s.parse::().unwrap() == s.parse().unwrap()); - } - - #[test] - fn test_write_null() { - assert_eq!(Null.to_string(), "null"); - assert_eq!(Null.pretty().to_string(), "null"); - } - - #[test] - fn test_write_i64() { - assert_eq!(U64(0).to_string(), "0"); - assert_eq!(U64(0).pretty().to_string(), "0"); - - assert_eq!(U64(1234).to_string(), "1234"); - assert_eq!(U64(1234).pretty().to_string(), "1234"); - - assert_eq!(I64(-5678).to_string(), "-5678"); - assert_eq!(I64(-5678).pretty().to_string(), "-5678"); - - assert_eq!(U64(7650007200025252000).to_string(), "7650007200025252000"); - assert_eq!(U64(7650007200025252000).pretty().to_string(), "7650007200025252000"); - } - - #[test] - fn test_write_f64() { - assert_eq!(F64(3.0).to_string(), "3.0"); - assert_eq!(F64(3.0).pretty().to_string(), "3.0"); - - assert_eq!(F64(3.1).to_string(), "3.1"); - assert_eq!(F64(3.1).pretty().to_string(), "3.1"); - - assert_eq!(F64(-1.5).to_string(), "-1.5"); - assert_eq!(F64(-1.5).pretty().to_string(), "-1.5"); - - assert_eq!(F64(0.5).to_string(), "0.5"); - assert_eq!(F64(0.5).pretty().to_string(), "0.5"); - - assert_eq!(F64(f64::NAN).to_string(), "null"); - assert_eq!(F64(f64::NAN).pretty().to_string(), "null"); - - assert_eq!(F64(f64::INFINITY).to_string(), "null"); - assert_eq!(F64(f64::INFINITY).pretty().to_string(), "null"); - - assert_eq!(F64(f64::NEG_INFINITY).to_string(), "null"); - assert_eq!(F64(f64::NEG_INFINITY).pretty().to_string(), "null"); - } - - #[test] - fn test_write_str() { - assert_eq!(String("".to_string()).to_string(), "\"\""); - assert_eq!(String("".to_string()).pretty().to_string(), "\"\""); - - assert_eq!(String("homura".to_string()).to_string(), "\"homura\""); - assert_eq!(String("madoka".to_string()).pretty().to_string(), "\"madoka\""); - } - - #[test] - fn test_write_bool() { - assert_eq!(Boolean(true).to_string(), "true"); - assert_eq!(Boolean(true).pretty().to_string(), "true"); - - assert_eq!(Boolean(false).to_string(), "false"); - assert_eq!(Boolean(false).pretty().to_string(), "false"); - } - - #[test] - fn test_write_array() { - assert_eq!(Array(vec![]).to_string(), "[]"); - assert_eq!(Array(vec![]).pretty().to_string(), "[]"); - - assert_eq!(Array(vec![Boolean(true)]).to_string(), "[true]"); - assert_eq!( - Array(vec![Boolean(true)]).pretty().to_string(), - "\ - [\n \ - true\n\ - ]" - ); - - let long_test_array = Array(vec![ - Boolean(false), - Null, - Array(vec![String("foo\nbar".to_string()), F64(3.5)])]); - - assert_eq!(long_test_array.to_string(), - "[false,null,[\"foo\\nbar\",3.5]]"); - assert_eq!( - long_test_array.pretty().to_string(), - "\ - [\n \ - false,\n \ - null,\n \ - [\n \ - \"foo\\nbar\",\n \ - 3.5\n \ - ]\n\ - ]" - ); - } - - #[test] - fn test_write_object() { - assert_eq!(mk_object(&[]).to_string(), "{}"); - assert_eq!(mk_object(&[]).pretty().to_string(), "{}"); - - assert_eq!( - mk_object(&[ - ("a".to_string(), Boolean(true)) - ]).to_string(), - "{\"a\":true}" - ); - assert_eq!( - mk_object(&[("a".to_string(), Boolean(true))]).pretty().to_string(), - "\ - {\n \ - \"a\": true\n\ - }" - ); - - let complex_obj = mk_object(&[ - ("b".to_string(), Array(vec![ - mk_object(&[("c".to_string(), String("\x0c\r".to_string()))]), - mk_object(&[("d".to_string(), String("".to_string()))]) - ])) - ]); - - assert_eq!( - complex_obj.to_string(), - "{\ - \"b\":[\ - {\"c\":\"\\f\\r\"},\ - {\"d\":\"\"}\ - ]\ - }" - ); - assert_eq!( - complex_obj.pretty().to_string(), - "\ - {\n \ - \"b\": [\n \ - {\n \ - \"c\": \"\\f\\r\"\n \ - },\n \ - {\n \ - \"d\": \"\"\n \ - }\n \ - ]\n\ - }" - ); - - let a = mk_object(&[ - ("a".to_string(), Boolean(true)), - ("b".to_string(), Array(vec![ - mk_object(&[("c".to_string(), String("\x0c\r".to_string()))]), - mk_object(&[("d".to_string(), String("".to_string()))]) - ])) - ]); - - // We can't compare the strings directly because the object fields be - // printed in a different order. - assert_eq!(a.clone(), a.to_string().parse().unwrap()); - assert_eq!(a.clone(), a.pretty().to_string().parse().unwrap()); - } - - #[test] - fn test_write_enum() { - let animal = Dog; - assert_eq!( - super::as_json(&animal).to_string(), - "\"Dog\"" - ); - assert_eq!( - super::as_pretty_json(&animal).to_string(), - "\"Dog\"" - ); - - let animal = Frog("Henry".to_string(), 349); - assert_eq!( - super::as_json(&animal).to_string(), - "{\"variant\":\"Frog\",\"fields\":[\"Henry\",349]}" - ); - assert_eq!( - super::as_pretty_json(&animal).to_string(), - "{\n \ - \"variant\": \"Frog\",\n \ - \"fields\": [\n \ - \"Henry\",\n \ - 349\n \ - ]\n\ - }" - ); - } - - macro_rules! check_encoder_for_simple { - ($value:expr, $expected:expr) => ({ - let s = super::as_json(&$value).to_string(); - assert_eq!(s, $expected); - - let s = super::as_pretty_json(&$value).to_string(); - assert_eq!(s, $expected); - }) - } - - #[test] - fn test_write_some() { - check_encoder_for_simple!(Some("jodhpurs".to_string()), "\"jodhpurs\""); - } - - #[test] - fn test_write_none() { - check_encoder_for_simple!(None::, "null"); - } - - #[test] - fn test_write_char() { - check_encoder_for_simple!('a', "\"a\""); - check_encoder_for_simple!('\t', "\"\\t\""); - check_encoder_for_simple!('\u{0000}', "\"\\u0000\""); - check_encoder_for_simple!('\u{001b}', "\"\\u001b\""); - check_encoder_for_simple!('\u{007f}', "\"\\u007f\""); - check_encoder_for_simple!('\u{00a0}', "\"\u{00a0}\""); - check_encoder_for_simple!('\u{abcd}', "\"\u{abcd}\""); - check_encoder_for_simple!('\u{10ffff}', "\"\u{10ffff}\""); - } - - #[test] - fn test_trailing_characters() { - assert_eq!(from_str("nulla"), Err(SyntaxError(TrailingCharacters, 1, 5))); - assert_eq!(from_str("truea"), Err(SyntaxError(TrailingCharacters, 1, 5))); - assert_eq!(from_str("falsea"), Err(SyntaxError(TrailingCharacters, 1, 6))); - assert_eq!(from_str("1a"), Err(SyntaxError(TrailingCharacters, 1, 2))); - assert_eq!(from_str("[]a"), Err(SyntaxError(TrailingCharacters, 1, 3))); - assert_eq!(from_str("{}a"), Err(SyntaxError(TrailingCharacters, 1, 3))); - } - - #[test] - fn test_read_identifiers() { - assert_eq!(from_str("n"), Err(SyntaxError(InvalidSyntax, 1, 2))); - assert_eq!(from_str("nul"), Err(SyntaxError(InvalidSyntax, 1, 4))); - assert_eq!(from_str("t"), Err(SyntaxError(InvalidSyntax, 1, 2))); - assert_eq!(from_str("truz"), Err(SyntaxError(InvalidSyntax, 1, 4))); - assert_eq!(from_str("f"), Err(SyntaxError(InvalidSyntax, 1, 2))); - assert_eq!(from_str("faz"), Err(SyntaxError(InvalidSyntax, 1, 3))); - - assert_eq!(from_str("null"), Ok(Null)); - assert_eq!(from_str("true"), Ok(Boolean(true))); - assert_eq!(from_str("false"), Ok(Boolean(false))); - assert_eq!(from_str(" null "), Ok(Null)); - assert_eq!(from_str(" true "), Ok(Boolean(true))); - assert_eq!(from_str(" false "), Ok(Boolean(false))); - } - - #[test] - fn test_decode_identifiers() { - let v: () = super::decode("null").unwrap(); - assert_eq!(v, ()); - - let v: bool = super::decode("true").unwrap(); - assert_eq!(v, true); - - let v: bool = super::decode("false").unwrap(); - assert_eq!(v, false); - } - - #[test] - fn test_read_number() { - assert_eq!(from_str("+"), Err(SyntaxError(InvalidSyntax, 1, 1))); - assert_eq!(from_str("."), Err(SyntaxError(InvalidSyntax, 1, 1))); - assert_eq!(from_str("NaN"), Err(SyntaxError(InvalidSyntax, 1, 1))); - assert_eq!(from_str("-"), Err(SyntaxError(InvalidNumber, 1, 2))); - assert_eq!(from_str("00"), Err(SyntaxError(InvalidNumber, 1, 2))); - assert_eq!(from_str("1."), Err(SyntaxError(InvalidNumber, 1, 3))); - assert_eq!(from_str("1e"), Err(SyntaxError(InvalidNumber, 1, 3))); - assert_eq!(from_str("1e+"), Err(SyntaxError(InvalidNumber, 1, 4))); - - assert_eq!(from_str("18446744073709551616"), Err(SyntaxError(InvalidNumber, 1, 20))); - assert_eq!(from_str("-9223372036854775809"), Err(SyntaxError(InvalidNumber, 1, 21))); - - assert_eq!(from_str("3"), Ok(U64(3))); - assert_eq!(from_str("3.1"), Ok(F64(3.1))); - assert_eq!(from_str("-1.2"), Ok(F64(-1.2))); - assert_eq!(from_str("0.4"), Ok(F64(0.4))); - assert_eq!(from_str("0.4e5"), Ok(F64(0.4e5))); - assert_eq!(from_str("0.4e+15"), Ok(F64(0.4e15))); - assert_eq!(from_str("0.4e-01"), Ok(F64(0.4e-01))); - assert_eq!(from_str(" 3 "), Ok(U64(3))); - - assert_eq!(from_str("-9223372036854775808"), Ok(I64(i64::MIN))); - assert_eq!(from_str("9223372036854775807"), Ok(U64(i64::MAX as u64))); - assert_eq!(from_str("18446744073709551615"), Ok(U64(u64::MAX))); - } - - #[test] - fn test_decode_numbers() { - let v: f64 = super::decode("3").unwrap(); - assert_eq!(v, 3.0); - - let v: f64 = super::decode("3.1").unwrap(); - assert_eq!(v, 3.1); - - let v: f64 = super::decode("-1.2").unwrap(); - assert_eq!(v, -1.2); - - let v: f64 = super::decode("0.4").unwrap(); - assert_eq!(v, 0.4); - - let v: f64 = super::decode("0.4e5").unwrap(); - assert_eq!(v, 0.4e5); - - let v: f64 = super::decode("0.4e15").unwrap(); - assert_eq!(v, 0.4e15); - - let v: f64 = super::decode("0.4e-01").unwrap(); - assert_eq!(v, 0.4e-01); - - let v: u64 = super::decode("0").unwrap(); - assert_eq!(v, 0); - - let v: u64 = super::decode("18446744073709551615").unwrap(); - assert_eq!(v, u64::MAX); - - let v: i64 = super::decode("-9223372036854775808").unwrap(); - assert_eq!(v, i64::MIN); - - let v: i64 = super::decode("9223372036854775807").unwrap(); - assert_eq!(v, i64::MAX); - - let res: DecodeResult = super::decode("765.25"); - assert_eq!(res, Err(ExpectedError("Integer".to_string(), - "765.25".to_string()))); - } - - #[test] - fn test_read_str() { - assert_eq!(from_str("\""), Err(SyntaxError(EOFWhileParsingString, 1, 2))); - assert_eq!(from_str("\"lol"), Err(SyntaxError(EOFWhileParsingString, 1, 5))); - - assert_eq!(from_str("\"\""), Ok(String("".to_string()))); - assert_eq!(from_str("\"foo\""), Ok(String("foo".to_string()))); - assert_eq!(from_str("\"\\\"\""), Ok(String("\"".to_string()))); - assert_eq!(from_str("\"\\b\""), Ok(String("\x08".to_string()))); - assert_eq!(from_str("\"\\n\""), Ok(String("\n".to_string()))); - assert_eq!(from_str("\"\\r\""), Ok(String("\r".to_string()))); - assert_eq!(from_str("\"\\t\""), Ok(String("\t".to_string()))); - assert_eq!(from_str(" \"foo\" "), Ok(String("foo".to_string()))); - assert_eq!(from_str("\"\\u12ab\""), Ok(String("\u{12ab}".to_string()))); - assert_eq!(from_str("\"\\uAB12\""), Ok(String("\u{AB12}".to_string()))); - } - - #[test] - fn test_decode_str() { - let s = [("\"\"", ""), - ("\"foo\"", "foo"), - ("\"\\\"\"", "\""), - ("\"\\b\"", "\x08"), - ("\"\\n\"", "\n"), - ("\"\\r\"", "\r"), - ("\"\\t\"", "\t"), - ("\"\\u12ab\"", "\u{12ab}"), - ("\"\\uAB12\"", "\u{AB12}")]; - - for &(i, o) in &s { - let v: string::String = super::decode(i).unwrap(); - assert_eq!(v, o); - } - } - - #[test] - fn test_read_array() { - assert_eq!(from_str("["), Err(SyntaxError(EOFWhileParsingValue, 1, 2))); - assert_eq!(from_str("[1"), Err(SyntaxError(EOFWhileParsingArray, 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))); - - assert_eq!(from_str("[]"), Ok(Array(vec![]))); - assert_eq!(from_str("[ ]"), Ok(Array(vec![]))); - assert_eq!(from_str("[true]"), Ok(Array(vec![Boolean(true)]))); - assert_eq!(from_str("[ false ]"), Ok(Array(vec![Boolean(false)]))); - assert_eq!(from_str("[null]"), Ok(Array(vec![Null]))); - assert_eq!(from_str("[3, 1]"), - Ok(Array(vec![U64(3), U64(1)]))); - assert_eq!(from_str("\n[3, 2]\n"), - Ok(Array(vec![U64(3), U64(2)]))); - assert_eq!(from_str("[2, [4, 1]]"), - Ok(Array(vec![U64(2), Array(vec![U64(4), U64(1)])]))); - } - - #[test] - fn test_decode_array() { - let v: Vec<()> = super::decode("[]").unwrap(); - assert_eq!(v, []); - - let v: Vec<()> = super::decode("[null]").unwrap(); - assert_eq!(v, [()]); - - let v: Vec = super::decode("[true]").unwrap(); - assert_eq!(v, [true]); - - let v: Vec = super::decode("[3, 1]").unwrap(); - assert_eq!(v, [3, 1]); - - let v: Vec> = super::decode("[[3], [1, 2]]").unwrap(); - assert_eq!(v, [vec![3], vec![1, 2]]); - } - - #[test] - fn test_decode_tuple() { - let t: (usize, usize, usize) = super::decode("[1, 2, 3]").unwrap(); - assert_eq!(t, (1, 2, 3)); - - let t: (usize, string::String) = super::decode("[1, \"two\"]").unwrap(); - assert_eq!(t, (1, "two".to_string())); - } - - #[test] - fn test_decode_tuple_malformed_types() { - assert!(super::decode::<(usize, string::String)>("[1, 2]").is_err()); - } - - #[test] - fn test_decode_tuple_malformed_length() { - assert!(super::decode::<(usize, usize)>("[1, 2, 3]").is_err()); - } - - #[test] - fn test_read_object() { - assert_eq!(from_str("{"), Err(SyntaxError(EOFWhileParsingObject, 1, 2))); - assert_eq!(from_str("{ "), Err(SyntaxError(EOFWhileParsingObject, 1, 3))); - assert_eq!(from_str("{1"), Err(SyntaxError(KeyMustBeAString, 1, 2))); - assert_eq!(from_str("{ \"a\""), Err(SyntaxError(EOFWhileParsingObject, 1, 6))); - assert_eq!(from_str("{\"a\""), Err(SyntaxError(EOFWhileParsingObject, 1, 5))); - assert_eq!(from_str("{\"a\" "), Err(SyntaxError(EOFWhileParsingObject, 1, 6))); - - assert_eq!(from_str("{\"a\" 1"), Err(SyntaxError(ExpectedColon, 1, 6))); - assert_eq!(from_str("{\"a\":"), Err(SyntaxError(EOFWhileParsingValue, 1, 6))); - assert_eq!(from_str("{\"a\":1"), Err(SyntaxError(EOFWhileParsingObject, 1, 7))); - assert_eq!(from_str("{\"a\":1 1"), Err(SyntaxError(InvalidSyntax, 1, 8))); - assert_eq!(from_str("{\"a\":1,"), Err(SyntaxError(EOFWhileParsingObject, 1, 8))); - - assert_eq!(from_str("{}").unwrap(), mk_object(&[])); - assert_eq!(from_str("{\"a\": 3}").unwrap(), - mk_object(&[("a".to_string(), U64(3))])); - - assert_eq!(from_str( - "{ \"a\": null, \"b\" : true }").unwrap(), - mk_object(&[ - ("a".to_string(), Null), - ("b".to_string(), Boolean(true))])); - assert_eq!(from_str("\n{ \"a\": null, \"b\" : true }\n").unwrap(), - mk_object(&[ - ("a".to_string(), Null), - ("b".to_string(), Boolean(true))])); - assert_eq!(from_str( - "{\"a\" : 1.0 ,\"b\": [ true ]}").unwrap(), - mk_object(&[ - ("a".to_string(), F64(1.0)), - ("b".to_string(), Array(vec![Boolean(true)])) - ])); - assert_eq!(from_str( - "{\ - \"a\": 1.0, \ - \"b\": [\ - true,\ - \"foo\\nbar\", \ - { \"c\": {\"d\": null} } \ - ]\ - }").unwrap(), - mk_object(&[ - ("a".to_string(), F64(1.0)), - ("b".to_string(), Array(vec![ - Boolean(true), - String("foo\nbar".to_string()), - mk_object(&[ - ("c".to_string(), mk_object(&[("d".to_string(), Null)])) - ]) - ])) - ])); - } - - #[test] - fn test_decode_struct() { - let s = "{ - \"inner\": [ - { \"a\": null, \"b\": 2, \"c\": [\"abc\", \"xyz\"] } - ] - }"; - - let v: Outer = super::decode(s).unwrap(); - assert_eq!( - v, - Outer { - inner: vec![ - Inner { a: (), b: 2, c: vec!["abc".to_string(), "xyz".to_string()] } - ] - } - ); - } - - #[derive(RustcDecodable)] - struct FloatStruct { - f: f64, - a: Vec - } - #[test] - fn test_decode_struct_with_nan() { - let s = "{\"f\":null,\"a\":[null,123]}"; - let obj: FloatStruct = super::decode(s).unwrap(); - assert!(obj.f.is_nan()); - assert!(obj.a[0].is_nan()); - assert_eq!(obj.a[1], 123f64); - } - - #[test] - fn test_decode_option() { - let value: Option = super::decode("null").unwrap(); - assert_eq!(value, None); - - let value: Option = super::decode("\"jodhpurs\"").unwrap(); - assert_eq!(value, Some("jodhpurs".to_string())); - } - - #[test] - fn test_decode_enum() { - let value: Animal = super::decode("\"Dog\"").unwrap(); - assert_eq!(value, Dog); - - let s = "{\"variant\":\"Frog\",\"fields\":[\"Henry\",349]}"; - let value: Animal = super::decode(s).unwrap(); - assert_eq!(value, Frog("Henry".to_string(), 349)); - } - - #[test] - fn test_decode_map() { - let s = "{\"a\": \"Dog\", \"b\": {\"variant\":\"Frog\",\ - \"fields\":[\"Henry\", 349]}}"; - let mut map: BTreeMap = super::decode(s).unwrap(); - - assert_eq!(map.remove(&"a".to_string()), Some(Dog)); - assert_eq!(map.remove(&"b".to_string()), Some(Frog("Henry".to_string(), 349))); - } - - #[test] - fn test_multiline_errors() { - assert_eq!(from_str("{\n \"foo\":\n \"bar\""), - Err(SyntaxError(EOFWhileParsingObject, 3, 8))); - } - - #[derive(RustcDecodable)] - #[allow(dead_code)] - struct DecodeStruct { - x: f64, - y: bool, - z: string::String, - w: Vec - } - #[derive(RustcDecodable)] - enum DecodeEnum { - A(f64), - B(string::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) => Decodable::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("Array".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("Array".to_string(), "null".to_string())); - check_err::("{\"variant\": \"C\", \"fields\": []}", - UnknownVariantError("C".to_string())); - } - - #[test] - fn test_find(){ - let json_value = from_str("{\"dog\" : \"cat\"}").unwrap(); - let found_str = json_value.find("dog"); - assert!(found_str.unwrap().as_string().unwrap() == "cat"); - } - - #[test] - fn test_find_path(){ - let json_value = from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap(); - let found_str = json_value.find_path(&["dog", "cat", "mouse"]); - assert!(found_str.unwrap().as_string().unwrap() == "cheese"); - } - - #[test] - fn test_search(){ - let json_value = from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap(); - let found_str = json_value.search("mouse").and_then(|j| j.as_string()); - assert!(found_str.unwrap() == "cheese"); - } - - #[test] - fn test_index(){ - let json_value = from_str("{\"animals\":[\"dog\",\"cat\",\"mouse\"]}").unwrap(); - let ref array = json_value["animals"]; - assert_eq!(array[0].as_string().unwrap(), "dog"); - assert_eq!(array[1].as_string().unwrap(), "cat"); - assert_eq!(array[2].as_string().unwrap(), "mouse"); - } - - #[test] - fn test_is_object(){ - let json_value = from_str("{}").unwrap(); - assert!(json_value.is_object()); - } - - #[test] - fn test_as_object(){ - let json_value = from_str("{}").unwrap(); - let json_object = json_value.as_object(); - assert!(json_object.is_some()); - } - - #[test] - fn test_is_array(){ - let json_value = from_str("[1, 2, 3]").unwrap(); - assert!(json_value.is_array()); - } - - #[test] - fn test_as_array(){ - let json_value = from_str("[1, 2, 3]").unwrap(); - let json_array = json_value.as_array(); - let expected_length = 3; - assert!(json_array.is_some() && json_array.unwrap().len() == expected_length); - } - - #[test] - fn test_is_string(){ - let json_value = from_str("\"dog\"").unwrap(); - assert!(json_value.is_string()); - } - - #[test] - fn test_as_string(){ - let json_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 = from_str("12").unwrap(); - assert!(json_value.is_number()); - } - - #[test] - fn test_is_i64(){ - let json_value = from_str("-12").unwrap(); - assert!(json_value.is_i64()); - - let json_value = from_str("12").unwrap(); - assert!(!json_value.is_i64()); - - let json_value = from_str("12.0").unwrap(); - assert!(!json_value.is_i64()); - } - - #[test] - fn test_is_u64(){ - let json_value = from_str("12").unwrap(); - assert!(json_value.is_u64()); - - let json_value = from_str("-12").unwrap(); - assert!(!json_value.is_u64()); - - let json_value = from_str("12.0").unwrap(); - assert!(!json_value.is_u64()); - } - - #[test] - fn test_is_f64(){ - let json_value = from_str("12").unwrap(); - assert!(!json_value.is_f64()); - - let json_value = from_str("-12").unwrap(); - assert!(!json_value.is_f64()); - - let json_value = from_str("12.0").unwrap(); - assert!(json_value.is_f64()); - - let json_value = from_str("-12.0").unwrap(); - assert!(json_value.is_f64()); - } - - #[test] - fn test_as_i64(){ - let json_value = from_str("-12").unwrap(); - let json_num = json_value.as_i64(); - assert_eq!(json_num, Some(-12)); - } - - #[test] - fn test_as_u64(){ - let json_value = from_str("12").unwrap(); - let json_num = json_value.as_u64(); - assert_eq!(json_num, Some(12)); - } - - #[test] - fn test_as_f64(){ - let json_value = from_str("12.0").unwrap(); - let json_num = json_value.as_f64(); - assert_eq!(json_num, Some(12f64)); - } - - #[test] - fn test_is_boolean(){ - let json_value = from_str("false").unwrap(); - assert!(json_value.is_boolean()); - } - - #[test] - fn test_as_boolean(){ - let json_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 = from_str("null").unwrap(); - assert!(json_value.is_null()); - } - - #[test] - fn test_as_null(){ - let json_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 = Vec::new(); - write!(&mut mem_buf, "{}", super::as_pretty_json(&hm)).unwrap(); - let json_str = from_utf8(&mem_buf[..]).unwrap(); - match from_str(json_str) { - Err(_) => panic!("Unable to parse json_str: {:?}", json_str), - _ => {} // it parsed and we are good to go - } - } - - #[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 = Vec::new(); - write!(&mut mem_buf, "{}", super::as_pretty_json(&hm)).unwrap(); - let json_str = from_utf8(&mem_buf[..]).unwrap(); - match from_str(json_str) { - Err(_) => panic!("Unable to parse json_str: {:?}", json_str), - _ => {} // it parsed and we are good to go - } - } - - #[test] - fn test_prettyencoder_indent_level_param() { - use std::str::from_utf8; - use std::collections::BTreeMap; - - let mut tree = BTreeMap::new(); - - tree.insert("hello".to_string(), String("guten tag".to_string())); - tree.insert("goodbye".to_string(), String("sayonara".to_string())); - - let json = Array( - // The following layout below should look a lot like - // the pretty-printed JSON (indent * x) - vec! - ( // 0x - String("greetings".to_string()), // 1x - Object(tree), // 1x + 2x + 2x + 1x - ) // 0x - // End JSON array (7 lines) - ); - - // Helper function for counting indents - fn indents(source: &str) -> usize { - let trimmed = source.trim_start_matches(' '); - source.len() - trimmed.len() - } - - // Test up to 4 spaces of indents (more?) - for i in 0..4 { - let mut writer = Vec::new(); - write!(&mut writer, "{}", - super::as_pretty_json(&json).indent(i)).unwrap(); - - let printed = from_utf8(&writer[..]).unwrap(); - - // Check for indents at each line - let lines: Vec<&str> = printed.lines().collect(); - assert_eq!(lines.len(), 7); // JSON should be 7 lines - - assert_eq!(indents(lines[0]), 0 * i); // [ - assert_eq!(indents(lines[1]), 1 * i); // "greetings", - assert_eq!(indents(lines[2]), 1 * i); // { - assert_eq!(indents(lines[3]), 2 * i); // "hello": "guten tag", - assert_eq!(indents(lines[4]), 2 * i); // "goodbye": "sayonara" - assert_eq!(indents(lines[5]), 1 * i); // }, - assert_eq!(indents(lines[6]), 0 * i); // ] - - // Finally, test that the pretty-printed JSON is valid - from_str(printed).ok().expect("Pretty-printed JSON is invalid!"); - } - } - - #[test] - fn test_hashmap_with_enum_key() { - use std::collections::HashMap; - use json; - #[derive(RustcEncodable, Eq, Hash, PartialEq, RustcDecodable, Debug)] - enum Enum { - Foo, - #[allow(dead_code)] - Bar, - } - let mut map = HashMap::new(); - map.insert(Enum::Foo, 0); - let result = json::encode(&map).unwrap(); - assert_eq!(&result[..], r#"{"Foo":0}"#); - let decoded: HashMap = json::decode(&result).unwrap(); - assert_eq!(map, decoded); - } - - #[test] - fn test_hashmap_with_numeric_key_can_handle_double_quote_delimited_key() { - use std::collections::HashMap; - use Decodable; - let json_str = "{\"1\":true}"; - let json_obj = match from_str(json_str) { - Err(_) => panic!("Unable to parse json_str: {:?}", json_str), - Ok(o) => o - }; - let mut decoder = Decoder::new(json_obj); - let _hm: HashMap = Decodable::decode(&mut decoder).unwrap(); - } - - #[test] - fn test_hashmap_with_numeric_key_will_error_with_string_keys() { - use std::collections::HashMap; - use Decodable; - let json_str = "{\"a\":true}"; - let json_obj = match from_str(json_str) { - Err(_) => panic!("Unable to parse json_str: {:?}", json_str), - Ok(o) => o - }; - let mut decoder = Decoder::new(json_obj); - let result: Result, DecoderError> = Decodable::decode(&mut decoder); - assert_eq!(result, Err(ExpectedError("Number".to_string(), "a".to_string()))); - } - - fn assert_stream_equal(src: &str, - expected: Vec<(JsonEvent, Vec)>) { - 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]}"#, - vec![ - (ObjectStart, vec![]), - (StringValue("bar".to_string()), vec![StackElement::Key("foo")]), - (ArrayStart, vec![StackElement::Key("array")]), - (U64Value(0), vec![StackElement::Key("array"), StackElement::Index(0)]), - (U64Value(1), vec![StackElement::Key("array"), StackElement::Index(1)]), - (U64Value(2), vec![StackElement::Key("array"), StackElement::Index(2)]), - (U64Value(3), vec![StackElement::Key("array"), StackElement::Index(3)]), - (U64Value(4), vec![StackElement::Key("array"), StackElement::Index(4)]), - (U64Value(5), vec![StackElement::Key("array"), StackElement::Index(5)]), - (ArrayEnd, vec![StackElement::Key("array")]), - (ArrayStart, vec![StackElement::Key("idents")]), - (NullValue, vec![StackElement::Key("idents"), - StackElement::Index(0)]), - (BooleanValue(true), vec![StackElement::Key("idents"), - StackElement::Index(1)]), - (BooleanValue(false), vec![StackElement::Key("idents"), - StackElement::Index(2)]), - (ArrayEnd, vec![StackElement::Key("idents")]), - (ObjectEnd, vec![]), - ] - ); - } - 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] - 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_eq!(last_event("{\"a\":1,}"), Error(SyntaxError(TrailingComma, 1, 8))); - - assert_stream_equal( - "{}", - vec![(ObjectStart, vec![]), (ObjectEnd, vec![])] - ); - assert_stream_equal( - "{\"a\": 3}", - vec![ - (ObjectStart, vec![]), - (U64Value(3), vec![StackElement::Key("a")]), - (ObjectEnd, vec![]), - ] - ); - assert_stream_equal( - "{ \"a\": null, \"b\" : true }", - vec![ - (ObjectStart, vec![]), - (NullValue, vec![StackElement::Key("a")]), - (BooleanValue(true), vec![StackElement::Key("b")]), - (ObjectEnd, vec![]), - ] - ); - assert_stream_equal( - "{\"a\" : 1.0 ,\"b\": [ true ]}", - vec![ - (ObjectStart, vec![]), - (F64Value(1.0), vec![StackElement::Key("a")]), - (ArrayStart, vec![StackElement::Key("b")]), - (BooleanValue(true),vec![StackElement::Key("b"), StackElement::Index(0)]), - (ArrayEnd, vec![StackElement::Key("b")]), - (ObjectEnd, vec![]), - ] - ); - assert_stream_equal( - r#"{ - "a": 1.0, - "b": [ - true, - "foo\nbar", - { "c": {"d": null} } - ] - }"#, - vec![ - (ObjectStart, vec![]), - (F64Value(1.0), vec![StackElement::Key("a")]), - (ArrayStart, vec![StackElement::Key("b")]), - (BooleanValue(true), vec![StackElement::Key("b"), - StackElement::Index(0)]), - (StringValue("foo\nbar".to_string()), vec![StackElement::Key("b"), - StackElement::Index(1)]), - (ObjectStart, vec![StackElement::Key("b"), - StackElement::Index(2)]), - (ObjectStart, vec![StackElement::Key("b"), - StackElement::Index(2), - StackElement::Key("c")]), - (NullValue, vec![StackElement::Key("b"), - StackElement::Index(2), - StackElement::Key("c"), - StackElement::Key("d")]), - (ObjectEnd, vec![StackElement::Key("b"), - StackElement::Index(2), - StackElement::Key("c")]), - (ObjectEnd, vec![StackElement::Key("b"), - StackElement::Index(2)]), - (ArrayEnd, vec![StackElement::Key("b")]), - (ObjectEnd, vec![]), - ] - ); - } - #[test] - fn test_read_array_streaming() { - assert_stream_equal( - "[]", - vec![ - (ArrayStart, vec![]), - (ArrayEnd, vec![]), - ] - ); - assert_stream_equal( - "[ ]", - vec![ - (ArrayStart, vec![]), - (ArrayEnd, vec![]), - ] - ); - assert_stream_equal( - "[true]", - vec![ - (ArrayStart, vec![]), - (BooleanValue(true), vec![StackElement::Index(0)]), - (ArrayEnd, vec![]), - ] - ); - assert_stream_equal( - "[ false ]", - vec![ - (ArrayStart, vec![]), - (BooleanValue(false), vec![StackElement::Index(0)]), - (ArrayEnd, vec![]), - ] - ); - assert_stream_equal( - "[null]", - vec![ - (ArrayStart, vec![]), - (NullValue, vec![StackElement::Index(0)]), - (ArrayEnd, vec![]), - ] - ); - assert_stream_equal( - "[3, 1]", - vec![ - (ArrayStart, vec![]), - (U64Value(3), vec![StackElement::Index(0)]), - (U64Value(1), vec![StackElement::Index(1)]), - (ArrayEnd, vec![]), - ] - ); - assert_stream_equal( - "\n[3, 2]\n", - vec![ - (ArrayStart, vec![]), - (U64Value(3), vec![StackElement::Index(0)]), - (U64Value(2), vec![StackElement::Index(1)]), - (ArrayEnd, vec![]), - ] - ); - assert_stream_equal( - "[2, [4, 1]]", - vec![ - (ArrayStart, vec![]), - (U64Value(2), vec![StackElement::Index(0)]), - (ArrayStart, vec![StackElement::Index(1)]), - (U64Value(4), vec![StackElement::Index(1), StackElement::Index(0)]), - (U64Value(1), vec![StackElement::Index(1), StackElement::Index(1)]), - (ArrayEnd, vec![StackElement::Index(1)]), - (ArrayEnd, vec![]), - ] - ); - - 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(EOFWhileParsingArray, 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(); @@ -3862,76 +2654,6 @@ mod tests { assert!(stack.get(1) == StackElement::Key("foo")); } - #[test] - fn test_to_json() { - use std::collections::{HashMap,BTreeMap}; - use super::ToJson; - - let array2 = Array(vec![U64(1), U64(2)]); - let array3 = Array(vec![U64(1), U64(2), U64(3)]); - let object = { - let mut tree_map = BTreeMap::new(); - tree_map.insert("a".to_string(), U64(1)); - tree_map.insert("b".to_string(), U64(2)); - Object(tree_map) - }; - - assert_eq!(array2.to_json(), array2); - assert_eq!(object.to_json(), object); - assert_eq!(3_isize.to_json(), I64(3)); - assert_eq!(4_i8.to_json(), I64(4)); - assert_eq!(5_i16.to_json(), I64(5)); - assert_eq!(6_i32.to_json(), I64(6)); - assert_eq!(7_i64.to_json(), I64(7)); - assert_eq!(8_usize.to_json(), U64(8)); - assert_eq!(9_u8.to_json(), U64(9)); - assert_eq!(10_u16.to_json(), U64(10)); - assert_eq!(11_u32.to_json(), U64(11)); - assert_eq!(12_u64.to_json(), U64(12)); - assert_eq!(13.0_f32.to_json(), F64(13.0_f64)); - assert_eq!(14.0_f64.to_json(), F64(14.0_f64)); - assert_eq!(().to_json(), Null); - assert_eq!(f32::INFINITY.to_json(), Null); - assert_eq!(f64::NAN.to_json(), Null); - assert_eq!(true.to_json(), Boolean(true)); - assert_eq!(false.to_json(), Boolean(false)); - assert_eq!("abc".to_json(), String("abc".to_string())); - assert_eq!("abc".to_string().to_json(), String("abc".to_string())); - assert_eq!((1_usize, 2_usize).to_json(), array2); - assert_eq!((1_usize, 2_usize, 3_usize).to_json(), array3); - assert_eq!([1_usize, 2_usize].to_json(), array2); - assert_eq!((&[1_usize, 2_usize, 3_usize]).to_json(), array3); - assert_eq!((vec![1_usize, 2_usize]).to_json(), array2); - assert_eq!(vec![1_usize, 2_usize, 3_usize].to_json(), array3); - let mut tree_map = BTreeMap::new(); - tree_map.insert("a".to_string(), 1 as usize); - tree_map.insert("b".to_string(), 2); - assert_eq!(tree_map.to_json(), object); - let mut hash_map = HashMap::new(); - hash_map.insert("a".to_string(), 1 as usize); - hash_map.insert("b".to_string(), 2); - assert_eq!(hash_map.to_json(), object); - assert_eq!(Some(15).to_json(), I64(15)); - assert_eq!(Some(15 as usize).to_json(), U64(15)); - assert_eq!(None::.to_json(), Null); - } - - #[test] - fn test_encode_hashmap_with_arbitrary_key() { - use std::collections::HashMap; - #[derive(PartialEq, Eq, Hash, RustcEncodable)] - struct ArbitraryType(usize); - let mut hm: HashMap = HashMap::new(); - hm.insert(ArbitraryType(1), true); - let mut mem_buf = string::String::new(); - let mut encoder = Encoder::new(&mut mem_buf); - let result = hm.encode(&mut encoder); - match result.unwrap_err() { - EncoderError::BadHashmapKey => (), - _ => panic!("expected bad hash map key") - } - } - #[bench] fn bench_streaming_small(b: &mut Bencher) { b.iter( || { diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index fe93a2dfb29b1..b8eeb4d2b34af 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -8,6 +8,8 @@ Core encoding and decoding interfaces. html_playground_url = "https://play.rust-lang.org/", test(attr(allow(unused_variables), deny(warnings))))] +#![deny(rust_2018_idioms)] + #![feature(box_syntax)] #![feature(core_intrinsics)] #![feature(specialization)] @@ -20,8 +22,6 @@ pub use self::serialize::{Decoder, Encoder, Decodable, Encodable}; pub use self::serialize::{SpecializationError, SpecializedEncoder, SpecializedDecoder}; pub use self::serialize::{UseSpecializedEncodable, UseSpecializedDecodable}; -extern crate smallvec; - mod serialize; mod collection_impls; @@ -30,7 +30,3 @@ pub mod json; pub mod opaque; pub mod leb128; - -mod rustc_serialize { - pub use serialize::*; -} diff --git a/src/libserialize/opaque.rs b/src/libserialize/opaque.rs index b8d4f8a79f34b..a6a5c318079f1 100644 --- a/src/libserialize/opaque.rs +++ b/src/libserialize/opaque.rs @@ -1,6 +1,6 @@ -use leb128::{self, read_signed_leb128, write_signed_leb128}; +use crate::leb128::{self, read_signed_leb128, write_signed_leb128}; +use crate::serialize; use std::borrow::Cow; -use serialize; // ----------------------------------------------------------------------------- // Encoder @@ -312,7 +312,7 @@ impl<'a> serialize::Decoder for Decoder<'a> { } #[inline] - fn read_str(&mut self) -> Result, Self::Error> { + fn read_str(&mut self) -> Result, Self::Error> { let len = self.read_usize()?; let s = ::std::str::from_utf8(&self.data[self.position..self.position + len]).unwrap(); self.position += len; @@ -324,288 +324,3 @@ impl<'a> serialize::Decoder for Decoder<'a> { err.to_string() } } - - -#[cfg(test)] -mod tests { - use serialize::{Encodable, Decodable}; - use std::fmt::Debug; - use super::{Encoder, Decoder}; - - #[derive(PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)] - struct Struct { - a: (), - b: u8, - c: u16, - d: u32, - e: u64, - f: usize, - - g: i8, - h: i16, - i: i32, - j: i64, - k: isize, - - l: char, - m: String, - n: f32, - o: f64, - p: bool, - q: Option, - } - - - fn check_round_trip(values: Vec) { - let mut encoder = Encoder::new(Vec::new()); - - for value in &values { - Encodable::encode(&value, &mut encoder).unwrap(); - } - - let data = encoder.into_inner(); - let mut decoder = Decoder::new(&data[..], 0); - - for value in values { - let decoded = Decodable::decode(&mut decoder).unwrap(); - assert_eq!(value, decoded); - } - } - - #[test] - fn test_unit() { - check_round_trip(vec![(), (), (), ()]); - } - - #[test] - fn test_u8() { - let mut vec = vec![]; - for i in ::std::u8::MIN..::std::u8::MAX { - vec.push(i); - } - check_round_trip(vec); - } - - #[test] - fn test_u16() { - for i in ::std::u16::MIN..::std::u16::MAX { - check_round_trip(vec![1, 2, 3, i, i, i]); - } - } - - #[test] - fn test_u32() { - check_round_trip(vec![1, 2, 3, ::std::u32::MIN, 0, 1, ::std::u32::MAX, 2, 1]); - } - - #[test] - fn test_u64() { - check_round_trip(vec![1, 2, 3, ::std::u64::MIN, 0, 1, ::std::u64::MAX, 2, 1]); - } - - #[test] - fn test_usize() { - check_round_trip(vec![1, 2, 3, ::std::usize::MIN, 0, 1, ::std::usize::MAX, 2, 1]); - } - - #[test] - fn test_i8() { - let mut vec = vec![]; - for i in ::std::i8::MIN..::std::i8::MAX { - vec.push(i); - } - check_round_trip(vec); - } - - #[test] - fn test_i16() { - for i in ::std::i16::MIN..::std::i16::MAX { - check_round_trip(vec![-1, 2, -3, i, i, i, 2]); - } - } - - #[test] - fn test_i32() { - check_round_trip(vec![-1, 2, -3, ::std::i32::MIN, 0, 1, ::std::i32::MAX, 2, 1]); - } - - #[test] - fn test_i64() { - check_round_trip(vec![-1, 2, -3, ::std::i64::MIN, 0, 1, ::std::i64::MAX, 2, 1]); - } - - #[test] - fn test_isize() { - check_round_trip(vec![-1, 2, -3, ::std::isize::MIN, 0, 1, ::std::isize::MAX, 2, 1]); - } - - #[test] - fn test_bool() { - check_round_trip(vec![false, true, true, false, false]); - } - - #[test] - fn test_f32() { - let mut vec = vec![]; - for i in -100..100 { - vec.push((i as f32) / 3.0); - } - check_round_trip(vec); - } - - #[test] - fn test_f64() { - let mut vec = vec![]; - for i in -100..100 { - vec.push((i as f64) / 3.0); - } - check_round_trip(vec); - } - - #[test] - fn test_char() { - let vec = vec!['a', 'b', 'c', 'd', 'A', 'X', ' ', '#', 'Ö', 'Ä', 'µ', '€']; - check_round_trip(vec); - } - - #[test] - fn test_string() { - let vec = vec!["abcbuÖeiovÄnameÜavmpßvmea€µsbpnvapeapmaebn".to_string(), - "abcbuÖganeiovÄnameÜavmpßvmea€µsbpnvapeapmaebn".to_string(), - "abcbuÖganeiovÄnameÜavmpßvmea€µsbpapmaebn".to_string(), - "abcbuÖganeiovÄnameÜavmpßvmeabpnvapeapmaebn".to_string(), - "abcbuÖganeiÄnameÜavmpßvmea€µsbpnvapeapmaebn".to_string(), - "abcbuÖganeiovÄnameÜavmpßvmea€µsbpmaebn".to_string(), - "abcbuÖganeiovÄnameÜavmpßvmea€µnvapeapmaebn".to_string()]; - - check_round_trip(vec); - } - - #[test] - fn test_option() { - check_round_trip(vec![Some(-1i8)]); - check_round_trip(vec![Some(-2i16)]); - check_round_trip(vec![Some(-3i32)]); - check_round_trip(vec![Some(-4i64)]); - check_round_trip(vec![Some(-5isize)]); - - let none_i8: Option = None; - check_round_trip(vec![none_i8]); - - let none_i16: Option = None; - check_round_trip(vec![none_i16]); - - let none_i32: Option = None; - check_round_trip(vec![none_i32]); - - let none_i64: Option = None; - check_round_trip(vec![none_i64]); - - let none_isize: Option = None; - check_round_trip(vec![none_isize]); - } - - #[test] - fn test_struct() { - check_round_trip(vec![Struct { - a: (), - b: 10, - c: 11, - d: 12, - e: 13, - f: 14, - - g: 15, - h: 16, - i: 17, - j: 18, - k: 19, - - l: 'x', - m: "abc".to_string(), - n: 20.5, - o: 21.5, - p: false, - q: None, - }]); - - check_round_trip(vec![Struct { - a: (), - b: 101, - c: 111, - d: 121, - e: 131, - f: 141, - - g: -15, - h: -16, - i: -17, - j: -18, - k: -19, - - l: 'y', - m: "def".to_string(), - n: -20.5, - o: -21.5, - p: true, - q: Some(1234567), - }]); - } - - #[derive(PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)] - enum Enum { - Variant1, - Variant2(usize, f32), - Variant3 { - a: i32, - b: char, - c: bool, - }, - } - - #[test] - fn test_enum() { - check_round_trip(vec![Enum::Variant1, - Enum::Variant2(1, 2.5), - Enum::Variant3 { - a: 3, - b: 'b', - c: false, - }, - Enum::Variant3 { - a: -4, - b: 'f', - c: true, - }]); - } - - #[test] - fn test_sequence() { - let mut vec = vec![]; - for i in -100i64..100i64 { - vec.push(i * 100000); - } - - check_round_trip(vec![vec]); - } - - #[test] - fn test_hash_map() { - use std::collections::HashMap; - let mut map = HashMap::new(); - for i in -100i64..100i64 { - map.insert(i * 100000, i * 10000); - } - - check_round_trip(vec![map]); - } - - #[test] - fn test_tuples() { - check_round_trip(vec![('x', (), false, 0.5f32)]); - check_round_trip(vec![(9i8, 10u16, 1.5f64)]); - check_round_trip(vec![(-12i16, 11u8, 12usize)]); - check_round_trip(vec![(1234567isize, 100000000000000u64, 99999999999999i64)]); - check_round_trip(vec![(String::new(), "some string".to_string())]); - } -} diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs index 03844b387ac81..977a36a220fdd 100644 --- a/src/libserialize/serialize.rs +++ b/src/libserialize/serialize.rs @@ -175,7 +175,7 @@ pub trait Decoder { fn read_f64(&mut self) -> Result; fn read_f32(&mut self) -> Result; fn read_char(&mut self) -> Result; - fn read_str(&mut self) -> Result, Self::Error>; + fn read_str(&mut self) -> Result, Self::Error>; // Compound types: fn read_enum(&mut self, _name: &str, f: F) -> Result diff --git a/src/libserialize/tests/json.rs b/src/libserialize/tests/json.rs new file mode 100644 index 0000000000000..3fb6bda679bc1 --- /dev/null +++ b/src/libserialize/tests/json.rs @@ -0,0 +1,1282 @@ +extern crate serialize as rustc_serialize; + +use rustc_serialize::{Encodable, Decodable}; +use rustc_serialize::json; +use json::Json::*; +use json::ErrorCode::*; +use json::ParserError::*; +use json::DecoderError::*; +use json::JsonEvent::*; +use json::{Json, from_str, DecodeResult, DecoderError, JsonEvent, Parser, StackElement, + Decoder, Encoder, EncoderError}; + +use Animal::*; +use std::{i64, u64, f32, f64}; +use std::io::prelude::*; +use std::collections::BTreeMap; +use std::string; + +#[derive(RustcDecodable, Eq, PartialEq, Debug)] +struct OptionData { + opt: Option, +} + +#[test] +fn test_decode_option_none() { + let s ="{}"; + let obj: OptionData = json::decode(s).unwrap(); + assert_eq!(obj, OptionData { opt: None }); +} + +#[test] +fn test_decode_option_some() { + let s = "{ \"opt\": 10 }"; + let obj: OptionData = json::decode(s).unwrap(); + assert_eq!(obj, OptionData { opt: Some(10) }); +} + +#[test] +fn test_decode_option_malformed() { + check_err::("{ \"opt\": [] }", + ExpectedError("Number".to_string(), "[]".to_string())); + check_err::("{ \"opt\": false }", + ExpectedError("Number".to_string(), "false".to_string())); +} + +#[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)] +enum Animal { + Dog, + Frog(string::String, isize) +} + +#[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)] +struct Inner { + a: (), + b: usize, + c: Vec, +} + +#[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)] +struct Outer { + inner: Vec, +} + +fn mk_object(items: &[(string::String, Json)]) -> Json { + let mut d = BTreeMap::new(); + + for item in items { + match *item { + (ref key, ref value) => { d.insert((*key).clone(), (*value).clone()); }, + } + }; + + Object(d) +} + +#[test] +fn test_from_str_trait() { + let s = "null"; + assert!(s.parse::().unwrap() == s.parse().unwrap()); +} + +#[test] +fn test_write_null() { + assert_eq!(Null.to_string(), "null"); + assert_eq!(Null.pretty().to_string(), "null"); +} + +#[test] +fn test_write_i64() { + assert_eq!(U64(0).to_string(), "0"); + assert_eq!(U64(0).pretty().to_string(), "0"); + + assert_eq!(U64(1234).to_string(), "1234"); + assert_eq!(U64(1234).pretty().to_string(), "1234"); + + assert_eq!(I64(-5678).to_string(), "-5678"); + assert_eq!(I64(-5678).pretty().to_string(), "-5678"); + + assert_eq!(U64(7650007200025252000).to_string(), "7650007200025252000"); + assert_eq!(U64(7650007200025252000).pretty().to_string(), "7650007200025252000"); +} + +#[test] +fn test_write_f64() { + assert_eq!(F64(3.0).to_string(), "3.0"); + assert_eq!(F64(3.0).pretty().to_string(), "3.0"); + + assert_eq!(F64(3.1).to_string(), "3.1"); + assert_eq!(F64(3.1).pretty().to_string(), "3.1"); + + assert_eq!(F64(-1.5).to_string(), "-1.5"); + assert_eq!(F64(-1.5).pretty().to_string(), "-1.5"); + + assert_eq!(F64(0.5).to_string(), "0.5"); + assert_eq!(F64(0.5).pretty().to_string(), "0.5"); + + assert_eq!(F64(f64::NAN).to_string(), "null"); + assert_eq!(F64(f64::NAN).pretty().to_string(), "null"); + + assert_eq!(F64(f64::INFINITY).to_string(), "null"); + assert_eq!(F64(f64::INFINITY).pretty().to_string(), "null"); + + assert_eq!(F64(f64::NEG_INFINITY).to_string(), "null"); + assert_eq!(F64(f64::NEG_INFINITY).pretty().to_string(), "null"); +} + +#[test] +fn test_write_str() { + assert_eq!(String("".to_string()).to_string(), "\"\""); + assert_eq!(String("".to_string()).pretty().to_string(), "\"\""); + + assert_eq!(String("homura".to_string()).to_string(), "\"homura\""); + assert_eq!(String("madoka".to_string()).pretty().to_string(), "\"madoka\""); +} + +#[test] +fn test_write_bool() { + assert_eq!(Boolean(true).to_string(), "true"); + assert_eq!(Boolean(true).pretty().to_string(), "true"); + + assert_eq!(Boolean(false).to_string(), "false"); + assert_eq!(Boolean(false).pretty().to_string(), "false"); +} + +#[test] +fn test_write_array() { + assert_eq!(Array(vec![]).to_string(), "[]"); + assert_eq!(Array(vec![]).pretty().to_string(), "[]"); + + assert_eq!(Array(vec![Boolean(true)]).to_string(), "[true]"); + assert_eq!( + Array(vec![Boolean(true)]).pretty().to_string(), + "\ + [\n \ + true\n\ + ]" + ); + + let long_test_array = Array(vec![ + Boolean(false), + Null, + Array(vec![String("foo\nbar".to_string()), F64(3.5)])]); + + assert_eq!(long_test_array.to_string(), + "[false,null,[\"foo\\nbar\",3.5]]"); + assert_eq!( + long_test_array.pretty().to_string(), + "\ + [\n \ + false,\n \ + null,\n \ + [\n \ + \"foo\\nbar\",\n \ + 3.5\n \ + ]\n\ + ]" + ); +} + +#[test] +fn test_write_object() { + assert_eq!(mk_object(&[]).to_string(), "{}"); + assert_eq!(mk_object(&[]).pretty().to_string(), "{}"); + + assert_eq!( + mk_object(&[ + ("a".to_string(), Boolean(true)) + ]).to_string(), + "{\"a\":true}" + ); + assert_eq!( + mk_object(&[("a".to_string(), Boolean(true))]).pretty().to_string(), + "\ + {\n \ + \"a\": true\n\ + }" + ); + + let complex_obj = mk_object(&[ + ("b".to_string(), Array(vec![ + mk_object(&[("c".to_string(), String("\x0c\r".to_string()))]), + mk_object(&[("d".to_string(), String("".to_string()))]) + ])) + ]); + + assert_eq!( + complex_obj.to_string(), + "{\ + \"b\":[\ + {\"c\":\"\\f\\r\"},\ + {\"d\":\"\"}\ + ]\ + }" + ); + assert_eq!( + complex_obj.pretty().to_string(), + "\ + {\n \ + \"b\": [\n \ + {\n \ + \"c\": \"\\f\\r\"\n \ + },\n \ + {\n \ + \"d\": \"\"\n \ + }\n \ + ]\n\ + }" + ); + + let a = mk_object(&[ + ("a".to_string(), Boolean(true)), + ("b".to_string(), Array(vec![ + mk_object(&[("c".to_string(), String("\x0c\r".to_string()))]), + mk_object(&[("d".to_string(), String("".to_string()))]) + ])) + ]); + + // We can't compare the strings directly because the object fields be + // printed in a different order. + assert_eq!(a.clone(), a.to_string().parse().unwrap()); + assert_eq!(a.clone(), a.pretty().to_string().parse().unwrap()); +} + +#[test] +fn test_write_enum() { + let animal = Dog; + assert_eq!( + json::as_json(&animal).to_string(), + "\"Dog\"" + ); + assert_eq!( + json::as_pretty_json(&animal).to_string(), + "\"Dog\"" + ); + + let animal = Frog("Henry".to_string(), 349); + assert_eq!( + json::as_json(&animal).to_string(), + "{\"variant\":\"Frog\",\"fields\":[\"Henry\",349]}" + ); + assert_eq!( + json::as_pretty_json(&animal).to_string(), + "{\n \ + \"variant\": \"Frog\",\n \ + \"fields\": [\n \ + \"Henry\",\n \ + 349\n \ + ]\n\ + }" + ); +} + +macro_rules! check_encoder_for_simple { + ($value:expr, $expected:expr) => ({ + let s = json::as_json(&$value).to_string(); + assert_eq!(s, $expected); + + let s = json::as_pretty_json(&$value).to_string(); + assert_eq!(s, $expected); + }) +} + +#[test] +fn test_write_some() { + check_encoder_for_simple!(Some("jodhpurs".to_string()), "\"jodhpurs\""); +} + +#[test] +fn test_write_none() { + check_encoder_for_simple!(None::, "null"); +} + +#[test] +fn test_write_char() { + check_encoder_for_simple!('a', "\"a\""); + check_encoder_for_simple!('\t', "\"\\t\""); + check_encoder_for_simple!('\u{0000}', "\"\\u0000\""); + check_encoder_for_simple!('\u{001b}', "\"\\u001b\""); + check_encoder_for_simple!('\u{007f}', "\"\\u007f\""); + check_encoder_for_simple!('\u{00a0}', "\"\u{00a0}\""); + check_encoder_for_simple!('\u{abcd}', "\"\u{abcd}\""); + check_encoder_for_simple!('\u{10ffff}', "\"\u{10ffff}\""); +} + +#[test] +fn test_trailing_characters() { + assert_eq!(from_str("nulla"), Err(SyntaxError(TrailingCharacters, 1, 5))); + assert_eq!(from_str("truea"), Err(SyntaxError(TrailingCharacters, 1, 5))); + assert_eq!(from_str("falsea"), Err(SyntaxError(TrailingCharacters, 1, 6))); + assert_eq!(from_str("1a"), Err(SyntaxError(TrailingCharacters, 1, 2))); + assert_eq!(from_str("[]a"), Err(SyntaxError(TrailingCharacters, 1, 3))); + assert_eq!(from_str("{}a"), Err(SyntaxError(TrailingCharacters, 1, 3))); +} + +#[test] +fn test_read_identifiers() { + assert_eq!(from_str("n"), Err(SyntaxError(InvalidSyntax, 1, 2))); + assert_eq!(from_str("nul"), Err(SyntaxError(InvalidSyntax, 1, 4))); + assert_eq!(from_str("t"), Err(SyntaxError(InvalidSyntax, 1, 2))); + assert_eq!(from_str("truz"), Err(SyntaxError(InvalidSyntax, 1, 4))); + assert_eq!(from_str("f"), Err(SyntaxError(InvalidSyntax, 1, 2))); + assert_eq!(from_str("faz"), Err(SyntaxError(InvalidSyntax, 1, 3))); + + assert_eq!(from_str("null"), Ok(Null)); + assert_eq!(from_str("true"), Ok(Boolean(true))); + assert_eq!(from_str("false"), Ok(Boolean(false))); + assert_eq!(from_str(" null "), Ok(Null)); + assert_eq!(from_str(" true "), Ok(Boolean(true))); + assert_eq!(from_str(" false "), Ok(Boolean(false))); +} + +#[test] +fn test_decode_identifiers() { + let v: () = json::decode("null").unwrap(); + assert_eq!(v, ()); + + let v: bool = json::decode("true").unwrap(); + assert_eq!(v, true); + + let v: bool = json::decode("false").unwrap(); + assert_eq!(v, false); +} + +#[test] +fn test_read_number() { + assert_eq!(from_str("+"), Err(SyntaxError(InvalidSyntax, 1, 1))); + assert_eq!(from_str("."), Err(SyntaxError(InvalidSyntax, 1, 1))); + assert_eq!(from_str("NaN"), Err(SyntaxError(InvalidSyntax, 1, 1))); + assert_eq!(from_str("-"), Err(SyntaxError(InvalidNumber, 1, 2))); + assert_eq!(from_str("00"), Err(SyntaxError(InvalidNumber, 1, 2))); + assert_eq!(from_str("1."), Err(SyntaxError(InvalidNumber, 1, 3))); + assert_eq!(from_str("1e"), Err(SyntaxError(InvalidNumber, 1, 3))); + assert_eq!(from_str("1e+"), Err(SyntaxError(InvalidNumber, 1, 4))); + + assert_eq!(from_str("18446744073709551616"), Err(SyntaxError(InvalidNumber, 1, 20))); + assert_eq!(from_str("-9223372036854775809"), Err(SyntaxError(InvalidNumber, 1, 21))); + + assert_eq!(from_str("3"), Ok(U64(3))); + assert_eq!(from_str("3.1"), Ok(F64(3.1))); + assert_eq!(from_str("-1.2"), Ok(F64(-1.2))); + assert_eq!(from_str("0.4"), Ok(F64(0.4))); + assert_eq!(from_str("0.4e5"), Ok(F64(0.4e5))); + assert_eq!(from_str("0.4e+15"), Ok(F64(0.4e15))); + assert_eq!(from_str("0.4e-01"), Ok(F64(0.4e-01))); + assert_eq!(from_str(" 3 "), Ok(U64(3))); + + assert_eq!(from_str("-9223372036854775808"), Ok(I64(i64::MIN))); + assert_eq!(from_str("9223372036854775807"), Ok(U64(i64::MAX as u64))); + assert_eq!(from_str("18446744073709551615"), Ok(U64(u64::MAX))); +} + +#[test] +fn test_decode_numbers() { + let v: f64 = json::decode("3").unwrap(); + assert_eq!(v, 3.0); + + let v: f64 = json::decode("3.1").unwrap(); + assert_eq!(v, 3.1); + + let v: f64 = json::decode("-1.2").unwrap(); + assert_eq!(v, -1.2); + + let v: f64 = json::decode("0.4").unwrap(); + assert_eq!(v, 0.4); + + let v: f64 = json::decode("0.4e5").unwrap(); + assert_eq!(v, 0.4e5); + + let v: f64 = json::decode("0.4e15").unwrap(); + assert_eq!(v, 0.4e15); + + let v: f64 = json::decode("0.4e-01").unwrap(); + assert_eq!(v, 0.4e-01); + + let v: u64 = json::decode("0").unwrap(); + assert_eq!(v, 0); + + let v: u64 = json::decode("18446744073709551615").unwrap(); + assert_eq!(v, u64::MAX); + + let v: i64 = json::decode("-9223372036854775808").unwrap(); + assert_eq!(v, i64::MIN); + + let v: i64 = json::decode("9223372036854775807").unwrap(); + assert_eq!(v, i64::MAX); + + let res: DecodeResult = json::decode("765.25"); + assert_eq!(res, Err(ExpectedError("Integer".to_string(), + "765.25".to_string()))); +} + +#[test] +fn test_read_str() { + assert_eq!(from_str("\""), Err(SyntaxError(EOFWhileParsingString, 1, 2))); + assert_eq!(from_str("\"lol"), Err(SyntaxError(EOFWhileParsingString, 1, 5))); + + assert_eq!(from_str("\"\""), Ok(String("".to_string()))); + assert_eq!(from_str("\"foo\""), Ok(String("foo".to_string()))); + assert_eq!(from_str("\"\\\"\""), Ok(String("\"".to_string()))); + assert_eq!(from_str("\"\\b\""), Ok(String("\x08".to_string()))); + assert_eq!(from_str("\"\\n\""), Ok(String("\n".to_string()))); + assert_eq!(from_str("\"\\r\""), Ok(String("\r".to_string()))); + assert_eq!(from_str("\"\\t\""), Ok(String("\t".to_string()))); + assert_eq!(from_str(" \"foo\" "), Ok(String("foo".to_string()))); + assert_eq!(from_str("\"\\u12ab\""), Ok(String("\u{12ab}".to_string()))); + assert_eq!(from_str("\"\\uAB12\""), Ok(String("\u{AB12}".to_string()))); +} + +#[test] +fn test_decode_str() { + let s = [("\"\"", ""), + ("\"foo\"", "foo"), + ("\"\\\"\"", "\""), + ("\"\\b\"", "\x08"), + ("\"\\n\"", "\n"), + ("\"\\r\"", "\r"), + ("\"\\t\"", "\t"), + ("\"\\u12ab\"", "\u{12ab}"), + ("\"\\uAB12\"", "\u{AB12}")]; + + for &(i, o) in &s { + let v: string::String = json::decode(i).unwrap(); + assert_eq!(v, o); + } +} + +#[test] +fn test_read_array() { + assert_eq!(from_str("["), Err(SyntaxError(EOFWhileParsingValue, 1, 2))); + assert_eq!(from_str("[1"), Err(SyntaxError(EOFWhileParsingArray, 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))); + + assert_eq!(from_str("[]"), Ok(Array(vec![]))); + assert_eq!(from_str("[ ]"), Ok(Array(vec![]))); + assert_eq!(from_str("[true]"), Ok(Array(vec![Boolean(true)]))); + assert_eq!(from_str("[ false ]"), Ok(Array(vec![Boolean(false)]))); + assert_eq!(from_str("[null]"), Ok(Array(vec![Null]))); + assert_eq!(from_str("[3, 1]"), + Ok(Array(vec![U64(3), U64(1)]))); + assert_eq!(from_str("\n[3, 2]\n"), + Ok(Array(vec![U64(3), U64(2)]))); + assert_eq!(from_str("[2, [4, 1]]"), + Ok(Array(vec![U64(2), Array(vec![U64(4), U64(1)])]))); +} + +#[test] +fn test_decode_array() { + let v: Vec<()> = json::decode("[]").unwrap(); + assert_eq!(v, []); + + let v: Vec<()> = json::decode("[null]").unwrap(); + assert_eq!(v, [()]); + + let v: Vec = json::decode("[true]").unwrap(); + assert_eq!(v, [true]); + + let v: Vec = json::decode("[3, 1]").unwrap(); + assert_eq!(v, [3, 1]); + + let v: Vec> = json::decode("[[3], [1, 2]]").unwrap(); + assert_eq!(v, [vec![3], vec![1, 2]]); +} + +#[test] +fn test_decode_tuple() { + let t: (usize, usize, usize) = json::decode("[1, 2, 3]").unwrap(); + assert_eq!(t, (1, 2, 3)); + + let t: (usize, string::String) = json::decode("[1, \"two\"]").unwrap(); + assert_eq!(t, (1, "two".to_string())); +} + +#[test] +fn test_decode_tuple_malformed_types() { + assert!(json::decode::<(usize, string::String)>("[1, 2]").is_err()); +} + +#[test] +fn test_decode_tuple_malformed_length() { + assert!(json::decode::<(usize, usize)>("[1, 2, 3]").is_err()); +} + +#[test] +fn test_read_object() { + assert_eq!(from_str("{"), Err(SyntaxError(EOFWhileParsingObject, 1, 2))); + assert_eq!(from_str("{ "), Err(SyntaxError(EOFWhileParsingObject, 1, 3))); + assert_eq!(from_str("{1"), Err(SyntaxError(KeyMustBeAString, 1, 2))); + assert_eq!(from_str("{ \"a\""), Err(SyntaxError(EOFWhileParsingObject, 1, 6))); + assert_eq!(from_str("{\"a\""), Err(SyntaxError(EOFWhileParsingObject, 1, 5))); + assert_eq!(from_str("{\"a\" "), Err(SyntaxError(EOFWhileParsingObject, 1, 6))); + + assert_eq!(from_str("{\"a\" 1"), Err(SyntaxError(ExpectedColon, 1, 6))); + assert_eq!(from_str("{\"a\":"), Err(SyntaxError(EOFWhileParsingValue, 1, 6))); + assert_eq!(from_str("{\"a\":1"), Err(SyntaxError(EOFWhileParsingObject, 1, 7))); + assert_eq!(from_str("{\"a\":1 1"), Err(SyntaxError(InvalidSyntax, 1, 8))); + assert_eq!(from_str("{\"a\":1,"), Err(SyntaxError(EOFWhileParsingObject, 1, 8))); + + assert_eq!(from_str("{}").unwrap(), mk_object(&[])); + assert_eq!(from_str("{\"a\": 3}").unwrap(), + mk_object(&[("a".to_string(), U64(3))])); + + assert_eq!(from_str( + "{ \"a\": null, \"b\" : true }").unwrap(), + mk_object(&[ + ("a".to_string(), Null), + ("b".to_string(), Boolean(true))])); + assert_eq!(from_str("\n{ \"a\": null, \"b\" : true }\n").unwrap(), + mk_object(&[ + ("a".to_string(), Null), + ("b".to_string(), Boolean(true))])); + assert_eq!(from_str( + "{\"a\" : 1.0 ,\"b\": [ true ]}").unwrap(), + mk_object(&[ + ("a".to_string(), F64(1.0)), + ("b".to_string(), Array(vec![Boolean(true)])) + ])); + assert_eq!(from_str( + "{\ + \"a\": 1.0, \ + \"b\": [\ + true,\ + \"foo\\nbar\", \ + { \"c\": {\"d\": null} } \ + ]\ + }").unwrap(), + mk_object(&[ + ("a".to_string(), F64(1.0)), + ("b".to_string(), Array(vec![ + Boolean(true), + String("foo\nbar".to_string()), + mk_object(&[ + ("c".to_string(), mk_object(&[("d".to_string(), Null)])) + ]) + ])) + ])); +} + +#[test] +fn test_decode_struct() { + let s = "{ + \"inner\": [ + { \"a\": null, \"b\": 2, \"c\": [\"abc\", \"xyz\"] } + ] + }"; + + let v: Outer = json::decode(s).unwrap(); + assert_eq!( + v, + Outer { + inner: vec![ + Inner { a: (), b: 2, c: vec!["abc".to_string(), "xyz".to_string()] } + ] + } + ); +} + +#[derive(RustcDecodable)] +struct FloatStruct { + f: f64, + a: Vec +} +#[test] +fn test_decode_struct_with_nan() { + let s = "{\"f\":null,\"a\":[null,123]}"; + let obj: FloatStruct = json::decode(s).unwrap(); + assert!(obj.f.is_nan()); + assert!(obj.a[0].is_nan()); + assert_eq!(obj.a[1], 123f64); +} + +#[test] +fn test_decode_option() { + let value: Option = json::decode("null").unwrap(); + assert_eq!(value, None); + + let value: Option = json::decode("\"jodhpurs\"").unwrap(); + assert_eq!(value, Some("jodhpurs".to_string())); +} + +#[test] +fn test_decode_enum() { + let value: Animal = json::decode("\"Dog\"").unwrap(); + assert_eq!(value, Dog); + + let s = "{\"variant\":\"Frog\",\"fields\":[\"Henry\",349]}"; + let value: Animal = json::decode(s).unwrap(); + assert_eq!(value, Frog("Henry".to_string(), 349)); +} + +#[test] +fn test_decode_map() { + let s = "{\"a\": \"Dog\", \"b\": {\"variant\":\"Frog\",\ + \"fields\":[\"Henry\", 349]}}"; + let mut map: BTreeMap = json::decode(s).unwrap(); + + assert_eq!(map.remove(&"a".to_string()), Some(Dog)); + assert_eq!(map.remove(&"b".to_string()), Some(Frog("Henry".to_string(), 349))); +} + +#[test] +fn test_multiline_errors() { + assert_eq!(from_str("{\n \"foo\":\n \"bar\""), + Err(SyntaxError(EOFWhileParsingObject, 3, 8))); +} + +#[derive(RustcDecodable)] +#[allow(dead_code)] +struct DecodeStruct { + x: f64, + y: bool, + z: string::String, + w: Vec +} +#[derive(RustcDecodable)] +enum DecodeEnum { + A(f64), + B(string::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) => Decodable::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("Array".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("Array".to_string(), "null".to_string())); + check_err::("{\"variant\": \"C\", \"fields\": []}", + UnknownVariantError("C".to_string())); +} + +#[test] +fn test_find(){ + let json_value = from_str("{\"dog\" : \"cat\"}").unwrap(); + let found_str = json_value.find("dog"); + assert!(found_str.unwrap().as_string().unwrap() == "cat"); +} + +#[test] +fn test_find_path(){ + let json_value = from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap(); + let found_str = json_value.find_path(&["dog", "cat", "mouse"]); + assert!(found_str.unwrap().as_string().unwrap() == "cheese"); +} + +#[test] +fn test_search(){ + let json_value = from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap(); + let found_str = json_value.search("mouse").and_then(|j| j.as_string()); + assert!(found_str.unwrap() == "cheese"); +} + +#[test] +fn test_index(){ + let json_value = from_str("{\"animals\":[\"dog\",\"cat\",\"mouse\"]}").unwrap(); + let ref array = json_value["animals"]; + assert_eq!(array[0].as_string().unwrap(), "dog"); + assert_eq!(array[1].as_string().unwrap(), "cat"); + assert_eq!(array[2].as_string().unwrap(), "mouse"); +} + +#[test] +fn test_is_object(){ + let json_value = from_str("{}").unwrap(); + assert!(json_value.is_object()); +} + +#[test] +fn test_as_object(){ + let json_value = from_str("{}").unwrap(); + let json_object = json_value.as_object(); + assert!(json_object.is_some()); +} + +#[test] +fn test_is_array(){ + let json_value = from_str("[1, 2, 3]").unwrap(); + assert!(json_value.is_array()); +} + +#[test] +fn test_as_array(){ + let json_value = from_str("[1, 2, 3]").unwrap(); + let json_array = json_value.as_array(); + let expected_length = 3; + assert!(json_array.is_some() && json_array.unwrap().len() == expected_length); +} + +#[test] +fn test_is_string(){ + let json_value = from_str("\"dog\"").unwrap(); + assert!(json_value.is_string()); +} + +#[test] +fn test_as_string(){ + let json_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 = from_str("12").unwrap(); + assert!(json_value.is_number()); +} + +#[test] +fn test_is_i64(){ + let json_value = from_str("-12").unwrap(); + assert!(json_value.is_i64()); + + let json_value = from_str("12").unwrap(); + assert!(!json_value.is_i64()); + + let json_value = from_str("12.0").unwrap(); + assert!(!json_value.is_i64()); +} + +#[test] +fn test_is_u64(){ + let json_value = from_str("12").unwrap(); + assert!(json_value.is_u64()); + + let json_value = from_str("-12").unwrap(); + assert!(!json_value.is_u64()); + + let json_value = from_str("12.0").unwrap(); + assert!(!json_value.is_u64()); +} + +#[test] +fn test_is_f64(){ + let json_value = from_str("12").unwrap(); + assert!(!json_value.is_f64()); + + let json_value = from_str("-12").unwrap(); + assert!(!json_value.is_f64()); + + let json_value = from_str("12.0").unwrap(); + assert!(json_value.is_f64()); + + let json_value = from_str("-12.0").unwrap(); + assert!(json_value.is_f64()); +} + +#[test] +fn test_as_i64(){ + let json_value = from_str("-12").unwrap(); + let json_num = json_value.as_i64(); + assert_eq!(json_num, Some(-12)); +} + +#[test] +fn test_as_u64(){ + let json_value = from_str("12").unwrap(); + let json_num = json_value.as_u64(); + assert_eq!(json_num, Some(12)); +} + +#[test] +fn test_as_f64(){ + let json_value = from_str("12.0").unwrap(); + let json_num = json_value.as_f64(); + assert_eq!(json_num, Some(12f64)); +} + +#[test] +fn test_is_boolean(){ + let json_value = from_str("false").unwrap(); + assert!(json_value.is_boolean()); +} + +#[test] +fn test_as_boolean(){ + let json_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 = from_str("null").unwrap(); + assert!(json_value.is_null()); +} + +#[test] +fn test_as_null(){ + let json_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 = Vec::new(); + write!(&mut mem_buf, "{}", json::as_pretty_json(&hm)).unwrap(); + let json_str = from_utf8(&mem_buf[..]).unwrap(); + match from_str(json_str) { + Err(_) => panic!("Unable to parse json_str: {:?}", json_str), + _ => {} // it parsed and we are good to go + } +} + +#[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 = Vec::new(); + write!(&mut mem_buf, "{}", json::as_pretty_json(&hm)).unwrap(); + let json_str = from_utf8(&mem_buf[..]).unwrap(); + match from_str(json_str) { + Err(_) => panic!("Unable to parse json_str: {:?}", json_str), + _ => {} // it parsed and we are good to go + } +} + +#[test] +fn test_prettyencoder_indent_level_param() { + use std::str::from_utf8; + use std::collections::BTreeMap; + + let mut tree = BTreeMap::new(); + + tree.insert("hello".to_string(), String("guten tag".to_string())); + tree.insert("goodbye".to_string(), String("sayonara".to_string())); + + let json = Array( + // The following layout below should look a lot like + // the pretty-printed JSON (indent * x) + vec! + ( // 0x + String("greetings".to_string()), // 1x + Object(tree), // 1x + 2x + 2x + 1x + ) // 0x + // End JSON array (7 lines) + ); + + // Helper function for counting indents + fn indents(source: &str) -> usize { + let trimmed = source.trim_start_matches(' '); + source.len() - trimmed.len() + } + + // Test up to 4 spaces of indents (more?) + for i in 0..4 { + let mut writer = Vec::new(); + write!(&mut writer, "{}", + json::as_pretty_json(&json).indent(i)).unwrap(); + + let printed = from_utf8(&writer[..]).unwrap(); + + // Check for indents at each line + let lines: Vec<&str> = printed.lines().collect(); + assert_eq!(lines.len(), 7); // JSON should be 7 lines + + assert_eq!(indents(lines[0]), 0 * i); // [ + assert_eq!(indents(lines[1]), 1 * i); // "greetings", + assert_eq!(indents(lines[2]), 1 * i); // { + assert_eq!(indents(lines[3]), 2 * i); // "hello": "guten tag", + assert_eq!(indents(lines[4]), 2 * i); // "goodbye": "sayonara" + assert_eq!(indents(lines[5]), 1 * i); // }, + assert_eq!(indents(lines[6]), 0 * i); // ] + + // Finally, test that the pretty-printed JSON is valid + from_str(printed).ok().expect("Pretty-printed JSON is invalid!"); + } +} + +#[test] +fn test_hashmap_with_enum_key() { + use std::collections::HashMap; + #[derive(RustcEncodable, Eq, Hash, PartialEq, RustcDecodable, Debug)] + enum Enum { + Foo, + #[allow(dead_code)] + Bar, + } + let mut map = HashMap::new(); + map.insert(Enum::Foo, 0); + let result = json::encode(&map).unwrap(); + assert_eq!(&result[..], r#"{"Foo":0}"#); + let decoded: HashMap = json::decode(&result).unwrap(); + assert_eq!(map, decoded); +} + +#[test] +fn test_hashmap_with_numeric_key_can_handle_double_quote_delimited_key() { + use std::collections::HashMap; + let json_str = "{\"1\":true}"; + let json_obj = match from_str(json_str) { + Err(_) => panic!("Unable to parse json_str: {:?}", json_str), + Ok(o) => o + }; + let mut decoder = Decoder::new(json_obj); + let _hm: HashMap = Decodable::decode(&mut decoder).unwrap(); +} + +#[test] +fn test_hashmap_with_numeric_key_will_error_with_string_keys() { + use std::collections::HashMap; + let json_str = "{\"a\":true}"; + let json_obj = match from_str(json_str) { + Err(_) => panic!("Unable to parse json_str: {:?}", json_str), + Ok(o) => o + }; + let mut decoder = Decoder::new(json_obj); + let result: Result, DecoderError> = Decodable::decode(&mut decoder); + assert_eq!(result, Err(ExpectedError("Number".to_string(), "a".to_string()))); +} + +fn assert_stream_equal(src: &str, + expected: Vec<(JsonEvent, Vec>)>) { + 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]}"#, + vec![ + (ObjectStart, vec![]), + (StringValue("bar".to_string()), vec![StackElement::Key("foo")]), + (ArrayStart, vec![StackElement::Key("array")]), + (U64Value(0), vec![StackElement::Key("array"), StackElement::Index(0)]), + (U64Value(1), vec![StackElement::Key("array"), StackElement::Index(1)]), + (U64Value(2), vec![StackElement::Key("array"), StackElement::Index(2)]), + (U64Value(3), vec![StackElement::Key("array"), StackElement::Index(3)]), + (U64Value(4), vec![StackElement::Key("array"), StackElement::Index(4)]), + (U64Value(5), vec![StackElement::Key("array"), StackElement::Index(5)]), + (ArrayEnd, vec![StackElement::Key("array")]), + (ArrayStart, vec![StackElement::Key("idents")]), + (NullValue, vec![StackElement::Key("idents"), + StackElement::Index(0)]), + (BooleanValue(true), vec![StackElement::Key("idents"), + StackElement::Index(1)]), + (BooleanValue(false), vec![StackElement::Key("idents"), + StackElement::Index(2)]), + (ArrayEnd, vec![StackElement::Key("idents")]), + (ObjectEnd, vec![]), + ] + ); +} +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] +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_eq!(last_event("{\"a\":1,}"), Error(SyntaxError(TrailingComma, 1, 8))); + + assert_stream_equal( + "{}", + vec![(ObjectStart, vec![]), (ObjectEnd, vec![])] + ); + assert_stream_equal( + "{\"a\": 3}", + vec![ + (ObjectStart, vec![]), + (U64Value(3), vec![StackElement::Key("a")]), + (ObjectEnd, vec![]), + ] + ); + assert_stream_equal( + "{ \"a\": null, \"b\" : true }", + vec![ + (ObjectStart, vec![]), + (NullValue, vec![StackElement::Key("a")]), + (BooleanValue(true), vec![StackElement::Key("b")]), + (ObjectEnd, vec![]), + ] + ); + assert_stream_equal( + "{\"a\" : 1.0 ,\"b\": [ true ]}", + vec![ + (ObjectStart, vec![]), + (F64Value(1.0), vec![StackElement::Key("a")]), + (ArrayStart, vec![StackElement::Key("b")]), + (BooleanValue(true),vec![StackElement::Key("b"), StackElement::Index(0)]), + (ArrayEnd, vec![StackElement::Key("b")]), + (ObjectEnd, vec![]), + ] + ); + assert_stream_equal( + r#"{ + "a": 1.0, + "b": [ + true, + "foo\nbar", + { "c": {"d": null} } + ] + }"#, + vec![ + (ObjectStart, vec![]), + (F64Value(1.0), vec![StackElement::Key("a")]), + (ArrayStart, vec![StackElement::Key("b")]), + (BooleanValue(true), vec![StackElement::Key("b"), + StackElement::Index(0)]), + (StringValue("foo\nbar".to_string()), vec![StackElement::Key("b"), + StackElement::Index(1)]), + (ObjectStart, vec![StackElement::Key("b"), + StackElement::Index(2)]), + (ObjectStart, vec![StackElement::Key("b"), + StackElement::Index(2), + StackElement::Key("c")]), + (NullValue, vec![StackElement::Key("b"), + StackElement::Index(2), + StackElement::Key("c"), + StackElement::Key("d")]), + (ObjectEnd, vec![StackElement::Key("b"), + StackElement::Index(2), + StackElement::Key("c")]), + (ObjectEnd, vec![StackElement::Key("b"), + StackElement::Index(2)]), + (ArrayEnd, vec![StackElement::Key("b")]), + (ObjectEnd, vec![]), + ] + ); +} +#[test] +fn test_read_array_streaming() { + assert_stream_equal( + "[]", + vec![ + (ArrayStart, vec![]), + (ArrayEnd, vec![]), + ] + ); + assert_stream_equal( + "[ ]", + vec![ + (ArrayStart, vec![]), + (ArrayEnd, vec![]), + ] + ); + assert_stream_equal( + "[true]", + vec![ + (ArrayStart, vec![]), + (BooleanValue(true), vec![StackElement::Index(0)]), + (ArrayEnd, vec![]), + ] + ); + assert_stream_equal( + "[ false ]", + vec![ + (ArrayStart, vec![]), + (BooleanValue(false), vec![StackElement::Index(0)]), + (ArrayEnd, vec![]), + ] + ); + assert_stream_equal( + "[null]", + vec![ + (ArrayStart, vec![]), + (NullValue, vec![StackElement::Index(0)]), + (ArrayEnd, vec![]), + ] + ); + assert_stream_equal( + "[3, 1]", + vec![ + (ArrayStart, vec![]), + (U64Value(3), vec![StackElement::Index(0)]), + (U64Value(1), vec![StackElement::Index(1)]), + (ArrayEnd, vec![]), + ] + ); + assert_stream_equal( + "\n[3, 2]\n", + vec![ + (ArrayStart, vec![]), + (U64Value(3), vec![StackElement::Index(0)]), + (U64Value(2), vec![StackElement::Index(1)]), + (ArrayEnd, vec![]), + ] + ); + assert_stream_equal( + "[2, [4, 1]]", + vec![ + (ArrayStart, vec![]), + (U64Value(2), vec![StackElement::Index(0)]), + (ArrayStart, vec![StackElement::Index(1)]), + (U64Value(4), vec![StackElement::Index(1), StackElement::Index(0)]), + (U64Value(1), vec![StackElement::Index(1), StackElement::Index(1)]), + (ArrayEnd, vec![StackElement::Index(1)]), + (ArrayEnd, vec![]), + ] + ); + + 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(EOFWhileParsingArray, 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_to_json() { + use std::collections::{HashMap,BTreeMap}; + use json::ToJson; + + let array2 = Array(vec![U64(1), U64(2)]); + let array3 = Array(vec![U64(1), U64(2), U64(3)]); + let object = { + let mut tree_map = BTreeMap::new(); + tree_map.insert("a".to_string(), U64(1)); + tree_map.insert("b".to_string(), U64(2)); + Object(tree_map) + }; + + assert_eq!(array2.to_json(), array2); + assert_eq!(object.to_json(), object); + assert_eq!(3_isize.to_json(), I64(3)); + assert_eq!(4_i8.to_json(), I64(4)); + assert_eq!(5_i16.to_json(), I64(5)); + assert_eq!(6_i32.to_json(), I64(6)); + assert_eq!(7_i64.to_json(), I64(7)); + assert_eq!(8_usize.to_json(), U64(8)); + assert_eq!(9_u8.to_json(), U64(9)); + assert_eq!(10_u16.to_json(), U64(10)); + assert_eq!(11_u32.to_json(), U64(11)); + assert_eq!(12_u64.to_json(), U64(12)); + assert_eq!(13.0_f32.to_json(), F64(13.0_f64)); + assert_eq!(14.0_f64.to_json(), F64(14.0_f64)); + assert_eq!(().to_json(), Null); + assert_eq!(f32::INFINITY.to_json(), Null); + assert_eq!(f64::NAN.to_json(), Null); + assert_eq!(true.to_json(), Boolean(true)); + assert_eq!(false.to_json(), Boolean(false)); + assert_eq!("abc".to_json(), String("abc".to_string())); + assert_eq!("abc".to_string().to_json(), String("abc".to_string())); + assert_eq!((1_usize, 2_usize).to_json(), array2); + assert_eq!((1_usize, 2_usize, 3_usize).to_json(), array3); + assert_eq!([1_usize, 2_usize].to_json(), array2); + assert_eq!((&[1_usize, 2_usize, 3_usize]).to_json(), array3); + assert_eq!((vec![1_usize, 2_usize]).to_json(), array2); + assert_eq!(vec![1_usize, 2_usize, 3_usize].to_json(), array3); + let mut tree_map = BTreeMap::new(); + tree_map.insert("a".to_string(), 1 as usize); + tree_map.insert("b".to_string(), 2); + assert_eq!(tree_map.to_json(), object); + let mut hash_map = HashMap::new(); + hash_map.insert("a".to_string(), 1 as usize); + hash_map.insert("b".to_string(), 2); + assert_eq!(hash_map.to_json(), object); + assert_eq!(Some(15).to_json(), I64(15)); + assert_eq!(Some(15 as usize).to_json(), U64(15)); + assert_eq!(None::.to_json(), Null); +} + +#[test] +fn test_encode_hashmap_with_arbitrary_key() { + use std::collections::HashMap; + #[derive(PartialEq, Eq, Hash, RustcEncodable)] + struct ArbitraryType(usize); + let mut hm: HashMap = HashMap::new(); + hm.insert(ArbitraryType(1), true); + let mut mem_buf = string::String::new(); + let mut encoder = Encoder::new(&mut mem_buf); + let result = hm.encode(&mut encoder); + match result.unwrap_err() { + EncoderError::BadHashmapKey => (), + _ => panic!("expected bad hash map key") + } +} diff --git a/src/libserialize/tests/opaque.rs b/src/libserialize/tests/opaque.rs new file mode 100644 index 0000000000000..fff6fc69e7842 --- /dev/null +++ b/src/libserialize/tests/opaque.rs @@ -0,0 +1,282 @@ +extern crate serialize as rustc_serialize; + +use rustc_serialize::{Encodable, Decodable}; +use rustc_serialize::opaque::{Encoder, Decoder}; +use std::fmt::Debug; + +#[derive(PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)] +struct Struct { + a: (), + b: u8, + c: u16, + d: u32, + e: u64, + f: usize, + + g: i8, + h: i16, + i: i32, + j: i64, + k: isize, + + l: char, + m: String, + n: f32, + o: f64, + p: bool, + q: Option, +} + + +fn check_round_trip(values: Vec) { + let mut encoder = Encoder::new(Vec::new()); + + for value in &values { + Encodable::encode(&value, &mut encoder).unwrap(); + } + + let data = encoder.into_inner(); + let mut decoder = Decoder::new(&data[..], 0); + + for value in values { + let decoded = Decodable::decode(&mut decoder).unwrap(); + assert_eq!(value, decoded); + } +} + +#[test] +fn test_unit() { + check_round_trip(vec![(), (), (), ()]); +} + +#[test] +fn test_u8() { + let mut vec = vec![]; + for i in ::std::u8::MIN..::std::u8::MAX { + vec.push(i); + } + check_round_trip(vec); +} + +#[test] +fn test_u16() { + for i in ::std::u16::MIN..::std::u16::MAX { + check_round_trip(vec![1, 2, 3, i, i, i]); + } +} + +#[test] +fn test_u32() { + check_round_trip(vec![1, 2, 3, ::std::u32::MIN, 0, 1, ::std::u32::MAX, 2, 1]); +} + +#[test] +fn test_u64() { + check_round_trip(vec![1, 2, 3, ::std::u64::MIN, 0, 1, ::std::u64::MAX, 2, 1]); +} + +#[test] +fn test_usize() { + check_round_trip(vec![1, 2, 3, ::std::usize::MIN, 0, 1, ::std::usize::MAX, 2, 1]); +} + +#[test] +fn test_i8() { + let mut vec = vec![]; + for i in ::std::i8::MIN..::std::i8::MAX { + vec.push(i); + } + check_round_trip(vec); +} + +#[test] +fn test_i16() { + for i in ::std::i16::MIN..::std::i16::MAX { + check_round_trip(vec![-1, 2, -3, i, i, i, 2]); + } +} + +#[test] +fn test_i32() { + check_round_trip(vec![-1, 2, -3, ::std::i32::MIN, 0, 1, ::std::i32::MAX, 2, 1]); +} + +#[test] +fn test_i64() { + check_round_trip(vec![-1, 2, -3, ::std::i64::MIN, 0, 1, ::std::i64::MAX, 2, 1]); +} + +#[test] +fn test_isize() { + check_round_trip(vec![-1, 2, -3, ::std::isize::MIN, 0, 1, ::std::isize::MAX, 2, 1]); +} + +#[test] +fn test_bool() { + check_round_trip(vec![false, true, true, false, false]); +} + +#[test] +fn test_f32() { + let mut vec = vec![]; + for i in -100..100 { + vec.push((i as f32) / 3.0); + } + check_round_trip(vec); +} + +#[test] +fn test_f64() { + let mut vec = vec![]; + for i in -100..100 { + vec.push((i as f64) / 3.0); + } + check_round_trip(vec); +} + +#[test] +fn test_char() { + let vec = vec!['a', 'b', 'c', 'd', 'A', 'X', ' ', '#', 'Ö', 'Ä', 'µ', '€']; + check_round_trip(vec); +} + +#[test] +fn test_string() { + let vec = vec!["abcbuÖeiovÄnameÜavmpßvmea€µsbpnvapeapmaebn".to_string(), + "abcbuÖganeiovÄnameÜavmpßvmea€µsbpnvapeapmaebn".to_string(), + "abcbuÖganeiovÄnameÜavmpßvmea€µsbpapmaebn".to_string(), + "abcbuÖganeiovÄnameÜavmpßvmeabpnvapeapmaebn".to_string(), + "abcbuÖganeiÄnameÜavmpßvmea€µsbpnvapeapmaebn".to_string(), + "abcbuÖganeiovÄnameÜavmpßvmea€µsbpmaebn".to_string(), + "abcbuÖganeiovÄnameÜavmpßvmea€µnvapeapmaebn".to_string()]; + + check_round_trip(vec); +} + +#[test] +fn test_option() { + check_round_trip(vec![Some(-1i8)]); + check_round_trip(vec![Some(-2i16)]); + check_round_trip(vec![Some(-3i32)]); + check_round_trip(vec![Some(-4i64)]); + check_round_trip(vec![Some(-5isize)]); + + let none_i8: Option = None; + check_round_trip(vec![none_i8]); + + let none_i16: Option = None; + check_round_trip(vec![none_i16]); + + let none_i32: Option = None; + check_round_trip(vec![none_i32]); + + let none_i64: Option = None; + check_round_trip(vec![none_i64]); + + let none_isize: Option = None; + check_round_trip(vec![none_isize]); +} + +#[test] +fn test_struct() { + check_round_trip(vec![Struct { + a: (), + b: 10, + c: 11, + d: 12, + e: 13, + f: 14, + + g: 15, + h: 16, + i: 17, + j: 18, + k: 19, + + l: 'x', + m: "abc".to_string(), + n: 20.5, + o: 21.5, + p: false, + q: None, + }]); + + check_round_trip(vec![Struct { + a: (), + b: 101, + c: 111, + d: 121, + e: 131, + f: 141, + + g: -15, + h: -16, + i: -17, + j: -18, + k: -19, + + l: 'y', + m: "def".to_string(), + n: -20.5, + o: -21.5, + p: true, + q: Some(1234567), + }]); +} + +#[derive(PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)] +enum Enum { + Variant1, + Variant2(usize, f32), + Variant3 { + a: i32, + b: char, + c: bool, + }, +} + +#[test] +fn test_enum() { + check_round_trip(vec![Enum::Variant1, + Enum::Variant2(1, 2.5), + Enum::Variant3 { + a: 3, + b: 'b', + c: false, + }, + Enum::Variant3 { + a: -4, + b: 'f', + c: true, + }]); +} + +#[test] +fn test_sequence() { + let mut vec = vec![]; + for i in -100i64..100i64 { + vec.push(i * 100000); + } + + check_round_trip(vec![vec]); +} + +#[test] +fn test_hash_map() { + use std::collections::HashMap; + let mut map = HashMap::new(); + for i in -100i64..100i64 { + map.insert(i * 100000, i * 10000); + } + + check_round_trip(vec![map]); +} + +#[test] +fn test_tuples() { + check_round_trip(vec![('x', (), false, 0.5f32)]); + check_round_trip(vec![(9i8, 10u16, 1.5f64)]); + check_round_trip(vec![(-12i16, 11u8, 12usize)]); + check_round_trip(vec![(1234567isize, 100000000000000u64, 99999999999999i64)]); + check_round_trip(vec![(String::new(), "some string".to_string())]); +}