Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
kardolus
GitHub Repository: kardolus/chatgpt-cli
Path: blob/main/vendor/github.com/spf13/cast/map.go
2875 views
1
// Copyright © 2014 Steve Francia <[email protected]>.
2
//
3
// Use of this source code is governed by an MIT-style
4
// license that can be found in the LICENSE file.
5
6
package cast
7
8
import (
9
"encoding/json"
10
"fmt"
11
"reflect"
12
)
13
14
func toMapE[K comparable, V any](i any, keyFn func(any) K, valFn func(any) V) (map[K]V, error) {
15
m := map[K]V{}
16
17
if i == nil {
18
return m, fmt.Errorf(errorMsg, i, i, m)
19
}
20
21
switch v := i.(type) {
22
case map[K]V:
23
return v, nil
24
25
case map[K]any:
26
for k, val := range v {
27
m[k] = valFn(val)
28
}
29
30
return m, nil
31
32
case map[any]V:
33
for k, val := range v {
34
m[keyFn(k)] = val
35
}
36
37
return m, nil
38
39
case map[any]any:
40
for k, val := range v {
41
m[keyFn(k)] = valFn(val)
42
}
43
44
return m, nil
45
46
case string:
47
err := jsonStringToObject(v, &m)
48
return m, err
49
50
default:
51
return m, fmt.Errorf(errorMsg, i, i, m)
52
}
53
}
54
55
func toStringMapE[T any](i any, fn func(any) T) (map[string]T, error) {
56
return toMapE(i, ToString, fn)
57
}
58
59
// ToStringMapStringE casts any value to a map[string]string type.
60
func ToStringMapStringE(i any) (map[string]string, error) {
61
return toStringMapE(i, ToString)
62
}
63
64
// ToStringMapStringSliceE casts any value to a map[string][]string type.
65
func ToStringMapStringSliceE(i any) (map[string][]string, error) {
66
m := map[string][]string{}
67
68
switch v := i.(type) {
69
case map[string][]string:
70
return v, nil
71
case map[string][]any:
72
for k, val := range v {
73
m[ToString(k)] = ToStringSlice(val)
74
}
75
return m, nil
76
case map[string]string:
77
for k, val := range v {
78
m[ToString(k)] = []string{val}
79
}
80
case map[string]any:
81
for k, val := range v {
82
switch vt := val.(type) {
83
case []any:
84
m[ToString(k)] = ToStringSlice(vt)
85
case []string:
86
m[ToString(k)] = vt
87
default:
88
m[ToString(k)] = []string{ToString(val)}
89
}
90
}
91
return m, nil
92
case map[any][]string:
93
for k, val := range v {
94
m[ToString(k)] = ToStringSlice(val)
95
}
96
return m, nil
97
case map[any]string:
98
for k, val := range v {
99
m[ToString(k)] = ToStringSlice(val)
100
}
101
return m, nil
102
case map[any][]any:
103
for k, val := range v {
104
m[ToString(k)] = ToStringSlice(val)
105
}
106
return m, nil
107
case map[any]any:
108
for k, val := range v {
109
key, err := ToStringE(k)
110
if err != nil {
111
return m, fmt.Errorf(errorMsg, i, i, m)
112
}
113
value, err := ToStringSliceE(val)
114
if err != nil {
115
return m, fmt.Errorf(errorMsg, i, i, m)
116
}
117
m[key] = value
118
}
119
case string:
120
err := jsonStringToObject(v, &m)
121
return m, err
122
default:
123
return m, fmt.Errorf(errorMsg, i, i, m)
124
}
125
126
return m, nil
127
}
128
129
// ToStringMapBoolE casts any value to a map[string]bool type.
130
func ToStringMapBoolE(i any) (map[string]bool, error) {
131
return toStringMapE(i, ToBool)
132
}
133
134
// ToStringMapE casts any value to a map[string]any type.
135
func ToStringMapE(i any) (map[string]any, error) {
136
fn := func(i any) any { return i }
137
138
return toStringMapE(i, fn)
139
}
140
141
func toStringMapIntE[T int | int64](i any, fn func(any) T, fnE func(any) (T, error)) (map[string]T, error) {
142
m := map[string]T{}
143
144
if i == nil {
145
return nil, fmt.Errorf(errorMsg, i, i, m)
146
}
147
148
switch v := i.(type) {
149
case map[string]T:
150
return v, nil
151
152
case map[string]any:
153
for k, val := range v {
154
m[k] = fn(val)
155
}
156
157
return m, nil
158
159
case map[any]T:
160
for k, val := range v {
161
m[ToString(k)] = val
162
}
163
164
return m, nil
165
166
case map[any]any:
167
for k, val := range v {
168
m[ToString(k)] = fn(val)
169
}
170
171
return m, nil
172
173
case string:
174
err := jsonStringToObject(v, &m)
175
return m, err
176
}
177
178
if reflect.TypeOf(i).Kind() != reflect.Map {
179
return m, fmt.Errorf(errorMsg, i, i, m)
180
}
181
182
mVal := reflect.ValueOf(m)
183
v := reflect.ValueOf(i)
184
185
for _, keyVal := range v.MapKeys() {
186
val, err := fnE(v.MapIndex(keyVal).Interface())
187
if err != nil {
188
return m, fmt.Errorf(errorMsg, i, i, m)
189
}
190
191
mVal.SetMapIndex(keyVal, reflect.ValueOf(val))
192
}
193
194
return m, nil
195
}
196
197
// ToStringMapIntE casts any value to a map[string]int type.
198
func ToStringMapIntE(i any) (map[string]int, error) {
199
return toStringMapIntE(i, ToInt, ToIntE)
200
}
201
202
// ToStringMapInt64E casts any value to a map[string]int64 type.
203
func ToStringMapInt64E(i any) (map[string]int64, error) {
204
return toStringMapIntE(i, ToInt64, ToInt64E)
205
}
206
207
// jsonStringToObject attempts to unmarshall a string as JSON into
208
// the object passed as pointer.
209
func jsonStringToObject(s string, v any) error {
210
data := []byte(s)
211
return json.Unmarshal(data, v)
212
}
213
214