Skip to content

Commit

Permalink
Merge branch 'master' into fix_travis_ci1
Browse files Browse the repository at this point in the history
  • Loading branch information
asaskevich authored Aug 17, 2020
2 parents 5b8b3f2 + bc321cc commit 9a7fa19
Show file tree
Hide file tree
Showing 13 changed files with 277 additions and 823 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ version: 2
jobs:
build:
docker:
- image: circleci/golang:1.9
- image: circleci/golang:1.13
working_directory: /go/src/github.com/asaskevich/govalidator
steps:
- checkout
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2014 Alex Saskevich
Copyright (c) 2014-2020 Alex Saskevich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ type User struct {
Age int `valid:"type(int)"`
Meta interface{} `valid:"type(string)"`
}
result, err := govalidator.ValidateStruct(user{"Bob", 20, "meta"})
result, err := govalidator.ValidateStruct(User{"Bob", 20, "meta"})
if err != nil {
println("error: " + err.Error())
}
Expand Down Expand Up @@ -393,6 +393,8 @@ Validators with parameters
"matches(pattern)": StringMatches,
"in(string1|string2|...|stringN)": IsIn,
"rsapub(keylength)" : IsRsaPub,
"minstringlength(int): MinStringLength,
"maxstringlength(int): MaxStringLength,
```
Validators with parameters for any type

Expand Down
60 changes: 60 additions & 0 deletions array_benchmark_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package govalidator

import "testing"

func BenchmarkEach(b *testing.B) {
b.ResetTimer()
for n := 0; n < b.N; n++ {
acc := 0
data := []interface{}{1, 2, 3, 4, 5}
var fn Iterator = func(value interface{}, index int) {
acc = acc + value.(int)
}
Each(data, fn)
}
}

func BenchmarkMap(b *testing.B) {
b.ResetTimer()
for n := 0; n < b.N; n++ {
data := []interface{}{1, 2, 3, 4, 5}
var fn ResultIterator = func(value interface{}, index int) interface{} {
return value.(int) * 3
}
_ = Map(data, fn)
}
}

func BenchmarkFind(b *testing.B) {
b.ResetTimer()
for n := 0; n < b.N; n++ {
findElement := 96
data := []interface{}{1, 2, 3, 4, findElement, 5}
var fn1 ConditionIterator = func(value interface{}, index int) bool {
return value.(int) == findElement
}
_ = Find(data, fn1)
}
}

func BenchmarkFilter(b *testing.B) {
b.ResetTimer()
for n := 0; n < b.N; n++ {
data := []interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
var fn ConditionIterator = func(value interface{}, index int) bool {
return value.(int)%2 == 0
}
_ = Filter(data, fn)
}
}

func BenchmarkCount(b *testing.B) {
b.ResetTimer()
for n := 0; n < b.N; n++ {
data := []interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
var fn ConditionIterator = func(value interface{}, index int) bool {
return value.(int)%2 == 0
}
_ = Count(data, fn)
}
}
41 changes: 41 additions & 0 deletions array_example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package govalidator

func ExampleFilter() {
data := []interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
var fn ConditionIterator = func(value interface{}, index int) bool {
return value.(int)%2 == 0
}
_ = Filter(data, fn) // result = []interface{}{2, 4, 6, 8, 10}
}

func ExampleCount() {
data := []interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
var fn ConditionIterator = func(value interface{}, index int) bool {
return value.(int)%2 == 0
}
_ = Count(data, fn) // result = 5
}

func ExampleMap() {
data := []interface{}{1, 2, 3, 4, 5}
var fn ResultIterator = func(value interface{}, index int) interface{} {
return value.(int) * 3
}
_ = Map(data, fn) // result = []interface{}{1, 6, 9, 12, 15}
}

func ExampleEach() {
data := []interface{}{1, 2, 3, 4, 5}
var fn Iterator = func(value interface{}, index int) {
println(value.(int))
}
Each(data, fn)
}

func ExampleFind() {
data := []interface{}{1, 2, 3, 4, 5}
var fn ConditionIterator = func(value interface{}, index int) bool {
return value.(int) == 4
}
_ = Find(data, fn) // result = 4
}
32 changes: 0 additions & 32 deletions arrays_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,6 @@ func TestEach(t *testing.T) {
}
}

func ExampleEach() {
data := []interface{}{1, 2, 3, 4, 5}
var fn Iterator = func(value interface{}, index int) {
println(value.(int))
}
Each(data, fn)
}

func TestMap(t *testing.T) {
// TODO Maybe refactor?
t.Parallel()
Expand All @@ -39,14 +31,6 @@ func TestMap(t *testing.T) {
}
}

func ExampleMap() {
data := []interface{}{1, 2, 3, 4, 5}
var fn ResultIterator = func(value interface{}, index int) interface{} {
return value.(int) * 3
}
_ = Map(data, fn) // result = []interface{}{1, 6, 9, 12, 15}
}

func TestFind(t *testing.T) {
// TODO Maybe refactor?
t.Parallel()
Expand Down Expand Up @@ -85,14 +69,6 @@ func TestFilter(t *testing.T) {
}
}

func ExampleFilter() {
data := []interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
var fn ConditionIterator = func(value interface{}, index int) bool {
return value.(int)%2 == 0
}
_ = Filter(data, fn) // result = []interface{}{2, 4, 6, 8, 10}
}

func TestCount(t *testing.T) {
// TODO Maybe refactor?
t.Parallel()
Expand All @@ -106,11 +82,3 @@ func TestCount(t *testing.T) {
t.Errorf("Expected Count(..) to be %v, got %v", count, result)
}
}

func ExampleCount() {
data := []interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
var fn ConditionIterator = func(value interface{}, index int) bool {
return value.(int)%2 == 0
}
_ = Count(data, fn) // result = 5
}
4 changes: 2 additions & 2 deletions converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ func ToInt(value interface{}) (res int64, err error) {
res = 0
}
} else {
err = fmt.Errorf("math: square root of negative number %g", value)
err = fmt.Errorf("ToInt: invalid numeric format %g", value)
res = 0
}
default:
err = fmt.Errorf("math: square root of negative number %g", value)
err = fmt.Errorf("ToInt: unknown interface type %T", value)
res = 0
}

Expand Down
4 changes: 2 additions & 2 deletions converter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
)

func TestToInt(t *testing.T) {
tests := []string{"1000", "-123", "abcdef", "100000000000000000000000000000000000000000000"}
expected := []int64{1000, -123, 0, 0}
tests := []interface{}{"1000", "-123", "abcdef", "100000000000000000000000000000000000000000000", false}
expected := []int64{1000, -123, 0, 0, 0}
for i := 0; i < len(tests); i++ {
result, _ := ToInt(tests[i])
if result != expected[i] {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module github.com/asaskevich/govalidator

go 1.12
go 1.13
2 changes: 2 additions & 0 deletions patterns.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ const (
hasWhitespace string = ".*[[:space:]]"
hasWhitespaceOnly string = "^[[:space:]]+$"
IMEI string = "^[0-9a-f]{14}$|^\\d{15}$|^\\d{18}$"
IMSI string = "^\\d{14,15}$"
)

// Used by IsFilePath func
Expand Down Expand Up @@ -102,4 +103,5 @@ var (
rxHasWhitespace = regexp.MustCompile(hasWhitespace)
rxHasWhitespaceOnly = regexp.MustCompile(hasWhitespaceOnly)
rxIMEI = regexp.MustCompile(IMEI)
rxIMSI = regexp.MustCompile(IMSI)
)
14 changes: 7 additions & 7 deletions types.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,13 @@ var ParamTagMap = map[string]ParamValidator{

// ParamTagRegexMap maps param tags to their respective regexes.
var ParamTagRegexMap = map[string]*regexp.Regexp{
"range": regexp.MustCompile("^range\\((\\d+)\\|(\\d+)\\)$"),
"length": regexp.MustCompile("^length\\((\\d+)\\|(\\d+)\\)$"),
"runelength": regexp.MustCompile("^runelength\\((\\d+)\\|(\\d+)\\)$"),
"stringlength": regexp.MustCompile("^stringlength\\((\\d+)\\|(\\d+)\\)$"),
"in": regexp.MustCompile(`^in\((.*)\)`),
"matches": regexp.MustCompile(`^matches\((.+)\)$`),
"rsapub": regexp.MustCompile("^rsapub\\((\\d+)\\)$"),
"range": regexp.MustCompile("^range\\((\\d+)\\|(\\d+)\\)$"),
"length": regexp.MustCompile("^length\\((\\d+)\\|(\\d+)\\)$"),
"runelength": regexp.MustCompile("^runelength\\((\\d+)\\|(\\d+)\\)$"),
"stringlength": regexp.MustCompile("^stringlength\\((\\d+)\\|(\\d+)\\)$"),
"in": regexp.MustCompile(`^in\((.*)\)`),
"matches": regexp.MustCompile(`^matches\((.+)\)$`),
"rsapub": regexp.MustCompile("^rsapub\\((\\d+)\\)$"),
"minstringlength": regexp.MustCompile("^minstringlength\\((\\d+)\\)$"),
"maxstringlength": regexp.MustCompile("^maxstringlength\\((\\d+)\\)$"),
}
Expand Down
71 changes: 63 additions & 8 deletions validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,49 @@ func IsIMEI(str string) bool {
return rxIMEI.MatchString(str)
}

// IsIMSI check if a string is valid IMSI
func IsIMSI(str string) bool {
if !rxIMSI.MatchString(str) {
return false
}

mcc, err := strconv.ParseInt(str[0:3], 10, 32)
if err != nil {
return false
}

switch mcc {
case 202, 204, 206, 208, 212, 213, 214, 216, 218, 219:
case 220, 221, 222, 226, 228, 230, 231, 232, 234, 235:
case 238, 240, 242, 244, 246, 247, 248, 250, 255, 257:
case 259, 260, 262, 266, 268, 270, 272, 274, 276, 278:
case 280, 282, 283, 284, 286, 288, 289, 290, 292, 293:
case 294, 295, 297, 302, 308, 310, 311, 312, 313, 314:
case 315, 316, 330, 332, 334, 338, 340, 342, 344, 346:
case 348, 350, 352, 354, 356, 358, 360, 362, 363, 364:
case 365, 366, 368, 370, 372, 374, 376, 400, 401, 402:
case 404, 405, 406, 410, 412, 413, 414, 415, 416, 417:
case 418, 419, 420, 421, 422, 424, 425, 426, 427, 428:
case 429, 430, 431, 432, 434, 436, 437, 438, 440, 441:
case 450, 452, 454, 455, 456, 457, 460, 461, 466, 467:
case 470, 472, 502, 505, 510, 514, 515, 520, 525, 528:
case 530, 536, 537, 539, 540, 541, 542, 543, 544, 545:
case 546, 547, 548, 549, 550, 551, 552, 553, 554, 555:
case 602, 603, 604, 605, 606, 607, 608, 609, 610, 611:
case 612, 613, 614, 615, 616, 617, 618, 619, 620, 621:
case 622, 623, 624, 625, 626, 627, 628, 629, 630, 631:
case 632, 633, 634, 635, 636, 637, 638, 639, 640, 641:
case 642, 643, 645, 646, 647, 648, 649, 650, 651, 652:
case 653, 654, 655, 657, 658, 659, 702, 704, 706, 708:
case 710, 712, 714, 716, 722, 724, 730, 732, 734, 736:
case 738, 740, 742, 744, 746, 748, 750, 995:
return true
default:
return false
}
return true
}

// IsRsaPublicKey check if a string is valid public key with provided length
func IsRsaPublicKey(str string, keylen int) bool {
bb := bytes.NewBufferString(str)
Expand Down Expand Up @@ -1238,7 +1281,7 @@ func typeCheck(v reflect.Value, t reflect.StructField, o reflect.Value, options
options = parseTagIntoMap(tag)
}

if !isFieldSet(v) {
if isEmptyValue(v) {
// an empty value is not validated, check only required
isValid, resultErr = checkRequired(v, t, options)
for key := range options {
Expand Down Expand Up @@ -1475,14 +1518,26 @@ func stripParams(validatorString string) string {
return paramsRegexp.ReplaceAllString(validatorString, "")
}

// isFieldSet returns false for nil pointers, interfaces, maps, and slices. For all other values, it returns true.
func isFieldSet(v reflect.Value) bool {
// isEmptyValue checks whether value empty or not
func isEmptyValue(v reflect.Value) bool {
switch v.Kind() {
case reflect.Map, reflect.Slice, reflect.Interface, reflect.Ptr:
return !v.IsNil()
}

return true
case reflect.String, reflect.Array:
return v.Len() == 0
case reflect.Map, reflect.Slice:
return v.Len() == 0 || v.IsNil()
case reflect.Bool:
return !v.Bool()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return v.Int() == 0
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return v.Uint() == 0
case reflect.Float32, reflect.Float64:
return v.Float() == 0
case reflect.Interface, reflect.Ptr:
return v.IsNil()
}

return reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface())
}

// ErrorByField returns error for specified field of the struct
Expand Down
Loading

0 comments on commit 9a7fa19

Please sign in to comment.