Skip to content

Commit 1925fab

Browse files
committed
support TOML 1.1
1 parent 5748812 commit 1925fab

File tree

3 files changed

+82
-7
lines changed

3 files changed

+82
-7
lines changed

integ-tests/tests/parser.rs

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,10 +140,9 @@ invalid!(eof, "key =");
140140
mod bad_inline_tables {
141141
use super::invalid;
142142

143-
invalid!(trailing_comma, "a = {a=1,}");
143+
// TOML 1.1: trailing_comma and newline are now valid, so removed from invalid tests
144144
invalid!(only_comma, "a = {,}");
145145
invalid!(duplicate_key, "a = {a=1,a=1}");
146-
invalid!(newline, "a = {\n}");
147146
invalid!(eof, "a = {");
148147
}
149148

@@ -307,3 +306,58 @@ mod require_newlines {
307306
invalid!(basic2, "0=0r0=0r=false");
308307
invalid!(basic3, "0=0r0=0r=falsefal=false");
309308
}
309+
310+
// TOML 1.1 features
311+
mod toml_1_1 {
312+
use super::valid;
313+
314+
// Inline tables can now have newlines
315+
valid!(
316+
inline_table_newlines,
317+
r#"
318+
tbl = {
319+
key = "value",
320+
nested = {
321+
inner = 42,
322+
},
323+
}
324+
"#
325+
);
326+
327+
// Trailing commas in inline tables
328+
valid!(inline_table_trailing_comma, "a = {a=1,}");
329+
330+
// Empty inline table with newlines
331+
valid!(inline_table_empty_newlines, "a = {\n}");
332+
333+
// \e escape sequence (escape character U+001B)
334+
valid!(escape_e, r#"csi = "\e[""#);
335+
336+
// \xHH escape sequence for codepoints < 255
337+
valid!(
338+
escape_x,
339+
r#"
340+
null = "\x00"
341+
letter = "\x61"
342+
"#
343+
);
344+
345+
// Combined escape sequences
346+
valid!(
347+
escape_combined,
348+
r#"test = "\x00\x1b\e\x61\u0041\U00000042""#
349+
);
350+
351+
// Complex inline table with comments
352+
valid!(
353+
inline_table_with_comments,
354+
r#"
355+
tbl = {
356+
# This is a comment
357+
key = "value",
358+
# Another comment
359+
num = 123,
360+
}
361+
"#
362+
);
363+
}

toml-span/src/de.rs

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -776,24 +776,40 @@ impl<'a> Deserializer<'a> {
776776
// great to defer parsing everything until later.
777777
fn inline_table(&mut self) -> Result<(Span, TableValues<'a>), Error> {
778778
let mut ret = TableValues::default();
779-
self.eat_whitespace();
779+
780+
// TOML 1.1: inline tables can span multiple lines and have trailing commas
781+
let intermediate = |me: &mut Deserializer<'_>| -> Result<(), Error> {
782+
loop {
783+
me.eat_whitespace();
784+
if !me.eat(Token::Newline)? && !me.eat_comment()? {
785+
break;
786+
}
787+
}
788+
Ok(())
789+
};
790+
791+
intermediate(self)?;
780792
if let Some(span) = self.eat_spanned(Token::RightBrace)? {
781793
return Ok((span, ret));
782794
}
783795
loop {
784796
let key = self.dotted_key()?;
785-
self.eat_whitespace();
797+
intermediate(self)?;
786798
self.expect(Token::Equals)?;
787-
self.eat_whitespace();
799+
intermediate(self)?;
788800
let value = self.value()?;
789801
self.add_dotted_key(key, value, &mut ret)?;
790802

791-
self.eat_whitespace();
803+
intermediate(self)?;
792804
if let Some(span) = self.eat_spanned(Token::RightBrace)? {
793805
return Ok((span, ret));
794806
}
795807
self.expect(Token::Comma)?;
796-
self.eat_whitespace();
808+
intermediate(self)?;
809+
// TOML 1.1: trailing comma is allowed
810+
if let Some(span) = self.eat_spanned(Token::RightBrace)? {
811+
return Ok((span, ret));
812+
}
797813
}
798814
}
799815

toml-span/src/tokens.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@ impl<'a> Tokenizer<'a> {
384384
Some((_, 'n')) => val.push('\n'),
385385
Some((_, 'r')) => val.push('\r'),
386386
Some((_, 't')) => val.push('\t'),
387+
Some((_, 'e')) => val.push('\u{1b}'), // TOML 1.1: escape character
387388
Some((i, c @ ('u' | 'U'))) => {
388389
let c = if c == 'u' {
389390
me.hex::<4>(start, i)
@@ -392,6 +393,10 @@ impl<'a> Tokenizer<'a> {
392393
};
393394
val.push(c?);
394395
}
396+
Some((i, 'x')) => {
397+
// TOML 1.1: \xHH for codepoints < 255
398+
val.push(me.hex::<2>(start, i)?);
399+
}
395400
Some((i, c @ (' ' | '\t' | '\n'))) if multi => {
396401
if c != '\n' {
397402
while let Some((_, ch)) = me.chars.clone().next() {

0 commit comments

Comments
 (0)