Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Min and Max added. #35

Merged
merged 1 commit into from
Jun 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ type Person struct {

This package currently provides the following checkers:

- [max](doc/checkers/max.md) checks if the given value is less than the given maximum.
- [max-length](doc/checkers/maxlength.md) checks if the length of the given value is less than the given maximum length.
- [min](doc/checkers/min.md) checks if the given value is greather than the given minimum.
- [min-length](doc/checkers/minlength.md) checks if the length of the given value is greather than the given minimum length.
- [required](doc/checkers/required.md) checks if the required value is provided.
- [same](doc/checkers/same.md) checks if the given value is equal to the value of the field with the given name.
16 changes: 16 additions & 0 deletions checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ const ResultValid Result = "VALID"

// makers provides mapping to maker function for the checkers.
var makers = map[string]MakeFunc{
CheckerMax: makeMax,
CheckerMaxLength: makeMaxLength,
CheckerMin: makeMin,
CheckerMinLength: makeMinLength,
CheckerRequired: makeRequired,
CheckerSame: makeSame,
Expand Down Expand Up @@ -120,3 +122,17 @@ func initCheckers(config string) []CheckFunc {

return checkers
}

// numberOf gives value's numerical value given that it is either an int or a float.
func numberOf(value reflect.Value) float64 {
switch value.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return float64(value.Int())

case reflect.Float32, reflect.Float64:
return value.Float()

default:
panic("expecting int or float")
}
}
28 changes: 28 additions & 0 deletions checker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,34 @@ func TestCheckNestedStruct(t *testing.T) {
}
}

func TestNumberOfInvalid(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Fail()
}
}()

s := "invalid"

numberOf(reflect.ValueOf(s))
}

func TestNumberOfInt(t *testing.T) {
n := 10

if numberOf(reflect.ValueOf(n)) != float64(n) {
t.Fail()
}
}

func TestNumberOfFloat(t *testing.T) {
n := float64(10.10)

if numberOf(reflect.ValueOf(n)) != n {
t.Fail()
}
}

func BenchmarkCheck(b *testing.B) {
type Address struct {
Street string `checkers:"required"`
Expand Down
30 changes: 30 additions & 0 deletions doc/checkers/max.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Max Checker

The ```max``` checker checks if the given ```int``` or ```float``` value is less than the given maximum. If the value is above the maximum, the checker will return the ```NOT_MAX``` result. Here is an example:

```golang
type Order struct {
Quantity int `checkers:"max:10"`
}

order := &Order{
Quantity: 5,
}

mistakes, valid := Check(order)
if !valid {
// Send the mistakes back to the user
}
```

In your custom checkers, you can call the ```max``` checker function ```IsMax``` to validate the user input. Here is an example:

```golang
quantity := 5

result := IsMax(quantity, 10 )

if result != ResultValid {
// Send the mistakes back to the user
}
```
30 changes: 30 additions & 0 deletions doc/checkers/min.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Min Checker

The ```min``` checker checks if the given ```int``` or ```float``` value is greather than the given minimum. If the value is below the minimum, the checker will return the ```NOT_MIN``` result. Here is an example:

```golang
type User struct {
Age int `checkers:"min:21"`
}

user := &User{
Age: 45,
}

mistakes, valid := Check(user)
if !valid {
// Send the mistakes back to the user
}
```

In your custom checkers, you can call the ```min``` checker function ```IsMin``` to validate the user input. Here is an example:

```golang
age := 45

result := IsMin(age, 21)

if result != ResultValid {
// Send the mistakes back to the user
}
```
40 changes: 40 additions & 0 deletions max.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package checker

import (
"reflect"
"strconv"
)

// CheckerMax is the name of the checker.
const CheckerMax = "max"

// ResultNotMax indicates that the given value is above the defined maximum.
const ResultNotMax = "NOT_MIN"

// IsMax checks if the given value is below than the given maximum.
func IsMax(value interface{}, max float64) Result {
return checkMax(reflect.Indirect(reflect.ValueOf(value)), reflect.ValueOf(nil), max)
}

// makeMax makes a checker function for the max checker.
func makeMax(config string) CheckFunc {
max, err := strconv.ParseFloat(config, 64)
if err != nil {
panic("unable to parse max")
}

return func(value, parent reflect.Value) Result {
return checkMax(value, parent, max)
}
}

// checkMax checks if the given value is less than the given maximum.
func checkMax(value, _ reflect.Value, max float64) Result {
n := numberOf(value)

if n > max {
return ResultNotMax
}

return ResultValid
}
57 changes: 57 additions & 0 deletions max_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package checker

import "testing"

func TestIsMaxValid(t *testing.T) {
n := 5

if IsMax(n, 10) != ResultValid {
t.Fail()
}
}

func TestCheckMaxInvalidConfig(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Fail()
}
}()

type Order struct {
Quantity int `checkers:"max:AB"`
}

order := &Order{}

Check(order)
}

func TestCheckMaxValid(t *testing.T) {
type Order struct {
Quantity int `checkers:"max:10"`
}

order := &Order{
Quantity: 5,
}

_, valid := Check(order)
if !valid {
t.Fail()
}
}

func TestCheckMaxInvalid(t *testing.T) {
type Order struct {
Quantity int `checkers:"max:10"`
}

order := &Order{
Quantity: 20,
}

_, valid := Check(order)
if valid {
t.Fail()
}
}
40 changes: 40 additions & 0 deletions min.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package checker

import (
"reflect"
"strconv"
)

// CheckerMin is the name of the checker.
const CheckerMin = "min"

// ResultNotMin indicates that the given value is below the defined minimum.
const ResultNotMin = "NOT_MIN"

// IsMin checks if the given value is above than the given minimum.
func IsMin(value interface{}, min float64) Result {
return checkMin(reflect.Indirect(reflect.ValueOf(value)), reflect.ValueOf(nil), min)
}

// makeMin makes a checker function for the min checker.
func makeMin(config string) CheckFunc {
min, err := strconv.ParseFloat(config, 64)
if err != nil {
panic("unable to parse min")
}

return func(value, parent reflect.Value) Result {
return checkMin(value, parent, min)
}
}

// checkMin checks if the given value is greather than the given minimum.
func checkMin(value, _ reflect.Value, min float64) Result {
n := numberOf(value)

if n < min {
return ResultNotMin
}

return ResultValid
}
57 changes: 57 additions & 0 deletions min_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package checker

import "testing"

func TestIsMinValid(t *testing.T) {
n := 45

if IsMin(n, 21) != ResultValid {
t.Fail()
}
}

func TestCheckMinInvalidConfig(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Fail()
}
}()

type User struct {
Age int `checkers:"min:AB"`
}

user := &User{}

Check(user)
}

func TestCheckMinValid(t *testing.T) {
type User struct {
Age int `checkers:"min:21"`
}

user := &User{
Age: 45,
}

_, valid := Check(user)
if !valid {
t.Fail()
}
}

func TestCheckMinInvalid(t *testing.T) {
type User struct {
Age int `checkers:"min:21"`
}

user := &User{
Age: 18,
}

_, valid := Check(user)
if valid {
t.Fail()
}
}