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  }