vendor/github.com/pelletier/go-toml/v2/unmarshaler.go
changeset 260 445e01aede7e
child 262 8d3354485fc3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vendor/github.com/pelletier/go-toml/v2/unmarshaler.go	Tue Aug 23 22:39:43 2022 +0200
@@ -0,0 +1,1205 @@
+package toml
+
+import (
+	"encoding"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"math"
+	"reflect"
+	"strings"
+	"sync/atomic"
+	"time"
+
+	"github.com/pelletier/go-toml/v2/internal/ast"
+	"github.com/pelletier/go-toml/v2/internal/danger"
+	"github.com/pelletier/go-toml/v2/internal/tracker"
+)
+
+// Unmarshal deserializes a TOML document into a Go value.
+//
+// It is a shortcut for Decoder.Decode() with the default options.
+func Unmarshal(data []byte, v interface{}) error {
+	p := parser{}
+	p.Reset(data)
+	d := decoder{p: &p}
+
+	return d.FromParser(v)
+}
+
+// Decoder reads and decode a TOML document from an input stream.
+type Decoder struct {
+	// input
+	r io.Reader
+
+	// global settings
+	strict bool
+}
+
+// NewDecoder creates a new Decoder that will read from r.
+func NewDecoder(r io.Reader) *Decoder {
+	return &Decoder{r: r}
+}
+
+// DisallowUnknownFields causes the Decoder to return an error when the
+// destination is a struct and the input contains a key that does not match a
+// non-ignored field.
+//
+// In that case, the Decoder returns a StrictMissingError that can be used to
+// retrieve the individual errors as well as generate a human readable
+// description of the missing fields.
+func (d *Decoder) DisallowUnknownFields() *Decoder {
+	d.strict = true
+	return d
+}
+
+// Decode the whole content of r into v.
+//
+// By default, values in the document that don't exist in the target Go value
+// are ignored. See Decoder.DisallowUnknownFields() to change this behavior.
+//
+// When a TOML local date, time, or date-time is decoded into a time.Time, its
+// value is represented in time.Local timezone. Otherwise the approriate Local*
+// structure is used. For time values, precision up to the nanosecond is
+// supported by truncating extra digits.
+//
+// Empty tables decoded in an interface{} create an empty initialized
+// map[string]interface{}.
+//
+// Types implementing the encoding.TextUnmarshaler interface are decoded from a
+// TOML string.
+//
+// When decoding a number, go-toml will return an error if the number is out of
+// bounds for the target type (which includes negative numbers when decoding
+// into an unsigned int).
+//
+// If an error occurs while decoding the content of the document, this function
+// returns a toml.DecodeError, providing context about the issue. When using
+// strict mode and a field is missing, a `toml.StrictMissingError` is
+// returned. In any other case, this function returns a standard Go error.
+//
+// # Type mapping
+//
+// List of supported TOML types and their associated accepted Go types:
+//
+//	String           -> string
+//	Integer          -> uint*, int*, depending on size
+//	Float            -> float*, depending on size
+//	Boolean          -> bool
+//	Offset Date-Time -> time.Time
+//	Local Date-time  -> LocalDateTime, time.Time
+//	Local Date       -> LocalDate, time.Time
+//	Local Time       -> LocalTime, time.Time
+//	Array            -> slice and array, depending on elements types
+//	Table            -> map and struct
+//	Inline Table     -> same as Table
+//	Array of Tables  -> same as Array and Table
+func (d *Decoder) Decode(v interface{}) error {
+	b, err := ioutil.ReadAll(d.r)
+	if err != nil {
+		return fmt.Errorf("toml: %w", err)
+	}
+
+	p := parser{}
+	p.Reset(b)
+	dec := decoder{
+		p: &p,
+		strict: strict{
+			Enabled: d.strict,
+		},
+	}
+
+	return dec.FromParser(v)
+}
+
+type decoder struct {
+	// Which parser instance in use for this decoding session.
+	p *parser
+
+	// Flag indicating that the current expression is stashed.
+	// If set to true, calling nextExpr will not actually pull a new expression
+	// but turn off the flag instead.
+	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
+	// need to be skipped.
+	skipUntilTable bool
+
+	// Tracks position in Go arrays.
+	// This is used when decoding [[array tables]] into Go arrays. Given array
+	// tables are separate TOML expression, we need to keep track of where we
+	// are at in the Go array, as we can't just introspect its size.
+	arrayIndexes map[reflect.Value]int
+
+	// Tracks keys that have been seen, with which type.
+	seen tracker.SeenTracker
+
+	// Strict mode
+	strict strict
+
+	// Current context for the error.
+	errorContext *errorContext
+}
+
+type errorContext struct {
+	Struct reflect.Type
+	Field  []int
+}
+
+func (d *decoder) typeMismatchError(toml string, target reflect.Type) error {
+	if d.errorContext != nil && d.errorContext.Struct != nil {
+		ctx := d.errorContext
+		f := ctx.Struct.FieldByIndex(ctx.Field)
+		return fmt.Errorf("toml: cannot decode TOML %s into struct field %s.%s of type %s", toml, ctx.Struct, f.Name, f.Type)
+	}
+	return fmt.Errorf("toml: cannot decode TOML %s into a Go value of type %s", toml, target)
+}
+
+func (d *decoder) expr() *ast.Node {
+	return d.p.Expression()
+}
+
+func (d *decoder) nextExpr() bool {
+	if d.stashedExpr {
+		d.stashedExpr = false
+		return true
+	}
+	return d.p.NextExpression()
+}
+
+func (d *decoder) stashExpr() {
+	d.stashedExpr = true
+}
+
+func (d *decoder) arrayIndex(shouldAppend bool, v reflect.Value) int {
+	if d.arrayIndexes == nil {
+		d.arrayIndexes = make(map[reflect.Value]int, 1)
+	}
+
+	idx, ok := d.arrayIndexes[v]
+
+	if !ok {
+		d.arrayIndexes[v] = 0
+	} else if shouldAppend {
+		idx++
+		d.arrayIndexes[v] = idx
+	}
+
+	return idx
+}
+
+func (d *decoder) FromParser(v interface{}) error {
+	r := reflect.ValueOf(v)
+	if r.Kind() != reflect.Ptr {
+		return fmt.Errorf("toml: decoding can only be performed into a pointer, not %s", r.Kind())
+	}
+
+	if r.IsNil() {
+		return fmt.Errorf("toml: decoding pointer target cannot be nil")
+	}
+
+	r = r.Elem()
+	if r.Kind() == reflect.Interface && r.IsNil() {
+		newMap := map[string]interface{}{}
+		r.Set(reflect.ValueOf(newMap))
+	}
+
+	err := d.fromParser(r)
+	if err == nil {
+		return d.strict.Error(d.p.data)
+	}
+
+	var e *decodeError
+	if errors.As(err, &e) {
+		return wrapDecodeError(d.p.data, e)
+	}
+
+	return err
+}
+
+func (d *decoder) fromParser(root reflect.Value) error {
+	for d.nextExpr() {
+		err := d.handleRootExpression(d.expr(), root)
+		if err != nil {
+			return err
+		}
+	}
+
+	return d.p.Error()
+}
+
+/*
+Rules for the unmarshal code:
+
+- The stack is used to keep track of which values need to be set where.
+- handle* functions <=> switch on a given ast.Kind.
+- unmarshalX* functions need to unmarshal a node of kind X.
+- An "object" is either a struct or a map.
+*/
+
+func (d *decoder) handleRootExpression(expr *ast.Node, v reflect.Value) error {
+	var x reflect.Value
+	var err error
+
+	if !(d.skipUntilTable && expr.Kind == ast.KeyValue) {
+		err = d.seen.CheckExpression(expr)
+		if err != nil {
+			return err
+		}
+	}
+
+	switch expr.Kind {
+	case ast.KeyValue:
+		if d.skipUntilTable {
+			return nil
+		}
+		x, err = d.handleKeyValue(expr, v)
+	case ast.Table:
+		d.skipUntilTable = false
+		d.strict.EnterTable(expr)
+		x, err = d.handleTable(expr.Key(), v)
+	case ast.ArrayTable:
+		d.skipUntilTable = false
+		d.strict.EnterArrayTable(expr)
+		x, err = d.handleArrayTable(expr.Key(), v)
+	default:
+		panic(fmt.Errorf("parser should not permit expression of kind %s at document root", expr.Kind))
+	}
+
+	if d.skipUntilTable {
+		if expr.Kind == ast.Table || expr.Kind == ast.ArrayTable {
+			d.strict.MissingTable(expr)
+		}
+	} else if err == nil && x.IsValid() {
+		v.Set(x)
+	}
+
+	return err
+}
+
+func (d *decoder) handleArrayTable(key ast.Iterator, v reflect.Value) (reflect.Value, error) {
+	if key.Next() {
+		return d.handleArrayTablePart(key, v)
+	}
+	return d.handleKeyValues(v)
+}
+
+func (d *decoder) handleArrayTableCollectionLast(key ast.Iterator, v reflect.Value) (reflect.Value, error) {
+	switch v.Kind() {
+	case reflect.Interface:
+		elem := v.Elem()
+		if !elem.IsValid() {
+			elem = reflect.New(sliceInterfaceType).Elem()
+			elem.Set(reflect.MakeSlice(sliceInterfaceType, 0, 16))
+		} else if elem.Kind() == reflect.Slice {
+			if elem.Type() != sliceInterfaceType {
+				elem = reflect.New(sliceInterfaceType).Elem()
+				elem.Set(reflect.MakeSlice(sliceInterfaceType, 0, 16))
+			} else if !elem.CanSet() {
+				nelem := reflect.New(sliceInterfaceType).Elem()
+				nelem.Set(reflect.MakeSlice(sliceInterfaceType, elem.Len(), elem.Cap()))
+				reflect.Copy(nelem, elem)
+				elem = nelem
+			}
+		}
+		return d.handleArrayTableCollectionLast(key, elem)
+	case reflect.Ptr:
+		elem := v.Elem()
+		if !elem.IsValid() {
+			ptr := reflect.New(v.Type().Elem())
+			v.Set(ptr)
+			elem = ptr.Elem()
+		}
+
+		elem, err := d.handleArrayTableCollectionLast(key, elem)
+		if err != nil {
+			return reflect.Value{}, err
+		}
+		v.Elem().Set(elem)
+
+		return v, nil
+	case reflect.Slice:
+		elemType := v.Type().Elem()
+		var elem reflect.Value
+		if elemType.Kind() == reflect.Interface {
+			elem = makeMapStringInterface()
+		} else {
+			elem = reflect.New(elemType).Elem()
+		}
+		elem2, err := d.handleArrayTable(key, elem)
+		if err != nil {
+			return reflect.Value{}, err
+		}
+		if elem2.IsValid() {
+			elem = elem2
+		}
+		return reflect.Append(v, elem), nil
+	case reflect.Array:
+		idx := d.arrayIndex(true, v)
+		if idx >= v.Len() {
+			return v, fmt.Errorf("toml: cannot decode array table into %s at position %d", v.Type(), idx)
+		}
+		elem := v.Index(idx)
+		_, err := d.handleArrayTable(key, elem)
+		return v, err
+	default:
+		return reflect.Value{}, fmt.Errorf("toml: cannot decode array table into a %s", v.Type())
+	}
+}
+
+// When parsing an array table expression, each part of the key needs to be
+// evaluated like a normal key, but if it returns a collection, it also needs to
+// point to the last element of the collection. Unless it is the last part of
+// the key, then it needs to create a new element at the end.
+func (d *decoder) handleArrayTableCollection(key ast.Iterator, v reflect.Value) (reflect.Value, error) {
+	if key.IsLast() {
+		return d.handleArrayTableCollectionLast(key, v)
+	}
+
+	switch v.Kind() {
+	case reflect.Ptr:
+		elem := v.Elem()
+		if !elem.IsValid() {
+			ptr := reflect.New(v.Type().Elem())
+			v.Set(ptr)
+			elem = ptr.Elem()
+		}
+
+		elem, err := d.handleArrayTableCollection(key, elem)
+		if err != nil {
+			return reflect.Value{}, err
+		}
+		if elem.IsValid() {
+			v.Elem().Set(elem)
+		}
+
+		return v, nil
+	case reflect.Slice:
+		elem := v.Index(v.Len() - 1)
+		x, err := d.handleArrayTable(key, elem)
+		if err != nil || d.skipUntilTable {
+			return reflect.Value{}, err
+		}
+		if x.IsValid() {
+			elem.Set(x)
+		}
+
+		return v, err
+	case reflect.Array:
+		idx := d.arrayIndex(false, v)
+		if idx >= v.Len() {
+			return v, fmt.Errorf("toml: cannot decode array table into %s at position %d", v.Type(), idx)
+		}
+		elem := v.Index(idx)
+		_, err := d.handleArrayTable(key, elem)
+		return v, err
+	}
+
+	return d.handleArrayTable(key, v)
+}
+
+func (d *decoder) handleKeyPart(key ast.Iterator, v reflect.Value, nextFn handlerFn, makeFn valueMakerFn) (reflect.Value, error) {
+	var rv reflect.Value
+
+	// First, dispatch over v to make sure it is a valid object.
+	// There is no guarantee over what it could be.
+	switch v.Kind() {
+	case reflect.Ptr:
+		elem := v.Elem()
+		if !elem.IsValid() {
+			v.Set(reflect.New(v.Type().Elem()))
+		}
+		elem = v.Elem()
+		return d.handleKeyPart(key, elem, nextFn, makeFn)
+	case reflect.Map:
+		vt := v.Type()
+
+		// Create the key for the map element. Convert to key type.
+		mk := reflect.ValueOf(string(key.Node().Data)).Convert(vt.Key())
+
+		// If the map does not exist, create it.
+		if v.IsNil() {
+			vt := v.Type()
+			v = reflect.MakeMap(vt)
+			rv = v
+		}
+
+		mv := v.MapIndex(mk)
+		set := false
+		if !mv.IsValid() {
+			// If there is no value in the map, create a new one according to
+			// the map type. If the element type is interface, create either a
+			// map[string]interface{} or a []interface{} depending on whether
+			// this is the last part of the array table key.
+
+			t := vt.Elem()
+			if t.Kind() == reflect.Interface {
+				mv = makeFn()
+			} else {
+				mv = reflect.New(t).Elem()
+			}
+			set = true
+		} else if mv.Kind() == reflect.Interface {
+			mv = mv.Elem()
+			if !mv.IsValid() {
+				mv = makeFn()
+			}
+			set = true
+		} else if !mv.CanAddr() {
+			vt := v.Type()
+			t := vt.Elem()
+			oldmv := mv
+			mv = reflect.New(t).Elem()
+			mv.Set(oldmv)
+			set = true
+		}
+
+		x, err := nextFn(key, mv)
+		if err != nil {
+			return reflect.Value{}, err
+		}
+
+		if x.IsValid() {
+			mv = x
+			set = true
+		}
+
+		if set {
+			v.SetMapIndex(mk, mv)
+		}
+	case reflect.Struct:
+		path, found := structFieldPath(v, string(key.Node().Data))
+		if !found {
+			d.skipUntilTable = true
+			return reflect.Value{}, nil
+		}
+
+		if d.errorContext == nil {
+			d.errorContext = new(errorContext)
+		}
+		t := v.Type()
+		d.errorContext.Struct = t
+		d.errorContext.Field = path
+
+		f := v.FieldByIndex(path)
+		x, err := nextFn(key, f)
+		if err != nil || d.skipUntilTable {
+			return reflect.Value{}, err
+		}
+		if x.IsValid() {
+			f.Set(x)
+		}
+		d.errorContext.Field = nil
+		d.errorContext.Struct = nil
+	case reflect.Interface:
+		if v.Elem().IsValid() {
+			v = v.Elem()
+		} else {
+			v = makeMapStringInterface()
+		}
+
+		x, err := d.handleKeyPart(key, v, nextFn, makeFn)
+		if err != nil {
+			return reflect.Value{}, err
+		}
+		if x.IsValid() {
+			v = x
+		}
+		rv = v
+	default:
+		panic(fmt.Errorf("unhandled part: %s", v.Kind()))
+	}
+
+	return rv, nil
+}
+
+// HandleArrayTablePart navigates the Go structure v using the key v. It is
+// only used for the prefix (non-last) parts of an array-table. When
+// encountering a collection, it should go to the last element.
+func (d *decoder) handleArrayTablePart(key ast.Iterator, v reflect.Value) (reflect.Value, error) {
+	var makeFn valueMakerFn
+	if key.IsLast() {
+		makeFn = makeSliceInterface
+	} else {
+		makeFn = makeMapStringInterface
+	}
+	return d.handleKeyPart(key, v, d.handleArrayTableCollection, makeFn)
+}
+
+// HandleTable returns a reference when it has checked the next expression but
+// cannot handle it.
+func (d *decoder) handleTable(key ast.Iterator, v reflect.Value) (reflect.Value, error) {
+	if v.Kind() == reflect.Slice {
+		if v.Len() == 0 {
+			return reflect.Value{}, newDecodeError(key.Node().Data, "cannot store a table in a slice")
+		}
+		elem := v.Index(v.Len() - 1)
+		x, err := d.handleTable(key, elem)
+		if err != nil {
+			return reflect.Value{}, err
+		}
+		if x.IsValid() {
+			elem.Set(x)
+		}
+		return reflect.Value{}, nil
+	}
+	if key.Next() {
+		// Still scoping the key
+		return d.handleTablePart(key, v)
+	}
+	// Done scoping the key.
+	// Now handle all the key-value expressions in this table.
+	return d.handleKeyValues(v)
+}
+
+// Handle root expressions until the end of the document or the next
+// non-key-value.
+func (d *decoder) handleKeyValues(v reflect.Value) (reflect.Value, error) {
+	var rv reflect.Value
+	for d.nextExpr() {
+		expr := d.expr()
+		if expr.Kind != ast.KeyValue {
+			// Stash the expression so that fromParser can just loop and use
+			// the right handler.
+			// We could just recurse ourselves here, but at least this gives a
+			// chance to pop the stack a bit.
+			d.stashExpr()
+			break
+		}
+
+		err := d.seen.CheckExpression(expr)
+		if err != nil {
+			return reflect.Value{}, err
+		}
+
+		x, err := d.handleKeyValue(expr, v)
+		if err != nil {
+			return reflect.Value{}, err
+		}
+		if x.IsValid() {
+			v = x
+			rv = x
+		}
+	}
+	return rv, nil
+}
+
+type (
+	handlerFn    func(key ast.Iterator, v reflect.Value) (reflect.Value, error)
+	valueMakerFn func() reflect.Value
+)
+
+func makeMapStringInterface() reflect.Value {
+	return reflect.MakeMap(mapStringInterfaceType)
+}
+
+func makeSliceInterface() reflect.Value {
+	return reflect.MakeSlice(sliceInterfaceType, 0, 16)
+}
+
+func (d *decoder) handleTablePart(key ast.Iterator, v reflect.Value) (reflect.Value, error) {
+	return d.handleKeyPart(key, v, d.handleTable, makeMapStringInterface)
+}
+
+func (d *decoder) tryTextUnmarshaler(node *ast.Node, v reflect.Value) (bool, error) {
+	// Special case for time, because we allow to unmarshal to it from
+	// different kind of AST nodes.
+	if v.Type() == timeType {
+		return false, nil
+	}
+
+	if v.CanAddr() && v.Addr().Type().Implements(textUnmarshalerType) {
+		err := v.Addr().Interface().(encoding.TextUnmarshaler).UnmarshalText(node.Data)
+		if err != nil {
+			return false, newDecodeError(d.p.Raw(node.Raw), "%w", err)
+		}
+
+		return true, nil
+	}
+
+	return false, nil
+}
+
+func (d *decoder) handleValue(value *ast.Node, v reflect.Value) error {
+	for v.Kind() == reflect.Ptr {
+		v = initAndDereferencePointer(v)
+	}
+
+	ok, err := d.tryTextUnmarshaler(value, v)
+	if ok || err != nil {
+		return err
+	}
+
+	switch value.Kind {
+	case ast.String:
+		return d.unmarshalString(value, v)
+	case ast.Integer:
+		return d.unmarshalInteger(value, v)
+	case ast.Float:
+		return d.unmarshalFloat(value, v)
+	case ast.Bool:
+		return d.unmarshalBool(value, v)
+	case ast.DateTime:
+		return d.unmarshalDateTime(value, v)
+	case ast.LocalDate:
+		return d.unmarshalLocalDate(value, v)
+	case ast.LocalTime:
+		return d.unmarshalLocalTime(value, v)
+	case ast.LocalDateTime:
+		return d.unmarshalLocalDateTime(value, v)
+	case ast.InlineTable:
+		return d.unmarshalInlineTable(value, v)
+	case ast.Array:
+		return d.unmarshalArray(value, v)
+	default:
+		panic(fmt.Errorf("handleValue not implemented for %s", value.Kind))
+	}
+}
+
+func (d *decoder) unmarshalArray(array *ast.Node, v reflect.Value) error {
+	switch v.Kind() {
+	case reflect.Slice:
+		if v.IsNil() {
+			v.Set(reflect.MakeSlice(v.Type(), 0, 16))
+		} else {
+			v.SetLen(0)
+		}
+	case reflect.Array:
+		// arrays are always initialized
+	case reflect.Interface:
+		elem := v.Elem()
+		if !elem.IsValid() {
+			elem = reflect.New(sliceInterfaceType).Elem()
+			elem.Set(reflect.MakeSlice(sliceInterfaceType, 0, 16))
+		} else if elem.Kind() == reflect.Slice {
+			if elem.Type() != sliceInterfaceType {
+				elem = reflect.New(sliceInterfaceType).Elem()
+				elem.Set(reflect.MakeSlice(sliceInterfaceType, 0, 16))
+			} else if !elem.CanSet() {
+				nelem := reflect.New(sliceInterfaceType).Elem()
+				nelem.Set(reflect.MakeSlice(sliceInterfaceType, elem.Len(), elem.Cap()))
+				reflect.Copy(nelem, elem)
+				elem = nelem
+			}
+		}
+		err := d.unmarshalArray(array, elem)
+		if err != nil {
+			return err
+		}
+		v.Set(elem)
+		return nil
+	default:
+		// TODO: use newDecodeError, but first the parser needs to fill
+		//   array.Data.
+		return d.typeMismatchError("array", v.Type())
+	}
+
+	elemType := v.Type().Elem()
+
+	it := array.Children()
+	idx := 0
+	for it.Next() {
+		n := it.Node()
+
+		// TODO: optimize
+		if v.Kind() == reflect.Slice {
+			elem := reflect.New(elemType).Elem()
+
+			err := d.handleValue(n, elem)
+			if err != nil {
+				return err
+			}
+
+			v.Set(reflect.Append(v, elem))
+		} else { // array
+			if idx >= v.Len() {
+				return nil
+			}
+			elem := v.Index(idx)
+			err := d.handleValue(n, elem)
+			if err != nil {
+				return err
+			}
+			idx++
+		}
+	}
+
+	return nil
+}
+
+func (d *decoder) unmarshalInlineTable(itable *ast.Node, v reflect.Value) error {
+	// Make sure v is an initialized object.
+	switch v.Kind() {
+	case reflect.Map:
+		if v.IsNil() {
+			v.Set(reflect.MakeMap(v.Type()))
+		}
+	case reflect.Struct:
+	// structs are always initialized.
+	case reflect.Interface:
+		elem := v.Elem()
+		if !elem.IsValid() {
+			elem = makeMapStringInterface()
+			v.Set(elem)
+		}
+		return d.unmarshalInlineTable(itable, elem)
+	default:
+		return newDecodeError(itable.Data, "cannot store inline table in Go type %s", v.Kind())
+	}
+
+	it := itable.Children()
+	for it.Next() {
+		n := it.Node()
+
+		x, err := d.handleKeyValue(n, v)
+		if err != nil {
+			return err
+		}
+		if x.IsValid() {
+			v = x
+		}
+	}
+
+	return nil
+}
+
+func (d *decoder) unmarshalDateTime(value *ast.Node, v reflect.Value) error {
+	dt, err := parseDateTime(value.Data)
+	if err != nil {
+		return err
+	}
+
+	v.Set(reflect.ValueOf(dt))
+	return nil
+}
+
+func (d *decoder) unmarshalLocalDate(value *ast.Node, v reflect.Value) error {
+	ld, err := parseLocalDate(value.Data)
+	if err != nil {
+		return err
+	}
+
+	if v.Type() == timeType {
+		cast := ld.AsTime(time.Local)
+		v.Set(reflect.ValueOf(cast))
+		return nil
+	}
+
+	v.Set(reflect.ValueOf(ld))
+
+	return nil
+}
+
+func (d *decoder) unmarshalLocalTime(value *ast.Node, v reflect.Value) error {
+	lt, rest, err := parseLocalTime(value.Data)
+	if err != nil {
+		return err
+	}
+
+	if len(rest) > 0 {
+		return newDecodeError(rest, "extra characters at the end of a local time")
+	}
+
+	v.Set(reflect.ValueOf(lt))
+	return nil
+}
+
+func (d *decoder) unmarshalLocalDateTime(value *ast.Node, v reflect.Value) error {
+	ldt, rest, err := parseLocalDateTime(value.Data)
+	if err != nil {
+		return err
+	}
+
+	if len(rest) > 0 {
+		return newDecodeError(rest, "extra characters at the end of a local date time")
+	}
+
+	if v.Type() == timeType {
+		cast := ldt.AsTime(time.Local)
+
+		v.Set(reflect.ValueOf(cast))
+		return nil
+	}
+
+	v.Set(reflect.ValueOf(ldt))
+
+	return nil
+}
+
+func (d *decoder) unmarshalBool(value *ast.Node, v reflect.Value) error {
+	b := value.Data[0] == 't'
+
+	switch v.Kind() {
+	case reflect.Bool:
+		v.SetBool(b)
+	case reflect.Interface:
+		v.Set(reflect.ValueOf(b))
+	default:
+		return newDecodeError(value.Data, "cannot assign boolean to a %t", b)
+	}
+
+	return nil
+}
+
+func (d *decoder) unmarshalFloat(value *ast.Node, v reflect.Value) error {
+	f, err := parseFloat(value.Data)
+	if err != nil {
+		return err
+	}
+
+	switch v.Kind() {
+	case reflect.Float64:
+		v.SetFloat(f)
+	case reflect.Float32:
+		if f > math.MaxFloat32 {
+			return newDecodeError(value.Data, "number %f does not fit in a float32", f)
+		}
+		v.SetFloat(f)
+	case reflect.Interface:
+		v.Set(reflect.ValueOf(f))
+	default:
+		return newDecodeError(value.Data, "float cannot be assigned to %s", v.Kind())
+	}
+
+	return nil
+}
+
+const (
+	maxInt = int64(^uint(0) >> 1)
+	minInt = -maxInt - 1
+)
+
+// Maximum value of uint for decoding. Currently the decoder parses the integer
+// into an int64. As a result, on architectures where uint is 64 bits, the
+// effective maximum uint we can decode is the maximum of int64. On
+// architectures where uint is 32 bits, the maximum value we can decode is
+// lower: the maximum of uint32. I didn't find a way to figure out this value at
+// compile time, so it is computed during initialization.
+var maxUint int64 = math.MaxInt64
+
+func init() {
+	m := uint64(^uint(0))
+	if m < uint64(maxUint) {
+		maxUint = int64(m)
+	}
+}
+
+func (d *decoder) unmarshalInteger(value *ast.Node, v reflect.Value) error {
+	i, err := parseInteger(value.Data)
+	if err != nil {
+		return err
+	}
+
+	var r reflect.Value
+
+	switch v.Kind() {
+	case reflect.Int64:
+		v.SetInt(i)
+		return nil
+	case reflect.Int32:
+		if i < math.MinInt32 || i > math.MaxInt32 {
+			return fmt.Errorf("toml: number %d does not fit in an int32", i)
+		}
+
+		r = reflect.ValueOf(int32(i))
+	case reflect.Int16:
+		if i < math.MinInt16 || i > math.MaxInt16 {
+			return fmt.Errorf("toml: number %d does not fit in an int16", i)
+		}
+
+		r = reflect.ValueOf(int16(i))
+	case reflect.Int8:
+		if i < math.MinInt8 || i > math.MaxInt8 {
+			return fmt.Errorf("toml: number %d does not fit in an int8", i)
+		}
+
+		r = reflect.ValueOf(int8(i))
+	case reflect.Int:
+		if i < minInt || i > maxInt {
+			return fmt.Errorf("toml: number %d does not fit in an int", i)
+		}
+
+		r = reflect.ValueOf(int(i))
+	case reflect.Uint64:
+		if i < 0 {
+			return fmt.Errorf("toml: negative number %d does not fit in an uint64", i)
+		}
+
+		r = reflect.ValueOf(uint64(i))
+	case reflect.Uint32:
+		if i < 0 || i > math.MaxUint32 {
+			return fmt.Errorf("toml: negative number %d does not fit in an uint32", i)
+		}
+
+		r = reflect.ValueOf(uint32(i))
+	case reflect.Uint16:
+		if i < 0 || i > math.MaxUint16 {
+			return fmt.Errorf("toml: negative number %d does not fit in an uint16", i)
+		}
+
+		r = reflect.ValueOf(uint16(i))
+	case reflect.Uint8:
+		if i < 0 || i > math.MaxUint8 {
+			return fmt.Errorf("toml: negative number %d does not fit in an uint8", i)
+		}
+
+		r = reflect.ValueOf(uint8(i))
+	case reflect.Uint:
+		if i < 0 || i > maxUint {
+			return fmt.Errorf("toml: negative number %d does not fit in an uint", i)
+		}
+
+		r = reflect.ValueOf(uint(i))
+	case reflect.Interface:
+		r = reflect.ValueOf(i)
+	default:
+		return d.typeMismatchError("integer", v.Type())
+	}
+
+	if !r.Type().AssignableTo(v.Type()) {
+		r = r.Convert(v.Type())
+	}
+
+	v.Set(r)
+
+	return nil
+}
+
+func (d *decoder) unmarshalString(value *ast.Node, v reflect.Value) error {
+	switch v.Kind() {
+	case reflect.String:
+		v.SetString(string(value.Data))
+	case reflect.Interface:
+		v.Set(reflect.ValueOf(string(value.Data)))
+	default:
+		return newDecodeError(d.p.Raw(value.Raw), "cannot store TOML string into a Go %s", v.Kind())
+	}
+
+	return nil
+}
+
+func (d *decoder) handleKeyValue(expr *ast.Node, v reflect.Value) (reflect.Value, error) {
+	d.strict.EnterKeyValue(expr)
+
+	v, err := d.handleKeyValueInner(expr.Key(), expr.Value(), v)
+	if d.skipUntilTable {
+		d.strict.MissingField(expr)
+		d.skipUntilTable = false
+	}
+
+	d.strict.ExitKeyValue(expr)
+
+	return v, err
+}
+
+func (d *decoder) handleKeyValueInner(key ast.Iterator, value *ast.Node, v reflect.Value) (reflect.Value, error) {
+	if key.Next() {
+		// Still scoping the key
+		return d.handleKeyValuePart(key, value, v)
+	}
+	// Done scoping the key.
+	// v is whatever Go value we need to fill.
+	return reflect.Value{}, d.handleValue(value, v)
+}
+
+func (d *decoder) handleKeyValuePart(key ast.Iterator, value *ast.Node, v reflect.Value) (reflect.Value, error) {
+	// contains the replacement for v
+	var rv reflect.Value
+
+	// First, dispatch over v to make sure it is a valid object.
+	// There is no guarantee over what it could be.
+	switch v.Kind() {
+	case reflect.Map:
+		vt := v.Type()
+
+		mk := reflect.ValueOf(string(key.Node().Data))
+		mkt := stringType
+
+		keyType := vt.Key()
+		if !mkt.AssignableTo(keyType) {
+			if !mkt.ConvertibleTo(keyType) {
+				return reflect.Value{}, fmt.Errorf("toml: cannot convert map key of type %s to expected type %s", mkt, keyType)
+			}
+
+			mk = mk.Convert(keyType)
+		}
+
+		// If the map does not exist, create it.
+		if v.IsNil() {
+			v = reflect.MakeMap(vt)
+			rv = v
+		}
+
+		mv := v.MapIndex(mk)
+		set := false
+		if !mv.IsValid() {
+			set = true
+			mv = reflect.New(v.Type().Elem()).Elem()
+		} else {
+			if key.IsLast() {
+				var x interface{}
+				mv = reflect.ValueOf(&x).Elem()
+				set = true
+			}
+		}
+
+		nv, err := d.handleKeyValueInner(key, value, mv)
+		if err != nil {
+			return reflect.Value{}, err
+		}
+		if nv.IsValid() {
+			mv = nv
+			set = true
+		}
+
+		if set {
+			v.SetMapIndex(mk, mv)
+		}
+	case reflect.Struct:
+		path, found := structFieldPath(v, string(key.Node().Data))
+		if !found {
+			d.skipUntilTable = true
+			break
+		}
+
+		if d.errorContext == nil {
+			d.errorContext = new(errorContext)
+		}
+		t := v.Type()
+		d.errorContext.Struct = t
+		d.errorContext.Field = path
+
+		f := v.FieldByIndex(path)
+		x, err := d.handleKeyValueInner(key, value, f)
+		if err != nil {
+			return reflect.Value{}, err
+		}
+
+		if x.IsValid() {
+			f.Set(x)
+		}
+		d.errorContext.Struct = nil
+		d.errorContext.Field = nil
+	case reflect.Interface:
+		v = v.Elem()
+
+		// Following encoding/json: decoding an object into an
+		// interface{}, it needs to always hold a
+		// map[string]interface{}. This is for the types to be
+		// consistent whether a previous value was set or not.
+		if !v.IsValid() || v.Type() != mapStringInterfaceType {
+			v = makeMapStringInterface()
+		}
+
+		x, err := d.handleKeyValuePart(key, value, v)
+		if err != nil {
+			return reflect.Value{}, err
+		}
+		if x.IsValid() {
+			v = x
+		}
+		rv = v
+	case reflect.Ptr:
+		elem := v.Elem()
+		if !elem.IsValid() {
+			ptr := reflect.New(v.Type().Elem())
+			v.Set(ptr)
+			rv = v
+			elem = ptr.Elem()
+		}
+
+		elem2, err := d.handleKeyValuePart(key, value, elem)
+		if err != nil {
+			return reflect.Value{}, err
+		}
+		if elem2.IsValid() {
+			elem = elem2
+		}
+		v.Elem().Set(elem)
+	default:
+		return reflect.Value{}, fmt.Errorf("unhandled kv part: %s", v.Kind())
+	}
+
+	return rv, nil
+}
+
+func initAndDereferencePointer(v reflect.Value) reflect.Value {
+	var elem reflect.Value
+	if v.IsNil() {
+		ptr := reflect.New(v.Type().Elem())
+		v.Set(ptr)
+	}
+	elem = v.Elem()
+	return elem
+}
+
+type fieldPathsMap = map[string][]int
+
+var globalFieldPathsCache atomic.Value // map[danger.TypeID]fieldPathsMap
+
+func structFieldPath(v reflect.Value, name string) ([]int, bool) {
+	t := v.Type()
+
+	cache, _ := globalFieldPathsCache.Load().(map[danger.TypeID]fieldPathsMap)
+	fieldPaths, ok := cache[danger.MakeTypeID(t)]
+
+	if !ok {
+		fieldPaths = map[string][]int{}
+
+		forEachField(t, nil, func(name string, path []int) {
+			fieldPaths[name] = path
+			// extra copy for the case-insensitive match
+			fieldPaths[strings.ToLower(name)] = path
+		})
+
+		newCache := make(map[danger.TypeID]fieldPathsMap, len(cache)+1)
+		newCache[danger.MakeTypeID(t)] = fieldPaths
+		for k, v := range cache {
+			newCache[k] = v
+		}
+		globalFieldPathsCache.Store(newCache)
+	}
+
+	path, ok := fieldPaths[name]
+	if !ok {
+		path, ok = fieldPaths[strings.ToLower(name)]
+	}
+	return path, ok
+}
+
+func forEachField(t reflect.Type, path []int, do func(name string, path []int)) {
+	n := t.NumField()
+	for i := 0; i < n; i++ {
+		f := t.Field(i)
+
+		if !f.Anonymous && f.PkgPath != "" {
+			// only consider exported fields.
+			continue
+		}
+
+		fieldPath := append(path, i)
+		fieldPath = fieldPath[:len(fieldPath):len(fieldPath)]
+
+		name := f.Tag.Get("toml")
+		if name == "-" {
+			continue
+		}
+
+		if i := strings.IndexByte(name, ','); i >= 0 {
+			name = name[:i]
+		}
+
+		if f.Anonymous && name == "" {
+			forEachField(f.Type, fieldPath, do)
+			continue
+		}
+
+		if name == "" {
+			name = f.Name
+		}
+
+		do(name, fieldPath)
+	}
+}