Improve error message when parsing unquoted string (#385)

* Improve error message when parsing unquoted string

* Remove conversion to lowercase in parse_keylike()

Converting keys to lowercase goes against
TOML specification for floats.

* Change error message for unquoted string
master
Alex Tokarev 2020-10-11 20:30:55 +03:00 committed by GitHub
parent 940fcf9e18
commit c74293f7a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 41 additions and 13 deletions

View File

@ -191,6 +191,9 @@ enum ErrorKind {
available: &'static [&'static str],
},
/// Unquoted string was found when quoted one was expected
UnquotedString,
#[doc(hidden)]
__Nonexhaustive,
}
@ -1428,7 +1431,7 @@ impl<'a> Deserializer<'a> {
start,
end,
},
Some((span, Token::Keylike(key))) => self.number_or_date(span, key)?,
Some((span, Token::Keylike(key))) => self.parse_keylike(at, span, key)?,
Some((span, Token::Plus)) => self.number_leading_plus(span)?,
Some((Span { start, .. }, Token::LeftBrace)) => {
self.inline_table().map(|(Span { end, .. }, table)| Value {
@ -1451,13 +1454,25 @@ impl<'a> Deserializer<'a> {
expected: "a value",
found: token.1.describe(),
},
))
));
}
None => return Err(self.eof()),
};
Ok(value)
}
fn parse_keylike(&mut self, at: usize, span: Span, key: &'a str) -> Result<Value<'a>, Error> {
if key == "inf" || key == "nan" {
return self.number_or_date(span, key);
}
let first_char = key.chars().next().expect("key should not be empty here");
match first_char {
'-' | '0'..='9' => self.number_or_date(span, key),
_ => Err(self.error(at, ErrorKind::UnquotedString)),
}
}
fn number_or_date(&mut self, span: Span, s: &'a str) -> Result<Value<'a>, Error> {
if s.contains('T')
|| s.contains('t')
@ -2076,7 +2091,7 @@ impl std::convert::From<Error> for std::io::Error {
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.inner.kind {
match &self.inner.kind {
ErrorKind::UnexpectedEof => "unexpected eof encountered".fmt(f)?,
ErrorKind::InvalidCharInString(c) => write!(
f,
@ -2131,6 +2146,10 @@ impl fmt::Display for Error {
"unexpected keys in table: `{:?}`, available keys: `{:?}`",
keys, available
)?,
ErrorKind::UnquotedString => write!(
f,
"invalid TOML value, did you mean to use a quoted string?"
)?,
ErrorKind::__Nonexhaustive => panic!(),
}

View File

@ -68,15 +68,15 @@ fn bad_times() {
);
bad!(
"foo = T",
"failed to parse datetime for key `foo` at line 1 column 7"
"invalid TOML value, did you mean to use a quoted string? at line 1 column 7"
);
bad!(
"foo = T.",
"expected newline, found a period at line 1 column 8"
"invalid TOML value, did you mean to use a quoted string? at line 1 column 7"
);
bad!(
"foo = TZ",
"failed to parse datetime for key `foo` at line 1 column 7"
"invalid TOML value, did you mean to use a quoted string? at line 1 column 7"
);
bad!(
"foo = 1997-09-09T09:09:09.09+",

View File

@ -197,7 +197,7 @@ test!(
test!(
text_after_array_entries,
include_str!("invalid/text-after-array-entries.toml"),
"invalid number at line 2 column 46"
"invalid TOML value, did you mean to use a quoted string? at line 2 column 46"
);
test!(
text_after_integer,
@ -222,5 +222,5 @@ test!(
test!(
text_in_array,
include_str!("invalid/text-in-array.toml"),
"invalid number at line 3 column 3"
"invalid TOML value, did you mean to use a quoted string? at line 3 column 3"
);

View File

@ -491,7 +491,10 @@ fn number_underscores() {
fn bad_underscores() {
bad!("foo = 0_", "invalid number at line 1 column 7");
bad!("foo = 0__0", "invalid number at line 1 column 7");
bad!("foo = __0", "invalid number at line 1 column 7");
bad!(
"foo = __0",
"invalid TOML value, did you mean to use a quoted string? at line 1 column 7"
);
bad!("foo = 1_0_", "invalid number at line 1 column 7");
}
@ -537,14 +540,20 @@ fn booleans() {
bad!(
"foo = true2",
"failed to parse datetime for key `foo` at line 1 column 7"
"invalid TOML value, did you mean to use a quoted string? at line 1 column 7"
);
bad!(
"foo = false2",
"invalid TOML value, did you mean to use a quoted string? at line 1 column 7"
);
bad!("foo = false2", "invalid number at line 1 column 7");
bad!(
"foo = t1",
"failed to parse datetime for key `foo` at line 1 column 7"
"invalid TOML value, did you mean to use a quoted string? at line 1 column 7"
);
bad!(
"foo = f2",
"invalid TOML value, did you mean to use a quoted string? at line 1 column 7"
);
bad!("foo = f2", "invalid number at line 1 column 7");
}
#[test]