1package validator
2
3import (
4	"fmt"
5	"net"
6	"net/url"
7	"reflect"
8	"strings"
9	"time"
10	"unicode/utf8"
11)
12
13// BakedInAliasValidators is a default mapping of a single validationstag that
14// defines a common or complex set of validation(s) to simplify
15// adding validation to structs. i.e. set key "_ageok" and the tags
16// are "gt=0,lte=130" or key "_preferredname" and tags "omitempty,gt=0,lte=60"
17var bakedInAliasValidators = map[string]string{
18	"iscolor": "hexcolor|rgb|rgba|hsl|hsla",
19}
20
21// BakedInValidators is the default map of ValidationFunc
22// you can add, remove or even replace items to suite your needs,
23// or even disregard and use your own map if so desired.
24var bakedInValidators = map[string]Func{
25	"required":     HasValue,
26	"len":          HasLengthOf,
27	"min":          HasMinOf,
28	"max":          HasMaxOf,
29	"eq":           IsEq,
30	"ne":           IsNe,
31	"lt":           IsLt,
32	"lte":          IsLte,
33	"gt":           IsGt,
34	"gte":          IsGte,
35	"eqfield":      IsEqField,
36	"eqcsfield":    IsEqCrossStructField,
37	"necsfield":    IsNeCrossStructField,
38	"gtcsfield":    IsGtCrossStructField,
39	"gtecsfield":   IsGteCrossStructField,
40	"ltcsfield":    IsLtCrossStructField,
41	"ltecsfield":   IsLteCrossStructField,
42	"nefield":      IsNeField,
43	"gtefield":     IsGteField,
44	"gtfield":      IsGtField,
45	"ltefield":     IsLteField,
46	"ltfield":      IsLtField,
47	"alpha":        IsAlpha,
48	"alphanum":     IsAlphanum,
49	"numeric":      IsNumeric,
50	"number":       IsNumber,
51	"hexadecimal":  IsHexadecimal,
52	"hexcolor":     IsHEXColor,
53	"rgb":          IsRGB,
54	"rgba":         IsRGBA,
55	"hsl":          IsHSL,
56	"hsla":         IsHSLA,
57	"email":        IsEmail,
58	"url":          IsURL,
59	"uri":          IsURI,
60	"base64":       IsBase64,
61	"contains":     Contains,
62	"containsany":  ContainsAny,
63	"containsrune": ContainsRune,
64	"excludes":     Excludes,
65	"excludesall":  ExcludesAll,
66	"excludesrune": ExcludesRune,
67	"isbn":         IsISBN,
68	"isbn10":       IsISBN10,
69	"isbn13":       IsISBN13,
70	"uuid":         IsUUID,
71	"uuid3":        IsUUID3,
72	"uuid4":        IsUUID4,
73	"uuid5":        IsUUID5,
74	"ascii":        IsASCII,
75	"printascii":   IsPrintableASCII,
76	"multibyte":    HasMultiByteCharacter,
77	"datauri":      IsDataURI,
78	"latitude":     IsLatitude,
79	"longitude":    IsLongitude,
80	"ssn":          IsSSN,
81	"ipv4":         IsIPv4,
82	"ipv6":         IsIPv6,
83	"ip":           IsIP,
84	"cidrv4":       IsCIDRv4,
85	"cidrv6":       IsCIDRv6,
86	"cidr":         IsCIDR,
87	"tcp4_addr":    IsTCP4AddrResolvable,
88	"tcp6_addr":    IsTCP6AddrResolvable,
89	"tcp_addr":     IsTCPAddrResolvable,
90	"udp4_addr":    IsUDP4AddrResolvable,
91	"udp6_addr":    IsUDP6AddrResolvable,
92	"udp_addr":     IsUDPAddrResolvable,
93	"ip4_addr":     IsIP4AddrResolvable,
94	"ip6_addr":     IsIP6AddrResolvable,
95	"ip_addr":      IsIPAddrResolvable,
96	"unix_addr":    IsUnixAddrResolvable,
97	"mac":          IsMAC,
98}
99
100// IsMAC is the validation function for validating if the field's value is a valid MAC address.
101// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
102func IsMAC(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
103	_, err := net.ParseMAC(field.String())
104	return err == nil
105}
106
107// IsCIDRv4 is the validation function for validating if the field's value is a valid v4 CIDR address.
108// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
109func IsCIDRv4(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
110
111	ip, _, err := net.ParseCIDR(field.String())
112
113	return err == nil && ip.To4() != nil
114}
115
116// IsCIDRv6 is the validation function for validating if the field's value is a valid v6 CIDR address.
117// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
118func IsCIDRv6(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
119
120	ip, _, err := net.ParseCIDR(field.String())
121
122	return err == nil && ip.To4() == nil
123}
124
125// IsCIDR is the validation function for validating if the field's value is a valid v4 or v6 CIDR address.
126// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
127func IsCIDR(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
128
129	_, _, err := net.ParseCIDR(field.String())
130
131	return err == nil
132}
133
134// IsIPv4 is the validation function for validating if a value is a valid v4 IP address.
135// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
136func IsIPv4(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
137
138	ip := net.ParseIP(field.String())
139
140	return ip != nil && ip.To4() != nil
141}
142
143// IsIPv6 is the validation function for validating if the field's value is a valid v6 IP address.
144// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
145func IsIPv6(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
146	ip := net.ParseIP(field.String())
147
148	return ip != nil && ip.To4() == nil
149}
150
151// IsIP is the validation function for validating if the field's value is a valid v4 or v6 IP address.
152// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
153func IsIP(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
154
155	ip := net.ParseIP(field.String())
156
157	return ip != nil
158}
159
160// IsSSN is the validation function for validating if the field's value is a valid SSN.
161// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
162func IsSSN(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
163
164	if field.Len() != 11 {
165		return false
166	}
167
168	return sSNRegex.MatchString(field.String())
169}
170
171// IsLongitude is the validation function for validating if the field's value is a valid longitude coordinate.
172// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
173func IsLongitude(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
174	return longitudeRegex.MatchString(field.String())
175}
176
177// IsLatitude is the validation function for validating if the field's value is a valid latitude coordinate.
178// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
179func IsLatitude(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
180	return latitudeRegex.MatchString(field.String())
181}
182
183// IsDataURI is the validation function for validating if the field's value is a valid data URI.
184// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
185func IsDataURI(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
186
187	uri := strings.SplitN(field.String(), ",", 2)
188
189	if len(uri) != 2 {
190		return false
191	}
192
193	if !dataURIRegex.MatchString(uri[0]) {
194		return false
195	}
196
197	fld := reflect.ValueOf(uri[1])
198
199	return IsBase64(v, topStruct, currentStructOrField, fld, fld.Type(), fld.Kind(), param)
200}
201
202// HasMultiByteCharacter is the validation function for validating if the field's value has a multi byte character.
203// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
204func HasMultiByteCharacter(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
205
206	if field.Len() == 0 {
207		return true
208	}
209
210	return multibyteRegex.MatchString(field.String())
211}
212
213// IsPrintableASCII is the validation function for validating if the field's value is a valid printable ASCII character.
214// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
215func IsPrintableASCII(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
216	return printableASCIIRegex.MatchString(field.String())
217}
218
219// IsASCII is the validation function for validating if the field's value is a valid ASCII character.
220// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
221func IsASCII(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
222	return aSCIIRegex.MatchString(field.String())
223}
224
225// IsUUID5 is the validation function for validating if the field's value is a valid v5 UUID.
226// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
227func IsUUID5(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
228	return uUID5Regex.MatchString(field.String())
229}
230
231// IsUUID4 is the validation function for validating if the field's value is a valid v4 UUID.
232// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
233func IsUUID4(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
234	return uUID4Regex.MatchString(field.String())
235}
236
237// IsUUID3 is the validation function for validating if the field's value is a valid v3 UUID.
238// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
239func IsUUID3(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
240	return uUID3Regex.MatchString(field.String())
241}
242
243// IsUUID is the validation function for validating if the field's value is a valid UUID of any version.
244// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
245func IsUUID(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
246	return uUIDRegex.MatchString(field.String())
247}
248
249// IsISBN is the validation function for validating if the field's value is a valid v10 or v13 ISBN.
250// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
251func IsISBN(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
252	return IsISBN10(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) || IsISBN13(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param)
253}
254
255// IsISBN13 is the validation function for validating if the field's value is a valid v13 ISBN.
256// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
257func IsISBN13(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
258
259	s := strings.Replace(strings.Replace(field.String(), "-", "", 4), " ", "", 4)
260
261	if !iSBN13Regex.MatchString(s) {
262		return false
263	}
264
265	var checksum int32
266	var i int32
267
268	factor := []int32{1, 3}
269
270	for i = 0; i < 12; i++ {
271		checksum += factor[i%2] * int32(s[i]-'0')
272	}
273
274	return (int32(s[12]-'0'))-((10-(checksum%10))%10) == 0
275}
276
277// IsISBN10 is the validation function for validating if the field's value is a valid v10 ISBN.
278// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
279func IsISBN10(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
280
281	s := strings.Replace(strings.Replace(field.String(), "-", "", 3), " ", "", 3)
282
283	if !iSBN10Regex.MatchString(s) {
284		return false
285	}
286
287	var checksum int32
288	var i int32
289
290	for i = 0; i < 9; i++ {
291		checksum += (i + 1) * int32(s[i]-'0')
292	}
293
294	if s[9] == 'X' {
295		checksum += 10 * 10
296	} else {
297		checksum += 10 * int32(s[9]-'0')
298	}
299
300	return checksum%11 == 0
301}
302
303// ExcludesRune is the validation function for validating that the field's value does not contain the rune specified within the param.
304// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
305func ExcludesRune(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
306	return !ContainsRune(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param)
307}
308
309// ExcludesAll is the validation function for validating that the field's value does not contain any of the characters specified within the param.
310// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
311func ExcludesAll(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
312	return !ContainsAny(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param)
313}
314
315// Excludes is the validation function for validating that the field's value does not contain the text specified within the param.
316// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
317func Excludes(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
318	return !Contains(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param)
319}
320
321// ContainsRune is the validation function for validating that the field's value contains the rune specified within the param.
322// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
323func ContainsRune(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
324	r, _ := utf8.DecodeRuneInString(param)
325
326	return strings.ContainsRune(field.String(), r)
327}
328
329// ContainsAny is the validation function for validating that the field's value contains any of the characters specified within the param.
330// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
331func ContainsAny(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
332	return strings.ContainsAny(field.String(), param)
333}
334
335// Contains is the validation function for validating that the field's value contains the text specified within the param.
336// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
337func Contains(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
338	return strings.Contains(field.String(), param)
339}
340
341// IsNeField is the validation function for validating if the current field's value is not equal to the field specified by the param's value.
342// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
343func IsNeField(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
344
345	currentField, currentKind, ok := v.GetStructFieldOK(currentStructOrField, param)
346
347	if !ok || currentKind != fieldKind {
348		return true
349	}
350
351	switch fieldKind {
352
353	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
354		return field.Int() != currentField.Int()
355
356	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
357		return field.Uint() != currentField.Uint()
358
359	case reflect.Float32, reflect.Float64:
360		return field.Float() != currentField.Float()
361
362	case reflect.Slice, reflect.Map, reflect.Array:
363		return int64(field.Len()) != int64(currentField.Len())
364
365	case reflect.Struct:
366
367		// Not Same underlying type i.e. struct and time
368		if fieldType != currentField.Type() {
369			return true
370		}
371
372		if fieldType == timeType {
373
374			t := currentField.Interface().(time.Time)
375			fieldTime := field.Interface().(time.Time)
376
377			return !fieldTime.Equal(t)
378		}
379
380	}
381
382	// default reflect.String:
383	return field.String() != currentField.String()
384}
385
386// IsNe is the validation function for validating that the field's value does not equal the provided param value.
387// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
388func IsNe(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
389	return !IsEq(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param)
390}
391
392// IsLteCrossStructField is the validation function for validating if the current field's value is less than or equal to the field, within a separate struct, specified by the param's value.
393// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
394func IsLteCrossStructField(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
395
396	topField, topKind, ok := v.GetStructFieldOK(topStruct, param)
397	if !ok || topKind != fieldKind {
398		return false
399	}
400
401	switch fieldKind {
402
403	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
404		return field.Int() <= topField.Int()
405
406	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
407		return field.Uint() <= topField.Uint()
408
409	case reflect.Float32, reflect.Float64:
410		return field.Float() <= topField.Float()
411
412	case reflect.Slice, reflect.Map, reflect.Array:
413		return int64(field.Len()) <= int64(topField.Len())
414
415	case reflect.Struct:
416
417		// Not Same underlying type i.e. struct and time
418		if fieldType != topField.Type() {
419			return false
420		}
421
422		if fieldType == timeType {
423
424			fieldTime := field.Interface().(time.Time)
425			topTime := topField.Interface().(time.Time)
426
427			return fieldTime.Before(topTime) || fieldTime.Equal(topTime)
428		}
429	}
430
431	// default reflect.String:
432	return field.String() <= topField.String()
433}
434
435// IsLtCrossStructField is the validation function for validating if the current field's value is less than the field, within a separate struct, specified by the param's value.
436// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
437func IsLtCrossStructField(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
438
439	topField, topKind, ok := v.GetStructFieldOK(topStruct, param)
440	if !ok || topKind != fieldKind {
441		return false
442	}
443
444	switch fieldKind {
445
446	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
447		return field.Int() < topField.Int()
448
449	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
450		return field.Uint() < topField.Uint()
451
452	case reflect.Float32, reflect.Float64:
453		return field.Float() < topField.Float()
454
455	case reflect.Slice, reflect.Map, reflect.Array:
456		return int64(field.Len()) < int64(topField.Len())
457
458	case reflect.Struct:
459
460		// Not Same underlying type i.e. struct and time
461		if fieldType != topField.Type() {
462			return false
463		}
464
465		if fieldType == timeType {
466
467			fieldTime := field.Interface().(time.Time)
468			topTime := topField.Interface().(time.Time)
469
470			return fieldTime.Before(topTime)
471		}
472	}
473
474	// default reflect.String:
475	return field.String() < topField.String()
476}
477
478// IsGteCrossStructField is the validation function for validating if the current field's value is greater than or equal to the field, within a separate struct, specified by the param's value.
479// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
480func IsGteCrossStructField(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
481
482	topField, topKind, ok := v.GetStructFieldOK(topStruct, param)
483	if !ok || topKind != fieldKind {
484		return false
485	}
486
487	switch fieldKind {
488
489	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
490		return field.Int() >= topField.Int()
491
492	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
493		return field.Uint() >= topField.Uint()
494
495	case reflect.Float32, reflect.Float64:
496		return field.Float() >= topField.Float()
497
498	case reflect.Slice, reflect.Map, reflect.Array:
499		return int64(field.Len()) >= int64(topField.Len())
500
501	case reflect.Struct:
502
503		// Not Same underlying type i.e. struct and time
504		if fieldType != topField.Type() {
505			return false
506		}
507
508		if fieldType == timeType {
509
510			fieldTime := field.Interface().(time.Time)
511			topTime := topField.Interface().(time.Time)
512
513			return fieldTime.After(topTime) || fieldTime.Equal(topTime)
514		}
515	}
516
517	// default reflect.String:
518	return field.String() >= topField.String()
519}
520
521// IsGtCrossStructField is the validation function for validating if the current field's value is greater than the field, within a separate struct, specified by the param's value.
522// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
523func IsGtCrossStructField(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
524
525	topField, topKind, ok := v.GetStructFieldOK(topStruct, param)
526	if !ok || topKind != fieldKind {
527		return false
528	}
529
530	switch fieldKind {
531
532	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
533		return field.Int() > topField.Int()
534
535	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
536		return field.Uint() > topField.Uint()
537
538	case reflect.Float32, reflect.Float64:
539		return field.Float() > topField.Float()
540
541	case reflect.Slice, reflect.Map, reflect.Array:
542		return int64(field.Len()) > int64(topField.Len())
543
544	case reflect.Struct:
545
546		// Not Same underlying type i.e. struct and time
547		if fieldType != topField.Type() {
548			return false
549		}
550
551		if fieldType == timeType {
552
553			fieldTime := field.Interface().(time.Time)
554			topTime := topField.Interface().(time.Time)
555
556			return fieldTime.After(topTime)
557		}
558	}
559
560	// default reflect.String:
561	return field.String() > topField.String()
562}
563
564// IsNeCrossStructField is the validation function for validating that the current field's value is not equal to the field, within a separate struct, specified by the param's value.
565// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
566func IsNeCrossStructField(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
567
568	topField, currentKind, ok := v.GetStructFieldOK(topStruct, param)
569	if !ok || currentKind != fieldKind {
570		return true
571	}
572
573	switch fieldKind {
574
575	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
576		return topField.Int() != field.Int()
577
578	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
579		return topField.Uint() != field.Uint()
580
581	case reflect.Float32, reflect.Float64:
582		return topField.Float() != field.Float()
583
584	case reflect.Slice, reflect.Map, reflect.Array:
585		return int64(topField.Len()) != int64(field.Len())
586
587	case reflect.Struct:
588
589		// Not Same underlying type i.e. struct and time
590		if fieldType != topField.Type() {
591			return true
592		}
593
594		if fieldType == timeType {
595
596			t := field.Interface().(time.Time)
597			fieldTime := topField.Interface().(time.Time)
598
599			return !fieldTime.Equal(t)
600		}
601	}
602
603	// default reflect.String:
604	return topField.String() != field.String()
605}
606
607// IsEqCrossStructField is the validation function for validating that the current field's value is equal to the field, within a separate struct, specified by the param's value.
608// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
609func IsEqCrossStructField(v *Validate, topStruct reflect.Value, current reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
610
611	topField, topKind, ok := v.GetStructFieldOK(topStruct, param)
612	if !ok || topKind != fieldKind {
613		return false
614	}
615
616	switch fieldKind {
617
618	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
619		return topField.Int() == field.Int()
620
621	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
622		return topField.Uint() == field.Uint()
623
624	case reflect.Float32, reflect.Float64:
625		return topField.Float() == field.Float()
626
627	case reflect.Slice, reflect.Map, reflect.Array:
628		return int64(topField.Len()) == int64(field.Len())
629
630	case reflect.Struct:
631
632		// Not Same underlying type i.e. struct and time
633		if fieldType != topField.Type() {
634			return false
635		}
636
637		if fieldType == timeType {
638
639			t := field.Interface().(time.Time)
640			fieldTime := topField.Interface().(time.Time)
641
642			return fieldTime.Equal(t)
643		}
644	}
645
646	// default reflect.String:
647	return topField.String() == field.String()
648}
649
650// IsEqField is the validation function for validating if the current field's value is equal to the field specified by the param's value.
651// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
652func IsEqField(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
653
654	currentField, currentKind, ok := v.GetStructFieldOK(currentStructOrField, param)
655	if !ok || currentKind != fieldKind {
656		return false
657	}
658
659	switch fieldKind {
660
661	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
662		return field.Int() == currentField.Int()
663
664	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
665		return field.Uint() == currentField.Uint()
666
667	case reflect.Float32, reflect.Float64:
668		return field.Float() == currentField.Float()
669
670	case reflect.Slice, reflect.Map, reflect.Array:
671		return int64(field.Len()) == int64(currentField.Len())
672
673	case reflect.Struct:
674
675		// Not Same underlying type i.e. struct and time
676		if fieldType != currentField.Type() {
677			return false
678		}
679
680		if fieldType == timeType {
681
682			t := currentField.Interface().(time.Time)
683			fieldTime := field.Interface().(time.Time)
684
685			return fieldTime.Equal(t)
686		}
687
688	}
689
690	// default reflect.String:
691	return field.String() == currentField.String()
692}
693
694// IsEq is the validation function for validating if the current field's value is equal to the param's value.
695// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
696func IsEq(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
697
698	switch fieldKind {
699
700	case reflect.String:
701		return field.String() == param
702
703	case reflect.Slice, reflect.Map, reflect.Array:
704		p := asInt(param)
705
706		return int64(field.Len()) == p
707
708	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
709		p := asInt(param)
710
711		return field.Int() == p
712
713	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
714		p := asUint(param)
715
716		return field.Uint() == p
717
718	case reflect.Float32, reflect.Float64:
719		p := asFloat(param)
720
721		return field.Float() == p
722	}
723
724	panic(fmt.Sprintf("Bad field type %T", field.Interface()))
725}
726
727// IsBase64 is the validation function for validating if the current field's value is a valid base 64.
728// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
729func IsBase64(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
730	return base64Regex.MatchString(field.String())
731}
732
733// IsURI is the validation function for validating if the current field's value is a valid URI.
734// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
735func IsURI(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
736
737	switch fieldKind {
738
739	case reflect.String:
740
741		s := field.String()
742
743		// checks needed as of Go 1.6 because of change https://github.com/golang/go/commit/617c93ce740c3c3cc28cdd1a0d712be183d0b328#diff-6c2d018290e298803c0c9419d8739885L195
744		// emulate browser and strip the '#' suffix prior to validation. see issue-#237
745		if i := strings.Index(s, "#"); i > -1 {
746			s = s[:i]
747		}
748
749		if s == blank {
750			return false
751		}
752
753		_, err := url.ParseRequestURI(s)
754
755		return err == nil
756	}
757
758	panic(fmt.Sprintf("Bad field type %T", field.Interface()))
759}
760
761// IsURL is the validation function for validating if the current field's value is a valid URL.
762// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
763func IsURL(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
764
765	switch fieldKind {
766
767	case reflect.String:
768
769		var i int
770		s := field.String()
771
772		// checks needed as of Go 1.6 because of change https://github.com/golang/go/commit/617c93ce740c3c3cc28cdd1a0d712be183d0b328#diff-6c2d018290e298803c0c9419d8739885L195
773		// emulate browser and strip the '#' suffix prior to validation. see issue-#237
774		if i = strings.Index(s, "#"); i > -1 {
775			s = s[:i]
776		}
777
778		if s == blank {
779			return false
780		}
781
782		url, err := url.ParseRequestURI(s)
783
784		if err != nil || url.Scheme == blank {
785			return false
786		}
787
788		return err == nil
789	}
790
791	panic(fmt.Sprintf("Bad field type %T", field.Interface()))
792}
793
794// IsEmail is the validation function for validating if the current field's value is a valid email address.
795// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
796func IsEmail(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
797	return emailRegex.MatchString(field.String())
798}
799
800// IsHSLA is the validation function for validating if the current field's value is a valid HSLA color.
801// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
802func IsHSLA(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
803	return hslaRegex.MatchString(field.String())
804}
805
806// IsHSL is the validation function for validating if the current field's value is a valid HSL color.
807// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
808func IsHSL(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
809	return hslRegex.MatchString(field.String())
810}
811
812// IsRGBA is the validation function for validating if the current field's value is a valid RGBA color.
813// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
814func IsRGBA(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
815	return rgbaRegex.MatchString(field.String())
816}
817
818// IsRGB is the validation function for validating if the current field's value is a valid RGB color.
819// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
820func IsRGB(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
821	return rgbRegex.MatchString(field.String())
822}
823
824// IsHEXColor is the validation function for validating if the current field's value is a valid HEX color.
825// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
826func IsHEXColor(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
827	return hexcolorRegex.MatchString(field.String())
828}
829
830// IsHexadecimal is the validation function for validating if the current field's value is a valid hexadecimal.
831// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
832func IsHexadecimal(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
833	return hexadecimalRegex.MatchString(field.String())
834}
835
836// IsNumber is the validation function for validating if the current field's value is a valid number.
837// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
838func IsNumber(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
839	return numberRegex.MatchString(field.String())
840}
841
842// IsNumeric is the validation function for validating if the current field's value is a valid numeric value.
843// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
844func IsNumeric(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
845	return numericRegex.MatchString(field.String())
846}
847
848// IsAlphanum is the validation function for validating if the current field's value is a valid alphanumeric value.
849// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
850func IsAlphanum(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
851	return alphaNumericRegex.MatchString(field.String())
852}
853
854// IsAlpha is the validation function for validating if the current field's value is a valid alpha value.
855// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
856func IsAlpha(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
857	return alphaRegex.MatchString(field.String())
858}
859
860// HasValue is the validation function for validating if the current field's value is not the default static value.
861// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
862func HasValue(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
863
864	switch fieldKind {
865	case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func:
866		return !field.IsNil()
867	default:
868		return field.IsValid() && field.Interface() != reflect.Zero(fieldType).Interface()
869	}
870}
871
872// IsGteField is the validation function for validating if the current field's value is greater than or equal to the field specified by the param's value.
873// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
874func IsGteField(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
875
876	currentField, currentKind, ok := v.GetStructFieldOK(currentStructOrField, param)
877	if !ok || currentKind != fieldKind {
878		return false
879	}
880
881	switch fieldKind {
882
883	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
884
885		return field.Int() >= currentField.Int()
886
887	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
888
889		return field.Uint() >= currentField.Uint()
890
891	case reflect.Float32, reflect.Float64:
892
893		return field.Float() >= currentField.Float()
894
895	case reflect.Struct:
896
897		// Not Same underlying type i.e. struct and time
898		if fieldType != currentField.Type() {
899			return false
900		}
901
902		if fieldType == timeType {
903
904			t := currentField.Interface().(time.Time)
905			fieldTime := field.Interface().(time.Time)
906
907			return fieldTime.After(t) || fieldTime.Equal(t)
908		}
909	}
910
911	// default reflect.String
912	return len(field.String()) >= len(currentField.String())
913}
914
915// IsGtField is the validation function for validating if the current field's value is greater than the field specified by the param's value.
916// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
917func IsGtField(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
918
919	currentField, currentKind, ok := v.GetStructFieldOK(currentStructOrField, param)
920	if !ok || currentKind != fieldKind {
921		return false
922	}
923
924	switch fieldKind {
925
926	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
927
928		return field.Int() > currentField.Int()
929
930	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
931
932		return field.Uint() > currentField.Uint()
933
934	case reflect.Float32, reflect.Float64:
935
936		return field.Float() > currentField.Float()
937
938	case reflect.Struct:
939
940		// Not Same underlying type i.e. struct and time
941		if fieldType != currentField.Type() {
942			return false
943		}
944
945		if fieldType == timeType {
946
947			t := currentField.Interface().(time.Time)
948			fieldTime := field.Interface().(time.Time)
949
950			return fieldTime.After(t)
951		}
952	}
953
954	// default reflect.String
955	return len(field.String()) > len(currentField.String())
956}
957
958// IsGte is the validation function for validating if the current field's value is greater than or equal to the param's value.
959// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
960func IsGte(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
961
962	switch fieldKind {
963
964	case reflect.String:
965		p := asInt(param)
966
967		return int64(utf8.RuneCountInString(field.String())) >= p
968
969	case reflect.Slice, reflect.Map, reflect.Array:
970		p := asInt(param)
971
972		return int64(field.Len()) >= p
973
974	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
975		p := asInt(param)
976
977		return field.Int() >= p
978
979	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
980		p := asUint(param)
981
982		return field.Uint() >= p
983
984	case reflect.Float32, reflect.Float64:
985		p := asFloat(param)
986
987		return field.Float() >= p
988
989	case reflect.Struct:
990
991		if fieldType == timeType || fieldType == timePtrType {
992
993			now := time.Now().UTC()
994			t := field.Interface().(time.Time)
995
996			return t.After(now) || t.Equal(now)
997		}
998	}
999
1000	panic(fmt.Sprintf("Bad field type %T", field.Interface()))
1001}
1002
1003// IsGt is the validation function for validating if the current field's value is greater than the param's value.
1004// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
1005func IsGt(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
1006
1007	switch fieldKind {
1008
1009	case reflect.String:
1010		p := asInt(param)
1011
1012		return int64(utf8.RuneCountInString(field.String())) > p
1013
1014	case reflect.Slice, reflect.Map, reflect.Array:
1015		p := asInt(param)
1016
1017		return int64(field.Len()) > p
1018
1019	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
1020		p := asInt(param)
1021
1022		return field.Int() > p
1023
1024	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
1025		p := asUint(param)
1026
1027		return field.Uint() > p
1028
1029	case reflect.Float32, reflect.Float64:
1030		p := asFloat(param)
1031
1032		return field.Float() > p
1033	case reflect.Struct:
1034
1035		if fieldType == timeType || fieldType == timePtrType {
1036
1037			return field.Interface().(time.Time).After(time.Now().UTC())
1038		}
1039	}
1040
1041	panic(fmt.Sprintf("Bad field type %T", field.Interface()))
1042}
1043
1044// HasLengthOf is the validation function for validating if the current field's value is equal to the param's value.
1045// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
1046func HasLengthOf(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
1047
1048	switch fieldKind {
1049
1050	case reflect.String:
1051		p := asInt(param)
1052
1053		return int64(utf8.RuneCountInString(field.String())) == p
1054
1055	case reflect.Slice, reflect.Map, reflect.Array:
1056		p := asInt(param)
1057
1058		return int64(field.Len()) == p
1059
1060	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
1061		p := asInt(param)
1062
1063		return field.Int() == p
1064
1065	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
1066		p := asUint(param)
1067
1068		return field.Uint() == p
1069
1070	case reflect.Float32, reflect.Float64:
1071		p := asFloat(param)
1072
1073		return field.Float() == p
1074	}
1075
1076	panic(fmt.Sprintf("Bad field type %T", field.Interface()))
1077}
1078
1079// HasMinOf is the validation function for validating if the current field's value is greater than or equal to the param's value.
1080// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
1081func HasMinOf(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
1082
1083	return IsGte(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param)
1084}
1085
1086// IsLteField is the validation function for validating if the current field's value is less than or equal to the field specified by the param's value.
1087// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
1088func IsLteField(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
1089
1090	currentField, currentKind, ok := v.GetStructFieldOK(currentStructOrField, param)
1091	if !ok || currentKind != fieldKind {
1092		return false
1093	}
1094
1095	switch fieldKind {
1096
1097	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
1098
1099		return field.Int() <= currentField.Int()
1100
1101	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
1102
1103		return field.Uint() <= currentField.Uint()
1104
1105	case reflect.Float32, reflect.Float64:
1106
1107		return field.Float() <= currentField.Float()
1108
1109	case reflect.Struct:
1110
1111		// Not Same underlying type i.e. struct and time
1112		if fieldType != currentField.Type() {
1113			return false
1114		}
1115
1116		if fieldType == timeType {
1117
1118			t := currentField.Interface().(time.Time)
1119			fieldTime := field.Interface().(time.Time)
1120
1121			return fieldTime.Before(t) || fieldTime.Equal(t)
1122		}
1123	}
1124
1125	// default reflect.String
1126	return len(field.String()) <= len(currentField.String())
1127}
1128
1129// IsLtField is the validation function for validating if the current field's value is less than the field specified by the param's value.
1130// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
1131func IsLtField(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
1132
1133	currentField, currentKind, ok := v.GetStructFieldOK(currentStructOrField, param)
1134	if !ok || currentKind != fieldKind {
1135		return false
1136	}
1137
1138	switch fieldKind {
1139
1140	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
1141
1142		return field.Int() < currentField.Int()
1143
1144	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
1145
1146		return field.Uint() < currentField.Uint()
1147
1148	case reflect.Float32, reflect.Float64:
1149
1150		return field.Float() < currentField.Float()
1151
1152	case reflect.Struct:
1153
1154		// Not Same underlying type i.e. struct and time
1155		if fieldType != currentField.Type() {
1156			return false
1157		}
1158
1159		if fieldType == timeType {
1160
1161			t := currentField.Interface().(time.Time)
1162			fieldTime := field.Interface().(time.Time)
1163
1164			return fieldTime.Before(t)
1165		}
1166	}
1167
1168	// default reflect.String
1169	return len(field.String()) < len(currentField.String())
1170}
1171
1172// IsLte is the validation function for validating if the current field's value is less than or equal to the param's value.
1173// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
1174func IsLte(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
1175
1176	switch fieldKind {
1177
1178	case reflect.String:
1179		p := asInt(param)
1180
1181		return int64(utf8.RuneCountInString(field.String())) <= p
1182
1183	case reflect.Slice, reflect.Map, reflect.Array:
1184		p := asInt(param)
1185
1186		return int64(field.Len()) <= p
1187
1188	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
1189		p := asInt(param)
1190
1191		return field.Int() <= p
1192
1193	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
1194		p := asUint(param)
1195
1196		return field.Uint() <= p
1197
1198	case reflect.Float32, reflect.Float64:
1199		p := asFloat(param)
1200
1201		return field.Float() <= p
1202
1203	case reflect.Struct:
1204
1205		if fieldType == timeType || fieldType == timePtrType {
1206
1207			now := time.Now().UTC()
1208			t := field.Interface().(time.Time)
1209
1210			return t.Before(now) || t.Equal(now)
1211		}
1212	}
1213
1214	panic(fmt.Sprintf("Bad field type %T", field.Interface()))
1215}
1216
1217// IsLt is the validation function for validating if the current field's value is less than the param's value.
1218// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
1219func IsLt(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
1220
1221	switch fieldKind {
1222
1223	case reflect.String:
1224		p := asInt(param)
1225
1226		return int64(utf8.RuneCountInString(field.String())) < p
1227
1228	case reflect.Slice, reflect.Map, reflect.Array:
1229		p := asInt(param)
1230
1231		return int64(field.Len()) < p
1232
1233	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
1234		p := asInt(param)
1235
1236		return field.Int() < p
1237
1238	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
1239		p := asUint(param)
1240
1241		return field.Uint() < p
1242
1243	case reflect.Float32, reflect.Float64:
1244		p := asFloat(param)
1245
1246		return field.Float() < p
1247
1248	case reflect.Struct:
1249
1250		if fieldType == timeType || fieldType == timePtrType {
1251
1252			return field.Interface().(time.Time).Before(time.Now().UTC())
1253		}
1254	}
1255
1256	panic(fmt.Sprintf("Bad field type %T", field.Interface()))
1257}
1258
1259// HasMaxOf is the validation function for validating if the current field's value is less than or equal to the param's value.
1260// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
1261func HasMaxOf(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
1262	return IsLte(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param)
1263}
1264
1265// IsTCP4AddrResolvable is the validation function for validating if the field's value is a resolvable tcp4 address.
1266// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
1267func IsTCP4AddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
1268
1269	if !isIP4Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) {
1270		return false
1271	}
1272
1273	_, err := net.ResolveTCPAddr("tcp4", field.String())
1274	return err == nil
1275}
1276
1277// IsTCP6AddrResolvable is the validation function for validating if the field's value is a resolvable tcp6 address.
1278// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
1279func IsTCP6AddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
1280
1281	if !isIP6Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) {
1282		return false
1283	}
1284
1285	_, err := net.ResolveTCPAddr("tcp6", field.String())
1286	return err == nil
1287}
1288
1289// IsTCPAddrResolvable is the validation function for validating if the field's value is a resolvable tcp address.
1290// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
1291func IsTCPAddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
1292
1293	if !isIP4Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) &&
1294		!isIP6Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) {
1295		return false
1296	}
1297
1298	_, err := net.ResolveTCPAddr("tcp", field.String())
1299	return err == nil
1300}
1301
1302// IsUDP4AddrResolvable is the validation function for validating if the field's value is a resolvable udp4 address.
1303// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
1304func IsUDP4AddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
1305
1306	if !isIP4Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) {
1307		return false
1308	}
1309
1310	_, err := net.ResolveUDPAddr("udp4", field.String())
1311	return err == nil
1312}
1313
1314// IsUDP6AddrResolvable is the validation function for validating if the field's value is a resolvable udp6 address.
1315// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
1316func IsUDP6AddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
1317
1318	if !isIP6Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) {
1319		return false
1320	}
1321
1322	_, err := net.ResolveUDPAddr("udp6", field.String())
1323	return err == nil
1324}
1325
1326// IsUDPAddrResolvable is the validation function for validating if the field's value is a resolvable udp address.
1327// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
1328func IsUDPAddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
1329
1330	if !isIP4Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) &&
1331		!isIP6Addr(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) {
1332		return false
1333	}
1334
1335	_, err := net.ResolveUDPAddr("udp", field.String())
1336	return err == nil
1337}
1338
1339// IsIP4AddrResolvable is the validation function for validating if the field's value is a resolvable ip4 address.
1340// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
1341func IsIP4AddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
1342
1343	if !IsIPv4(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) {
1344		return false
1345	}
1346
1347	_, err := net.ResolveIPAddr("ip4", field.String())
1348	return err == nil
1349}
1350
1351// IsIP6AddrResolvable is the validation function for validating if the field's value is a resolvable ip6 address.
1352// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
1353func IsIP6AddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
1354
1355	if !IsIPv6(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) {
1356		return false
1357	}
1358
1359	_, err := net.ResolveIPAddr("ip6", field.String())
1360	return err == nil
1361}
1362
1363// IsIPAddrResolvable is the validation function for validating if the field's value is a resolvable ip address.
1364// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
1365func IsIPAddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
1366
1367	if !IsIP(v, topStruct, currentStructOrField, field, fieldType, fieldKind, param) {
1368		return false
1369	}
1370
1371	_, err := net.ResolveIPAddr("ip", field.String())
1372	return err == nil
1373}
1374
1375// IsUnixAddrResolvable is the validation function for validating if the field's value is a resolvable unix address.
1376// NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
1377func IsUnixAddrResolvable(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
1378	_, err := net.ResolveUnixAddr("unix", field.String())
1379	return err == nil
1380}
1381
1382func isIP4Addr(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
1383	val := field.String()
1384
1385	if idx := strings.LastIndex(val, ":"); idx != -1 {
1386		val = val[0:idx]
1387	}
1388
1389	if !IsIPv4(v, topStruct, currentStructOrField, reflect.ValueOf(val), fieldType, fieldKind, param) {
1390		return false
1391	}
1392
1393	return true
1394}
1395
1396func isIP6Addr(v *Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
1397	val := field.String()
1398
1399	if idx := strings.LastIndex(val, ":"); idx != -1 {
1400		if idx != 0 && val[idx-1:idx] == "]" {
1401			val = val[1 : idx-1]
1402		}
1403	}
1404
1405	if !IsIPv6(v, topStruct, currentStructOrField, reflect.ValueOf(val), fieldType, fieldKind, param) {
1406		return false
1407	}
1408
1409	return true
1410}
1411