Quote keys during encoding when the key isn't bare (#291)

In case the key contains non-bare characters (out of `A-Za-z0-9_-`), the
key needs to be quoted during encoding to be valid TOML.
This commit is contained in:
Thomas Pelletier
2019-08-18 23:00:12 -07:00
committed by GitHub
parent 84da2c4a25
commit 68063a447e
2 changed files with 52 additions and 1 deletions
+28 -1
View File
@@ -354,7 +354,8 @@ func (t *Tree) writeToOrdered(w io.Writer, indent, keyspace string, bytesCount i
if v.commented { if v.commented {
commented = "# " commented = "# "
} }
writtenBytesCount, err := writeStrings(w, indent, commented, k, " = ", repr, "\n") quotedKey := quoteKeyIfNeeded(k)
writtenBytesCount, err := writeStrings(w, indent, commented, quotedKey, " = ", repr, "\n")
bytesCount += int64(writtenBytesCount) bytesCount += int64(writtenBytesCount)
if err != nil { if err != nil {
return bytesCount, err return bytesCount, err
@@ -365,6 +366,32 @@ func (t *Tree) writeToOrdered(w io.Writer, indent, keyspace string, bytesCount i
return bytesCount, nil return bytesCount, nil
} }
// quote a key if it does not fit the bare key format (A-Za-z0-9_-)
// quoted keys use the same rules as strings
func quoteKeyIfNeeded(k string) string {
// when encoding a map with the 'quoteMapKeys' option enabled, the tree will contain
// keys that have already been quoted.
// not an ideal situation, but good enough of a stop gap.
if len(k) >= 2 && k[0] == '"' && k[len(k)-1] == '"' {
return k
}
isBare := true
for _, r := range k {
if !isValidBareChar(r) {
isBare = false
break
}
}
if isBare {
return k
}
return quoteKey(k)
}
func quoteKey(k string) string {
return "\"" + encodeTomlString(k) + "\""
}
func writeStrings(w io.Writer, s ...string) (int, error) { func writeStrings(w io.Writer, s ...string) (int, error) {
var n int var n int
for i := range s { for i := range s {
+24
View File
@@ -327,6 +327,30 @@ c = nan`
} }
} }
func TestIssue290(t *testing.T) {
tomlString :=
`[table]
"127.0.0.1" = "value"
"127.0.0.1:8028" = "value"
"character encoding" = "value"
"ʎǝʞ" = "value"`
t1, err := Load(tomlString)
if err != nil {
t.Fatal("load err:", err)
}
s, err := t1.ToTomlString()
if err != nil {
t.Fatal("ToTomlString err:", err)
}
_, err = Load(s)
if err != nil {
t.Fatal("reload err:", err)
}
}
func BenchmarkTreeToTomlString(b *testing.B) { func BenchmarkTreeToTomlString(b *testing.B) {
toml, err := Load(sampleHard) toml, err := Load(sampleHard)
if err != nil { if err != nil {