1
2
3
4
5 package binding
6
7 import (
8 "errors"
9 "fmt"
10 "reflect"
11 "strconv"
12 "strings"
13 "time"
14
15 "github.com/gin-gonic/gin/internal/bytesconv"
16 "github.com/gin-gonic/gin/internal/json"
17 )
18
19 var (
20 errUnknownType = errors.New("unknown type")
21
22
23 ErrConvertMapStringSlice = errors.New("can not convert to map slices of strings")
24
25
26 ErrConvertToMapString = errors.New("can not convert to map of strings")
27 )
28
29 func mapURI(ptr any, m map[string][]string) error {
30 return mapFormByTag(ptr, m, "uri")
31 }
32
33 func mapForm(ptr any, form map[string][]string) error {
34 return mapFormByTag(ptr, form, "form")
35 }
36
37 func MapFormWithTag(ptr any, form map[string][]string, tag string) error {
38 return mapFormByTag(ptr, form, tag)
39 }
40
41 var emptyField = reflect.StructField{}
42
43 func mapFormByTag(ptr any, form map[string][]string, tag string) error {
44
45 ptrVal := reflect.ValueOf(ptr)
46 var pointed any
47 if ptrVal.Kind() == reflect.Ptr {
48 ptrVal = ptrVal.Elem()
49 pointed = ptrVal.Interface()
50 }
51 if ptrVal.Kind() == reflect.Map &&
52 ptrVal.Type().Key().Kind() == reflect.String {
53 if pointed != nil {
54 ptr = pointed
55 }
56 return setFormMap(ptr, form)
57 }
58
59 return mappingByPtr(ptr, formSource(form), tag)
60 }
61
62
63 type setter interface {
64 TrySet(value reflect.Value, field reflect.StructField, key string, opt setOptions) (isSet bool, err error)
65 }
66
67 type formSource map[string][]string
68
69 var _ setter = formSource(nil)
70
71
72 func (form formSource) TrySet(value reflect.Value, field reflect.StructField, tagValue string, opt setOptions) (isSet bool, err error) {
73 return setByForm(value, field, form, tagValue, opt)
74 }
75
76 func mappingByPtr(ptr any, setter setter, tag string) error {
77 _, err := mapping(reflect.ValueOf(ptr), emptyField, setter, tag)
78 return err
79 }
80
81 func mapping(value reflect.Value, field reflect.StructField, setter setter, tag string) (bool, error) {
82 if field.Tag.Get(tag) == "-" {
83 return false, nil
84 }
85
86 vKind := value.Kind()
87
88 if vKind == reflect.Ptr {
89 var isNew bool
90 vPtr := value
91 if value.IsNil() {
92 isNew = true
93 vPtr = reflect.New(value.Type().Elem())
94 }
95 isSet, err := mapping(vPtr.Elem(), field, setter, tag)
96 if err != nil {
97 return false, err
98 }
99 if isNew && isSet {
100 value.Set(vPtr)
101 }
102 return isSet, nil
103 }
104
105 if vKind != reflect.Struct || !field.Anonymous {
106 ok, err := tryToSetValue(value, field, setter, tag)
107 if err != nil {
108 return false, err
109 }
110 if ok {
111 return true, nil
112 }
113 }
114
115 if vKind == reflect.Struct {
116 tValue := value.Type()
117
118 var isSet bool
119 for i := 0; i < value.NumField(); i++ {
120 sf := tValue.Field(i)
121 if sf.PkgPath != "" && !sf.Anonymous {
122 continue
123 }
124 ok, err := mapping(value.Field(i), sf, setter, tag)
125 if err != nil {
126 return false, err
127 }
128 isSet = isSet || ok
129 }
130 return isSet, nil
131 }
132 return false, nil
133 }
134
135 type setOptions struct {
136 isDefaultExists bool
137 defaultValue string
138 }
139
140 func tryToSetValue(value reflect.Value, field reflect.StructField, setter setter, tag string) (bool, error) {
141 var tagValue string
142 var setOpt setOptions
143
144 tagValue = field.Tag.Get(tag)
145 tagValue, opts := head(tagValue, ",")
146
147 if tagValue == "" {
148 tagValue = field.Name
149 }
150 if tagValue == "" {
151 return false, nil
152 }
153
154 var opt string
155 for len(opts) > 0 {
156 opt, opts = head(opts, ",")
157
158 if k, v := head(opt, "="); k == "default" {
159 setOpt.isDefaultExists = true
160 setOpt.defaultValue = v
161 }
162 }
163
164 return setter.TrySet(value, field, tagValue, setOpt)
165 }
166
167 func setByForm(value reflect.Value, field reflect.StructField, form map[string][]string, tagValue string, opt setOptions) (isSet bool, err error) {
168 vs, ok := form[tagValue]
169 if !ok && !opt.isDefaultExists {
170 return false, nil
171 }
172
173 switch value.Kind() {
174 case reflect.Slice:
175 if !ok {
176 vs = []string{opt.defaultValue}
177 }
178 return true, setSlice(vs, value, field)
179 case reflect.Array:
180 if !ok {
181 vs = []string{opt.defaultValue}
182 }
183 if len(vs) != value.Len() {
184 return false, fmt.Errorf("%q is not valid value for %s", vs, value.Type().String())
185 }
186 return true, setArray(vs, value, field)
187 default:
188 var val string
189 if !ok {
190 val = opt.defaultValue
191 }
192
193 if len(vs) > 0 {
194 val = vs[0]
195 }
196 return true, setWithProperType(val, value, field)
197 }
198 }
199
200 func setWithProperType(val string, value reflect.Value, field reflect.StructField) error {
201 switch value.Kind() {
202 case reflect.Int:
203 return setIntField(val, 0, value)
204 case reflect.Int8:
205 return setIntField(val, 8, value)
206 case reflect.Int16:
207 return setIntField(val, 16, value)
208 case reflect.Int32:
209 return setIntField(val, 32, value)
210 case reflect.Int64:
211 switch value.Interface().(type) {
212 case time.Duration:
213 return setTimeDuration(val, value)
214 }
215 return setIntField(val, 64, value)
216 case reflect.Uint:
217 return setUintField(val, 0, value)
218 case reflect.Uint8:
219 return setUintField(val, 8, value)
220 case reflect.Uint16:
221 return setUintField(val, 16, value)
222 case reflect.Uint32:
223 return setUintField(val, 32, value)
224 case reflect.Uint64:
225 return setUintField(val, 64, value)
226 case reflect.Bool:
227 return setBoolField(val, value)
228 case reflect.Float32:
229 return setFloatField(val, 32, value)
230 case reflect.Float64:
231 return setFloatField(val, 64, value)
232 case reflect.String:
233 value.SetString(val)
234 case reflect.Struct:
235 switch value.Interface().(type) {
236 case time.Time:
237 return setTimeField(val, field, value)
238 }
239 return json.Unmarshal(bytesconv.StringToBytes(val), value.Addr().Interface())
240 case reflect.Map:
241 return json.Unmarshal(bytesconv.StringToBytes(val), value.Addr().Interface())
242 default:
243 return errUnknownType
244 }
245 return nil
246 }
247
248 func setIntField(val string, bitSize int, field reflect.Value) error {
249 if val == "" {
250 val = "0"
251 }
252 intVal, err := strconv.ParseInt(val, 10, bitSize)
253 if err == nil {
254 field.SetInt(intVal)
255 }
256 return err
257 }
258
259 func setUintField(val string, bitSize int, field reflect.Value) error {
260 if val == "" {
261 val = "0"
262 }
263 uintVal, err := strconv.ParseUint(val, 10, bitSize)
264 if err == nil {
265 field.SetUint(uintVal)
266 }
267 return err
268 }
269
270 func setBoolField(val string, field reflect.Value) error {
271 if val == "" {
272 val = "false"
273 }
274 boolVal, err := strconv.ParseBool(val)
275 if err == nil {
276 field.SetBool(boolVal)
277 }
278 return err
279 }
280
281 func setFloatField(val string, bitSize int, field reflect.Value) error {
282 if val == "" {
283 val = "0.0"
284 }
285 floatVal, err := strconv.ParseFloat(val, bitSize)
286 if err == nil {
287 field.SetFloat(floatVal)
288 }
289 return err
290 }
291
292 func setTimeField(val string, structField reflect.StructField, value reflect.Value) error {
293 timeFormat := structField.Tag.Get("time_format")
294 if timeFormat == "" {
295 timeFormat = time.RFC3339
296 }
297
298 switch tf := strings.ToLower(timeFormat); tf {
299 case "unix", "unixnano":
300 tv, err := strconv.ParseInt(val, 10, 64)
301 if err != nil {
302 return err
303 }
304
305 d := time.Duration(1)
306 if tf == "unixnano" {
307 d = time.Second
308 }
309
310 t := time.Unix(tv/int64(d), tv%int64(d))
311 value.Set(reflect.ValueOf(t))
312 return nil
313 }
314
315 if val == "" {
316 value.Set(reflect.ValueOf(time.Time{}))
317 return nil
318 }
319
320 l := time.Local
321 if isUTC, _ := strconv.ParseBool(structField.Tag.Get("time_utc")); isUTC {
322 l = time.UTC
323 }
324
325 if locTag := structField.Tag.Get("time_location"); locTag != "" {
326 loc, err := time.LoadLocation(locTag)
327 if err != nil {
328 return err
329 }
330 l = loc
331 }
332
333 t, err := time.ParseInLocation(timeFormat, val, l)
334 if err != nil {
335 return err
336 }
337
338 value.Set(reflect.ValueOf(t))
339 return nil
340 }
341
342 func setArray(vals []string, value reflect.Value, field reflect.StructField) error {
343 for i, s := range vals {
344 err := setWithProperType(s, value.Index(i), field)
345 if err != nil {
346 return err
347 }
348 }
349 return nil
350 }
351
352 func setSlice(vals []string, value reflect.Value, field reflect.StructField) error {
353 slice := reflect.MakeSlice(value.Type(), len(vals), len(vals))
354 err := setArray(vals, slice, field)
355 if err != nil {
356 return err
357 }
358 value.Set(slice)
359 return nil
360 }
361
362 func setTimeDuration(val string, value reflect.Value) error {
363 d, err := time.ParseDuration(val)
364 if err != nil {
365 return err
366 }
367 value.Set(reflect.ValueOf(d))
368 return nil
369 }
370
371 func head(str, sep string) (head string, tail string) {
372 idx := strings.Index(str, sep)
373 if idx < 0 {
374 return str, ""
375 }
376 return str[:idx], str[idx+len(sep):]
377 }
378
379 func setFormMap(ptr any, form map[string][]string) error {
380 el := reflect.TypeOf(ptr).Elem()
381
382 if el.Kind() == reflect.Slice {
383 ptrMap, ok := ptr.(map[string][]string)
384 if !ok {
385 return ErrConvertMapStringSlice
386 }
387 for k, v := range form {
388 ptrMap[k] = v
389 }
390
391 return nil
392 }
393
394 ptrMap, ok := ptr.(map[string]string)
395 if !ok {
396 return ErrConvertToMapString
397 }
398 for k, v := range form {
399 ptrMap[k] = v[len(v)-1]
400 }
401
402 return nil
403 }
404
View as plain text