123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- package valid
- import (
- "fmt"
- "reflect"
- "time"
- )
- var (
-
- ErrMinGreaterEqualThanRequired = NewError("validation_min_greater_equal_than_required", "must be no less than {{.threshold}}")
-
- ErrMaxLessEqualThanRequired = NewError("validation_max_less_equal_than_required", "must be no greater than {{.threshold}}")
-
- ErrMinGreaterThanRequired = NewError("validation_min_greater_than_required", "must be greater than {{.threshold}}")
-
- ErrMaxLessThanRequired = NewError("validation_max_less_than_required", "must be less than {{.threshold}}")
- )
- type ThresholdRule struct {
- threshold interface{}
- operator int
- err Error
- }
- const (
- greaterThan = iota
- greaterEqualThan
- lessThan
- lessEqualThan
- )
- func Min(min interface{}) ThresholdRule {
- return ThresholdRule{
- threshold: min,
- operator: greaterEqualThan,
- err: ErrMinGreaterEqualThanRequired,
- }
- }
- func Max(max interface{}) ThresholdRule {
- return ThresholdRule{
- threshold: max,
- operator: lessEqualThan,
- err: ErrMaxLessEqualThanRequired,
- }
- }
- 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
- }
- 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})
- }
- func (r ThresholdRule) Error(message string) ThresholdRule {
- r.err = r.err.SetMessage(message)
- return r
- }
- 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)
- }
- }
|