More Progess

added single field validation function.
updated a few more baked in functions.
added back single field validation benchmark.
pull/114/head
joeybloggs 9 years ago
parent 7af3fb7c1f
commit 68ba87af24
  1. 54
      baked_in.go
  2. 10
      benchmarks_test.go
  3. 24
      validator.go

@ -13,7 +13,7 @@ import (
// or even disregard and use your own map if so desired.
var BakedInValidators = map[string]Func{
"required": hasValue,
// "len": hasLengthOf,
"len": hasLengthOf,
"min": hasMinOf,
"max": hasMaxOf,
// "eq": isEq,
@ -621,7 +621,7 @@ func isGte(topStruct reflect.Value, currentStruct reflect.Value, field reflect.V
}
}
panic(fmt.Sprintf("Bad field type %T", field))
panic(fmt.Sprintf("Bad field type %T", field.Interface()))
}
// func isGt(top interface{}, current interface{}, field interface{}, param string) bool {
@ -665,43 +665,41 @@ func isGte(topStruct reflect.Value, currentStruct reflect.Value, field reflect.V
// panic(fmt.Sprintf("Bad field type %T", field))
// }
// // length tests whether a variable's length is equal to a given
// // value. For strings it tests the number of characters whereas
// // for maps and slices it tests the number of items.
// func hasLengthOf(top interface{}, current interface{}, field interface{}, param string) bool {
// length tests whether a variable's length is equal to a given
// value. For strings it tests the number of characters whereas
// for maps and slices it tests the number of items.
func hasLengthOf(topStruct reflect.Value, currentStruct reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
// st := reflect.ValueOf(field)
switch fieldKind {
// switch st.Kind() {
case reflect.String:
p := asInt(param)
// case reflect.String:
// p := asInt(param)
return int64(utf8.RuneCountInString(field.String())) == p
// return int64(utf8.RuneCountInString(st.String())) == p
case reflect.Slice, reflect.Map, reflect.Array:
p := asInt(param)
// case reflect.Slice, reflect.Map, reflect.Array:
// p := asInt(param)
return int64(field.Len()) == p
// return int64(st.Len()) == p
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
p := asInt(param)
// case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
// p := asInt(param)
return field.Int() == p
// return st.Int() == p
// case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
// p := asUint(param)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
p := asUint(param)
// return st.Uint() == p
return field.Uint() == p
// case reflect.Float32, reflect.Float64:
// p := asFloat(param)
case reflect.Float32, reflect.Float64:
p := asFloat(param)
// return st.Float() == p
// }
return field.Float() == p
}
// panic(fmt.Sprintf("Bad field type %T", field))
// }
panic(fmt.Sprintf("Bad field type %T", field.Interface()))
}
// min tests whether a variable value is larger or equal to a given
// number. For number types, it's a simple lesser-than test; for
@ -902,7 +900,7 @@ func isLte(topStruct reflect.Value, currentStruct reflect.Value, field reflect.V
}
}
panic(fmt.Sprintf("Bad field type %T", field))
panic(fmt.Sprintf("Bad field type %T", field.Interface()))
}
// func isLt(top interface{}, current interface{}, field interface{}, param string) bool {

@ -2,11 +2,11 @@ package validator
import "testing"
// func BenchmarkValidateField(b *testing.B) {
// for n := 0; n < b.N; n++ {
// validate.Field("1", "len=1")
// }
// }
func BenchmarkValidateField(b *testing.B) {
for n := 0; n < b.N; n++ {
validate.Field("1", "len=1")
}
}
func BenchmarkValidateStructSimple(b *testing.B) {

@ -141,6 +141,30 @@ func (v *Validate) tranverseStruct(topStruct reflect.Value, currentStruct reflec
}
}
// Field allows validation of a single field, still using tag style validation to check multiple errors
func (v *Validate) Field(field interface{}, tag string) ValidationErrors {
errs := map[string]*FieldError{}
fieldVal := reflect.ValueOf(field)
v.traverseField(fieldVal, fieldVal, fieldVal, "", errs, false, tag, "")
return errs
// return v.FieldWithValue(nil, field, tag)
}
// FieldWithValue allows validation of a single field, possibly even against another fields value, still using tag style validation to check multiple errors
func (v *Validate) FieldWithValue(val interface{}, field interface{}, tag string) ValidationErrors {
errs := map[string]*FieldError{}
topVal := reflect.ValueOf(val)
v.traverseField(topVal, topVal, reflect.ValueOf(field), "", errs, false, tag, "")
return errs
}
func (v *Validate) traverseField(topStruct reflect.Value, currentStruct reflect.Value, current reflect.Value, errPrefix string, errs ValidationErrors, isStructField bool, tag string, name string) {
if tag == skipValidationTag {

Loading…
Cancel
Save