mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	Bump github.com/mitchellh/mapstructure
This commit is contained in:
		
							
								
								
									
										7
									
								
								vendor/github.com/mitchellh/mapstructure/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/mitchellh/mapstructure/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
language: go 
 | 
			
		||||
 | 
			
		||||
go: 
 | 
			
		||||
  - 1.4
 | 
			
		||||
  
 | 
			
		||||
script:
 | 
			
		||||
  - go test 
 | 
			
		||||
							
								
								
									
										78
									
								
								vendor/github.com/mitchellh/mapstructure/decode_hooks.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										78
									
								
								vendor/github.com/mitchellh/mapstructure/decode_hooks.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,11 +1,59 @@
 | 
			
		||||
package mapstructure
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// typedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns
 | 
			
		||||
// it into the proper DecodeHookFunc type, such as DecodeHookFuncType.
 | 
			
		||||
func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc {
 | 
			
		||||
	// Create variables here so we can reference them with the reflect pkg
 | 
			
		||||
	var f1 DecodeHookFuncType
 | 
			
		||||
	var f2 DecodeHookFuncKind
 | 
			
		||||
 | 
			
		||||
	// Fill in the variables into this interface and the rest is done
 | 
			
		||||
	// automatically using the reflect package.
 | 
			
		||||
	potential := []interface{}{f1, f2}
 | 
			
		||||
 | 
			
		||||
	v := reflect.ValueOf(h)
 | 
			
		||||
	vt := v.Type()
 | 
			
		||||
	for _, raw := range potential {
 | 
			
		||||
		pt := reflect.ValueOf(raw).Type()
 | 
			
		||||
		if vt.ConvertibleTo(pt) {
 | 
			
		||||
			return v.Convert(pt).Interface()
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DecodeHookExec executes the given decode hook. This should be used
 | 
			
		||||
// since it'll naturally degrade to the older backwards compatible DecodeHookFunc
 | 
			
		||||
// that took reflect.Kind instead of reflect.Type.
 | 
			
		||||
func DecodeHookExec(
 | 
			
		||||
	raw DecodeHookFunc,
 | 
			
		||||
	from reflect.Type, to reflect.Type,
 | 
			
		||||
	data interface{}) (interface{}, error) {
 | 
			
		||||
	// Build our arguments that reflect expects
 | 
			
		||||
	argVals := make([]reflect.Value, 3)
 | 
			
		||||
	argVals[0] = reflect.ValueOf(from)
 | 
			
		||||
	argVals[1] = reflect.ValueOf(to)
 | 
			
		||||
	argVals[2] = reflect.ValueOf(data)
 | 
			
		||||
 | 
			
		||||
	switch f := typedDecodeHook(raw).(type) {
 | 
			
		||||
	case DecodeHookFuncType:
 | 
			
		||||
		return f(from, to, data)
 | 
			
		||||
	case DecodeHookFuncKind:
 | 
			
		||||
		return f(from.Kind(), to.Kind(), data)
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, errors.New("invalid decode hook signature")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ComposeDecodeHookFunc creates a single DecodeHookFunc that
 | 
			
		||||
// automatically composes multiple DecodeHookFuncs.
 | 
			
		||||
//
 | 
			
		||||
@@ -13,18 +61,21 @@ import (
 | 
			
		||||
// previous transformation.
 | 
			
		||||
func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
 | 
			
		||||
	return func(
 | 
			
		||||
		f reflect.Kind,
 | 
			
		||||
		t reflect.Kind,
 | 
			
		||||
		f reflect.Type,
 | 
			
		||||
		t reflect.Type,
 | 
			
		||||
		data interface{}) (interface{}, error) {
 | 
			
		||||
		var err error
 | 
			
		||||
		for _, f1 := range fs {
 | 
			
		||||
			data, err = f1(f, t, data)
 | 
			
		||||
			data, err = DecodeHookExec(f1, f, t, data)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Modify the from kind to be correct with the new data
 | 
			
		||||
			f = getKind(reflect.ValueOf(data))
 | 
			
		||||
			f = nil
 | 
			
		||||
			if val := reflect.ValueOf(data); val.IsValid() {
 | 
			
		||||
				f = val.Type()
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return data, nil
 | 
			
		||||
@@ -51,6 +102,25 @@ func StringToSliceHookFunc(sep string) DecodeHookFunc {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StringToTimeDurationHookFunc returns a DecodeHookFunc that converts
 | 
			
		||||
// strings to time.Duration.
 | 
			
		||||
func StringToTimeDurationHookFunc() DecodeHookFunc {
 | 
			
		||||
	return func(
 | 
			
		||||
		f reflect.Type,
 | 
			
		||||
		t reflect.Type,
 | 
			
		||||
		data interface{}) (interface{}, error) {
 | 
			
		||||
		if f.Kind() != reflect.String {
 | 
			
		||||
			return data, nil
 | 
			
		||||
		}
 | 
			
		||||
		if t != reflect.TypeOf(time.Duration(5)) {
 | 
			
		||||
			return data, nil
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Convert it by parsing
 | 
			
		||||
		return time.ParseDuration(data.(string))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WeaklyTypedHook(
 | 
			
		||||
	f reflect.Kind,
 | 
			
		||||
	t reflect.Kind,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										18
									
								
								vendor/github.com/mitchellh/mapstructure/error.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										18
									
								
								vendor/github.com/mitchellh/mapstructure/error.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,7 +1,9 @@
 | 
			
		||||
package mapstructure
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -17,11 +19,27 @@ func (e *Error) Error() string {
 | 
			
		||||
		points[i] = fmt.Sprintf("* %s", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sort.Strings(points)
 | 
			
		||||
	return fmt.Sprintf(
 | 
			
		||||
		"%d error(s) decoding:\n\n%s",
 | 
			
		||||
		len(e.Errors), strings.Join(points, "\n"))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WrappedErrors implements the errwrap.Wrapper interface to make this
 | 
			
		||||
// return value more useful with the errwrap and go-multierror libraries.
 | 
			
		||||
func (e *Error) WrappedErrors() []error {
 | 
			
		||||
	if e == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	result := make([]error, len(e.Errors))
 | 
			
		||||
	for i, e := range e.Errors {
 | 
			
		||||
		result[i] = errors.New(e)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func appendErrors(errors []string, err error) []string {
 | 
			
		||||
	switch e := err.(type) {
 | 
			
		||||
	case *Error:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										227
									
								
								vendor/github.com/mitchellh/mapstructure/mapstructure.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										227
									
								
								vendor/github.com/mitchellh/mapstructure/mapstructure.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,5 +1,5 @@
 | 
			
		||||
// The mapstructure package exposes functionality to convert an
 | 
			
		||||
// abitrary map[string]interface{} into a native Go structure.
 | 
			
		||||
// arbitrary map[string]interface{} into a native Go structure.
 | 
			
		||||
//
 | 
			
		||||
// The Go structure can be arbitrarily complex, containing slices,
 | 
			
		||||
// other structs, etc. and the decoder will properly decode nested
 | 
			
		||||
@@ -8,6 +8,7 @@
 | 
			
		||||
package mapstructure
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"reflect"
 | 
			
		||||
@@ -19,10 +20,20 @@ import (
 | 
			
		||||
// DecodeHookFunc is the callback function that can be used for
 | 
			
		||||
// data transformations. See "DecodeHook" in the DecoderConfig
 | 
			
		||||
// struct.
 | 
			
		||||
type DecodeHookFunc func(
 | 
			
		||||
	from reflect.Kind,
 | 
			
		||||
	to reflect.Kind,
 | 
			
		||||
	data interface{}) (interface{}, error)
 | 
			
		||||
//
 | 
			
		||||
// The type should be DecodeHookFuncType or DecodeHookFuncKind.
 | 
			
		||||
// Either is accepted. Types are a superset of Kinds (Types can return
 | 
			
		||||
// Kinds) and are generally a richer thing to use, but Kinds are simpler
 | 
			
		||||
// if you only need those.
 | 
			
		||||
//
 | 
			
		||||
// The reason DecodeHookFunc is multi-typed is for backwards compatibility:
 | 
			
		||||
// we started with Kinds and then realized Types were the better solution,
 | 
			
		||||
// but have a promise to not break backwards compat so we now support
 | 
			
		||||
// both.
 | 
			
		||||
type DecodeHookFunc interface{}
 | 
			
		||||
 | 
			
		||||
type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error)
 | 
			
		||||
type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error)
 | 
			
		||||
 | 
			
		||||
// DecoderConfig is the configuration that is used to create a new decoder
 | 
			
		||||
// and allows customization of various aspects of decoding.
 | 
			
		||||
@@ -40,6 +51,11 @@ type DecoderConfig struct {
 | 
			
		||||
	// (extra keys).
 | 
			
		||||
	ErrorUnused bool
 | 
			
		||||
 | 
			
		||||
	// ZeroFields, if set to true, will zero fields before writing them.
 | 
			
		||||
	// For example, a map will be emptied before decoded values are put in
 | 
			
		||||
	// it. If this is false, a map will be merged.
 | 
			
		||||
	ZeroFields bool
 | 
			
		||||
 | 
			
		||||
	// If WeaklyTypedInput is true, the decoder will make the following
 | 
			
		||||
	// "weak" conversions:
 | 
			
		||||
	//
 | 
			
		||||
@@ -51,6 +67,11 @@ type DecoderConfig struct {
 | 
			
		||||
	//   - string to bool (accepts: 1, t, T, TRUE, true, True, 0, f, F,
 | 
			
		||||
	//     FALSE, false, False. Anything else is an error)
 | 
			
		||||
	//   - empty array = empty map and vice versa
 | 
			
		||||
	//   - negative numbers to overflowed uint values (base 10)
 | 
			
		||||
	//   - slice of maps to a merged map
 | 
			
		||||
	//   - single values are converted to slices if required. Each
 | 
			
		||||
	//     element is weakly decoded. For example: "4" can become []int{4}
 | 
			
		||||
	//     if the target type is an int slice.
 | 
			
		||||
	//
 | 
			
		||||
	WeaklyTypedInput bool
 | 
			
		||||
 | 
			
		||||
@@ -180,9 +201,11 @@ func (d *Decoder) decode(name string, data interface{}, val reflect.Value) error
 | 
			
		||||
	if d.config.DecodeHook != nil {
 | 
			
		||||
		// We have a DecodeHook, so let's pre-process the data.
 | 
			
		||||
		var err error
 | 
			
		||||
		data, err = d.config.DecodeHook(getKind(dataVal), getKind(val), data)
 | 
			
		||||
		data, err = DecodeHookExec(
 | 
			
		||||
			d.config.DecodeHook,
 | 
			
		||||
			dataVal.Type(), val.Type(), data)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
			return fmt.Errorf("error decoding '%s': %s", name, err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -209,6 +232,8 @@ func (d *Decoder) decode(name string, data interface{}, val reflect.Value) error
 | 
			
		||||
		err = d.decodePtr(name, data, val)
 | 
			
		||||
	case reflect.Slice:
 | 
			
		||||
		err = d.decodeSlice(name, data, val)
 | 
			
		||||
	case reflect.Func:
 | 
			
		||||
		err = d.decodeFunc(name, data, val)
 | 
			
		||||
	default:
 | 
			
		||||
		// If we reached this point then we weren't able to decode it
 | 
			
		||||
		return fmt.Errorf("%s: unsupported type: %s", name, dataKind)
 | 
			
		||||
@@ -227,6 +252,10 @@ func (d *Decoder) decode(name string, data interface{}, val reflect.Value) error
 | 
			
		||||
// value to "data" of that type.
 | 
			
		||||
func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error {
 | 
			
		||||
	dataVal := reflect.ValueOf(data)
 | 
			
		||||
	if !dataVal.IsValid() {
 | 
			
		||||
		dataVal = reflect.Zero(val.Type())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dataValType := dataVal.Type()
 | 
			
		||||
	if !dataValType.AssignableTo(val.Type()) {
 | 
			
		||||
		return fmt.Errorf(
 | 
			
		||||
@@ -283,6 +312,7 @@ func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value)
 | 
			
		||||
func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error {
 | 
			
		||||
	dataVal := reflect.ValueOf(data)
 | 
			
		||||
	dataKind := getKind(dataVal)
 | 
			
		||||
	dataType := dataVal.Type()
 | 
			
		||||
 | 
			
		||||
	switch {
 | 
			
		||||
	case dataKind == reflect.Int:
 | 
			
		||||
@@ -304,6 +334,14 @@ func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) er
 | 
			
		||||
		} else {
 | 
			
		||||
			return fmt.Errorf("cannot parse '%s' as int: %s", name, err)
 | 
			
		||||
		}
 | 
			
		||||
	case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
 | 
			
		||||
		jn := data.(json.Number)
 | 
			
		||||
		i, err := jn.Int64()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return fmt.Errorf(
 | 
			
		||||
				"error decoding json.Number into %s: %s", name, err)
 | 
			
		||||
		}
 | 
			
		||||
		val.SetInt(i)
 | 
			
		||||
	default:
 | 
			
		||||
		return fmt.Errorf(
 | 
			
		||||
			"'%s' expected type '%s', got unconvertible type '%s'",
 | 
			
		||||
@@ -319,11 +357,21 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e
 | 
			
		||||
 | 
			
		||||
	switch {
 | 
			
		||||
	case dataKind == reflect.Int:
 | 
			
		||||
		val.SetUint(uint64(dataVal.Int()))
 | 
			
		||||
		i := dataVal.Int()
 | 
			
		||||
		if i < 0 && !d.config.WeaklyTypedInput {
 | 
			
		||||
			return fmt.Errorf("cannot parse '%s', %d overflows uint",
 | 
			
		||||
				name, i)
 | 
			
		||||
		}
 | 
			
		||||
		val.SetUint(uint64(i))
 | 
			
		||||
	case dataKind == reflect.Uint:
 | 
			
		||||
		val.SetUint(dataVal.Uint())
 | 
			
		||||
	case dataKind == reflect.Float32:
 | 
			
		||||
		val.SetUint(uint64(dataVal.Float()))
 | 
			
		||||
		f := dataVal.Float()
 | 
			
		||||
		if f < 0 && !d.config.WeaklyTypedInput {
 | 
			
		||||
			return fmt.Errorf("cannot parse '%s', %f overflows uint",
 | 
			
		||||
				name, f)
 | 
			
		||||
		}
 | 
			
		||||
		val.SetUint(uint64(f))
 | 
			
		||||
	case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
 | 
			
		||||
		if dataVal.Bool() {
 | 
			
		||||
			val.SetUint(1)
 | 
			
		||||
@@ -380,6 +428,7 @@ func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) e
 | 
			
		||||
func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error {
 | 
			
		||||
	dataVal := reflect.ValueOf(data)
 | 
			
		||||
	dataKind := getKind(dataVal)
 | 
			
		||||
	dataType := dataVal.Type()
 | 
			
		||||
 | 
			
		||||
	switch {
 | 
			
		||||
	case dataKind == reflect.Int:
 | 
			
		||||
@@ -401,6 +450,14 @@ func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value)
 | 
			
		||||
		} else {
 | 
			
		||||
			return fmt.Errorf("cannot parse '%s' as float: %s", name, err)
 | 
			
		||||
		}
 | 
			
		||||
	case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
 | 
			
		||||
		jn := data.(json.Number)
 | 
			
		||||
		i, err := jn.Float64()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return fmt.Errorf(
 | 
			
		||||
				"error decoding json.Number into %s: %s", name, err)
 | 
			
		||||
		}
 | 
			
		||||
		val.SetFloat(i)
 | 
			
		||||
	default:
 | 
			
		||||
		return fmt.Errorf(
 | 
			
		||||
			"'%s' expected type '%s', got unconvertible type '%s'",
 | 
			
		||||
@@ -415,22 +472,43 @@ func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) er
 | 
			
		||||
	valKeyType := valType.Key()
 | 
			
		||||
	valElemType := valType.Elem()
 | 
			
		||||
 | 
			
		||||
	// Make a new map to hold our result
 | 
			
		||||
	mapType := reflect.MapOf(valKeyType, valElemType)
 | 
			
		||||
	valMap := reflect.MakeMap(mapType)
 | 
			
		||||
	// By default we overwrite keys in the current map
 | 
			
		||||
	valMap := val
 | 
			
		||||
 | 
			
		||||
	// If the map is nil or we're purposely zeroing fields, make a new map
 | 
			
		||||
	if valMap.IsNil() || d.config.ZeroFields {
 | 
			
		||||
		// Make a new map to hold our result
 | 
			
		||||
		mapType := reflect.MapOf(valKeyType, valElemType)
 | 
			
		||||
		valMap = reflect.MakeMap(mapType)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Check input type
 | 
			
		||||
	dataVal := reflect.Indirect(reflect.ValueOf(data))
 | 
			
		||||
	if dataVal.Kind() != reflect.Map {
 | 
			
		||||
		// Accept empty array/slice instead of an empty map in weakly typed mode
 | 
			
		||||
		if d.config.WeaklyTypedInput &&
 | 
			
		||||
			(dataVal.Kind() == reflect.Slice || dataVal.Kind() == reflect.Array) &&
 | 
			
		||||
			dataVal.Len() == 0 {
 | 
			
		||||
			val.Set(valMap)
 | 
			
		||||
			return nil
 | 
			
		||||
		} else {
 | 
			
		||||
			return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind())
 | 
			
		||||
		// In weak mode, we accept a slice of maps as an input...
 | 
			
		||||
		if d.config.WeaklyTypedInput {
 | 
			
		||||
			switch dataVal.Kind() {
 | 
			
		||||
			case reflect.Array, reflect.Slice:
 | 
			
		||||
				// Special case for BC reasons (covered by tests)
 | 
			
		||||
				if dataVal.Len() == 0 {
 | 
			
		||||
					val.Set(valMap)
 | 
			
		||||
					return nil
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				for i := 0; i < dataVal.Len(); i++ {
 | 
			
		||||
					err := d.decode(
 | 
			
		||||
						fmt.Sprintf("%s[%d]", name, i),
 | 
			
		||||
						dataVal.Index(i).Interface(), val)
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						return err
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				return nil
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Accumulate errors
 | 
			
		||||
@@ -473,7 +551,12 @@ func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) er
 | 
			
		||||
	// into that. Then set the value of the pointer to this type.
 | 
			
		||||
	valType := val.Type()
 | 
			
		||||
	valElemType := valType.Elem()
 | 
			
		||||
	realVal := reflect.New(valElemType)
 | 
			
		||||
 | 
			
		||||
	realVal := val
 | 
			
		||||
	if realVal.IsNil() || d.config.ZeroFields {
 | 
			
		||||
		realVal = reflect.New(valElemType)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := d.decode(name, data, reflect.Indirect(realVal)); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
@@ -482,6 +565,19 @@ func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) er
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) error {
 | 
			
		||||
	// Create an element of the concrete (non pointer) type and decode
 | 
			
		||||
	// into that. Then set the value of the pointer to this type.
 | 
			
		||||
	dataVal := reflect.Indirect(reflect.ValueOf(data))
 | 
			
		||||
	if val.Type() != dataVal.Type() {
 | 
			
		||||
		return fmt.Errorf(
 | 
			
		||||
			"'%s' expected type '%s', got unconvertible type '%s'",
 | 
			
		||||
			name, val.Type(), dataVal.Type())
 | 
			
		||||
	}
 | 
			
		||||
	val.Set(dataVal)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error {
 | 
			
		||||
	dataVal := reflect.Indirect(reflect.ValueOf(data))
 | 
			
		||||
	dataValKind := dataVal.Kind()
 | 
			
		||||
@@ -489,26 +585,44 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value)
 | 
			
		||||
	valElemType := valType.Elem()
 | 
			
		||||
	sliceType := reflect.SliceOf(valElemType)
 | 
			
		||||
 | 
			
		||||
	// Check input type
 | 
			
		||||
	if dataValKind != reflect.Array && dataValKind != reflect.Slice {
 | 
			
		||||
		// Accept empty map instead of array/slice in weakly typed mode
 | 
			
		||||
		if d.config.WeaklyTypedInput && dataVal.Kind() == reflect.Map && dataVal.Len() == 0 {
 | 
			
		||||
			val.Set(reflect.MakeSlice(sliceType, 0, 0))
 | 
			
		||||
			return nil
 | 
			
		||||
		} else {
 | 
			
		||||
	valSlice := val
 | 
			
		||||
	if valSlice.IsNil() || d.config.ZeroFields {
 | 
			
		||||
		// Check input type
 | 
			
		||||
		if dataValKind != reflect.Array && dataValKind != reflect.Slice {
 | 
			
		||||
			if d.config.WeaklyTypedInput {
 | 
			
		||||
				switch {
 | 
			
		||||
				// Empty maps turn into empty slices
 | 
			
		||||
				case dataValKind == reflect.Map:
 | 
			
		||||
					if dataVal.Len() == 0 {
 | 
			
		||||
						val.Set(reflect.MakeSlice(sliceType, 0, 0))
 | 
			
		||||
						return nil
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
				// All other types we try to convert to the slice type
 | 
			
		||||
				// and "lift" it into it. i.e. a string becomes a string slice.
 | 
			
		||||
				default:
 | 
			
		||||
					// Just re-try this function with data as a slice.
 | 
			
		||||
					return d.decodeSlice(name, []interface{}{data}, val)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return fmt.Errorf(
 | 
			
		||||
				"'%s': source data must be an array or slice, got %s", name, dataValKind)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Make a new slice to hold our result, same size as the original data.
 | 
			
		||||
	valSlice := reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len())
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Make a new slice to hold our result, same size as the original data.
 | 
			
		||||
		valSlice = reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Accumulate any errors
 | 
			
		||||
	errors := make([]string, 0)
 | 
			
		||||
 | 
			
		||||
	for i := 0; i < dataVal.Len(); i++ {
 | 
			
		||||
		currentData := dataVal.Index(i).Interface()
 | 
			
		||||
		for valSlice.Len() <= i {
 | 
			
		||||
			valSlice = reflect.Append(valSlice, reflect.Zero(valElemType))
 | 
			
		||||
		}
 | 
			
		||||
		currentField := valSlice.Index(i)
 | 
			
		||||
 | 
			
		||||
		fieldName := fmt.Sprintf("%s[%d]", name, i)
 | 
			
		||||
@@ -530,6 +644,14 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value)
 | 
			
		||||
 | 
			
		||||
func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) error {
 | 
			
		||||
	dataVal := reflect.Indirect(reflect.ValueOf(data))
 | 
			
		||||
 | 
			
		||||
	// If the type of the value to write to and the data match directly,
 | 
			
		||||
	// then we just set it directly instead of recursing into the structure.
 | 
			
		||||
	if dataVal.Type() == val.Type() {
 | 
			
		||||
		val.Set(dataVal)
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dataValKind := dataVal.Kind()
 | 
			
		||||
	if dataValKind != reflect.Map {
 | 
			
		||||
		return fmt.Errorf("'%s' expected a map, got '%s'", name, dataValKind)
 | 
			
		||||
@@ -565,32 +687,29 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value)
 | 
			
		||||
		structs = structs[1:]
 | 
			
		||||
 | 
			
		||||
		structType := structVal.Type()
 | 
			
		||||
 | 
			
		||||
		for i := 0; i < structType.NumField(); i++ {
 | 
			
		||||
			fieldType := structType.Field(i)
 | 
			
		||||
			fieldKind := fieldType.Type.Kind()
 | 
			
		||||
 | 
			
		||||
			if fieldType.Anonymous {
 | 
			
		||||
				fieldKind := fieldType.Type.Kind()
 | 
			
		||||
			// If "squash" is specified in the tag, we squash the field down.
 | 
			
		||||
			squash := false
 | 
			
		||||
			tagParts := strings.Split(fieldType.Tag.Get(d.config.TagName), ",")
 | 
			
		||||
			for _, tag := range tagParts[1:] {
 | 
			
		||||
				if tag == "squash" {
 | 
			
		||||
					squash = true
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if squash {
 | 
			
		||||
				if fieldKind != reflect.Struct {
 | 
			
		||||
					errors = appendErrors(errors,
 | 
			
		||||
						fmt.Errorf("%s: unsupported type: %s", fieldType.Name, fieldKind))
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// We have an embedded field. We "squash" the fields down
 | 
			
		||||
				// if specified in the tag.
 | 
			
		||||
				squash := false
 | 
			
		||||
				tagParts := strings.Split(fieldType.Tag.Get(d.config.TagName), ",")
 | 
			
		||||
				for _, tag := range tagParts[1:] {
 | 
			
		||||
					if tag == "squash" {
 | 
			
		||||
						squash = true
 | 
			
		||||
						break
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if squash {
 | 
			
		||||
						fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldKind))
 | 
			
		||||
				} else {
 | 
			
		||||
					structs = append(structs, val.FieldByName(fieldType.Name))
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Normal struct field, store it away
 | 
			
		||||
@@ -612,7 +731,7 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value)
 | 
			
		||||
		if !rawMapVal.IsValid() {
 | 
			
		||||
			// Do a slower search by iterating over each key and
 | 
			
		||||
			// doing case-insensitive search.
 | 
			
		||||
			for dataValKey, _ := range dataValKeys {
 | 
			
		||||
			for dataValKey := range dataValKeys {
 | 
			
		||||
				mK, ok := dataValKey.Interface().(string)
 | 
			
		||||
				if !ok {
 | 
			
		||||
					// Not a string key
 | 
			
		||||
@@ -660,7 +779,7 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value)
 | 
			
		||||
 | 
			
		||||
	if d.config.ErrorUnused && len(dataValKeysUnused) > 0 {
 | 
			
		||||
		keys := make([]string, 0, len(dataValKeysUnused))
 | 
			
		||||
		for rawKey, _ := range dataValKeysUnused {
 | 
			
		||||
		for rawKey := range dataValKeysUnused {
 | 
			
		||||
			keys = append(keys, rawKey.(string))
 | 
			
		||||
		}
 | 
			
		||||
		sort.Strings(keys)
 | 
			
		||||
@@ -675,7 +794,7 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value)
 | 
			
		||||
 | 
			
		||||
	// Add the unused keys to the list of unused keys if we're tracking metadata
 | 
			
		||||
	if d.config.Metadata != nil {
 | 
			
		||||
		for rawKey, _ := range dataValKeysUnused {
 | 
			
		||||
		for rawKey := range dataValKeysUnused {
 | 
			
		||||
			key := rawKey.(string)
 | 
			
		||||
			if name != "" {
 | 
			
		||||
				key = fmt.Sprintf("%s.%s", name, key)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user