Skip to content

Commit

Permalink
Merge pull request #617 from epage/update
Browse files Browse the repository at this point in the history
fix(parser): Failed on mixed inline tables
  • Loading branch information
epage authored Oct 3, 2023
2 parents c9b481c + 7eaf286 commit 4b44f53
Show file tree
Hide file tree
Showing 20 changed files with 122 additions and 39 deletions.
13 changes: 7 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion crates/toml/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ serde_spanned = { version = "0.6.3", path = "../serde_spanned", features = ["ser
[dev-dependencies]
serde = { version = "1.0.160", features = ["derive"] }
serde_json = "1.0.96"
toml-test-harness = "0.4.3"
toml-test-harness = "0.4.5"
toml-test-data = "1.3.1"
snapbox = "0.4.11"

[[test]]
Expand Down
12 changes: 2 additions & 10 deletions crates/toml/tests/decoder_compliance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,8 @@ mod decoder;
fn main() {
let decoder = decoder::Decoder;
let mut harness = toml_test_harness::DecoderHarness::new(decoder);
harness
.ignore([
"valid/spec/float-0.toml",
// Unreleased
"valid/string/escape-esc.toml",
"valid/string/hex-escape.toml",
"valid/datetime/no-seconds.toml",
"valid/inline-table/newline.toml",
])
.unwrap();
harness.ignore(["valid/spec/float-0.toml"]).unwrap();
harness.version("1.0.0");
harness.test();
}

Expand Down
1 change: 1 addition & 0 deletions crates/toml/tests/encoder_compliance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ fn main() {
let decoder = decoder::Decoder;
let mut harness = toml_test_harness::EncoderHarness::new(encoder, decoder);
harness.ignore(["valid/spec/float-0.toml"]).unwrap();
harness.version("1.0.0");
harness.test();
}

Expand Down
4 changes: 2 additions & 2 deletions crates/toml_edit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ serde_spanned = { version = "0.6.3", path = "../serde_spanned", features = ["ser

[dev-dependencies]
serde_json = "1.0.96"
toml-test-harness = "0.4.3"
toml-test-data = "1.3.0"
toml-test-harness = "0.4.5"
toml-test-data = "1.3.1"
libtest-mimic = "0.6.0"
snapbox = { version = "0.4.11", features = ["harness"] }

Expand Down
28 changes: 28 additions & 0 deletions crates/toml_edit/src/inline_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ use crate::{InternalString, Item, KeyMut, RawString, Table, Value};
pub struct InlineTable {
// `preamble` represents whitespaces in an empty table
preamble: RawString,
// Whether to hide an empty table
pub(crate) implicit: bool,
// prefix before `{` and suffix after `}`
decor: Decor,
pub(crate) span: Option<std::ops::Range<usize>>,
Expand Down Expand Up @@ -133,6 +135,32 @@ impl InlineTable {
}
}

/// If a table has no key/value pairs and implicit, it will not be displayed.
///
/// # Examples
///
/// ```notrust
/// [target."x86_64/windows.json".dependencies]
/// ```
///
/// In the document above, tables `target` and `target."x86_64/windows.json"` are implicit.
///
/// ```
/// use toml_edit::Document;
/// let mut doc = "[a]\n[a.b]\n".parse::<Document>().expect("invalid toml");
///
/// doc["a"].as_table_mut().unwrap().set_implicit(true);
/// assert_eq!(doc.to_string(), "[a.b]\n");
/// ```
pub(crate) fn set_implicit(&mut self, implicit: bool) {
self.implicit = implicit;
}

/// If a table has no key/value pairs and implicit, it will not be displayed.
pub(crate) fn is_implicit(&self) -> bool {
self.implicit
}

/// Change this table's dotted status
pub fn set_dotted(&mut self, yes: bool) {
self.dotted = yes;
Expand Down
23 changes: 22 additions & 1 deletion crates/toml_edit/src/parser/inline_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@ fn table_from_pairs(

for (path, kv) in v {
let table = descend_path(&mut root, &path)?;

// "Likewise, using dotted keys to redefine tables already defined in [table] form is not allowed"
let mixed_table_types = table.is_dotted() == path.is_empty();
if mixed_table_types {
return Err(CustomError::DuplicateKey {
key: kv.key.get().into(),
table: None,
});
}

let key: InternalString = kv.key.get_internal().into();
match table.items.entry(key) {
Entry::Vacant(o) => {
Expand All @@ -64,15 +74,26 @@ fn descend_path<'a>(
mut table: &'a mut InlineTable,
path: &'a [Key],
) -> Result<&'a mut InlineTable, CustomError> {
let dotted = !path.is_empty();
for (i, key) in path.iter().enumerate() {
let entry = table.entry_format(key).or_insert_with(|| {
let mut new_table = InlineTable::new();
new_table.set_dotted(true);
new_table.set_implicit(dotted);
new_table.set_dotted(dotted);

Value::InlineTable(new_table)
});
match *entry {
Value::InlineTable(ref mut sweet_child_of_mine) => {
// Since tables cannot be defined more than once, redefining such tables using a
// [table] header is not allowed. Likewise, using dotted keys to redefine tables
// already defined in [table] form is not allowed.
if dotted && !sweet_child_of_mine.is_implicit() {
return Err(CustomError::DuplicateKey {
key: key.get().into(),
table: None,
});
}
table = sweet_child_of_mine;
}
ref v => {
Expand Down
12 changes: 2 additions & 10 deletions crates/toml_edit/tests/decoder_compliance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,7 @@ mod decoder;
fn main() {
let decoder = decoder::Decoder;
let mut harness = toml_test_harness::DecoderHarness::new(decoder);
harness
.ignore([
"valid/spec/float-0.toml", // Test issue; `Decoder` turns `6.626e-34` into `0.0`
// Unreleased
"valid/string/escape-esc.toml",
"valid/string/hex-escape.toml",
"valid/datetime/no-seconds.toml",
"valid/inline-table/newline.toml",
])
.unwrap();
harness.ignore(["valid/spec/float-0.toml"]).unwrap();
harness.version("1.0.0");
harness.test();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
invalid utf-8 sequence of 1 bytes from index 29
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
TOML parse error at line 1, column 21
TOML parse error at line 1, column 24
|
1 | exp-trailing-us = 1e_23_
| ^
1 | exp-trailing-us = 1e23_
| ^
invalid floating-point number
expected digit
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
TOML parse error at line 1, column 5
|
1 | v = Inf
| ^
invalid string
expected `"`, `'`
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
TOML parse error at line 1, column 5
|
1 | v = NaN
| ^
invalid string
expected `"`, `'`
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
TOML parse error at line 1, column 23
|
1 | trailing-us-exp-1 = 1_e2
| ^
invalid integer
expected digit
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
TOML parse error at line 1, column 25
|
1 | trailing-us-exp-2 = 1.2_e2
| ^
invalid floating-point number
expected digit, digit

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
TOML parse error at line 1, column 14
|
1 | tbl = { a = 1, [b] }
| ^
invalid inline table
expected `}`
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
TOML parse error at line 1, column 8
|
1 | tbl = { a.b = "a_b", a.b.c = "a_b_c" }
| ^
dotted key `a.b` attempted to extend non-table type (string)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
TOML parse error at line 1, column 8
|
1 | tbl = { fruit = { apple.color = "red" }, fruit.apple.texture = { smooth = true } }
| ^
duplicate key `fruit`
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
TOML parse error at line 4, column 1
|
4 | b.y = 2
| ^
duplicate key `y`
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
TOML parse error at line 4, column 1
|
4 | [[fruit.apple]]
| ^
invalid table header
duplicate key `apple` in table `fruit`

0 comments on commit 4b44f53

Please sign in to comment.