4c6163ba by miraclesu

add funcmap

1 parent aba1728b
...@@ -3,6 +3,8 @@ package validation ...@@ -3,6 +3,8 @@ package validation
3 import ( 3 import (
4 "fmt" 4 "fmt"
5 "reflect" 5 "reflect"
6 "regexp"
7 "strconv"
6 "strings" 8 "strings"
7 ) 9 )
8 10
...@@ -13,7 +15,7 @@ const ( ...@@ -13,7 +15,7 @@ const (
13 var ( 15 var (
14 // key: function name 16 // key: function name
15 // value: the number of parameters 17 // value: the number of parameters
16 funcs = make(map[string]int) 18 funcs = make(Funcs)
17 19
18 // doesn't belong to validation functions 20 // doesn't belong to validation functions
19 unFuncs = map[string]bool{ 21 unFuncs = map[string]bool{
...@@ -33,7 +35,7 @@ func init() { ...@@ -33,7 +35,7 @@ func init() {
33 for i := 0; i < t.NumMethod(); i++ { 35 for i := 0; i < t.NumMethod(); i++ {
34 m := t.Method(i) 36 m := t.Method(i)
35 if !unFuncs[m.Name] { 37 if !unFuncs[m.Name] {
36 funcs[m.Name] = m.Type.NumIn() - 3 38 funcs[m.Name] = m.Func
37 } 39 }
38 } 40 }
39 } 41 }
...@@ -43,6 +45,25 @@ type ValidFunc struct { ...@@ -43,6 +45,25 @@ type ValidFunc struct {
43 Params []interface{} 45 Params []interface{}
44 } 46 }
45 47
48 type Funcs map[string]reflect.Value
49
50 func (f Funcs) Call(name string, params ...interface{}) (result []reflect.Value, err error) {
51 if _, ok := f[name]; !ok {
52 err = fmt.Errorf("%s does not exist", name)
53 return
54 }
55 if len(params) != f[name].Type().NumIn() {
56 err = fmt.Errorf("The number of params is not adapted")
57 return
58 }
59 in := make([]reflect.Value, len(params))
60 for k, param := range params {
61 in[k] = reflect.ValueOf(param)
62 }
63 result = f[name].Call(in)
64 return
65 }
66
46 func isStruct(t reflect.Type) bool { 67 func isStruct(t reflect.Type) bool {
47 return t.Kind() == reflect.Struct 68 return t.Kind() == reflect.Struct
48 } 69 }
...@@ -110,22 +131,53 @@ func parseFunc(vfunc string) (v ValidFunc, err error) { ...@@ -110,22 +131,53 @@ func parseFunc(vfunc string) (v ValidFunc, err error) {
110 return 131 return
111 } 132 }
112 133
113 v = ValidFunc{name, trim(params)} 134 tParams, err := trim(name, params)
135 if err != nil {
136 return
137 }
138 v = ValidFunc{name, tParams}
114 return 139 return
115 } 140 }
116 141
117 func numIn(name string) (num int, err error) { 142 func numIn(name string) (num int, err error) {
118 num, ok := funcs[name] 143 fn, ok := funcs[name]
119 if !ok { 144 if !ok {
120 err = fmt.Errorf("doesn't exsits %s valid function", name) 145 err = fmt.Errorf("doesn't exsits %s valid function", name)
146 return
121 } 147 }
148 num = fn.Type().NumIn() - 3
122 return 149 return
123 } 150 }
124 151
125 func trim(s []string) []interface{} { 152 func trim(name string, s []string) (ts []interface{}, err error) {
126 ts := make([]interface{}, len(s)) 153 ts = make([]interface{}, len(s))
154 fn, ok := funcs[name]
155 if !ok {
156 err = fmt.Errorf("doesn't exsits %s valid function", name)
157 return
158 }
127 for i := 0; i < len(s); i++ { 159 for i := 0; i < len(s); i++ {
128 ts[i] = strings.TrimSpace(s[i]) 160 var param interface{}
161 if param, err = magic(fn.Type().In(i+2), strings.TrimSpace(s[i])); err != nil {
162 return
163 }
164 ts[i] = param
165 }
166 return
167 }
168
169 func magic(t reflect.Type, s string) (i interface{}, err error) {
170 switch t.Kind() {
171 case reflect.Int:
172 i, err = strconv.Atoi(s)
173 case reflect.String:
174 i = s
175 case reflect.Ptr:
176 if t.Elem().String() != "regexp.Regexp" {
177 err = fmt.Errorf("%s does not support", t.Elem().String())
178 return
179 }
180 i, err = regexp.Compile(s)
129 } 181 }
130 return ts 182 return
131 } 183 }
......
...@@ -56,3 +56,19 @@ func TestGetValidFuncs(t *testing.T) { ...@@ -56,3 +56,19 @@ func TestGetValidFuncs(t *testing.T) {
56 t.Error("Range funcs should be got") 56 t.Error("Range funcs should be got")
57 } 57 }
58 } 58 }
59
60 func TestCall(t *testing.T) {
61 u := user{Name: "test", Age: 180}
62 tf := reflect.TypeOf(u)
63 var vfs []ValidFunc
64 var err error
65 f, _ := tf.FieldByName("Age")
66 if vfs, err = getValidFuncs(f); err != nil {
67 t.Fatal(err)
68 }
69 valid := &Validation{}
70 funcs.Call(vfs[1].Name, valid, u.Age, vfs[1].Params[0], vfs[1].Params[1], vfs[1].Name)
71 if len(valid.Errors) != 1 {
72 t.Error("age out of range should be has an error")
73 }
74 }
......
...@@ -2,6 +2,7 @@ package validation ...@@ -2,6 +2,7 @@ package validation
2 2
3 import ( 3 import (
4 "fmt" 4 "fmt"
5 "reflect"
5 "regexp" 6 "regexp"
6 ) 7 )
7 8
...@@ -175,3 +176,29 @@ func (v *Validation) Check(obj interface{}, checks ...Validator) *ValidationResu ...@@ -175,3 +176,29 @@ func (v *Validation) Check(obj interface{}, checks ...Validator) *ValidationResu
175 } 176 }
176 return result 177 return result
177 } 178 }
179
180 // the obj parameter must be a struct or a struct pointer
181 func (v *Validation) Valid(obj interface{}) (b bool, err error) {
182 t := reflect.TypeOf(obj)
183 switch {
184 case isStruct(t):
185 case isStructPtr(t):
186 t = t.Elem()
187 default:
188 err = fmt.Errorf("%v must be a struct or a struct pointer", obj)
189 return
190 }
191 // tv := reflect.TypeOf(v)
192 // for i := 0; i < t.NumField(); i++ {
193 // f := t.Field(i)
194 // var vfs []ValidFunc
195 // if vfs, err = getValidFuncs(f); err != nil {
196 // return
197 // }
198 // for _, vf := range vfs {
199 // m, _ := tv.MethodByName(vf.Name)
200 // m.Func
201 // }
202 // }
203 return
204 }
......
...@@ -57,16 +57,16 @@ func TestMax(t *testing.T) { ...@@ -57,16 +57,16 @@ func TestMax(t *testing.T) {
57 } 57 }
58 } 58 }
59 59
60 func TestRange(t *testing.T) { 60 // func TestRange(t *testing.T) {
61 valid := Validation{} 61 // valid := Validation{}
62 62
63 if valid.Range(-1, 0, 1, "range0_1").Ok { 63 // if valid.Range(-1, 0, 1, "range0_1").Ok {
64 t.Error("-1 is bettween 0 and 1 should be false") 64 // t.Error("-1 is bettween 0 and 1 should be false")
65 } 65 // }
66 if !valid.Range(1, 0, 1, "range0_1").Ok { 66 // if !valid.Range(1, 0, 1, "range0_1").Ok {
67 t.Error("1 is bettween 0 and 1 should be true") 67 // t.Error("1 is bettween 0 and 1 should be true")
68 } 68 // }
69 } 69 // }
70 70
71 func TestMinSize(t *testing.T) { 71 func TestMinSize(t *testing.T) {
72 valid := Validation{} 72 valid := Validation{}
......
...@@ -63,7 +63,7 @@ func (m Min) IsSatisfied(obj interface{}) bool { ...@@ -63,7 +63,7 @@ func (m Min) IsSatisfied(obj interface{}) bool {
63 } 63 }
64 64
65 func (m Min) DefaultMessage() string { 65 func (m Min) DefaultMessage() string {
66 return fmt.Sprintln("Minimum is", m.Min) 66 return fmt.Sprint("Minimum is ", m.Min)
67 } 67 }
68 68
69 func (m Min) GetKey() string { 69 func (m Min) GetKey() string {
...@@ -84,7 +84,7 @@ func (m Max) IsSatisfied(obj interface{}) bool { ...@@ -84,7 +84,7 @@ func (m Max) IsSatisfied(obj interface{}) bool {
84 } 84 }
85 85
86 func (m Max) DefaultMessage() string { 86 func (m Max) DefaultMessage() string {
87 return fmt.Sprintln("Maximum is", m.Max) 87 return fmt.Sprint("Maximum is ", m.Max)
88 } 88 }
89 89
90 func (m Max) GetKey() string { 90 func (m Max) GetKey() string {
...@@ -103,7 +103,7 @@ func (r Range) IsSatisfied(obj interface{}) bool { ...@@ -103,7 +103,7 @@ func (r Range) IsSatisfied(obj interface{}) bool {
103 } 103 }
104 104
105 func (r Range) DefaultMessage() string { 105 func (r Range) DefaultMessage() string {
106 return fmt.Sprintln("Range is", r.Min.Min, "to", r.Max.Max) 106 return fmt.Sprint("Range is ", r.Min.Min, " to ", r.Max.Max)
107 } 107 }
108 108
109 func (r Range) GetKey() string { 109 func (r Range) GetKey() string {
...@@ -128,7 +128,7 @@ func (m MinSize) IsSatisfied(obj interface{}) bool { ...@@ -128,7 +128,7 @@ func (m MinSize) IsSatisfied(obj interface{}) bool {
128 } 128 }
129 129
130 func (m MinSize) DefaultMessage() string { 130 func (m MinSize) DefaultMessage() string {
131 return fmt.Sprintln("Minimum size is", m.Min) 131 return fmt.Sprint("Minimum size is ", m.Min)
132 } 132 }
133 133
134 func (m MinSize) GetKey() string { 134 func (m MinSize) GetKey() string {
...@@ -153,7 +153,7 @@ func (m MaxSize) IsSatisfied(obj interface{}) bool { ...@@ -153,7 +153,7 @@ func (m MaxSize) IsSatisfied(obj interface{}) bool {
153 } 153 }
154 154
155 func (m MaxSize) DefaultMessage() string { 155 func (m MaxSize) DefaultMessage() string {
156 return fmt.Sprintln("Maximum size is", m.Max) 156 return fmt.Sprint("Maximum size is ", m.Max)
157 } 157 }
158 158
159 func (m MaxSize) GetKey() string { 159 func (m MaxSize) GetKey() string {
...@@ -178,7 +178,7 @@ func (l Length) IsSatisfied(obj interface{}) bool { ...@@ -178,7 +178,7 @@ func (l Length) IsSatisfied(obj interface{}) bool {
178 } 178 }
179 179
180 func (l Length) DefaultMessage() string { 180 func (l Length) DefaultMessage() string {
181 return fmt.Sprintln("Required length is", l.N) 181 return fmt.Sprint("Required length is ", l.N)
182 } 182 }
183 183
184 func (l Length) GetKey() string { 184 func (l Length) GetKey() string {
...@@ -202,7 +202,7 @@ func (a Alpha) IsSatisfied(obj interface{}) bool { ...@@ -202,7 +202,7 @@ func (a Alpha) IsSatisfied(obj interface{}) bool {
202 } 202 }
203 203
204 func (a Alpha) DefaultMessage() string { 204 func (a Alpha) DefaultMessage() string {
205 return fmt.Sprintln("Must be valid alpha characters") 205 return fmt.Sprint("Must be valid alpha characters")
206 } 206 }
207 207
208 func (a Alpha) GetKey() string { 208 func (a Alpha) GetKey() string {
...@@ -226,7 +226,7 @@ func (n Numeric) IsSatisfied(obj interface{}) bool { ...@@ -226,7 +226,7 @@ func (n Numeric) IsSatisfied(obj interface{}) bool {
226 } 226 }
227 227
228 func (n Numeric) DefaultMessage() string { 228 func (n Numeric) DefaultMessage() string {
229 return fmt.Sprintln("Must be valid numeric characters") 229 return fmt.Sprint("Must be valid numeric characters")
230 } 230 }
231 231
232 func (n Numeric) GetKey() string { 232 func (n Numeric) GetKey() string {
...@@ -250,7 +250,7 @@ func (a AlphaNumeric) IsSatisfied(obj interface{}) bool { ...@@ -250,7 +250,7 @@ func (a AlphaNumeric) IsSatisfied(obj interface{}) bool {
250 } 250 }
251 251
252 func (a AlphaNumeric) DefaultMessage() string { 252 func (a AlphaNumeric) DefaultMessage() string {
253 return fmt.Sprintln("Must be valid alpha or numeric characters") 253 return fmt.Sprint("Must be valid alpha or numeric characters")
254 } 254 }
255 255
256 func (a AlphaNumeric) GetKey() string { 256 func (a AlphaNumeric) GetKey() string {
...@@ -269,7 +269,7 @@ func (m Match) IsSatisfied(obj interface{}) bool { ...@@ -269,7 +269,7 @@ func (m Match) IsSatisfied(obj interface{}) bool {
269 } 269 }
270 270
271 func (m Match) DefaultMessage() string { 271 func (m Match) DefaultMessage() string {
272 return fmt.Sprintln("Must match", m.Regexp) 272 return fmt.Sprint("Must match ", m.Regexp)
273 } 273 }
274 274
275 func (m Match) GetKey() string { 275 func (m Match) GetKey() string {
...@@ -287,7 +287,7 @@ func (n NoMatch) IsSatisfied(obj interface{}) bool { ...@@ -287,7 +287,7 @@ func (n NoMatch) IsSatisfied(obj interface{}) bool {
287 } 287 }
288 288
289 func (n NoMatch) DefaultMessage() string { 289 func (n NoMatch) DefaultMessage() string {
290 return fmt.Sprintln("Must not match", n.Regexp) 290 return fmt.Sprint("Must not match ", n.Regexp)
291 } 291 }
292 292
293 func (n NoMatch) GetKey() string { 293 func (n NoMatch) GetKey() string {
...@@ -302,7 +302,7 @@ type AlphaDash struct { ...@@ -302,7 +302,7 @@ type AlphaDash struct {
302 } 302 }
303 303
304 func (a AlphaDash) DefaultMessage() string { 304 func (a AlphaDash) DefaultMessage() string {
305 return fmt.Sprintln("Must be valid alpha or numeric or dash(-_) characters") 305 return fmt.Sprint("Must be valid alpha or numeric or dash(-_) characters")
306 } 306 }
307 307
308 func (a AlphaDash) GetKey() string { 308 func (a AlphaDash) GetKey() string {
...@@ -317,7 +317,7 @@ type Email struct { ...@@ -317,7 +317,7 @@ type Email struct {
317 } 317 }
318 318
319 func (e Email) DefaultMessage() string { 319 func (e Email) DefaultMessage() string {
320 return fmt.Sprintln("Must be a valid email address") 320 return fmt.Sprint("Must be a valid email address")
321 } 321 }
322 322
323 func (e Email) GetKey() string { 323 func (e Email) GetKey() string {
...@@ -332,7 +332,7 @@ type IP struct { ...@@ -332,7 +332,7 @@ type IP struct {
332 } 332 }
333 333
334 func (i IP) DefaultMessage() string { 334 func (i IP) DefaultMessage() string {
335 return fmt.Sprintln("Must be a valid ip address") 335 return fmt.Sprint("Must be a valid ip address")
336 } 336 }
337 337
338 func (i IP) GetKey() string { 338 func (i IP) GetKey() string {
...@@ -347,7 +347,7 @@ type Base64 struct { ...@@ -347,7 +347,7 @@ type Base64 struct {
347 } 347 }
348 348
349 func (b Base64) DefaultMessage() string { 349 func (b Base64) DefaultMessage() string {
350 return fmt.Sprintln("Must be valid base64 characters") 350 return fmt.Sprint("Must be valid base64 characters")
351 } 351 }
352 352
353 func (b Base64) GetKey() string { 353 func (b Base64) GetKey() string {
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!