mirror of https://github.com/docker/cli.git
Merge pull request #5634 from thaJeztah/bump_mapstructure
vendor: github.com/go-viper/mapstructure/v2 v2.2.1
This commit is contained in:
commit
9ccc462005
|
@ -19,7 +19,7 @@ require (
|
||||||
github.com/docker/go-units v0.5.0
|
github.com/docker/go-units v0.5.0
|
||||||
github.com/fvbommel/sortorder v1.1.0
|
github.com/fvbommel/sortorder v1.1.0
|
||||||
github.com/go-jose/go-jose/v4 v4.0.4
|
github.com/go-jose/go-jose/v4 v4.0.4
|
||||||
github.com/go-viper/mapstructure/v2 v2.0.0
|
github.com/go-viper/mapstructure/v2 v2.2.1
|
||||||
github.com/gogo/protobuf v1.3.2
|
github.com/gogo/protobuf v1.3.2
|
||||||
github.com/google/go-cmp v0.6.0
|
github.com/google/go-cmp v0.6.0
|
||||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
||||||
|
|
|
@ -89,8 +89,8 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre
|
||||||
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
||||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/go-viper/mapstructure/v2 v2.0.0 h1:dhn8MZ1gZ0mzeodTG3jt5Vj/o87xZKuNAprG2mQfMfc=
|
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
|
||||||
github.com/go-viper/mapstructure/v2 v2.0.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||||
github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
"net/url"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -36,6 +37,30 @@ func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cachedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns
|
||||||
|
// it into a closure to be used directly
|
||||||
|
// if the type fails to convert we return a closure always erroring to keep the previous behaviour
|
||||||
|
func cachedDecodeHook(raw DecodeHookFunc) func(from reflect.Value, to reflect.Value) (interface{}, error) {
|
||||||
|
switch f := typedDecodeHook(raw).(type) {
|
||||||
|
case DecodeHookFuncType:
|
||||||
|
return func(from reflect.Value, to reflect.Value) (interface{}, error) {
|
||||||
|
return f(from.Type(), to.Type(), from.Interface())
|
||||||
|
}
|
||||||
|
case DecodeHookFuncKind:
|
||||||
|
return func(from reflect.Value, to reflect.Value) (interface{}, error) {
|
||||||
|
return f(from.Kind(), to.Kind(), from.Interface())
|
||||||
|
}
|
||||||
|
case DecodeHookFuncValue:
|
||||||
|
return func(from reflect.Value, to reflect.Value) (interface{}, error) {
|
||||||
|
return f(from, to)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return func(from reflect.Value, to reflect.Value) (interface{}, error) {
|
||||||
|
return nil, errors.New("invalid decode hook signature")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// DecodeHookExec executes the given decode hook. This should be used
|
// DecodeHookExec executes the given decode hook. This should be used
|
||||||
// since it'll naturally degrade to the older backwards compatible DecodeHookFunc
|
// since it'll naturally degrade to the older backwards compatible DecodeHookFunc
|
||||||
// that took reflect.Kind instead of reflect.Type.
|
// that took reflect.Kind instead of reflect.Type.
|
||||||
|
@ -61,13 +86,17 @@ func DecodeHookExec(
|
||||||
// The composed funcs are called in order, with the result of the
|
// The composed funcs are called in order, with the result of the
|
||||||
// previous transformation.
|
// previous transformation.
|
||||||
func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
|
func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
|
||||||
|
cached := make([]func(from reflect.Value, to reflect.Value) (interface{}, error), 0, len(fs))
|
||||||
|
for _, f := range fs {
|
||||||
|
cached = append(cached, cachedDecodeHook(f))
|
||||||
|
}
|
||||||
return func(f reflect.Value, t reflect.Value) (interface{}, error) {
|
return func(f reflect.Value, t reflect.Value) (interface{}, error) {
|
||||||
var err error
|
var err error
|
||||||
data := f.Interface()
|
data := f.Interface()
|
||||||
|
|
||||||
newFrom := f
|
newFrom := f
|
||||||
for _, f1 := range fs {
|
for _, c := range cached {
|
||||||
data, err = DecodeHookExec(f1, newFrom, t)
|
data, err = c(newFrom, t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -81,13 +110,17 @@ func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
|
||||||
// OrComposeDecodeHookFunc executes all input hook functions until one of them returns no error. In that case its value is returned.
|
// OrComposeDecodeHookFunc executes all input hook functions until one of them returns no error. In that case its value is returned.
|
||||||
// If all hooks return an error, OrComposeDecodeHookFunc returns an error concatenating all error messages.
|
// If all hooks return an error, OrComposeDecodeHookFunc returns an error concatenating all error messages.
|
||||||
func OrComposeDecodeHookFunc(ff ...DecodeHookFunc) DecodeHookFunc {
|
func OrComposeDecodeHookFunc(ff ...DecodeHookFunc) DecodeHookFunc {
|
||||||
|
cached := make([]func(from reflect.Value, to reflect.Value) (interface{}, error), 0, len(ff))
|
||||||
|
for _, f := range ff {
|
||||||
|
cached = append(cached, cachedDecodeHook(f))
|
||||||
|
}
|
||||||
return func(a, b reflect.Value) (interface{}, error) {
|
return func(a, b reflect.Value) (interface{}, error) {
|
||||||
var allErrs string
|
var allErrs string
|
||||||
var out interface{}
|
var out interface{}
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
for _, f := range ff {
|
for _, c := range cached {
|
||||||
out, err = DecodeHookExec(f, a, b)
|
out, err = c(a, b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
allErrs += err.Error() + "\n"
|
allErrs += err.Error() + "\n"
|
||||||
continue
|
continue
|
||||||
|
@ -144,6 +177,26 @@ func StringToTimeDurationHookFunc() DecodeHookFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StringToURLHookFunc returns a DecodeHookFunc that converts
|
||||||
|
// strings to *url.URL.
|
||||||
|
func StringToURLHookFunc() 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(&url.URL{}) {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert it by parsing
|
||||||
|
return url.Parse(data.(string))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// StringToIPHookFunc returns a DecodeHookFunc that converts
|
// StringToIPHookFunc returns a DecodeHookFunc that converts
|
||||||
// strings to net.IP
|
// strings to net.IP
|
||||||
func StringToIPHookFunc() DecodeHookFunc {
|
func StringToIPHookFunc() DecodeHookFunc {
|
||||||
|
|
|
@ -266,6 +266,10 @@ type DecoderConfig struct {
|
||||||
// defaults to "mapstructure"
|
// defaults to "mapstructure"
|
||||||
TagName string
|
TagName string
|
||||||
|
|
||||||
|
// The option of the value in the tag that indicates a field should
|
||||||
|
// be squashed. This defaults to "squash".
|
||||||
|
SquashTagOption string
|
||||||
|
|
||||||
// IgnoreUntaggedFields ignores all struct fields without explicit
|
// IgnoreUntaggedFields ignores all struct fields without explicit
|
||||||
// TagName, comparable to `mapstructure:"-"` as default behaviour.
|
// TagName, comparable to `mapstructure:"-"` as default behaviour.
|
||||||
IgnoreUntaggedFields bool
|
IgnoreUntaggedFields bool
|
||||||
|
@ -274,6 +278,10 @@ type DecoderConfig struct {
|
||||||
// field name or tag. Defaults to `strings.EqualFold`. This can be used
|
// field name or tag. Defaults to `strings.EqualFold`. This can be used
|
||||||
// to implement case-sensitive tag values, support snake casing, etc.
|
// to implement case-sensitive tag values, support snake casing, etc.
|
||||||
MatchName func(mapKey, fieldName string) bool
|
MatchName func(mapKey, fieldName string) bool
|
||||||
|
|
||||||
|
// DecodeNil, if set to true, will cause the DecodeHook (if present) to run
|
||||||
|
// even if the input is nil. This can be used to provide default values.
|
||||||
|
DecodeNil bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Decoder takes a raw interface value and turns it into structured
|
// A Decoder takes a raw interface value and turns it into structured
|
||||||
|
@ -283,7 +291,8 @@ type DecoderConfig struct {
|
||||||
// structure. The top-level Decode method is just a convenience that sets
|
// structure. The top-level Decode method is just a convenience that sets
|
||||||
// up the most basic Decoder.
|
// up the most basic Decoder.
|
||||||
type Decoder struct {
|
type Decoder struct {
|
||||||
config *DecoderConfig
|
config *DecoderConfig
|
||||||
|
cachedDecodeHook func(from reflect.Value, to reflect.Value) (interface{}, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Metadata contains information about decoding a structure that
|
// Metadata contains information about decoding a structure that
|
||||||
|
@ -401,6 +410,10 @@ func NewDecoder(config *DecoderConfig) (*Decoder, error) {
|
||||||
config.TagName = "mapstructure"
|
config.TagName = "mapstructure"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config.SquashTagOption == "" {
|
||||||
|
config.SquashTagOption = "squash"
|
||||||
|
}
|
||||||
|
|
||||||
if config.MatchName == nil {
|
if config.MatchName == nil {
|
||||||
config.MatchName = strings.EqualFold
|
config.MatchName = strings.EqualFold
|
||||||
}
|
}
|
||||||
|
@ -408,6 +421,9 @@ func NewDecoder(config *DecoderConfig) (*Decoder, error) {
|
||||||
result := &Decoder{
|
result := &Decoder{
|
||||||
config: config,
|
config: config,
|
||||||
}
|
}
|
||||||
|
if config.DecodeHook != nil {
|
||||||
|
result.cachedDecodeHook = cachedDecodeHook(config.DecodeHook)
|
||||||
|
}
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
@ -426,19 +442,26 @@ func (d *Decoder) Decode(input interface{}) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isNil returns true if the input is nil or a typed nil pointer.
|
||||||
|
func isNil(input interface{}) bool {
|
||||||
|
if input == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
val := reflect.ValueOf(input)
|
||||||
|
return val.Kind() == reflect.Ptr && val.IsNil()
|
||||||
|
}
|
||||||
|
|
||||||
// Decodes an unknown data type into a specific reflection value.
|
// Decodes an unknown data type into a specific reflection value.
|
||||||
func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) error {
|
func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) error {
|
||||||
var inputVal reflect.Value
|
var (
|
||||||
if input != nil {
|
inputVal = reflect.ValueOf(input)
|
||||||
inputVal = reflect.ValueOf(input)
|
outputKind = getKind(outVal)
|
||||||
|
decodeNil = d.config.DecodeNil && d.cachedDecodeHook != nil
|
||||||
// We need to check here if input is a typed nil. Typed nils won't
|
)
|
||||||
// match the "input == nil" below so we check that here.
|
if isNil(input) {
|
||||||
if inputVal.Kind() == reflect.Ptr && inputVal.IsNil() {
|
// Typed nils won't match the "input == nil" below, so reset input.
|
||||||
input = nil
|
input = nil
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if input == nil {
|
if input == nil {
|
||||||
// If the data is nil, then we don't set anything, unless ZeroFields is set
|
// If the data is nil, then we don't set anything, unless ZeroFields is set
|
||||||
// to true.
|
// to true.
|
||||||
|
@ -449,30 +472,46 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e
|
||||||
d.config.Metadata.Keys = append(d.config.Metadata.Keys, name)
|
d.config.Metadata.Keys = append(d.config.Metadata.Keys, name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
if !decodeNil {
|
||||||
}
|
return nil
|
||||||
|
}
|
||||||
if !inputVal.IsValid() {
|
}
|
||||||
// If the input value is invalid, then we just set the value
|
if !inputVal.IsValid() {
|
||||||
// to be the zero value.
|
if !decodeNil {
|
||||||
outVal.Set(reflect.Zero(outVal.Type()))
|
// If the input value is invalid, then we just set the value
|
||||||
if d.config.Metadata != nil && name != "" {
|
// to be the zero value.
|
||||||
d.config.Metadata.Keys = append(d.config.Metadata.Keys, name)
|
outVal.Set(reflect.Zero(outVal.Type()))
|
||||||
|
if d.config.Metadata != nil && name != "" {
|
||||||
|
d.config.Metadata.Keys = append(d.config.Metadata.Keys, name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Hooks need a valid inputVal, so reset it to zero value of outVal type.
|
||||||
|
switch outputKind {
|
||||||
|
case reflect.Struct, reflect.Map:
|
||||||
|
var mapVal map[string]interface{}
|
||||||
|
inputVal = reflect.ValueOf(mapVal) // create nil map pointer
|
||||||
|
case reflect.Slice, reflect.Array:
|
||||||
|
var sliceVal []interface{}
|
||||||
|
inputVal = reflect.ValueOf(sliceVal) // create nil slice pointer
|
||||||
|
default:
|
||||||
|
inputVal = reflect.Zero(outVal.Type())
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if d.config.DecodeHook != nil {
|
if d.cachedDecodeHook != nil {
|
||||||
// We have a DecodeHook, so let's pre-process the input.
|
// We have a DecodeHook, so let's pre-process the input.
|
||||||
var err error
|
var err error
|
||||||
input, err = DecodeHookExec(d.config.DecodeHook, inputVal, outVal)
|
input, err = d.cachedDecodeHook(inputVal, outVal)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error decoding '%s': %w", name, err)
|
return fmt.Errorf("error decoding '%s': %w", name, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if isNil(input) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
outputKind := getKind(outVal)
|
|
||||||
addMetaKey := true
|
addMetaKey := true
|
||||||
switch outputKind {
|
switch outputKind {
|
||||||
case reflect.Bool:
|
case reflect.Bool:
|
||||||
|
@ -753,8 +792,8 @@ func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) e
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
"'%s' expected type '%s', got unconvertible type '%s', value: '%v'",
|
"'%s' expected type '%s', got unconvertible type '%#v', value: '%#v'",
|
||||||
name, val.Type(), dataVal.Type(), data)
|
name, val, dataVal, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -973,7 +1012,7 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
|
||||||
}
|
}
|
||||||
|
|
||||||
// If "squash" is specified in the tag, we squash the field down.
|
// If "squash" is specified in the tag, we squash the field down.
|
||||||
squash = squash || strings.Index(tagValue[index+1:], "squash") != -1
|
squash = squash || strings.Contains(tagValue[index+1:], d.config.SquashTagOption)
|
||||||
if squash {
|
if squash {
|
||||||
// When squashing, the embedded type can be a pointer to a struct.
|
// When squashing, the embedded type can be a pointer to a struct.
|
||||||
if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct {
|
if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct {
|
||||||
|
@ -1351,7 +1390,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
|
||||||
// We always parse the tags cause we're looking for other tags too
|
// We always parse the tags cause we're looking for other tags too
|
||||||
tagParts := strings.Split(fieldType.Tag.Get(d.config.TagName), ",")
|
tagParts := strings.Split(fieldType.Tag.Get(d.config.TagName), ",")
|
||||||
for _, tag := range tagParts[1:] {
|
for _, tag := range tagParts[1:] {
|
||||||
if tag == "squash" {
|
if tag == d.config.SquashTagOption {
|
||||||
squash = true
|
squash = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -1363,10 +1402,15 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
|
||||||
}
|
}
|
||||||
|
|
||||||
if squash {
|
if squash {
|
||||||
if fieldVal.Kind() != reflect.Struct {
|
switch fieldVal.Kind() {
|
||||||
errs = append(errs, fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldVal.Kind()))
|
case reflect.Struct:
|
||||||
} else {
|
|
||||||
structs = append(structs, fieldVal)
|
structs = append(structs, fieldVal)
|
||||||
|
case reflect.Interface:
|
||||||
|
if !fieldVal.IsNil() {
|
||||||
|
structs = append(structs, fieldVal.Elem().Elem())
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
errs = append(errs, fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldVal.Kind()))
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,7 +136,7 @@ github.com/go-logr/logr/funcr
|
||||||
# github.com/go-logr/stdr v1.2.2
|
# github.com/go-logr/stdr v1.2.2
|
||||||
## explicit; go 1.16
|
## explicit; go 1.16
|
||||||
github.com/go-logr/stdr
|
github.com/go-logr/stdr
|
||||||
# github.com/go-viper/mapstructure/v2 v2.0.0
|
# github.com/go-viper/mapstructure/v2 v2.2.1
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
github.com/go-viper/mapstructure/v2
|
github.com/go-viper/mapstructure/v2
|
||||||
github.com/go-viper/mapstructure/v2/internal/errors
|
github.com/go-viper/mapstructure/v2/internal/errors
|
||||||
|
|
Loading…
Reference in New Issue