github.com/codingeasygo/util@v0.0.0-20231206062002-1ce2f004b7d9/attrvalid/atrrvalid.go (about)

     1  package attrvalid
     2  
     3  import (
     4  	"database/sql"
     5  	"errors"
     6  	"fmt"
     7  	"math"
     8  	"net/http"
     9  	"net/url"
    10  	"reflect"
    11  	"regexp"
    12  	"strconv"
    13  	"strings"
    14  
    15  	"github.com/codingeasygo/util/attrscan"
    16  	"github.com/codingeasygo/util/converter"
    17  )
    18  
    19  type ZeroChecker interface {
    20  	IsZero() bool
    21  }
    22  
    23  //EnumValider is interface to enum valid
    24  type EnumValider interface {
    25  	EnumValid(v interface{}) error
    26  }
    27  
    28  //Validable is interface to define object can be valid by valid temple
    29  type Validable interface {
    30  	ValidFormat(format string, args ...interface{}) error
    31  }
    32  
    33  //M is an map[string]interface{} which can be valid by valid temple
    34  type M map[string]interface{}
    35  
    36  //RawMap will return raw map
    37  func (m M) RawMap() map[string]interface{} {
    38  	return m
    39  }
    40  
    41  //Get will return value by key
    42  func (m M) Get(key string) (v interface{}, err error) {
    43  	return m[key], nil
    44  }
    45  
    46  //ValidFormat will valid args by format temple
    47  func (m M) ValidFormat(format string, args ...interface{}) error {
    48  	return ValidAttrFormat(format, m, true, args...)
    49  }
    50  
    51  //MS is an map[string]string which can be valid by valid temple
    52  type MS map[string]string
    53  
    54  //Get will return value by key
    55  func (m MS) Get(key string) (v interface{}, err error) {
    56  	return m[key], nil
    57  }
    58  
    59  //ValidFormat will valid args by format temple
    60  func (m MS) ValidFormat(format string, args ...interface{}) error {
    61  	return ValidAttrFormat(format, m, true, args...)
    62  }
    63  
    64  //Values is an url.Values which can be valid by valid temple
    65  type Values url.Values
    66  
    67  //Get will return value by key
    68  func (v Values) Get(key string) (val interface{}, err error) {
    69  	return url.Values(v).Get(key), nil
    70  }
    71  
    72  //ValidFormat will valid args by format temple
    73  func (v Values) ValidFormat(format string, args ...interface{}) error {
    74  	return ValidAttrFormat(format, v, true, args...)
    75  }
    76  
    77  //QueryValidFormat will valid args by http request query
    78  func QueryValidFormat(req *http.Request, format string, args ...interface{}) error {
    79  	return Values(req.URL.Query()).ValidFormat(format, args...)
    80  }
    81  
    82  //FormValidFormat will valid args by http request form
    83  func FormValidFormat(req *http.Request, format string, args ...interface{}) error {
    84  	return Values(req.Form).ValidFormat(format, args...)
    85  }
    86  
    87  //PostFormValidFormat will valid args by http request post form
    88  func PostFormValidFormat(req *http.Request, format string, args ...interface{}) error {
    89  	return Values(req.PostForm).ValidFormat(format, args...)
    90  }
    91  
    92  //RequestValidFormat will valid args by http request query/form/postform
    93  func RequestValidFormat(req *http.Request, format string, args ...interface{}) error {
    94  	query := req.URL.Query()
    95  	getter := func(key string) (v interface{}, err error) {
    96  		val := query.Get(key)
    97  		if len(val) < 1 {
    98  			val = req.Form.Get(key)
    99  		}
   100  		if len(val) < 1 {
   101  			val = req.PostForm.Get(key)
   102  		}
   103  		v = val
   104  		return
   105  	}
   106  	return ValidAttrFormat(format, ValueGetterF(getter), true, args...)
   107  }
   108  
   109  func checkTemplateRequired(data interface{}, required bool, lts []string) (bool, error) {
   110  	zeroChecker, ok := data.(ZeroChecker)
   111  	if v := reflect.ValueOf(data); (ok && zeroChecker.IsZero()) || v.Kind() == reflect.Invalid || (v.IsZero() || reflect.Indirect(v).IsZero()) {
   112  		if (lts[0] == "R" || lts[0] == "r") && required {
   113  			return true, errors.New("data is empty")
   114  		}
   115  		return true, nil
   116  	}
   117  	// if v, ok := data.(string); data == nil || (ok && len(v) < 1) { //chekc the value required.
   118  	// 	if (lts[0] == "R" || lts[0] == "r") && required {
   119  	// 		return true, errors.New("data is empty")
   120  	// 	}
   121  	// 	return true, nil
   122  	// }
   123  	// if v, ok := data.([]interface{}); data == nil || (ok && len(v) < 1) { //chekc the value required.
   124  	// 	if (lts[0] == "R" || lts[0] == "r") && required {
   125  	// 		return true, errors.New("data is empty")
   126  	// 	}
   127  	// 	return true, nil
   128  	// }
   129  	return false, nil
   130  }
   131  
   132  func CompatibleType(typ reflect.Type) (ok bool) {
   133  	if typ == reflect.TypeOf(nil) {
   134  		return
   135  	}
   136  	switch typ.Kind() {
   137  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
   138  		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
   139  		reflect.Float32, reflect.Float64, reflect.String:
   140  		ok = true
   141  	case reflect.Ptr, reflect.Slice:
   142  		ok = CompatibleType(typ.Elem())
   143  	}
   144  	return
   145  }
   146  
   147  //ValidAttrTemple will valid the data to specified value by limit
   148  //
   149  //
   150  //data: target value for valding
   151  //
   152  //valueType: target value type limit by <R or O>|<S or I or F>
   153  //
   154  //	R is value must be having and valid
   155  //
   156  //	O is vlaue can be empty or nil, but must be valid if it having value
   157  //
   158  //	S:string value,I:integet value,F:float value
   159  //
   160  //	example "R|F" is required float value
   161  //
   162  //	example "O|F" is optional float value
   163  //
   164  //
   165  //valueRange: taget value range limit by <O or R or P>:<limit pattern>
   166  //
   167  //	O is value must be in options, all optional is seperated by -
   168  //
   169  //	R is value must be in range by "start-end", or "start" to positive infinite or negative infinite  to "-end"
   170  //
   171  //	P is value must be matched by regex pattern
   172  //
   173  //	example "O:1-2-3-4" is valid by value is in options 1-2-3-4)
   174  //	example "P:^.*\@.*$" is valid by string having "@"
   175  //
   176  //required: if true, ValidAttrTemple will return fail when require value is empty or nil,
   177  //if false, ValidAttrTemple will return success although setting required for emppty/nil value
   178  func ValidAttrTemple(data interface{}, valueType string, valueRange string, required bool, enum EnumValider) (interface{}, error) {
   179  	valueRange = strings.Replace(valueRange, "%N", ",", -1)
   180  	valueRange = strings.Replace(valueRange, "%%", "%", -1)
   181  	lts := strings.SplitN(valueType, "|", 2) //valid required type
   182  	if len(lts) < 2 {
   183  		return nil, fmt.Errorf("invalid type limit:%s", valueType)
   184  	}
   185  	lrs := strings.SplitN(valueRange, ":", 2) //valid value range.
   186  	if len(lrs) < 2 {
   187  		return nil, fmt.Errorf("invalid range limit:%s", valueRange)
   188  	}
   189  	if ret, err := checkTemplateRequired(data, required, lts); ret { //check required
   190  		return nil, err
   191  	}
   192  	// required = required && (lts[0] == "R" || lts[0] == "r")
   193  	//define the valid string function.
   194  	validStr := func(ds string) (interface{}, error) {
   195  		//check range limit.
   196  		switch lrs[0] {
   197  		case "o", "O": //option limit.
   198  			options := strings.Split(lrs[1], "~")
   199  			if converter.ArrayHaving(options, ds) {
   200  				return ds, nil
   201  			}
   202  			return nil, fmt.Errorf("invalid value(%s) for options(%s)", ds, lrs[1])
   203  		case "l", "L": //length limit
   204  			slen := int64(len(ds))
   205  			rgs := strings.Split(lrs[1], "~")
   206  			var beg, end int64 = 0, 0
   207  			var err error = nil
   208  			if len(rgs) > 0 && len(rgs[0]) > 0 {
   209  				beg, err = strconv.ParseInt(rgs[0], 10, 64)
   210  				if err != nil {
   211  					return nil, fmt.Errorf("invalid range begin number(%s)", rgs[0])
   212  				}
   213  			} else {
   214  				beg = 0
   215  			}
   216  			if len(rgs) > 1 && len(rgs[1]) > 0 {
   217  				end, err = strconv.ParseInt(rgs[1], 10, 64)
   218  				if err != nil {
   219  					return nil, fmt.Errorf("invalid range end number option(%s)", rgs[1])
   220  				}
   221  			} else {
   222  				end = math.MaxInt64
   223  			}
   224  			if beg < slen && end > slen {
   225  				return ds, nil
   226  			}
   227  			return nil, fmt.Errorf("string length must match %d<len<%d, but %d", beg, end, slen)
   228  		case "p", "P": //regex pattern limit
   229  			mched, err := regexp.MatchString(lrs[1], ds)
   230  			if err != nil {
   231  				return nil, err
   232  			}
   233  			if mched {
   234  				return ds, nil
   235  			}
   236  			return nil, fmt.Errorf("value(%s) not match regex(%s)", ds, lrs[1])
   237  		case "e", "E":
   238  			if enum == nil {
   239  				return nil, fmt.Errorf("target is not enum able")
   240  			}
   241  			return ds, enum.EnumValid(ds)
   242  		case "n", "N":
   243  			return ds, nil
   244  		}
   245  		//unknow range limit type.
   246  		return nil, fmt.Errorf("invalid range limit %s for string", lrs[0])
   247  	}
   248  	//define valid number function.
   249  	validNum := func(ds float64) (interface{}, error) {
   250  		//check range limit.
   251  		switch lrs[0] {
   252  		case "r", "R":
   253  			var beg, end float64 = 0, 0
   254  			var err error = nil
   255  			rgs := strings.Split(lrs[1], "~")
   256  			if len(rgs) > 0 && len(rgs[0]) > 0 {
   257  				beg, err = strconv.ParseFloat(rgs[0], 64)
   258  				if err != nil {
   259  					return nil, fmt.Errorf("invalid range begin number(%s)", rgs[0])
   260  				}
   261  			} else {
   262  				beg = 0
   263  			}
   264  			endStr := ""
   265  			if len(rgs) > 1 && len(rgs[1]) > 0 {
   266  				end, err = strconv.ParseFloat(rgs[1], 64)
   267  				if err != nil {
   268  					return nil, fmt.Errorf("invalid range end number option(%s)", rgs[1])
   269  				}
   270  				endStr = rgs[1]
   271  			} else {
   272  				end = math.MaxFloat64
   273  				endStr = "MaxFloat64"
   274  			}
   275  			if beg < ds && end > ds {
   276  				return ds, nil
   277  			}
   278  			return nil, fmt.Errorf("value must match %f<val<%v, but %v", beg, endStr, ds)
   279  		case "o", "O":
   280  			options := strings.Split(lrs[1], "~")
   281  			var oary []float64
   282  			for _, o := range options { //covert to float array.
   283  				v, err := strconv.ParseFloat(o, 64)
   284  				if err != nil {
   285  					return nil, fmt.Errorf("invalid number option(%s)", lrs[1])
   286  				}
   287  				oary = append(oary, v)
   288  			}
   289  			if converter.ArrayHaving(oary, ds) {
   290  				return ds, nil
   291  			}
   292  			return nil, fmt.Errorf("invalid value(%f) for options(%s)", ds, lrs[1])
   293  		case "e", "E":
   294  			if enum == nil {
   295  				return nil, fmt.Errorf("target is not enum able")
   296  			}
   297  			return ds, enum.EnumValid(ds)
   298  		case "n", "N":
   299  			return ds, nil
   300  		}
   301  		//unknow range limit type.
   302  		return nil, fmt.Errorf("invalid range limit %s for float", lrs[0])
   303  	}
   304  	//define valid number function.
   305  	validInt := func(ds int64) (interface{}, error) {
   306  		//check range limit.
   307  		switch lrs[0] {
   308  		case "r", "R":
   309  			var beg, end int64 = 0, 0
   310  			var err error = nil
   311  			rgs := strings.Split(lrs[1], "~")
   312  			if len(rgs) > 0 && len(rgs[0]) > 0 {
   313  				beg, err = strconv.ParseInt(rgs[0], 10, 64)
   314  				if err != nil {
   315  					return nil, fmt.Errorf("invalid range begin number(%s)", rgs[0])
   316  				}
   317  			} else {
   318  				beg = 0
   319  			}
   320  			endStr := ""
   321  			if len(rgs) > 1 && len(rgs[1]) > 0 {
   322  				end, err = strconv.ParseInt(rgs[1], 10, 64)
   323  				if err != nil {
   324  					return nil, fmt.Errorf("invalid range end number option(%s)", rgs[1])
   325  				}
   326  				endStr = rgs[1]
   327  			} else {
   328  				end = math.MaxInt64
   329  				endStr = "MaxInt64"
   330  			}
   331  			if beg < ds && end > ds {
   332  				return ds, nil
   333  			}
   334  			return nil, fmt.Errorf("value must match %v<val<%v, but %v", beg, endStr, ds)
   335  		case "o", "O":
   336  			options := strings.Split(lrs[1], "~")
   337  			var oary []int64
   338  			for _, o := range options { //covert to float array.
   339  				v, err := strconv.ParseInt(o, 10, 64)
   340  				if err != nil {
   341  					return nil, fmt.Errorf("invalid number option(%s)", lrs[1])
   342  				}
   343  				oary = append(oary, v)
   344  			}
   345  			if converter.ArrayHaving(oary, ds) {
   346  				return ds, nil
   347  			}
   348  			return nil, fmt.Errorf("invalid value(%v) for options(%s)", ds, lrs[1])
   349  		case "e", "E":
   350  			if enum == nil {
   351  				return nil, fmt.Errorf("target is not enum able")
   352  			}
   353  			return ds, enum.EnumValid(ds)
   354  		case "n", "N":
   355  			return ds, nil
   356  		}
   357  		//unknow range limit type.
   358  		return nil, fmt.Errorf("invalid range limit %s for float", lrs[0])
   359  	}
   360  	//define value type function
   361  	validValeuType := func(ds interface{}) (interface{}, error) {
   362  		switch lts[1] {
   363  		case "s", "S":
   364  			sval, _ := converter.StringVal(ds)
   365  			return validStr(sval)
   366  		case "i", "I":
   367  			ids, err := converter.Int64Val(ds)
   368  			if err != nil {
   369  				return nil, fmt.Errorf("invalid value(%s) for type(%s):%v", ds, lts[1], err)
   370  			}
   371  			return validInt(ids)
   372  		case "f", "F":
   373  			fds, err := converter.Float64Val(ds)
   374  			if err != nil {
   375  				return nil, fmt.Errorf("invalid value(%s) for type(%s):%v", ds, lts[1], err)
   376  			}
   377  			return validNum(fds)
   378  		}
   379  		return nil, fmt.Errorf("invalid value type:%s", lts[1])
   380  	}
   381  	return validValeuType(data)
   382  }
   383  
   384  func validAttrTemple(data interface{}, temple string, parts []string, required bool, enum EnumValider) (val interface{}, err error) {
   385  	val, err = ValidAttrTemple(data, parts[1], parts[2], required, enum)
   386  	if err != nil {
   387  		err = fmt.Errorf("limit(%s),%s", temple, err.Error())
   388  		if len(parts) > 3 {
   389  			err = errors.New(parts[3])
   390  		}
   391  	}
   392  	return
   393  }
   394  
   395  //ValueSetter is interface to set value to target arg
   396  type ValueSetter interface {
   397  	//Set the value
   398  	Set(value interface{}) error
   399  }
   400  
   401  //ValueSetterF is func for implment ValueSetter
   402  type ValueSetterF func(interface{}) error
   403  
   404  //Set will set value to arg
   405  func (v ValueSetterF) Set(value interface{}) error { return v(value) }
   406  
   407  //ValueGetter is inteface for using get the value by key
   408  type ValueGetter interface {
   409  	//Get the value by key
   410  	Get(key string) (interface{}, error)
   411  }
   412  
   413  //ValueGetterF is func for implment ValueGetter
   414  type ValueGetterF func(key string) (interface{}, error)
   415  
   416  //Get will call the func
   417  func (v ValueGetterF) Get(key string) (interface{}, error) { return v(key) }
   418  
   419  //ValidAttrFormat will valid multi value by foramt template, return error if fail
   420  //
   421  //format is temple set is seperated by ";", general it is one line one temple end with ";"
   422  //
   423  //	arg1,R|I,R:0;
   424  //	arg2,O|F,R:0;
   425  //	...
   426  //
   427  //valueGetter is value getter by key
   428  //
   429  //required if true, ValidAttrTemple will return fail when require value is empty or nil,
   430  //if false, ValidAttrTemple will return success although setting required for emppty/nil value
   431  //
   432  //args is variable list for store value, it must be go pointer
   433  //
   434  //	var arg1 int
   435  //	var arg2 float64
   436  //	ValidAttrFormat(format,getter,&arg1,&arg2)
   437  //
   438  func ValidAttrFormat(format string, valueGetter ValueGetter, required bool, args ...interface{}) error {
   439  	format = regexp.MustCompile(`\/\/.*`).ReplaceAllString(format, "")
   440  	format = strings.Replace(format, "\n", "", -1)
   441  	format = strings.Trim(format, " \t;")
   442  	if len(format) < 1 {
   443  		return errors.New("format not found")
   444  	}
   445  	temples := strings.Split(format, ";")
   446  	if len(args) < 1 {
   447  		args = make([]interface{}, len(temples))
   448  	}
   449  	if len(temples) != len(args) {
   450  		return errors.New("args count is not equal format count")
   451  	}
   452  	for idx, temple := range temples {
   453  		temple = strings.TrimSpace(temple)
   454  		parts := strings.SplitN(temple, ",", 4)
   455  		if len(parts) < 3 {
   456  			return fmt.Errorf("temple error:%s", temple)
   457  		}
   458  		sval, err := valueGetter.Get(parts[0])
   459  		if err != nil {
   460  			return fmt.Errorf("get value by key %v fail with %v", parts[0], err)
   461  		}
   462  		var target interface{}
   463  		var targetValue reflect.Value
   464  		var targetKind reflect.Kind
   465  		var enum EnumValider
   466  		if args[idx] != nil {
   467  			target = args[idx]
   468  			targetValue = reflect.Indirect(reflect.ValueOf(target))
   469  			targetKind = targetValue.Kind()
   470  			enum, _ = args[idx].(EnumValider)
   471  		}
   472  		checkValue := reflect.ValueOf(sval)
   473  		if checkValue.Kind() == reflect.Ptr && !checkValue.IsZero() {
   474  			sval = reflect.Indirect(reflect.ValueOf(sval)).Interface()
   475  		}
   476  		if targetKind != reflect.Slice {
   477  			rval, err := validAttrTemple(sval, temple, parts, required, enum)
   478  			if err != nil {
   479  				return err
   480  			}
   481  			if rval == nil {
   482  				continue
   483  			}
   484  			var setted bool
   485  			if target != nil && !CompatibleType(targetValue.Type()) {
   486  				if setter, ok := target.(ValueSetter); ok {
   487  					setted = true
   488  					err = setter.Set(rval)
   489  				} else if sc, ok := target.(sql.Scanner); ok {
   490  					setted = true
   491  					err = sc.Scan(rval)
   492  				}
   493  			}
   494  			if target != nil && !setted {
   495  				err = ValidSetValue(target, rval)
   496  			}
   497  			if err != nil {
   498  				return fmt.Errorf("set value to %v by key %v,%v fail with %v", reflect.TypeOf(target), parts[0], reflect.TypeOf(sval), err)
   499  			}
   500  			continue
   501  		}
   502  		if target != nil && !CompatibleType(targetValue.Type()) {
   503  			if setter, ok := target.(ValueSetter); ok {
   504  				_, err = validAttrTemple(sval, temple, parts, required, enum)
   505  				if err != nil {
   506  					return err
   507  				}
   508  				err = setter.Set(sval)
   509  				if err != nil {
   510  					return fmt.Errorf("set value to %v by key %v,%v fail with %v", reflect.TypeOf(target), parts[0], reflect.TypeOf(sval), err)
   511  				}
   512  				continue
   513  			}
   514  			if sc, ok := target.(sql.Scanner); ok {
   515  				_, err = validAttrTemple(sval, temple, parts, required, enum)
   516  				if err != nil {
   517  					return err
   518  				}
   519  				err = sc.Scan(sval)
   520  				if err != nil {
   521  					return fmt.Errorf("set value to %v by key %v,%v fail with %v", reflect.TypeOf(target), parts[0], reflect.TypeOf(sval), err)
   522  				}
   523  				continue
   524  			}
   525  		}
   526  		svals, _ := converter.ArrayValAll(sval, true) //ignore error
   527  		// if err != nil && err != converter.ErrNil {
   528  		// 	return err
   529  		// }
   530  		if ret, err := checkTemplateRequired(svals, required, strings.SplitN(parts[1], "|", 2)); ret { //check required
   531  			if err != nil {
   532  				return err
   533  			}
   534  			continue
   535  		}
   536  		var targetArray reflect.Value
   537  		if target != nil {
   538  			targetArray = targetValue
   539  		}
   540  		for _, sval = range svals {
   541  			rval, err := validAttrTemple(sval, temple, parts, required, enum)
   542  			if err != nil {
   543  				return err
   544  			}
   545  			if rval == nil {
   546  				continue
   547  			}
   548  			if targetArray.IsValid() {
   549  				tval, err := ValidValue(targetValue.Type().Elem(), rval)
   550  				if err != nil {
   551  					return err
   552  				}
   553  				targetArray = reflect.Append(targetArray, reflect.ValueOf(tval))
   554  			}
   555  		}
   556  		if targetArray.IsValid() {
   557  			targetValue.Set(targetArray)
   558  		}
   559  	}
   560  	return nil
   561  }
   562  
   563  //ValidSetValue will convert src value to dst type and set it
   564  func ValidSetValue(dst, src interface{}) error {
   565  	if sc, ok := dst.(sql.Scanner); ok {
   566  		return sc.Scan(src)
   567  	}
   568  	if setter, ok := dst.(ValueSetter); ok {
   569  		return setter.Set(src)
   570  	}
   571  	dstValue := reflect.Indirect(reflect.ValueOf(dst))
   572  	val, err := ValidValue(dstValue.Type(), src)
   573  	if err == nil {
   574  		targetValue := reflect.ValueOf(val)
   575  		if targetValue.Type() == dstValue.Type() {
   576  			dstValue.Set(targetValue)
   577  		} else {
   578  			dstValue.Set(targetValue.Convert(dstValue.Type()))
   579  		}
   580  	}
   581  	return err
   582  }
   583  
   584  //ValidValue will convert src value to dst type and return it
   585  func ValidValue(dst reflect.Type, src interface{}) (val interface{}, err error) {
   586  	srcType := reflect.TypeOf(src)
   587  	srcValue := reflect.ValueOf(src)
   588  	if srcType.Kind() == dst.Kind() {
   589  		return srcValue.Convert(dst).Interface(), nil
   590  	}
   591  	if dst.Kind() != reflect.String && srcValue.CanConvert(dst) { //skip string for int=>string is invalid
   592  		return srcValue.Convert(dst).Interface(), nil
   593  	}
   594  	var isptr = false
   595  	var kind = dst.Kind()
   596  	if kind == reflect.Ptr {
   597  		kind = dst.Elem().Kind()
   598  		isptr = true
   599  	}
   600  	var tiv int64
   601  	var tfv float64
   602  	var tsv string
   603  	switch kind {
   604  	case reflect.Int:
   605  		tiv, err = converter.Int64Val(src)
   606  		if err == nil {
   607  			target := int(tiv)
   608  			if isptr {
   609  				val = &target
   610  			} else {
   611  				val = target
   612  			}
   613  		}
   614  	case reflect.Int16:
   615  		tiv, err = converter.Int64Val(src)
   616  		if err == nil {
   617  			target := int16(tiv)
   618  			if isptr {
   619  				val = &target
   620  			} else {
   621  				val = target
   622  			}
   623  		}
   624  	case reflect.Int32:
   625  		tiv, err = converter.Int64Val(src)
   626  		if err == nil {
   627  			target := int32(tiv)
   628  			if isptr {
   629  				val = &target
   630  			} else {
   631  				val = target
   632  			}
   633  		}
   634  	case reflect.Int64:
   635  		tiv, err = converter.Int64Val(src)
   636  		if err == nil {
   637  			target := int64(tiv)
   638  			if isptr {
   639  				val = &target
   640  			} else {
   641  				val = target
   642  			}
   643  		}
   644  	case reflect.Uint:
   645  		tiv, err = converter.Int64Val(src)
   646  		if err == nil {
   647  			target := uint(tiv)
   648  			if isptr {
   649  				val = &target
   650  			} else {
   651  				val = target
   652  			}
   653  		}
   654  	case reflect.Uint16:
   655  		tiv, err = converter.Int64Val(src)
   656  		if err == nil {
   657  			target := uint16(tiv)
   658  			if isptr {
   659  				val = &target
   660  			} else {
   661  				val = target
   662  			}
   663  		}
   664  	case reflect.Uint32:
   665  		tiv, err = converter.Int64Val(src)
   666  		if err == nil {
   667  			target := uint32(tiv)
   668  			if isptr {
   669  				val = &target
   670  			} else {
   671  				val = target
   672  			}
   673  		}
   674  	case reflect.Uint64:
   675  		tiv, err = converter.Int64Val(src)
   676  		if err == nil {
   677  			target := uint64(tiv)
   678  			if isptr {
   679  				val = &target
   680  			} else {
   681  				val = target
   682  			}
   683  		}
   684  	case reflect.Float32:
   685  		tfv, err = converter.Float64Val(src)
   686  		if err == nil {
   687  			target := float32(tfv)
   688  			if isptr {
   689  				val = &target
   690  			} else {
   691  				val = target
   692  			}
   693  		}
   694  	case reflect.Float64:
   695  		tfv, err = converter.Float64Val(src)
   696  		if err == nil {
   697  			target := float64(tfv)
   698  			if isptr {
   699  				val = &target
   700  			} else {
   701  				val = target
   702  			}
   703  		}
   704  	case reflect.String:
   705  		tsv, err = converter.StringVal(src)
   706  		if isptr {
   707  			val = &tsv
   708  		} else {
   709  			val = tsv
   710  		}
   711  	default:
   712  		err = fmt.Errorf("not supported")
   713  	}
   714  	if err == nil {
   715  		return val, err
   716  	}
   717  	return nil, fmt.Errorf("parse kind(%v) value to kind(%v) value->%v", srcType.Kind(), dst, err)
   718  }
   719  
   720  type rawMapable interface {
   721  	RawMap() map[string]interface{}
   722  }
   723  
   724  //Struct is validable struct impl
   725  type Struct struct {
   726  	Target   interface{}
   727  	Required bool
   728  	Tag      string
   729  	loaded   map[string]interface{}
   730  }
   731  
   732  //NewStruct will return new struct
   733  func NewStruct(target interface{}) (s *Struct) {
   734  	if reflect.TypeOf(target).Kind() != reflect.Ptr {
   735  		panic("target must be pointer")
   736  	}
   737  	s = &Struct{
   738  		Target:   target,
   739  		Required: true,
   740  		Tag:      "json",
   741  		loaded:   map[string]interface{}{},
   742  	}
   743  	return
   744  }
   745  
   746  //Get will return field value by key
   747  func (s *Struct) Get(key string) (value interface{}, err error) {
   748  	if len(s.loaded) < 1 {
   749  		value := reflect.ValueOf(s.Target).Elem()
   750  		vtype := reflect.TypeOf(s.Target).Elem()
   751  		for i := 0; i < vtype.NumField(); i++ {
   752  			valueField := value.Field(i)
   753  			typeField := vtype.Field(i)
   754  			if !typeField.IsExported() {
   755  				continue
   756  			}
   757  			tag := strings.SplitN(typeField.Tag.Get(s.Tag), ",", 2)[0]
   758  			targetValue := valueField.Interface()
   759  			if mv, ok := targetValue.(map[string]interface{}); ok {
   760  				targetValue = M(mv)
   761  			} else if mv, ok := targetValue.(rawMapable); ok {
   762  				targetValue = M(mv.RawMap())
   763  			} else {
   764  				if typeField.Type.Kind() == reflect.Struct {
   765  					targetValue = NewStruct(valueField.Addr().Interface())
   766  				} else if typeField.Type.Kind() == reflect.Ptr && typeField.Type.Elem().Kind() == reflect.Struct {
   767  					targetValue = NewStruct(valueField.Interface())
   768  				}
   769  			}
   770  			s.loaded[typeField.Name] = targetValue
   771  			s.loaded[tag] = targetValue
   772  		}
   773  	}
   774  	key = strings.Trim(key, "/")
   775  	parts := strings.SplitN(key, "/", 2)
   776  	value = s.loaded[parts[0]]
   777  	if len(parts) < 2 || value == nil {
   778  		return
   779  	}
   780  	if getter, ok := value.(ValueGetter); ok {
   781  		value, err = getter.Get(parts[1])
   782  	}
   783  	return
   784  }
   785  
   786  //ValidFormat will valid format to struct filed
   787  func (s *Struct) ValidFormat(format string, args ...interface{}) error {
   788  	return ValidAttrFormat(format, s, s.Required, args...)
   789  }
   790  
   791  //ValidStructAttrFormat will valid struct by filed
   792  func ValidStructAttrFormat(format string, target interface{}, required bool, args ...interface{}) error {
   793  	return ValidAttrFormat(format, NewStruct(target), required, args...)
   794  }
   795  
   796  //ValidFormat will check all supported type and run valid format
   797  func ValidFormat(format string, target interface{}, args ...interface{}) error {
   798  	if getter, ok := target.(ValueGetter); ok {
   799  		return ValidAttrFormat(format, getter, true, args...)
   800  	}
   801  	if req, ok := target.(*http.Request); ok {
   802  		return QueryValidFormat(req, format, args...)
   803  	}
   804  	if val, ok := target.(url.Values); ok {
   805  		return Values(val).ValidFormat(format, args...)
   806  	}
   807  	if ms, ok := target.(map[string]string); ok {
   808  		return MS(ms).ValidFormat(format, args...)
   809  	}
   810  	if mv, ok := target.(map[string]interface{}); ok {
   811  		return M(mv).ValidFormat(format, args...)
   812  	}
   813  	if mv, ok := target.(rawMapable); ok {
   814  		return M(mv.RawMap()).ValidFormat(format, args...)
   815  	}
   816  	return NewStruct(target).ValidFormat(format, args...)
   817  }
   818  
   819  type Valider struct {
   820  	attrscan.Scanner
   821  }
   822  
   823  var Default = &Valider{
   824  	Scanner: attrscan.Scanner{
   825  		Tag: "json",
   826  		NameConv: func(on, name string, field reflect.StructField) string {
   827  			return name
   828  		},
   829  	},
   830  }
   831  
   832  func ValidArgs(target interface{}, filter string, args ...interface{}) (format string, args_ []interface{}) {
   833  	format, args_ = Default.ValidArgs(target, filter, args...)
   834  	return
   835  }
   836  
   837  func (v *Valider) addValidArgs(target interface{}, filter string, format string, args []interface{}) (format_ string, args_ []interface{}) {
   838  	format_, args_ = format, args
   839  	v.FilterFieldCall("valid", target, filter, func(fieldName, fieldFunc string, field reflect.StructField, value interface{}) {
   840  		valid := field.Tag.Get("valid")
   841  		if field.Type.Kind() == reflect.Struct && valid == "inline" {
   842  			format_, args_ = v.addValidArgs(value, filter, format_, args_)
   843  			return
   844  		}
   845  		if len(valid) < 1 || valid == "-" {
   846  			return
   847  		}
   848  		valid = strings.TrimSpace(valid)
   849  		if strings.HasSuffix(valid, ";") {
   850  			format_ += valid + "\n"
   851  		} else {
   852  			format_ += valid + ";\n"
   853  		}
   854  		args_ = append(args_, value)
   855  	})
   856  	return
   857  }
   858  
   859  func (v *Valider) ValidArgs(target interface{}, filter string, args ...interface{}) (format string, args_ []interface{}) {
   860  	format, args_ = v.addValidArgs(target, filter, "", nil)
   861  	for _, arg := range args {
   862  		if v, ok := arg.(string); ok {
   863  			arg = strings.TrimSpace(v)
   864  			if strings.HasSuffix(v, ";") {
   865  				format += v + "\n"
   866  			} else {
   867  				format += v + ";\n"
   868  			}
   869  		} else {
   870  			args_ = append(args_, arg)
   871  		}
   872  	}
   873  	format = strings.TrimSpace(format)
   874  	return
   875  }
   876  
   877  func Valid(target interface{}, filter, optional string) (err error) {
   878  	err = Default.Valid(target, filter, optional)
   879  	return
   880  }
   881  
   882  func (v *Valider) Valid(target interface{}, filter, optional string) (err error) {
   883  	errList := []string{}
   884  	optional = strings.TrimSpace(optional)
   885  	isExc := strings.HasPrefix(optional, "^")
   886  	optional = strings.TrimPrefix(optional, "^")
   887  	optional = strings.Trim(optional, ",")
   888  	optional = "," + optional + ","
   889  	isRequired := func(fieldName string) bool {
   890  		if isExc {
   891  			return strings.Contains(optional, ","+fieldName+",")
   892  		} else {
   893  			return !strings.Contains(optional, ","+fieldName+",")
   894  		}
   895  	}
   896  	v.FilterFieldCall("valid", target, filter, func(fieldName, fieldFunc string, field reflect.StructField, value interface{}) {
   897  		valid := field.Tag.Get("valid")
   898  		if len(valid) < 1 {
   899  			return
   900  		}
   901  		valid = strings.TrimSpace(valid)
   902  		valid = strings.TrimSuffix(valid, ";")
   903  		parts := strings.SplitN(valid, ",", 4)
   904  		if len(parts) < 3 {
   905  			errList = append(errList, fmt.Sprintf("valid error:%s", valid))
   906  			return
   907  		}
   908  		var xerr error
   909  		enum, _ := value.(EnumValider)
   910  		targetValue := reflect.Indirect(reflect.ValueOf(value))
   911  		if targetValue.Kind() == reflect.Slice {
   912  			n := targetValue.Len()
   913  			for i := 0; i < n; i++ {
   914  				targetItem := targetValue.Index(i)
   915  				_, xerr = validAttrTemple(targetItem.Interface(), valid, parts, isRequired(fieldName), enum)
   916  				if xerr != nil {
   917  					break
   918  				}
   919  			}
   920  			if xerr == nil && n < 1 {
   921  				_, xerr = validAttrTemple(nil, valid, parts, isRequired(fieldName), enum)
   922  			}
   923  		} else {
   924  			_, xerr = validAttrTemple(targetValue.Interface(), valid, parts, isRequired(fieldName), enum)
   925  		}
   926  		if xerr != nil {
   927  			errList = append(errList, xerr.Error())
   928  		}
   929  	})
   930  	if len(errList) > 0 {
   931  		err = fmt.Errorf("%v", strings.Join(errList, "\n"))
   932  	}
   933  	return
   934  }