add serde2 json deserializing to the benchmark

This commit is contained in:
Erick Tryzelaar
2014-12-05 22:19:30 -08:00
parent 38dc9aaf72
commit f6434fcf77
6 changed files with 488 additions and 289 deletions
+174 -226
View File
@@ -1,104 +1,36 @@
use std::char;
use std::fmt;
use std::num::Float;
use std::str::ScalarValue;
use std::str;
use de;
use de::Deserializer;
#[deriving(Clone, PartialEq, Eq)]
pub enum ErrorCode {
EOFWhileParsingList,
EOFWhileParsingObject,
EOFWhileParsingString,
EOFWhileParsingValue,
ExpectedColon,
InvalidEscape,
InvalidNumber,
InvalidSyntax(SyntaxExpectation),
InvalidUnicodeCodePoint,
KeyMustBeAString,
LoneLeadingSurrogateInHexEscape,
MissingField(&'static str),
NotFourDigit,
NotUtf8,
TrailingCharacters,
UnexpectedEndOfHexEscape,
UnknownVariant,
UnrecognizedHex,
}
/// The failed expectation of InvalidSyntax
#[deriving(Clone, PartialEq, Eq, Show)]
pub enum SyntaxExpectation {
ListCommaOrEnd,
ObjectCommaOrEnd,
SomeValue,
SomeIdent,
EnumMapStart,
EnumVariantString,
EnumToken,
EnumEndToken,
EnumEnd,
}
impl fmt::Show for ErrorCode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ErrorCode::EOFWhileParsingList => "EOF While parsing list".fmt(f),
ErrorCode::EOFWhileParsingObject => "EOF While parsing object".fmt(f),
ErrorCode::EOFWhileParsingString => "EOF While parsing string".fmt(f),
ErrorCode::EOFWhileParsingValue => "EOF While parsing value".fmt(f),
ErrorCode::ExpectedColon => "expected `:`".fmt(f),
ErrorCode::InvalidEscape => "invalid escape".fmt(f),
ErrorCode::InvalidNumber => "invalid number".fmt(f),
ErrorCode::InvalidSyntax(expect) => {
write!(f, "invalid syntax, expected: {}", expect)
}
ErrorCode::InvalidUnicodeCodePoint => "invalid unicode code point".fmt(f),
ErrorCode::KeyMustBeAString => "key must be a string".fmt(f),
ErrorCode::LoneLeadingSurrogateInHexEscape => "lone leading surrogate in hex escape".fmt(f),
ErrorCode::MissingField(field) => {
write!(f, "missing field \"{}\"", field)
}
ErrorCode::NotFourDigit => "invalid \\u escape (not four digits)".fmt(f),
ErrorCode::NotUtf8 => "contents not utf-8".fmt(f),
ErrorCode::TrailingCharacters => "trailing characters".fmt(f),
ErrorCode::UnexpectedEndOfHexEscape => "unexpected end of hex escape".fmt(f),
ErrorCode::UnknownVariant => "unknown variant".fmt(f),
ErrorCode::UnrecognizedHex => "invalid \\u escape (unrecognized hex)".fmt(f),
}
}
}
#[deriving(PartialEq, Eq, Show)]
pub enum Error {
SyntaxError(ErrorCode, uint, uint),
}
use super::error::{Error, ErrorCode};
pub struct Parser<Iter> {
rdr: Iter,
ch: Option<char>,
ch: Option<u8>,
line: uint,
col: uint,
buf: Vec<u8>,
}
impl<
Iter: Iterator<char>,
> Parser<Iter> {
impl<Iter: Iterator<u8>> Parser<Iter> {
/// Creates the JSON parser.
#[inline]
pub fn new(rdr: Iter) -> Parser<Iter> {
let mut p = Parser {
rdr: rdr,
ch: Some('\x00'),
ch: Some(b'\x00'),
line: 1,
col: 0,
buf: Vec::with_capacity(128),
};
p.bump();
return p;
}
#[inline]
pub fn end(&mut self) -> Result<(), Error> {
if self.eof() {
Ok(())
@@ -109,12 +41,14 @@ impl<
fn eof(&self) -> bool { self.ch.is_none() }
fn ch_or_null(&self) -> char { self.ch.unwrap_or('\x00') }
#[inline]
fn ch_or_null(&self) -> u8 { self.ch.unwrap_or(b'\x00') }
#[inline]
fn bump(&mut self) {
self.ch = self.rdr.next();
if self.ch_is('\n') {
if self.ch_is(b'\n') {
self.line += 1;
self.col = 1;
} else {
@@ -122,27 +56,31 @@ impl<
}
}
fn next_char(&mut self) -> Option<char> {
#[inline]
fn next_char(&mut self) -> Option<u8> {
self.bump();
self.ch
}
fn ch_is(&self, c: char) -> bool {
#[inline]
fn ch_is(&self, c: u8) -> bool {
self.ch == Some(c)
}
fn parse_whitespace(&mut self) {
while self.ch_is(' ') ||
self.ch_is('\n') ||
self.ch_is('\t') ||
self.ch_is('\r') { self.bump(); }
}
#[inline]
fn error(&mut self, reason: ErrorCode) -> Error {
//self.state_stack.clear();
Error::SyntaxError(reason, self.line, self.col)
}
#[inline]
fn parse_whitespace(&mut self) {
while self.ch_is(b' ') ||
self.ch_is(b'\n') ||
self.ch_is(b'\t') ||
self.ch_is(b'\r') { self.bump(); }
}
#[inline]
fn parse_value<
R,
V: de::Visitor<Parser<Iter>, R, Error>,
@@ -154,68 +92,71 @@ impl<
}
match self.ch_or_null() {
'n' => {
try!(self.parse_ident("ull"));
b'n' => {
try!(self.parse_ident(b"ull"));
visitor.visit_null(self)
}
't' => {
try!(self.parse_ident("rue"));
b't' => {
try!(self.parse_ident(b"rue"));
visitor.visit_bool(self, true)
}
'f' => {
try!(self.parse_ident("alse"));
b'f' => {
try!(self.parse_ident(b"alse"));
visitor.visit_bool(self, false)
}
'0' ... '9' | '-' => self.parse_number(visitor),
'"' => {
let s = try!(self.parse_string());
b'0' ... b'9' | b'-' => self.parse_number(visitor),
b'"' => {
try!(self.parse_string());
let s = String::from_utf8(self.buf.clone()).unwrap();
visitor.visit_string(self, s)
}
'[' => {
b'[' => {
self.bump();
visitor.visit_seq(self, SeqVisitor { first: true })
}
'{' => {
b'{' => {
self.bump();
visitor.visit_map(self, MapVisitor { first: true })
}
_ => {
Err(self.error(ErrorCode::InvalidSyntax(SyntaxExpectation::SomeValue)))
Err(self.error(ErrorCode::ExpectedSomeValue))
}
}
}
fn parse_ident(&mut self, ident: &str) -> Result<(), Error> {
if ident.chars().all(|c| Some(c) == self.next_char()) {
#[inline]
fn parse_ident(&mut self, ident: &[u8]) -> Result<(), Error> {
if ident.iter().all(|c| Some(*c) == self.next_char()) {
self.bump();
Ok(())
} else {
Err(self.error(ErrorCode::InvalidSyntax(SyntaxExpectation::SomeIdent)))
Err(self.error(ErrorCode::ExpectedSomeIdent))
}
}
#[inline]
fn parse_number<
R,
V: de::Visitor<Parser<Iter>, R, Error>,
>(&mut self, visitor: &mut V) -> Result<R, Error> {
let mut neg = 1;
if self.ch_is('-') {
if self.ch_is(b'-') {
self.bump();
neg = -1;
}
let res = try!(self.parse_integer());
if self.ch_is('.') || self.ch_is('e') || self.ch_is('E') {
if self.ch_is(b'.') || self.ch_is(b'e') || self.ch_is(b'E') {
let neg = neg as f64;
let mut res = res as f64;
if self.ch_is('.') {
if self.ch_is(b'.') {
res = try!(self.parse_decimal(res));
}
if self.ch_is('e') || self.ch_is('E') {
if self.ch_is(b'e') || self.ch_is(b'E') {
res = try!(self.parse_exponent(res));
}
@@ -225,59 +166,57 @@ impl<
}
}
#[inline]
fn parse_integer(&mut self) -> Result<i64, Error> {
let mut res = 0;
match self.ch_or_null() {
'0' => {
b'0' => {
self.bump();
// There can be only one leading '0'.
match self.ch_or_null() {
'0' ... '9' => {
b'0' ... b'9' => {
return Err(self.error(ErrorCode::InvalidNumber));
}
_ => ()
}
},
'1' ... '9' => {
b'1' ... b'9' => {
while !self.eof() {
match self.ch_or_null() {
c @ '0' ... '9' => {
c @ b'0' ... b'9' => {
res *= 10;
res += (c as i64) - ('0' as i64);
res += (c as i64) - (b'0' as i64);
self.bump();
}
_ => break,
}
}
}
_ => {
return Err(self.error(ErrorCode::InvalidNumber));
}
_ => { return Err(self.error(ErrorCode::InvalidNumber)); }
}
Ok(res)
}
#[inline]
fn parse_decimal(&mut self, res: f64) -> Result<f64, Error> {
self.bump();
// Make sure a digit follows the decimal place.
match self.ch_or_null() {
'0' ... '9' => (),
_ => {
return Err(self.error(ErrorCode::InvalidNumber));
}
b'0' ... b'9' => (),
_ => { return Err(self.error(ErrorCode::InvalidNumber)); }
}
let mut res = res;
let mut dec = 1.0;
while !self.eof() {
match self.ch_or_null() {
c @ '0' ... '9' => {
c @ b'0' ... b'9' => {
dec /= 10.0;
res += (((c as int) - ('0' as int)) as f64) * dec;
res += (((c as int) - (b'0' as int)) as f64) * dec;
self.bump();
}
_ => break,
@@ -287,31 +226,30 @@ impl<
Ok(res)
}
#[inline]
fn parse_exponent(&mut self, mut res: f64) -> Result<f64, Error> {
self.bump();
let mut exp = 0u;
let mut neg_exp = false;
if self.ch_is('+') {
if self.ch_is(b'+') {
self.bump();
} else if self.ch_is('-') {
} else if self.ch_is(b'-') {
self.bump();
neg_exp = true;
}
// Make sure a digit follows the exponent place.
match self.ch_or_null() {
'0' ... '9' => (),
_ => {
return Err(self.error(ErrorCode::InvalidNumber));
}
b'0' ... b'9' => (),
_ => { return Err(self.error(ErrorCode::InvalidNumber)); }
}
while !self.eof() {
match self.ch_or_null() {
c @ '0' ... '9' => {
c @ b'0' ... b'9' => {
exp *= 10;
exp += (c as uint) - ('0' as uint);
exp += (c as uint) - (b'0' as uint);
self.bump();
}
@@ -329,22 +267,21 @@ impl<
Ok(res)
}
#[inline]
fn decode_hex_escape(&mut self) -> Result<u16, Error> {
let mut i = 0u;
let mut n = 0u16;
while i < 4u && !self.eof() {
self.bump();
n = match self.ch_or_null() {
c @ '0' ... '9' => n * 16_u16 + ((c as u16) - ('0' as u16)),
'a' | 'A' => n * 16_u16 + 10_u16,
'b' | 'B' => n * 16_u16 + 11_u16,
'c' | 'C' => n * 16_u16 + 12_u16,
'd' | 'D' => n * 16_u16 + 13_u16,
'e' | 'E' => n * 16_u16 + 14_u16,
'f' | 'F' => n * 16_u16 + 15_u16,
_ => {
return Err(self.error(ErrorCode::InvalidEscape));
}
c @ b'0' ... b'9' => n * 16_u16 + ((c as u16) - (b'0' as u16)),
b'a' | b'A' => n * 16_u16 + 10_u16,
b'b' | b'B' => n * 16_u16 + 11_u16,
b'c' | b'C' => n * 16_u16 + 12_u16,
b'd' | b'D' => n * 16_u16 + 13_u16,
b'e' | b'E' => n * 16_u16 + 14_u16,
b'f' | b'F' => n * 16_u16 + 15_u16,
_ => { return Err(self.error(ErrorCode::InvalidEscape)); }
};
i += 1u;
@@ -358,81 +295,91 @@ impl<
Ok(n)
}
fn parse_string(&mut self) -> Result<String, Error> {
#[inline]
fn parse_string(&mut self) -> Result<(), Error> {
self.buf.clear();
let mut escape = false;
let mut res = String::new();
loop {
self.bump();
if self.eof() {
return Err(self.error(ErrorCode::EOFWhileParsingString));
}
let ch = match self.next_char() {
Some(ch) => ch,
None => { return Err(self.error(ErrorCode::EOFWhileParsingString)); }
};
if escape {
match self.ch_or_null() {
'"' => res.push('"'),
'\\' => res.push('\\'),
'/' => res.push('/'),
'b' => res.push('\x08'),
'f' => res.push('\x0c'),
'n' => res.push('\n'),
'r' => res.push('\r'),
't' => res.push('\t'),
'u' => match try!(self.decode_hex_escape()) {
0xDC00 ... 0xDFFF => {
return Err(self.error(ErrorCode::LoneLeadingSurrogateInHexEscape));
}
match ch {
b'"' => self.buf.push(b'"'),
b'\\' => self.buf.push(b'\\'),
b'/' => self.buf.push(b'/'),
b'b' => self.buf.push(b'\x08'),
b'f' => self.buf.push(b'\x0c'),
b'n' => self.buf.push(b'\n'),
b'r' => self.buf.push(b'\r'),
b't' => self.buf.push(b'\t'),
b'u' => {
let c = match try!(self.decode_hex_escape()) {
0xDC00 ... 0xDFFF => {
return Err(self.error(ErrorCode::LoneLeadingSurrogateInHexEscape));
}
// Non-BMP characters are encoded as a sequence of
// two hex escapes, representing UTF-16 surrogates.
n1 @ 0xD800 ... 0xDBFF => {
let c1 = self.next_char();
let c2 = self.next_char();
match (c1, c2) {
(Some('\\'), Some('u')) => (),
_ => {
return Err(self.error(ErrorCode::UnexpectedEndOfHexEscape));
// Non-BMP characters are encoded as a sequence of
// two hex escapes, representing UTF-16 surrogates.
n1 @ 0xD800 ... 0xDBFF => {
let c1 = self.next_char();
let c2 = self.next_char();
match (c1, c2) {
(Some(b'\\'), Some(b'u')) => (),
_ => {
return Err(self.error(ErrorCode::UnexpectedEndOfHexEscape));
}
}
let buf = &[n1, try!(self.decode_hex_escape())];
match str::utf16_items(buf.as_slice()).next() {
Some(ScalarValue(c)) => c,
_ => {
return Err(self.error(ErrorCode::LoneLeadingSurrogateInHexEscape));
}
}
}
let buf = [n1, try!(self.decode_hex_escape())];
match str::utf16_items(buf.as_slice()).next() {
Some(ScalarValue(c)) => res.push(c),
_ => {
return Err(self.error(ErrorCode::LoneLeadingSurrogateInHexEscape));
n => match char::from_u32(n as u32) {
Some(c) => c,
None => {
return Err(self.error(ErrorCode::InvalidUnicodeCodePoint));
}
}
}
};
n => match char::from_u32(n as u32) {
Some(c) => res.push(c),
None => {
return Err(self.error(ErrorCode::InvalidUnicodeCodePoint));
}
},
},
let buf = &mut [0u8, .. 4];
let len = c.encode_utf8(buf).unwrap_or(0);
self.buf.extend(buf.slice_to(len).iter().map(|b| *b));
}
_ => {
return Err(self.error(ErrorCode::InvalidEscape));
}
}
escape = false;
} else if self.ch_is('\\') {
escape = true;
} else {
match self.ch {
Some('"') => {
match ch {
b'"' => {
self.bump();
return Ok(res);
},
Some(c) => res.push(c),
None => unreachable!()
return Ok(());
}
b'\\' => {
escape = true;
}
ch => {
self.buf.push(ch);
}
}
}
}
}
}
impl<Iter: Iterator<char>> Deserializer<Error> for Parser<Iter> {
impl<Iter: Iterator<u8>> Deserializer<Error> for Parser<Iter> {
#[inline]
fn visit<
R,
@@ -442,7 +389,7 @@ impl<Iter: Iterator<char>> Deserializer<Error> for Parser<Iter> {
}
fn syntax_error(&mut self) -> Error {
Error::SyntaxError(ErrorCode::InvalidSyntax(SyntaxExpectation::SomeValue), self.line, self.col)
Error::SyntaxError(ErrorCode::ExpectedSomeValue, self.line, self.col)
}
fn end_of_stream_error(&mut self) -> Error {
@@ -454,13 +401,13 @@ struct SeqVisitor {
first: bool,
}
impl<Iter: Iterator<char>> de::SeqVisitor<Parser<Iter>, Error> for SeqVisitor {
impl<Iter: Iterator<u8>> de::SeqVisitor<Parser<Iter>, Error> for SeqVisitor {
fn visit<
T: de::Deserialize<Parser<Iter>, Error>,
>(&mut self, d: &mut Parser<Iter>) -> Result<Option<T>, Error> {
d.parse_whitespace();
if d.ch_is(']') {
if d.ch_is(b']') {
d.bump();
return Ok(None);
}
@@ -468,12 +415,12 @@ impl<Iter: Iterator<char>> de::SeqVisitor<Parser<Iter>, Error> for SeqVisitor {
if self.first {
self.first = false;
} else {
if d.ch_is(',') {
if d.ch_is(b',') {
d.bump();
} else if d.eof() {
return Err(d.error(ErrorCode::EOFWhileParsingList));
} else {
return Err(d.error(ErrorCode::InvalidSyntax(SyntaxExpectation::ListCommaOrEnd)));
return Err(d.error(ErrorCode::ExpectedListCommaOrEnd));
}
}
@@ -482,7 +429,7 @@ impl<Iter: Iterator<char>> de::SeqVisitor<Parser<Iter>, Error> for SeqVisitor {
}
fn end(&mut self, d: &mut Parser<Iter>) -> Result<(), Error> {
if d.ch_is(']') {
if d.ch_is(b']') {
d.bump();
Ok(())
} else if d.eof() {
@@ -497,14 +444,13 @@ struct MapVisitor {
first: bool,
}
impl<Iter: Iterator<char>> de::MapVisitor<Parser<Iter>, Error> for MapVisitor {
fn visit<
impl<Iter: Iterator<u8>> de::MapVisitor<Parser<Iter>, Error> for MapVisitor {
fn visit_key<
K: de::Deserialize<Parser<Iter>, Error>,
V: de::Deserialize<Parser<Iter>, Error>,
>(&mut self, d: &mut Parser<Iter>) -> Result<Option<(K, V)>, Error> {
>(&mut self, d: &mut Parser<Iter>) -> Result<Option<K>, Error> {
d.parse_whitespace();
if d.ch_is('}') {
if d.ch_is(b'}') {
d.bump();
return Ok(None);
}
@@ -512,13 +458,13 @@ impl<Iter: Iterator<char>> de::MapVisitor<Parser<Iter>, Error> for MapVisitor {
if self.first {
self.first = false;
} else {
if d.ch_is(',') {
if d.ch_is(b',') {
d.bump();
d.parse_whitespace();
} else if d.eof() {
return Err(d.error(ErrorCode::EOFWhileParsingObject));
} else {
return Err(d.error(ErrorCode::InvalidSyntax(SyntaxExpectation::ObjectCommaOrEnd)));
return Err(d.error(ErrorCode::ExpectedObjectCommaOrEnd));
}
}
@@ -526,15 +472,19 @@ impl<Iter: Iterator<char>> de::MapVisitor<Parser<Iter>, Error> for MapVisitor {
return Err(d.error(ErrorCode::EOFWhileParsingValue));
}
if !d.ch_is('"') {
if !d.ch_is(b'"') {
return Err(d.error(ErrorCode::KeyMustBeAString));
}
let key = try!(de::Deserialize::deserialize(d));
Ok(Some(try!(de::Deserialize::deserialize(d))))
}
fn visit_value<
V: de::Deserialize<Parser<Iter>, Error>,
>(&mut self, d: &mut Parser<Iter>) -> Result<V, Error> {
d.parse_whitespace();
if d.ch_is(':') {
if d.ch_is(b':') {
d.bump();
} else if d.eof() {
return Err(d.error(ErrorCode::EOFWhileParsingObject));
@@ -544,13 +494,11 @@ impl<Iter: Iterator<char>> de::MapVisitor<Parser<Iter>, Error> for MapVisitor {
d.parse_whitespace();
let value = try!(de::Deserialize::deserialize(d));
Ok(Some((key, value)))
Ok(try!(de::Deserialize::deserialize(d)))
}
fn end(&mut self, d: &mut Parser<Iter>) -> Result<(), Error> {
if d.ch_is(']') {
if d.ch_is(b']') {
d.bump();
Ok(())
} else if d.eof() {
@@ -561,9 +509,9 @@ impl<Iter: Iterator<char>> de::MapVisitor<Parser<Iter>, Error> for MapVisitor {
}
}
/// Decodes a json value from an `Iterator<Char>`.
/// Decodes a json value from an `Iterator<u8>`.
pub fn from_iter<
Iter: Iterator<char>,
Iter: Iterator<u8>,
T: de::Deserialize<Parser<Iter>, Error>
>(iter: Iter) -> Result<T, Error> {
let mut parser = Parser::new(iter);
@@ -577,12 +525,11 @@ pub fn from_iter<
/// Decodes a json value from a string
pub fn from_str<
'a,
T: de::Deserialize<Parser<str::Chars<'a>>, Error>
T: de::Deserialize<Parser<str::Bytes<'a>>, Error>
>(s: &'a str) -> Result<T, Error> {
from_iter(s.chars())
from_iter(s.bytes())
}
#[cfg(test)]
mod tests {
use std::str;
@@ -590,7 +537,8 @@ mod tests {
use std::collections::TreeMap;
use de::Deserialize;
use super::{Parser, Error, ErrorCode, SyntaxExpectation, from_str};
use super::{Parser, from_str};
use super::super::error::{Error, ErrorCode};
macro_rules! treemap {
($($k:expr => $v:expr),*) => ({
@@ -602,7 +550,7 @@ mod tests {
fn test_parse_ok<
'a,
T: PartialEq + Show + Deserialize<Parser<str::Chars<'a>>, Error>,
T: PartialEq + Show + Deserialize<Parser<str::Bytes<'a>>, Error>,
>(errors: Vec<(&'a str, T)>) {
for (s, value) in errors.into_iter() {
let v: Result<T, Error> = from_str(s);
@@ -617,7 +565,7 @@ mod tests {
fn test_parse_err<
'a,
T: PartialEq + Show + Deserialize<Parser<str::Chars<'a>>, Error>
T: PartialEq + Show + Deserialize<Parser<str::Bytes<'a>>, Error>
>(errors: Vec<(&'a str, Error)>) {
for (s, err) in errors.into_iter() {
let v: Result<T, Error> = from_str(s);
@@ -635,10 +583,10 @@ mod tests {
#[test]
fn test_parse_bool() {
test_parse_err::<bool>(vec![
("t", Error::SyntaxError(ErrorCode::InvalidSyntax(SyntaxExpectation::SomeIdent), 1, 2)),
("truz", Error::SyntaxError(ErrorCode::InvalidSyntax(SyntaxExpectation::SomeIdent), 1, 4)),
("f", Error::SyntaxError(ErrorCode::InvalidSyntax(SyntaxExpectation::SomeIdent), 1, 2)),
("faz", Error::SyntaxError(ErrorCode::InvalidSyntax(SyntaxExpectation::SomeIdent), 1, 3)),
("t", Error::SyntaxError(ErrorCode::ExpectedSomeIdent, 1, 2)),
("truz", Error::SyntaxError(ErrorCode::ExpectedSomeIdent, 1, 4)),
("f", Error::SyntaxError(ErrorCode::ExpectedSomeIdent, 1, 2)),
("faz", Error::SyntaxError(ErrorCode::ExpectedSomeIdent, 1, 3)),
("truea", Error::SyntaxError(ErrorCode::TrailingCharacters, 1, 5)),
("falsea", Error::SyntaxError(ErrorCode::TrailingCharacters, 1, 6)),
]);
@@ -652,8 +600,8 @@ mod tests {
#[test]
fn test_parse_numbers() {
test_parse_err::<f64>(vec![
("+", Error::SyntaxError(ErrorCode::InvalidSyntax(SyntaxExpectation::SomeValue), 1, 1)),
(".", Error::SyntaxError(ErrorCode::InvalidSyntax(SyntaxExpectation::SomeValue), 1, 1)),
("+", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 1)),
(".", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 1)),
("-", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 2)),
("00", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 2)),
("1.", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 3)),
@@ -707,8 +655,8 @@ mod tests {
("[ ", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 3)),
("[1", Error::SyntaxError(ErrorCode::EOFWhileParsingList, 1, 3)),
("[1,", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 4)),
("[1,]", Error::SyntaxError(ErrorCode::InvalidSyntax(SyntaxExpectation::SomeValue), 1, 4)),
("[1 2]", Error::SyntaxError(ErrorCode::InvalidSyntax(SyntaxExpectation::ListCommaOrEnd), 1, 4)),
("[1,]", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 4)),
("[1 2]", Error::SyntaxError(ErrorCode::ExpectedListCommaOrEnd, 1, 4)),
("[]a", Error::SyntaxError(ErrorCode::TrailingCharacters, 1, 3)),
]);
@@ -761,7 +709,7 @@ mod tests {
("{\"a\" 1", Error::SyntaxError(ErrorCode::ExpectedColon, 1, 6)),
("{\"a\":", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 6)),
("{\"a\":1", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 1, 7)),
("{\"a\":1 1", Error::SyntaxError(ErrorCode::InvalidSyntax(SyntaxExpectation::ObjectCommaOrEnd), 1, 8)),
("{\"a\":1 1", Error::SyntaxError(ErrorCode::ExpectedObjectCommaOrEnd, 1, 8)),
("{\"a\":1,", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 8)),
("{}a", Error::SyntaxError(ErrorCode::TrailingCharacters, 1, 3)),
]);