Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 28f1efc7d3 | |||
| 7d69e4a728 | |||
| e46d245c09 |
@@ -1,4 +1,5 @@
|
||||
//go:build go1.18 || go1.19
|
||||
// +build go1.18 go1.19
|
||||
|
||||
package toml_test
|
||||
|
||||
|
||||
+26
-4
@@ -123,7 +123,7 @@ type decoder struct {
|
||||
stashedExpr bool
|
||||
|
||||
// Skip expressions until a table is found. This is set to true when a
|
||||
// table could not be create (missing field in map), so all KV expressions
|
||||
// table could not be created (missing field in map), so all KV expressions
|
||||
// need to be skipped.
|
||||
skipUntilTable bool
|
||||
|
||||
@@ -483,7 +483,7 @@ func (d *decoder) handleKeyPart(key ast.Iterator, v reflect.Value, nextFn handle
|
||||
d.errorContext.Struct = t
|
||||
d.errorContext.Field = path
|
||||
|
||||
f := v.FieldByIndex(path)
|
||||
f := fieldByIndex(v, path)
|
||||
x, err := nextFn(key, f)
|
||||
if err != nil || d.skipUntilTable {
|
||||
return reflect.Value{}, err
|
||||
@@ -1071,7 +1071,7 @@ func (d *decoder) handleKeyValuePart(key ast.Iterator, value *ast.Node, v reflec
|
||||
d.errorContext.Struct = t
|
||||
d.errorContext.Field = path
|
||||
|
||||
f := v.FieldByIndex(path)
|
||||
f := fieldByIndex(v, path)
|
||||
x, err := d.handleKeyValueInner(key, value, f)
|
||||
if err != nil {
|
||||
return reflect.Value{}, err
|
||||
@@ -1135,6 +1135,21 @@ func initAndDereferencePointer(v reflect.Value) reflect.Value {
|
||||
return elem
|
||||
}
|
||||
|
||||
// Same as reflect.Value.FieldByIndex, but creates pointers if needed.
|
||||
func fieldByIndex(v reflect.Value, path []int) reflect.Value {
|
||||
for i, x := range path {
|
||||
v = v.Field(x)
|
||||
|
||||
if i < len(path)-1 && v.Kind() == reflect.Pointer {
|
||||
if v.IsNil() {
|
||||
v.Set(reflect.New(v.Type().Elem()))
|
||||
}
|
||||
v = v.Elem()
|
||||
}
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
type fieldPathsMap = map[string][]int
|
||||
|
||||
var globalFieldPathsCache atomic.Value // map[danger.TypeID]fieldPathsMap
|
||||
@@ -1192,7 +1207,14 @@ func forEachField(t reflect.Type, path []int, do func(name string, path []int))
|
||||
}
|
||||
|
||||
if f.Anonymous && name == "" {
|
||||
forEachField(f.Type, fieldPath, do)
|
||||
t2 := f.Type
|
||||
if t2.Kind() == reflect.Pointer {
|
||||
t2 = t2.Elem()
|
||||
}
|
||||
|
||||
if t2.Kind() == reflect.Struct {
|
||||
forEachField(t2, fieldPath, do)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -2451,6 +2451,21 @@ answer = 42
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestIssue807(t *testing.T) {
|
||||
type A struct {
|
||||
Name string `toml:"name"`
|
||||
}
|
||||
|
||||
type M struct {
|
||||
*A
|
||||
}
|
||||
|
||||
var m M
|
||||
err := toml.Unmarshal([]byte(`name = 'foo'`), &m)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "foo", m.Name)
|
||||
}
|
||||
|
||||
func TestUnmarshalDecodeErrors(t *testing.T) {
|
||||
examples := []struct {
|
||||
desc string
|
||||
@@ -3273,3 +3288,16 @@ func TestUnmarshal_RecursiveTableArray(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalEmbedNonString(t *testing.T) {
|
||||
type Foo []byte
|
||||
type doc struct {
|
||||
Foo
|
||||
}
|
||||
|
||||
d := doc{}
|
||||
|
||||
err := toml.Unmarshal([]byte(`foo = 'bar'`), &d)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, d.Foo)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user