1
2 package govalidator
3
4 import (
5 "bytes"
6 "crypto/rsa"
7 "crypto/x509"
8 "encoding/base64"
9 "encoding/json"
10 "encoding/pem"
11 "fmt"
12 "io/ioutil"
13 "net"
14 "net/url"
15 "reflect"
16 "regexp"
17 "sort"
18 "strconv"
19 "strings"
20 "time"
21 "unicode"
22 "unicode/utf8"
23 )
24
25 var (
26 fieldsRequiredByDefault bool
27 nilPtrAllowedByRequired = false
28 notNumberRegexp = regexp.MustCompile("[^0-9]+")
29 whiteSpacesAndMinus = regexp.MustCompile(`[\s-]+`)
30 paramsRegexp = regexp.MustCompile(`\(.*\)$`)
31 )
32
33 const maxURLRuneCount = 2083
34 const minURLRuneCount = 3
35 const rfc3339WithoutZone = "2006-01-02T15:04:05"
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 func SetFieldsRequiredByDefault(value bool) {
52 fieldsRequiredByDefault = value
53 }
54
55
56
57
58
59
60
61
62 func SetNilPtrAllowedByRequired(value bool) {
63 nilPtrAllowedByRequired = value
64 }
65
66
67 func IsEmail(str string) bool {
68
69 return rxEmail.MatchString(str)
70 }
71
72
73 func IsExistingEmail(email string) bool {
74
75 if len(email) < 6 || len(email) > 254 {
76 return false
77 }
78 at := strings.LastIndex(email, "@")
79 if at <= 0 || at > len(email)-3 {
80 return false
81 }
82 user := email[:at]
83 host := email[at+1:]
84 if len(user) > 64 {
85 return false
86 }
87 switch host {
88 case "localhost", "example.com":
89 return true
90 }
91 if userDotRegexp.MatchString(user) || !userRegexp.MatchString(user) || !hostRegexp.MatchString(host) {
92 return false
93 }
94 if _, err := net.LookupMX(host); err != nil {
95 if _, err := net.LookupIP(host); err != nil {
96 return false
97 }
98 }
99
100 return true
101 }
102
103
104 func IsURL(str string) bool {
105 if str == "" || utf8.RuneCountInString(str) >= maxURLRuneCount || len(str) <= minURLRuneCount || strings.HasPrefix(str, ".") {
106 return false
107 }
108 strTemp := str
109 if strings.Contains(str, ":") && !strings.Contains(str, "://") {
110
111
112 strTemp = "http://" + str
113 }
114 u, err := url.Parse(strTemp)
115 if err != nil {
116 return false
117 }
118 if strings.HasPrefix(u.Host, ".") {
119 return false
120 }
121 if u.Host == "" && (u.Path != "" && !strings.Contains(u.Path, ".")) {
122 return false
123 }
124 return rxURL.MatchString(str)
125 }
126
127
128
129
130 func IsRequestURL(rawurl string) bool {
131 url, err := url.ParseRequestURI(rawurl)
132 if err != nil {
133 return false
134 }
135 if len(url.Scheme) == 0 {
136 return false
137 }
138 return true
139 }
140
141
142
143
144 func IsRequestURI(rawurl string) bool {
145 _, err := url.ParseRequestURI(rawurl)
146 return err == nil
147 }
148
149
150 func IsAlpha(str string) bool {
151 if IsNull(str) {
152 return true
153 }
154 return rxAlpha.MatchString(str)
155 }
156
157
158
159 func IsUTFLetter(str string) bool {
160 if IsNull(str) {
161 return true
162 }
163
164 for _, c := range str {
165 if !unicode.IsLetter(c) {
166 return false
167 }
168 }
169 return true
170
171 }
172
173
174 func IsAlphanumeric(str string) bool {
175 if IsNull(str) {
176 return true
177 }
178 return rxAlphanumeric.MatchString(str)
179 }
180
181
182 func IsUTFLetterNumeric(str string) bool {
183 if IsNull(str) {
184 return true
185 }
186 for _, c := range str {
187 if !unicode.IsLetter(c) && !unicode.IsNumber(c) {
188 return false
189 }
190 }
191 return true
192
193 }
194
195
196 func IsNumeric(str string) bool {
197 if IsNull(str) {
198 return true
199 }
200 return rxNumeric.MatchString(str)
201 }
202
203
204
205 func IsUTFNumeric(str string) bool {
206 if IsNull(str) {
207 return true
208 }
209 if strings.IndexAny(str, "+-") > 0 {
210 return false
211 }
212 if len(str) > 1 {
213 str = strings.TrimPrefix(str, "-")
214 str = strings.TrimPrefix(str, "+")
215 }
216 for _, c := range str {
217 if !unicode.IsNumber(c) {
218 return false
219 }
220 }
221 return true
222
223 }
224
225
226 func IsUTFDigit(str string) bool {
227 if IsNull(str) {
228 return true
229 }
230 if strings.IndexAny(str, "+-") > 0 {
231 return false
232 }
233 if len(str) > 1 {
234 str = strings.TrimPrefix(str, "-")
235 str = strings.TrimPrefix(str, "+")
236 }
237 for _, c := range str {
238 if !unicode.IsDigit(c) {
239 return false
240 }
241 }
242 return true
243
244 }
245
246
247 func IsHexadecimal(str string) bool {
248 return rxHexadecimal.MatchString(str)
249 }
250
251
252 func IsHexcolor(str string) bool {
253 return rxHexcolor.MatchString(str)
254 }
255
256
257 func IsRGBcolor(str string) bool {
258 return rxRGBcolor.MatchString(str)
259 }
260
261
262 func IsLowerCase(str string) bool {
263 if IsNull(str) {
264 return true
265 }
266 return str == strings.ToLower(str)
267 }
268
269
270 func IsUpperCase(str string) bool {
271 if IsNull(str) {
272 return true
273 }
274 return str == strings.ToUpper(str)
275 }
276
277
278 func HasLowerCase(str string) bool {
279 if IsNull(str) {
280 return true
281 }
282 return rxHasLowerCase.MatchString(str)
283 }
284
285
286 func HasUpperCase(str string) bool {
287 if IsNull(str) {
288 return true
289 }
290 return rxHasUpperCase.MatchString(str)
291 }
292
293
294 func IsInt(str string) bool {
295 if IsNull(str) {
296 return true
297 }
298 return rxInt.MatchString(str)
299 }
300
301
302 func IsFloat(str string) bool {
303 return str != "" && rxFloat.MatchString(str)
304 }
305
306
307
308
309 func IsDivisibleBy(str, num string) bool {
310 f, _ := ToFloat(str)
311 p := int64(f)
312 q, _ := ToInt(num)
313 if q == 0 {
314 return false
315 }
316 return (p == 0) || (p%q == 0)
317 }
318
319
320 func IsNull(str string) bool {
321 return len(str) == 0
322 }
323
324
325 func IsNotNull(str string) bool {
326 return !IsNull(str)
327 }
328
329
330 func HasWhitespaceOnly(str string) bool {
331 return len(str) > 0 && rxHasWhitespaceOnly.MatchString(str)
332 }
333
334
335 func HasWhitespace(str string) bool {
336 return len(str) > 0 && rxHasWhitespace.MatchString(str)
337 }
338
339
340 func IsByteLength(str string, min, max int) bool {
341 return len(str) >= min && len(str) <= max
342 }
343
344
345 func IsUUIDv3(str string) bool {
346 return rxUUID3.MatchString(str)
347 }
348
349
350 func IsUUIDv4(str string) bool {
351 return rxUUID4.MatchString(str)
352 }
353
354
355 func IsUUIDv5(str string) bool {
356 return rxUUID5.MatchString(str)
357 }
358
359
360 func IsUUID(str string) bool {
361 return rxUUID.MatchString(str)
362 }
363
364
365
366 var ulidDec = [...]byte{
367 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
368 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
369 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
370 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
371 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01,
372 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xFF, 0xFF,
373 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
374 0x0F, 0x10, 0x11, 0xFF, 0x12, 0x13, 0xFF, 0x14, 0x15, 0xFF,
375 0x16, 0x17, 0x18, 0x19, 0x1A, 0xFF, 0x1B, 0x1C, 0x1D, 0x1E,
376 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x0B, 0x0C,
377 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0xFF, 0x12, 0x13, 0xFF, 0x14,
378 0x15, 0xFF, 0x16, 0x17, 0x18, 0x19, 0x1A, 0xFF, 0x1B, 0x1C,
379 0x1D, 0x1E, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
380 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
381 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
382 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
383 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
384 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
385 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
386 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
387 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
388 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
389 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
390 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
391 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
392 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
393 }
394
395
396 const ulidEncodedSize = 26
397
398
399
400
401
402
403 func IsULID(str string) bool {
404
405 if len(str) != ulidEncodedSize {
406 return false
407 }
408
409
410
411 if ulidDec[str[0]] == 0xFF ||
412 ulidDec[str[1]] == 0xFF ||
413 ulidDec[str[2]] == 0xFF ||
414 ulidDec[str[3]] == 0xFF ||
415 ulidDec[str[4]] == 0xFF ||
416 ulidDec[str[5]] == 0xFF ||
417 ulidDec[str[6]] == 0xFF ||
418 ulidDec[str[7]] == 0xFF ||
419 ulidDec[str[8]] == 0xFF ||
420 ulidDec[str[9]] == 0xFF ||
421 ulidDec[str[10]] == 0xFF ||
422 ulidDec[str[11]] == 0xFF ||
423 ulidDec[str[12]] == 0xFF ||
424 ulidDec[str[13]] == 0xFF ||
425 ulidDec[str[14]] == 0xFF ||
426 ulidDec[str[15]] == 0xFF ||
427 ulidDec[str[16]] == 0xFF ||
428 ulidDec[str[17]] == 0xFF ||
429 ulidDec[str[18]] == 0xFF ||
430 ulidDec[str[19]] == 0xFF ||
431 ulidDec[str[20]] == 0xFF ||
432 ulidDec[str[21]] == 0xFF ||
433 ulidDec[str[22]] == 0xFF ||
434 ulidDec[str[23]] == 0xFF ||
435 ulidDec[str[24]] == 0xFF ||
436 ulidDec[str[25]] == 0xFF {
437 return false
438 }
439
440
441
442
443
444
445 if str[0] > '7' {
446 return false
447 }
448 return true
449 }
450
451
452 func IsCreditCard(str string) bool {
453 sanitized := whiteSpacesAndMinus.ReplaceAllString(str, "")
454 if !rxCreditCard.MatchString(sanitized) {
455 return false
456 }
457
458 number, _ := ToInt(sanitized)
459 number, lastDigit := number / 10, number % 10
460
461 var sum int64
462 for i:=0; number > 0; i++ {
463 digit := number % 10
464
465 if i % 2 == 0 {
466 digit *= 2
467 if digit > 9 {
468 digit -= 9
469 }
470 }
471
472 sum += digit
473 number = number / 10
474 }
475
476 return (sum + lastDigit) % 10 == 0
477 }
478
479
480 func IsISBN10(str string) bool {
481 return IsISBN(str, 10)
482 }
483
484
485 func IsISBN13(str string) bool {
486 return IsISBN(str, 13)
487 }
488
489
490
491 func IsISBN(str string, version int) bool {
492 sanitized := whiteSpacesAndMinus.ReplaceAllString(str, "")
493 var checksum int32
494 var i int32
495 if version == 10 {
496 if !rxISBN10.MatchString(sanitized) {
497 return false
498 }
499 for i = 0; i < 9; i++ {
500 checksum += (i + 1) * int32(sanitized[i]-'0')
501 }
502 if sanitized[9] == 'X' {
503 checksum += 10 * 10
504 } else {
505 checksum += 10 * int32(sanitized[9]-'0')
506 }
507 if checksum%11 == 0 {
508 return true
509 }
510 return false
511 } else if version == 13 {
512 if !rxISBN13.MatchString(sanitized) {
513 return false
514 }
515 factor := []int32{1, 3}
516 for i = 0; i < 12; i++ {
517 checksum += factor[i%2] * int32(sanitized[i]-'0')
518 }
519 return (int32(sanitized[12]-'0'))-((10-(checksum%10))%10) == 0
520 }
521 return IsISBN(str, 10) || IsISBN(str, 13)
522 }
523
524
525 func IsJSON(str string) bool {
526 var js json.RawMessage
527 return json.Unmarshal([]byte(str), &js) == nil
528 }
529
530
531 func IsMultibyte(str string) bool {
532 if IsNull(str) {
533 return true
534 }
535 return rxMultibyte.MatchString(str)
536 }
537
538
539 func IsASCII(str string) bool {
540 if IsNull(str) {
541 return true
542 }
543 return rxASCII.MatchString(str)
544 }
545
546
547 func IsPrintableASCII(str string) bool {
548 if IsNull(str) {
549 return true
550 }
551 return rxPrintableASCII.MatchString(str)
552 }
553
554
555 func IsFullWidth(str string) bool {
556 if IsNull(str) {
557 return true
558 }
559 return rxFullWidth.MatchString(str)
560 }
561
562
563 func IsHalfWidth(str string) bool {
564 if IsNull(str) {
565 return true
566 }
567 return rxHalfWidth.MatchString(str)
568 }
569
570
571 func IsVariableWidth(str string) bool {
572 if IsNull(str) {
573 return true
574 }
575 return rxHalfWidth.MatchString(str) && rxFullWidth.MatchString(str)
576 }
577
578
579 func IsBase64(str string) bool {
580 return rxBase64.MatchString(str)
581 }
582
583
584 func IsFilePath(str string) (bool, int) {
585 if rxWinPath.MatchString(str) {
586
587
588 if len(str[3:]) > 32767 {
589 return false, Win
590 }
591 return true, Win
592 } else if rxUnixPath.MatchString(str) {
593 return true, Unix
594 }
595 return false, Unknown
596 }
597
598
599 func IsWinFilePath(str string) bool {
600 if rxARWinPath.MatchString(str) {
601
602
603 if len(str[3:]) > 32767 {
604 return false
605 }
606 return true
607 }
608 return false
609 }
610
611
612 func IsUnixFilePath(str string) bool {
613 if rxARUnixPath.MatchString(str) {
614 return true
615 }
616 return false
617 }
618
619
620 func IsDataURI(str string) bool {
621 dataURI := strings.Split(str, ",")
622 if !rxDataURI.MatchString(dataURI[0]) {
623 return false
624 }
625 return IsBase64(dataURI[1])
626 }
627
628
629 func IsMagnetURI(str string) bool {
630 return rxMagnetURI.MatchString(str)
631 }
632
633
634 func IsISO3166Alpha2(str string) bool {
635 for _, entry := range ISO3166List {
636 if str == entry.Alpha2Code {
637 return true
638 }
639 }
640 return false
641 }
642
643
644 func IsISO3166Alpha3(str string) bool {
645 for _, entry := range ISO3166List {
646 if str == entry.Alpha3Code {
647 return true
648 }
649 }
650 return false
651 }
652
653
654 func IsISO693Alpha2(str string) bool {
655 for _, entry := range ISO693List {
656 if str == entry.Alpha2Code {
657 return true
658 }
659 }
660 return false
661 }
662
663
664 func IsISO693Alpha3b(str string) bool {
665 for _, entry := range ISO693List {
666 if str == entry.Alpha3bCode {
667 return true
668 }
669 }
670 return false
671 }
672
673
674 func IsDNSName(str string) bool {
675 if str == "" || len(strings.Replace(str, ".", "", -1)) > 255 {
676
677 return false
678 }
679 return !IsIP(str) && rxDNSName.MatchString(str)
680 }
681
682
683
684 func IsHash(str string, algorithm string) bool {
685 var len string
686 algo := strings.ToLower(algorithm)
687
688 if algo == "crc32" || algo == "crc32b" {
689 len = "8"
690 } else if algo == "md5" || algo == "md4" || algo == "ripemd128" || algo == "tiger128" {
691 len = "32"
692 } else if algo == "sha1" || algo == "ripemd160" || algo == "tiger160" {
693 len = "40"
694 } else if algo == "tiger192" {
695 len = "48"
696 } else if algo == "sha3-224" {
697 len = "56"
698 } else if algo == "sha256" || algo == "sha3-256" {
699 len = "64"
700 } else if algo == "sha384" || algo == "sha3-384" {
701 len = "96"
702 } else if algo == "sha512" || algo == "sha3-512" {
703 len = "128"
704 } else {
705 return false
706 }
707
708 return Matches(str, "^[a-f0-9]{"+len+"}$")
709 }
710
711
712 func IsSHA3224(str string) bool {
713 return IsHash(str, "sha3-224")
714 }
715
716
717 func IsSHA3256(str string) bool {
718 return IsHash(str, "sha3-256")
719 }
720
721
722 func IsSHA3384(str string) bool {
723 return IsHash(str, "sha3-384")
724 }
725
726
727 func IsSHA3512(str string) bool {
728 return IsHash(str, "sha3-512")
729 }
730
731
732 func IsSHA512(str string) bool {
733 return IsHash(str, "sha512")
734 }
735
736
737 func IsSHA384(str string) bool {
738 return IsHash(str, "sha384")
739 }
740
741
742 func IsSHA256(str string) bool {
743 return IsHash(str, "sha256")
744 }
745
746
747 func IsTiger192(str string) bool {
748 return IsHash(str, "tiger192")
749 }
750
751
752 func IsTiger160(str string) bool {
753 return IsHash(str, "tiger160")
754 }
755
756
757 func IsRipeMD160(str string) bool {
758 return IsHash(str, "ripemd160")
759 }
760
761
762 func IsSHA1(str string) bool {
763 return IsHash(str, "sha1")
764 }
765
766
767 func IsTiger128(str string) bool {
768 return IsHash(str, "tiger128")
769 }
770
771
772 func IsRipeMD128(str string) bool {
773 return IsHash(str, "ripemd128")
774 }
775
776
777 func IsCRC32(str string) bool {
778 return IsHash(str, "crc32")
779 }
780
781
782 func IsCRC32b(str string) bool {
783 return IsHash(str, "crc32b")
784 }
785
786
787 func IsMD5(str string) bool {
788 return IsHash(str, "md5")
789 }
790
791
792 func IsMD4(str string) bool {
793 return IsHash(str, "md4")
794 }
795
796
797 func IsDialString(str string) bool {
798 if h, p, err := net.SplitHostPort(str); err == nil && h != "" && p != "" && (IsDNSName(h) || IsIP(h)) && IsPort(p) {
799 return true
800 }
801
802 return false
803 }
804
805
806 func IsIP(str string) bool {
807 return net.ParseIP(str) != nil
808 }
809
810
811 func IsPort(str string) bool {
812 if i, err := strconv.Atoi(str); err == nil && i > 0 && i < 65536 {
813 return true
814 }
815 return false
816 }
817
818
819 func IsIPv4(str string) bool {
820 ip := net.ParseIP(str)
821 return ip != nil && strings.Contains(str, ".")
822 }
823
824
825 func IsIPv6(str string) bool {
826 ip := net.ParseIP(str)
827 return ip != nil && strings.Contains(str, ":")
828 }
829
830
831 func IsCIDR(str string) bool {
832 _, _, err := net.ParseCIDR(str)
833 return err == nil
834 }
835
836
837
838
839
840
841
842
843
844 func IsMAC(str string) bool {
845 _, err := net.ParseMAC(str)
846 return err == nil
847 }
848
849
850 func IsHost(str string) bool {
851 return IsIP(str) || IsDNSName(str)
852 }
853
854
855 func IsMongoID(str string) bool {
856 return rxHexadecimal.MatchString(str) && (len(str) == 24)
857 }
858
859
860 func IsLatitude(str string) bool {
861 return rxLatitude.MatchString(str)
862 }
863
864
865 func IsLongitude(str string) bool {
866 return rxLongitude.MatchString(str)
867 }
868
869
870 func IsIMEI(str string) bool {
871 return rxIMEI.MatchString(str)
872 }
873
874
875 func IsIMSI(str string) bool {
876 if !rxIMSI.MatchString(str) {
877 return false
878 }
879
880 mcc, err := strconv.ParseInt(str[0:3], 10, 32)
881 if err != nil {
882 return false
883 }
884
885 switch mcc {
886 case 202, 204, 206, 208, 212, 213, 214, 216, 218, 219:
887 case 220, 221, 222, 226, 228, 230, 231, 232, 234, 235:
888 case 238, 240, 242, 244, 246, 247, 248, 250, 255, 257:
889 case 259, 260, 262, 266, 268, 270, 272, 274, 276, 278:
890 case 280, 282, 283, 284, 286, 288, 289, 290, 292, 293:
891 case 294, 295, 297, 302, 308, 310, 311, 312, 313, 314:
892 case 315, 316, 330, 332, 334, 338, 340, 342, 344, 346:
893 case 348, 350, 352, 354, 356, 358, 360, 362, 363, 364:
894 case 365, 366, 368, 370, 372, 374, 376, 400, 401, 402:
895 case 404, 405, 406, 410, 412, 413, 414, 415, 416, 417:
896 case 418, 419, 420, 421, 422, 424, 425, 426, 427, 428:
897 case 429, 430, 431, 432, 434, 436, 437, 438, 440, 441:
898 case 450, 452, 454, 455, 456, 457, 460, 461, 466, 467:
899 case 470, 472, 502, 505, 510, 514, 515, 520, 525, 528:
900 case 530, 536, 537, 539, 540, 541, 542, 543, 544, 545:
901 case 546, 547, 548, 549, 550, 551, 552, 553, 554, 555:
902 case 602, 603, 604, 605, 606, 607, 608, 609, 610, 611:
903 case 612, 613, 614, 615, 616, 617, 618, 619, 620, 621:
904 case 622, 623, 624, 625, 626, 627, 628, 629, 630, 631:
905 case 632, 633, 634, 635, 636, 637, 638, 639, 640, 641:
906 case 642, 643, 645, 646, 647, 648, 649, 650, 651, 652:
907 case 653, 654, 655, 657, 658, 659, 702, 704, 706, 708:
908 case 710, 712, 714, 716, 722, 724, 730, 732, 734, 736:
909 case 738, 740, 742, 744, 746, 748, 750, 995:
910 return true
911 default:
912 return false
913 }
914 return true
915 }
916
917
918 func IsRsaPublicKey(str string, keylen int) bool {
919 bb := bytes.NewBufferString(str)
920 pemBytes, err := ioutil.ReadAll(bb)
921 if err != nil {
922 return false
923 }
924 block, _ := pem.Decode(pemBytes)
925 if block != nil && block.Type != "PUBLIC KEY" {
926 return false
927 }
928 var der []byte
929
930 if block != nil {
931 der = block.Bytes
932 } else {
933 der, err = base64.StdEncoding.DecodeString(str)
934 if err != nil {
935 return false
936 }
937 }
938
939 key, err := x509.ParsePKIXPublicKey(der)
940 if err != nil {
941 return false
942 }
943 pubkey, ok := key.(*rsa.PublicKey)
944 if !ok {
945 return false
946 }
947 bitlen := len(pubkey.N.Bytes()) * 8
948 return bitlen == int(keylen)
949 }
950
951
952 func IsRegex(str string) bool {
953 if _, err := regexp.Compile(str); err == nil {
954 return true
955 }
956 return false
957 }
958
959 func toJSONName(tag string) string {
960 if tag == "" {
961 return ""
962 }
963
964
965
966 split := strings.SplitN(tag, ",", 2)
967
968 name := split[0]
969
970
971
972
973 if name == "-" {
974 return ""
975 }
976 return name
977 }
978
979 func prependPathToErrors(err error, path string) error {
980 switch err2 := err.(type) {
981 case Error:
982 err2.Path = append([]string{path}, err2.Path...)
983 return err2
984 case Errors:
985 errors := err2.Errors()
986 for i, err3 := range errors {
987 errors[i] = prependPathToErrors(err3, path)
988 }
989 return err2
990 }
991 return err
992 }
993
994
995 func ValidateArray(array []interface{}, iterator ConditionIterator) bool {
996 return Every(array, iterator)
997 }
998
999
1000
1001
1002
1003
1004 func ValidateMap(s map[string]interface{}, m map[string]interface{}) (bool, error) {
1005 if s == nil {
1006 return true, nil
1007 }
1008 result := true
1009 var err error
1010 var errs Errors
1011 var index int
1012 val := reflect.ValueOf(s)
1013 for key, value := range s {
1014 presentResult := true
1015 validator, ok := m[key]
1016 if !ok {
1017 presentResult = false
1018 var err error
1019 err = fmt.Errorf("all map keys has to be present in the validation map; got %s", key)
1020 err = prependPathToErrors(err, key)
1021 errs = append(errs, err)
1022 }
1023 valueField := reflect.ValueOf(value)
1024 mapResult := true
1025 typeResult := true
1026 structResult := true
1027 resultField := true
1028 switch subValidator := validator.(type) {
1029 case map[string]interface{}:
1030 var err error
1031 if v, ok := value.(map[string]interface{}); !ok {
1032 mapResult = false
1033 err = fmt.Errorf("map validator has to be for the map type only; got %s", valueField.Type().String())
1034 err = prependPathToErrors(err, key)
1035 errs = append(errs, err)
1036 } else {
1037 mapResult, err = ValidateMap(v, subValidator)
1038 if err != nil {
1039 mapResult = false
1040 err = prependPathToErrors(err, key)
1041 errs = append(errs, err)
1042 }
1043 }
1044 case string:
1045 if (valueField.Kind() == reflect.Struct ||
1046 (valueField.Kind() == reflect.Ptr && valueField.Elem().Kind() == reflect.Struct)) &&
1047 subValidator != "-" {
1048 var err error
1049 structResult, err = ValidateStruct(valueField.Interface())
1050 if err != nil {
1051 err = prependPathToErrors(err, key)
1052 errs = append(errs, err)
1053 }
1054 }
1055 resultField, err = typeCheck(valueField, reflect.StructField{
1056 Name: key,
1057 PkgPath: "",
1058 Type: val.Type(),
1059 Tag: reflect.StructTag(fmt.Sprintf("%s:%q", tagName, subValidator)),
1060 Offset: 0,
1061 Index: []int{index},
1062 Anonymous: false,
1063 }, val, nil)
1064 if err != nil {
1065 errs = append(errs, err)
1066 }
1067 case nil:
1068
1069 default:
1070 typeResult = false
1071 err = fmt.Errorf("map validator has to be either map[string]interface{} or string; got %s", valueField.Type().String())
1072 err = prependPathToErrors(err, key)
1073 errs = append(errs, err)
1074 }
1075 result = result && presentResult && typeResult && resultField && structResult && mapResult
1076 index++
1077 }
1078
1079 requiredResult := true
1080 for key, value := range m {
1081 if schema, ok := value.(string); ok {
1082 tags := parseTagIntoMap(schema)
1083 if required, ok := tags["required"]; ok {
1084 if _, ok := s[key]; !ok {
1085 requiredResult = false
1086 if required.customErrorMessage != "" {
1087 err = Error{key, fmt.Errorf(required.customErrorMessage), true, "required", []string{}}
1088 } else {
1089 err = Error{key, fmt.Errorf("required field missing"), false, "required", []string{}}
1090 }
1091 errs = append(errs, err)
1092 }
1093 }
1094 }
1095 }
1096
1097 if len(errs) > 0 {
1098 err = errs
1099 }
1100 return result && requiredResult, err
1101 }
1102
1103
1104
1105
1106 func ValidateStruct(s interface{}) (bool, error) {
1107 if s == nil {
1108 return true, nil
1109 }
1110 result := true
1111 var err error
1112 val := reflect.ValueOf(s)
1113 if val.Kind() == reflect.Interface || val.Kind() == reflect.Ptr {
1114 val = val.Elem()
1115 }
1116
1117 if val.Kind() != reflect.Struct {
1118 return false, fmt.Errorf("function only accepts structs; got %s", val.Kind())
1119 }
1120 var errs Errors
1121 for i := 0; i < val.NumField(); i++ {
1122 valueField := val.Field(i)
1123 typeField := val.Type().Field(i)
1124 if typeField.PkgPath != "" {
1125 continue
1126 }
1127 structResult := true
1128 if valueField.Kind() == reflect.Interface {
1129 valueField = valueField.Elem()
1130 }
1131 if (valueField.Kind() == reflect.Struct ||
1132 (valueField.Kind() == reflect.Ptr && valueField.Elem().Kind() == reflect.Struct)) &&
1133 typeField.Tag.Get(tagName) != "-" {
1134 var err error
1135 structResult, err = ValidateStruct(valueField.Interface())
1136 if err != nil {
1137 err = prependPathToErrors(err, typeField.Name)
1138 errs = append(errs, err)
1139 }
1140 }
1141 resultField, err2 := typeCheck(valueField, typeField, val, nil)
1142 if err2 != nil {
1143
1144
1145 jsonTag := toJSONName(typeField.Tag.Get("json"))
1146 if jsonTag != "" {
1147 switch jsonError := err2.(type) {
1148 case Error:
1149 jsonError.Name = jsonTag
1150 err2 = jsonError
1151 case Errors:
1152 for i2, err3 := range jsonError {
1153 switch customErr := err3.(type) {
1154 case Error:
1155 customErr.Name = jsonTag
1156 jsonError[i2] = customErr
1157 }
1158 }
1159
1160 err2 = jsonError
1161 }
1162 }
1163
1164 errs = append(errs, err2)
1165 }
1166 result = result && resultField && structResult
1167 }
1168 if len(errs) > 0 {
1169 err = errs
1170 }
1171 return result, err
1172 }
1173
1174
1175 func ValidateStructAsync(s interface{}) (<-chan bool, <-chan error) {
1176 res := make(chan bool)
1177 errors := make(chan error)
1178
1179 go func() {
1180 defer close(res)
1181 defer close(errors)
1182
1183 isValid, isFailed := ValidateStruct(s)
1184
1185 res <- isValid
1186 errors <- isFailed
1187 }()
1188
1189 return res, errors
1190 }
1191
1192
1193 func ValidateMapAsync(s map[string]interface{}, m map[string]interface{}) (<-chan bool, <-chan error) {
1194 res := make(chan bool)
1195 errors := make(chan error)
1196
1197 go func() {
1198 defer close(res)
1199 defer close(errors)
1200
1201 isValid, isFailed := ValidateMap(s, m)
1202
1203 res <- isValid
1204 errors <- isFailed
1205 }()
1206
1207 return res, errors
1208 }
1209
1210
1211 func parseTagIntoMap(tag string) tagOptionsMap {
1212 optionsMap := make(tagOptionsMap)
1213 options := strings.Split(tag, ",")
1214
1215 for i, option := range options {
1216 option = strings.TrimSpace(option)
1217
1218 validationOptions := strings.Split(option, "~")
1219 if !isValidTag(validationOptions[0]) {
1220 continue
1221 }
1222 if len(validationOptions) == 2 {
1223 optionsMap[validationOptions[0]] = tagOption{validationOptions[0], validationOptions[1], i}
1224 } else {
1225 optionsMap[validationOptions[0]] = tagOption{validationOptions[0], "", i}
1226 }
1227 }
1228 return optionsMap
1229 }
1230
1231 func isValidTag(s string) bool {
1232 if s == "" {
1233 return false
1234 }
1235 for _, c := range s {
1236 switch {
1237 case strings.ContainsRune("\\'\"!#$%&()*+-./:<=>?@[]^_{|}~ ", c):
1238
1239
1240
1241 default:
1242 if !unicode.IsLetter(c) && !unicode.IsDigit(c) {
1243 return false
1244 }
1245 }
1246 }
1247 return true
1248 }
1249
1250
1251 func IsSSN(str string) bool {
1252 if str == "" || len(str) != 11 {
1253 return false
1254 }
1255 return rxSSN.MatchString(str)
1256 }
1257
1258
1259 func IsSemver(str string) bool {
1260 return rxSemver.MatchString(str)
1261 }
1262
1263
1264 func IsType(v interface{}, params ...string) bool {
1265 if len(params) == 1 {
1266 typ := params[0]
1267 return strings.Replace(reflect.TypeOf(v).String(), " ", "", -1) == strings.Replace(typ, " ", "", -1)
1268 }
1269 return false
1270 }
1271
1272
1273 func IsTime(str string, format string) bool {
1274 _, err := time.Parse(format, str)
1275 return err == nil
1276 }
1277
1278
1279 func IsUnixTime(str string) bool {
1280 if _, err := strconv.Atoi(str); err == nil {
1281 return true
1282 }
1283 return false
1284 }
1285
1286
1287 func IsRFC3339(str string) bool {
1288 return IsTime(str, time.RFC3339)
1289 }
1290
1291
1292 func IsRFC3339WithoutZone(str string) bool {
1293 return IsTime(str, rfc3339WithoutZone)
1294 }
1295
1296
1297 func IsISO4217(str string) bool {
1298 for _, currency := range ISO4217List {
1299 if str == currency {
1300 return true
1301 }
1302 }
1303
1304 return false
1305 }
1306
1307
1308 func ByteLength(str string, params ...string) bool {
1309 if len(params) == 2 {
1310 min, _ := ToInt(params[0])
1311 max, _ := ToInt(params[1])
1312 return len(str) >= int(min) && len(str) <= int(max)
1313 }
1314
1315 return false
1316 }
1317
1318
1319
1320 func RuneLength(str string, params ...string) bool {
1321 return StringLength(str, params...)
1322 }
1323
1324
1325
1326 func IsRsaPub(str string, params ...string) bool {
1327 if len(params) == 1 {
1328 len, _ := ToInt(params[0])
1329 return IsRsaPublicKey(str, int(len))
1330 }
1331
1332 return false
1333 }
1334
1335
1336 func StringMatches(s string, params ...string) bool {
1337 if len(params) == 1 {
1338 pattern := params[0]
1339 return Matches(s, pattern)
1340 }
1341 return false
1342 }
1343
1344
1345 func StringLength(str string, params ...string) bool {
1346
1347 if len(params) == 2 {
1348 strLength := utf8.RuneCountInString(str)
1349 min, _ := ToInt(params[0])
1350 max, _ := ToInt(params[1])
1351 return strLength >= int(min) && strLength <= int(max)
1352 }
1353
1354 return false
1355 }
1356
1357
1358 func MinStringLength(str string, params ...string) bool {
1359
1360 if len(params) == 1 {
1361 strLength := utf8.RuneCountInString(str)
1362 min, _ := ToInt(params[0])
1363 return strLength >= int(min)
1364 }
1365
1366 return false
1367 }
1368
1369
1370 func MaxStringLength(str string, params ...string) bool {
1371
1372 if len(params) == 1 {
1373 strLength := utf8.RuneCountInString(str)
1374 max, _ := ToInt(params[0])
1375 return strLength <= int(max)
1376 }
1377
1378 return false
1379 }
1380
1381
1382 func Range(str string, params ...string) bool {
1383 if len(params) == 2 {
1384 value, _ := ToFloat(str)
1385 min, _ := ToFloat(params[0])
1386 max, _ := ToFloat(params[1])
1387 return InRange(value, min, max)
1388 }
1389
1390 return false
1391 }
1392
1393
1394 func IsInRaw(str string, params ...string) bool {
1395 if len(params) == 1 {
1396 rawParams := params[0]
1397
1398 parsedParams := strings.Split(rawParams, "|")
1399
1400 return IsIn(str, parsedParams...)
1401 }
1402
1403 return false
1404 }
1405
1406
1407 func IsIn(str string, params ...string) bool {
1408 for _, param := range params {
1409 if str == param {
1410 return true
1411 }
1412 }
1413
1414 return false
1415 }
1416
1417 func checkRequired(v reflect.Value, t reflect.StructField, options tagOptionsMap) (bool, error) {
1418 if nilPtrAllowedByRequired {
1419 k := v.Kind()
1420 if (k == reflect.Ptr || k == reflect.Interface) && v.IsNil() {
1421 return true, nil
1422 }
1423 }
1424
1425 if requiredOption, isRequired := options["required"]; isRequired {
1426 if len(requiredOption.customErrorMessage) > 0 {
1427 return false, Error{t.Name, fmt.Errorf(requiredOption.customErrorMessage), true, "required", []string{}}
1428 }
1429 return false, Error{t.Name, fmt.Errorf("non zero value required"), false, "required", []string{}}
1430 } else if _, isOptional := options["optional"]; fieldsRequiredByDefault && !isOptional {
1431 return false, Error{t.Name, fmt.Errorf("Missing required field"), false, "required", []string{}}
1432 }
1433
1434 return true, nil
1435 }
1436
1437 func typeCheck(v reflect.Value, t reflect.StructField, o reflect.Value, options tagOptionsMap) (isValid bool, resultErr error) {
1438 if !v.IsValid() {
1439 return false, nil
1440 }
1441
1442 tag := t.Tag.Get(tagName)
1443
1444
1445 switch tag {
1446 case "":
1447 if v.Kind() != reflect.Slice && v.Kind() != reflect.Map {
1448 if !fieldsRequiredByDefault {
1449 return true, nil
1450 }
1451 return false, Error{t.Name, fmt.Errorf("All fields are required to at least have one validation defined"), false, "required", []string{}}
1452 }
1453 case "-":
1454 return true, nil
1455 }
1456
1457 isRootType := false
1458 if options == nil {
1459 isRootType = true
1460 options = parseTagIntoMap(tag)
1461 }
1462
1463 if isEmptyValue(v) {
1464
1465 isValid, resultErr = checkRequired(v, t, options)
1466 for key := range options {
1467 delete(options, key)
1468 }
1469 return isValid, resultErr
1470 }
1471
1472 var customTypeErrors Errors
1473 optionsOrder := options.orderedKeys()
1474 for _, validatorName := range optionsOrder {
1475 validatorStruct := options[validatorName]
1476 if validatefunc, ok := CustomTypeTagMap.Get(validatorName); ok {
1477 delete(options, validatorName)
1478
1479 if result := validatefunc(v.Interface(), o.Interface()); !result {
1480 if len(validatorStruct.customErrorMessage) > 0 {
1481 customTypeErrors = append(customTypeErrors, Error{Name: t.Name, Err: TruncatingErrorf(validatorStruct.customErrorMessage, fmt.Sprint(v), validatorName), CustomErrorMessageExists: true, Validator: stripParams(validatorName)})
1482 continue
1483 }
1484 customTypeErrors = append(customTypeErrors, Error{Name: t.Name, Err: fmt.Errorf("%s does not validate as %s", fmt.Sprint(v), validatorName), CustomErrorMessageExists: false, Validator: stripParams(validatorName)})
1485 }
1486 }
1487 }
1488
1489 if len(customTypeErrors.Errors()) > 0 {
1490 return false, customTypeErrors
1491 }
1492
1493 if isRootType {
1494
1495 defer func() {
1496 delete(options, "optional")
1497 delete(options, "required")
1498
1499 if isValid && resultErr == nil && len(options) != 0 {
1500 optionsOrder := options.orderedKeys()
1501 for _, validator := range optionsOrder {
1502 isValid = false
1503 resultErr = Error{t.Name, fmt.Errorf(
1504 "The following validator is invalid or can't be applied to the field: %q", validator), false, stripParams(validator), []string{}}
1505 return
1506 }
1507 }
1508 }()
1509 }
1510
1511 for _, validatorSpec := range optionsOrder {
1512 validatorStruct := options[validatorSpec]
1513 var negate bool
1514 validator := validatorSpec
1515 customMsgExists := len(validatorStruct.customErrorMessage) > 0
1516
1517
1518 if validator[0] == '!' {
1519 validator = validator[1:]
1520 negate = true
1521 }
1522
1523
1524 for key, value := range InterfaceParamTagRegexMap {
1525 ps := value.FindStringSubmatch(validator)
1526 if len(ps) == 0 {
1527 continue
1528 }
1529
1530 validatefunc, ok := InterfaceParamTagMap[key]
1531 if !ok {
1532 continue
1533 }
1534
1535 delete(options, validatorSpec)
1536
1537 field := fmt.Sprint(v)
1538 if result := validatefunc(v.Interface(), ps[1:]...); (!result && !negate) || (result && negate) {
1539 if customMsgExists {
1540 return false, Error{t.Name, TruncatingErrorf(validatorStruct.customErrorMessage, field, validator), customMsgExists, stripParams(validatorSpec), []string{}}
1541 }
1542 if negate {
1543 return false, Error{t.Name, fmt.Errorf("%s does validate as %s", field, validator), customMsgExists, stripParams(validatorSpec), []string{}}
1544 }
1545 return false, Error{t.Name, fmt.Errorf("%s does not validate as %s", field, validator), customMsgExists, stripParams(validatorSpec), []string{}}
1546 }
1547 }
1548 }
1549
1550 switch v.Kind() {
1551 case reflect.Bool,
1552 reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
1553 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
1554 reflect.Float32, reflect.Float64,
1555 reflect.String:
1556
1557 for _, validatorSpec := range optionsOrder {
1558 validatorStruct := options[validatorSpec]
1559 var negate bool
1560 validator := validatorSpec
1561 customMsgExists := len(validatorStruct.customErrorMessage) > 0
1562
1563
1564 if validator[0] == '!' {
1565 validator = validator[1:]
1566 negate = true
1567 }
1568
1569
1570 for key, value := range ParamTagRegexMap {
1571 ps := value.FindStringSubmatch(validator)
1572 if len(ps) == 0 {
1573 continue
1574 }
1575
1576 validatefunc, ok := ParamTagMap[key]
1577 if !ok {
1578 continue
1579 }
1580
1581 delete(options, validatorSpec)
1582
1583 switch v.Kind() {
1584 case reflect.String,
1585 reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
1586 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
1587 reflect.Float32, reflect.Float64:
1588
1589 field := fmt.Sprint(v)
1590 if result := validatefunc(field, ps[1:]...); (!result && !negate) || (result && negate) {
1591 if customMsgExists {
1592 return false, Error{t.Name, TruncatingErrorf(validatorStruct.customErrorMessage, field, validator), customMsgExists, stripParams(validatorSpec), []string{}}
1593 }
1594 if negate {
1595 return false, Error{t.Name, fmt.Errorf("%s does validate as %s", field, validator), customMsgExists, stripParams(validatorSpec), []string{}}
1596 }
1597 return false, Error{t.Name, fmt.Errorf("%s does not validate as %s", field, validator), customMsgExists, stripParams(validatorSpec), []string{}}
1598 }
1599 default:
1600
1601 return false, Error{t.Name, fmt.Errorf("Validator %s doesn't support kind %s", validator, v.Kind()), false, stripParams(validatorSpec), []string{}}
1602 }
1603 }
1604
1605 if validatefunc, ok := TagMap[validator]; ok {
1606 delete(options, validatorSpec)
1607
1608 switch v.Kind() {
1609 case reflect.String,
1610 reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
1611 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
1612 reflect.Float32, reflect.Float64:
1613 field := fmt.Sprint(v)
1614 if result := validatefunc(field); !result && !negate || result && negate {
1615 if customMsgExists {
1616 return false, Error{t.Name, TruncatingErrorf(validatorStruct.customErrorMessage, field, validator), customMsgExists, stripParams(validatorSpec), []string{}}
1617 }
1618 if negate {
1619 return false, Error{t.Name, fmt.Errorf("%s does validate as %s", field, validator), customMsgExists, stripParams(validatorSpec), []string{}}
1620 }
1621 return false, Error{t.Name, fmt.Errorf("%s does not validate as %s", field, validator), customMsgExists, stripParams(validatorSpec), []string{}}
1622 }
1623 default:
1624
1625 err := fmt.Errorf("Validator %s doesn't support kind %s for value %v", validator, v.Kind(), v)
1626 return false, Error{t.Name, err, false, stripParams(validatorSpec), []string{}}
1627 }
1628 }
1629 }
1630 return true, nil
1631 case reflect.Map:
1632 if v.Type().Key().Kind() != reflect.String {
1633 return false, &UnsupportedTypeError{v.Type()}
1634 }
1635 var sv stringValues
1636 sv = v.MapKeys()
1637 sort.Sort(sv)
1638 result := true
1639 for i, k := range sv {
1640 var resultItem bool
1641 var err error
1642 if v.MapIndex(k).Kind() != reflect.Struct {
1643 resultItem, err = typeCheck(v.MapIndex(k), t, o, options)
1644 if err != nil {
1645 return false, err
1646 }
1647 } else {
1648 resultItem, err = ValidateStruct(v.MapIndex(k).Interface())
1649 if err != nil {
1650 err = prependPathToErrors(err, t.Name+"."+sv[i].Interface().(string))
1651 return false, err
1652 }
1653 }
1654 result = result && resultItem
1655 }
1656 return result, nil
1657 case reflect.Slice, reflect.Array:
1658 result := true
1659 for i := 0; i < v.Len(); i++ {
1660 var resultItem bool
1661 var err error
1662 if v.Index(i).Kind() != reflect.Struct {
1663 resultItem, err = typeCheck(v.Index(i), t, o, options)
1664 if err != nil {
1665 return false, err
1666 }
1667 } else {
1668 resultItem, err = ValidateStruct(v.Index(i).Interface())
1669 if err != nil {
1670 err = prependPathToErrors(err, t.Name+"."+strconv.Itoa(i))
1671 return false, err
1672 }
1673 }
1674 result = result && resultItem
1675 }
1676 return result, nil
1677 case reflect.Interface:
1678
1679 if v.IsNil() {
1680 return true, nil
1681 }
1682 return ValidateStruct(v.Interface())
1683 case reflect.Ptr:
1684
1685 if v.IsNil() {
1686 return true, nil
1687 }
1688 return typeCheck(v.Elem(), t, o, options)
1689 case reflect.Struct:
1690 return true, nil
1691 default:
1692 return false, &UnsupportedTypeError{v.Type()}
1693 }
1694 }
1695
1696 func stripParams(validatorString string) string {
1697 return paramsRegexp.ReplaceAllString(validatorString, "")
1698 }
1699
1700
1701 func isEmptyValue(v reflect.Value) bool {
1702 switch v.Kind() {
1703 case reflect.String, reflect.Array:
1704 return v.Len() == 0
1705 case reflect.Map, reflect.Slice:
1706 return v.Len() == 0 || v.IsNil()
1707 case reflect.Bool:
1708 return !v.Bool()
1709 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
1710 return v.Int() == 0
1711 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
1712 return v.Uint() == 0
1713 case reflect.Float32, reflect.Float64:
1714 return v.Float() == 0
1715 case reflect.Interface, reflect.Ptr:
1716 return v.IsNil()
1717 }
1718
1719 return reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface())
1720 }
1721
1722
1723
1724
1725 func ErrorByField(e error, field string) string {
1726 if e == nil {
1727 return ""
1728 }
1729 return ErrorsByField(e)[field]
1730 }
1731
1732
1733
1734 func ErrorsByField(e error) map[string]string {
1735 m := make(map[string]string)
1736 if e == nil {
1737 return m
1738 }
1739
1740
1741 switch e := e.(type) {
1742 case Error:
1743 m[e.Name] = e.Err.Error()
1744 case Errors:
1745 for _, item := range e.Errors() {
1746 n := ErrorsByField(item)
1747 for k, v := range n {
1748 m[k] = v
1749 }
1750 }
1751 }
1752
1753 return m
1754 }
1755
1756
1757 func (e *UnsupportedTypeError) Error() string {
1758 return "validator: unsupported type: " + e.Type.String()
1759 }
1760
1761 func (sv stringValues) Len() int { return len(sv) }
1762 func (sv stringValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] }
1763 func (sv stringValues) Less(i, j int) bool { return sv.get(i) < sv.get(j) }
1764 func (sv stringValues) get(i int) string { return sv[i].String() }
1765
1766 func IsE164(str string) bool {
1767 return rxE164.MatchString(str)
1768 }
1769
View as plain text