Skip to content

Commit

Permalink
Merge pull request #379 from BurntSushi/uni-keys
Browse files Browse the repository at this point in the history
Support unicode bare keys
  • Loading branch information
arp242 committed Jan 21, 2023
2 parents d73da82 + f7d4e0a commit 7edfd73
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 33 deletions.
18 changes: 18 additions & 0 deletions internal/toml-test/tests/valid/key/unicode.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"a‍b": {
"type": "string",
"value": "zwj"
},
"ÅÅ": {
"type": "string",
"value": "U+00C5 U+0041 U+030A"
},
"€": {
"type": "string",
"value": "Euro"
},
"😂": {
"type": "string",
"value": "rofl"
}
}
6 changes: 6 additions & 0 deletions internal/toml-test/tests/valid/key/unicode.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# TOML 1.1 supports Unicode for bare keys.

€ = 'Euro'
😂 = "rofl"
a‍b = "zwj"
ÅÅ = "U+00C5 U+0041 U+030A"
32 changes: 2 additions & 30 deletions internal/toml-test/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ var versions = map[string]versionSpec{
"invalid/inline-table/linebreak-2",
"invalid/inline-table/linebreak-3",
"invalid/inline-table/linebreak-4",
"invalid/key/special-character", // Unicode can now be in bare keys.
},
},

Expand All @@ -27,36 +28,7 @@ var versions = map[string]versionSpec{
"valid/string/hex-escape", "invalid/string/bad-hex-esc", // \x..
"valid/datetime/no-seconds", // Times without seconds
"valid/inline-table/newline",
},
},

// Added in 1.0.0:
// Leading zeroes in exponent parts of floats are permitted.
// Allow raw tab characters in basic strings and multi-line basic strings.
// Allow heterogenous values in arrays.
"0.5.0": versionSpec{
inherit: "1.0.0",
exclude: []string{
"valid/hetergeneous",
"valid/array/mixed-*",
},
},

// Added in 0.5.0:
// Add dotted keys.
// Add hex, octal, and binary integer formats.
// Add special float values (inf, nan)
// Add Local Date-Time.
// Add Local Date.
// Add Local Time.
// Allow space (instead of T) to separate date and time in Date-Time.
// Allow accidental whitespace between backslash and newline in the line
// continuation operator in multi-line basic strings.
"0.4.0": versionSpec{
inherit: "0.5.0",
exclude: []string{
"valid/datetime/local*",
"valid/key/dotted",
"valid/key/unicode", // Unicode bare keys
},
},
}
16 changes: 16 additions & 0 deletions lex.go
Original file line number Diff line number Diff line change
Expand Up @@ -1257,7 +1257,23 @@ func isOctal(r rune) bool { return r >= '0' && r <= '7' }
func isHexadecimal(r rune) bool {
return (r >= '0' && r <= '9') || (r >= 'a' && r <= 'f') || (r >= 'A' && r <= 'F')
}

func isBareKeyChar(r rune) bool {
if tomlNext {
return (r >= 'A' && r <= 'Z') ||
(r >= 'a' && r <= 'z') ||
(r >= '0' && r <= '9') ||
r == '_' || r == '-' ||
r == 0xb2 || r == 0xb3 || r == 0xb9 || (r >= 0xbc && r <= 0xbe) ||
(r >= 0xc0 && r <= 0xd6) || (r >= 0xd8 && r <= 0xf6) || (r >= 0xf8 && r <= 0x037d) ||
(r >= 0x037f && r <= 0x1fff) ||
(r >= 0x200c && r <= 0x200d) || (r >= 0x203f && r <= 0x2040) ||
(r >= 0x2070 && r <= 0x218f) || (r >= 0x2460 && r <= 0x24ff) ||
(r >= 0x2c00 && r <= 0x2fef) || (r >= 0x3001 && r <= 0xd7ff) ||
(r >= 0xf900 && r <= 0xfdcf) || (r >= 0xfdf0 && r <= 0xfffd) ||
(r >= 0x10000 && r <= 0xeffff)
}

return (r >= 'A' && r <= 'Z') ||
(r >= 'a' && r <= 'z') ||
(r >= '0' && r <= '9') ||
Expand Down
13 changes: 10 additions & 3 deletions toml_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,8 @@ func TestTomlNextFails(t *testing.T) {
"valid/string/escape-esc",
"valid/datetime/no-seconds",
"valid/string/hex-escape",
"valid/inline-table/newline")
"valid/inline-table/newline",
"valid/key/unicode")
}

func runTomlTest(t *testing.T, includeNext bool, wantFail ...string) {
Expand Down Expand Up @@ -360,7 +361,7 @@ func runTomlTest(t *testing.T, includeNext bool, wantFail ...string) {
// Test metadata
if !enc && test.Type() == tomltest.TypeValid {
delete(shouldExistValid, test.Path)
testMeta(t, test)
testMeta(t, test, includeNext)
}
})
}
Expand Down Expand Up @@ -394,11 +395,17 @@ func runTomlTest(t *testing.T, includeNext bool, wantFail ...string) {

var reCollapseSpace = regexp.MustCompile(` +`)

func testMeta(t *testing.T, test tomltest.Test) {
func testMeta(t *testing.T, test tomltest.Test, includeNext bool) {
want, ok := metaTests[strings.TrimPrefix(test.Path, "valid/")]
if !ok {
return
}

// Output is slightly different due to different quoting; just skip for now.
if includeNext && (test.Path == "valid/table/names" || test.Path == "valid/key/case-sensitive") {
return
}

var s interface{}
meta, err := toml.Decode(test.Input, &s)
if err != nil {
Expand Down

0 comments on commit 7edfd73

Please sign in to comment.