| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 | 
							- package valid
 
- import (
 
- 	"fmt"
 
- 	"reflect"
 
- 	"time"
 
- )
 
- var (
 
- 	// ErrMinGreaterEqualThanRequired is the error that returns when a value is less than a specified threshold.
 
- 	ErrMinGreaterEqualThanRequired = NewError("validation_min_greater_equal_than_required", "must be no less than {{.threshold}}")
 
- 	// ErrMaxLessEqualThanRequired is the error that returns when a value is greater than a specified threshold.
 
- 	ErrMaxLessEqualThanRequired = NewError("validation_max_less_equal_than_required", "must be no greater than {{.threshold}}")
 
- 	// ErrMinGreaterThanRequired is the error that returns when a value is less than or equal to a specified threshold.
 
- 	ErrMinGreaterThanRequired = NewError("validation_min_greater_than_required", "must be greater than {{.threshold}}")
 
- 	// ErrMaxLessThanRequired is the error that returns when a value is greater than or equal to a specified threshold.
 
- 	ErrMaxLessThanRequired = NewError("validation_max_less_than_required", "must be less than {{.threshold}}")
 
- )
 
- // ThresholdRule is a validation rule that checks if a value satisfies the specified threshold requirement.
 
- type ThresholdRule struct {
 
- 	threshold interface{}
 
- 	operator  int
 
- 	err       Error
 
- }
 
- const (
 
- 	greaterThan = iota
 
- 	greaterEqualThan
 
- 	lessThan
 
- 	lessEqualThan
 
- )
 
- // Min returns a validation rule that checks if a value is greater or equal than the specified value.
 
- // By calling Exclusive, the rule will check if the value is strictly greater than the specified value.
 
- // Note that the value being checked and the threshold value must be of the same type.
 
- // Only int, uint, float and time.Time types are supported.
 
- // An empty value is considered valid. Please use the Required rule to make sure a value is not empty.
 
- func Min(min interface{}) ThresholdRule {
 
- 	return ThresholdRule{
 
- 		threshold: min,
 
- 		operator:  greaterEqualThan,
 
- 		err:       ErrMinGreaterEqualThanRequired,
 
- 	}
 
- }
 
- // Max returns a validation rule that checks if a value is less or equal than the specified value.
 
- // By calling Exclusive, the rule will check if the value is strictly less than the specified value.
 
- // Note that the value being checked and the threshold value must be of the same type.
 
- // Only int, uint, float and time.Time types are supported.
 
- // An empty value is considered valid. Please use the Required rule to make sure a value is not empty.
 
- func Max(max interface{}) ThresholdRule {
 
- 	return ThresholdRule{
 
- 		threshold: max,
 
- 		operator:  lessEqualThan,
 
- 		err:       ErrMaxLessEqualThanRequired,
 
- 	}
 
- }
 
- // Exclusive sets the comparison to exclude the boundary value.
 
- func (r ThresholdRule) Exclusive() ThresholdRule {
 
- 	if r.operator == greaterEqualThan {
 
- 		r.operator = greaterThan
 
- 		r.err = ErrMinGreaterThanRequired
 
- 	} else if r.operator == lessEqualThan {
 
- 		r.operator = lessThan
 
- 		r.err = ErrMaxLessThanRequired
 
- 	}
 
- 	return r
 
- }
 
- // Validate checks if the given value is valid or not.
 
- func (r ThresholdRule) Validate(value interface{}) error {
 
- 	value, isNil := Indirect(value)
 
- 	if isNil || IsEmpty(value) {
 
- 		return nil
 
- 	}
 
- 	rv := reflect.ValueOf(r.threshold)
 
- 	switch rv.Kind() {
 
- 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 
- 		v, err := ToInt(value)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		if r.compareInt(rv.Int(), v) {
 
- 			return nil
 
- 		}
 
- 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
 
- 		v, err := ToUint(value)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		if r.compareUint(rv.Uint(), v) {
 
- 			return nil
 
- 		}
 
- 	case reflect.Float32, reflect.Float64:
 
- 		v, err := ToFloat(value)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		if r.compareFloat(rv.Float(), v) {
 
- 			return nil
 
- 		}
 
- 	case reflect.Struct:
 
- 		t, ok := r.threshold.(time.Time)
 
- 		if !ok {
 
- 			return fmt.Errorf("type not supported: %v", rv.Type())
 
- 		}
 
- 		v, ok := value.(time.Time)
 
- 		if !ok {
 
- 			return fmt.Errorf("cannot convert %v to time.Time", reflect.TypeOf(value))
 
- 		}
 
- 		if v.IsZero() || r.compareTime(t, v) {
 
- 			return nil
 
- 		}
 
- 	default:
 
- 		return fmt.Errorf("type not supported: %v", rv.Type())
 
- 	}
 
- 	return r.err.SetParams(map[string]interface{}{"threshold": r.threshold})
 
- }
 
- // Error sets the error message for the rule.
 
- func (r ThresholdRule) Error(message string) ThresholdRule {
 
- 	r.err = r.err.SetMessage(message)
 
- 	return r
 
- }
 
- // ErrorObject sets the error struct for the rule.
 
- func (r ThresholdRule) ErrorObject(err Error) ThresholdRule {
 
- 	r.err = err
 
- 	return r
 
- }
 
- func (r ThresholdRule) compareInt(threshold, value int64) bool {
 
- 	switch r.operator {
 
- 	case greaterThan:
 
- 		return value > threshold
 
- 	case greaterEqualThan:
 
- 		return value >= threshold
 
- 	case lessThan:
 
- 		return value < threshold
 
- 	default:
 
- 		return value <= threshold
 
- 	}
 
- }
 
- func (r ThresholdRule) compareUint(threshold, value uint64) bool {
 
- 	switch r.operator {
 
- 	case greaterThan:
 
- 		return value > threshold
 
- 	case greaterEqualThan:
 
- 		return value >= threshold
 
- 	case lessThan:
 
- 		return value < threshold
 
- 	default:
 
- 		return value <= threshold
 
- 	}
 
- }
 
- func (r ThresholdRule) compareFloat(threshold, value float64) bool {
 
- 	switch r.operator {
 
- 	case greaterThan:
 
- 		return value > threshold
 
- 	case greaterEqualThan:
 
- 		return value >= threshold
 
- 	case lessThan:
 
- 		return value < threshold
 
- 	default:
 
- 		return value <= threshold
 
- 	}
 
- }
 
- func (r ThresholdRule) compareTime(threshold, value time.Time) bool {
 
- 	switch r.operator {
 
- 	case greaterThan:
 
- 		return value.After(threshold)
 
- 	case greaterEqualThan:
 
- 		return value.After(threshold) || value.Equal(threshold)
 
- 	case lessThan:
 
- 		return value.Before(threshold)
 
- 	default:
 
- 		return value.Before(threshold) || value.Equal(threshold)
 
- 	}
 
- }
 
 
  |