Skip to content

Commit 7edfd73

Browse files
authored
Merge pull request #379 from BurntSushi/uni-keys
Support unicode bare keys
2 parents d73da82 + f7d4e0a commit 7edfd73

File tree

5 files changed

+52
-33
lines changed

5 files changed

+52
-33
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"a‍b": {
3+
"type": "string",
4+
"value": "zwj"
5+
},
6+
"ÅÅ": {
7+
"type": "string",
8+
"value": "U+00C5 U+0041 U+030A"
9+
},
10+
"€": {
11+
"type": "string",
12+
"value": "Euro"
13+
},
14+
"😂": {
15+
"type": "string",
16+
"value": "rofl"
17+
}
18+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# TOML 1.1 supports Unicode for bare keys.
2+
3+
€ = 'Euro'
4+
😂 = "rofl"
5+
a‍b = "zwj"
6+
ÅÅ = "U+00C5 U+0041 U+030A"

internal/toml-test/version.go

Lines changed: 2 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ var versions = map[string]versionSpec{
1818
"invalid/inline-table/linebreak-2",
1919
"invalid/inline-table/linebreak-3",
2020
"invalid/inline-table/linebreak-4",
21+
"invalid/key/special-character", // Unicode can now be in bare keys.
2122
},
2223
},
2324

@@ -27,36 +28,7 @@ var versions = map[string]versionSpec{
2728
"valid/string/hex-escape", "invalid/string/bad-hex-esc", // \x..
2829
"valid/datetime/no-seconds", // Times without seconds
2930
"valid/inline-table/newline",
30-
},
31-
},
32-
33-
// Added in 1.0.0:
34-
// Leading zeroes in exponent parts of floats are permitted.
35-
// Allow raw tab characters in basic strings and multi-line basic strings.
36-
// Allow heterogenous values in arrays.
37-
"0.5.0": versionSpec{
38-
inherit: "1.0.0",
39-
exclude: []string{
40-
"valid/hetergeneous",
41-
"valid/array/mixed-*",
42-
},
43-
},
44-
45-
// Added in 0.5.0:
46-
// Add dotted keys.
47-
// Add hex, octal, and binary integer formats.
48-
// Add special float values (inf, nan)
49-
// Add Local Date-Time.
50-
// Add Local Date.
51-
// Add Local Time.
52-
// Allow space (instead of T) to separate date and time in Date-Time.
53-
// Allow accidental whitespace between backslash and newline in the line
54-
// continuation operator in multi-line basic strings.
55-
"0.4.0": versionSpec{
56-
inherit: "0.5.0",
57-
exclude: []string{
58-
"valid/datetime/local*",
59-
"valid/key/dotted",
31+
"valid/key/unicode", // Unicode bare keys
6032
},
6133
},
6234
}

lex.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,7 +1257,23 @@ func isOctal(r rune) bool { return r >= '0' && r <= '7' }
12571257
func isHexadecimal(r rune) bool {
12581258
return (r >= '0' && r <= '9') || (r >= 'a' && r <= 'f') || (r >= 'A' && r <= 'F')
12591259
}
1260+
12601261
func isBareKeyChar(r rune) bool {
1262+
if tomlNext {
1263+
return (r >= 'A' && r <= 'Z') ||
1264+
(r >= 'a' && r <= 'z') ||
1265+
(r >= '0' && r <= '9') ||
1266+
r == '_' || r == '-' ||
1267+
r == 0xb2 || r == 0xb3 || r == 0xb9 || (r >= 0xbc && r <= 0xbe) ||
1268+
(r >= 0xc0 && r <= 0xd6) || (r >= 0xd8 && r <= 0xf6) || (r >= 0xf8 && r <= 0x037d) ||
1269+
(r >= 0x037f && r <= 0x1fff) ||
1270+
(r >= 0x200c && r <= 0x200d) || (r >= 0x203f && r <= 0x2040) ||
1271+
(r >= 0x2070 && r <= 0x218f) || (r >= 0x2460 && r <= 0x24ff) ||
1272+
(r >= 0x2c00 && r <= 0x2fef) || (r >= 0x3001 && r <= 0xd7ff) ||
1273+
(r >= 0xf900 && r <= 0xfdcf) || (r >= 0xfdf0 && r <= 0xfffd) ||
1274+
(r >= 0x10000 && r <= 0xeffff)
1275+
}
1276+
12611277
return (r >= 'A' && r <= 'Z') ||
12621278
(r >= 'a' && r <= 'z') ||
12631279
(r >= '0' && r <= '9') ||

toml_test.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,8 @@ func TestTomlNextFails(t *testing.T) {
257257
"valid/string/escape-esc",
258258
"valid/datetime/no-seconds",
259259
"valid/string/hex-escape",
260-
"valid/inline-table/newline")
260+
"valid/inline-table/newline",
261+
"valid/key/unicode")
261262
}
262263

263264
func runTomlTest(t *testing.T, includeNext bool, wantFail ...string) {
@@ -360,7 +361,7 @@ func runTomlTest(t *testing.T, includeNext bool, wantFail ...string) {
360361
// Test metadata
361362
if !enc && test.Type() == tomltest.TypeValid {
362363
delete(shouldExistValid, test.Path)
363-
testMeta(t, test)
364+
testMeta(t, test, includeNext)
364365
}
365366
})
366367
}
@@ -394,11 +395,17 @@ func runTomlTest(t *testing.T, includeNext bool, wantFail ...string) {
394395

395396
var reCollapseSpace = regexp.MustCompile(` +`)
396397

397-
func testMeta(t *testing.T, test tomltest.Test) {
398+
func testMeta(t *testing.T, test tomltest.Test, includeNext bool) {
398399
want, ok := metaTests[strings.TrimPrefix(test.Path, "valid/")]
399400
if !ok {
400401
return
401402
}
403+
404+
// Output is slightly different due to different quoting; just skip for now.
405+
if includeNext && (test.Path == "valid/table/names" || test.Path == "valid/key/case-sensitive") {
406+
return
407+
}
408+
402409
var s interface{}
403410
meta, err := toml.Decode(test.Input, &s)
404411
if err != nil {

0 commit comments

Comments
 (0)