Skip to content

Commit

Permalink
decode: allow subtables to be defined later (#750)
Browse files Browse the repository at this point in the history
Fixes #739
  • Loading branch information
pelletier committed Apr 8, 2022
1 parent 88a8aec commit 89d7b41
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 7 deletions.
19 changes: 12 additions & 7 deletions internal/tracker/seen.go
Expand Up @@ -79,6 +79,7 @@ type entry struct {
name []byte
kind keyKind
explicit bool
kv bool
}

// Find the index of the child of parentIdx with key k. Returns -1 if
Expand Down Expand Up @@ -111,14 +112,15 @@ func (s *SeenTracker) clear(idx int) {
s.entries[idx].child = -1
}

func (s *SeenTracker) create(parentIdx int, name []byte, kind keyKind, explicit bool) int {
func (s *SeenTracker) create(parentIdx int, name []byte, kind keyKind, explicit bool, kv bool) int {
e := entry{
child: -1,
next: s.entries[parentIdx].child,

name: name,
kind: kind,
explicit: explicit,
kv: kv,
}
var idx int
if s.entries[0].next >= 0 {
Expand All @@ -137,7 +139,10 @@ func (s *SeenTracker) create(parentIdx int, name []byte, kind keyKind, explicit

func (s *SeenTracker) setExplicitFlag(parentIdx int) {
for i := s.entries[parentIdx].child; i >= 0; i = s.entries[i].next {
s.entries[i].explicit = true
if s.entries[i].kv {
s.entries[i].explicit = true
s.entries[i].kv = false
}
s.setExplicitFlag(i)
}
}
Expand Down Expand Up @@ -183,7 +188,7 @@ func (s *SeenTracker) checkTable(node *ast.Node) error {
idx := s.find(parentIdx, k)

if idx < 0 {
idx = s.create(parentIdx, k, tableKind, false)
idx = s.create(parentIdx, k, tableKind, false, false)
} else {
entry := s.entries[idx]
if entry.kind == valueKind {
Expand All @@ -206,7 +211,7 @@ func (s *SeenTracker) checkTable(node *ast.Node) error {
}
s.entries[idx].explicit = true
} else {
idx = s.create(parentIdx, k, tableKind, true)
idx = s.create(parentIdx, k, tableKind, true, false)
}

s.currentIdx = idx
Expand All @@ -233,7 +238,7 @@ func (s *SeenTracker) checkArrayTable(node *ast.Node) error {
idx := s.find(parentIdx, k)

if idx < 0 {
idx = s.create(parentIdx, k, tableKind, false)
idx = s.create(parentIdx, k, tableKind, false, false)
} else {
entry := s.entries[idx]
if entry.kind == valueKind {
Expand All @@ -254,7 +259,7 @@ func (s *SeenTracker) checkArrayTable(node *ast.Node) error {
}
s.clear(idx)
} else {
idx = s.create(parentIdx, k, arrayTableKind, true)
idx = s.create(parentIdx, k, arrayTableKind, true, false)
}

s.currentIdx = idx
Expand All @@ -272,7 +277,7 @@ func (s *SeenTracker) checkKeyValue(node *ast.Node) error {
idx := s.find(parentIdx, k)

if idx < 0 {
idx = s.create(parentIdx, k, tableKind, false)
idx = s.create(parentIdx, k, tableKind, false, true)
} else {
entry := s.entries[idx]
if it.IsLast() {
Expand Down
15 changes: 15 additions & 0 deletions internal/tracker/seen_test.go
@@ -0,0 +1,15 @@
package tracker

import (
"testing"
"unsafe"

"github.com/stretchr/testify/require"
)

func TestEntrySize(t *testing.T) {
// Validate no regression on the size of entry{}. This is a critical bit for
// performance of unmarshaling documents. Should only be increased with care
// and a very good reason.
require.LessOrEqual(t, 48, int(unsafe.Sizeof(entry{})))
}
29 changes: 29 additions & 0 deletions unmarshaler_test.go
Expand Up @@ -545,6 +545,35 @@ func TestUnmarshal(t *testing.T) {
}
},
},
{
desc: "issue 739 - table redefinition",
input: `
[foo.bar.baz]
wibble = 'wobble'
[foo]
[foo.bar]
huey = 'dewey'
`,
gen: func() test {
m := map[string]interface{}{}

return test{
target: &m,
expected: &map[string]interface{}{
`foo`: map[string]interface{}{
"bar": map[string]interface{}{
"huey": "dewey",
"baz": map[string]interface{}{
"wibble": "wobble",
},
},
},
},
}
},
},
{
desc: "multiline basic string",
input: `A = """\
Expand Down

0 comments on commit 89d7b41

Please sign in to comment.