Bump github.com/go-viper/mapstructure/v2 in the go_modules group (#27)
Some checks failed
CodeQL / Analyze (go) (push) Has been cancelled
Docker / build (push) Has been cancelled
golangci-lint / lint (push) Has been cancelled

Bumps the go_modules group with 1 update: [github.com/go-viper/mapstructure/v2](https://github.com/go-viper/mapstructure).


Updates `github.com/go-viper/mapstructure/v2` from 2.3.0 to 2.4.0
- [Release notes](https://github.com/go-viper/mapstructure/releases)
- [Changelog](https://github.com/go-viper/mapstructure/blob/main/CHANGELOG.md)
- [Commits](https://github.com/go-viper/mapstructure/compare/v2.3.0...v2.4.0)

---
updated-dependencies:
- dependency-name: github.com/go-viper/mapstructure/v2
  dependency-version: 2.4.0
  dependency-type: indirect
  dependency-group: go_modules
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
dependabot[bot]
2025-08-26 12:36:59 +03:00
committed by GitHub
parent d7f1de425f
commit 539a62678b
8 changed files with 370 additions and 131 deletions

2
go.mod
View File

@@ -10,7 +10,7 @@ require (
require (
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/go-viper/mapstructure/v2 v2.3.0 // indirect
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
github.com/sagikazarmark/locafero v0.9.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect

4
go.sum
View File

@@ -4,8 +4,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/go-viper/mapstructure/v2 v2.3.0 h1:27XbWsHIqhbdR5TIC911OfYvgSaW93HM+dX7970Q7jk=
github.com/go-viper/mapstructure/v2 v2.3.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/gorilla/feeds v1.2.0 h1:O6pBiXJ5JHhPvqy53NsjKOThq+dNFm8+DFrxBEdzSCc=

View File

@@ -37,3 +37,12 @@ formatters:
- standard
- default
- localmodule
gofmt:
simplify: true
rewrite-rules:
- pattern: interface{}
replacement: any
exclusions:
paths:
- internal/

View File

@@ -1,7 +1,7 @@
# mapstructure
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/go-viper/mapstructure/ci.yaml?style=flat-square)](https://github.com/go-viper/mapstructure/actions/workflows/ci.yaml)
[![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/mod/github.com/go-viper/mapstructure)
[![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/mod/github.com/go-viper/mapstructure/v2)
![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/go-viper/mapstructure?style=flat-square&color=61CFDD)
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/go-viper/mapstructure/badge?style=flat-square)](https://deps.dev/go/github.com%252Fgo-viper%252Fmapstructure%252Fv2)

View File

@@ -13,7 +13,7 @@ import (
"time"
)
// typedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns
// typedDecodeHook takes a raw DecodeHookFunc (an any) 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
@@ -23,7 +23,7 @@ func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc {
// Fill in the variables into this interface and the rest is done
// automatically using the reflect package.
potential := []interface{}{f1, f2, f3}
potential := []any{f1, f2, f3}
v := reflect.ValueOf(h)
vt := v.Type()
@@ -37,25 +37,25 @@ func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc {
return nil
}
// cachedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns
// cachedDecodeHook takes a raw DecodeHookFunc (an any) 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) {
func cachedDecodeHook(raw DecodeHookFunc) func(from reflect.Value, to reflect.Value) (any, error) {
switch f := typedDecodeHook(raw).(type) {
case DecodeHookFuncType:
return func(from reflect.Value, to reflect.Value) (interface{}, error) {
return func(from reflect.Value, to reflect.Value) (any, error) {
return f(from.Type(), to.Type(), from.Interface())
}
case DecodeHookFuncKind:
return func(from reflect.Value, to reflect.Value) (interface{}, error) {
return func(from reflect.Value, to reflect.Value) (any, error) {
return f(from.Kind(), to.Kind(), from.Interface())
}
case DecodeHookFuncValue:
return func(from reflect.Value, to reflect.Value) (interface{}, error) {
return func(from reflect.Value, to reflect.Value) (any, error) {
return f(from, to)
}
default:
return func(from reflect.Value, to reflect.Value) (interface{}, error) {
return func(from reflect.Value, to reflect.Value) (any, error) {
return nil, errors.New("invalid decode hook signature")
}
}
@@ -67,7 +67,7 @@ func cachedDecodeHook(raw DecodeHookFunc) func(from reflect.Value, to reflect.Va
func DecodeHookExec(
raw DecodeHookFunc,
from reflect.Value, to reflect.Value,
) (interface{}, error) {
) (any, error) {
switch f := typedDecodeHook(raw).(type) {
case DecodeHookFuncType:
return f(from.Type(), to.Type(), from.Interface())
@@ -86,11 +86,11 @@ func DecodeHookExec(
// The composed funcs are called in order, with the result of the
// previous transformation.
func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
cached := make([]func(from reflect.Value, to reflect.Value) (interface{}, error), 0, len(fs))
cached := make([]func(from reflect.Value, to reflect.Value) (any, 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) (any, error) {
var err error
data := f.Interface()
@@ -114,13 +114,13 @@ 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.
// If all hooks return an error, OrComposeDecodeHookFunc returns an error concatenating all error messages.
func OrComposeDecodeHookFunc(ff ...DecodeHookFunc) DecodeHookFunc {
cached := make([]func(from reflect.Value, to reflect.Value) (interface{}, error), 0, len(ff))
cached := make([]func(from reflect.Value, to reflect.Value) (any, 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) (any, error) {
var allErrs string
var out interface{}
var out any
var err error
for _, c := range cached {
@@ -143,8 +143,8 @@ func StringToSliceHookFunc(sep string) DecodeHookFunc {
return func(
f reflect.Type,
t reflect.Type,
data interface{},
) (interface{}, error) {
data any,
) (any, error) {
if f.Kind() != reflect.String {
return data, nil
}
@@ -161,14 +161,37 @@ func StringToSliceHookFunc(sep string) DecodeHookFunc {
}
}
// StringToWeakSliceHookFunc brings back the old (pre-v2) behavior of [StringToSliceHookFunc].
//
// As of mapstructure v2.0.0 [StringToSliceHookFunc] checks if the return type is a string slice.
// This function removes that check.
func StringToWeakSliceHookFunc(sep string) DecodeHookFunc {
return func(
f reflect.Type,
t reflect.Type,
data any,
) (any, error) {
if f.Kind() != reflect.String || t.Kind() != reflect.Slice {
return data, nil
}
raw := data.(string)
if raw == "" {
return []string{}, nil
}
return strings.Split(raw, sep), nil
}
}
// 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) {
data any,
) (any, error) {
if f.Kind() != reflect.String {
return data, nil
}
@@ -177,7 +200,29 @@ func StringToTimeDurationHookFunc() DecodeHookFunc {
}
// Convert it by parsing
return time.ParseDuration(data.(string))
d, err := time.ParseDuration(data.(string))
return d, wrapTimeParseDurationError(err)
}
}
// StringToTimeLocationHookFunc returns a DecodeHookFunc that converts
// strings to *time.Location.
func StringToTimeLocationHookFunc() DecodeHookFunc {
return func(
f reflect.Type,
t reflect.Type,
data any,
) (any, error) {
if f.Kind() != reflect.String {
return data, nil
}
if t != reflect.TypeOf(time.Local) {
return data, nil
}
d, err := time.LoadLocation(data.(string))
return d, wrapTimeParseLocationError(err)
}
}
@@ -187,8 +232,8 @@ func StringToURLHookFunc() DecodeHookFunc {
return func(
f reflect.Type,
t reflect.Type,
data interface{},
) (interface{}, error) {
data any,
) (any, error) {
if f.Kind() != reflect.String {
return data, nil
}
@@ -197,7 +242,9 @@ func StringToURLHookFunc() DecodeHookFunc {
}
// Convert it by parsing
return url.Parse(data.(string))
u, err := url.Parse(data.(string))
return u, wrapUrlError(err)
}
}
@@ -207,8 +254,8 @@ func StringToIPHookFunc() DecodeHookFunc {
return func(
f reflect.Type,
t reflect.Type,
data interface{},
) (interface{}, error) {
data any,
) (any, error) {
if f.Kind() != reflect.String {
return data, nil
}
@@ -219,7 +266,7 @@ func StringToIPHookFunc() DecodeHookFunc {
// Convert it by parsing
ip := net.ParseIP(data.(string))
if ip == nil {
return net.IP{}, fmt.Errorf("failed parsing ip %v", data)
return net.IP{}, fmt.Errorf("failed parsing ip")
}
return ip, nil
@@ -232,8 +279,8 @@ func StringToIPNetHookFunc() DecodeHookFunc {
return func(
f reflect.Type,
t reflect.Type,
data interface{},
) (interface{}, error) {
data any,
) (any, error) {
if f.Kind() != reflect.String {
return data, nil
}
@@ -243,7 +290,7 @@ func StringToIPNetHookFunc() DecodeHookFunc {
// Convert it by parsing
_, net, err := net.ParseCIDR(data.(string))
return net, err
return net, wrapNetParseError(err)
}
}
@@ -253,8 +300,8 @@ func StringToTimeHookFunc(layout string) DecodeHookFunc {
return func(
f reflect.Type,
t reflect.Type,
data interface{},
) (interface{}, error) {
data any,
) (any, error) {
if f.Kind() != reflect.String {
return data, nil
}
@@ -263,7 +310,9 @@ func StringToTimeHookFunc(layout string) DecodeHookFunc {
}
// Convert it by parsing
return time.Parse(layout, data.(string))
ti, err := time.Parse(layout, data.(string))
return ti, wrapTimeParseError(err)
}
}
@@ -275,8 +324,8 @@ func StringToTimeHookFunc(layout string) DecodeHookFunc {
func WeaklyTypedHook(
f reflect.Kind,
t reflect.Kind,
data interface{},
) (interface{}, error) {
data any,
) (any, error) {
dataVal := reflect.ValueOf(data)
switch t {
case reflect.String:
@@ -305,17 +354,17 @@ func WeaklyTypedHook(
}
func RecursiveStructToMapHookFunc() DecodeHookFunc {
return func(f reflect.Value, t reflect.Value) (interface{}, error) {
return func(f reflect.Value, t reflect.Value) (any, error) {
if f.Kind() != reflect.Struct {
return f.Interface(), nil
}
var i interface{} = struct{}{}
var i any = struct{}{}
if t.Type() != reflect.TypeOf(&i).Elem() {
return f.Interface(), nil
}
m := make(map[string]interface{})
m := make(map[string]any)
t.Set(reflect.ValueOf(m))
return f.Interface(), nil
@@ -329,8 +378,8 @@ func TextUnmarshallerHookFunc() DecodeHookFuncType {
return func(
f reflect.Type,
t reflect.Type,
data interface{},
) (interface{}, error) {
data any,
) (any, error) {
if f.Kind() != reflect.String {
return data, nil
}
@@ -356,8 +405,8 @@ func StringToNetIPAddrHookFunc() DecodeHookFunc {
return func(
f reflect.Type,
t reflect.Type,
data interface{},
) (interface{}, error) {
data any,
) (any, error) {
if f.Kind() != reflect.String {
return data, nil
}
@@ -366,7 +415,9 @@ func StringToNetIPAddrHookFunc() DecodeHookFunc {
}
// Convert it by parsing
return netip.ParseAddr(data.(string))
addr, err := netip.ParseAddr(data.(string))
return addr, wrapNetIPParseAddrError(err)
}
}
@@ -376,8 +427,8 @@ func StringToNetIPAddrPortHookFunc() DecodeHookFunc {
return func(
f reflect.Type,
t reflect.Type,
data interface{},
) (interface{}, error) {
data any,
) (any, error) {
if f.Kind() != reflect.String {
return data, nil
}
@@ -386,7 +437,9 @@ func StringToNetIPAddrPortHookFunc() DecodeHookFunc {
}
// Convert it by parsing
return netip.ParseAddrPort(data.(string))
addrPort, err := netip.ParseAddrPort(data.(string))
return addrPort, wrapNetIPParseAddrPortError(err)
}
}
@@ -396,8 +449,8 @@ func StringToNetIPPrefixHookFunc() DecodeHookFunc {
return func(
f reflect.Type,
t reflect.Type,
data interface{},
) (interface{}, error) {
data any,
) (any, error) {
if f.Kind() != reflect.String {
return data, nil
}
@@ -406,7 +459,9 @@ func StringToNetIPPrefixHookFunc() DecodeHookFunc {
}
// Convert it by parsing
return netip.ParsePrefix(data.(string))
prefix, err := netip.ParsePrefix(data.(string))
return prefix, wrapNetIPParsePrefixError(err)
}
}
@@ -439,178 +494,182 @@ func StringToBasicTypeHookFunc() DecodeHookFunc {
// StringToInt8HookFunc returns a DecodeHookFunc that converts
// strings to int8.
func StringToInt8HookFunc() DecodeHookFunc {
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
if f.Kind() != reflect.String || t.Kind() != reflect.Int8 {
return data, nil
}
// Convert it by parsing
i64, err := strconv.ParseInt(data.(string), 0, 8)
return int8(i64), err
return int8(i64), wrapStrconvNumError(err)
}
}
// StringToUint8HookFunc returns a DecodeHookFunc that converts
// strings to uint8.
func StringToUint8HookFunc() DecodeHookFunc {
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
if f.Kind() != reflect.String || t.Kind() != reflect.Uint8 {
return data, nil
}
// Convert it by parsing
u64, err := strconv.ParseUint(data.(string), 0, 8)
return uint8(u64), err
return uint8(u64), wrapStrconvNumError(err)
}
}
// StringToInt16HookFunc returns a DecodeHookFunc that converts
// strings to int16.
func StringToInt16HookFunc() DecodeHookFunc {
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
if f.Kind() != reflect.String || t.Kind() != reflect.Int16 {
return data, nil
}
// Convert it by parsing
i64, err := strconv.ParseInt(data.(string), 0, 16)
return int16(i64), err
return int16(i64), wrapStrconvNumError(err)
}
}
// StringToUint16HookFunc returns a DecodeHookFunc that converts
// strings to uint16.
func StringToUint16HookFunc() DecodeHookFunc {
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
if f.Kind() != reflect.String || t.Kind() != reflect.Uint16 {
return data, nil
}
// Convert it by parsing
u64, err := strconv.ParseUint(data.(string), 0, 16)
return uint16(u64), err
return uint16(u64), wrapStrconvNumError(err)
}
}
// StringToInt32HookFunc returns a DecodeHookFunc that converts
// strings to int32.
func StringToInt32HookFunc() DecodeHookFunc {
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
if f.Kind() != reflect.String || t.Kind() != reflect.Int32 {
return data, nil
}
// Convert it by parsing
i64, err := strconv.ParseInt(data.(string), 0, 32)
return int32(i64), err
return int32(i64), wrapStrconvNumError(err)
}
}
// StringToUint32HookFunc returns a DecodeHookFunc that converts
// strings to uint32.
func StringToUint32HookFunc() DecodeHookFunc {
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
if f.Kind() != reflect.String || t.Kind() != reflect.Uint32 {
return data, nil
}
// Convert it by parsing
u64, err := strconv.ParseUint(data.(string), 0, 32)
return uint32(u64), err
return uint32(u64), wrapStrconvNumError(err)
}
}
// StringToInt64HookFunc returns a DecodeHookFunc that converts
// strings to int64.
func StringToInt64HookFunc() DecodeHookFunc {
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
if f.Kind() != reflect.String || t.Kind() != reflect.Int64 {
return data, nil
}
// Convert it by parsing
return strconv.ParseInt(data.(string), 0, 64)
i64, err := strconv.ParseInt(data.(string), 0, 64)
return int64(i64), wrapStrconvNumError(err)
}
}
// StringToUint64HookFunc returns a DecodeHookFunc that converts
// strings to uint64.
func StringToUint64HookFunc() DecodeHookFunc {
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
if f.Kind() != reflect.String || t.Kind() != reflect.Uint64 {
return data, nil
}
// Convert it by parsing
return strconv.ParseUint(data.(string), 0, 64)
u64, err := strconv.ParseUint(data.(string), 0, 64)
return uint64(u64), wrapStrconvNumError(err)
}
}
// StringToIntHookFunc returns a DecodeHookFunc that converts
// strings to int.
func StringToIntHookFunc() DecodeHookFunc {
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
if f.Kind() != reflect.String || t.Kind() != reflect.Int {
return data, nil
}
// Convert it by parsing
i64, err := strconv.ParseInt(data.(string), 0, 0)
return int(i64), err
return int(i64), wrapStrconvNumError(err)
}
}
// StringToUintHookFunc returns a DecodeHookFunc that converts
// strings to uint.
func StringToUintHookFunc() DecodeHookFunc {
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
if f.Kind() != reflect.String || t.Kind() != reflect.Uint {
return data, nil
}
// Convert it by parsing
u64, err := strconv.ParseUint(data.(string), 0, 0)
return uint(u64), err
return uint(u64), wrapStrconvNumError(err)
}
}
// StringToFloat32HookFunc returns a DecodeHookFunc that converts
// strings to float32.
func StringToFloat32HookFunc() DecodeHookFunc {
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
if f.Kind() != reflect.String || t.Kind() != reflect.Float32 {
return data, nil
}
// Convert it by parsing
f64, err := strconv.ParseFloat(data.(string), 32)
return float32(f64), err
return float32(f64), wrapStrconvNumError(err)
}
}
// StringToFloat64HookFunc returns a DecodeHookFunc that converts
// strings to float64.
func StringToFloat64HookFunc() DecodeHookFunc {
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
if f.Kind() != reflect.String || t.Kind() != reflect.Float64 {
return data, nil
}
// Convert it by parsing
return strconv.ParseFloat(data.(string), 64)
f64, err := strconv.ParseFloat(data.(string), 64)
return f64, wrapStrconvNumError(err)
}
}
// StringToBoolHookFunc returns a DecodeHookFunc that converts
// strings to bool.
func StringToBoolHookFunc() DecodeHookFunc {
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
if f.Kind() != reflect.String || t.Kind() != reflect.Bool {
return data, nil
}
// Convert it by parsing
return strconv.ParseBool(data.(string))
b, err := strconv.ParseBool(data.(string))
return b, wrapStrconvNumError(err)
}
}
@@ -629,26 +688,27 @@ func StringToRuneHookFunc() DecodeHookFunc {
// StringToComplex64HookFunc returns a DecodeHookFunc that converts
// strings to complex64.
func StringToComplex64HookFunc() DecodeHookFunc {
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
if f.Kind() != reflect.String || t.Kind() != reflect.Complex64 {
return data, nil
}
// Convert it by parsing
c128, err := strconv.ParseComplex(data.(string), 64)
return complex64(c128), err
return complex64(c128), wrapStrconvNumError(err)
}
}
// StringToComplex128HookFunc returns a DecodeHookFunc that converts
// strings to complex128.
func StringToComplex128HookFunc() DecodeHookFunc {
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
return func(f reflect.Type, t reflect.Type, data any) (any, error) {
if f.Kind() != reflect.String || t.Kind() != reflect.Complex128 {
return data, nil
}
// Convert it by parsing
return strconv.ParseComplex(data.(string), 128)
c128, err := strconv.ParseComplex(data.(string), 128)
return c128, wrapStrconvNumError(err)
}
}

View File

@@ -1,8 +1,14 @@
package mapstructure
import (
"errors"
"fmt"
"net"
"net/url"
"reflect"
"strconv"
"strings"
"time"
)
// Error interface is implemented by all errors emitted by mapstructure.
@@ -72,3 +78,167 @@ func (e *UnconvertibleTypeError) Error() string {
}
func (*UnconvertibleTypeError) mapstructure() {}
func wrapStrconvNumError(err error) error {
if err == nil {
return nil
}
if err, ok := err.(*strconv.NumError); ok {
return &strconvNumError{Err: err}
}
return err
}
type strconvNumError struct {
Err *strconv.NumError
}
func (e *strconvNumError) Error() string {
return "strconv." + e.Err.Func + ": " + e.Err.Err.Error()
}
func (e *strconvNumError) Unwrap() error { return e.Err }
func wrapUrlError(err error) error {
if err == nil {
return nil
}
if err, ok := err.(*url.Error); ok {
return &urlError{Err: err}
}
return err
}
type urlError struct {
Err *url.Error
}
func (e *urlError) Error() string {
return fmt.Sprintf("%s", e.Err.Err)
}
func (e *urlError) Unwrap() error { return e.Err }
func wrapNetParseError(err error) error {
if err == nil {
return nil
}
if err, ok := err.(*net.ParseError); ok {
return &netParseError{Err: err}
}
return err
}
type netParseError struct {
Err *net.ParseError
}
func (e *netParseError) Error() string {
return "invalid " + e.Err.Type
}
func (e *netParseError) Unwrap() error { return e.Err }
func wrapTimeParseError(err error) error {
if err == nil {
return nil
}
if err, ok := err.(*time.ParseError); ok {
return &timeParseError{Err: err}
}
return err
}
type timeParseError struct {
Err *time.ParseError
}
func (e *timeParseError) Error() string {
if e.Err.Message == "" {
return fmt.Sprintf("parsing time as %q: cannot parse as %q", e.Err.Layout, e.Err.LayoutElem)
}
return "parsing time " + e.Err.Message
}
func (e *timeParseError) Unwrap() error { return e.Err }
func wrapNetIPParseAddrError(err error) error {
if err == nil {
return nil
}
if errMsg := err.Error(); strings.HasPrefix(errMsg, "ParseAddr") {
errPieces := strings.Split(errMsg, ": ")
return fmt.Errorf("ParseAddr: %s", errPieces[len(errPieces)-1])
}
return err
}
func wrapNetIPParseAddrPortError(err error) error {
if err == nil {
return nil
}
errMsg := err.Error()
if strings.HasPrefix(errMsg, "invalid port ") {
return errors.New("invalid port")
} else if strings.HasPrefix(errMsg, "invalid ip:port ") {
return errors.New("invalid ip:port")
}
return err
}
func wrapNetIPParsePrefixError(err error) error {
if err == nil {
return nil
}
if errMsg := err.Error(); strings.HasPrefix(errMsg, "netip.ParsePrefix") {
errPieces := strings.Split(errMsg, ": ")
return fmt.Errorf("netip.ParsePrefix: %s", errPieces[len(errPieces)-1])
}
return err
}
func wrapTimeParseDurationError(err error) error {
if err == nil {
return nil
}
errMsg := err.Error()
if strings.HasPrefix(errMsg, "time: unknown unit ") {
return errors.New("time: unknown unit")
} else if strings.HasPrefix(errMsg, "time: ") {
idx := strings.LastIndex(errMsg, " ")
return errors.New(errMsg[:idx])
}
return err
}
func wrapTimeParseLocationError(err error) error {
if err == nil {
return nil
}
errMsg := err.Error()
if strings.Contains(errMsg, "unknown time zone") || strings.HasPrefix(errMsg, "time: unknown format") {
return fmt.Errorf("invalid time zone format: %w", err)
}
return err
}

View File

@@ -1,5 +1,5 @@
// Package mapstructure exposes functionality to convert one arbitrary
// Go type into another, typically to convert a map[string]interface{}
// Go type into another, typically to convert a map[string]any
// into a native Go structure.
//
// The Go structure can be arbitrarily complex, containing slices,
@@ -54,8 +54,8 @@
//
// This would require an input that looks like below:
//
// map[string]interface{}{
// "person": map[string]interface{}{"name": "alice"},
// map[string]any{
// "person": map[string]any{"name": "alice"},
// }
//
// If your "person" value is NOT nested, then you can append ",squash" to
@@ -68,7 +68,7 @@
//
// Now the following input would be accepted:
//
// map[string]interface{}{
// map[string]any{
// "name": "alice",
// }
//
@@ -79,7 +79,7 @@
//
// Will be decoded into a map:
//
// map[string]interface{}{
// map[string]any{
// "name": "alice",
// }
//
@@ -95,18 +95,18 @@
//
// You can also use the ",remain" suffix on your tag to collect all unused
// values in a map. The field with this tag MUST be a map type and should
// probably be a "map[string]interface{}" or "map[interface{}]interface{}".
// probably be a "map[string]any" or "map[any]any".
// See example below:
//
// type Friend struct {
// Name string
// Other map[string]interface{} `mapstructure:",remain"`
// Other map[string]any `mapstructure:",remain"`
// }
//
// Given the input below, Other would be populated with the other
// values that weren't used (everything but "name"):
//
// map[string]interface{}{
// map[string]any{
// "name": "bob",
// "address": "123 Maple St.",
// }
@@ -161,7 +161,7 @@
//
// Using this map as input:
//
// map[string]interface{}{
// map[string]any{
// "private": "I will be ignored",
// "Public": "I made it through!",
// }
@@ -204,19 +204,19 @@ import (
// 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 DecodeHookFunc any
// DecodeHookFuncType is a DecodeHookFunc which has complete information about
// the source and target types.
type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error)
type DecodeHookFuncType func(reflect.Type, reflect.Type, any) (any, error)
// DecodeHookFuncKind is a DecodeHookFunc which knows only the Kinds of the
// source and target types.
type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error)
type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, any) (any, error)
// DecodeHookFuncValue is a DecodeHookFunc which has complete access to both the source and target
// values.
type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (interface{}, error)
type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (any, error)
// DecoderConfig is the configuration that is used to create a new decoder
// and allows customization of various aspects of decoding.
@@ -287,7 +287,7 @@ type DecoderConfig struct {
// Result is a pointer to the struct that will contain the decoded
// value.
Result interface{}
Result any
// The tag name that mapstructure reads for field names. This
// defaults to "mapstructure"
@@ -319,7 +319,7 @@ type DecoderConfig struct {
// up the most basic Decoder.
type Decoder struct {
config *DecoderConfig
cachedDecodeHook func(from reflect.Value, to reflect.Value) (interface{}, error)
cachedDecodeHook func(from reflect.Value, to reflect.Value) (any, error)
}
// Metadata contains information about decoding a structure that
@@ -340,7 +340,7 @@ type Metadata struct {
// Decode takes an input structure and uses reflection to translate it to
// the output structure. output must be a pointer to a map or struct.
func Decode(input interface{}, output interface{}) error {
func Decode(input any, output any) error {
config := &DecoderConfig{
Metadata: nil,
Result: output,
@@ -356,7 +356,7 @@ func Decode(input interface{}, output interface{}) error {
// WeakDecode is the same as Decode but is shorthand to enable
// WeaklyTypedInput. See DecoderConfig for more info.
func WeakDecode(input, output interface{}) error {
func WeakDecode(input, output any) error {
config := &DecoderConfig{
Metadata: nil,
Result: output,
@@ -373,7 +373,7 @@ func WeakDecode(input, output interface{}) error {
// DecodeMetadata is the same as Decode, but is shorthand to
// enable metadata collection. See DecoderConfig for more info.
func DecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error {
func DecodeMetadata(input any, output any, metadata *Metadata) error {
config := &DecoderConfig{
Metadata: metadata,
Result: output,
@@ -390,7 +390,7 @@ func DecodeMetadata(input interface{}, output interface{}, metadata *Metadata) e
// WeakDecodeMetadata is the same as Decode, but is shorthand to
// enable both WeaklyTypedInput and metadata collection. See
// DecoderConfig for more info.
func WeakDecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error {
func WeakDecodeMetadata(input any, output any, metadata *Metadata) error {
config := &DecoderConfig{
Metadata: metadata,
Result: output,
@@ -457,7 +457,7 @@ func NewDecoder(config *DecoderConfig) (*Decoder, error) {
// Decode decodes the given raw interface to the target pointer specified
// by the configuration.
func (d *Decoder) Decode(input interface{}) error {
func (d *Decoder) Decode(input any) error {
err := d.decode("", input, reflect.ValueOf(d.config.Result).Elem())
// Retain some of the original behavior when multiple errors ocurr
@@ -470,7 +470,7 @@ func (d *Decoder) Decode(input interface{}) error {
}
// isNil returns true if the input is nil or a typed nil pointer.
func isNil(input interface{}) bool {
func isNil(input any) bool {
if input == nil {
return true
}
@@ -479,7 +479,7 @@ func isNil(input interface{}) bool {
}
// 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 any, outVal reflect.Value) error {
var (
inputVal = reflect.ValueOf(input)
outputKind = getKind(outVal)
@@ -516,10 +516,10 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e
// 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{}
var mapVal map[string]any
inputVal = reflect.ValueOf(mapVal) // create nil map pointer
case reflect.Slice, reflect.Array:
var sliceVal []interface{}
var sliceVal []any
inputVal = reflect.ValueOf(sliceVal) // create nil slice pointer
default:
inputVal = reflect.Zero(outVal.Type())
@@ -583,7 +583,7 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e
// This decodes a basic type (bool, int, string, etc.) and sets the
// value to "data" of that type.
func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error {
func (d *Decoder) decodeBasic(name string, data any, val reflect.Value) error {
if val.IsValid() && val.Elem().IsValid() {
elem := val.Elem()
@@ -640,7 +640,7 @@ func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value)
return nil
}
func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) error {
func (d *Decoder) decodeString(name string, data any, val reflect.Value) error {
dataVal := reflect.Indirect(reflect.ValueOf(data))
dataKind := getKind(dataVal)
@@ -693,7 +693,7 @@ func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value)
return nil
}
func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error {
func (d *Decoder) decodeInt(name string, data any, val reflect.Value) error {
dataVal := reflect.Indirect(reflect.ValueOf(data))
dataKind := getKind(dataVal)
dataType := dataVal.Type()
@@ -724,7 +724,7 @@ func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) er
return newDecodeError(name, &ParseError{
Expected: val,
Value: data,
Err: err,
Err: wrapStrconvNumError(err),
})
}
case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
@@ -748,7 +748,7 @@ func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) er
return nil
}
func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) error {
func (d *Decoder) decodeUint(name string, data any, val reflect.Value) error {
dataVal := reflect.Indirect(reflect.ValueOf(data))
dataKind := getKind(dataVal)
dataType := dataVal.Type()
@@ -795,7 +795,7 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e
return newDecodeError(name, &ParseError{
Expected: val,
Value: data,
Err: err,
Err: wrapStrconvNumError(err),
})
}
case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
@@ -805,7 +805,7 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e
return newDecodeError(name, &ParseError{
Expected: val,
Value: data,
Err: err,
Err: wrapStrconvNumError(err),
})
}
val.SetUint(i)
@@ -819,7 +819,7 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e
return nil
}
func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) error {
func (d *Decoder) decodeBool(name string, data any, val reflect.Value) error {
dataVal := reflect.Indirect(reflect.ValueOf(data))
dataKind := getKind(dataVal)
@@ -842,7 +842,7 @@ func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) e
return newDecodeError(name, &ParseError{
Expected: val,
Value: data,
Err: err,
Err: wrapStrconvNumError(err),
})
}
default:
@@ -855,7 +855,7 @@ func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) e
return nil
}
func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error {
func (d *Decoder) decodeFloat(name string, data any, val reflect.Value) error {
dataVal := reflect.Indirect(reflect.ValueOf(data))
dataKind := getKind(dataVal)
dataType := dataVal.Type()
@@ -886,7 +886,7 @@ func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value)
return newDecodeError(name, &ParseError{
Expected: val,
Value: data,
Err: err,
Err: wrapStrconvNumError(err),
})
}
case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
@@ -910,7 +910,7 @@ func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value)
return nil
}
func (d *Decoder) decodeComplex(name string, data interface{}, val reflect.Value) error {
func (d *Decoder) decodeComplex(name string, data any, val reflect.Value) error {
dataVal := reflect.Indirect(reflect.ValueOf(data))
dataKind := getKind(dataVal)
@@ -927,7 +927,7 @@ func (d *Decoder) decodeComplex(name string, data interface{}, val reflect.Value
return nil
}
func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) error {
func (d *Decoder) decodeMap(name string, data any, val reflect.Value) error {
valType := val.Type()
valKeyType := valType.Key()
valElemType := valType.Elem()
@@ -1176,7 +1176,7 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
return nil
}
func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) (bool, error) {
func (d *Decoder) decodePtr(name string, data any, val reflect.Value) (bool, error) {
// If the input data is nil, then we want to just set the output
// pointer to be nil as well.
isNil := data == nil
@@ -1223,7 +1223,7 @@ func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) (b
return false, nil
}
func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) error {
func (d *Decoder) decodeFunc(name string, data any, 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))
@@ -1237,7 +1237,7 @@ func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) e
return nil
}
func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error {
func (d *Decoder) decodeSlice(name string, data any, val reflect.Value) error {
dataVal := reflect.Indirect(reflect.ValueOf(data))
dataValKind := dataVal.Kind()
valType := val.Type()
@@ -1259,7 +1259,7 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value)
return nil
}
// Create slice of maps of other sizes
return d.decodeSlice(name, []interface{}{data}, val)
return d.decodeSlice(name, []any{data}, val)
case dataValKind == reflect.String && valElemType.Kind() == reflect.Uint8:
return d.decodeSlice(name, []byte(dataVal.String()), val)
@@ -1268,7 +1268,7 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value)
// 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 d.decodeSlice(name, []any{data}, val)
}
}
@@ -1311,7 +1311,7 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value)
return errors.Join(errs...)
}
func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) error {
func (d *Decoder) decodeArray(name string, data any, val reflect.Value) error {
dataVal := reflect.Indirect(reflect.ValueOf(data))
dataValKind := dataVal.Kind()
valType := val.Type()
@@ -1336,7 +1336,7 @@ func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value)
// and "lift" it into it. i.e. a string becomes a string array.
default:
// Just re-try this function with data as a slice.
return d.decodeArray(name, []interface{}{data}, val)
return d.decodeArray(name, []any{data}, val)
}
}
@@ -1372,7 +1372,7 @@ func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value)
return errors.Join(errs...)
}
func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) error {
func (d *Decoder) decodeStruct(name string, data any, val reflect.Value) error {
dataVal := reflect.Indirect(reflect.ValueOf(data))
// If the type of the value to write to and the data match directly,
@@ -1393,7 +1393,7 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value)
// as an intermediary.
// Make a new map to hold our result
mapType := reflect.TypeOf((map[string]interface{})(nil))
mapType := reflect.TypeOf((map[string]any)(nil))
mval := reflect.MakeMap(mapType)
// Creating a pointer to a map so that other methods can completely
@@ -1424,13 +1424,13 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
}
dataValKeys := make(map[reflect.Value]struct{})
dataValKeysUnused := make(map[interface{}]struct{})
dataValKeysUnused := make(map[any]struct{})
for _, dataValKey := range dataVal.MapKeys() {
dataValKeys[dataValKey] = struct{}{}
dataValKeysUnused[dataValKey.Interface()] = struct{}{}
}
targetValKeysUnused := make(map[interface{}]struct{})
targetValKeysUnused := make(map[any]struct{})
var errs []error
@@ -1583,7 +1583,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
// we put the unused keys directly into the remain field.
if remainField != nil && len(dataValKeysUnused) > 0 {
// Build a map of only the unused values
remain := map[interface{}]interface{}{}
remain := map[any]any{}
for key := range dataValKeysUnused {
remain[key] = dataVal.MapIndex(reflect.ValueOf(key)).Interface()
}

2
vendor/modules.txt vendored
View File

@@ -2,7 +2,7 @@
## explicit; go 1.17
github.com/fsnotify/fsnotify
github.com/fsnotify/fsnotify/internal
# github.com/go-viper/mapstructure/v2 v2.3.0
# github.com/go-viper/mapstructure/v2 v2.4.0
## explicit; go 1.18
github.com/go-viper/mapstructure/v2
github.com/go-viper/mapstructure/v2/internal/errors