github.com/laof/lite-speed-test@v0.0.0-20230930011949-1f39b7037845/common/structure/structure.go (about) 1 package structure 2 3 import ( 4 "fmt" 5 "reflect" 6 "strconv" 7 "strings" 8 ) 9 10 // Option is the configuration that is used to create a new decoder 11 type Option struct { 12 TagName string 13 WeaklyTypedInput bool 14 } 15 16 // Decoder is the core of structure 17 type Decoder struct { 18 option *Option 19 } 20 21 // NewDecoder return a Decoder by Option 22 func NewDecoder(option Option) *Decoder { 23 if option.TagName == "" { 24 option.TagName = "structure" 25 } 26 return &Decoder{option: &option} 27 } 28 29 // Decode transform a map[string]interface{} to a struct 30 func (d *Decoder) Decode(src map[string]interface{}, dst interface{}) error { 31 if reflect.TypeOf(dst).Kind() != reflect.Ptr { 32 return fmt.Errorf("Decode must recive a ptr struct") 33 } 34 t := reflect.TypeOf(dst).Elem() 35 v := reflect.ValueOf(dst).Elem() 36 for idx := 0; idx < v.NumField(); idx++ { 37 field := t.Field(idx) 38 if field.Anonymous { 39 if err := d.decodeStruct(field.Name, src, v.Field(idx)); err != nil { 40 return err 41 } 42 continue 43 } 44 45 tag := field.Tag.Get(d.option.TagName) 46 str := strings.SplitN(tag, ",", 2) 47 key := str[0] 48 omitempty := false 49 if len(str) > 1 { 50 omitempty = str[1] == "omitempty" 51 } 52 53 value, ok := src[key] 54 if !ok || value == nil { 55 if omitempty { 56 continue 57 } 58 return fmt.Errorf("key '%s' missing", key) 59 } 60 61 err := d.decode(key, value, v.Field(idx)) 62 if err != nil { 63 return err 64 } 65 } 66 return nil 67 } 68 69 func (d *Decoder) decode(name string, data interface{}, val reflect.Value) error { 70 switch val.Kind() { 71 case reflect.Int: 72 return d.decodeInt(name, data, val) 73 case reflect.Uint16: 74 return d.decodeUint16(name, data, val) 75 case reflect.String: 76 return d.decodeString(name, data, val) 77 case reflect.Bool: 78 return d.decodeBool(name, data, val) 79 case reflect.Slice: 80 return d.decodeSlice(name, data, val) 81 case reflect.Map: 82 return d.decodeMap(name, data, val) 83 case reflect.Interface: 84 return d.setInterface(name, data, val) 85 case reflect.Struct: 86 return d.decodeStruct(name, data, val) 87 default: 88 return fmt.Errorf("type %s not support", val.Kind().String()) 89 } 90 } 91 92 func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) (err error) { 93 dataVal := reflect.ValueOf(data) 94 kind := dataVal.Kind() 95 switch { 96 case kind == reflect.Int: 97 val.SetInt(dataVal.Int()) 98 case kind == reflect.Float64: 99 val.SetInt(int64(dataVal.Float())) 100 case kind == reflect.String: 101 var i int64 102 v := dataVal.String() 103 if v == "undefined" { 104 v = "0" 105 } 106 i, err = strconv.ParseInt(v, 0, val.Type().Bits()) 107 if err == nil { 108 val.SetInt(i) 109 } else { 110 err = fmt.Errorf("cannot parse '%s' as int: %s", name, err) 111 } 112 default: 113 err = fmt.Errorf( 114 "'%s' expected type '%s', got unconvertible type '%s'", 115 name, val.Type(), dataVal.Type(), 116 ) 117 } 118 return err 119 } 120 121 func (d *Decoder) decodeUint16(name string, data interface{}, val reflect.Value) (err error) { 122 dataVal := reflect.ValueOf(data) 123 kind := dataVal.Kind() 124 switch { 125 case kind == reflect.Int: 126 val.SetUint(uint64(dataVal.Int())) 127 case kind == reflect.String && d.option.WeaklyTypedInput: 128 var i uint64 129 v := dataVal.String() 130 if v == "undefined" { 131 v = "0" 132 } 133 i, err = strconv.ParseUint(v, 0, val.Type().Bits()) 134 if err == nil { 135 val.SetUint(i) 136 } else { 137 err = fmt.Errorf("cannot parse '%s' as int: %s", name, err) 138 } 139 default: 140 err = fmt.Errorf( 141 "'%s' expected type '%s', got unconvertible type '%s'", 142 name, val.Type(), dataVal.Type(), 143 ) 144 } 145 return err 146 } 147 148 func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) (err error) { 149 dataVal := reflect.ValueOf(data) 150 kind := dataVal.Kind() 151 switch { 152 case kind == reflect.String: 153 val.SetString(dataVal.String()) 154 case kind == reflect.Int && d.option.WeaklyTypedInput: 155 val.SetString(strconv.FormatInt(dataVal.Int(), 10)) 156 default: 157 err = fmt.Errorf( 158 "'%s' expected type '%s', got unconvertible type '%s'", 159 name, val.Type(), dataVal.Type(), 160 ) 161 } 162 return err 163 } 164 165 func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) (err error) { 166 dataVal := reflect.ValueOf(data) 167 kind := dataVal.Kind() 168 switch { 169 case kind == reflect.Bool: 170 val.SetBool(dataVal.Bool()) 171 case kind == reflect.Int && d.option.WeaklyTypedInput: 172 val.SetBool(dataVal.Int() != 0) 173 default: 174 err = fmt.Errorf( 175 "'%s' expected type '%s', got unconvertible type '%s'", 176 name, val.Type(), dataVal.Type(), 177 ) 178 } 179 return err 180 } 181 182 func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error { 183 dataVal := reflect.Indirect(reflect.ValueOf(data)) 184 valType := val.Type() 185 valElemType := valType.Elem() 186 187 if dataVal.Kind() != reflect.Slice { 188 return fmt.Errorf("'%s' is not a slice", name) 189 } 190 191 valSlice := val 192 for i := 0; i < dataVal.Len(); i++ { 193 currentData := dataVal.Index(i).Interface() 194 for valSlice.Len() <= i { 195 valSlice = reflect.Append(valSlice, reflect.Zero(valElemType)) 196 } 197 fieldName := fmt.Sprintf("%s[%d]", name, i) 198 if currentData == nil { 199 // in weakly type mode, null will convert to zero value 200 if d.option.WeaklyTypedInput { 201 continue 202 } 203 // in non-weakly type mode, null will convert to nil if element's zero value is nil, otherwise return an error 204 if elemKind := valElemType.Kind(); elemKind == reflect.Map || elemKind == reflect.Slice { 205 continue 206 } 207 return fmt.Errorf("'%s' can not be null", fieldName) 208 } 209 currentField := valSlice.Index(i) 210 if err := d.decode(fieldName, currentData, currentField); err != nil { 211 return err 212 } 213 } 214 215 val.Set(valSlice) 216 return nil 217 } 218 219 func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) error { 220 valType := val.Type() 221 valKeyType := valType.Key() 222 valElemType := valType.Elem() 223 224 valMap := val 225 226 if valMap.IsNil() { 227 mapType := reflect.MapOf(valKeyType, valElemType) 228 valMap = reflect.MakeMap(mapType) 229 } 230 231 dataVal := reflect.Indirect(reflect.ValueOf(data)) 232 if dataVal.Kind() != reflect.Map { 233 return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) 234 } 235 236 return d.decodeMapFromMap(name, dataVal, val, valMap) 237 } 238 239 func (d *Decoder) decodeMapFromMap(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error { 240 valType := val.Type() 241 valKeyType := valType.Key() 242 valElemType := valType.Elem() 243 244 errors := make([]string, 0) 245 246 if dataVal.Len() == 0 { 247 if dataVal.IsNil() { 248 if !val.IsNil() { 249 val.Set(dataVal) 250 } 251 } else { 252 val.Set(valMap) 253 } 254 255 return nil 256 } 257 258 for _, k := range dataVal.MapKeys() { 259 fieldName := fmt.Sprintf("%s[%s]", name, k) 260 261 currentKey := reflect.Indirect(reflect.New(valKeyType)) 262 if err := d.decode(fieldName, k.Interface(), currentKey); err != nil { 263 errors = append(errors, err.Error()) 264 continue 265 } 266 267 v := dataVal.MapIndex(k).Interface() 268 if v == nil { 269 errors = append(errors, fmt.Sprintf("filed %s invalid", fieldName)) 270 continue 271 } 272 273 currentVal := reflect.Indirect(reflect.New(valElemType)) 274 if err := d.decode(fieldName, v, currentVal); err != nil { 275 errors = append(errors, err.Error()) 276 continue 277 } 278 279 valMap.SetMapIndex(currentKey, currentVal) 280 } 281 282 val.Set(valMap) 283 284 if len(errors) > 0 { 285 return fmt.Errorf(strings.Join(errors, ",")) 286 } 287 288 return nil 289 } 290 291 func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) error { 292 dataVal := reflect.Indirect(reflect.ValueOf(data)) 293 294 // If the type of the value to write to and the data match directly, 295 // then we just set it directly instead of recursing into the structure. 296 if dataVal.Type() == val.Type() { 297 val.Set(dataVal) 298 return nil 299 } 300 301 dataValKind := dataVal.Kind() 302 switch dataValKind { 303 case reflect.Map: 304 return d.decodeStructFromMap(name, dataVal, val) 305 default: 306 return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) 307 } 308 } 309 310 func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) error { 311 dataValType := dataVal.Type() 312 if kind := dataValType.Key().Kind(); kind != reflect.String && kind != reflect.Interface { 313 return fmt.Errorf( 314 "'%s' needs a map with string keys, has '%s' keys", 315 name, dataValType.Key().Kind()) 316 } 317 318 dataValKeys := make(map[reflect.Value]struct{}) 319 dataValKeysUnused := make(map[interface{}]struct{}) 320 for _, dataValKey := range dataVal.MapKeys() { 321 dataValKeys[dataValKey] = struct{}{} 322 dataValKeysUnused[dataValKey.Interface()] = struct{}{} 323 } 324 325 errors := make([]string, 0) 326 327 // This slice will keep track of all the structs we'll be decoding. 328 // There can be more than one struct if there are embedded structs 329 // that are squashed. 330 structs := make([]reflect.Value, 1, 5) 331 structs[0] = val 332 333 // Compile the list of all the fields that we're going to be decoding 334 // from all the structs. 335 type field struct { 336 field reflect.StructField 337 val reflect.Value 338 } 339 fields := []field{} 340 for len(structs) > 0 { 341 structVal := structs[0] 342 structs = structs[1:] 343 344 structType := structVal.Type() 345 346 for i := 0; i < structType.NumField(); i++ { 347 fieldType := structType.Field(i) 348 fieldKind := fieldType.Type.Kind() 349 350 // If "squash" is specified in the tag, we squash the field down. 351 squash := false 352 tagParts := strings.Split(fieldType.Tag.Get(d.option.TagName), ",") 353 for _, tag := range tagParts[1:] { 354 if tag == "squash" { 355 squash = true 356 break 357 } 358 } 359 360 if squash { 361 if fieldKind != reflect.Struct { 362 errors = append(errors, 363 fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldKind).Error()) 364 } else { 365 structs = append(structs, structVal.FieldByName(fieldType.Name)) 366 } 367 continue 368 } 369 370 // Normal struct field, store it away 371 fields = append(fields, field{fieldType, structVal.Field(i)}) 372 } 373 } 374 375 // for fieldType, field := range fields { 376 for _, f := range fields { 377 field, fieldValue := f.field, f.val 378 fieldName := field.Name 379 380 tagValue := field.Tag.Get(d.option.TagName) 381 tagValue = strings.SplitN(tagValue, ",", 2)[0] 382 if tagValue != "" { 383 fieldName = tagValue 384 } 385 386 rawMapKey := reflect.ValueOf(fieldName) 387 rawMapVal := dataVal.MapIndex(rawMapKey) 388 if !rawMapVal.IsValid() { 389 // Do a slower search by iterating over each key and 390 // doing case-insensitive search. 391 for dataValKey := range dataValKeys { 392 mK, ok := dataValKey.Interface().(string) 393 if !ok { 394 // Not a string key 395 continue 396 } 397 398 if strings.EqualFold(mK, fieldName) { 399 rawMapKey = dataValKey 400 rawMapVal = dataVal.MapIndex(dataValKey) 401 break 402 } 403 } 404 405 if !rawMapVal.IsValid() { 406 // There was no matching key in the map for the value in 407 // the struct. Just ignore. 408 continue 409 } 410 } 411 412 // Delete the key we're using from the unused map so we stop tracking 413 delete(dataValKeysUnused, rawMapKey.Interface()) 414 415 if !fieldValue.IsValid() { 416 // This should never happen 417 panic("field is not valid") 418 } 419 420 // If we can't set the field, then it is unexported or something, 421 // and we just continue onwards. 422 if !fieldValue.CanSet() { 423 continue 424 } 425 426 // If the name is empty string, then we're at the root, and we 427 // don't dot-join the fields. 428 if name != "" { 429 fieldName = fmt.Sprintf("%s.%s", name, fieldName) 430 } 431 432 if err := d.decode(fieldName, rawMapVal.Interface(), fieldValue); err != nil { 433 errors = append(errors, err.Error()) 434 } 435 } 436 437 if len(errors) > 0 { 438 return fmt.Errorf(strings.Join(errors, ",")) 439 } 440 441 return nil 442 } 443 444 func (d *Decoder) setInterface(name string, data interface{}, val reflect.Value) (err error) { 445 dataVal := reflect.ValueOf(data) 446 val.Set(dataVal) 447 return nil 448 }