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  }