Skip to content

Commit 10c0bd9

Browse files
Dean KarnDean Karn
authored andcommitted
Merge pull request #25 from joeybloggs/v4-development
V4 development
2 parents 130dcba + 1e1442d commit 10c0bd9

File tree

5 files changed

+78
-174
lines changed

5 files changed

+78
-174
lines changed

baked_in.go

Lines changed: 21 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ import (
88
"time"
99
)
1010

11-
// BakedInValidators is the map of ValidationFunc used internally
12-
// but can be used with any new Validator if desired
11+
// BakedInValidators is the default map of ValidationFunc
12+
// you can add, remove or even replace items to suite your needs,
13+
// or even disregard and use your own map if so desired.
1314
var BakedInValidators = map[string]ValidationFunc{
1415
"required": hasValue,
1516
"len": hasLengthOf,
@@ -54,7 +55,6 @@ func isURI(top interface{}, current interface{}, field interface{}, param string
5455
}
5556

5657
func isURL(top interface{}, current interface{}, field interface{}, param string) bool {
57-
5858
st := reflect.ValueOf(field)
5959

6060
switch st.Kind() {
@@ -77,146 +77,47 @@ func isURL(top interface{}, current interface{}, field interface{}, param string
7777
}
7878

7979
func isEmail(top interface{}, current interface{}, field interface{}, param string) bool {
80-
81-
st := reflect.ValueOf(field)
82-
83-
switch st.Kind() {
84-
85-
case reflect.String:
86-
return emailRegex.MatchString(field.(string))
87-
}
88-
89-
panic(fmt.Sprintf("Bad field type %T", field))
80+
return matchesRegex(emailRegex, field)
9081
}
9182

9283
func isHsla(top interface{}, current interface{}, field interface{}, param string) bool {
93-
94-
st := reflect.ValueOf(field)
95-
96-
switch st.Kind() {
97-
98-
case reflect.String:
99-
return hslaRegex.MatchString(field.(string))
100-
}
101-
102-
panic(fmt.Sprintf("Bad field type %T", field))
84+
return matchesRegex(hslaRegex, field)
10385
}
10486

10587
func isHsl(top interface{}, current interface{}, field interface{}, param string) bool {
106-
107-
st := reflect.ValueOf(field)
108-
109-
switch st.Kind() {
110-
111-
case reflect.String:
112-
return hslRegex.MatchString(field.(string))
113-
}
114-
115-
panic(fmt.Sprintf("Bad field type %T", field))
88+
return matchesRegex(hslRegex, field)
11689
}
11790

11891
func isRgba(top interface{}, current interface{}, field interface{}, param string) bool {
119-
120-
st := reflect.ValueOf(field)
121-
122-
switch st.Kind() {
123-
124-
case reflect.String:
125-
return rgbaRegex.MatchString(field.(string))
126-
}
127-
128-
panic(fmt.Sprintf("Bad field type %T", field))
92+
return matchesRegex(rgbaRegex, field)
12993
}
13094

13195
func isRgb(top interface{}, current interface{}, field interface{}, param string) bool {
132-
133-
st := reflect.ValueOf(field)
134-
135-
switch st.Kind() {
136-
137-
case reflect.String:
138-
return rgbRegex.MatchString(field.(string))
139-
}
140-
141-
panic(fmt.Sprintf("Bad field type %T", field))
96+
return matchesRegex(rgbRegex, field)
14297
}
14398

14499
func isHexcolor(top interface{}, current interface{}, field interface{}, param string) bool {
145-
146-
st := reflect.ValueOf(field)
147-
148-
switch st.Kind() {
149-
150-
case reflect.String:
151-
return hexcolorRegex.MatchString(field.(string))
152-
}
153-
154-
panic(fmt.Sprintf("Bad field type %T", field))
100+
return matchesRegex(hexcolorRegex, field)
155101
}
156102

157103
func isHexadecimal(top interface{}, current interface{}, field interface{}, param string) bool {
158-
159-
st := reflect.ValueOf(field)
160-
161-
switch st.Kind() {
162-
163-
case reflect.String:
164-
return hexadecimalRegex.MatchString(field.(string))
165-
}
166-
167-
panic(fmt.Sprintf("Bad field type %T", field))
104+
return matchesRegex(hexadecimalRegex, field)
168105
}
169106

170107
func isNumber(top interface{}, current interface{}, field interface{}, param string) bool {
171-
172-
st := reflect.ValueOf(field)
173-
174-
switch st.Kind() {
175-
176-
case reflect.String:
177-
return numberRegex.MatchString(field.(string))
178-
}
179-
180-
panic(fmt.Sprintf("Bad field type %T", field))
108+
return matchesRegex(numberRegex, field)
181109
}
182110

183111
func isNumeric(top interface{}, current interface{}, field interface{}, param string) bool {
184-
185-
st := reflect.ValueOf(field)
186-
187-
switch st.Kind() {
188-
189-
case reflect.String:
190-
return numericRegex.MatchString(field.(string))
191-
}
192-
193-
panic(fmt.Sprintf("Bad field type %T", field))
112+
return matchesRegex(numericRegex, field)
194113
}
195114

196115
func isAlphanum(top interface{}, current interface{}, field interface{}, param string) bool {
197-
198-
st := reflect.ValueOf(field)
199-
200-
switch st.Kind() {
201-
202-
case reflect.String:
203-
return alphaNumericRegex.MatchString(field.(string))
204-
}
205-
206-
panic(fmt.Sprintf("Bad field type %T", field))
116+
return matchesRegex(alphaNumericRegex, field)
207117
}
208118

209119
func isAlpha(top interface{}, current interface{}, field interface{}, param string) bool {
210-
211-
st := reflect.ValueOf(field)
212-
213-
switch st.Kind() {
214-
215-
case reflect.String:
216-
return alphaRegex.MatchString(field.(string))
217-
}
218-
219-
panic(fmt.Sprintf("Bad field type %T", field))
120+
return matchesRegex(alphaRegex, field)
220121
}
221122

222123
func hasValue(top interface{}, current interface{}, field interface{}, param string) bool {
@@ -767,10 +668,7 @@ func hasMaxOf(top interface{}, current interface{}, field interface{}, param str
767668
func asInt(param string) int64 {
768669

769670
i, err := strconv.ParseInt(param, 0, 64)
770-
771-
if err != nil {
772-
panic(err.Error())
773-
}
671+
panicIf(err)
774672

775673
return i
776674
}
@@ -780,10 +678,7 @@ func asInt(param string) int64 {
780678
func asUint(param string) uint64 {
781679

782680
i, err := strconv.ParseUint(param, 0, 64)
783-
784-
if err != nil {
785-
panic(err.Error())
786-
}
681+
panicIf(err)
787682

788683
return i
789684
}
@@ -793,10 +688,13 @@ func asUint(param string) uint64 {
793688
func asFloat(param string) float64 {
794689

795690
i, err := strconv.ParseFloat(param, 64)
691+
panicIf(err)
796692

693+
return i
694+
}
695+
696+
func panicIf(err error) {
797697
if err != nil {
798698
panic(err.Error())
799699
}
800-
801-
return i
802700
}

doc.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
/*
2-
Package validator implements value validations for structs and individual fields based on tags.
2+
Package validator implements value validations for structs and individual fields based on tags. It can also handle Cross Field validation and even Cross Field Cross Struct validation for nested structs.
33
44
Built In Validator
55
6-
v3 no longer contains a built in Validator instance.
7-
86
myValidator = validator.NewValidator("validate", validator.BakedInValidators)
97
108
errs := myValidator.ValidateStruct(//your struct)
@@ -36,6 +34,9 @@ A simple example usage:
3634
errs.StructErrors will be empty <-- fields that were structs
3735
errs.Errors will have 1 error of type FieldValidationError
3836
37+
NOTE: Anonymous Structs - they don't have names so expect the Struct name
38+
within StructValidationErrors to be blank.
39+
3940
Error Handling
4041
4142
The error can be used like so
@@ -103,9 +104,9 @@ Cross Field Validation can be implemented, for example Start & End Date range va
103104
// when calling myValidator.ValidateFieldByTag(field, tag) val will be nil
104105
//
105106
// Because of the specific requirements and field names within each persons project that
106-
// uses this library it is likely that custom functions will need to be created.
107-
// however there are some build in Generic Cross Field validation, see Baked In Validators and
108-
// Tags below
107+
// uses this library it is likely that custom functions will need to be created for your
108+
// Cross Field Validation needs, however there are some build in Generic Cross Field validations,
109+
// see Baked In Validators and Tags below
109110
110111
func isDateRangeValid(val interface{}, field interface{}, param string) bool {
111112
@@ -307,10 +308,11 @@ Validator notes:
307308
a regex which conflict with the validation definitions, although workarounds
308309
can be made, they take away from using pure regex's. Furthermore it's quick
309310
and dirty but the regex's become harder to maintain and are not reusable, so
310-
it's as much as a programming philosiphy as anything.
311+
it's as much a programming philosiphy as anything.
311312
312313
In place of this new validator functions should be created; a regex can be
313-
used within the validator function and even be precompiled for better efficiency.
314+
used within the validator function and even be precompiled for better efficiency
315+
within regexes.go.
314316
315317
And the best reason, you can sumit a pull request and we can keep on adding to the
316318
validation library of this package!

regexes.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ const (
1414
hslRegexString = "^hsl\\(\\s*(0|[1-9]\\d?|[12]\\d\\d|3[0-5]\\d|360)\\s*,\\s*((0|[1-9]\\d?|100)%)\\s*,\\s*((0|[1-9]\\d?|100)%)\\s*\\)$"
1515
hslaRegexString = "^hsla\\(\\s*(0|[1-9]\\d?|[12]\\d\\d|3[0-5]\\d|360)\\s*,\\s*((0|[1-9]\\d?|100)%)\\s*,\\s*((0|[1-9]\\d?|100)%)\\s*,\\s*((0.[1-9]*)|[01])\\s*\\)$"
1616
emailRegexString = "^(((([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+(\\.([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.)+(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.?$"
17-
// urlRegexString = `^((ftp|http|https):\/\/)?(\S+(:\S*)?@)?((([1-9]\d?|1\d\d|2[01]\d|22[0-3])(\.(1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.([0-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|((www\.)?)?(([a-z\x{00a1}-\x{ffff}0-9]+-?-?_?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.([a-z\x{00a1}-\x{ffff}]{2,}))?)|localhost)(:(\d{1,5}))?((\/|\?|#)[^\s]*)?$`
18-
// urlRegexString = "^(?:(?:https?|ftp):\\/\\/)(?:\\S+(?::\\S*)?@)?(?:(?!10(?:\\.\\d{1,3}){3})(?!127(?:\\.\\d{1,3}){3})(?!169\\.254(?:\\.\\d{1,3}){2})(?!192\\.168(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\\.(?:[a-z\u00a1-\uffff]{2,})))(?::\\d{2,5})?(?:\\/[^\\s]*)?$"
1917
)
2018

2119
var (
@@ -31,3 +29,8 @@ var (
3129
hslaRegex = regexp.MustCompile(hslaRegexString)
3230
emailRegex = regexp.MustCompile(emailRegexString)
3331
)
32+
33+
func matchesRegex(regex *regexp.Regexp, field interface{}) bool {
34+
fieldAsString := field.(string) //this will panic inherently
35+
return regex.MatchString(fieldAsString)
36+
}

0 commit comments

Comments
 (0)