Skip to content

Commit 2923f59

Browse files
authored
feat(toml): Add DeTable::parse_recoverable (#953)
I had considered naming this new method `parse` and the `Result` method `try_parse` but the `Result` method should be the default / go-to for people and so the shorter name that matches similar functions is a better choice. `recovery` felt odd. Having it after `parse`, instead of `recoverable_parse`, keeps the emphasis on the most important part. Fixes #371
2 parents ba7fe7f + 899301c commit 2923f59

File tree

132 files changed

+1291
-3
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

132 files changed

+1291
-3
lines changed

Cargo.lock

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/toml/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ toml-test-harness = { version = "1.3.2", features = ["snapshot"] }
6565
toml-test-data = "2.3.0"
6666
snapbox = "0.6.0"
6767
walkdir = "2.5.0"
68+
itertools = "0.14.0"
6869

6970
[[test]]
7071
name = "decoder_compliance"

crates/toml/src/de/detable.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use alloc::borrow::Cow;
22

33
use serde_spanned::Spanned;
44

5+
use crate::alloc_prelude::*;
56
use crate::de::DeString;
67
use crate::de::DeValue;
78
use crate::map::Map;
@@ -27,6 +28,14 @@ impl<'i> DeTable<'i> {
2728
}
2829
}
2930

31+
/// Parse a TOML document, with best effort recovery on error
32+
pub fn parse_recoverable(input: &'i str) -> (Spanned<Self>, Vec<crate::de::Error>) {
33+
let source = toml_parse::Source::new(input);
34+
let mut errors = crate::de::error::TomlSink::<Vec<_>>::new(source);
35+
let value = crate::de::parser::parse_document(source, &mut errors);
36+
(value, errors.into_inner())
37+
}
38+
3039
/// Ensure no data is borrowed
3140
pub fn make_owned(&mut self) {
3241
let borrowed = core::mem::take(self);

crates/toml/src/de/devalue.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ pub enum DeValue<'i> {
3434
}
3535

3636
impl<'i> DeValue<'i> {
37-
/// Parse a TOML document
37+
/// Parse a TOML value
3838
pub fn parse(input: &'i str) -> Result<Spanned<Self>, crate::de::Error> {
3939
let source = toml_parse::Source::new(input);
4040
let mut errors = crate::de::error::TomlSink::<Option<_>>::new(source);
@@ -46,6 +46,14 @@ impl<'i> DeValue<'i> {
4646
}
4747
}
4848

49+
/// Parse a TOML value, with best effort recovery on error
50+
pub fn parse_recoverable(input: &'i str) -> (Spanned<Self>, Vec<crate::de::Error>) {
51+
let source = toml_parse::Source::new(input);
52+
let mut errors = crate::de::error::TomlSink::<Vec<_>>::new(source);
53+
let value = crate::de::parser::parse_value(source, &mut errors);
54+
(value, errors.into_inner())
55+
}
56+
4957
/// Ensure no data is borrowed
5058
pub fn make_owned(&mut self) {
5159
match self {

crates/toml/tests/decoder.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,17 @@ impl toml_test_harness::Decoder for Decoder {
1313
&self,
1414
data: &[u8],
1515
) -> Result<toml_test_harness::DecodedValue, toml_test_harness::Error> {
16+
use itertools::Itertools as _;
17+
use serde::de::Deserialize as _;
18+
1619
let data = std::str::from_utf8(data).map_err(toml_test_harness::Error::new)?;
17-
let document = data
18-
.parse::<toml::Table>()
20+
let (table, errors) = toml::de::DeTable::parse_recoverable(data);
21+
if !errors.is_empty() {
22+
let errors = errors.into_iter().join("\n---\n");
23+
let error = toml_test_harness::Error::new(errors);
24+
return Err(error);
25+
}
26+
let document = toml::Table::deserialize(toml::de::Deserializer::from(table))
1927
.map_err(toml_test_harness::Error::new)?;
2028
let value = toml::Value::Table(document);
2129
value_to_decoded(&value)

crates/toml/tests/snapshots/invalid/array/extending-table.stderr

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,10 @@ TOML parse error at line 5, column 2
33
5 | [a.c]
44
| ^
55
cannot extend value of type array with a dotted key
6+
7+
---
8+
TOML parse error at line 5, column 2
9+
|
10+
5 | [a.c]
11+
| ^
12+
cannot extend value of type array with a dotted key

crates/toml/tests/snapshots/invalid/array/missing-separator-02.stderr

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,10 @@ TOML parse error at line 1, column 15
33
1 | wrong = [ 1 2 3 ]
44
| ^
55
missing comma between array elements, expected `,`
6+
7+
---
8+
TOML parse error at line 1, column 11
9+
|
10+
1 | wrong = [ 1 2 3 ]
11+
| ^^^
12+
string values must be quoted, expected literal string

crates/toml/tests/snapshots/invalid/array/no-close-04.stderr

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,17 @@ TOML parse error at line 1, column 25
33
1 | no-close-4 = [{ key = 42
44
| ^
55
newlines are unsupported in inline tables, expected nothing
6+
7+
---
8+
TOML parse error at line 1, column 26
9+
|
10+
1 | no-close-4 = [{ key = 42
11+
| ^
12+
unclosed inline table, expected `}`
13+
14+
---
15+
TOML parse error at line 1, column 25
16+
|
17+
1 | no-close-4 = [{ key = 42
18+
| ^
19+
unclosed array, expected `]`

crates/toml/tests/snapshots/invalid/array/no-close-06.stderr

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,17 @@ TOML parse error at line 1, column 26
33
1 | no-close-6 = [{ key = 42 #}]
44
| ^^^
55
comments are unsupported in inline tables, expected nothing
6+
7+
---
8+
TOML parse error at line 1, column 30
9+
|
10+
1 | no-close-6 = [{ key = 42 #}]
11+
| ^
12+
unclosed inline table, expected `}`
13+
14+
---
15+
TOML parse error at line 1, column 25
16+
|
17+
1 | no-close-6 = [{ key = 42 #}]
18+
| ^
19+
unclosed array, expected `]`

crates/toml/tests/snapshots/invalid/array/no-close-4.stderr

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,17 @@ TOML parse error at line 1, column 25
33
1 | no-close-4 = [{ key = 42
44
| ^
55
newlines are unsupported in inline tables, expected nothing
6+
7+
---
8+
TOML parse error at line 1, column 26
9+
|
10+
1 | no-close-4 = [{ key = 42
11+
| ^
12+
unclosed inline table, expected `}`
13+
14+
---
15+
TOML parse error at line 1, column 25
16+
|
17+
1 | no-close-4 = [{ key = 42
18+
| ^
19+
unclosed array, expected `]`

0 commit comments

Comments
 (0)