From afc18e0aada2cccf994545f29224a5aefc0a62f3 Mon Sep 17 00:00:00 2001 From: Jason Lam Date: Wed, 10 Jan 2018 22:07:25 -0800 Subject: [PATCH 1/3] Refactor ToInt (converter.go) to handle all int types and string type and updated InRangeInt (numerics.go) to handle all int types not just type int --- converter.go | 29 ++++++- numerics.go | 11 ++- numerics_test.go | 206 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 238 insertions(+), 8 deletions(-) diff --git a/converter.go b/converter.go index d69114c..fe90ec4 100644 --- a/converter.go +++ b/converter.go @@ -3,6 +3,7 @@ package govalidator import ( "encoding/json" "fmt" + "reflect" "strconv" ) @@ -31,7 +32,7 @@ func ToFloat(str string) (float64, error) { } // ToInt convert the input string to an integer, or 0 if the input is not an integer. -func ToInt(str string) (int64, error) { +func ToIntX(str string) (int64, error) { res, err := strconv.ParseInt(str, 0, 64) if err != nil { res = 0 @@ -39,6 +40,32 @@ func ToInt(str string) (int64, error) { return res, err } +func ToInt(value interface{}) (res int64, err error) { + val := reflect.ValueOf(value) + + switch value.(type) { + case int, int8, int16, int32, int64: + res = val.Int() + case uint, uint8, uint16, uint32, uint64: + res = int64(val.Uint()) + case string: + if IsInt(val.String()) { + res, err = strconv.ParseInt(val.String(), 0, 64) + if err != nil { + res = 0 + } + } else { + err = fmt.Errorf("math: square root of negative number %g", value) + res = 0 + } + default: + err = fmt.Errorf("math: square root of negative number %g", value) + res = 0 + } + + return +} + // ToBoolean convert the input string to a boolean. func ToBoolean(str string) (bool, error) { return strconv.ParseBool(str) diff --git a/numerics.go b/numerics.go index d0140d4..7e6c652 100644 --- a/numerics.go +++ b/numerics.go @@ -42,11 +42,14 @@ func IsNonPositive(value float64) bool { } // InRange returns true if value lies between left and right border -func InRangeInt(value, left, right int) bool { - if left > right { - left, right = right, left +func InRangeInt(value, left, right interface{}) bool { + value64, _ := ToInt(value) + left64, _ := ToInt(left) + right64, _ := ToInt(right) + if left64 > right64 { + left64, right64 = right64, left64 } - return value >= left && value <= right + return value64 >= left64 && value64 <= right64 } // InRange returns true if value lies between left and right border diff --git a/numerics_test.go b/numerics_test.go index ca743df..8a28415 100644 --- a/numerics_test.go +++ b/numerics_test.go @@ -181,7 +181,7 @@ func TestIsNatural(t *testing.T) { func TestInRangeInt(t *testing.T) { t.Parallel() - var tests = []struct { + var testAsInts = []struct { param int left int right int @@ -196,10 +196,210 @@ func TestInRangeInt(t *testing.T) { {0, 0, -1, true}, {0, 10, 5, false}, } - for _, test := range tests { + for _, test := range testAsInts { + actual := InRangeInt(test.param, test.left, test.right) + if actual != test.expected { + t.Errorf("Expected InRangeInt(%v, %v, %v) to be %v, got %v using type int", test.param, test.left, test.right, test.expected, actual) + } + } + + var testAsInt8s = []struct { + param int8 + left int8 + right int8 + expected bool + }{ + {0, 0, 0, true}, + {1, 0, 0, false}, + {-1, 0, 0, false}, + {0, -1, 1, true}, + {0, 0, 1, true}, + {0, -1, 0, true}, + {0, 0, -1, true}, + {0, 10, 5, false}, + } + for _, test := range testAsInt8s { + actual := InRangeInt(test.param, test.left, test.right) + if actual != test.expected { + t.Errorf("Expected InRangeInt(%v, %v, %v) to be %v, got %v using type int8", test.param, test.left, test.right, test.expected, actual) + } + } + + var testAsInt16s = []struct { + param int16 + left int16 + right int16 + expected bool + }{ + {0, 0, 0, true}, + {1, 0, 0, false}, + {-1, 0, 0, false}, + {0, -1, 1, true}, + {0, 0, 1, true}, + {0, -1, 0, true}, + {0, 0, -1, true}, + {0, 10, 5, false}, + } + for _, test := range testAsInt16s { + actual := InRangeInt(test.param, test.left, test.right) + if actual != test.expected { + t.Errorf("Expected InRangeInt(%v, %v, %v) to be %v, got %v using type int16", test.param, test.left, test.right, test.expected, actual) + } + } + + var testAsInt32s = []struct { + param int32 + left int32 + right int32 + expected bool + }{ + {0, 0, 0, true}, + {1, 0, 0, false}, + {-1, 0, 0, false}, + {0, -1, 1, true}, + {0, 0, 1, true}, + {0, -1, 0, true}, + {0, 0, -1, true}, + {0, 10, 5, false}, + } + for _, test := range testAsInt32s { + actual := InRangeInt(test.param, test.left, test.right) + if actual != test.expected { + t.Errorf("Expected InRangeInt(%v, %v, %v) to be %v, got %v using type int32", test.param, test.left, test.right, test.expected, actual) + } + } + + var testAsInt64s = []struct { + param int64 + left int64 + right int64 + expected bool + }{ + {0, 0, 0, true}, + {1, 0, 0, false}, + {-1, 0, 0, false}, + {0, -1, 1, true}, + {0, 0, 1, true}, + {0, -1, 0, true}, + {0, 0, -1, true}, + {0, 10, 5, false}, + } + for _, test := range testAsInt64s { + actual := InRangeInt(test.param, test.left, test.right) + if actual != test.expected { + t.Errorf("Expected InRangeInt(%v, %v, %v) to be %v, got %v using type int64", test.param, test.left, test.right, test.expected, actual) + } + } + + var testAsUInts = []struct { + param uint + left uint + right uint + expected bool + }{ + {0, 0, 0, true}, + {1, 0, 0, false}, + {0, 0, 1, true}, + {0, 10, 5, false}, + } + for _, test := range testAsUInts { + actual := InRangeInt(test.param, test.left, test.right) + if actual != test.expected { + t.Errorf("Expected InRangeInt(%v, %v, %v) to be %v, got %v using type uint", test.param, test.left, test.right, test.expected, actual) + } + } + + var testAsUInt8s = []struct { + param uint8 + left uint8 + right uint8 + expected bool + }{ + {0, 0, 0, true}, + {1, 0, 0, false}, + {0, 0, 1, true}, + {0, 10, 5, false}, + } + for _, test := range testAsUInt8s { + actual := InRangeInt(test.param, test.left, test.right) + if actual != test.expected { + t.Errorf("Expected InRangeInt(%v, %v, %v) to be %v, got %v using type uint", test.param, test.left, test.right, test.expected, actual) + } + } + + var testAsUInt16s = []struct { + param uint16 + left uint16 + right uint16 + expected bool + }{ + {0, 0, 0, true}, + {1, 0, 0, false}, + {0, 0, 1, true}, + {0, 10, 5, false}, + } + for _, test := range testAsUInt16s { + actual := InRangeInt(test.param, test.left, test.right) + if actual != test.expected { + t.Errorf("Expected InRangeInt(%v, %v, %v) to be %v, got %v using type uint", test.param, test.left, test.right, test.expected, actual) + } + } + + var testAsUInt32s = []struct { + param uint32 + left uint32 + right uint32 + expected bool + }{ + {0, 0, 0, true}, + {1, 0, 0, false}, + {0, 0, 1, true}, + {0, 10, 5, false}, + } + for _, test := range testAsUInt32s { + actual := InRangeInt(test.param, test.left, test.right) + if actual != test.expected { + t.Errorf("Expected InRangeInt(%v, %v, %v) to be %v, got %v using type uint", test.param, test.left, test.right, test.expected, actual) + } + } + + var testAsUInt64s = []struct { + param uint64 + left uint64 + right uint64 + expected bool + }{ + {0, 0, 0, true}, + {1, 0, 0, false}, + {0, 0, 1, true}, + {0, 10, 5, false}, + } + for _, test := range testAsUInt64s { + actual := InRangeInt(test.param, test.left, test.right) + if actual != test.expected { + t.Errorf("Expected InRangeInt(%v, %v, %v) to be %v, got %v using type uint", test.param, test.left, test.right, test.expected, actual) + } + } + + var testAsStrings = []struct { + param string + left string + right string + expected bool + }{ + {"0", "0", "0", true}, + {"1", "0", "0", false}, + {"-1", "0", "0", false}, + {"0", "-1", "1", true}, + {"0", "0", "1", true}, + {"0", "-1", "0", true}, + {"0", "0", "-1", true}, + {"0", "10", "5", false}, + } + for _, test := range testAsStrings { actual := InRangeInt(test.param, test.left, test.right) if actual != test.expected { - t.Errorf("Expected InRangeInt(%v, %v, %v) to be %v, got %v", test.param, test.left, test.right, test.expected, actual) + t.Errorf("Expected InRangeInt(%v, %v, %v) to be %v, got %v using type string", test.param, test.left, test.right, test.expected, actual) } } } From 166340604017002ec22567a99e20985d7c4f0112 Mon Sep 17 00:00:00 2001 From: Jason Lam Date: Wed, 10 Jan 2018 22:15:44 -0800 Subject: [PATCH 2/3] Remove old function ToIntX (was using it as reference) --- converter.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/converter.go b/converter.go index fe90ec4..2339c45 100644 --- a/converter.go +++ b/converter.go @@ -31,15 +31,6 @@ func ToFloat(str string) (float64, error) { return res, err } -// ToInt convert the input string to an integer, or 0 if the input is not an integer. -func ToIntX(str string) (int64, error) { - res, err := strconv.ParseInt(str, 0, 64) - if err != nil { - res = 0 - } - return res, err -} - func ToInt(value interface{}) (res int64, err error) { val := reflect.ValueOf(value) From 4086df8220c5ed2c259ad5f850e41d052a6c7b3d Mon Sep 17 00:00:00 2001 From: Jason Lam Date: Wed, 10 Jan 2018 22:18:44 -0800 Subject: [PATCH 3/3] Update ToInt comment --- converter.go | 1 + 1 file changed, 1 insertion(+) diff --git a/converter.go b/converter.go index 2339c45..cf1e5d5 100644 --- a/converter.go +++ b/converter.go @@ -31,6 +31,7 @@ func ToFloat(str string) (float64, error) { return res, err } +// ToInt convert the input string or any int type to an integer type 64, or 0 if the input is not an integer. func ToInt(value interface{}) (res int64, err error) { val := reflect.ValueOf(value)