Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 39 additions & 28 deletions map.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func toMapE[K comparable, V any](i any, keyFn func(any) K, valFn func(any) V) (m
m := map[K]V{}

if i == nil {
return m, fmt.Errorf("unable to cast %#v of type %T to %T", i, i, m)
return nil, fmt.Errorf(errorMsg, i, i, m)
}

switch v := i.(type) {
Expand Down Expand Up @@ -45,31 +45,34 @@ func toMapE[K comparable, V any](i any, keyFn func(any) K, valFn func(any) V) (m

case string:
err := jsonStringToObject(v, &m)
if err != nil {
return nil, err
}

return m, err
return m, nil

default:
return m, fmt.Errorf("unable to cast %#v of type %T to %T", i, i, m)
return nil, fmt.Errorf(errorMsg, i, i, m)
}
}

func toStringMapE[T any](i any, fn func(any) T) (map[string]T, error) {
return toMapE(i, ToString, fn)
}

// ToStringMapStringE casts an interface to a map[string]string type.
// ToStringMapStringE casts any value to a map[string]string type.
func ToStringMapStringE(i any) (map[string]string, error) {
return toStringMapE(i, ToString)
}

// ToStringMapStringSliceE casts an interface to a map[string][]string type.
func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) {
// ToStringMapStringSliceE casts any value to a map[string][]string type.
func ToStringMapStringSliceE(i any) (map[string][]string, error) {
m := map[string][]string{}

switch v := i.(type) {
case map[string][]string:
return v, nil
case map[string][]interface{}:
case map[string][]any:
for k, val := range v {
m[ToString(k)] = ToStringSlice(val)
}
Expand All @@ -78,10 +81,10 @@ func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) {
for k, val := range v {
m[ToString(k)] = []string{val}
}
case map[string]interface{}:
case map[string]any:
for k, val := range v {
switch vt := val.(type) {
case []interface{}:
case []any:
m[ToString(k)] = ToStringSlice(vt)
case []string:
m[ToString(k)] = vt
Expand All @@ -90,49 +93,54 @@ func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) {
}
}
return m, nil
case map[interface{}][]string:
case map[any][]string:
for k, val := range v {
m[ToString(k)] = ToStringSlice(val)
}
return m, nil
case map[interface{}]string:
case map[any]string:
for k, val := range v {
m[ToString(k)] = ToStringSlice(val)
}
return m, nil
case map[interface{}][]interface{}:
case map[any][]any:
for k, val := range v {
m[ToString(k)] = ToStringSlice(val)
}
return m, nil
case map[interface{}]interface{}:
case map[any]any:
for k, val := range v {
key, err := ToStringE(k)
if err != nil {
return m, fmt.Errorf("unable to cast %#v of type %T to map[string][]string", i, i)
return nil, fmt.Errorf(errorMsg, i, i, m)
}
value, err := ToStringSliceE(val)
if err != nil {
return m, fmt.Errorf("unable to cast %#v of type %T to map[string][]string", i, i)
return nil, fmt.Errorf(errorMsg, i, i, m)
}
m[key] = value
}
case string:
err := jsonStringToObject(v, &m)
return m, err
if err != nil {
return nil, err
}

return m, nil
default:
return m, fmt.Errorf("unable to cast %#v of type %T to map[string][]string", i, i)
return nil, fmt.Errorf(errorMsg, i, i, m)
}

return m, nil
}

// ToStringMapBoolE casts an interface to a map[string]bool type.
func ToStringMapBoolE(i interface{}) (map[string]bool, error) {
// ToStringMapBoolE casts any value to a map[string]bool type.
func ToStringMapBoolE(i any) (map[string]bool, error) {
return toStringMapE(i, ToBool)
}

// ToStringMapE casts an interface to a map[string]interface{} type.
func ToStringMapE(i interface{}) (map[string]interface{}, error) {
// ToStringMapE casts any value to a map[string]any type.
func ToStringMapE(i any) (map[string]any, error) {
fn := func(i any) any { return i }

return toStringMapE(i, fn)
Expand All @@ -142,7 +150,7 @@ func toStringMapIntE[T int | int64](i any, fn func(any) T, fnE func(any) (T, err
m := map[string]T{}

if i == nil {
return m, fmt.Errorf("unable to cast %#v of type %T to %T", i, i, m)
return nil, fmt.Errorf(errorMsg, i, i, m)
}

switch v := i.(type) {
Expand Down Expand Up @@ -172,12 +180,15 @@ func toStringMapIntE[T int | int64](i any, fn func(any) T, fnE func(any) (T, err

case string:
err := jsonStringToObject(v, &m)
if err != nil {
return nil, err
}

return m, err
return m, nil
}

if reflect.TypeOf(i).Kind() != reflect.Map {
return m, fmt.Errorf(errorMsg, i, i, m)
return nil, fmt.Errorf(errorMsg, i, i, m)
}

mVal := reflect.ValueOf(m)
Expand All @@ -195,19 +206,19 @@ func toStringMapIntE[T int | int64](i any, fn func(any) T, fnE func(any) (T, err
return m, nil
}

// ToStringMapIntE casts an interface to a map[string]int{} type.
// ToStringMapIntE casts any value to a map[string]int type.
func ToStringMapIntE(i any) (map[string]int, error) {
return toStringMapIntE(i, ToInt, ToIntE)
}

// ToStringMapInt64E casts an interface to a map[string]int64{} type.
func ToStringMapInt64E(i interface{}) (map[string]int64, error) {
// ToStringMapInt64E casts any value to a map[string]int64 type.
func ToStringMapInt64E(i any) (map[string]int64, error) {
return toStringMapIntE(i, ToInt64, ToInt64E)
}

// jsonStringToObject attempts to unmarshall a string as JSON into
// the object passed as pointer.
func jsonStringToObject(s string, v interface{}) error {
func jsonStringToObject(s string, v any) error {
data := []byte(s)
return json.Unmarshal(data, v)
}
Loading