Skip to content

Commit

Permalink
fix #17 use regex validate will panic
Browse files Browse the repository at this point in the history
  • Loading branch information
inhere committed Aug 30, 2019
1 parent 0da91ce commit 95eea92
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 70 deletions.
134 changes: 66 additions & 68 deletions validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,7 @@ func (r *Rule) Apply(v *Validation) (stop bool) {
return false
}

// func (r *Rule) doValidating() {
//
// }
// func (r *Rule) doValidating() {}

func (r *Rule) fileValidate(field, name string, v *Validation) uint8 {
// check data source
Expand Down Expand Up @@ -188,6 +186,71 @@ func (r *Rule) valueValidate(field, name string, isNotRequired bool, val interfa
return callValidator(v, fm, field, val, r.arguments)
}

func callValidator(v *Validation, fm *funcMeta, field string, val interface{}, args []interface{}) (ok bool) {
// 1. args data type convert
if ok = convertArgsType(v, fm, args); !ok {
return
}

// 2. call built in validator
switch fm.name {
case "required":
ok = v.Required(field, val)
case "lt":
ok = Lt(val, args[0].(int64))
case "gt":
ok = Gt(val, args[0].(int64))
case "min":
ok = Min(val, args[0].(int64))
case "max":
ok = Max(val, args[0].(int64))
case "enum":
ok = Enum(val, args[0])
case "notIn":
ok = NotIn(val, args[0])
case "isInt":
if argLn := len(args); argLn == 0 {
ok = IsInt(val)
} else if argLn == 1 {
ok = IsInt(val, args[0].(int64))
} else { // argLn == 2
ok = IsInt(val, args[0].(int64), args[1].(int64))
}
case "isString":
if argLn := len(args); argLn == 0 {
ok = IsString(val)
} else if argLn == 1 {
ok = IsString(val, args[0].(int))
} else { // argLn == 2
ok = IsString(val, args[0].(int), args[1].(int))
}
case "isNumber":
ok = IsNumber(val.(string))
case "length":
ok = Length(val, args[0].(int))
case "minLength":
ok = MinLength(val, args[0].(int))
case "maxLength":
ok = MaxLength(val, args[0].(int))
case "stringLength":
if argLn := len(args); argLn == 1 {
ok = RuneLength(val, args[0].(int))
} else if argLn == 2 {
ok = RuneLength(val, args[0].(int), args[1].(int))
}
case "regexp":
ok = Regexp(val.(string), args[0].(string))
case "between":
ok = Between(val, args[0].(int64), args[1].(int64))
case "isJSON":
ok = IsJSON(val.(string))
default:
// 3. call user custom validators, will call by reflect
ok = callValidatorValue(fm.fv, val, args)
}
return
}

// convert args data type
func convertArgsType(v *Validation, fm *funcMeta, args []interface{}) (ok bool) {
ft := fm.fv.Type()
Expand Down Expand Up @@ -258,71 +321,6 @@ func convertArgsType(v *Validation, fm *funcMeta, args []interface{}) (ok bool)
return true
}

func callValidator(v *Validation, fm *funcMeta, field string, val interface{}, args []interface{}) (ok bool) {
// 1. args data type convert
if ok = convertArgsType(v, fm, args); !ok {
return
}

// 2. call built in validator
switch fm.name {
case "required":
ok = v.Required(field, val)
case "lt":
ok = Lt(val, args[0].(int64))
case "gt":
ok = Gt(val, args[0].(int64))
case "min":
ok = Min(val, args[0].(int64))
case "max":
ok = Max(val, args[0].(int64))
case "enum":
ok = Enum(val, args[0])
case "notIn":
ok = NotIn(val, args[0])
case "isInt":
if argLn := len(args); argLn == 0 {
ok = IsInt(val)
} else if argLn == 1 {
ok = IsInt(val, args[0].(int64))
} else { // argLn == 2
ok = IsInt(val, args[0].(int64), args[1].(int64))
}
case "isString":
if argLn := len(args); argLn == 0 {
ok = IsString(val)
} else if argLn == 1 {
ok = IsString(val, args[0].(int))
} else { // argLn == 2
ok = IsString(val, args[0].(int), args[1].(int))
}
case "isNumber":
ok = IsNumber(val.(string))
case "length":
ok = Length(val, args[0].(int))
case "minLength":
ok = MinLength(val, args[0].(int))
case "maxLength":
ok = MaxLength(val, args[0].(int))
case "stringLength":
if argLn := len(args); argLn == 1 {
ok = RuneLength(val, args[0].(int))
} else if argLn == 2 {
ok = RuneLength(val, args[0].(int), args[1].(int))
}
case "regexp":
ok = Regexp(val.(string), args[0].(string))
case "between":
ok = Between(val, args[0].(int64), args[1].(int64))
case "isJSON":
ok = IsJSON(val.(string))
default:
// 3. call user custom validators, will call by reflect
ok = callValidatorValue(fm.fv, val, args)
}
return
}

func callValidatorValue(fv reflect.Value, val interface{}, args []interface{}) bool {
argNum := len(args)

Expand Down
2 changes: 2 additions & 0 deletions validate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ func TestRule_Apply(t *testing.T) {
is := assert.New(t)
mp := M{
"name": "inhere",
"code": "2363",
}

v := Map(mp)
v.ConfigRules(MS{
"name": `regex:\w+`,
})
v.AddRule("name", "stringLength", 3)
v.StringRule("code", `required|regex:\d{4,6}`)

is.True(v.Validate())
}
6 changes: 6 additions & 0 deletions validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,12 @@ func (v *Validation) Get(key string) (interface{}, bool) {
return val, true
}

// find from validated data. (such as has default value)
if val, ok := v.safeData[key]; ok {
return val, true
}

// get from source data
return v.data.Get(key)
}

Expand Down
14 changes: 12 additions & 2 deletions validation_rule.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package validate

import "strings"
import (
"strings"
)

// Rules definition
type Rules []*Rule
Expand Down Expand Up @@ -44,7 +46,7 @@ type Rule struct {
emptyChecker func(val interface{}) bool
}

// NewRule instance
// NewRule create new Rule instance
func NewRule(fields, validator string, args ...interface{}) *Rule {
return &Rule{
fields: stringSplit(fields, ","),
Expand All @@ -70,6 +72,11 @@ func (r *Rule) SetSkipEmpty(skipEmpty bool) {
r.skipEmpty = skipEmpty
}

// SetDefValue for the rule
func (r *Rule) SetDefValue(defValue interface{}) {
r.defValue = defValue
}

// SetCheckFunc set custom validate func.
func (r *Rule) SetCheckFunc(checkFunc interface{}) *Rule {
var name string
Expand Down Expand Up @@ -165,6 +172,9 @@ func (v *Validation) StringRule(field, rule string, filterRule ...string) *Valid
args := parseArgString(list[1])
name := ValidatorName(list[0])
switch name {
// eg 'regex:\d{4,6}' dont need split
case "regexp":
v.AddRule(field, list[0], list[1])
// some special validator. need merge args to one.
case "enum", "notIn":
v.AddRule(field, list[0], args)
Expand Down

0 comments on commit 95eea92

Please sign in to comment.