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