1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package validate
16
17 import (
18 "fmt"
19 "reflect"
20 "unicode/utf8"
21
22 "github.com/go-openapi/swag"
23 "k8s.io/kube-openapi/pkg/validation/errors"
24 "k8s.io/kube-openapi/pkg/validation/strfmt"
25 )
26
27
28 func Enum(path, in string, data interface{}, enum interface{}) *errors.Validation {
29 val := reflect.ValueOf(enum)
30 if val.Kind() != reflect.Slice {
31 return nil
32 }
33
34 var values []interface{}
35 for i := 0; i < val.Len(); i++ {
36 ele := val.Index(i)
37 enumValue := ele.Interface()
38 if data != nil {
39 if reflect.DeepEqual(data, enumValue) {
40 return nil
41 }
42 actualType := reflect.TypeOf(enumValue)
43 if actualType == nil {
44 continue
45 }
46 expectedValue := reflect.ValueOf(data)
47 if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) {
48
49 if reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), enumValue) {
50 return nil
51 }
52 }
53 }
54 values = append(values, enumValue)
55 }
56 return errors.EnumFail(path, in, data, values)
57 }
58
59
60 func MinItems(path, in string, size, min int64) *errors.Validation {
61 if size < min {
62 return errors.TooFewItems(path, in, min, size)
63 }
64 return nil
65 }
66
67
68 func MaxItems(path, in string, size, max int64) *errors.Validation {
69 if size > max {
70 return errors.TooManyItems(path, in, max, size)
71 }
72 return nil
73 }
74
75
76 func UniqueItems(path, in string, data interface{}) *errors.Validation {
77 val := reflect.ValueOf(data)
78 if val.Kind() != reflect.Slice {
79 return nil
80 }
81 var unique []interface{}
82 for i := 0; i < val.Len(); i++ {
83 v := val.Index(i).Interface()
84 for _, u := range unique {
85 if reflect.DeepEqual(v, u) {
86 return errors.DuplicateItems(path, in)
87 }
88 }
89 unique = append(unique, v)
90 }
91 return nil
92 }
93
94
95 func MinLength(path, in, data string, minLength int64) *errors.Validation {
96 strLen := int64(utf8.RuneCount([]byte(data)))
97 if strLen < minLength {
98 return errors.TooShort(path, in, minLength, data)
99 }
100 return nil
101 }
102
103
104 func MaxLength(path, in, data string, maxLength int64) *errors.Validation {
105 strLen := int64(utf8.RuneCount([]byte(data)))
106 if strLen > maxLength {
107 return errors.TooLong(path, in, maxLength, data)
108 }
109 return nil
110 }
111
112
113 func Required(path, in string, data interface{}) *errors.Validation {
114 val := reflect.ValueOf(data)
115 if val.IsValid() {
116 if reflect.DeepEqual(reflect.Zero(val.Type()).Interface(), val.Interface()) {
117 return errors.Required(path, in)
118 }
119 return nil
120 }
121 return errors.Required(path, in)
122 }
123
124
125 func Pattern(path, in, data, pattern string) *errors.Validation {
126 re, err := compileRegexp(pattern)
127 if err != nil {
128 return errors.FailedPattern(path, in, fmt.Sprintf("%s, but pattern is invalid: %s", pattern, err.Error()), data)
129 }
130 if !re.MatchString(data) {
131 return errors.FailedPattern(path, in, pattern, data)
132 }
133 return nil
134 }
135
136
137 func MaximumInt(path, in string, data, max int64, exclusive bool) *errors.Validation {
138 if (!exclusive && data > max) || (exclusive && data >= max) {
139 return errors.ExceedsMaximumInt(path, in, max, exclusive, data)
140 }
141 return nil
142 }
143
144
145 func MaximumUint(path, in string, data, max uint64, exclusive bool) *errors.Validation {
146 if (!exclusive && data > max) || (exclusive && data >= max) {
147 return errors.ExceedsMaximumUint(path, in, max, exclusive, data)
148 }
149 return nil
150 }
151
152
153 func Maximum(path, in string, data, max float64, exclusive bool) *errors.Validation {
154 if (!exclusive && data > max) || (exclusive && data >= max) {
155 return errors.ExceedsMaximum(path, in, max, exclusive, data)
156 }
157 return nil
158 }
159
160
161 func Minimum(path, in string, data, min float64, exclusive bool) *errors.Validation {
162 if (!exclusive && data < min) || (exclusive && data <= min) {
163 return errors.ExceedsMinimum(path, in, min, exclusive, data)
164 }
165 return nil
166 }
167
168
169 func MinimumInt(path, in string, data, min int64, exclusive bool) *errors.Validation {
170 if (!exclusive && data < min) || (exclusive && data <= min) {
171 return errors.ExceedsMinimumInt(path, in, min, exclusive, data)
172 }
173 return nil
174 }
175
176
177 func MinimumUint(path, in string, data, min uint64, exclusive bool) *errors.Validation {
178 if (!exclusive && data < min) || (exclusive && data <= min) {
179 return errors.ExceedsMinimumUint(path, in, min, exclusive, data)
180 }
181 return nil
182 }
183
184
185 func MultipleOf(path, in string, data, factor float64) *errors.Validation {
186
187 if factor <= 0 {
188 return errors.MultipleOfMustBePositive(path, in, factor)
189 }
190 var mult float64
191 if factor < 1 {
192 mult = 1 / factor * data
193 } else {
194 mult = data / factor
195 }
196 if !swag.IsFloat64AJSONInteger(mult) {
197 return errors.NotMultipleOf(path, in, factor, data)
198 }
199 return nil
200 }
201
202
203 func MultipleOfInt(path, in string, data int64, factor int64) *errors.Validation {
204
205 if factor <= 0 {
206 return errors.MultipleOfMustBePositive(path, in, factor)
207 }
208 mult := data / factor
209 if mult*factor != data {
210 return errors.NotMultipleOf(path, in, factor, data)
211 }
212 return nil
213 }
214
215
216 func MultipleOfUint(path, in string, data, factor uint64) *errors.Validation {
217
218 if factor == 0 {
219 return errors.MultipleOfMustBePositive(path, in, factor)
220 }
221 mult := data / factor
222 if mult*factor != data {
223 return errors.NotMultipleOf(path, in, factor, data)
224 }
225 return nil
226 }
227
228
229 func FormatOf(path, in, format, data string, registry strfmt.Registry) *errors.Validation {
230 if registry == nil {
231 registry = strfmt.Default
232 }
233 if ok := registry.ContainsName(format); !ok {
234 return errors.InvalidTypeName(format)
235 }
236 if ok := registry.Validates(format, data); !ok {
237 return errors.InvalidType(path, in, format, data)
238 }
239 return nil
240 }
241
242
243
244
245
246
247
248
249
250
251
252 func MaximumNativeType(path, in string, val interface{}, max float64, exclusive bool) *errors.Validation {
253 kind := reflect.ValueOf(val).Type().Kind()
254 switch kind {
255 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
256 value := valueHelp.asInt64(val)
257 return MaximumInt(path, in, value, int64(max), exclusive)
258 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
259 value := valueHelp.asUint64(val)
260 if max < 0 {
261 return errors.ExceedsMaximum(path, in, max, exclusive, val)
262 }
263 return MaximumUint(path, in, value, uint64(max), exclusive)
264 case reflect.Float32, reflect.Float64:
265 fallthrough
266 default:
267 value := valueHelp.asFloat64(val)
268 return Maximum(path, in, value, max, exclusive)
269 }
270 }
271
272
273
274
275
276
277
278
279
280
281
282 func MinimumNativeType(path, in string, val interface{}, min float64, exclusive bool) *errors.Validation {
283 kind := reflect.ValueOf(val).Type().Kind()
284 switch kind {
285 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
286 value := valueHelp.asInt64(val)
287 return MinimumInt(path, in, value, int64(min), exclusive)
288 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
289 value := valueHelp.asUint64(val)
290 if min < 0 {
291 return nil
292 }
293 return MinimumUint(path, in, value, uint64(min), exclusive)
294 case reflect.Float32, reflect.Float64:
295 fallthrough
296 default:
297 value := valueHelp.asFloat64(val)
298 return Minimum(path, in, value, min, exclusive)
299 }
300 }
301
302
303
304
305
306
307
308
309
310
311
312 func MultipleOfNativeType(path, in string, val interface{}, multipleOf float64) *errors.Validation {
313 kind := reflect.ValueOf(val).Type().Kind()
314 switch kind {
315 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
316 value := valueHelp.asInt64(val)
317 return MultipleOfInt(path, in, value, int64(multipleOf))
318 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
319 value := valueHelp.asUint64(val)
320 return MultipleOfUint(path, in, value, uint64(multipleOf))
321 case reflect.Float32, reflect.Float64:
322 fallthrough
323 default:
324 value := valueHelp.asFloat64(val)
325 return MultipleOf(path, in, value, multipleOf)
326 }
327 }
328
329
330
331
332
333 func IsValueValidAgainstRange(val interface{}, typeName, format, prefix, path string) error {
334 kind := reflect.ValueOf(val).Type().Kind()
335
336
337 stringRep := ""
338 switch kind {
339 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
340 stringRep = swag.FormatUint64(valueHelp.asUint64(val))
341 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
342 stringRep = swag.FormatInt64(valueHelp.asInt64(val))
343 case reflect.Float32, reflect.Float64:
344 stringRep = swag.FormatFloat64(valueHelp.asFloat64(val))
345 default:
346 return fmt.Errorf("%s value number range checking called with invalid (non numeric) val type in %s", prefix, path)
347 }
348
349 var errVal error
350
351 switch typeName {
352 case integerType:
353 switch format {
354 case integerFormatInt32:
355 _, errVal = swag.ConvertInt32(stringRep)
356 case integerFormatUInt32:
357 _, errVal = swag.ConvertUint32(stringRep)
358 case integerFormatUInt64:
359 _, errVal = swag.ConvertUint64(stringRep)
360 case integerFormatInt64:
361 fallthrough
362 default:
363 _, errVal = swag.ConvertInt64(stringRep)
364 }
365 case numberType:
366 fallthrough
367 default:
368 switch format {
369 case numberFormatFloat, numberFormatFloat32:
370 _, errVal = swag.ConvertFloat32(stringRep)
371 case numberFormatDouble, numberFormatFloat64:
372 fallthrough
373 default:
374
375
376 }
377 }
378 if errVal != nil {
379 if format != "" {
380 errVal = fmt.Errorf("%s value must be of type %s with format %s in %s", prefix, typeName, format, path)
381 } else {
382 errVal = fmt.Errorf("%s value must be of type %s (default format) in %s", prefix, typeName, path)
383 }
384 }
385 return errVal
386 }
387
View as plain text