Commit 4c6163ba authored by miraclesu's avatar miraclesu

add funcmap

parent aba1728b
...@@ -3,6 +3,8 @@ package validation ...@@ -3,6 +3,8 @@ package validation
import ( import (
"fmt" "fmt"
"reflect" "reflect"
"regexp"
"strconv"
"strings" "strings"
) )
...@@ -13,7 +15,7 @@ const ( ...@@ -13,7 +15,7 @@ const (
var ( var (
// key: function name // key: function name
// value: the number of parameters // value: the number of parameters
funcs = make(map[string]int) funcs = make(Funcs)
// doesn't belong to validation functions // doesn't belong to validation functions
unFuncs = map[string]bool{ unFuncs = map[string]bool{
...@@ -33,7 +35,7 @@ func init() { ...@@ -33,7 +35,7 @@ func init() {
for i := 0; i < t.NumMethod(); i++ { for i := 0; i < t.NumMethod(); i++ {
m := t.Method(i) m := t.Method(i)
if !unFuncs[m.Name] { if !unFuncs[m.Name] {
funcs[m.Name] = m.Type.NumIn() - 3 funcs[m.Name] = m.Func
} }
} }
} }
...@@ -43,6 +45,25 @@ type ValidFunc struct { ...@@ -43,6 +45,25 @@ type ValidFunc struct {
Params []interface{} Params []interface{}
} }
type Funcs map[string]reflect.Value
func (f Funcs) Call(name string, params ...interface{}) (result []reflect.Value, err error) {
if _, ok := f[name]; !ok {
err = fmt.Errorf("%s does not exist", name)
return
}
if len(params) != f[name].Type().NumIn() {
err = fmt.Errorf("The number of params is not adapted")
return
}
in := make([]reflect.Value, len(params))
for k, param := range params {
in[k] = reflect.ValueOf(param)
}
result = f[name].Call(in)
return
}
func isStruct(t reflect.Type) bool { func isStruct(t reflect.Type) bool {
return t.Kind() == reflect.Struct return t.Kind() == reflect.Struct
} }
...@@ -110,22 +131,53 @@ func parseFunc(vfunc string) (v ValidFunc, err error) { ...@@ -110,22 +131,53 @@ func parseFunc(vfunc string) (v ValidFunc, err error) {
return return
} }
v = ValidFunc{name, trim(params)} tParams, err := trim(name, params)
if err != nil {
return
}
v = ValidFunc{name, tParams}
return return
} }
func numIn(name string) (num int, err error) { func numIn(name string) (num int, err error) {
num, ok := funcs[name] fn, ok := funcs[name]
if !ok { if !ok {
err = fmt.Errorf("doesn't exsits %s valid function", name) err = fmt.Errorf("doesn't exsits %s valid function", name)
return
} }
num = fn.Type().NumIn() - 3
return return
} }
func trim(s []string) []interface{} { func trim(name string, s []string) (ts []interface{}, err error) {
ts := make([]interface{}, len(s)) ts = make([]interface{}, len(s))
fn, ok := funcs[name]
if !ok {
err = fmt.Errorf("doesn't exsits %s valid function", name)
return
}
for i := 0; i < len(s); i++ { for i := 0; i < len(s); i++ {
ts[i] = strings.TrimSpace(s[i]) var param interface{}
if param, err = magic(fn.Type().In(i+2), strings.TrimSpace(s[i])); err != nil {
return
}
ts[i] = param
}
return
}
func magic(t reflect.Type, s string) (i interface{}, err error) {
switch t.Kind() {
case reflect.Int:
i, err = strconv.Atoi(s)
case reflect.String:
i = s
case reflect.Ptr:
if t.Elem().String() != "regexp.Regexp" {
err = fmt.Errorf("%s does not support", t.Elem().String())
return
}
i, err = regexp.Compile(s)
} }
return ts return
} }
...@@ -56,3 +56,19 @@ func TestGetValidFuncs(t *testing.T) { ...@@ -56,3 +56,19 @@ func TestGetValidFuncs(t *testing.T) {
t.Error("Range funcs should be got") t.Error("Range funcs should be got")
} }
} }
func TestCall(t *testing.T) {
u := user{Name: "test", Age: 180}
tf := reflect.TypeOf(u)
var vfs []ValidFunc
var err error
f, _ := tf.FieldByName("Age")
if vfs, err = getValidFuncs(f); err != nil {
t.Fatal(err)
}
valid := &Validation{}
funcs.Call(vfs[1].Name, valid, u.Age, vfs[1].Params[0], vfs[1].Params[1], vfs[1].Name)
if len(valid.Errors) != 1 {
t.Error("age out of range should be has an error")
}
}
...@@ -2,6 +2,7 @@ package validation ...@@ -2,6 +2,7 @@ package validation
import ( import (
"fmt" "fmt"
"reflect"
"regexp" "regexp"
) )
...@@ -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
} }
return result return result
} }
// the obj parameter must be a struct or a struct pointer
func (v *Validation) Valid(obj interface{}) (b bool, err error) {
t := reflect.TypeOf(obj)
switch {
case isStruct(t):
case isStructPtr(t):
t = t.Elem()
default:
err = fmt.Errorf("%v must be a struct or a struct pointer", obj)
return
}
// tv := reflect.TypeOf(v)
// for i := 0; i < t.NumField(); i++ {
// f := t.Field(i)
// var vfs []ValidFunc
// if vfs, err = getValidFuncs(f); err != nil {
// return
// }
// for _, vf := range vfs {
// m, _ := tv.MethodByName(vf.Name)
// m.Func
// }
// }
return
}
...@@ -57,16 +57,16 @@ func TestMax(t *testing.T) { ...@@ -57,16 +57,16 @@ func TestMax(t *testing.T) {
} }
} }
func TestRange(t *testing.T) { // func TestRange(t *testing.T) {
valid := Validation{} // valid := Validation{}
if valid.Range(-1, 0, 1, "range0_1").Ok { // if valid.Range(-1, 0, 1, "range0_1").Ok {
t.Error("-1 is bettween 0 and 1 should be false") // t.Error("-1 is bettween 0 and 1 should be false")
} // }
if !valid.Range(1, 0, 1, "range0_1").Ok { // if !valid.Range(1, 0, 1, "range0_1").Ok {
t.Error("1 is bettween 0 and 1 should be true") // t.Error("1 is bettween 0 and 1 should be true")
} // }
} // }
func TestMinSize(t *testing.T) { func TestMinSize(t *testing.T) {
valid := Validation{} valid := Validation{}
......
...@@ -63,7 +63,7 @@ func (m Min) IsSatisfied(obj interface{}) bool { ...@@ -63,7 +63,7 @@ func (m Min) IsSatisfied(obj interface{}) bool {
} }
func (m Min) DefaultMessage() string { func (m Min) DefaultMessage() string {
return fmt.Sprintln("Minimum is", m.Min) return fmt.Sprint("Minimum is ", m.Min)
} }
func (m Min) GetKey() string { 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 {
} }
func (m Max) DefaultMessage() string { func (m Max) DefaultMessage() string {
return fmt.Sprintln("Maximum is", m.Max) return fmt.Sprint("Maximum is ", m.Max)
} }
func (m Max) GetKey() string { 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 {
} }
func (r Range) DefaultMessage() string { func (r Range) DefaultMessage() string {
return fmt.Sprintln("Range is", r.Min.Min, "to", r.Max.Max) return fmt.Sprint("Range is ", r.Min.Min, " to ", r.Max.Max)
} }
func (r Range) GetKey() string { 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 {
} }
func (m MinSize) DefaultMessage() string { func (m MinSize) DefaultMessage() string {
return fmt.Sprintln("Minimum size is", m.Min) return fmt.Sprint("Minimum size is ", m.Min)
} }
func (m MinSize) GetKey() string { 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 {
} }
func (m MaxSize) DefaultMessage() string { func (m MaxSize) DefaultMessage() string {
return fmt.Sprintln("Maximum size is", m.Max) return fmt.Sprint("Maximum size is ", m.Max)
} }
func (m MaxSize) GetKey() string { 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 {
} }
func (l Length) DefaultMessage() string { func (l Length) DefaultMessage() string {
return fmt.Sprintln("Required length is", l.N) return fmt.Sprint("Required length is ", l.N)
} }
func (l Length) GetKey() string { 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 {
} }
func (a Alpha) DefaultMessage() string { func (a Alpha) DefaultMessage() string {
return fmt.Sprintln("Must be valid alpha characters") return fmt.Sprint("Must be valid alpha characters")
} }
func (a Alpha) GetKey() string { 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 {
} }
func (n Numeric) DefaultMessage() string { func (n Numeric) DefaultMessage() string {
return fmt.Sprintln("Must be valid numeric characters") return fmt.Sprint("Must be valid numeric characters")
} }
func (n Numeric) GetKey() string { 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 {
} }
func (a AlphaNumeric) DefaultMessage() string { func (a AlphaNumeric) DefaultMessage() string {
return fmt.Sprintln("Must be valid alpha or numeric characters") return fmt.Sprint("Must be valid alpha or numeric characters")
} }
func (a AlphaNumeric) GetKey() string { 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 {
} }
func (m Match) DefaultMessage() string { func (m Match) DefaultMessage() string {
return fmt.Sprintln("Must match", m.Regexp) return fmt.Sprint("Must match ", m.Regexp)
} }
func (m Match) GetKey() string { 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 {
} }
func (n NoMatch) DefaultMessage() string { func (n NoMatch) DefaultMessage() string {
return fmt.Sprintln("Must not match", n.Regexp) return fmt.Sprint("Must not match ", n.Regexp)
} }
func (n NoMatch) GetKey() string { func (n NoMatch) GetKey() string {
...@@ -302,7 +302,7 @@ type AlphaDash struct { ...@@ -302,7 +302,7 @@ type AlphaDash struct {
} }
func (a AlphaDash) DefaultMessage() string { func (a AlphaDash) DefaultMessage() string {
return fmt.Sprintln("Must be valid alpha or numeric or dash(-_) characters") return fmt.Sprint("Must be valid alpha or numeric or dash(-_) characters")
} }
func (a AlphaDash) GetKey() string { func (a AlphaDash) GetKey() string {
...@@ -317,7 +317,7 @@ type Email struct { ...@@ -317,7 +317,7 @@ type Email struct {
} }
func (e Email) DefaultMessage() string { func (e Email) DefaultMessage() string {
return fmt.Sprintln("Must be a valid email address") return fmt.Sprint("Must be a valid email address")
} }
func (e Email) GetKey() string { func (e Email) GetKey() string {
...@@ -332,7 +332,7 @@ type IP struct { ...@@ -332,7 +332,7 @@ type IP struct {
} }
func (i IP) DefaultMessage() string { func (i IP) DefaultMessage() string {
return fmt.Sprintln("Must be a valid ip address") return fmt.Sprint("Must be a valid ip address")
} }
func (i IP) GetKey() string { func (i IP) GetKey() string {
...@@ -347,7 +347,7 @@ type Base64 struct { ...@@ -347,7 +347,7 @@ type Base64 struct {
} }
func (b Base64) DefaultMessage() string { func (b Base64) DefaultMessage() string {
return fmt.Sprintln("Must be valid base64 characters") return fmt.Sprint("Must be valid base64 characters")
} }
func (b Base64) GetKey() string { func (b Base64) GetKey() string {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment