Path: blob/main/vendor/github.com/pelletier/go-toml/v2/unmarshaler.go
2880 views
package toml12import (3"encoding"4"errors"5"fmt"6"io"7"math"8"reflect"9"strconv"10"strings"11"sync/atomic"12"time"1314"github.com/pelletier/go-toml/v2/internal/danger"15"github.com/pelletier/go-toml/v2/internal/tracker"16"github.com/pelletier/go-toml/v2/unstable"17)1819// Unmarshal deserializes a TOML document into a Go value.20//21// It is a shortcut for Decoder.Decode() with the default options.22func Unmarshal(data []byte, v interface{}) error {23d := decoder{}24d.p.Reset(data)25return d.FromParser(v)26}2728// Decoder reads and decode a TOML document from an input stream.29type Decoder struct {30// input31r io.Reader3233// global settings34strict bool3536// toggles unmarshaler interface37unmarshalerInterface bool38}3940// NewDecoder creates a new Decoder that will read from r.41func NewDecoder(r io.Reader) *Decoder {42return &Decoder{r: r}43}4445// DisallowUnknownFields causes the Decoder to return an error when the46// destination is a struct and the input contains a key that does not match a47// non-ignored field.48//49// In that case, the Decoder returns a StrictMissingError that can be used to50// retrieve the individual errors as well as generate a human readable51// description of the missing fields.52func (d *Decoder) DisallowUnknownFields() *Decoder {53d.strict = true54return d55}5657// EnableUnmarshalerInterface allows to enable unmarshaler interface.58//59// With this feature enabled, types implementing the unstable/Unmarshaler60// interface can be decoded from any structure of the document. It allows types61// that don't have a straightforward TOML representation to provide their own62// decoding logic.63//64// Currently, types can only decode from a single value. Tables and array tables65// are not supported.66//67// *Unstable:* This method does not follow the compatibility guarantees of68// semver. It can be changed or removed without a new major version being69// issued.70func (d *Decoder) EnableUnmarshalerInterface() *Decoder {71d.unmarshalerInterface = true72return d73}7475// Decode the whole content of r into v.76//77// By default, values in the document that don't exist in the target Go value78// are ignored. See Decoder.DisallowUnknownFields() to change this behavior.79//80// When a TOML local date, time, or date-time is decoded into a time.Time, its81// value is represented in time.Local timezone. Otherwise the appropriate Local*82// structure is used. For time values, precision up to the nanosecond is83// supported by truncating extra digits.84//85// Empty tables decoded in an interface{} create an empty initialized86// map[string]interface{}.87//88// Types implementing the encoding.TextUnmarshaler interface are decoded from a89// TOML string.90//91// When decoding a number, go-toml will return an error if the number is out of92// bounds for the target type (which includes negative numbers when decoding93// into an unsigned int).94//95// If an error occurs while decoding the content of the document, this function96// returns a toml.DecodeError, providing context about the issue. When using97// strict mode and a field is missing, a `toml.StrictMissingError` is98// returned. In any other case, this function returns a standard Go error.99//100// # Type mapping101//102// List of supported TOML types and their associated accepted Go types:103//104// String -> string105// Integer -> uint*, int*, depending on size106// Float -> float*, depending on size107// Boolean -> bool108// Offset Date-Time -> time.Time109// Local Date-time -> LocalDateTime, time.Time110// Local Date -> LocalDate, time.Time111// Local Time -> LocalTime, time.Time112// Array -> slice and array, depending on elements types113// Table -> map and struct114// Inline Table -> same as Table115// Array of Tables -> same as Array and Table116func (d *Decoder) Decode(v interface{}) error {117b, err := io.ReadAll(d.r)118if err != nil {119return fmt.Errorf("toml: %w", err)120}121122dec := decoder{123strict: strict{124Enabled: d.strict,125},126unmarshalerInterface: d.unmarshalerInterface,127}128dec.p.Reset(b)129130return dec.FromParser(v)131}132133type decoder struct {134// Which parser instance in use for this decoding session.135p unstable.Parser136137// Flag indicating that the current expression is stashed.138// If set to true, calling nextExpr will not actually pull a new expression139// but turn off the flag instead.140stashedExpr bool141142// Skip expressions until a table is found. This is set to true when a143// table could not be created (missing field in map), so all KV expressions144// need to be skipped.145skipUntilTable bool146147// Flag indicating that the current array/slice table should be cleared because148// it is the first encounter of an array table.149clearArrayTable bool150151// Tracks position in Go arrays.152// This is used when decoding [[array tables]] into Go arrays. Given array153// tables are separate TOML expression, we need to keep track of where we154// are at in the Go array, as we can't just introspect its size.155arrayIndexes map[reflect.Value]int156157// Tracks keys that have been seen, with which type.158seen tracker.SeenTracker159160// Strict mode161strict strict162163// Flag that enables/disables unmarshaler interface.164unmarshalerInterface bool165166// Current context for the error.167errorContext *errorContext168}169170type errorContext struct {171Struct reflect.Type172Field []int173}174175func (d *decoder) typeMismatchError(toml string, target reflect.Type) error {176return fmt.Errorf("toml: %s", d.typeMismatchString(toml, target))177}178179func (d *decoder) typeMismatchString(toml string, target reflect.Type) string {180if d.errorContext != nil && d.errorContext.Struct != nil {181ctx := d.errorContext182f := ctx.Struct.FieldByIndex(ctx.Field)183return fmt.Sprintf("cannot decode TOML %s into struct field %s.%s of type %s", toml, ctx.Struct, f.Name, f.Type)184}185return fmt.Sprintf("cannot decode TOML %s into a Go value of type %s", toml, target)186}187188func (d *decoder) expr() *unstable.Node {189return d.p.Expression()190}191192func (d *decoder) nextExpr() bool {193if d.stashedExpr {194d.stashedExpr = false195return true196}197return d.p.NextExpression()198}199200func (d *decoder) stashExpr() {201d.stashedExpr = true202}203204func (d *decoder) arrayIndex(shouldAppend bool, v reflect.Value) int {205if d.arrayIndexes == nil {206d.arrayIndexes = make(map[reflect.Value]int, 1)207}208209idx, ok := d.arrayIndexes[v]210211if !ok {212d.arrayIndexes[v] = 0213} else if shouldAppend {214idx++215d.arrayIndexes[v] = idx216}217218return idx219}220221func (d *decoder) FromParser(v interface{}) error {222r := reflect.ValueOf(v)223if r.Kind() != reflect.Ptr {224return fmt.Errorf("toml: decoding can only be performed into a pointer, not %s", r.Kind())225}226227if r.IsNil() {228return fmt.Errorf("toml: decoding pointer target cannot be nil")229}230231r = r.Elem()232if r.Kind() == reflect.Interface && r.IsNil() {233newMap := map[string]interface{}{}234r.Set(reflect.ValueOf(newMap))235}236237err := d.fromParser(r)238if err == nil {239return d.strict.Error(d.p.Data())240}241242var e *unstable.ParserError243if errors.As(err, &e) {244return wrapDecodeError(d.p.Data(), e)245}246247return err248}249250func (d *decoder) fromParser(root reflect.Value) error {251for d.nextExpr() {252err := d.handleRootExpression(d.expr(), root)253if err != nil {254return err255}256}257258return d.p.Error()259}260261/*262Rules for the unmarshal code:263264- The stack is used to keep track of which values need to be set where.265- handle* functions <=> switch on a given unstable.Kind.266- unmarshalX* functions need to unmarshal a node of kind X.267- An "object" is either a struct or a map.268*/269270func (d *decoder) handleRootExpression(expr *unstable.Node, v reflect.Value) error {271var x reflect.Value272var err error273var first bool // used for to clear array tables on first use274275if !(d.skipUntilTable && expr.Kind == unstable.KeyValue) {276first, err = d.seen.CheckExpression(expr)277if err != nil {278return err279}280}281282switch expr.Kind {283case unstable.KeyValue:284if d.skipUntilTable {285return nil286}287x, err = d.handleKeyValue(expr, v)288case unstable.Table:289d.skipUntilTable = false290d.strict.EnterTable(expr)291x, err = d.handleTable(expr.Key(), v)292case unstable.ArrayTable:293d.skipUntilTable = false294d.strict.EnterArrayTable(expr)295d.clearArrayTable = first296x, err = d.handleArrayTable(expr.Key(), v)297default:298panic(fmt.Errorf("parser should not permit expression of kind %s at document root", expr.Kind))299}300301if d.skipUntilTable {302if expr.Kind == unstable.Table || expr.Kind == unstable.ArrayTable {303d.strict.MissingTable(expr)304}305} else if err == nil && x.IsValid() {306v.Set(x)307}308309return err310}311312func (d *decoder) handleArrayTable(key unstable.Iterator, v reflect.Value) (reflect.Value, error) {313if key.Next() {314return d.handleArrayTablePart(key, v)315}316return d.handleKeyValues(v)317}318319func (d *decoder) handleArrayTableCollectionLast(key unstable.Iterator, v reflect.Value) (reflect.Value, error) {320switch v.Kind() {321case reflect.Interface:322elem := v.Elem()323if !elem.IsValid() {324elem = reflect.New(sliceInterfaceType).Elem()325elem.Set(reflect.MakeSlice(sliceInterfaceType, 0, 16))326} else if elem.Kind() == reflect.Slice {327if elem.Type() != sliceInterfaceType {328elem = reflect.New(sliceInterfaceType).Elem()329elem.Set(reflect.MakeSlice(sliceInterfaceType, 0, 16))330} else if !elem.CanSet() {331nelem := reflect.New(sliceInterfaceType).Elem()332nelem.Set(reflect.MakeSlice(sliceInterfaceType, elem.Len(), elem.Cap()))333reflect.Copy(nelem, elem)334elem = nelem335}336if d.clearArrayTable && elem.Len() > 0 {337elem.SetLen(0)338d.clearArrayTable = false339}340}341return d.handleArrayTableCollectionLast(key, elem)342case reflect.Ptr:343elem := v.Elem()344if !elem.IsValid() {345ptr := reflect.New(v.Type().Elem())346v.Set(ptr)347elem = ptr.Elem()348}349350elem, err := d.handleArrayTableCollectionLast(key, elem)351if err != nil {352return reflect.Value{}, err353}354v.Elem().Set(elem)355356return v, nil357case reflect.Slice:358if d.clearArrayTable && v.Len() > 0 {359v.SetLen(0)360d.clearArrayTable = false361}362elemType := v.Type().Elem()363var elem reflect.Value364if elemType.Kind() == reflect.Interface {365elem = makeMapStringInterface()366} else {367elem = reflect.New(elemType).Elem()368}369elem2, err := d.handleArrayTable(key, elem)370if err != nil {371return reflect.Value{}, err372}373if elem2.IsValid() {374elem = elem2375}376return reflect.Append(v, elem), nil377case reflect.Array:378idx := d.arrayIndex(true, v)379if idx >= v.Len() {380return v, fmt.Errorf("%s at position %d", d.typeMismatchError("array table", v.Type()), idx)381}382elem := v.Index(idx)383_, err := d.handleArrayTable(key, elem)384return v, err385default:386return reflect.Value{}, d.typeMismatchError("array table", v.Type())387}388}389390// When parsing an array table expression, each part of the key needs to be391// evaluated like a normal key, but if it returns a collection, it also needs to392// point to the last element of the collection. Unless it is the last part of393// the key, then it needs to create a new element at the end.394func (d *decoder) handleArrayTableCollection(key unstable.Iterator, v reflect.Value) (reflect.Value, error) {395if key.IsLast() {396return d.handleArrayTableCollectionLast(key, v)397}398399switch v.Kind() {400case reflect.Ptr:401elem := v.Elem()402if !elem.IsValid() {403ptr := reflect.New(v.Type().Elem())404v.Set(ptr)405elem = ptr.Elem()406}407408elem, err := d.handleArrayTableCollection(key, elem)409if err != nil {410return reflect.Value{}, err411}412if elem.IsValid() {413v.Elem().Set(elem)414}415416return v, nil417case reflect.Slice:418elem := v.Index(v.Len() - 1)419x, err := d.handleArrayTable(key, elem)420if err != nil || d.skipUntilTable {421return reflect.Value{}, err422}423if x.IsValid() {424elem.Set(x)425}426427return v, err428case reflect.Array:429idx := d.arrayIndex(false, v)430if idx >= v.Len() {431return v, fmt.Errorf("%s at position %d", d.typeMismatchError("array table", v.Type()), idx)432}433elem := v.Index(idx)434_, err := d.handleArrayTable(key, elem)435return v, err436}437438return d.handleArrayTable(key, v)439}440441func (d *decoder) handleKeyPart(key unstable.Iterator, v reflect.Value, nextFn handlerFn, makeFn valueMakerFn) (reflect.Value, error) {442var rv reflect.Value443444// First, dispatch over v to make sure it is a valid object.445// There is no guarantee over what it could be.446switch v.Kind() {447case reflect.Ptr:448elem := v.Elem()449if !elem.IsValid() {450v.Set(reflect.New(v.Type().Elem()))451}452elem = v.Elem()453return d.handleKeyPart(key, elem, nextFn, makeFn)454case reflect.Map:455vt := v.Type()456457// Create the key for the map element. Convert to key type.458mk, err := d.keyFromData(vt.Key(), key.Node().Data)459if err != nil {460return reflect.Value{}, err461}462463// If the map does not exist, create it.464if v.IsNil() {465vt := v.Type()466v = reflect.MakeMap(vt)467rv = v468}469470mv := v.MapIndex(mk)471set := false472if !mv.IsValid() {473// If there is no value in the map, create a new one according to474// the map type. If the element type is interface, create either a475// map[string]interface{} or a []interface{} depending on whether476// this is the last part of the array table key.477478t := vt.Elem()479if t.Kind() == reflect.Interface {480mv = makeFn()481} else {482mv = reflect.New(t).Elem()483}484set = true485} else if mv.Kind() == reflect.Interface {486mv = mv.Elem()487if !mv.IsValid() {488mv = makeFn()489}490set = true491} else if !mv.CanAddr() {492vt := v.Type()493t := vt.Elem()494oldmv := mv495mv = reflect.New(t).Elem()496mv.Set(oldmv)497set = true498}499500x, err := nextFn(key, mv)501if err != nil {502return reflect.Value{}, err503}504505if x.IsValid() {506mv = x507set = true508}509510if set {511v.SetMapIndex(mk, mv)512}513case reflect.Struct:514path, found := structFieldPath(v, string(key.Node().Data))515if !found {516d.skipUntilTable = true517return reflect.Value{}, nil518}519520if d.errorContext == nil {521d.errorContext = new(errorContext)522}523t := v.Type()524d.errorContext.Struct = t525d.errorContext.Field = path526527f := fieldByIndex(v, path)528x, err := nextFn(key, f)529if err != nil || d.skipUntilTable {530return reflect.Value{}, err531}532if x.IsValid() {533f.Set(x)534}535d.errorContext.Field = nil536d.errorContext.Struct = nil537case reflect.Interface:538if v.Elem().IsValid() {539v = v.Elem()540} else {541v = makeMapStringInterface()542}543544x, err := d.handleKeyPart(key, v, nextFn, makeFn)545if err != nil {546return reflect.Value{}, err547}548if x.IsValid() {549v = x550}551rv = v552default:553panic(fmt.Errorf("unhandled part: %s", v.Kind()))554}555556return rv, nil557}558559// HandleArrayTablePart navigates the Go structure v using the key v. It is560// only used for the prefix (non-last) parts of an array-table. When561// encountering a collection, it should go to the last element.562func (d *decoder) handleArrayTablePart(key unstable.Iterator, v reflect.Value) (reflect.Value, error) {563var makeFn valueMakerFn564if key.IsLast() {565makeFn = makeSliceInterface566} else {567makeFn = makeMapStringInterface568}569return d.handleKeyPart(key, v, d.handleArrayTableCollection, makeFn)570}571572// HandleTable returns a reference when it has checked the next expression but573// cannot handle it.574func (d *decoder) handleTable(key unstable.Iterator, v reflect.Value) (reflect.Value, error) {575if v.Kind() == reflect.Slice {576if v.Len() == 0 {577return reflect.Value{}, unstable.NewParserError(key.Node().Data, "cannot store a table in a slice")578}579elem := v.Index(v.Len() - 1)580x, err := d.handleTable(key, elem)581if err != nil {582return reflect.Value{}, err583}584if x.IsValid() {585elem.Set(x)586}587return reflect.Value{}, nil588}589if key.Next() {590// Still scoping the key591return d.handleTablePart(key, v)592}593// Done scoping the key.594// Now handle all the key-value expressions in this table.595return d.handleKeyValues(v)596}597598// Handle root expressions until the end of the document or the next599// non-key-value.600func (d *decoder) handleKeyValues(v reflect.Value) (reflect.Value, error) {601var rv reflect.Value602for d.nextExpr() {603expr := d.expr()604if expr.Kind != unstable.KeyValue {605// Stash the expression so that fromParser can just loop and use606// the right handler.607// We could just recurse ourselves here, but at least this gives a608// chance to pop the stack a bit.609d.stashExpr()610break611}612613_, err := d.seen.CheckExpression(expr)614if err != nil {615return reflect.Value{}, err616}617618x, err := d.handleKeyValue(expr, v)619if err != nil {620return reflect.Value{}, err621}622if x.IsValid() {623v = x624rv = x625}626}627return rv, nil628}629630type (631handlerFn func(key unstable.Iterator, v reflect.Value) (reflect.Value, error)632valueMakerFn func() reflect.Value633)634635func makeMapStringInterface() reflect.Value {636return reflect.MakeMap(mapStringInterfaceType)637}638639func makeSliceInterface() reflect.Value {640return reflect.MakeSlice(sliceInterfaceType, 0, 16)641}642643func (d *decoder) handleTablePart(key unstable.Iterator, v reflect.Value) (reflect.Value, error) {644return d.handleKeyPart(key, v, d.handleTable, makeMapStringInterface)645}646647func (d *decoder) tryTextUnmarshaler(node *unstable.Node, v reflect.Value) (bool, error) {648// Special case for time, because we allow to unmarshal to it from649// different kind of AST nodes.650if v.Type() == timeType {651return false, nil652}653654if v.CanAddr() && v.Addr().Type().Implements(textUnmarshalerType) {655err := v.Addr().Interface().(encoding.TextUnmarshaler).UnmarshalText(node.Data)656if err != nil {657return false, unstable.NewParserError(d.p.Raw(node.Raw), "%w", err)658}659660return true, nil661}662663return false, nil664}665666func (d *decoder) handleValue(value *unstable.Node, v reflect.Value) error {667for v.Kind() == reflect.Ptr {668v = initAndDereferencePointer(v)669}670671if d.unmarshalerInterface {672if v.CanAddr() && v.Addr().CanInterface() {673if outi, ok := v.Addr().Interface().(unstable.Unmarshaler); ok {674return outi.UnmarshalTOML(value)675}676}677}678679ok, err := d.tryTextUnmarshaler(value, v)680if ok || err != nil {681return err682}683684switch value.Kind {685case unstable.String:686return d.unmarshalString(value, v)687case unstable.Integer:688return d.unmarshalInteger(value, v)689case unstable.Float:690return d.unmarshalFloat(value, v)691case unstable.Bool:692return d.unmarshalBool(value, v)693case unstable.DateTime:694return d.unmarshalDateTime(value, v)695case unstable.LocalDate:696return d.unmarshalLocalDate(value, v)697case unstable.LocalTime:698return d.unmarshalLocalTime(value, v)699case unstable.LocalDateTime:700return d.unmarshalLocalDateTime(value, v)701case unstable.InlineTable:702return d.unmarshalInlineTable(value, v)703case unstable.Array:704return d.unmarshalArray(value, v)705default:706panic(fmt.Errorf("handleValue not implemented for %s", value.Kind))707}708}709710func (d *decoder) unmarshalArray(array *unstable.Node, v reflect.Value) error {711switch v.Kind() {712case reflect.Slice:713if v.IsNil() {714v.Set(reflect.MakeSlice(v.Type(), 0, 16))715} else {716v.SetLen(0)717}718case reflect.Array:719// arrays are always initialized720case reflect.Interface:721elem := v.Elem()722if !elem.IsValid() {723elem = reflect.New(sliceInterfaceType).Elem()724elem.Set(reflect.MakeSlice(sliceInterfaceType, 0, 16))725} else if elem.Kind() == reflect.Slice {726if elem.Type() != sliceInterfaceType {727elem = reflect.New(sliceInterfaceType).Elem()728elem.Set(reflect.MakeSlice(sliceInterfaceType, 0, 16))729} else if !elem.CanSet() {730nelem := reflect.New(sliceInterfaceType).Elem()731nelem.Set(reflect.MakeSlice(sliceInterfaceType, elem.Len(), elem.Cap()))732reflect.Copy(nelem, elem)733elem = nelem734}735}736err := d.unmarshalArray(array, elem)737if err != nil {738return err739}740v.Set(elem)741return nil742default:743// TODO: use newDecodeError, but first the parser needs to fill744// array.Data.745return d.typeMismatchError("array", v.Type())746}747748elemType := v.Type().Elem()749750it := array.Children()751idx := 0752for it.Next() {753n := it.Node()754755// TODO: optimize756if v.Kind() == reflect.Slice {757elem := reflect.New(elemType).Elem()758759err := d.handleValue(n, elem)760if err != nil {761return err762}763764v.Set(reflect.Append(v, elem))765} else { // array766if idx >= v.Len() {767return nil768}769elem := v.Index(idx)770err := d.handleValue(n, elem)771if err != nil {772return err773}774idx++775}776}777778return nil779}780781func (d *decoder) unmarshalInlineTable(itable *unstable.Node, v reflect.Value) error {782// Make sure v is an initialized object.783switch v.Kind() {784case reflect.Map:785if v.IsNil() {786v.Set(reflect.MakeMap(v.Type()))787}788case reflect.Struct:789// structs are always initialized.790case reflect.Interface:791elem := v.Elem()792if !elem.IsValid() {793elem = makeMapStringInterface()794v.Set(elem)795}796return d.unmarshalInlineTable(itable, elem)797default:798return unstable.NewParserError(d.p.Raw(itable.Raw), "cannot store inline table in Go type %s", v.Kind())799}800801it := itable.Children()802for it.Next() {803n := it.Node()804805x, err := d.handleKeyValue(n, v)806if err != nil {807return err808}809if x.IsValid() {810v = x811}812}813814return nil815}816817func (d *decoder) unmarshalDateTime(value *unstable.Node, v reflect.Value) error {818dt, err := parseDateTime(value.Data)819if err != nil {820return err821}822823v.Set(reflect.ValueOf(dt))824return nil825}826827func (d *decoder) unmarshalLocalDate(value *unstable.Node, v reflect.Value) error {828ld, err := parseLocalDate(value.Data)829if err != nil {830return err831}832833if v.Type() == timeType {834cast := ld.AsTime(time.Local)835v.Set(reflect.ValueOf(cast))836return nil837}838839v.Set(reflect.ValueOf(ld))840841return nil842}843844func (d *decoder) unmarshalLocalTime(value *unstable.Node, v reflect.Value) error {845lt, rest, err := parseLocalTime(value.Data)846if err != nil {847return err848}849850if len(rest) > 0 {851return unstable.NewParserError(rest, "extra characters at the end of a local time")852}853854v.Set(reflect.ValueOf(lt))855return nil856}857858func (d *decoder) unmarshalLocalDateTime(value *unstable.Node, v reflect.Value) error {859ldt, rest, err := parseLocalDateTime(value.Data)860if err != nil {861return err862}863864if len(rest) > 0 {865return unstable.NewParserError(rest, "extra characters at the end of a local date time")866}867868if v.Type() == timeType {869cast := ldt.AsTime(time.Local)870871v.Set(reflect.ValueOf(cast))872return nil873}874875v.Set(reflect.ValueOf(ldt))876877return nil878}879880func (d *decoder) unmarshalBool(value *unstable.Node, v reflect.Value) error {881b := value.Data[0] == 't'882883switch v.Kind() {884case reflect.Bool:885v.SetBool(b)886case reflect.Interface:887v.Set(reflect.ValueOf(b))888default:889return unstable.NewParserError(value.Data, "cannot assign boolean to a %t", b)890}891892return nil893}894895func (d *decoder) unmarshalFloat(value *unstable.Node, v reflect.Value) error {896f, err := parseFloat(value.Data)897if err != nil {898return err899}900901switch v.Kind() {902case reflect.Float64:903v.SetFloat(f)904case reflect.Float32:905if f > math.MaxFloat32 {906return unstable.NewParserError(value.Data, "number %f does not fit in a float32", f)907}908v.SetFloat(f)909case reflect.Interface:910v.Set(reflect.ValueOf(f))911default:912return unstable.NewParserError(value.Data, "float cannot be assigned to %s", v.Kind())913}914915return nil916}917918const (919maxInt = int64(^uint(0) >> 1)920minInt = -maxInt - 1921)922923// Maximum value of uint for decoding. Currently the decoder parses the integer924// into an int64. As a result, on architectures where uint is 64 bits, the925// effective maximum uint we can decode is the maximum of int64. On926// architectures where uint is 32 bits, the maximum value we can decode is927// lower: the maximum of uint32. I didn't find a way to figure out this value at928// compile time, so it is computed during initialization.929var maxUint int64 = math.MaxInt64930931func init() {932m := uint64(^uint(0))933if m < uint64(maxUint) {934maxUint = int64(m)935}936}937938func (d *decoder) unmarshalInteger(value *unstable.Node, v reflect.Value) error {939kind := v.Kind()940if kind == reflect.Float32 || kind == reflect.Float64 {941return d.unmarshalFloat(value, v)942}943944i, err := parseInteger(value.Data)945if err != nil {946return err947}948949var r reflect.Value950951switch kind {952case reflect.Int64:953v.SetInt(i)954return nil955case reflect.Int32:956if i < math.MinInt32 || i > math.MaxInt32 {957return fmt.Errorf("toml: number %d does not fit in an int32", i)958}959960r = reflect.ValueOf(int32(i))961case reflect.Int16:962if i < math.MinInt16 || i > math.MaxInt16 {963return fmt.Errorf("toml: number %d does not fit in an int16", i)964}965966r = reflect.ValueOf(int16(i))967case reflect.Int8:968if i < math.MinInt8 || i > math.MaxInt8 {969return fmt.Errorf("toml: number %d does not fit in an int8", i)970}971972r = reflect.ValueOf(int8(i))973case reflect.Int:974if i < minInt || i > maxInt {975return fmt.Errorf("toml: number %d does not fit in an int", i)976}977978r = reflect.ValueOf(int(i))979case reflect.Uint64:980if i < 0 {981return fmt.Errorf("toml: negative number %d does not fit in an uint64", i)982}983984r = reflect.ValueOf(uint64(i))985case reflect.Uint32:986if i < 0 || i > math.MaxUint32 {987return fmt.Errorf("toml: negative number %d does not fit in an uint32", i)988}989990r = reflect.ValueOf(uint32(i))991case reflect.Uint16:992if i < 0 || i > math.MaxUint16 {993return fmt.Errorf("toml: negative number %d does not fit in an uint16", i)994}995996r = reflect.ValueOf(uint16(i))997case reflect.Uint8:998if i < 0 || i > math.MaxUint8 {999return fmt.Errorf("toml: negative number %d does not fit in an uint8", i)1000}10011002r = reflect.ValueOf(uint8(i))1003case reflect.Uint:1004if i < 0 || i > maxUint {1005return fmt.Errorf("toml: negative number %d does not fit in an uint", i)1006}10071008r = reflect.ValueOf(uint(i))1009case reflect.Interface:1010r = reflect.ValueOf(i)1011default:1012return unstable.NewParserError(d.p.Raw(value.Raw), d.typeMismatchString("integer", v.Type()))1013}10141015if !r.Type().AssignableTo(v.Type()) {1016r = r.Convert(v.Type())1017}10181019v.Set(r)10201021return nil1022}10231024func (d *decoder) unmarshalString(value *unstable.Node, v reflect.Value) error {1025switch v.Kind() {1026case reflect.String:1027v.SetString(string(value.Data))1028case reflect.Interface:1029v.Set(reflect.ValueOf(string(value.Data)))1030default:1031return unstable.NewParserError(d.p.Raw(value.Raw), d.typeMismatchString("string", v.Type()))1032}10331034return nil1035}10361037func (d *decoder) handleKeyValue(expr *unstable.Node, v reflect.Value) (reflect.Value, error) {1038d.strict.EnterKeyValue(expr)10391040v, err := d.handleKeyValueInner(expr.Key(), expr.Value(), v)1041if d.skipUntilTable {1042d.strict.MissingField(expr)1043d.skipUntilTable = false1044}10451046d.strict.ExitKeyValue(expr)10471048return v, err1049}10501051func (d *decoder) handleKeyValueInner(key unstable.Iterator, value *unstable.Node, v reflect.Value) (reflect.Value, error) {1052if key.Next() {1053// Still scoping the key1054return d.handleKeyValuePart(key, value, v)1055}1056// Done scoping the key.1057// v is whatever Go value we need to fill.1058return reflect.Value{}, d.handleValue(value, v)1059}10601061func (d *decoder) keyFromData(keyType reflect.Type, data []byte) (reflect.Value, error) {1062switch {1063case stringType.AssignableTo(keyType):1064return reflect.ValueOf(string(data)), nil10651066case stringType.ConvertibleTo(keyType):1067return reflect.ValueOf(string(data)).Convert(keyType), nil10681069case keyType.Implements(textUnmarshalerType):1070mk := reflect.New(keyType.Elem())1071if err := mk.Interface().(encoding.TextUnmarshaler).UnmarshalText(data); err != nil {1072return reflect.Value{}, fmt.Errorf("toml: error unmarshalling key type %s from text: %w", stringType, err)1073}1074return mk, nil10751076case reflect.PointerTo(keyType).Implements(textUnmarshalerType):1077mk := reflect.New(keyType)1078if err := mk.Interface().(encoding.TextUnmarshaler).UnmarshalText(data); err != nil {1079return reflect.Value{}, fmt.Errorf("toml: error unmarshalling key type %s from text: %w", stringType, err)1080}1081return mk.Elem(), nil10821083case keyType.Kind() == reflect.Int || keyType.Kind() == reflect.Int8 || keyType.Kind() == reflect.Int16 || keyType.Kind() == reflect.Int32 || keyType.Kind() == reflect.Int64:1084key, err := strconv.ParseInt(string(data), 10, 64)1085if err != nil {1086return reflect.Value{}, fmt.Errorf("toml: error parsing key of type %s from integer: %w", stringType, err)1087}1088return reflect.ValueOf(key).Convert(keyType), nil1089case keyType.Kind() == reflect.Uint || keyType.Kind() == reflect.Uint8 || keyType.Kind() == reflect.Uint16 || keyType.Kind() == reflect.Uint32 || keyType.Kind() == reflect.Uint64:1090key, err := strconv.ParseUint(string(data), 10, 64)1091if err != nil {1092return reflect.Value{}, fmt.Errorf("toml: error parsing key of type %s from unsigned integer: %w", stringType, err)1093}1094return reflect.ValueOf(key).Convert(keyType), nil10951096case keyType.Kind() == reflect.Float32:1097key, err := strconv.ParseFloat(string(data), 32)1098if err != nil {1099return reflect.Value{}, fmt.Errorf("toml: error parsing key of type %s from float: %w", stringType, err)1100}1101return reflect.ValueOf(float32(key)), nil11021103case keyType.Kind() == reflect.Float64:1104key, err := strconv.ParseFloat(string(data), 64)1105if err != nil {1106return reflect.Value{}, fmt.Errorf("toml: error parsing key of type %s from float: %w", stringType, err)1107}1108return reflect.ValueOf(float64(key)), nil1109}1110return reflect.Value{}, fmt.Errorf("toml: cannot convert map key of type %s to expected type %s", stringType, keyType)1111}11121113func (d *decoder) handleKeyValuePart(key unstable.Iterator, value *unstable.Node, v reflect.Value) (reflect.Value, error) {1114// contains the replacement for v1115var rv reflect.Value11161117// First, dispatch over v to make sure it is a valid object.1118// There is no guarantee over what it could be.1119switch v.Kind() {1120case reflect.Map:1121vt := v.Type()11221123mk, err := d.keyFromData(vt.Key(), key.Node().Data)1124if err != nil {1125return reflect.Value{}, err1126}11271128// If the map does not exist, create it.1129if v.IsNil() {1130v = reflect.MakeMap(vt)1131rv = v1132}11331134mv := v.MapIndex(mk)1135set := false1136if !mv.IsValid() || key.IsLast() {1137set = true1138mv = reflect.New(v.Type().Elem()).Elem()1139}11401141nv, err := d.handleKeyValueInner(key, value, mv)1142if err != nil {1143return reflect.Value{}, err1144}1145if nv.IsValid() {1146mv = nv1147set = true1148}11491150if set {1151v.SetMapIndex(mk, mv)1152}1153case reflect.Struct:1154path, found := structFieldPath(v, string(key.Node().Data))1155if !found {1156d.skipUntilTable = true1157break1158}11591160if d.errorContext == nil {1161d.errorContext = new(errorContext)1162}1163t := v.Type()1164d.errorContext.Struct = t1165d.errorContext.Field = path11661167f := fieldByIndex(v, path)11681169if !f.CanAddr() {1170// If the field is not addressable, need to take a slower path and1171// make a copy of the struct itself to a new location.1172nvp := reflect.New(v.Type())1173nvp.Elem().Set(v)1174v = nvp.Elem()1175_, err := d.handleKeyValuePart(key, value, v)1176if err != nil {1177return reflect.Value{}, err1178}1179return nvp.Elem(), nil1180}1181x, err := d.handleKeyValueInner(key, value, f)1182if err != nil {1183return reflect.Value{}, err1184}11851186if x.IsValid() {1187f.Set(x)1188}1189d.errorContext.Struct = nil1190d.errorContext.Field = nil1191case reflect.Interface:1192v = v.Elem()11931194// Following encoding/json: decoding an object into an1195// interface{}, it needs to always hold a1196// map[string]interface{}. This is for the types to be1197// consistent whether a previous value was set or not.1198if !v.IsValid() || v.Type() != mapStringInterfaceType {1199v = makeMapStringInterface()1200}12011202x, err := d.handleKeyValuePart(key, value, v)1203if err != nil {1204return reflect.Value{}, err1205}1206if x.IsValid() {1207v = x1208}1209rv = v1210case reflect.Ptr:1211elem := v.Elem()1212if !elem.IsValid() {1213ptr := reflect.New(v.Type().Elem())1214v.Set(ptr)1215rv = v1216elem = ptr.Elem()1217}12181219elem2, err := d.handleKeyValuePart(key, value, elem)1220if err != nil {1221return reflect.Value{}, err1222}1223if elem2.IsValid() {1224elem = elem21225}1226v.Elem().Set(elem)1227default:1228return reflect.Value{}, fmt.Errorf("unhandled kv part: %s", v.Kind())1229}12301231return rv, nil1232}12331234func initAndDereferencePointer(v reflect.Value) reflect.Value {1235var elem reflect.Value1236if v.IsNil() {1237ptr := reflect.New(v.Type().Elem())1238v.Set(ptr)1239}1240elem = v.Elem()1241return elem1242}12431244// Same as reflect.Value.FieldByIndex, but creates pointers if needed.1245func fieldByIndex(v reflect.Value, path []int) reflect.Value {1246for _, x := range path {1247v = v.Field(x)12481249if v.Kind() == reflect.Ptr {1250if v.IsNil() {1251v.Set(reflect.New(v.Type().Elem()))1252}1253v = v.Elem()1254}1255}1256return v1257}12581259type fieldPathsMap = map[string][]int12601261var globalFieldPathsCache atomic.Value // map[danger.TypeID]fieldPathsMap12621263func structFieldPath(v reflect.Value, name string) ([]int, bool) {1264t := v.Type()12651266cache, _ := globalFieldPathsCache.Load().(map[danger.TypeID]fieldPathsMap)1267fieldPaths, ok := cache[danger.MakeTypeID(t)]12681269if !ok {1270fieldPaths = map[string][]int{}12711272forEachField(t, nil, func(name string, path []int) {1273fieldPaths[name] = path1274// extra copy for the case-insensitive match1275fieldPaths[strings.ToLower(name)] = path1276})12771278newCache := make(map[danger.TypeID]fieldPathsMap, len(cache)+1)1279newCache[danger.MakeTypeID(t)] = fieldPaths1280for k, v := range cache {1281newCache[k] = v1282}1283globalFieldPathsCache.Store(newCache)1284}12851286path, ok := fieldPaths[name]1287if !ok {1288path, ok = fieldPaths[strings.ToLower(name)]1289}1290return path, ok1291}12921293func forEachField(t reflect.Type, path []int, do func(name string, path []int)) {1294n := t.NumField()1295for i := 0; i < n; i++ {1296f := t.Field(i)12971298if !f.Anonymous && f.PkgPath != "" {1299// only consider exported fields.1300continue1301}13021303fieldPath := append(path, i)1304fieldPath = fieldPath[:len(fieldPath):len(fieldPath)]13051306name := f.Tag.Get("toml")1307if name == "-" {1308continue1309}13101311if i := strings.IndexByte(name, ','); i >= 0 {1312name = name[:i]1313}13141315if f.Anonymous && name == "" {1316t2 := f.Type1317if t2.Kind() == reflect.Ptr {1318t2 = t2.Elem()1319}13201321if t2.Kind() == reflect.Struct {1322forEachField(t2, fieldPath, do)1323}1324continue1325}13261327if name == "" {1328name = f.Name1329}13301331do(name, fieldPath)1332}1333}133413351336