forked from gookit/validate
-
Notifications
You must be signed in to change notification settings - Fork 0
/
value.go
120 lines (103 loc) · 2.97 KB
/
value.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package validate
import (
"reflect"
"strings"
)
var (
// DefaultFieldName for value validate.
DefaultFieldName = "input"
// provide value validate
emptyV = newValValidation()
)
// apply validator to each sub-element of the val(slice, map)
// TODO func Each(val interface{}, rule string)
// Var validating the value by given rule.
// alias of the Val()
func Var(val interface{}, rule string) error {
return Val(val, rule)
}
// Val quick validating the value by given rule.
// returns error on fail, return nil on check ok.
//
// Usage:
// validate.Val("xxx@mail.com", "required|email")
//
// refer the Validation.StringRule() for parse rule string.
func Val(val interface{}, rule string) error {
rule = strings.TrimSpace(rule)
// input emtpy rule, skip validate
if rule == "" {
return nil
}
field := DefaultFieldName
rules := stringSplit(strings.Trim(rule, "|:"), "|")
es := make(Errors)
var r *Rule
var realName string
for _, validator := range rules {
validator = strings.Trim(validator, ":")
if validator == "" {
continue
}
// validator has args. eg: "min:12"
if strings.ContainsRune(validator, ':') {
list := stringSplit(validator, ":")
// reassign value
validator = list[0]
realName = ValidatorName(validator)
switch realName {
// eg 'regex:\d{4,6}' dont need split args. args is "\d{4,6}"
case "regexp":
// v.AddRule(field, validator, list[1])
r = buildRule(field, validator, realName, []interface{}{list[1]})
// some special validator. need merge args to one.
case "enum", "notIn":
arg := parseArgString(list[1])
// ev.AddRule(field, validator, arg)
r = buildRule(field, validator, realName, []interface{}{arg})
default:
args := parseArgString(list[1])
r = buildRule(field, validator, realName, strings2Args(args))
}
} else {
realName = ValidatorName(validator)
r = buildRule(field, validator, realName, nil)
}
// validate value use validator.
if !r.valueValidate(field, realName, val, emptyV) {
es.Add(field, validator, r.errorMessage(field, r.validator, emptyV))
break
}
}
return es.ErrOrNil()
}
// add one Rule
func buildRule(fields, validator, realName string, args []interface{}) *Rule {
rule := NewRule(fields, validator, args...)
// init some settings
rule.realName = realName
rule.skipEmpty = gOpt.SkipOnEmpty
// validator name is not "required"
rule.nameNotRequired = !strings.HasPrefix(realName, "required")
return rule
}
// create a without context validator's instance.
// see newValidation()
func newValValidation() *Validation {
v := &Validation{
trans: NewTranslator(),
// validator names
validators: make(map[string]int8, 2),
}
// init build in context validator
v.validatorMetas = make(map[string]*funcMeta, 2)
v.validatorValues = map[string]reflect.Value{
"required": reflect.ValueOf(v.Required),
}
// collect func meta info
for n, fv := range v.validatorValues {
v.validators[n] = 1 // built in
v.validatorMetas[n] = newFuncMeta(n, true, fv)
}
return v
}