toml: comply with BurntSushi @eb989e5 (#12616)

pull/12618/head
Larpon 2021-11-29 21:15:22 +01:00 committed by GitHub
parent 83260e5074
commit 14424100e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 47 additions and 11 deletions

View File

@ -14,7 +14,7 @@ jobs:
timeout-minutes: 10
env:
TOML_BS_TESTS_PATH: vlib/toml/tests/testdata/burntsushi/toml-test
TOML_BS_TESTS_PINNED_COMMIT: 8baf830
TOML_BS_TESTS_PINNED_COMMIT: eb989e5
TOML_IARNA_TESTS_PATH: vlib/toml/tests/testdata/iarna/toml-test
TOML_IARNA_TESTS_PINNED_COMMIT: 1880b1a
steps:

View File

@ -356,7 +356,23 @@ fn (c Checker) check_date(date ast.Date) ? {
fn (c Checker) check_time(t ast.Time) ? {
lit := t.text
// Split any offsets from the time
parts := lit.split('-')
mut offset_splitter := if lit.contains('+') { '+' } else { '-' }
parts := lit.split(offset_splitter)
mut hhmmss := parts[0].all_before('.')
// Check for 2 digits in all fields
mut check_length := 8
if hhmmss.to_upper().ends_with('Z') {
check_length++
}
if hhmmss.len != check_length {
starts_with_zero := hhmmss.starts_with('0')
if !starts_with_zero {
return error(@MOD + '.' + @STRUCT + '.' + @FN +
' "$lit" must be zero prefixed in ...${c.excerpt(t.pos)}...')
}
return error(@MOD + '.' + @STRUCT + '.' + @FN +
' "$lit" is not a valid RFC 3339 Time format string in ...${c.excerpt(t.pos)}...')
}
// Use V's builtin functionality to validate the time string
time.parse_rfc3339(parts[0]) or {
return error(@MOD + '.' + @STRUCT + '.' + @FN +
@ -397,6 +413,7 @@ fn (c Checker) check_quoted_escapes(q ast.Quoted) ? {
// See https://toml.io/en/v1.0.0#string for more info on string types.
is_basic := q.quote == `\"`
contains_newlines := q.text.contains('\n')
for {
ch := s.next()
if ch == scanner.end_of_text {
@ -414,10 +431,17 @@ fn (c Checker) check_quoted_escapes(q ast.Quoted) ? {
escape := ch_byte.ascii_str() + next_ch.ascii_str()
if is_basic {
if q.is_multiline {
if next_ch == byte(32) && s.peek(1) == byte(92) {
st := s.state()
return error(@MOD + '.' + @STRUCT + '.' + @FN +
' can not escape whitespaces before escapes in multi-line strings (`\\ \\`) at `$escape` ($st.line_nr,$st.col) in ...${c.excerpt(q.pos)}...')
if next_ch == byte(32) {
if s.peek(1) == byte(92) {
st := s.state()
return error(@MOD + '.' + @STRUCT + '.' + @FN +
' can not escape whitespaces before escapes in multi-line strings (`\\ \\`) at `$escape` ($st.line_nr,$st.col) in ...${c.excerpt(q.pos)}...')
}
if !contains_newlines {
st := s.state()
return error(@MOD + '.' + @STRUCT + '.' + @FN +
' can not escape whitespaces in multi-line strings (`\\ `) at `$escape` ($st.line_nr,$st.col) in ...${c.excerpt(q.pos)}...')
}
}
if next_ch in [`\t`, `\n`, ` `] {
s.next()
@ -518,10 +542,16 @@ pub fn (c Checker) check_comment(comment ast.Comment) ? {
mut s := scanner.new_simple(lit) ?
for {
ch := s.next()
if ch == -1 {
if ch == scanner.end_of_text {
break
}
ch_byte := byte(ch)
// Check for carrige return
if ch_byte == 0x0D {
st := s.state()
return error(@MOD + '.' + @STRUCT + '.' + @FN +
' carrige return character `$ch_byte.hex()` is not allowed ($st.line_nr,$st.col) "${byte(s.at()).ascii_str()}" near ...${s.excerpt(st.pos, 10)}...')
}
// Check for control characters (allow TAB)
if util.is_illegal_ascii_control_character(ch_byte) {
st := s.state()

View File

@ -252,7 +252,7 @@ fn (d Decoder) decode_date_time(mut dt ast.DateTime) ? {
if ms.len > 1 {
return
}
ms = ms + '0'.repeat(6 - ms.len) + z
ms = ms + '0'.repeat(4 - ms.len) + z
dt.text = yymmddhhmmss + '.' + ms + offset
}
}

View File

@ -93,6 +93,12 @@ pub fn (mut s Scanner) scan() ?token.Token {
ascii := byte_c.ascii_str()
util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'current char "$ascii"')
if byte_c == byte(0x0) {
s.reset()
return error(@MOD + '.' + @STRUCT + '.' + @FN +
' NULL control character `$c.hex()` is not allowed at ($s.line_nr,$s.col) "$ascii" near ...${s.excerpt(s.pos, 5)}...')
}
is_sign := c == `+` || c == `-`
// (+/-)nan & (+/-)inf
@ -340,7 +346,7 @@ fn (mut s Scanner) ignore_line() ?string {
util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'skipping "${byte(c).ascii_str()} / $c"')
if s.at_crlf() {
util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'letting `\\r\\n` slip through')
return s.text[start..s.pos]
return s.text[start..s.pos + 1]
}
}
return s.text[start..s.pos]

View File

@ -2,8 +2,8 @@ import toml
fn test_crlf() {
str_value := 'test string'
mut toml_txt := 'crlf_string = "test string"
# Comment with CRLF\r\n'
mut toml_txt := 'crlf_string = "test string"\r\n
# Comment with CRLF is not allowed'
toml_doc := toml.parse(toml_txt) or { panic(err) }
value := toml_doc.value('crlf_string')