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