Skip to content

Commit

Permalink
Correctly set the Meta.Keys() order for inline tables
Browse files Browse the repository at this point in the history
The table name would be listed *after* the key name; e.g. ./cmd/tomlv
would print:

	    toml-schema.version                              Integer
	toml-schema                                          Hash

For the document:

	toml-schema = {version = 1}

With this it prints the expected:

	toml-schema                                          Hash
	    toml-schema.version                              Integer
  • Loading branch information
arp242 committed Jun 5, 2023
1 parent c859a22 commit 60801d0
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 13 deletions.
2 changes: 1 addition & 1 deletion decode.go
Expand Up @@ -248,7 +248,7 @@ func (md *MetaData) unify(data interface{}, rv reflect.Value) error {
case reflect.Bool:
return md.unifyBool(data, rv)
case reflect.Interface:
if rv.NumMethod() > 0 { // Only support empty interfaces are supported.
if rv.NumMethod() > 0 { /// Only empty interfaces are supported.
return md.e("unsupported type %s", rv.Type())
}
return md.unifyAnything(data, rv)
Expand Down
30 changes: 30 additions & 0 deletions decode_test.go
Expand Up @@ -1171,6 +1171,36 @@ func TestDecodeDoubleTags(t *testing.T) {
}
}

func TestMetaKeys(t *testing.T) {
tests := []struct {
in string
want []Key
}{
{"", []Key{}},
{"b=1\na=1", []Key{Key{"b"}, Key{"a"}}},
{"a.b=1\na.a=1", []Key{Key{"a", "b"}, Key{"a", "a"}}}, // TODO: should include "a"
{"[tbl]\na=1", []Key{Key{"tbl"}, Key{"tbl", "a"}}},
{"[tbl]\na.a=1", []Key{Key{"tbl"}, Key{"tbl", "a", "a"}}}, // TODO: should include "a.a"
{"tbl={a=1}", []Key{Key{"tbl"}, Key{"tbl", "a"}}},
{"tbl={a={b=1}}", []Key{Key{"tbl"}, Key{"tbl", "a"}, Key{"tbl", "a", "b"}}},
}

for _, tt := range tests {
t.Run("", func(t *testing.T) {
var x interface{}
meta, err := Decode(tt.in, &x)
if err != nil {
t.Fatal(err)
}

have := meta.Keys()
if !reflect.DeepEqual(tt.want, have) {
t.Errorf("\nhave: %s\nwant: %s\n", have, tt.want)
}
})
}
}

// errorContains checks if the error message in have contains the text in
// want.
//
Expand Down
2 changes: 1 addition & 1 deletion encode.go
Expand Up @@ -503,7 +503,7 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value, inline bool) {

fieldVal = eindirect(fieldVal)

if isNil(fieldVal) { // Don't write anything for nil fields.
if isNil(fieldVal) { /// Don't write anything for nil fields.
continue
}

Expand Down
18 changes: 7 additions & 11 deletions parse.go
Expand Up @@ -203,12 +203,12 @@ func (p *parser) topLevel(item item) {
for i := range context {
p.addImplicitContext(append(p.context, context[i:i+1]...))
}
p.ordered = append(p.ordered, p.context.add(p.currentKey))

/// Set value.
vItem := p.next()
val, typ := p.value(vItem, false)
p.set(p.currentKey, val, typ, vItem.pos)
p.ordered = append(p.ordered, p.context.add(p.currentKey))

/// Remove the context we added (preserving any context from [tbl] lines).
p.context = outerContext
Expand Down Expand Up @@ -445,11 +445,11 @@ func (p *parser) valueInlineTable(it item, parentIsArray bool) (interface{}, tom
for i := range context {
p.addImplicitContext(append(p.context, context[i:i+1]...))
}
p.ordered = append(p.ordered, p.context.add(p.currentKey))

/// Set the value.
val, typ := p.value(p.next(), false)
p.set(p.currentKey, val, typ, it.pos)
p.ordered = append(p.ordered, p.context.add(p.currentKey))
hash[p.currentKey] = val

/// Restore context.
Expand Down Expand Up @@ -570,7 +570,6 @@ func (p *parser) addContext(key Key, array bool) {
func (p *parser) set(key string, val interface{}, typ tomlType, pos Position) {
p.setValue(key, val)
p.setType(key, typ, pos)

}

// setValue sets the given key to the given value in the current context.
Expand Down Expand Up @@ -651,14 +650,11 @@ func (p *parser) setType(key string, typ tomlType, pos Position) {

// Implicit keys need to be created when tables are implied in "a.b.c.d = 1" and
// "[a.b.c]" (the "a", "b", and "c" hashes are never created explicitly).
func (p *parser) addImplicit(key Key) { p.implicits[key.String()] = struct{}{} }
func (p *parser) removeImplicit(key Key) { delete(p.implicits, key.String()) }
func (p *parser) isImplicit(key Key) bool { _, ok := p.implicits[key.String()]; return ok }
func (p *parser) isArray(key Key) bool { return p.keyInfo[key.String()].tomlType == tomlArray }
func (p *parser) addImplicitContext(key Key) {
p.addImplicit(key)
p.addContext(key, false)
}
func (p *parser) addImplicit(key Key) { p.implicits[key.String()] = struct{}{} }
func (p *parser) removeImplicit(key Key) { delete(p.implicits, key.String()) }
func (p *parser) isImplicit(key Key) bool { _, ok := p.implicits[key.String()]; return ok }
func (p *parser) isArray(key Key) bool { return p.keyInfo[key.String()].tomlType == tomlArray }
func (p *parser) addImplicitContext(key Key) { p.addImplicit(key); p.addContext(key, false) }

// current returns the full key name of the current context.
func (p *parser) current() string {
Expand Down

0 comments on commit 60801d0

Please sign in to comment.