6662eef2 by miraclesu

Support Match validate function for tag

1 parent dcdfaf36
...@@ -55,9 +55,10 @@ Struct Tag Use: ...@@ -55,9 +55,10 @@ Struct Tag Use:
55 // validation function follow with "valid" tag 55 // validation function follow with "valid" tag
56 // functions divide with ";" 56 // functions divide with ";"
57 // parameters in parentheses "()" and divide with "," 57 // parameters in parentheses "()" and divide with ","
58 // Match function's pattern string must in "//"
58 type user struct { 59 type user struct {
59 Id int 60 Id int
60 Name string `valid:"Required"` 61 Name string `valid:"Required;Match(/^(test)?\\w*@;com$/)"`
61 Age int `valid:"Required;Range(1, 140)"` 62 Age int `valid:"Required;Range(1, 140)"`
62 } 63 }
63 64
...@@ -86,8 +87,7 @@ Struct Tag Functions: ...@@ -86,8 +87,7 @@ Struct Tag Functions:
86 Alpha 87 Alpha
87 Numeric 88 Numeric
88 AlphaNumeric 89 AlphaNumeric
89 Match(regexp string) // does not support yet 90 Match(pattern string)
90 NoMatch(regexp string) // does not support yet
91 AlphaDash 91 AlphaDash
92 Email 92 Email
93 IP 93 IP
......
...@@ -26,6 +26,7 @@ var ( ...@@ -26,6 +26,7 @@ var (
26 "apply": true, 26 "apply": true,
27 "Check": true, 27 "Check": true,
28 "Valid": true, 28 "Valid": true,
29 "NoMatch": true,
29 } 30 }
30 ) 31 )
31 32
...@@ -50,7 +51,7 @@ type Funcs map[string]reflect.Value ...@@ -50,7 +51,7 @@ type Funcs map[string]reflect.Value
50 func (f Funcs) Call(name string, params ...interface{}) (result []reflect.Value, err error) { 51 func (f Funcs) Call(name string, params ...interface{}) (result []reflect.Value, err error) {
51 defer func() { 52 defer func() {
52 if r := recover(); r != nil { 53 if r := recover(); r != nil {
53 err = r.(error) 54 err = fmt.Errorf("%v", r)
54 } 55 }
55 }() 56 }()
56 if _, ok := f[name]; !ok { 57 if _, ok := f[name]; !ok {
...@@ -82,10 +83,17 @@ func getValidFuncs(f reflect.StructField) (vfs []ValidFunc, err error) { ...@@ -82,10 +83,17 @@ func getValidFuncs(f reflect.StructField) (vfs []ValidFunc, err error) {
82 if len(tag) == 0 { 83 if len(tag) == 0 {
83 return 84 return
84 } 85 }
86 if vfs, tag, err = getRegFuncs(tag, f.Name); err != nil {
87 fmt.Printf("%+v\n", err)
88 return
89 }
85 fs := strings.Split(tag, ";") 90 fs := strings.Split(tag, ";")
86 for _, vfunc := range fs { 91 for _, vfunc := range fs {
87 var vf ValidFunc 92 var vf ValidFunc
88 vf, err = parseFunc(vfunc) 93 if len(vfunc) == 0 {
94 continue
95 }
96 vf, err = parseFunc(vfunc, f.Name)
89 if err != nil { 97 if err != nil {
90 return 98 return
91 } 99 }
...@@ -94,10 +102,33 @@ func getValidFuncs(f reflect.StructField) (vfs []ValidFunc, err error) { ...@@ -94,10 +102,33 @@ func getValidFuncs(f reflect.StructField) (vfs []ValidFunc, err error) {
94 return 102 return
95 } 103 }
96 104
97 func parseFunc(vfunc string) (v ValidFunc, err error) { 105 // Get Match function
106 // May be get NoMatch function in the future
107 func getRegFuncs(tag, key string) (vfs []ValidFunc, str string, err error) {
108 tag = strings.TrimSpace(tag)
109 index := strings.Index(tag, "Match(/")
110 if index == -1 {
111 str = tag
112 return
113 }
114 end := strings.LastIndex(tag, "/)")
115 if end < index {
116 err = fmt.Errorf("invalid Match function")
117 return
118 }
119 reg, err := regexp.Compile(tag[index+len("Match(/") : end])
120 if err != nil {
121 return
122 }
123 vfs = []ValidFunc{ValidFunc{"Match", []interface{}{reg, key}}}
124 str = strings.TrimSpace(tag[:index]) + strings.TrimSpace(tag[end+len("/)"):])
125 return
126 }
127
128 func parseFunc(vfunc, key string) (v ValidFunc, err error) {
98 defer func() { 129 defer func() {
99 if r := recover(); r != nil { 130 if r := recover(); r != nil {
100 err = r.(error) 131 err = fmt.Errorf("%v", r)
101 } 132 }
102 }() 133 }()
103 134
...@@ -114,7 +145,7 @@ func parseFunc(vfunc string) (v ValidFunc, err error) { ...@@ -114,7 +145,7 @@ func parseFunc(vfunc string) (v ValidFunc, err error) {
114 err = fmt.Errorf("%s require %d parameters", vfunc, num) 145 err = fmt.Errorf("%s require %d parameters", vfunc, num)
115 return 146 return
116 } 147 }
117 v = ValidFunc{vfunc, []interface{}{vfunc}} 148 v = ValidFunc{vfunc, []interface{}{key}}
118 return 149 return
119 } 150 }
120 151
...@@ -136,7 +167,7 @@ func parseFunc(vfunc string) (v ValidFunc, err error) { ...@@ -136,7 +167,7 @@ func parseFunc(vfunc string) (v ValidFunc, err error) {
136 return 167 return
137 } 168 }
138 169
139 tParams, err := trim(name, params) 170 tParams, err := trim(name, key, params)
140 if err != nil { 171 if err != nil {
141 return 172 return
142 } 173 }
...@@ -155,7 +186,7 @@ func numIn(name string) (num int, err error) { ...@@ -155,7 +186,7 @@ func numIn(name string) (num int, err error) {
155 return 186 return
156 } 187 }
157 188
158 func trim(name string, s []string) (ts []interface{}, err error) { 189 func trim(name, key string, s []string) (ts []interface{}, err error) {
159 ts = make([]interface{}, len(s), len(s)+1) 190 ts = make([]interface{}, len(s), len(s)+1)
160 fn, ok := funcs[name] 191 fn, ok := funcs[name]
161 if !ok { 192 if !ok {
...@@ -170,7 +201,7 @@ func trim(name string, s []string) (ts []interface{}, err error) { ...@@ -170,7 +201,7 @@ func trim(name string, s []string) (ts []interface{}, err error) {
170 } 201 }
171 ts[i] = param 202 ts[i] = param
172 } 203 }
173 ts = append(ts, name) 204 ts = append(ts, key)
174 return 205 return
175 } 206 }
176 207
......
...@@ -8,8 +8,9 @@ import ( ...@@ -8,8 +8,9 @@ import (
8 type user struct { 8 type user struct {
9 Id int 9 Id int
10 Tag string `valid:"Maxx(aa)"` 10 Tag string `valid:"Maxx(aa)"`
11 Name string `valid:"Required"` 11 Name string `valid:"Required;"`
12 Age int `valid:"Required;Range(1, 140)"` 12 Age int `valid:"Required;Range(1, 140)"`
13 match string `valid:"Required; Match(/^(test)?\\w*@(/test/);com$/);Max(2)"`
13 } 14 }
14 15
15 func TestGetValidFuncs(t *testing.T) { 16 func TestGetValidFuncs(t *testing.T) {
...@@ -55,6 +56,14 @@ func TestGetValidFuncs(t *testing.T) { ...@@ -55,6 +56,14 @@ func TestGetValidFuncs(t *testing.T) {
55 if vfs[1].Name != "Range" && len(vfs[1].Params) != 2 { 56 if vfs[1].Name != "Range" && len(vfs[1].Params) != 2 {
56 t.Error("Range funcs should be got") 57 t.Error("Range funcs should be got")
57 } 58 }
59
60 f, _ = tf.FieldByName("match")
61 if vfs, err = getValidFuncs(f); err != nil {
62 t.Fatal(err)
63 }
64 if len(vfs) != 3 {
65 t.Fatal("should get 3 ValidFunc but now is", len(vfs))
66 }
58 } 67 }
59 68
60 func TestCall(t *testing.T) { 69 func TestCall(t *testing.T) {
......
...@@ -283,12 +283,12 @@ func TestZipCode(t *testing.T) { ...@@ -283,12 +283,12 @@ func TestZipCode(t *testing.T) {
283 func TestValid(t *testing.T) { 283 func TestValid(t *testing.T) {
284 type user struct { 284 type user struct {
285 Id int 285 Id int
286 Name string `valid:"Required"` 286 Name string `valid:"Required;Match(/^(test)?\\w*@(/test/);com$/)"`
287 Age int `valid:"Required;Range(1, 140)"` 287 Age int `valid:"Required;Range(1, 140)"`
288 } 288 }
289 valid := Validation{} 289 valid := Validation{}
290 290
291 u := user{Name: "test", Age: 40} 291 u := user{Name: "test@/test/;com", Age: 40}
292 b, err := valid.Valid(u) 292 b, err := valid.Valid(u)
293 if err != nil { 293 if err != nil {
294 t.Fatal(err) 294 t.Fatal(err)
...@@ -297,7 +297,7 @@ func TestValid(t *testing.T) { ...@@ -297,7 +297,7 @@ func TestValid(t *testing.T) {
297 t.Error("validation should be passed") 297 t.Error("validation should be passed")
298 } 298 }
299 299
300 uptr := &user{Name: "test", Age: 180} 300 uptr := &user{Name: "test", Age: 40}
301 b, err = valid.Valid(uptr) 301 b, err = valid.Valid(uptr)
302 if err != nil { 302 if err != nil {
303 t.Fatal(err) 303 t.Fatal(err)
...@@ -305,4 +305,13 @@ func TestValid(t *testing.T) { ...@@ -305,4 +305,13 @@ func TestValid(t *testing.T) {
305 if b { 305 if b {
306 t.Error("validation should not be passed") 306 t.Error("validation should not be passed")
307 } 307 }
308
309 u = user{Name: "test@/test/;com", Age: 180}
310 b, err = valid.Valid(u)
311 if err != nil {
312 t.Fatal(err)
313 }
314 if b {
315 t.Error("validation should not be passed")
316 }
308 } 317 }
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!