15
"github.com/pelletier/go-toml/v2/internal/danger"
16
"github.com/pelletier/go-toml/v2/internal/tracker"
17
"github.com/pelletier/go-toml/v2/unstable"
20
// Unmarshal deserializes a TOML document into a Go value.
22
// It is a shortcut for Decoder.Decode() with the default options.
23
func Unmarshal(data []byte, v interface{}) error {
24
p := unstable.Parser{}
28
return d.FromParser(v)
31
// Decoder reads and decode a TOML document from an input stream.
40
// NewDecoder creates a new Decoder that will read from r.
41
func NewDecoder(r io.Reader) *Decoder {
45
// DisallowUnknownFields causes the Decoder to return an error when the
46
// destination is a struct and the input contains a key that does not match a
49
// In that case, the Decoder returns a StrictMissingError that can be used to
50
// retrieve the individual errors as well as generate a human readable
51
// description of the missing fields.
52
func (d *Decoder) DisallowUnknownFields() *Decoder {
57
// Decode the whole content of r into v.
59
// By default, values in the document that don't exist in the target Go value
60
// are ignored. See Decoder.DisallowUnknownFields() to change this behavior.
62
// When a TOML local date, time, or date-time is decoded into a time.Time, its
63
// value is represented in time.Local timezone. Otherwise the appropriate Local*
64
// structure is used. For time values, precision up to the nanosecond is
65
// supported by truncating extra digits.
67
// Empty tables decoded in an interface{} create an empty initialized
68
// map[string]interface{}.
70
// Types implementing the encoding.TextUnmarshaler interface are decoded from a
73
// When decoding a number, go-toml will return an error if the number is out of
74
// bounds for the target type (which includes negative numbers when decoding
75
// into an unsigned int).
77
// If an error occurs while decoding the content of the document, this function
78
// returns a toml.DecodeError, providing context about the issue. When using
79
// strict mode and a field is missing, a `toml.StrictMissingError` is
80
// returned. In any other case, this function returns a standard Go error.
84
// List of supported TOML types and their associated accepted Go types:
87
// Integer -> uint*, int*, depending on size
88
// Float -> float*, depending on size
90
// Offset Date-Time -> time.Time
91
// Local Date-time -> LocalDateTime, time.Time
92
// Local Date -> LocalDate, time.Time
93
// Local Time -> LocalTime, time.Time
94
// Array -> slice and array, depending on elements types
95
// Table -> map and struct
96
// Inline Table -> same as Table
97
// Array of Tables -> same as Array and Table
98
func (d *Decoder) Decode(v interface{}) error {
99
b, err := ioutil.ReadAll(d.r)
101
return fmt.Errorf("toml: %w", err)
104
p := unstable.Parser{}
113
return dec.FromParser(v)
117
// Which parser instance in use for this decoding session.
120
// Flag indicating that the current expression is stashed.
121
// If set to true, calling nextExpr will not actually pull a new expression
122
// but turn off the flag instead.
125
// Skip expressions until a table is found. This is set to true when a
126
// table could not be created (missing field in map), so all KV expressions
127
// need to be skipped.
130
// Tracks position in Go arrays.
131
// This is used when decoding [[array tables]] into Go arrays. Given array
132
// tables are separate TOML expression, we need to keep track of where we
133
// are at in the Go array, as we can't just introspect its size.
134
arrayIndexes map[reflect.Value]int
136
// Tracks keys that have been seen, with which type.
137
seen tracker.SeenTracker
142
// Current context for the error.
143
errorContext *errorContext
146
type errorContext struct {
151
func (d *decoder) typeMismatchError(toml string, target reflect.Type) error {
152
if d.errorContext != nil && d.errorContext.Struct != nil {
153
ctx := d.errorContext
154
f := ctx.Struct.FieldByIndex(ctx.Field)
155
return fmt.Errorf("toml: cannot decode TOML %s into struct field %s.%s of type %s", toml, ctx.Struct, f.Name, f.Type)
157
return fmt.Errorf("toml: cannot decode TOML %s into a Go value of type %s", toml, target)
160
func (d *decoder) expr() *unstable.Node {
161
return d.p.Expression()
164
func (d *decoder) nextExpr() bool {
166
d.stashedExpr = false
169
return d.p.NextExpression()
172
func (d *decoder) stashExpr() {
176
func (d *decoder) arrayIndex(shouldAppend bool, v reflect.Value) int {
177
if d.arrayIndexes == nil {
178
d.arrayIndexes = make(map[reflect.Value]int, 1)
181
idx, ok := d.arrayIndexes[v]
184
d.arrayIndexes[v] = 0
185
} else if shouldAppend {
187
d.arrayIndexes[v] = idx
193
func (d *decoder) FromParser(v interface{}) error {
194
r := reflect.ValueOf(v)
195
if r.Kind() != reflect.Ptr {
196
return fmt.Errorf("toml: decoding can only be performed into a pointer, not %s", r.Kind())
200
return fmt.Errorf("toml: decoding pointer target cannot be nil")
204
if r.Kind() == reflect.Interface && r.IsNil() {
205
newMap := map[string]interface{}{}
206
r.Set(reflect.ValueOf(newMap))
209
err := d.fromParser(r)
211
return d.strict.Error(d.p.Data())
214
var e *unstable.ParserError
215
if errors.As(err, &e) {
216
return wrapDecodeError(d.p.Data(), e)
222
func (d *decoder) fromParser(root reflect.Value) error {
224
err := d.handleRootExpression(d.expr(), root)
234
Rules for the unmarshal code:
236
- The stack is used to keep track of which values need to be set where.
237
- handle* functions <=> switch on a given unstable.Kind.
238
- unmarshalX* functions need to unmarshal a node of kind X.
239
- An "object" is either a struct or a map.
242
func (d *decoder) handleRootExpression(expr *unstable.Node, v reflect.Value) error {
246
if !(d.skipUntilTable && expr.Kind == unstable.KeyValue) {
247
err = d.seen.CheckExpression(expr)
254
case unstable.KeyValue:
255
if d.skipUntilTable {
258
x, err = d.handleKeyValue(expr, v)
260
d.skipUntilTable = false
261
d.strict.EnterTable(expr)
262
x, err = d.handleTable(expr.Key(), v)
263
case unstable.ArrayTable:
264
d.skipUntilTable = false
265
d.strict.EnterArrayTable(expr)
266
x, err = d.handleArrayTable(expr.Key(), v)
268
panic(fmt.Errorf("parser should not permit expression of kind %s at document root", expr.Kind))
271
if d.skipUntilTable {
272
if expr.Kind == unstable.Table || expr.Kind == unstable.ArrayTable {
273
d.strict.MissingTable(expr)
275
} else if err == nil && x.IsValid() {
282
func (d *decoder) handleArrayTable(key unstable.Iterator, v reflect.Value) (reflect.Value, error) {
284
return d.handleArrayTablePart(key, v)
286
return d.handleKeyValues(v)
289
func (d *decoder) handleArrayTableCollectionLast(key unstable.Iterator, v reflect.Value) (reflect.Value, error) {
291
case reflect.Interface:
294
elem = reflect.New(sliceInterfaceType).Elem()
295
elem.Set(reflect.MakeSlice(sliceInterfaceType, 0, 16))
296
} else if elem.Kind() == reflect.Slice {
297
if elem.Type() != sliceInterfaceType {
298
elem = reflect.New(sliceInterfaceType).Elem()
299
elem.Set(reflect.MakeSlice(sliceInterfaceType, 0, 16))
300
} else if !elem.CanSet() {
301
nelem := reflect.New(sliceInterfaceType).Elem()
302
nelem.Set(reflect.MakeSlice(sliceInterfaceType, elem.Len(), elem.Cap()))
303
reflect.Copy(nelem, elem)
307
return d.handleArrayTableCollectionLast(key, elem)
311
ptr := reflect.New(v.Type().Elem())
316
elem, err := d.handleArrayTableCollectionLast(key, elem)
318
return reflect.Value{}, err
324
elemType := v.Type().Elem()
325
var elem reflect.Value
326
if elemType.Kind() == reflect.Interface {
327
elem = makeMapStringInterface()
329
elem = reflect.New(elemType).Elem()
331
elem2, err := d.handleArrayTable(key, elem)
333
return reflect.Value{}, err
338
return reflect.Append(v, elem), nil
340
idx := d.arrayIndex(true, v)
342
return v, fmt.Errorf("%s at position %d", d.typeMismatchError("array table", v.Type()), idx)
345
_, err := d.handleArrayTable(key, elem)
348
return reflect.Value{}, d.typeMismatchError("array table", v.Type())
352
// When parsing an array table expression, each part of the key needs to be
353
// evaluated like a normal key, but if it returns a collection, it also needs to
354
// point to the last element of the collection. Unless it is the last part of
355
// the key, then it needs to create a new element at the end.
356
func (d *decoder) handleArrayTableCollection(key unstable.Iterator, v reflect.Value) (reflect.Value, error) {
358
return d.handleArrayTableCollectionLast(key, v)
365
ptr := reflect.New(v.Type().Elem())
370
elem, err := d.handleArrayTableCollection(key, elem)
372
return reflect.Value{}, err
380
elem := v.Index(v.Len() - 1)
381
x, err := d.handleArrayTable(key, elem)
382
if err != nil || d.skipUntilTable {
383
return reflect.Value{}, err
391
idx := d.arrayIndex(false, v)
393
return v, fmt.Errorf("%s at position %d", d.typeMismatchError("array table", v.Type()), idx)
396
_, err := d.handleArrayTable(key, elem)
400
return d.handleArrayTable(key, v)
403
func (d *decoder) handleKeyPart(key unstable.Iterator, v reflect.Value, nextFn handlerFn, makeFn valueMakerFn) (reflect.Value, error) {
406
// First, dispatch over v to make sure it is a valid object.
407
// There is no guarantee over what it could be.
412
v.Set(reflect.New(v.Type().Elem()))
415
return d.handleKeyPart(key, elem, nextFn, makeFn)
419
// Create the key for the map element. Convert to key type.
420
mk, err := d.keyFromData(vt.Key(), key.Node().Data)
422
return reflect.Value{}, err
425
// If the map does not exist, create it.
428
v = reflect.MakeMap(vt)
435
// If there is no value in the map, create a new one according to
436
// the map type. If the element type is interface, create either a
437
// map[string]interface{} or a []interface{} depending on whether
438
// this is the last part of the array table key.
441
if t.Kind() == reflect.Interface {
444
mv = reflect.New(t).Elem()
447
} else if mv.Kind() == reflect.Interface {
453
} else if !mv.CanAddr() {
457
mv = reflect.New(t).Elem()
462
x, err := nextFn(key, mv)
464
return reflect.Value{}, err
473
v.SetMapIndex(mk, mv)
476
path, found := structFieldPath(v, string(key.Node().Data))
478
d.skipUntilTable = true
479
return reflect.Value{}, nil
482
if d.errorContext == nil {
483
d.errorContext = new(errorContext)
486
d.errorContext.Struct = t
487
d.errorContext.Field = path
489
f := fieldByIndex(v, path)
490
x, err := nextFn(key, f)
491
if err != nil || d.skipUntilTable {
492
return reflect.Value{}, err
497
d.errorContext.Field = nil
498
d.errorContext.Struct = nil
499
case reflect.Interface:
500
if v.Elem().IsValid() {
503
v = makeMapStringInterface()
506
x, err := d.handleKeyPart(key, v, nextFn, makeFn)
508
return reflect.Value{}, err
515
panic(fmt.Errorf("unhandled part: %s", v.Kind()))
521
// HandleArrayTablePart navigates the Go structure v using the key v. It is
522
// only used for the prefix (non-last) parts of an array-table. When
523
// encountering a collection, it should go to the last element.
524
func (d *decoder) handleArrayTablePart(key unstable.Iterator, v reflect.Value) (reflect.Value, error) {
525
var makeFn valueMakerFn
527
makeFn = makeSliceInterface
529
makeFn = makeMapStringInterface
531
return d.handleKeyPart(key, v, d.handleArrayTableCollection, makeFn)
534
// HandleTable returns a reference when it has checked the next expression but
536
func (d *decoder) handleTable(key unstable.Iterator, v reflect.Value) (reflect.Value, error) {
537
if v.Kind() == reflect.Slice {
539
return reflect.Value{}, unstable.NewParserError(key.Node().Data, "cannot store a table in a slice")
541
elem := v.Index(v.Len() - 1)
542
x, err := d.handleTable(key, elem)
544
return reflect.Value{}, err
549
return reflect.Value{}, nil
552
// Still scoping the key
553
return d.handleTablePart(key, v)
555
// Done scoping the key.
556
// Now handle all the key-value expressions in this table.
557
return d.handleKeyValues(v)
560
// Handle root expressions until the end of the document or the next
562
func (d *decoder) handleKeyValues(v reflect.Value) (reflect.Value, error) {
566
if expr.Kind != unstable.KeyValue {
567
// Stash the expression so that fromParser can just loop and use
568
// the right handler.
569
// We could just recurse ourselves here, but at least this gives a
570
// chance to pop the stack a bit.
575
err := d.seen.CheckExpression(expr)
577
return reflect.Value{}, err
580
x, err := d.handleKeyValue(expr, v)
582
return reflect.Value{}, err
593
handlerFn func(key unstable.Iterator, v reflect.Value) (reflect.Value, error)
594
valueMakerFn func() reflect.Value
597
func makeMapStringInterface() reflect.Value {
598
return reflect.MakeMap(mapStringInterfaceType)
601
func makeSliceInterface() reflect.Value {
602
return reflect.MakeSlice(sliceInterfaceType, 0, 16)
605
func (d *decoder) handleTablePart(key unstable.Iterator, v reflect.Value) (reflect.Value, error) {
606
return d.handleKeyPart(key, v, d.handleTable, makeMapStringInterface)
609
func (d *decoder) tryTextUnmarshaler(node *unstable.Node, v reflect.Value) (bool, error) {
610
// Special case for time, because we allow to unmarshal to it from
611
// different kind of AST nodes.
612
if v.Type() == timeType {
616
if v.CanAddr() && v.Addr().Type().Implements(textUnmarshalerType) {
617
err := v.Addr().Interface().(encoding.TextUnmarshaler).UnmarshalText(node.Data)
619
return false, unstable.NewParserError(d.p.Raw(node.Raw), "%w", err)
628
func (d *decoder) handleValue(value *unstable.Node, v reflect.Value) error {
629
for v.Kind() == reflect.Ptr {
630
v = initAndDereferencePointer(v)
633
ok, err := d.tryTextUnmarshaler(value, v)
634
if ok || err != nil {
639
case unstable.String:
640
return d.unmarshalString(value, v)
641
case unstable.Integer:
642
return d.unmarshalInteger(value, v)
644
return d.unmarshalFloat(value, v)
646
return d.unmarshalBool(value, v)
647
case unstable.DateTime:
648
return d.unmarshalDateTime(value, v)
649
case unstable.LocalDate:
650
return d.unmarshalLocalDate(value, v)
651
case unstable.LocalTime:
652
return d.unmarshalLocalTime(value, v)
653
case unstable.LocalDateTime:
654
return d.unmarshalLocalDateTime(value, v)
655
case unstable.InlineTable:
656
return d.unmarshalInlineTable(value, v)
658
return d.unmarshalArray(value, v)
660
panic(fmt.Errorf("handleValue not implemented for %s", value.Kind))
664
func (d *decoder) unmarshalArray(array *unstable.Node, v reflect.Value) error {
668
v.Set(reflect.MakeSlice(v.Type(), 0, 16))
673
// arrays are always initialized
674
case reflect.Interface:
677
elem = reflect.New(sliceInterfaceType).Elem()
678
elem.Set(reflect.MakeSlice(sliceInterfaceType, 0, 16))
679
} else if elem.Kind() == reflect.Slice {
680
if elem.Type() != sliceInterfaceType {
681
elem = reflect.New(sliceInterfaceType).Elem()
682
elem.Set(reflect.MakeSlice(sliceInterfaceType, 0, 16))
683
} else if !elem.CanSet() {
684
nelem := reflect.New(sliceInterfaceType).Elem()
685
nelem.Set(reflect.MakeSlice(sliceInterfaceType, elem.Len(), elem.Cap()))
686
reflect.Copy(nelem, elem)
690
err := d.unmarshalArray(array, elem)
697
// TODO: use newDecodeError, but first the parser needs to fill
699
return d.typeMismatchError("array", v.Type())
702
elemType := v.Type().Elem()
704
it := array.Children()
710
if v.Kind() == reflect.Slice {
711
elem := reflect.New(elemType).Elem()
713
err := d.handleValue(n, elem)
718
v.Set(reflect.Append(v, elem))
724
err := d.handleValue(n, elem)
735
func (d *decoder) unmarshalInlineTable(itable *unstable.Node, v reflect.Value) error {
736
// Make sure v is an initialized object.
740
v.Set(reflect.MakeMap(v.Type()))
743
// structs are always initialized.
744
case reflect.Interface:
747
elem = makeMapStringInterface()
750
return d.unmarshalInlineTable(itable, elem)
752
return unstable.NewParserError(d.p.Raw(itable.Raw), "cannot store inline table in Go type %s", v.Kind())
755
it := itable.Children()
759
x, err := d.handleKeyValue(n, v)
771
func (d *decoder) unmarshalDateTime(value *unstable.Node, v reflect.Value) error {
772
dt, err := parseDateTime(value.Data)
777
v.Set(reflect.ValueOf(dt))
781
func (d *decoder) unmarshalLocalDate(value *unstable.Node, v reflect.Value) error {
782
ld, err := parseLocalDate(value.Data)
787
if v.Type() == timeType {
788
cast := ld.AsTime(time.Local)
789
v.Set(reflect.ValueOf(cast))
793
v.Set(reflect.ValueOf(ld))
798
func (d *decoder) unmarshalLocalTime(value *unstable.Node, v reflect.Value) error {
799
lt, rest, err := parseLocalTime(value.Data)
805
return unstable.NewParserError(rest, "extra characters at the end of a local time")
808
v.Set(reflect.ValueOf(lt))
812
func (d *decoder) unmarshalLocalDateTime(value *unstable.Node, v reflect.Value) error {
813
ldt, rest, err := parseLocalDateTime(value.Data)
819
return unstable.NewParserError(rest, "extra characters at the end of a local date time")
822
if v.Type() == timeType {
823
cast := ldt.AsTime(time.Local)
825
v.Set(reflect.ValueOf(cast))
829
v.Set(reflect.ValueOf(ldt))
834
func (d *decoder) unmarshalBool(value *unstable.Node, v reflect.Value) error {
835
b := value.Data[0] == 't'
840
case reflect.Interface:
841
v.Set(reflect.ValueOf(b))
843
return unstable.NewParserError(value.Data, "cannot assign boolean to a %t", b)
849
func (d *decoder) unmarshalFloat(value *unstable.Node, v reflect.Value) error {
850
f, err := parseFloat(value.Data)
856
case reflect.Float64:
858
case reflect.Float32:
859
if f > math.MaxFloat32 {
860
return unstable.NewParserError(value.Data, "number %f does not fit in a float32", f)
863
case reflect.Interface:
864
v.Set(reflect.ValueOf(f))
866
return unstable.NewParserError(value.Data, "float cannot be assigned to %s", v.Kind())
873
maxInt = int64(^uint(0) >> 1)
877
// Maximum value of uint for decoding. Currently the decoder parses the integer
878
// into an int64. As a result, on architectures where uint is 64 bits, the
879
// effective maximum uint we can decode is the maximum of int64. On
880
// architectures where uint is 32 bits, the maximum value we can decode is
881
// lower: the maximum of uint32. I didn't find a way to figure out this value at
882
// compile time, so it is computed during initialization.
883
var maxUint int64 = math.MaxInt64
886
m := uint64(^uint(0))
887
if m < uint64(maxUint) {
892
func (d *decoder) unmarshalInteger(value *unstable.Node, v reflect.Value) error {
894
if kind == reflect.Float32 || kind == reflect.Float64 {
895
return d.unmarshalFloat(value, v)
898
i, err := parseInteger(value.Data)
910
if i < math.MinInt32 || i > math.MaxInt32 {
911
return fmt.Errorf("toml: number %d does not fit in an int32", i)
914
r = reflect.ValueOf(int32(i))
916
if i < math.MinInt16 || i > math.MaxInt16 {
917
return fmt.Errorf("toml: number %d does not fit in an int16", i)
920
r = reflect.ValueOf(int16(i))
922
if i < math.MinInt8 || i > math.MaxInt8 {
923
return fmt.Errorf("toml: number %d does not fit in an int8", i)
926
r = reflect.ValueOf(int8(i))
928
if i < minInt || i > maxInt {
929
return fmt.Errorf("toml: number %d does not fit in an int", i)
932
r = reflect.ValueOf(int(i))
935
return fmt.Errorf("toml: negative number %d does not fit in an uint64", i)
938
r = reflect.ValueOf(uint64(i))
940
if i < 0 || i > math.MaxUint32 {
941
return fmt.Errorf("toml: negative number %d does not fit in an uint32", i)
944
r = reflect.ValueOf(uint32(i))
946
if i < 0 || i > math.MaxUint16 {
947
return fmt.Errorf("toml: negative number %d does not fit in an uint16", i)
950
r = reflect.ValueOf(uint16(i))
952
if i < 0 || i > math.MaxUint8 {
953
return fmt.Errorf("toml: negative number %d does not fit in an uint8", i)
956
r = reflect.ValueOf(uint8(i))
958
if i < 0 || i > maxUint {
959
return fmt.Errorf("toml: negative number %d does not fit in an uint", i)
962
r = reflect.ValueOf(uint(i))
963
case reflect.Interface:
964
r = reflect.ValueOf(i)
966
return d.typeMismatchError("integer", v.Type())
969
if !r.Type().AssignableTo(v.Type()) {
970
r = r.Convert(v.Type())
978
func (d *decoder) unmarshalString(value *unstable.Node, v reflect.Value) error {
981
v.SetString(string(value.Data))
982
case reflect.Interface:
983
v.Set(reflect.ValueOf(string(value.Data)))
985
return unstable.NewParserError(d.p.Raw(value.Raw), "cannot store TOML string into a Go %s", v.Kind())
991
func (d *decoder) handleKeyValue(expr *unstable.Node, v reflect.Value) (reflect.Value, error) {
992
d.strict.EnterKeyValue(expr)
994
v, err := d.handleKeyValueInner(expr.Key(), expr.Value(), v)
995
if d.skipUntilTable {
996
d.strict.MissingField(expr)
997
d.skipUntilTable = false
1000
d.strict.ExitKeyValue(expr)
1005
func (d *decoder) handleKeyValueInner(key unstable.Iterator, value *unstable.Node, v reflect.Value) (reflect.Value, error) {
1007
// Still scoping the key
1008
return d.handleKeyValuePart(key, value, v)
1010
// Done scoping the key.
1011
// v is whatever Go value we need to fill.
1012
return reflect.Value{}, d.handleValue(value, v)
1015
func (d *decoder) keyFromData(keyType reflect.Type, data []byte) (reflect.Value, error) {
1017
case stringType.AssignableTo(keyType):
1018
return reflect.ValueOf(string(data)), nil
1020
case stringType.ConvertibleTo(keyType):
1021
return reflect.ValueOf(string(data)).Convert(keyType), nil
1023
case keyType.Implements(textUnmarshalerType):
1024
mk := reflect.New(keyType.Elem())
1025
if err := mk.Interface().(encoding.TextUnmarshaler).UnmarshalText(data); err != nil {
1026
return reflect.Value{}, fmt.Errorf("toml: error unmarshalling key type %s from text: %w", stringType, err)
1030
case reflect.PtrTo(keyType).Implements(textUnmarshalerType):
1031
mk := reflect.New(keyType)
1032
if err := mk.Interface().(encoding.TextUnmarshaler).UnmarshalText(data); err != nil {
1033
return reflect.Value{}, fmt.Errorf("toml: error unmarshalling key type %s from text: %w", stringType, err)
1035
return mk.Elem(), nil
1037
return reflect.Value{}, fmt.Errorf("toml: cannot convert map key of type %s to expected type %s", stringType, keyType)
1040
func (d *decoder) handleKeyValuePart(key unstable.Iterator, value *unstable.Node, v reflect.Value) (reflect.Value, error) {
1041
// contains the replacement for v
1042
var rv reflect.Value
1044
// First, dispatch over v to make sure it is a valid object.
1045
// There is no guarantee over what it could be.
1050
mk, err := d.keyFromData(vt.Key(), key.Node().Data)
1052
return reflect.Value{}, err
1055
// If the map does not exist, create it.
1057
v = reflect.MakeMap(vt)
1061
mv := v.MapIndex(mk)
1063
if !mv.IsValid() || key.IsLast() {
1065
mv = reflect.New(v.Type().Elem()).Elem()
1068
nv, err := d.handleKeyValueInner(key, value, mv)
1070
return reflect.Value{}, err
1078
v.SetMapIndex(mk, mv)
1080
case reflect.Struct:
1081
path, found := structFieldPath(v, string(key.Node().Data))
1083
d.skipUntilTable = true
1087
if d.errorContext == nil {
1088
d.errorContext = new(errorContext)
1091
d.errorContext.Struct = t
1092
d.errorContext.Field = path
1094
f := fieldByIndex(v, path)
1097
// If the field is not settable, need to take a slower path and make a copy of
1098
// the struct itself to a new location.
1099
nvp := reflect.New(v.Type())
1102
_, err := d.handleKeyValuePart(key, value, v)
1104
return reflect.Value{}, err
1106
return nvp.Elem(), nil
1108
x, err := d.handleKeyValueInner(key, value, f)
1110
return reflect.Value{}, err
1116
d.errorContext.Struct = nil
1117
d.errorContext.Field = nil
1118
case reflect.Interface:
1121
// Following encoding/json: decoding an object into an
1122
// interface{}, it needs to always hold a
1123
// map[string]interface{}. This is for the types to be
1124
// consistent whether a previous value was set or not.
1125
if !v.IsValid() || v.Type() != mapStringInterfaceType {
1126
v = makeMapStringInterface()
1129
x, err := d.handleKeyValuePart(key, value, v)
1131
return reflect.Value{}, err
1139
if !elem.IsValid() {
1140
ptr := reflect.New(v.Type().Elem())
1146
elem2, err := d.handleKeyValuePart(key, value, elem)
1148
return reflect.Value{}, err
1150
if elem2.IsValid() {
1155
return reflect.Value{}, fmt.Errorf("unhandled kv part: %s", v.Kind())
1161
func initAndDereferencePointer(v reflect.Value) reflect.Value {
1162
var elem reflect.Value
1164
ptr := reflect.New(v.Type().Elem())
1171
// Same as reflect.Value.FieldByIndex, but creates pointers if needed.
1172
func fieldByIndex(v reflect.Value, path []int) reflect.Value {
1173
for i, x := range path {
1176
if i < len(path)-1 && v.Kind() == reflect.Ptr {
1178
v.Set(reflect.New(v.Type().Elem()))
1186
type fieldPathsMap = map[string][]int
1188
var globalFieldPathsCache atomic.Value // map[danger.TypeID]fieldPathsMap
1190
func structFieldPath(v reflect.Value, name string) ([]int, bool) {
1193
cache, _ := globalFieldPathsCache.Load().(map[danger.TypeID]fieldPathsMap)
1194
fieldPaths, ok := cache[danger.MakeTypeID(t)]
1197
fieldPaths = map[string][]int{}
1199
forEachField(t, nil, func(name string, path []int) {
1200
fieldPaths[name] = path
1201
// extra copy for the case-insensitive match
1202
fieldPaths[strings.ToLower(name)] = path
1205
newCache := make(map[danger.TypeID]fieldPathsMap, len(cache)+1)
1206
newCache[danger.MakeTypeID(t)] = fieldPaths
1207
for k, v := range cache {
1210
globalFieldPathsCache.Store(newCache)
1213
path, ok := fieldPaths[name]
1215
path, ok = fieldPaths[strings.ToLower(name)]
1220
func forEachField(t reflect.Type, path []int, do func(name string, path []int)) {
1222
for i := 0; i < n; i++ {
1225
if !f.Anonymous && f.PkgPath != "" {
1226
// only consider exported fields.
1230
fieldPath := append(path, i)
1231
fieldPath = fieldPath[:len(fieldPath):len(fieldPath)]
1233
name := f.Tag.Get("toml")
1238
if i := strings.IndexByte(name, ','); i >= 0 {
1242
if f.Anonymous && name == "" {
1244
if t2.Kind() == reflect.Ptr {
1248
if t2.Kind() == reflect.Struct {
1249
forEachField(t2, fieldPath, do)