From 4a713cdbea2859b8d5bde59c6af928431c6c11f1 Mon Sep 17 00:00:00 2001 From: kvark Date: Sat, 6 Sep 2014 23:08:51 -0400 Subject: [PATCH] Improved SyntaxError --- benches/bench_log.rs | 1 + src/de.rs | 17 ++++---- src/json/mod.rs | 97 ++++++++++++++++++++++++++++---------------- 3 files changed, 74 insertions(+), 41 deletions(-) diff --git a/benches/bench_log.rs b/benches/bench_log.rs index 67da760b..d9c47251 100644 --- a/benches/bench_log.rs +++ b/benches/bench_log.rs @@ -844,6 +844,7 @@ fn bench_manual_mem_writer_no_escape(b: &mut Bencher) { b.iter(|| { let mut wr = MemWriter::with_capacity(1024); manual_no_escape(wr.by_ref(), &log); + let _json = wr.unwrap(); //let _json = String::from_utf8(_json).unwrap(); diff --git a/src/de.rs b/src/de.rs index 6c9d22c7..618b9f49 100644 --- a/src/de.rs +++ b/src/de.rs @@ -1100,8 +1100,11 @@ mod tests { #[deriving(Show)] enum Error { EndOfStream, - SyntaxError, + SyntaxError(Vec), + UnexpectedName, + ConversionError, IncompleteValue, + MissingField(&'static str), } ////////////////////////////////////////////////////////////////////////////// @@ -1134,23 +1137,23 @@ mod tests { EndOfStream } - fn syntax_error(&mut self, _token: Token, _expected: &[TokenKind]) -> Error { - SyntaxError + fn syntax_error(&mut self, _token: Token, expected: &[TokenKind]) -> Error { + SyntaxError(expected.to_vec()) } fn unexpected_name_error(&mut self, _token: Token) -> Error { - SyntaxError + UnexpectedName } fn conversion_error(&mut self, _token: Token) -> Error { - SyntaxError + ConversionError } #[inline] fn missing_field< T: Deserializable, Error> - >(&mut self, _field: &'static str) -> Result { - Err(SyntaxError) + >(&mut self, field: &'static str) -> Result { + Err(MissingField(field)) } } diff --git a/src/json/mod.rs b/src/json/mod.rs index de2a4640..ba709910 100644 --- a/src/json/mod.rs +++ b/src/json/mod.rs @@ -645,16 +645,16 @@ impl de::Deserializer for JsonDeserializer { SyntaxError(EOFWhileParsingValue, 0, 0) } - fn syntax_error(&mut self, _token: de::Token, _expected: &[de::TokenKind]) -> ParserError { - SyntaxError(InvalidSyntax, 0, 0) + fn syntax_error(&mut self, token: de::Token, expected: &[de::TokenKind]) -> ParserError { + SyntaxError(DeserializerError(token, ExpectTokens(expected.to_vec())), 0, 0) } - fn unexpected_name_error(&mut self, _token: de::Token) -> ParserError { - SyntaxError(InvalidSyntax, 0, 0) + fn unexpected_name_error(&mut self, token: de::Token) -> ParserError { + SyntaxError(DeserializerError(token, ExpectName), 0, 0) } - fn conversion_error(&mut self, _token: de::Token) -> ParserError { - SyntaxError(InvalidSyntax, 0, 0) + fn conversion_error(&mut self, token: de::Token) -> ParserError { + SyntaxError(DeserializerError(token, ExpectConversion), 0, 0) } #[inline] @@ -735,9 +735,32 @@ impl de::Deserializer for JsonDeserializer { } } +/// The failed expectation of InvalidSyntax +#[deriving(Clone, PartialEq, Show)] +pub enum SyntaxExpectation { + ListCommaOrEnd, + ObjectCommaOrEnd, + SomeValue, + SomeIdent, + EnumMapStart, + EnumVariantString, + EnumToken, + EnumEndToken, + EnumEnd, +} + +/// JSON deserializer expectations +#[deriving(Clone, PartialEq, Show)] +pub enum DeserializerExpectation { + ExpectTokens(Vec), + ExpectName, + ExpectConversion, +} + /// The errors that can arise while parsing a JSON stream. #[deriving(Clone, PartialEq)] pub enum ErrorCode { + DeserializerError(de::Token, DeserializerExpectation), EOFWhileParsingList, EOFWhileParsingObject, EOFWhileParsingString, @@ -745,7 +768,7 @@ pub enum ErrorCode { ExpectedColon, InvalidEscape, InvalidNumber, - InvalidSyntax, + InvalidSyntax(SyntaxExpectation), InvalidUnicodeCodePoint, KeyMustBeAString, LoneLeadingSurrogateInHexEscape, @@ -784,6 +807,8 @@ pub enum DecoderError { impl fmt::Show for ErrorCode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { + DeserializerError(ref token, ref expect) => write!(f, + "deserializer found {} when {}", token, expect), EOFWhileParsingList => "EOF While parsing list".fmt(f), EOFWhileParsingObject => "EOF While parsing object".fmt(f), EOFWhileParsingString => "EOF While parsing string".fmt(f), @@ -791,7 +816,7 @@ impl fmt::Show for ErrorCode { ExpectedColon => "expected `:`".fmt(f), InvalidEscape => "invalid escape".fmt(f), InvalidNumber => "invalid number".fmt(f), - InvalidSyntax => "invalid syntax".fmt(f), + InvalidSyntax(expect) => write!(f, "invalid syntax, expected: {}", expect), InvalidUnicodeCodePoint => "invalid unicode code point".fmt(f), KeyMustBeAString => "key must be a string".fmt(f), LoneLeadingSurrogateInHexEscape => "lone leading surrogate in hex escape".fmt(f), @@ -1925,7 +1950,7 @@ impl> Parser { } else if self.eof() { self.error_event(EOFWhileParsingList) } else { - self.error_event(InvalidSyntax) + self.error_event(InvalidSyntax(ListCommaOrEnd)) } } @@ -1952,7 +1977,7 @@ impl> Parser { } else if self.eof() { self.error_event(EOFWhileParsingObject) } else { - self.error_event(InvalidSyntax) + self.error_event(InvalidSyntax(ObjectCommaOrEnd)) } } @@ -2015,7 +2040,7 @@ impl> Parser { Ok(de::MapStart(0)) } _ => { - self.error_event(InvalidSyntax) + self.error_event(InvalidSyntax(SomeValue)) } } } @@ -2025,7 +2050,7 @@ impl> Parser { self.bump(); Ok(token) } else { - self.error_event(InvalidSyntax) + self.error_event(InvalidSyntax(SomeIdent)) } } @@ -2040,16 +2065,16 @@ impl> de::Deserializer for Parser { SyntaxError(EOFWhileParsingValue, self.line, self.col) } - fn syntax_error(&mut self, _token: de::Token, _expected: &[de::TokenKind]) -> ParserError { - SyntaxError(InvalidSyntax, self.line, self.col) + fn syntax_error(&mut self, token: de::Token, expected: &[de::TokenKind]) -> ParserError { + SyntaxError(DeserializerError(token, ExpectTokens(expected.to_vec())), self.line, self.col) } - fn unexpected_name_error(&mut self, _token: de::Token) -> ParserError { - SyntaxError(InvalidSyntax, self.line, self.col) + fn unexpected_name_error(&mut self, token: de::Token) -> ParserError { + SyntaxError(DeserializerError(token, ExpectName), self.line, self.col) } - fn conversion_error(&mut self, _token: de::Token) -> ParserError { - SyntaxError(InvalidSyntax, self.line, self.col) + fn conversion_error(&mut self, token: de::Token) -> ParserError { + SyntaxError(DeserializerError(token, ExpectConversion), self.line, self.col) } #[inline] @@ -2083,19 +2108,19 @@ impl> de::Deserializer for Parser { variants: &[&str]) -> Result { match token { de::MapStart(_) => { } - _ => { return self.error(InvalidSyntax); } + _ => { return self.error(InvalidSyntax(EnumMapStart)); } }; // Enums only have one field in them, which is the variant name. let variant = match try!(self.expect_token()) { de::String(variant) => variant, - _ => { return self.error(InvalidSyntax); } + _ => { return self.error(InvalidSyntax(EnumVariantString)); } }; // The variant's field is a list of the values. match try!(self.expect_token()) { de::SeqStart(_) => { } - _ => { return self.error(InvalidSyntax); } + _ => { return self.error(InvalidSyntax(EnumToken)); } } match variants.iter().position(|v| *v == variant.as_slice()) { @@ -2110,10 +2135,10 @@ impl> de::Deserializer for Parser { de::End => { match try!(self.expect_token()) { de::End => Ok(()), - _ => self.error(InvalidSyntax), + _ => self.error(InvalidSyntax(EnumEndToken)), } } - _ => self.error(InvalidSyntax), + _ => self.error(InvalidSyntax(EnumEnd)), } } } @@ -2331,6 +2356,10 @@ mod tests { KeyMustBeAString, TrailingCharacters, SyntaxError, + SomeIdent, + SomeValue, + ObjectCommaOrEnd, + ListCommaOrEnd, }; use de; use ser::{Serializable, Serializer}; @@ -2800,8 +2829,8 @@ mod tests { #[test] fn test_parse_null() { test_parse_err::<()>([ - ("n", SyntaxError(InvalidSyntax, 1, 2)), - ("nul", SyntaxError(InvalidSyntax, 1, 4)), + ("n", SyntaxError(InvalidSyntax(SomeIdent), 1, 2)), + ("nul", SyntaxError(InvalidSyntax(SomeIdent), 1, 4)), ("nulla", SyntaxError(TrailingCharacters, 1, 5)), ]); @@ -2820,10 +2849,10 @@ mod tests { #[test] fn test_parse_bool() { test_parse_err::([ - ("t", SyntaxError(InvalidSyntax, 1, 2)), - ("truz", SyntaxError(InvalidSyntax, 1, 4)), - ("f", SyntaxError(InvalidSyntax, 1, 2)), - ("faz", SyntaxError(InvalidSyntax, 1, 3)), + ("t", SyntaxError(InvalidSyntax(SomeIdent), 1, 2)), + ("truz", SyntaxError(InvalidSyntax(SomeIdent), 1, 4)), + ("f", SyntaxError(InvalidSyntax(SomeIdent), 1, 2)), + ("faz", SyntaxError(InvalidSyntax(SomeIdent), 1, 3)), ("truea", SyntaxError(TrailingCharacters, 1, 5)), ("falsea", SyntaxError(TrailingCharacters, 1, 6)), ]); @@ -2845,8 +2874,8 @@ mod tests { #[test] fn test_parse_number_errors() { test_parse_err::([ - ("+", SyntaxError(InvalidSyntax, 1, 1)), - (".", SyntaxError(InvalidSyntax, 1, 1)), + ("+", SyntaxError(InvalidSyntax(SomeValue), 1, 1)), + (".", SyntaxError(InvalidSyntax(SomeValue), 1, 1)), ("-", SyntaxError(InvalidNumber, 1, 2)), ("00", SyntaxError(InvalidNumber, 1, 2)), ("1.", SyntaxError(InvalidNumber, 1, 3)), @@ -2934,8 +2963,8 @@ mod tests { ("[ ", SyntaxError(EOFWhileParsingValue, 1, 3)), ("[1", SyntaxError(EOFWhileParsingList, 1, 3)), ("[1,", SyntaxError(EOFWhileParsingValue, 1, 4)), - ("[1,]", SyntaxError(InvalidSyntax, 1, 4)), - ("[1 2]", SyntaxError(InvalidSyntax, 1, 4)), + ("[1,]", SyntaxError(InvalidSyntax(SomeValue), 1, 4)), + ("[1 2]", SyntaxError(InvalidSyntax(ListCommaOrEnd), 1, 4)), ("[]a", SyntaxError(TrailingCharacters, 1, 3)), ]); @@ -2999,7 +3028,7 @@ mod tests { ("{\"a\" 1", SyntaxError(ExpectedColon, 1, 6)), ("{\"a\":", SyntaxError(EOFWhileParsingValue, 1, 6)), ("{\"a\":1", SyntaxError(EOFWhileParsingObject, 1, 7)), - ("{\"a\":1 1", SyntaxError(InvalidSyntax, 1, 8)), + ("{\"a\":1 1", SyntaxError(InvalidSyntax(ObjectCommaOrEnd), 1, 8)), ("{\"a\":1,", SyntaxError(EOFWhileParsingString, 1, 8)), ("{}a", SyntaxError(TrailingCharacters, 1, 3)), ]);