Add support for json deserializing enums and options, clean up tests
This commit is contained in:
parent
85fd2797a6
commit
27a914cdcf
539
json.rs
539
json.rs
@ -316,9 +316,10 @@ enum JsonDeserializerState {
|
|||||||
JsonDeserializerValueState(Json),
|
JsonDeserializerValueState(Json),
|
||||||
JsonDeserializerListState(vec::MoveItems<Json>),
|
JsonDeserializerListState(vec::MoveItems<Json>),
|
||||||
JsonDeserializerObjectState(treemap::MoveEntries<String, Json>),
|
JsonDeserializerObjectState(treemap::MoveEntries<String, Json>),
|
||||||
|
JsonDeserializerEndState,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct JsonDeserializer {
|
pub struct JsonDeserializer {
|
||||||
stack: Vec<JsonDeserializerState>,
|
stack: Vec<JsonDeserializerState>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -380,6 +381,9 @@ impl Iterator<Result<de::Token, ParserError>> for JsonDeserializer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Some(JsonDeserializerEndState) => {
|
||||||
|
return Some(Ok(de::End));
|
||||||
|
}
|
||||||
None => { return None; }
|
None => { return None; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -394,6 +398,131 @@ impl de::Deserializer<ParserError> for JsonDeserializer {
|
|||||||
fn syntax_error(&self) -> ParserError {
|
fn syntax_error(&self) -> ParserError {
|
||||||
SyntaxError(InvalidSyntax, 0, 0)
|
SyntaxError(InvalidSyntax, 0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Special case treating options as a nullable value.
|
||||||
|
#[inline]
|
||||||
|
fn expect_option<
|
||||||
|
U: de::Deserializable<ParserError, JsonDeserializer>
|
||||||
|
>(&mut self, token: de::Token) -> Result<Option<U>, ParserError> {
|
||||||
|
match token {
|
||||||
|
de::Null => Ok(None),
|
||||||
|
token => {
|
||||||
|
let value: U = try!(de::Deserializable::deserialize_token(self, token));
|
||||||
|
Ok(Some(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn expect_enum_start(&mut self, token: de::Token, _name: &str, variants: &[&str]) -> Result<uint, ParserError> {
|
||||||
|
let variant = match token {
|
||||||
|
de::String(variant) => {
|
||||||
|
self.stack.push(JsonDeserializerEndState);
|
||||||
|
variant
|
||||||
|
}
|
||||||
|
de::MapStart(_) => {
|
||||||
|
let state = match self.stack.pop() {
|
||||||
|
Some(state) => state,
|
||||||
|
None => { fail!("state machine error, state stack empty"); }
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut iter = match state {
|
||||||
|
JsonDeserializerObjectState(iter) => iter,
|
||||||
|
_ => { fail!("state machine error, expected an object"); }
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut variant = None;
|
||||||
|
let mut fields = None;
|
||||||
|
|
||||||
|
for (key, value) in iter {
|
||||||
|
if key.equiv(&"variant") {
|
||||||
|
match value {
|
||||||
|
String(v) => { variant = Some(v); }
|
||||||
|
value => {
|
||||||
|
return Err(ExpectedError("String".to_string(),
|
||||||
|
format!("{}", value)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if key.equiv(&"fields") {
|
||||||
|
match value {
|
||||||
|
List(v) => { fields = Some(v); }
|
||||||
|
value => {
|
||||||
|
return Err(ExpectedError("List".to_string(),
|
||||||
|
format!("{}", value)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let (variant, fields) = match (variant, fields) {
|
||||||
|
(Some(variant), Some(fields)) => (variant, fields),
|
||||||
|
(None, _) => {
|
||||||
|
return Err(MissingFieldError("variant".to_string()))
|
||||||
|
}
|
||||||
|
(_, None) => {
|
||||||
|
return Err(MissingFieldError("fields".to_string()))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.stack.push(JsonDeserializerEndState);
|
||||||
|
|
||||||
|
for field in fields.move_iter().rev() {
|
||||||
|
self.stack.push(JsonDeserializerValueState(field));
|
||||||
|
}
|
||||||
|
|
||||||
|
variant
|
||||||
|
}
|
||||||
|
token => {
|
||||||
|
return Err(ExpectedError("String or Object".to_string(),
|
||||||
|
format!("{}", token)))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
|
||||||
|
let name = match self.stack.pop() {
|
||||||
|
String(s) => s,
|
||||||
|
Object(mut object) => {
|
||||||
|
let n = match object.pop_equiv(&"variant") {
|
||||||
|
Some(String(s)) => s,
|
||||||
|
Some(value) => {
|
||||||
|
return Err(ExpectedError("String".to_string(),
|
||||||
|
format!("{}", value)))
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
return Err(MissingFieldError("variant".to_string()))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
match object.pop_equiv(&"fields") {
|
||||||
|
Some(List(list)) => {
|
||||||
|
for field in list.move_iter().rev() {
|
||||||
|
self.stack.push(JsonDeserializerValueState(field));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Some(value) => {
|
||||||
|
return Err(ExpectedError("List".to_string(),
|
||||||
|
format!("{}", value)))
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
return Err(MissingFieldError("fields".to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
n
|
||||||
|
}
|
||||||
|
json => {
|
||||||
|
return Err(ExpectedError("String or Object".to_string(),
|
||||||
|
format!("{}", json)))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
match variants.iter().position(|v| *v == variant.as_slice()) {
|
||||||
|
Some(idx) => Ok(idx),
|
||||||
|
None => Err(UnknownVariantError(variant)),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The errors that can arise while parsing a JSON stream.
|
/// The errors that can arise while parsing a JSON stream.
|
||||||
@ -422,11 +551,15 @@ pub enum ParserError {
|
|||||||
/// msg, line, col
|
/// msg, line, col
|
||||||
SyntaxError(ErrorCode, uint, uint),
|
SyntaxError(ErrorCode, uint, uint),
|
||||||
IoError(io::IoErrorKind, &'static str),
|
IoError(io::IoErrorKind, &'static str),
|
||||||
|
ExpectedError(String, String),
|
||||||
|
MissingFieldError(String),
|
||||||
|
UnknownVariantError(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Builder and Parser have the same errors.
|
// Builder and Parser have the same errors.
|
||||||
pub type BuilderError = ParserError;
|
pub type BuilderError = ParserError;
|
||||||
|
|
||||||
|
/*
|
||||||
#[deriving(Clone, Eq, Show)]
|
#[deriving(Clone, Eq, Show)]
|
||||||
pub enum DecoderError {
|
pub enum DecoderError {
|
||||||
ParseError(ParserError),
|
ParseError(ParserError),
|
||||||
@ -434,6 +567,7 @@ pub enum DecoderError {
|
|||||||
MissingFieldError(String),
|
MissingFieldError(String),
|
||||||
UnknownVariantError(String),
|
UnknownVariantError(String),
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/// Returns a readable error string for a given error code.
|
/// Returns a readable error string for a given error code.
|
||||||
pub fn error_str(error: ErrorCode) -> &'static str {
|
pub fn error_str(error: ErrorCode) -> &'static str {
|
||||||
@ -469,7 +603,7 @@ fn io_error_to_error(io: io::IoError) -> ParserError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub type EncodeResult = io::IoResult<()>;
|
pub type EncodeResult = io::IoResult<()>;
|
||||||
pub type DecodeResult<T> = Result<T, DecoderError>;
|
//pub type DecodeResult<T> = Result<T, DecoderError>;
|
||||||
|
|
||||||
fn escape_str(s: &str) -> String {
|
fn escape_str(s: &str) -> String {
|
||||||
let mut escaped = String::from_str("\"");
|
let mut escaped = String::from_str("\"");
|
||||||
@ -1754,7 +1888,7 @@ impl<T: Iterator<char>> de::Deserializer<ParserError> for Parser<T> {
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn expect_enum_start(&mut self, token: de::Token, _name: &str, variants: &[&str]) -> Result<uint, ParserError> {
|
fn expect_enum_start(&mut self, token: de::Token, _name: &str, variants: &[&str]) -> Result<uint, ParserError> {
|
||||||
match token {
|
match token {
|
||||||
Str(name) =>
|
Str(name) =>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2463,7 +2597,7 @@ mod tests {
|
|||||||
Object,
|
Object,
|
||||||
};
|
};
|
||||||
use super::{Parser, ParserError, from_iter};
|
use super::{Parser, ParserError, from_iter};
|
||||||
use super::{JsonDeserializer, from_json};
|
use super::{JsonDeserializer, from_json, ToJson};
|
||||||
use super::{
|
use super::{
|
||||||
EOFWhileParsingList,
|
EOFWhileParsingList,
|
||||||
EOFWhileParsingObject,
|
EOFWhileParsingObject,
|
||||||
@ -2472,7 +2606,7 @@ mod tests {
|
|||||||
ExpectedColon,
|
ExpectedColon,
|
||||||
InvalidNumber,
|
InvalidNumber,
|
||||||
InvalidSyntax,
|
InvalidSyntax,
|
||||||
KeyMustBeAString,
|
KeyMustBeAString,
|
||||||
TrailingCharacters,
|
TrailingCharacters,
|
||||||
SyntaxError,
|
SyntaxError,
|
||||||
};
|
};
|
||||||
@ -2483,6 +2617,14 @@ mod tests {
|
|||||||
use std::str;
|
use std::str;
|
||||||
use collections::TreeMap;
|
use collections::TreeMap;
|
||||||
|
|
||||||
|
macro_rules! treemap {
|
||||||
|
($($k:expr => $v:expr),*) => ({
|
||||||
|
let mut _m = ::collections::TreeMap::new();
|
||||||
|
$(_m.insert($k, $v);)*
|
||||||
|
_m
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[deriving(Eq, Show)]
|
#[deriving(Eq, Show)]
|
||||||
enum Animal {
|
enum Animal {
|
||||||
Dog,
|
Dog,
|
||||||
@ -2574,6 +2716,18 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ToJson for Inner {
|
||||||
|
fn to_json(&self) -> Json {
|
||||||
|
Object(
|
||||||
|
treemap!(
|
||||||
|
"a".to_string() => self.a.to_json(),
|
||||||
|
"b".to_string() => self.b.to_json(),
|
||||||
|
"c".to_string() => self.c.to_json()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[deriving(Eq, Show)]
|
#[deriving(Eq, Show)]
|
||||||
struct Outer {
|
struct Outer {
|
||||||
inner: Vec<Inner>,
|
inner: Vec<Inner>,
|
||||||
@ -2622,6 +2776,16 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ToJson for Outer {
|
||||||
|
fn to_json(&self) -> Json {
|
||||||
|
Object(
|
||||||
|
treemap!(
|
||||||
|
"inner".to_string() => self.inner.to_json()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
fn mk_object(items: &[(String, Json)]) -> Json {
|
fn mk_object(items: &[(String, Json)]) -> Json {
|
||||||
let mut d = box TreeMap::new();
|
let mut d = box TreeMap::new();
|
||||||
@ -2874,59 +3038,61 @@ mod tests {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
fn test_parser_err<
|
fn test_parse_err<
|
||||||
'a,
|
'a,
|
||||||
T: Eq + Show + de::Deserializable<ParserError, Parser<str::Chars<'a>>>
|
T: Eq + Show + de::Deserializable<ParserError, Parser<str::Chars<'a>>>
|
||||||
>(errors: &[(&'a str, ParserError)]) {
|
>(errors: &[(&'a str, ParserError)]) {
|
||||||
for &(s, err) in errors.iter() {
|
for &(s, ref err) in errors.iter() {
|
||||||
let v: Result<T, ParserError> = from_iter(s.chars());
|
let v: Result<T, ParserError> = from_iter(s.chars());
|
||||||
assert_eq!(v, Err(err));
|
assert_eq!(v.unwrap_err(), *err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_parser_ok<
|
fn test_parse_ok<
|
||||||
'a,
|
'a,
|
||||||
T: Eq + Show + de::Deserializable<ParserError, Parser<str::Chars<'a>>>
|
T: Eq + Show + ToJson + de::Deserializable<ParserError, Parser<str::Chars<'a>>>
|
||||||
>(errors: &[(&'a str, T)]) {
|
>(errors: &[(&'a str, T)]) {
|
||||||
for &(s, ref value) in errors.iter() {
|
for &(s, ref value) in errors.iter() {
|
||||||
let v: T = from_iter(s.chars()).unwrap();
|
let v: T = from_iter(s.chars()).unwrap();
|
||||||
assert_eq!(v, *value);
|
assert_eq!(v, *value);
|
||||||
|
|
||||||
|
let v: Json = from_iter(s.chars()).unwrap();
|
||||||
|
assert_eq!(v, value.to_json());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_json_deserializer_ok<
|
fn test_json_deserialize_ok<
|
||||||
T: Eq + Show + de::Deserializable<ParserError, JsonDeserializer>
|
T: Eq + Show + ToJson + de::Deserializable<ParserError, JsonDeserializer>
|
||||||
>(errors: &[(Json, T)]) {
|
>(errors: &[T]) {
|
||||||
for &(ref json, ref value) in errors.iter() {
|
for value in errors.iter() {
|
||||||
let v: T = from_json(json.clone()).unwrap();
|
let v: T = from_json(value.to_json()).unwrap();
|
||||||
assert_eq!(v, *value);
|
assert_eq!(v, *value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_decode_null() {
|
fn test_parse_null() {
|
||||||
test_parser_err::<()>([
|
test_parse_err::<()>([
|
||||||
("n", SyntaxError(InvalidSyntax, 1, 2)),
|
("n", SyntaxError(InvalidSyntax, 1, 2)),
|
||||||
("nul", SyntaxError(InvalidSyntax, 1, 4)),
|
("nul", SyntaxError(InvalidSyntax, 1, 4)),
|
||||||
("nulla", SyntaxError(TrailingCharacters, 1, 5)),
|
("nulla", SyntaxError(TrailingCharacters, 1, 5)),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
test_parser_ok([
|
test_parse_ok([
|
||||||
("null", ()),
|
("null", ()),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
test_parser_ok([
|
|
||||||
("null", Null),
|
|
||||||
]);
|
|
||||||
|
|
||||||
test_json_deserializer_ok([
|
|
||||||
(Null, ()),
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_decode_bool() {
|
fn test_json_deserialize_null() {
|
||||||
test_parser_err::<bool>([
|
test_json_deserialize_ok([
|
||||||
|
(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_bool() {
|
||||||
|
test_parse_err::<bool>([
|
||||||
("t", SyntaxError(InvalidSyntax, 1, 2)),
|
("t", SyntaxError(InvalidSyntax, 1, 2)),
|
||||||
("truz", SyntaxError(InvalidSyntax, 1, 4)),
|
("truz", SyntaxError(InvalidSyntax, 1, 4)),
|
||||||
("f", SyntaxError(InvalidSyntax, 1, 2)),
|
("f", SyntaxError(InvalidSyntax, 1, 2)),
|
||||||
@ -2935,20 +3101,17 @@ mod tests {
|
|||||||
("falsea", SyntaxError(TrailingCharacters, 1, 6)),
|
("falsea", SyntaxError(TrailingCharacters, 1, 6)),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
test_parser_ok([
|
test_parse_ok([
|
||||||
("true", true),
|
("true", true),
|
||||||
("false", false),
|
("false", false),
|
||||||
]);
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
test_parser_ok([
|
#[test]
|
||||||
("true", Boolean(true)),
|
fn test_json_deserialize_bool() {
|
||||||
("false", Boolean(false)),
|
test_json_deserialize_ok([
|
||||||
]);
|
true,
|
||||||
|
false,
|
||||||
|
|
||||||
test_json_deserializer_ok([
|
|
||||||
(Boolean(true), true),
|
|
||||||
(Boolean(false), false),
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2975,8 +3138,8 @@ mod tests {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_decode_numbers() {
|
fn test_parse_numbers() {
|
||||||
let errors = [
|
test_parse_err::<f64>([
|
||||||
("+", SyntaxError(InvalidSyntax, 1, 1)),
|
("+", SyntaxError(InvalidSyntax, 1, 1)),
|
||||||
(".", SyntaxError(InvalidSyntax, 1, 1)),
|
(".", SyntaxError(InvalidSyntax, 1, 1)),
|
||||||
("-", SyntaxError(InvalidNumber, 1, 2)),
|
("-", SyntaxError(InvalidNumber, 1, 2)),
|
||||||
@ -2985,14 +3148,9 @@ mod tests {
|
|||||||
("1e", SyntaxError(InvalidNumber, 1, 3)),
|
("1e", SyntaxError(InvalidNumber, 1, 3)),
|
||||||
("1e+", SyntaxError(InvalidNumber, 1, 4)),
|
("1e+", SyntaxError(InvalidNumber, 1, 4)),
|
||||||
("1a", SyntaxError(TrailingCharacters, 1, 2)),
|
("1a", SyntaxError(TrailingCharacters, 1, 2)),
|
||||||
];
|
]);
|
||||||
|
|
||||||
for &(s, err) in errors.iter() {
|
test_parse_ok([
|
||||||
let v: Result<f64, ParserError> = from_iter(s.chars());
|
|
||||||
assert_eq!(v, Err(err));
|
|
||||||
}
|
|
||||||
|
|
||||||
let values = [
|
|
||||||
("3", 3.0),
|
("3", 3.0),
|
||||||
("3.1", 3.1),
|
("3.1", 3.1),
|
||||||
("-1.2", -1.2),
|
("-1.2", -1.2),
|
||||||
@ -3000,12 +3158,20 @@ mod tests {
|
|||||||
("0.4e5", 0.4e5),
|
("0.4e5", 0.4e5),
|
||||||
("0.4e15", 0.4e15),
|
("0.4e15", 0.4e15),
|
||||||
("0.4e-01", 0.4e-01),
|
("0.4e-01", 0.4e-01),
|
||||||
];
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
for &(s, value) in values.iter() {
|
#[test]
|
||||||
let v: Result<f64, ParserError> = from_iter(s.chars());
|
fn test_json_deserialize_numbers() {
|
||||||
assert_eq!(v, Ok(value));
|
test_json_deserialize_ok([
|
||||||
}
|
3.0,
|
||||||
|
3.1,
|
||||||
|
-1.2,
|
||||||
|
0.4,
|
||||||
|
0.4e5,
|
||||||
|
0.4e15,
|
||||||
|
0.4e-01,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3028,33 +3194,39 @@ mod tests {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_decode_str() {
|
fn test_parse_str() {
|
||||||
let errors = [
|
test_parse_err::<String>([
|
||||||
("\"", SyntaxError(EOFWhileParsingString, 1, 2)),
|
("\"", SyntaxError(EOFWhileParsingString, 1, 2)),
|
||||||
("\"lol", SyntaxError(EOFWhileParsingString, 1, 5)),
|
("\"lol", SyntaxError(EOFWhileParsingString, 1, 5)),
|
||||||
("\"lol\"a", SyntaxError(TrailingCharacters, 1, 6)),
|
("\"lol\"a", SyntaxError(TrailingCharacters, 1, 6)),
|
||||||
];
|
]);
|
||||||
|
|
||||||
for &(s, err) in errors.iter() {
|
test_parse_ok([
|
||||||
let v: Result<String, ParserError> = from_iter(s.chars());
|
("\"\"", "".to_string()),
|
||||||
assert_eq!(v, Err(err));
|
("\"foo\"", "foo".to_string()),
|
||||||
}
|
("\"\\\"\"", "\"".to_string()),
|
||||||
|
("\"\\b\"", "\x08".to_string()),
|
||||||
|
("\"\\n\"", "\n".to_string()),
|
||||||
|
("\"\\r\"", "\r".to_string()),
|
||||||
|
("\"\\t\"", "\t".to_string()),
|
||||||
|
("\"\\u12ab\"", "\u12ab".to_string()),
|
||||||
|
("\"\\uAB12\"", "\uAB12".to_string()),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
let s = [("\"\"", ""),
|
#[test]
|
||||||
("\"foo\"", "foo"),
|
fn test_json_deserialize_str() {
|
||||||
("\"\\\"\"", "\""),
|
test_json_deserialize_ok([
|
||||||
("\"\\b\"", "\x08"),
|
"".to_string(),
|
||||||
("\"\\n\"", "\n"),
|
"foo".to_string(),
|
||||||
("\"\\r\"", "\r"),
|
"\"".to_string(),
|
||||||
("\"\\t\"", "\t"),
|
"\x08".to_string(),
|
||||||
("\"\\u12ab\"", "\u12ab"),
|
"\n".to_string(),
|
||||||
("\"\\uAB12\"", "\uAB12")];
|
"\r".to_string(),
|
||||||
|
"\t".to_string(),
|
||||||
for &(i, o) in s.iter() {
|
"\u12ab".to_string(),
|
||||||
let mut parser = Parser::new(i.chars());
|
"\uAB12".to_string(),
|
||||||
let v: String = de::Deserializable::deserialize(&mut parser).unwrap();
|
]);
|
||||||
assert_eq!(v.as_slice(), o);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3081,44 +3253,56 @@ mod tests {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_decode_list() {
|
fn test_parse_list() {
|
||||||
let errors = [
|
test_parse_err::<Vec<f64>>([
|
||||||
("[", SyntaxError(EOFWhileParsingValue, 1, 2)),
|
("[", SyntaxError(EOFWhileParsingValue, 1, 2)),
|
||||||
("[ ", SyntaxError(EOFWhileParsingValue, 1, 3)),
|
("[ ", SyntaxError(EOFWhileParsingValue, 1, 3)),
|
||||||
("[1", SyntaxError(EOFWhileParsingList, 1, 3)),
|
("[1", SyntaxError(EOFWhileParsingList, 1, 3)),
|
||||||
("[1,", SyntaxError(EOFWhileParsingValue, 1, 4)),
|
("[1,", SyntaxError(EOFWhileParsingValue, 1, 4)),
|
||||||
("[1,]", SyntaxError(InvalidSyntax, 1, 4)),
|
("[1,]", SyntaxError(InvalidSyntax, 1, 4)),
|
||||||
("[1 2]", SyntaxError(InvalidSyntax, 1, 4)),
|
("[1 2]", SyntaxError(InvalidSyntax, 1, 4)),
|
||||||
("[]a", SyntaxError(TrailingCharacters, 1, 3)),
|
("[]a", SyntaxError(TrailingCharacters, 1, 3)),
|
||||||
];
|
]);
|
||||||
for &(s, err) in errors.iter() {
|
|
||||||
let v: Result<Vec<f64>, ParserError> = from_iter(s.chars());
|
|
||||||
assert_eq!(v, Err(err));
|
|
||||||
}
|
|
||||||
|
|
||||||
let v: Vec<()> = from_iter("[]".chars()).unwrap();
|
test_parse_ok([
|
||||||
assert_eq!(v, vec![]);
|
("[]", vec!()),
|
||||||
|
("[ ]", vec!()),
|
||||||
|
("[null]", vec!(())),
|
||||||
|
("[ null ]", vec!(())),
|
||||||
|
]);
|
||||||
|
|
||||||
let v: Vec<()> = from_iter("[ ]".chars()).unwrap();
|
test_parse_ok([
|
||||||
assert_eq!(v, vec![]);
|
("[true]", vec!(true)),
|
||||||
|
]);
|
||||||
|
|
||||||
let v: Vec<()> = from_iter("[null]".chars()).unwrap();
|
test_parse_ok([
|
||||||
assert_eq!(v, vec![()]);
|
("[3,1]", vec!(3, 1)),
|
||||||
|
("[ 3 , 1 ]", vec!(3, 1)),
|
||||||
|
]);
|
||||||
|
|
||||||
let v: Vec<()> = from_iter("[ null ]".chars()).unwrap();
|
test_parse_ok([
|
||||||
assert_eq!(v, vec![()]);
|
("[[3], [1, 2]]", vec!(vec!(3), vec!(1, 2))),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
let v: Vec<bool> = from_iter("[true]".chars()).unwrap();
|
#[test]
|
||||||
assert_eq!(v, vec![true]);
|
fn test_json_deserialize_list() {
|
||||||
|
test_json_deserialize_ok([
|
||||||
|
vec!(),
|
||||||
|
vec!(()),
|
||||||
|
]);
|
||||||
|
|
||||||
let v: Vec<int> = from_iter("[3,1]".chars()).unwrap();
|
test_json_deserialize_ok([
|
||||||
assert_eq!(v, vec![3, 1]);
|
vec!(true),
|
||||||
|
]);
|
||||||
|
|
||||||
let v: Vec<int> = from_iter("[ 3 , 1 ]".chars()).unwrap();
|
test_json_deserialize_ok([
|
||||||
assert_eq!(v, vec![3, 1]);
|
vec!(3, 1),
|
||||||
|
]);
|
||||||
|
|
||||||
let v: Vec<Vec<uint>> = from_iter("[[3], [1, 2]]".chars()).unwrap();
|
test_json_deserialize_ok([
|
||||||
assert_eq!(v, vec![vec![3], vec![1, 2]]);
|
vec!(vec!(3), vec!(1, 2)),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3179,8 +3363,8 @@ mod tests {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_decode_object() {
|
fn test_parse_object() {
|
||||||
let errors = [
|
test_parse_err::<TreeMap<String, int>>([
|
||||||
("{", SyntaxError(EOFWhileParsingString, 1, 2)),
|
("{", SyntaxError(EOFWhileParsingString, 1, 2)),
|
||||||
("{ ", SyntaxError(EOFWhileParsingString, 1, 3)),
|
("{ ", SyntaxError(EOFWhileParsingString, 1, 3)),
|
||||||
("{1", SyntaxError(KeyMustBeAString, 1, 2)),
|
("{1", SyntaxError(KeyMustBeAString, 1, 2)),
|
||||||
@ -3193,82 +3377,101 @@ mod tests {
|
|||||||
("{\"a\":1 1", SyntaxError(InvalidSyntax, 1, 8)),
|
("{\"a\":1 1", SyntaxError(InvalidSyntax, 1, 8)),
|
||||||
("{\"a\":1,", SyntaxError(EOFWhileParsingString, 1, 8)),
|
("{\"a\":1,", SyntaxError(EOFWhileParsingString, 1, 8)),
|
||||||
("{}a", SyntaxError(TrailingCharacters, 1, 3)),
|
("{}a", SyntaxError(TrailingCharacters, 1, 3)),
|
||||||
];
|
]);
|
||||||
|
|
||||||
for &(s, err) in errors.iter() {
|
test_parse_ok([
|
||||||
let v: Result<TreeMap<String, int>, ParserError> = from_iter(s.chars());
|
("{}", treemap!()),
|
||||||
assert_eq!(v, Err(err));
|
("{ }", treemap!()),
|
||||||
}
|
(
|
||||||
|
"{\"a\":3}",
|
||||||
|
treemap!("a".to_string() => 3)
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"{ \"a\" : 3 }",
|
||||||
|
treemap!("a".to_string() => 3)
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"{\"a\":3,\"b\":4}",
|
||||||
|
treemap!("a".to_string() => 3, "b".to_string() => 4)
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"{ \"a\" : 3 , \"b\" : 4 }",
|
||||||
|
treemap!("a".to_string() => 3, "b".to_string() => 4),
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
|
||||||
let v: TreeMap<String, int> = from_iter("{}".chars()).unwrap();
|
test_parse_ok([
|
||||||
let m = TreeMap::new();
|
(
|
||||||
assert!(v == m);
|
"{\"a\": {\"b\": 3, \"c\": 4}}",
|
||||||
|
treemap!("a".to_string() => treemap!("b".to_string() => 3, "c".to_string() => 4)),
|
||||||
let v: TreeMap<String, int> = from_iter("{ }".chars()).unwrap();
|
),
|
||||||
let m = TreeMap::new();
|
]);
|
||||||
assert!(v == m);
|
|
||||||
|
|
||||||
let v: TreeMap<String, int> = from_iter("{\"a\":3}".chars()).unwrap();
|
|
||||||
let mut m = TreeMap::new();
|
|
||||||
m.insert("a".to_str(), 3);
|
|
||||||
assert!(v == m);
|
|
||||||
|
|
||||||
let v: TreeMap<String, int> = from_iter("{\"a\" :3}".chars()).unwrap();
|
|
||||||
let mut m = TreeMap::new();
|
|
||||||
m.insert("a".to_str(), 3);
|
|
||||||
assert!(v == m);
|
|
||||||
|
|
||||||
let v: TreeMap<String, int> = from_iter("{\"a\" : 3}".chars()).unwrap();
|
|
||||||
let mut m = TreeMap::new();
|
|
||||||
m.insert("a".to_str(), 3);
|
|
||||||
assert!(v == m);
|
|
||||||
|
|
||||||
let v: TreeMap<String, int> = from_iter("{\"a\": 3, \"b\": 4}".chars()).unwrap();
|
|
||||||
let mut m = TreeMap::new();
|
|
||||||
m.insert("a".to_str(), 3);
|
|
||||||
m.insert("b".to_str(), 4);
|
|
||||||
assert!(v == m);
|
|
||||||
|
|
||||||
let v: TreeMap<String, int> = from_iter("{ \"a\": 3, \"b\": 4 }".chars()).unwrap();
|
|
||||||
let mut m = TreeMap::new();
|
|
||||||
m.insert("a".to_str(), 3);
|
|
||||||
m.insert("b".to_str(), 4);
|
|
||||||
assert!(v == m);
|
|
||||||
|
|
||||||
let v: TreeMap<String, TreeMap<String, int>> = from_iter("{\"a\": {\"b\": 3, \"c\": 4}}".chars()).unwrap();
|
|
||||||
let mut mm = TreeMap::new();
|
|
||||||
mm.insert("b".to_str(), 3);
|
|
||||||
mm.insert("c".to_str(), 4);
|
|
||||||
let mut m = TreeMap::new();
|
|
||||||
m.insert("a".to_str(), mm);
|
|
||||||
assert!(v == m);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_decode_struct() {
|
fn test_json_deserialize_object() {
|
||||||
let s = "{
|
test_json_deserialize_ok([
|
||||||
\"inner\": [
|
treemap!(),
|
||||||
{ \"a\": null, \"b\": 2, \"c\": [\"abc\", \"xyz\"] }
|
treemap!("a".to_string() => 3),
|
||||||
]
|
treemap!("a".to_string() => 3, "b".to_string() => 4),
|
||||||
}";
|
]);
|
||||||
let v: Outer = from_iter(s.chars()).unwrap();
|
|
||||||
assert_eq!(
|
test_json_deserialize_ok([
|
||||||
v,
|
treemap!("a".to_string() => treemap!("b".to_string() => 3, "c".to_string() => 4)),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_struct() {
|
||||||
|
test_parse_ok([
|
||||||
|
(
|
||||||
|
"{
|
||||||
|
\"inner\": []
|
||||||
|
}",
|
||||||
|
Outer {
|
||||||
|
inner: vec![]
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"{
|
||||||
|
\"inner\": [
|
||||||
|
{ \"a\": null, \"b\": 2, \"c\": [\"abc\", \"xyz\"] }
|
||||||
|
]
|
||||||
|
}",
|
||||||
|
Outer {
|
||||||
|
inner: vec![
|
||||||
|
Inner { a: (), b: 2, c: vec!["abc".to_string(), "xyz".to_string()] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_json_deserialize_struct() {
|
||||||
|
test_json_deserialize_ok([
|
||||||
Outer {
|
Outer {
|
||||||
inner: vec![
|
inner: vec![
|
||||||
Inner { a: (), b: 2, c: vec!["abc".to_string(), "xyz".to_string()] }
|
Inner { a: (), b: 2, c: vec!["abc".to_string(), "xyz".to_string()] }
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_decode_option() {
|
fn test_parse_option() {
|
||||||
let value: Result<Option<String>, ParserError> = from_iter("null".chars());
|
test_parse_ok([
|
||||||
assert_eq!(value, Ok(None));
|
("null", None),
|
||||||
|
("\"jodhpurs\"", Some("jodhpurs".to_string())),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
let value: Result<Option<String>, ParserError> = from_iter("\"jodhpurs\"".chars());
|
#[test]
|
||||||
assert_eq!(value, Ok(Some("jodhpurs".to_string())));
|
fn test_json_deserialize_option() {
|
||||||
|
test_json_deserialize_ok([
|
||||||
|
None,
|
||||||
|
Some("jodhpurs".to_string()),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user