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  }