From 6de25e7cc83795bbab2b5a19bf94ec4514f7ad8e Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Thu, 30 Jan 2020 23:35:15 -0700 Subject: [PATCH] Allow empty table keys Quoting https://github.com/toml-lang/toml/tree/68076ffc6d9a150d48f1df964551283542ad47bc#user-content-keys > A bare key must be non-empty, but an empty quoted key is allowed (though discouraged). See also the discussion in https://github.com/toml-lang/toml/issues/432 --- src/de.rs | 1 - src/ser.rs | 9 +++++---- src/tokens.rs | 4 ---- test-suite/tests/invalid-misc.rs | 2 +- test-suite/tests/parser.rs | 8 ++++---- test-suite/tests/valid.rs | 5 +++++ test-suite/tests/valid/key-empty.json | 3 +++ test-suite/tests/valid/key-empty.toml | 1 + 8 files changed, 19 insertions(+), 14 deletions(-) create mode 100644 test-suite/tests/valid/key-empty.json create mode 100644 test-suite/tests/valid/key-empty.toml diff --git a/src/de.rs b/src/de.rs index 98b3a60..2c6e49a 100644 --- a/src/de.rs +++ b/src/de.rs @@ -1978,7 +1978,6 @@ impl<'a> Deserializer<'a> { expected, found, } => self.error(at, ErrorKind::Wanted { expected, found }), - TokenError::EmptyTableKey(at) => self.error(at, ErrorKind::EmptyTableKey), TokenError::MultilineStringKey(at) => self.error(at, ErrorKind::MultilineStringKey), } } diff --git a/src/ser.rs b/src/ser.rs index 90cfcd7..017903b 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -509,10 +509,11 @@ impl<'a> Serializer<'a> { } fn escape_key(&mut self, key: &str) -> Result<(), Error> { - let ok = key.chars().all(|c| match c { - 'a'..='z' | 'A'..='Z' | '0'..='9' | '-' | '_' => true, - _ => false, - }); + let ok = key.len() > 0 + && key.chars().all(|c| match c { + 'a'..='z' | 'A'..='Z' | '0'..='9' | '-' | '_' => true, + _ => false, + }); if ok { write!(self.dst, "{}", key).map_err(ser::Error::custom)?; } else { diff --git a/src/tokens.rs b/src/tokens.rs index 49265fb..5553b07 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -56,7 +56,6 @@ pub enum Error { UnterminatedString(usize), NewlineInTableKey(usize), MultilineStringKey(usize), - EmptyTableKey(usize), Wanted { at: usize, expected: &'static str, @@ -194,9 +193,6 @@ impl<'a> Tokenizer<'a> { if multiline { return Err(Error::MultilineStringKey(offset)); } - if val == "" { - return Err(Error::EmptyTableKey(offset)); - } match src.find('\n') { None => Ok((span, val)), Some(i) => Err(Error::NewlineInTableKey(offset + i)), diff --git a/test-suite/tests/invalid-misc.rs b/test-suite/tests/invalid-misc.rs index cea0801..7a10192 100644 --- a/test-suite/tests/invalid-misc.rs +++ b/test-suite/tests/invalid-misc.rs @@ -14,7 +14,7 @@ fn bad() { bad!("a = 01", "invalid number at line 1 column 6"); bad!("a = 1__1", "invalid number at line 1 column 5"); bad!("a = 1_", "invalid number at line 1 column 5"); - bad!("''", "empty table key found at line 1 column 1"); + bad!("''", "expected an equals, found eof at line 1 column 3"); bad!("a = 9e99999", "invalid number at line 1 column 5"); bad!( diff --git a/test-suite/tests/parser.rs b/test-suite/tests/parser.rs index eab9f5a..70d418e 100644 --- a/test-suite/tests/parser.rs +++ b/test-suite/tests/parser.rs @@ -342,12 +342,14 @@ fn bad_keys() { "key|=3", "unexpected character found: `|` at line 1 column 4" ); - bad!("\"\"=3", "empty table key found at line 1 column 1"); bad!( "=3", "expected a table key, found an equals at line 1 column 1" ); - bad!("\"\"|=3", "empty table key found at line 1 column 1"); + bad!( + "\"\"|=3", + "unexpected character found: `|` at line 1 column 3" + ); bad!("\"\n\"|=3", "newline in string found at line 1 column 2"); bad!( "\"\r\"|=3", @@ -381,12 +383,10 @@ fn bad_table_names() { "[.]", "expected a table key, found a period at line 1 column 2" ); - bad!("[\"\".\"\"]", "empty table key found at line 1 column 2"); bad!( "[a.]", "expected a table key, found a right bracket at line 1 column 4" ); - bad!("[\"\"]", "empty table key found at line 1 column 2"); bad!("[!]", "unexpected character found: `!` at line 1 column 2"); bad!("[\"\n\"]", "newline in string found at line 1 column 3"); bad!( diff --git a/test-suite/tests/valid.rs b/test-suite/tests/valid.rs index 0bb7caa..9729063 100644 --- a/test-suite/tests/valid.rs +++ b/test-suite/tests/valid.rs @@ -231,6 +231,11 @@ test!( include_str!("valid/key-with-pound.toml"), include_str!("valid/key-with-pound.json") ); +test!( + key_empty, + include_str!("valid/key-empty.toml"), + include_str!("valid/key-empty.json") +); test!( long_float, include_str!("valid/long-float.toml"), diff --git a/test-suite/tests/valid/key-empty.json b/test-suite/tests/valid/key-empty.json new file mode 100644 index 0000000..99afee4 --- /dev/null +++ b/test-suite/tests/valid/key-empty.json @@ -0,0 +1,3 @@ +{ + "": {"type": "integer", "value": "1"} +} diff --git a/test-suite/tests/valid/key-empty.toml b/test-suite/tests/valid/key-empty.toml new file mode 100644 index 0000000..2f6a07c --- /dev/null +++ b/test-suite/tests/valid/key-empty.toml @@ -0,0 +1 @@ +"" = 1