Finished converting baked in functions & some updates

completed all validations function conversion.
updated omitempty check to continue if all ok instead of
passing tag to be validated.
pull/114/head
joeybloggs 9 years ago
parent 68ba87af24
commit 019c5fc4ac
  1. 1059
      baked_in.go
  2. 238
      benchmarks_test.go
  3. 6
      regexes.go
  4. 56
      validator.go

File diff suppressed because it is too large Load Diff

@ -42,122 +42,122 @@ func BenchmarkTemplateParallelSimple(b *testing.B) {
}) })
} }
// func BenchmarkValidateStructLarge(b *testing.B) { func BenchmarkValidateStructLarge(b *testing.B) {
// tFail := &TestString{ tFail := &TestString{
// Required: "", Required: "",
// Len: "", Len: "",
// Min: "", Min: "",
// Max: "12345678901", Max: "12345678901",
// MinMax: "", MinMax: "",
// Lt: "0123456789", Lt: "0123456789",
// Lte: "01234567890", Lte: "01234567890",
// Gt: "1", Gt: "1",
// Gte: "1", Gte: "1",
// OmitEmpty: "12345678901", OmitEmpty: "12345678901",
// Sub: &SubTest{ Sub: &SubTest{
// Test: "", Test: "",
// }, },
// Anonymous: struct { Anonymous: struct {
// A string `validate:"required"` A string `validate:"required"`
// }{ }{
// A: "", A: "",
// }, },
// Iface: &Impl{ Iface: &Impl{
// F: "12", F: "12",
// }, },
// } }
// tSuccess := &TestString{ tSuccess := &TestString{
// Required: "Required", Required: "Required",
// Len: "length==10", Len: "length==10",
// Min: "min=1", Min: "min=1",
// Max: "1234567890", Max: "1234567890",
// MinMax: "12345", MinMax: "12345",
// Lt: "012345678", Lt: "012345678",
// Lte: "0123456789", Lte: "0123456789",
// Gt: "01234567890", Gt: "01234567890",
// Gte: "0123456789", Gte: "0123456789",
// OmitEmpty: "", OmitEmpty: "",
// Sub: &SubTest{ Sub: &SubTest{
// Test: "1", Test: "1",
// }, },
// SubIgnore: &SubTest{ SubIgnore: &SubTest{
// Test: "", Test: "",
// }, },
// Anonymous: struct { Anonymous: struct {
// A string `validate:"required"` A string `validate:"required"`
// }{ }{
// A: "1", A: "1",
// }, },
// Iface: &Impl{ Iface: &Impl{
// F: "123", F: "123",
// }, },
// } }
// for n := 0; n < b.N; n++ { for n := 0; n < b.N; n++ {
// validate.Struct(tSuccess) validate.Struct(tSuccess)
// validate.Struct(tFail) validate.Struct(tFail)
// } }
// } }
// func BenchmarkTemplateParallelLarge(b *testing.B) { func BenchmarkTemplateParallelLarge(b *testing.B) {
// tFail := &TestString{ tFail := &TestString{
// Required: "", Required: "",
// Len: "", Len: "",
// Min: "", Min: "",
// Max: "12345678901", Max: "12345678901",
// MinMax: "", MinMax: "",
// Lt: "0123456789", Lt: "0123456789",
// Lte: "01234567890", Lte: "01234567890",
// Gt: "1", Gt: "1",
// Gte: "1", Gte: "1",
// OmitEmpty: "12345678901", OmitEmpty: "12345678901",
// Sub: &SubTest{ Sub: &SubTest{
// Test: "", Test: "",
// }, },
// Anonymous: struct { Anonymous: struct {
// A string `validate:"required"` A string `validate:"required"`
// }{ }{
// A: "", A: "",
// }, },
// Iface: &Impl{ Iface: &Impl{
// F: "12", F: "12",
// }, },
// } }
// tSuccess := &TestString{ tSuccess := &TestString{
// Required: "Required", Required: "Required",
// Len: "length==10", Len: "length==10",
// Min: "min=1", Min: "min=1",
// Max: "1234567890", Max: "1234567890",
// MinMax: "12345", MinMax: "12345",
// Lt: "012345678", Lt: "012345678",
// Lte: "0123456789", Lte: "0123456789",
// Gt: "01234567890", Gt: "01234567890",
// Gte: "0123456789", Gte: "0123456789",
// OmitEmpty: "", OmitEmpty: "",
// Sub: &SubTest{ Sub: &SubTest{
// Test: "1", Test: "1",
// }, },
// SubIgnore: &SubTest{ SubIgnore: &SubTest{
// Test: "", Test: "",
// }, },
// Anonymous: struct { Anonymous: struct {
// A string `validate:"required"` A string `validate:"required"`
// }{ }{
// A: "1", A: "1",
// }, },
// Iface: &Impl{ Iface: &Impl{
// F: "123", F: "123",
// }, },
// } }
// b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
// for pb.Next() { for pb.Next() {
// validate.Struct(tSuccess) validate.Struct(tSuccess)
// validate.Struct(tFail) validate.Struct(tFail)
// } }
// }) })
// } }

@ -58,7 +58,7 @@ var (
sSNRegex = regexp.MustCompile(sSNRegexString) sSNRegex = regexp.MustCompile(sSNRegexString)
) )
func matchesRegex(regex *regexp.Regexp, field interface{}) bool { func matchesRegex(regex *regexp.Regexp, value string) bool {
fieldAsString := field.(string) //this will panic inherently // fieldAsString := field.(string) //this will panic inherently
return regex.MatchString(fieldAsString) return regex.MatchString(value)
} }

@ -101,6 +101,28 @@ func New(config Config) *Validate {
return &Validate{config: config} return &Validate{config: config}
} }
// 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
}
// 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
}
// Struct validates a struct, even it's nested structs, and returns a struct containing the errors // Struct validates a struct, even it's nested structs, and returns a struct containing the errors
// NOTE: Nested Arrays, or Maps of structs do not get validated only the Array or Map itself; the reason is that there is no good // NOTE: Nested Arrays, or Maps of structs do not get validated only the Array or Map itself; the reason is that there is no good
// way to represent or report which struct within the array has the error, besides can validate the struct prior to adding it to // way to represent or report which struct within the array has the error, besides can validate the struct prior to adding it to
@ -141,30 +163,6 @@ 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) { 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 { if tag == skipValidationTag {
@ -275,13 +273,13 @@ func (v *Validate) traverseField(topStruct reflect.Value, currentStruct reflect.
// no use in checking tags if it's empty and is ok to be // no use in checking tags if it's empty and is ok to be
// omitempty needs to be the first tag if you wish to use it // omitempty needs to be the first tag if you wish to use it
if t == omitempty && !hasValue(topStruct, currentStruct, current, typ, kind, "") { if t == omitempty {
if !hasValue(topStruct, currentStruct, current, typ, kind, "") {
return return
} }
continue
// if strings.Contains(tag, omitempty) && !hasValue(topStruct, currentStruct, current, "") { }
// return
// }
var key string var key string
var param string var param string

Loading…
Cancel
Save