github.com/blend/go-sdk@v1.20220411.3/validate/any.go (about) 1 /* 2 3 Copyright (c) 2022 - Present. Blend Labs, Inc. All rights reserved 4 Use of this source code is governed by a MIT license that can be found in the LICENSE file. 5 6 */ 7 8 package validate 9 10 import ( 11 "reflect" 12 13 "github.com/blend/go-sdk/ex" 14 ) 15 16 // Basic errors 17 const ( 18 ErrZero ex.Class = "object should be its default value or unset" 19 ErrNotZero ex.Class = "object should not be its default value or unset" 20 ErrRequired ex.Class = "field is required" 21 ErrForbidden ex.Class = "field is forbidden" 22 ErrEmpty ex.Class = "object should be empty" 23 ErrNotEmpty ex.Class = "object should not be empty" 24 ErrLen ex.Class = "object should have a given length" 25 ErrNil ex.Class = "object should be nil" 26 ErrNotNil ex.Class = "object should not be nil" 27 ErrEquals ex.Class = "objects should be equal" 28 ErrNotEquals ex.Class = "objects should not be equal" 29 ErrAllowed ex.Class = "objects should be one of a given set of allowed values" 30 ErrDisallowed ex.Class = "objects should not be one of a given set of disallowed values" 31 ) 32 33 // Any returns a new AnyRefValidators. 34 // AnyRef can be used to validate any type, but will be more limited 35 // than using type specific validators. 36 func Any(obj interface{}) AnyValidators { 37 return AnyValidators{Obj: obj} 38 } 39 40 // AnyValidators are validators for the empty interface{}. 41 type AnyValidators struct { 42 Obj interface{} 43 } 44 45 // Forbidden mirrors Zero but uses a specific error. 46 // This is useful if you want to have more aggressive failure cases. 47 func (a AnyValidators) Forbidden() Validator { 48 return func() error { 49 if err := a.Zero()(); err != nil { 50 return Error(ErrForbidden, a.Obj) 51 } 52 return nil 53 } 54 } 55 56 // Required mirrors NotZero but uses a specific error. 57 // This is useful if you want to have more aggressive failure cases. 58 func (a AnyValidators) Required() Validator { 59 return func() error { 60 if err := a.NotZero()(); err != nil { 61 return Error(ErrRequired, a.Obj) 62 } 63 return nil 64 } 65 } 66 67 // Zero returns a validator that asserts an object is it's zero value. 68 // This nil for pointers, slices, maps, channels. 69 // And whatever equality passes for everything else with it's initialized value. 70 // Note: this method uses reflect.Zero, there are faster .Zero evaluators 71 // for the relevant numeric types. 72 func (a AnyValidators) Zero() Validator { 73 return func() error { 74 if a.Obj == nil { 75 return nil 76 } 77 78 zero := reflect.Zero(reflect.TypeOf(a.Obj)).Interface() 79 if verr := a.Equals(zero)(); verr == nil { 80 return nil 81 } 82 return Error(ErrZero, a.Obj) 83 } 84 } 85 86 // NotZero returns a validator that a given field is set. 87 // It will return an error if the field is unset. 88 // Note: this method uses reflect.Zero, there are faster .NotZero evaluators 89 // for the relevant numeric types. 90 func (a AnyValidators) NotZero() Validator { 91 return func() error { 92 if err := a.Zero()(); err == nil { 93 return Error(ErrNotZero, a.Obj) 94 } 95 return nil 96 } 97 } 98 99 // Empty returns if a slice, map or channel is empty. 100 // It will error if the object is not a slice, map or channel. 101 func (a AnyValidators) Empty() Validator { 102 return func() error { 103 objLen, err := GetLength(a.Obj) 104 if err != nil { 105 return err 106 } 107 if objLen == 0 { 108 return nil 109 } 110 return Error(ErrEmpty, a.Obj) 111 } 112 } 113 114 // NotEmpty returns if a slice, map or channel is not empty. 115 // It will error if the object is not a slice, map or channel. 116 func (a AnyValidators) NotEmpty() Validator { 117 return func() error { 118 objLen, err := GetLength(a.Obj) 119 if err != nil { 120 return err 121 } 122 if objLen > 0 { 123 return nil 124 } 125 return Error(ErrNotEmpty, a.Obj) 126 } 127 } 128 129 // Len validates the length is a given value. 130 func (a AnyValidators) Len(length int) Validator { 131 return func() error { 132 objLen, err := GetLength(a.Obj) 133 if err != nil { 134 return err 135 } 136 if objLen == length { 137 return nil 138 } 139 return Error(ErrLen, a.Obj) 140 } 141 } 142 143 // Nil validates the object is nil. 144 func (a AnyValidators) Nil() Validator { 145 return func() error { 146 if IsNil(a.Obj) { 147 return nil 148 } 149 return Error(ErrNil, a.Obj) 150 } 151 } 152 153 // NotNil validates the object is not nil. 154 // It also validates that the object is not an unset pointer. 155 func (a AnyValidators) NotNil() Validator { 156 return func() error { 157 if verr := a.Nil()(); verr != nil { 158 return nil 159 } 160 return Error(ErrNotNil, a.Obj) 161 } 162 } 163 164 // Equals validates an object equals another object. 165 func (a AnyValidators) Equals(expected interface{}) Validator { 166 return func() error { 167 actual := a.Obj 168 169 if IsNil(expected) && IsNil(actual) { 170 return nil 171 } 172 if (IsNil(expected) && !IsNil(actual)) || (!IsNil(expected) && IsNil(actual)) { 173 return Error(ErrEquals, a.Obj) 174 } 175 176 actualType := reflect.TypeOf(actual) 177 if actualType == nil { 178 return Error(ErrEquals, a.Obj) 179 } 180 expectedValue := reflect.ValueOf(expected) 181 if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) { 182 if !reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual) { 183 return Error(ErrEquals, a.Obj) 184 } 185 } 186 187 if !reflect.DeepEqual(expected, actual) { 188 return Error(ErrEquals, a.Obj) 189 } 190 return nil 191 } 192 } 193 194 // NotEquals validates an object does not equal another object. 195 func (a AnyValidators) NotEquals(expected interface{}) Validator { 196 return func() error { 197 if verr := a.Equals(expected)(); verr != nil { 198 return nil 199 } 200 return Error(ErrNotEquals, a.Obj) 201 } 202 } 203 204 // Allow validates a field is one of a given set of allowed values. 205 func (a AnyValidators) Allow(values ...interface{}) Validator { 206 return func() error { 207 for _, expected := range values { 208 if verr := a.Equals(expected)(); verr == nil { 209 return nil 210 } 211 } 212 return Error(ErrAllowed, a.Obj) 213 } 214 } 215 216 // Disallow validates a field is one of a given set of allowed values. 217 func (a AnyValidators) Disallow(values ...interface{}) Validator { 218 return func() error { 219 for _, expected := range values { 220 if verr := a.Equals(expected)(); verr == nil { 221 return Error(ErrDisallowed, a.Obj) 222 } 223 } 224 return nil 225 } 226 }