Skip to content

Commit 276e0f9

Browse files
Dean KarnDean Karn
authored andcommitted
Merge branch 'v2-development' into v2
2 parents bb80e92 + edb25ac commit 276e0f9

File tree

3 files changed

+892
-4
lines changed

3 files changed

+892
-4
lines changed

baked_in.go

Lines changed: 308 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ var BakedInValidators = map[string]ValidationFunc{
1919
"lte": isLte,
2020
"gt": isGt,
2121
"gte": isGte,
22+
"gtefield": isGteField,
23+
"gtfield": isGtField,
24+
"ltefield": isLteField,
25+
"ltfield": isLtField,
2226
"alpha": isAlpha,
2327
"alphanum": isAlphanum,
2428
"numeric": isNumeric,
@@ -229,6 +233,156 @@ func hasValue(val interface{}, field interface{}, param string) bool {
229233
}
230234
}
231235

236+
func isGteField(val interface{}, field interface{}, param string) bool {
237+
238+
if val == nil {
239+
panic("struct not passed for cross validation")
240+
}
241+
242+
topVal := reflect.ValueOf(val)
243+
244+
if topVal.Kind() == reflect.Ptr && !topVal.IsNil() {
245+
topVal = reflect.ValueOf(topVal.Elem().Interface())
246+
}
247+
248+
var topFieldVal reflect.Value
249+
250+
switch topVal.Kind() {
251+
252+
case reflect.Struct:
253+
254+
if topVal.Type() == reflect.TypeOf(time.Time{}) {
255+
topFieldVal = topVal
256+
break
257+
}
258+
259+
f := topVal.FieldByName(param)
260+
261+
if f.Kind() == reflect.Invalid {
262+
panic(fmt.Sprintf("Field \"%s\" not found in struct", param))
263+
}
264+
265+
topFieldVal = f
266+
267+
default:
268+
269+
topFieldVal = topVal
270+
}
271+
272+
if topFieldVal.Kind() == reflect.Ptr && !topFieldVal.IsNil() {
273+
274+
topFieldVal = reflect.ValueOf(topFieldVal.Elem().Interface())
275+
}
276+
277+
fv := reflect.ValueOf(field)
278+
279+
switch fv.Kind() {
280+
281+
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
282+
283+
return fv.Int() >= topFieldVal.Int()
284+
285+
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
286+
287+
return fv.Uint() >= topFieldVal.Uint()
288+
289+
case reflect.Float32, reflect.Float64:
290+
291+
return fv.Float() >= topFieldVal.Float()
292+
293+
case reflect.Struct:
294+
295+
if fv.Type() == reflect.TypeOf(time.Time{}) {
296+
297+
if topFieldVal.Type() != reflect.TypeOf(time.Time{}) {
298+
panic("Bad Top Level field type")
299+
}
300+
301+
t := topFieldVal.Interface().(time.Time)
302+
fieldTime := field.(time.Time)
303+
304+
return fieldTime.After(t) || fieldTime.Equal(t)
305+
}
306+
}
307+
308+
panic(fmt.Sprintf("Bad field type %T", field))
309+
}
310+
311+
func isGtField(val interface{}, field interface{}, param string) bool {
312+
313+
if val == nil {
314+
panic("struct not passed for cross validation")
315+
}
316+
317+
topVal := reflect.ValueOf(val)
318+
319+
if topVal.Kind() == reflect.Ptr && !topVal.IsNil() {
320+
topVal = reflect.ValueOf(topVal.Elem().Interface())
321+
}
322+
323+
var topFieldVal reflect.Value
324+
325+
switch topVal.Kind() {
326+
327+
case reflect.Struct:
328+
329+
if topVal.Type() == reflect.TypeOf(time.Time{}) {
330+
topFieldVal = topVal
331+
break
332+
}
333+
334+
f := topVal.FieldByName(param)
335+
336+
if f.Kind() == reflect.Invalid {
337+
panic(fmt.Sprintf("Field \"%s\" not found in struct", param))
338+
}
339+
340+
topFieldVal = f
341+
342+
default:
343+
344+
topFieldVal = topVal
345+
}
346+
347+
if topFieldVal.Kind() == reflect.Ptr && !topFieldVal.IsNil() {
348+
349+
topFieldVal = reflect.ValueOf(topFieldVal.Elem().Interface())
350+
}
351+
352+
fv := reflect.ValueOf(field)
353+
354+
switch fv.Kind() {
355+
356+
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
357+
358+
return fv.Int() > topFieldVal.Int()
359+
360+
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
361+
362+
return fv.Uint() > topFieldVal.Uint()
363+
364+
case reflect.Float32, reflect.Float64:
365+
366+
return fv.Float() > topFieldVal.Float()
367+
368+
case reflect.Struct:
369+
370+
if fv.Type() == reflect.TypeOf(time.Time{}) {
371+
372+
if topFieldVal.Type() != reflect.TypeOf(time.Time{}) {
373+
panic("Bad Top Level field type")
374+
}
375+
376+
t := topFieldVal.Interface().(time.Time)
377+
fieldTime := field.(time.Time)
378+
379+
return fieldTime.After(t)
380+
}
381+
}
382+
383+
panic(fmt.Sprintf("Bad field type %T", field))
384+
}
385+
232386
func isGte(val interface{}, field interface{}, param string) bool {
233387

234388
st := reflect.ValueOf(field)
@@ -262,7 +416,7 @@ func isGte(val interface{}, field interface{}, param string) bool {
262416

263417
case reflect.Struct:
264418

265-
if st.Type() == reflect.TypeOf(field) {
419+
if st.Type() == reflect.TypeOf(time.Time{}) {
266420

267421
now := time.Now().UTC()
268422
t := field.(time.Time)
@@ -306,7 +460,7 @@ func isGt(val interface{}, field interface{}, param string) bool {
306460
return st.Float() > p
307461
case reflect.Struct:
308462

309-
if st.Type() == reflect.TypeOf(field) {
463+
if st.Type() == reflect.TypeOf(time.Time{}) {
310464

311465
return field.(time.Time).After(time.Now().UTC())
312466
}
@@ -362,6 +516,156 @@ func hasMinOf(val interface{}, field interface{}, param string) bool {
362516
return isGte(val, field, param)
363517
}
364518

519+
func isLteField(val interface{}, field interface{}, param string) bool {
520+
521+
if val == nil {
522+
panic("struct not passed for cross validation")
523+
}
524+
525+
topVal := reflect.ValueOf(val)
526+
527+
if topVal.Kind() == reflect.Ptr && !topVal.IsNil() {
528+
topVal = reflect.ValueOf(topVal.Elem().Interface())
529+
}
530+
531+
var topFieldVal reflect.Value
532+
533+
switch topVal.Kind() {
534+
535+
case reflect.Struct:
536+
537+
if topVal.Type() == reflect.TypeOf(time.Time{}) {
538+
topFieldVal = topVal
539+
break
540+
}
541+
542+
f := topVal.FieldByName(param)
543+
544+
if f.Kind() == reflect.Invalid {
545+
panic(fmt.Sprintf("Field \"%s\" not found in struct", param))
546+
}
547+
548+
topFieldVal = f
549+
550+
default:
551+
552+
topFieldVal = topVal
553+
}
554+
555+
if topFieldVal.Kind() == reflect.Ptr && !topFieldVal.IsNil() {
556+
557+
topFieldVal = reflect.ValueOf(topFieldVal.Elem().Interface())
558+
}
559+
560+
fv := reflect.ValueOf(field)
561+
562+
switch fv.Kind() {
563+
564+
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
565+
566+
return fv.Int() <= topFieldVal.Int()
567+
568+
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
569+
570+
return fv.Uint() <= topFieldVal.Uint()
571+
572+
case reflect.Float32, reflect.Float64:
573+
574+
return fv.Float() <= topFieldVal.Float()
575+
576+
case reflect.Struct:
577+
578+
if fv.Type() == reflect.TypeOf(time.Time{}) {
579+
580+
if topFieldVal.Type() != reflect.TypeOf(time.Time{}) {
581+
panic("Bad Top Level field type")
582+
}
583+
584+
t := topFieldVal.Interface().(time.Time)
585+
fieldTime := field.(time.Time)
586+
587+
return fieldTime.Before(t) || fieldTime.Equal(t)
588+
}
589+
}
590+
591+
panic(fmt.Sprintf("Bad field type %T", field))
592+
}
593+
594+
func isLtField(val interface{}, field interface{}, param string) bool {
595+
596+
if val == nil {
597+
panic("struct not passed for cross validation")
598+
}
599+
600+
topVal := reflect.ValueOf(val)
601+
602+
if topVal.Kind() == reflect.Ptr && !topVal.IsNil() {
603+
topVal = reflect.ValueOf(topVal.Elem().Interface())
604+
}
605+
606+
var topFieldVal reflect.Value
607+
608+
switch topVal.Kind() {
609+
610+
case reflect.Struct:
611+
612+
if topVal.Type() == reflect.TypeOf(time.Time{}) {
613+
topFieldVal = topVal
614+
break
615+
}
616+
617+
f := topVal.FieldByName(param)
618+
619+
if f.Kind() == reflect.Invalid {
620+
panic(fmt.Sprintf("Field \"%s\" not found in struct", param))
621+
}
622+
623+
topFieldVal = f
624+
625+
default:
626+
627+
topFieldVal = topVal
628+
}
629+
630+
if topFieldVal.Kind() == reflect.Ptr && !topFieldVal.IsNil() {
631+
632+
topFieldVal = reflect.ValueOf(topFieldVal.Elem().Interface())
633+
}
634+
635+
fv := reflect.ValueOf(field)
636+
637+
switch fv.Kind() {
638+
639+
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
640+
641+
return fv.Int() < topFieldVal.Int()
642+
643+
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
644+
645+
return fv.Uint() < topFieldVal.Uint()
646+
647+
case reflect.Float32, reflect.Float64:
648+
649+
return fv.Float() < topFieldVal.Float()
650+
651+
case reflect.Struct:
652+
653+
if fv.Type() == reflect.TypeOf(time.Time{}) {
654+
655+
if topFieldVal.Type() != reflect.TypeOf(time.Time{}) {
656+
panic("Bad Top Level field type")
657+
}
658+
659+
t := topFieldVal.Interface().(time.Time)
660+
fieldTime := field.(time.Time)
661+
662+
return fieldTime.Before(t)
663+
}
664+
}
665+
666+
panic(fmt.Sprintf("Bad field type %T", field))
667+
}
668+
365669
func isLte(val interface{}, field interface{}, param string) bool {
366670

367671
st := reflect.ValueOf(field)
@@ -395,7 +699,7 @@ func isLte(val interface{}, field interface{}, param string) bool {
395699

396700
case reflect.Struct:
397701

398-
if st.Type() == reflect.TypeOf(field) {
702+
if st.Type() == reflect.TypeOf(time.Time{}) {
399703

400704
now := time.Now().UTC()
401705
t := field.(time.Time)
@@ -440,7 +744,7 @@ func isLt(val interface{}, field interface{}, param string) bool {
440744

441745
case reflect.Struct:
442746

443-
if st.Type() == reflect.TypeOf(field) {
747+
if st.Type() == reflect.TypeOf(time.Time{}) {
444748

445749
return field.(time.Time).Before(time.Now().UTC())
446750
}

doc.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,34 @@ Here is a list of the current built in validators:
218218
For time.Time ensures the time value is less than or equal to time.Now.UTC()
219219
(Usage: lte)
220220
221+
gtfield
222+
Only valid for Numbers and time.Time types, this will validate the field value
223+
against another fields value either within a struct or passed in field.
224+
usage examples are for validation of a Start and End date:
225+
Validation on End field using ValidateByStruct Usage(gtfield=Start)
226+
Validating by field ValidateFieldByTagAndValue(start, end, "gtfield")
227+
228+
gtefield
229+
Only valid for Numbers and time.Time types, this will validate the field value
230+
against another fields value either within a struct or passed in field.
231+
usage examples are for validation of a Start and End date:
232+
Validation on End field using ValidateByStruct Usage(gtefield=Start)
233+
Validating by field ValidateFieldByTagAndValue(start, end, "gtefield")
234+
235+
ltfield
236+
Only valid for Numbers and time.Time types, this will validate the field value
237+
against another fields value either within a struct or passed in field.
238+
usage examples are for validation of a Start and End date:
239+
Validation on End field using ValidateByStruct Usage(ltfield=Start)
240+
Validating by field ValidateFieldByTagAndValue(start, end, "ltfield")
241+
242+
ltefield
243+
Only valid for Numbers and time.Time types, this will validate the field value
244+
against another fields value either within a struct or passed in field.
245+
usage examples are for validation of a Start and End date:
246+
Validation on End field using ValidateByStruct Usage(ltefield=Start)
247+
Validating by field ValidateFieldByTagAndValue(start, end, "ltefield")
248+
221249
alpha
222250
This validates that a strings value contains alpha characters only
223251
(Usage: alpha)

0 commit comments

Comments
 (0)