Get all the json types to parse

This commit is contained in:
Erick Tryzelaar
2014-05-26 14:27:08 -07:00
parent 0d56ae5986
commit e58096dcc2
+173 -245
View File
@@ -976,6 +976,7 @@ impl Json {
} }
*/ */
/*
/// The output of the streaming parser. /// The output of the streaming parser.
#[deriving(Eq, Clone, Show)] #[deriving(Eq, Clone, Show)]
pub enum JsonEvent { pub enum JsonEvent {
@@ -989,19 +990,24 @@ pub enum JsonEvent {
NullValue, NullValue,
Error(ParserError), Error(ParserError),
} }
*/
#[deriving(Eq, Show)] #[deriving(Eq, Show)]
enum ParserState { enum ParserState {
// Parse a value in a list, true means first element. // Parse a value.
ParseList(bool), ParseValue,
// Parse a value or ']'.
ParseListStart,
// Parse ',' or ']' after an element in a list. // Parse ',' or ']' after an element in a list.
ParseListComma, ParseListCommaOrEnd,
// Parse a key:value in an object, true means first element. // Parse a key:value or an ']'.
ParseObject(bool), ParseObjectStart,
// Parse ',' or ']' after an element in an object. // Parse ',' or ']' after an element in an object.
ParseObjectComma, ParseObjectCommaOrEnd,
// Initialial state. // Parse a key in an object.
ParseStart, ParseObjectKey,
// Parse a value in an object.
ParseObjectValue,
// Expecting the stream to end. // Expecting the stream to end.
ParseBeforeFinish, ParseBeforeFinish,
// Parsing can't continue. // Parsing can't continue.
@@ -1157,42 +1163,36 @@ pub struct Parser<T> {
ch: Option<char>, ch: Option<char>,
line: uint, line: uint,
col: uint, col: uint,
// We maintain a stack representing where we are in the logical structure
// of the JSON stream.
stack: Stack,
// A state machine is kept to make it possible to interupt and resume parsing. // A state machine is kept to make it possible to interupt and resume parsing.
state: ParserState, state: Vec<ParserState>,
} }
impl<T: Iterator<char>> Iterator<Result<de::Token, ParserError>> for Parser<T> { impl<T: Iterator<char>> Iterator<Result<de::Token, ParserError>> for Parser<T> {
fn next(&mut self) -> Option<Result<de::Token, ParserError>> { fn next(&mut self) -> Option<Result<de::Token, ParserError>> {
if self.state == ParseFinished { let state = match self.state.pop() {
return None; Some(state) => state,
} None => { return None; }
};
if self.state == ParseBeforeFinish { match state {
self.parse_whitespace(); ParseFinished => None,
// Make sure there is no trailing characters. ParseBeforeFinish => {
if self.eof() { self.parse_whitespace();
self.state = ParseFinished; // Make sure there is no trailing characters.
return None; if self.eof() {
} else { self.state.push(ParseFinished);
return Some(self.error(TrailingCharacters)); None
} else {
Some(self.error(TrailingCharacters))
}
} }
} ParseValue => Some(self.parse_value()),
ParseListStart => Some(self.parse_list_start()),
let event = self.parse(); ParseListCommaOrEnd => Some(self.parse_list_comma_or_end()),
ParseObjectStart => Some(self.parse_object_start()),
match event { ParseObjectCommaOrEnd => Some(self.parse_object_comma_or_end()),
ObjectStart => Some(Ok(de::MapStart(0))), ParseObjectKey => Some(self.parse_object_key()),
ObjectEnd => Some(Ok(de::End)), ParseObjectValue => Some(self.parse_object_value()),
ListStart => Some(Ok(de::SeqStart(0))),
ListEnd => Some(Ok(de::End)),
NullValue => Some(Ok(de::Null)),
BooleanValue(value) => Some(Ok(de::Bool(value))),
NumberValue(value) => Some(Ok(de::F64(value))),
StringValue(value) => Some(Ok(de::String(value.to_strbuf()))),
Error(err) => Some(Err(err)),
} }
} }
} }
@@ -1205,19 +1205,12 @@ impl<T: Iterator<char>> Parser<T> {
ch: Some('\x00'), ch: Some('\x00'),
line: 1, line: 1,
col: 0, col: 0,
stack: Stack::new(), state: vec!(ParseValue),
state: ParseStart,
}; };
p.bump(); p.bump();
return p; return p;
} }
/// Provides access to the current position in the logical structure of the
/// JSON stream.
pub fn stack<'l>(&'l self) -> &'l Stack {
return &'l self.stack;
}
fn eof(&self) -> bool { self.ch.is_none() } fn eof(&self) -> bool { self.ch.is_none() }
fn ch_or_null(&self) -> char { self.ch.unwrap_or('\x00') } fn ch_or_null(&self) -> char { self.ch.unwrap_or('\x00') }
fn bump(&mut self) { fn bump(&mut self) {
@@ -1465,238 +1458,121 @@ impl<T: Iterator<char>> Parser<T> {
} }
} }
// Invoked at each iteration, consumes the stream until it has enough fn parse_list_start(&mut self) -> Result<de::Token, ParserError> {
// information to return a JsonEvent.
// Manages an internal state so that parsing can be interrupted and resumed.
// Also keeps track of the position in the logical structure of the json
// stream int the form of a stack that can be queried by the user usng the
// stack() method.
fn parse(&mut self) -> JsonEvent {
loop {
// The only paths where the loop can spin a new iteration
// are in the cases ParseListComma and ParseObjectComma if ','
// is parsed. In these cases the state is set to (respectively)
// ParseList(false) and ParseObject(false), which always return,
// so there is no risk of getting stuck in an infinite loop.
// All other paths return before the end of the loop's iteration.
self.parse_whitespace();
match self.state {
ParseStart => {
return self.parse_start();
}
ParseList(first) => {
return self.parse_list(first);
}
ParseListComma => {
match self.parse_list_comma_or_end() {
Some(evt) => { return evt; }
None => {}
}
}
/*
ParseObject(first) => {
return self.parse_object(first);
}
ParseObjectComma => {
self.stack.pop();
if self.ch_is(',') {
self.state = ParseObject(false);
self.bump();
} else {
return self.parse_object_end();
}
}
*/
_ => {
return self.error_event(InvalidSyntax);
}
}
}
}
fn parse_start(&mut self) -> JsonEvent {
let val = self.parse_value();
self.state = match val {
Error(_) => { ParseFinished }
ListStart => { ParseList(true) }
//ObjectStart => { ParseObject(true) }
_ => { ParseBeforeFinish }
};
return val;
}
fn parse_list(&mut self, first: bool) -> JsonEvent {
if self.ch_is(']') { if self.ch_is(']') {
if !first {
return self.error_event(InvalidSyntax);
}
if self.stack.is_empty() {
self.state = ParseBeforeFinish;
} else {
self.state = if self.stack.last_is_index() {
ParseListComma
} else {
ParseObjectComma
}
}
self.bump(); self.bump();
return ListEnd; Ok(de::End)
} else {
self.state.push(ParseListCommaOrEnd);
self.parse_value()
} }
if first {
self.stack.push_index(0);
}
let val = self.parse_value();
self.state = match val {
Error(_) => { ParseFinished }
ListStart => { ParseList(true) }
ObjectStart => { ParseObject(true) }
_ => { ParseListComma }
};
return val;
} }
fn parse_list_comma_or_end(&mut self) -> Option<JsonEvent> { fn parse_list_comma_or_end(&mut self) -> Result<de::Token, ParserError> {
if self.ch_is(',') { if self.ch_is(',') {
self.stack.bump_index();
self.state = ParseList(false);
self.bump(); self.bump();
return None; self.state.push(ParseListCommaOrEnd);
self.parse_value()
} else if self.ch_is(']') { } else if self.ch_is(']') {
self.stack.pop();
if self.stack.is_empty() {
self.state = ParseBeforeFinish;
} else {
self.state = if self.stack.last_is_index() {
ParseListComma
} else {
ParseObjectComma
}
}
self.bump(); self.bump();
return Some(ListEnd); Ok(de::End)
} else if self.eof() { } else if self.eof() {
return Some(self.error_event(EOFWhileParsingList)); self.error_event(EOFWhileParsingList)
} else { } else {
return Some(self.error_event(InvalidSyntax)); self.error_event(InvalidSyntax)
} }
} }
/* fn parse_object_start(&mut self) -> Result<de::Token, ParserError> {
fn parse_object(&mut self, first: bool) -> JsonEvent {
if self.ch_is('}') {
if !first {
self.stack.pop();
}
if self.stack.is_empty() {
self.state = ParseBeforeFinish;
} else {
self.state = if self.stack.last_is_index() {
ParseListComma
} else {
ParseObjectComma
}
}
self.bump();
return ObjectEnd;
}
if self.eof() {
return self.error_event(EOFWhileParsingObject);
}
if !self.ch_is('"') {
return self.error_event(KeyMustBeAString);
}
let s = match self.parse_str() {
Ok(s) => { s }
Err(e) => {
self.state = ParseFinished;
return Error(e);
}
};
self.parse_whitespace(); self.parse_whitespace();
if self.eof() { if self.ch_is('}') {
return self.error_event(EOFWhileParsingObject); self.bump();
} else if self.ch_or_null() != ':' { Ok(de::End)
return self.error_event(ExpectedColon); } else {
self.parse_object_key()
} }
self.stack.push_key(s); }
self.bump();
fn parse_object_comma_or_end(&mut self) -> Result<de::Token, ParserError> {
self.parse_whitespace();
if self.ch_is(',') {
self.bump();
self.parse_object_key()
} else if self.ch_is('}') {
self.bump();
Ok(de::End)
} else if self.eof() {
self.error_event(EOFWhileParsingList)
} else {
self.error_event(InvalidSyntax)
}
}
fn parse_object_key(&mut self) -> Result<de::Token, ParserError> {
self.parse_whitespace();
self.state.push(ParseObjectValue);
let key = try!(self.parse_str());
Ok(de::String(key))
}
fn parse_object_value(&mut self) -> Result<de::Token, ParserError> {
self.parse_whitespace();
if self.ch_is(':') {
self.bump();
self.state.push(ParseObjectCommaOrEnd);
self.parse_value()
} else if self.eof() {
self.error_event(EOFWhileParsingList)
} else {
self.error_event(InvalidSyntax)
}
}
fn parse_value(&mut self) -> Result<de::Token, ParserError> {
self.parse_whitespace(); self.parse_whitespace();
let val = self.parse_value(); if self.eof() {
return self.error_event(EOFWhileParsingValue);
self.state = match val {
Error(_) => { ParseFinished }
ListStart => { ParseList(true) }
ObjectStart => { ParseObject(true) }
_ => { ParseObjectComma }
};
return val;
}
fn parse_object_end(&mut self) -> JsonEvent {
if self.ch_is('}') {
if self.stack.is_empty() {
self.state = ParseBeforeFinish;
} else {
self.state = if self.stack.last_is_index() {
ParseListComma
} else {
ParseObjectComma
}
}
self.bump();
return ObjectEnd;
} else if self.eof() {
return self.error_event(EOFWhileParsingObject);
} else {
return self.error_event(InvalidSyntax);
} }
}
*/
fn parse_value(&mut self) -> JsonEvent {
if self.eof() { return self.error_event(EOFWhileParsingValue); }
match self.ch_or_null() { match self.ch_or_null() {
'n' => { return self.parse_ident("ull", NullValue); } 'n' => self.parse_ident("ull", de::Null),
't' => { return self.parse_ident("rue", BooleanValue(true)); } 't' => self.parse_ident("rue", de::Bool(true)),
'f' => { return self.parse_ident("alse", BooleanValue(false)); } 'f' => self.parse_ident("alse", de::Bool(false)),
'0' .. '9' | '-' => return match self.parse_number() { '0' .. '9' | '-' => {
Ok(f) => NumberValue(f), let number = try!(self.parse_number());
Err(e) => Error(e), Ok(de::F64(number))
}, }
'"' => return match self.parse_str() { '"' => {
Ok(s) => StringValue(s), let s = try!(self.parse_str());
Err(e) => Error(e), Ok(de::String(s))
}, }
'[' => { '[' => {
self.bump(); self.bump();
return ListStart; self.state.push(ParseListStart);
Ok(de::SeqStart(0))
} }
/*
'{' => { '{' => {
self.bump(); self.bump();
return ObjectStart; self.state.push(ParseObjectStart);
Ok(de::MapStart(0))
} }
*/ _ => self.error_event(InvalidSyntax),
_ => { return self.error_event(InvalidSyntax); }
} }
} }
fn parse_ident(&mut self, ident: &str, value: JsonEvent) -> JsonEvent { fn parse_ident(&mut self, ident: &str, value: de::Token) -> Result<de::Token, ParserError> {
if ident.chars().all(|c| Some(c) == self.next_char()) { if ident.chars().all(|c| Some(c) == self.next_char()) {
self.bump(); self.bump();
value Ok(value)
} else { } else {
Error(SyntaxError(InvalidSyntax, self.line, self.col)) Err(SyntaxError(InvalidSyntax, self.line, self.col))
} }
} }
fn error_event(&mut self, reason: ErrorCode) -> JsonEvent { fn error_event(&mut self, reason: ErrorCode) -> Result<de::Token, ParserError> {
self.state = ParseFinished; self.state.clear();
Error(SyntaxError(reason, self.line, self.col)) Err(SyntaxError(reason, self.line, self.col))
} }
} }
@@ -2754,10 +2630,6 @@ mod tests {
let v: Vec<bool> = de::Deserializable::deserialize(&mut parser).unwrap(); let v: Vec<bool> = de::Deserializable::deserialize(&mut parser).unwrap();
assert_eq!(v, vec![true]); assert_eq!(v, vec![true]);
let mut parser = Parser::new("[true]".chars());
let v: Vec<bool> = de::Deserializable::deserialize(&mut parser).unwrap();
assert_eq!(v, vec![true]);
let mut parser = Parser::new("[3, 1]".chars()); let mut parser = Parser::new("[3, 1]".chars());
let v: Vec<int> = de::Deserializable::deserialize(&mut parser).unwrap(); let v: Vec<int> = de::Deserializable::deserialize(&mut parser).unwrap();
assert_eq!(v, vec![3, 1]); assert_eq!(v, vec![3, 1]);
@@ -2822,7 +2694,63 @@ mod tests {
])) ]))
])); ]));
} }
*/
#[test]
fn test_decode_object() {
let mut parser = Parser::new("{}".chars());
let v: TreeMap<String, int> = de::Deserializable::deserialize(&mut parser).unwrap();
let m = TreeMap::new();
assert!(v == m);
let mut parser = Parser::new("{ }".chars());
let v: TreeMap<String, int> = de::Deserializable::deserialize(&mut parser).unwrap();
let m = TreeMap::new();
assert!(v == m);
let mut parser = Parser::new("{\"a\":3}".chars());
let v: TreeMap<String, int> = de::Deserializable::deserialize(&mut parser).unwrap();
let mut m = TreeMap::new();
m.insert("a".to_str(), 3);
assert!(v == m);
let mut parser = Parser::new("{\"a\" :3}".chars());
let v: TreeMap<String, int> = de::Deserializable::deserialize(&mut parser).unwrap();
let mut m = TreeMap::new();
m.insert("a".to_str(), 3);
assert!(v == m);
let mut parser = Parser::new("{\"a\" : 3}".chars());
let v: TreeMap<String, int> = de::Deserializable::deserialize(&mut parser).unwrap();
let mut m = TreeMap::new();
m.insert("a".to_str(), 3);
assert!(v == m);
let mut parser = Parser::new("{\"a\": 3, \"b\": 4}".chars());
let v: TreeMap<String, int> = de::Deserializable::deserialize(&mut parser).unwrap();
let mut m = TreeMap::new();
m.insert("a".to_str(), 3);
m.insert("b".to_str(), 4);
assert!(v == m);
let mut parser = Parser::new("{ \"a\": 3, \"b\": 4 }".chars());
let v: TreeMap<String, int> = de::Deserializable::deserialize(&mut parser).unwrap();
let mut m = TreeMap::new();
m.insert("a".to_str(), 3);
m.insert("b".to_str(), 4);
assert!(v == m);
let mut parser = Parser::new("{\"a\": {\"b\": 3, \"c\": 4}}".chars());
let v: TreeMap<String, TreeMap<String, int>> = de::Deserializable::deserialize(&mut parser).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_decode_struct() {
let s = "{ let s = "{