OSDN Git Service

new repo
[bytom/vapor.git] / vendor / gopkg.in / go-playground / validator.v9 / validator_instance.go
1 package validator
2
3 import (
4         "context"
5         "errors"
6         "fmt"
7         "reflect"
8         "strings"
9         "sync"
10         "time"
11
12         ut "github.com/go-playground/universal-translator"
13 )
14
15 const (
16         defaultTagName     = "validate"
17         utf8HexComma       = "0x2C"
18         utf8Pipe           = "0x7C"
19         tagSeparator       = ","
20         orSeparator        = "|"
21         tagKeySeparator    = "="
22         structOnlyTag      = "structonly"
23         noStructLevelTag   = "nostructlevel"
24         omitempty          = "omitempty"
25         isdefault          = "isdefault"
26         skipValidationTag  = "-"
27         diveTag            = "dive"
28         requiredTag        = "required"
29         namespaceSeparator = "."
30         leftBracket        = "["
31         rightBracket       = "]"
32         restrictedTagChars = ".[],|=+()`~!@#$%^&*\\\"/?<>{}"
33         restrictedAliasErr = "Alias '%s' either contains restricted characters or is the same as a restricted tag needed for normal operation"
34         restrictedTagErr   = "Tag '%s' either contains restricted characters or is the same as a restricted tag needed for normal operation"
35 )
36
37 var (
38         timeType      = reflect.TypeOf(time.Time{})
39         defaultCField = &cField{namesEqual: true}
40 )
41
42 // FilterFunc is the type used to filter fields using
43 // StructFiltered(...) function.
44 // returning true results in the field being filtered/skiped from
45 // validation
46 type FilterFunc func(ns []byte) bool
47
48 // CustomTypeFunc allows for overriding or adding custom field type handler functions
49 // field = field value of the type to return a value to be validated
50 // example Valuer from sql drive see https://golang.org/src/database/sql/driver/types.go?s=1210:1293#L29
51 type CustomTypeFunc func(field reflect.Value) interface{}
52
53 // TagNameFunc allows for adding of a custom tag name parser
54 type TagNameFunc func(field reflect.StructField) string
55
56 // Validate contains the validator settings and cache
57 type Validate struct {
58         tagName          string
59         pool             *sync.Pool
60         hasCustomFuncs   bool
61         hasTagNameFunc   bool
62         tagNameFunc      TagNameFunc
63         structLevelFuncs map[reflect.Type]StructLevelFuncCtx
64         customFuncs      map[reflect.Type]CustomTypeFunc
65         aliases          map[string]string
66         validations      map[string]FuncCtx
67         transTagFunc     map[ut.Translator]map[string]TranslationFunc // map[<locale>]map[<tag>]TranslationFunc
68         tagCache         *tagCache
69         structCache      *structCache
70 }
71
72 // New returns a new instacne of 'validate' with sane defaults.
73 func New() *Validate {
74
75         tc := new(tagCache)
76         tc.m.Store(make(map[string]*cTag))
77
78         sc := new(structCache)
79         sc.m.Store(make(map[reflect.Type]*cStruct))
80
81         v := &Validate{
82                 tagName:     defaultTagName,
83                 aliases:     make(map[string]string, len(bakedInAliases)),
84                 validations: make(map[string]FuncCtx, len(bakedInValidators)),
85                 tagCache:    tc,
86                 structCache: sc,
87         }
88
89         // must copy alias validators for separate validations to be used in each validator instance
90         for k, val := range bakedInAliases {
91                 v.RegisterAlias(k, val)
92         }
93
94         // must copy validators for separate validations to be used in each instance
95         for k, val := range bakedInValidators {
96
97                 // no need to error check here, baked in will always be valid
98                 v.registerValidation(k, wrapFunc(val), true)
99         }
100
101         v.pool = &sync.Pool{
102                 New: func() interface{} {
103                         return &validate{
104                                 v:        v,
105                                 ns:       make([]byte, 0, 64),
106                                 actualNs: make([]byte, 0, 64),
107                                 misc:     make([]byte, 32),
108                         }
109                 },
110         }
111
112         return v
113 }
114
115 // SetTagName allows for changing of the default tag name of 'validate'
116 func (v *Validate) SetTagName(name string) {
117         v.tagName = name
118 }
119
120 // RegisterTagNameFunc registers a function to get another name from the
121 // StructField eg. the JSON name
122 func (v *Validate) RegisterTagNameFunc(fn TagNameFunc) {
123         v.tagNameFunc = fn
124         v.hasTagNameFunc = true
125 }
126
127 // RegisterValidation adds a validation with the given tag
128 //
129 // NOTES:
130 // - if the key already exists, the previous validation function will be replaced.
131 // - this method is not thread-safe it is intended that these all be registered prior to any validation
132 func (v *Validate) RegisterValidation(tag string, fn Func) error {
133         return v.RegisterValidationCtx(tag, wrapFunc(fn))
134 }
135
136 // RegisterValidationCtx does the same as RegisterValidation on accepts a FuncCtx validation
137 // allowing context.Context validation support.
138 func (v *Validate) RegisterValidationCtx(tag string, fn FuncCtx) error {
139         return v.registerValidation(tag, fn, false)
140 }
141
142 func (v *Validate) registerValidation(tag string, fn FuncCtx, bakedIn bool) error {
143
144         if len(tag) == 0 {
145                 return errors.New("Function Key cannot be empty")
146         }
147
148         if fn == nil {
149                 return errors.New("Function cannot be empty")
150         }
151
152         _, ok := restrictedTags[tag]
153
154         if !bakedIn && (ok || strings.ContainsAny(tag, restrictedTagChars)) {
155                 panic(fmt.Sprintf(restrictedTagErr, tag))
156         }
157
158         v.validations[tag] = fn
159
160         return nil
161 }
162
163 // RegisterAlias registers a mapping of a single validation tag that
164 // defines a common or complex set of validation(s) to simplify adding validation
165 // to structs.
166 //
167 // NOTE: this function is not thread-safe it is intended that these all be registered prior to any validation
168 func (v *Validate) RegisterAlias(alias, tags string) {
169
170         _, ok := restrictedTags[alias]
171
172         if ok || strings.ContainsAny(alias, restrictedTagChars) {
173                 panic(fmt.Sprintf(restrictedAliasErr, alias))
174         }
175
176         v.aliases[alias] = tags
177 }
178
179 // RegisterStructValidation registers a StructLevelFunc against a number of types.
180 //
181 // NOTE:
182 // - this method is not thread-safe it is intended that these all be registered prior to any validation
183 func (v *Validate) RegisterStructValidation(fn StructLevelFunc, types ...interface{}) {
184         v.RegisterStructValidationCtx(wrapStructLevelFunc(fn), types...)
185 }
186
187 // RegisterStructValidationCtx registers a StructLevelFuncCtx against a number of types and allows passing
188 // of contextual validation information via context.Context.
189 //
190 // NOTE:
191 // - this method is not thread-safe it is intended that these all be registered prior to any validation
192 func (v *Validate) RegisterStructValidationCtx(fn StructLevelFuncCtx, types ...interface{}) {
193
194         if v.structLevelFuncs == nil {
195                 v.structLevelFuncs = make(map[reflect.Type]StructLevelFuncCtx)
196         }
197
198         for _, t := range types {
199                 v.structLevelFuncs[reflect.TypeOf(t)] = fn
200         }
201 }
202
203 // RegisterCustomTypeFunc registers a CustomTypeFunc against a number of types
204 //
205 // NOTE: this method is not thread-safe it is intended that these all be registered prior to any validation
206 func (v *Validate) RegisterCustomTypeFunc(fn CustomTypeFunc, types ...interface{}) {
207
208         if v.customFuncs == nil {
209                 v.customFuncs = make(map[reflect.Type]CustomTypeFunc)
210         }
211
212         for _, t := range types {
213                 v.customFuncs[reflect.TypeOf(t)] = fn
214         }
215
216         v.hasCustomFuncs = true
217 }
218
219 // RegisterTranslation registers translations against the provided tag.
220 func (v *Validate) RegisterTranslation(tag string, trans ut.Translator, registerFn RegisterTranslationsFunc, translationFn TranslationFunc) (err error) {
221
222         if v.transTagFunc == nil {
223                 v.transTagFunc = make(map[ut.Translator]map[string]TranslationFunc)
224         }
225
226         if err = registerFn(trans); err != nil {
227                 return
228         }
229
230         m, ok := v.transTagFunc[trans]
231         if !ok {
232                 m = make(map[string]TranslationFunc)
233                 v.transTagFunc[trans] = m
234         }
235
236         m[tag] = translationFn
237
238         return
239 }
240
241 // Struct validates a structs exposed fields, and automatically validates nested structs, unless otherwise specified.
242 //
243 // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
244 // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
245 func (v *Validate) Struct(s interface{}) error {
246         return v.StructCtx(context.Background(), s)
247 }
248
249 // StructCtx validates a structs exposed fields, and automatically validates nested structs, unless otherwise specified
250 // and also allows passing of context.Context for contextual validation information.
251 //
252 // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
253 // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
254 func (v *Validate) StructCtx(ctx context.Context, s interface{}) (err error) {
255
256         val := reflect.ValueOf(s)
257         top := val
258
259         if val.Kind() == reflect.Ptr && !val.IsNil() {
260                 val = val.Elem()
261         }
262
263         if val.Kind() != reflect.Struct || val.Type() == timeType {
264                 return &InvalidValidationError{Type: reflect.TypeOf(s)}
265         }
266
267         // good to validate
268         vd := v.pool.Get().(*validate)
269         vd.top = top
270         vd.isPartial = false
271         // vd.hasExcludes = false // only need to reset in StructPartial and StructExcept
272
273         vd.validateStruct(ctx, top, val, val.Type(), vd.ns[0:0], vd.actualNs[0:0], nil)
274
275         if len(vd.errs) > 0 {
276                 err = vd.errs
277                 vd.errs = nil
278         }
279
280         v.pool.Put(vd)
281
282         return
283 }
284
285 // StructFiltered validates a structs exposed fields, that pass the FilterFunc check and automatically validates
286 // nested structs, unless otherwise specified.
287 //
288 // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
289 // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
290 func (v *Validate) StructFiltered(s interface{}, fn FilterFunc) error {
291         return v.StructFilteredCtx(context.Background(), s, fn)
292 }
293
294 // StructFilteredCtx validates a structs exposed fields, that pass the FilterFunc check and automatically validates
295 // nested structs, unless otherwise specified and also allows passing of contextual validation information via
296 // context.Context
297 //
298 // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
299 // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
300 func (v *Validate) StructFilteredCtx(ctx context.Context, s interface{}, fn FilterFunc) (err error) {
301         val := reflect.ValueOf(s)
302         top := val
303
304         if val.Kind() == reflect.Ptr && !val.IsNil() {
305                 val = val.Elem()
306         }
307
308         if val.Kind() != reflect.Struct || val.Type() == timeType {
309                 return &InvalidValidationError{Type: reflect.TypeOf(s)}
310         }
311
312         // good to validate
313         vd := v.pool.Get().(*validate)
314         vd.top = top
315         vd.isPartial = true
316         vd.ffn = fn
317         // vd.hasExcludes = false // only need to reset in StructPartial and StructExcept
318
319         vd.validateStruct(context.Background(), top, val, val.Type(), vd.ns[0:0], vd.actualNs[0:0], nil)
320
321         if len(vd.errs) > 0 {
322                 err = vd.errs
323                 vd.errs = nil
324         }
325
326         v.pool.Put(vd)
327
328         return
329 }
330
331 // StructPartial validates the fields passed in only, ignoring all others.
332 // Fields may be provided in a namespaced fashion relative to the  struct provided
333 // eg. NestedStruct.Field or NestedArrayField[0].Struct.Name
334 //
335 // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
336 // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
337 func (v *Validate) StructPartial(s interface{}, fields ...string) error {
338         return v.StructPartialCtx(context.Background(), s, fields...)
339 }
340
341 // StructPartialCtx validates the fields passed in only, ignoring all others and allows passing of contextual
342 // validation validation information via context.Context
343 // Fields may be provided in a namespaced fashion relative to the  struct provided
344 // eg. NestedStruct.Field or NestedArrayField[0].Struct.Name
345 //
346 // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
347 // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
348 func (v *Validate) StructPartialCtx(ctx context.Context, s interface{}, fields ...string) (err error) {
349         val := reflect.ValueOf(s)
350         top := val
351
352         if val.Kind() == reflect.Ptr && !val.IsNil() {
353                 val = val.Elem()
354         }
355
356         if val.Kind() != reflect.Struct || val.Type() == timeType {
357                 return &InvalidValidationError{Type: reflect.TypeOf(s)}
358         }
359
360         // good to validate
361         vd := v.pool.Get().(*validate)
362         vd.top = top
363         vd.isPartial = true
364         vd.ffn = nil
365         vd.hasExcludes = false
366         vd.includeExclude = make(map[string]struct{})
367
368         typ := val.Type()
369         name := typ.Name()
370
371         if fields != nil {
372                 for _, k := range fields {
373
374                         flds := strings.Split(k, namespaceSeparator)
375                         if len(flds) > 0 {
376
377                                 vd.misc = append(vd.misc[0:0], name...)
378                                 vd.misc = append(vd.misc, '.')
379
380                                 for _, s := range flds {
381
382                                         idx := strings.Index(s, leftBracket)
383
384                                         if idx != -1 {
385                                                 for idx != -1 {
386                                                         vd.misc = append(vd.misc, s[:idx]...)
387                                                         vd.includeExclude[string(vd.misc)] = struct{}{}
388
389                                                         idx2 := strings.Index(s, rightBracket)
390                                                         idx2++
391                                                         vd.misc = append(vd.misc, s[idx:idx2]...)
392                                                         vd.includeExclude[string(vd.misc)] = struct{}{}
393                                                         s = s[idx2:]
394                                                         idx = strings.Index(s, leftBracket)
395                                                 }
396                                         } else {
397
398                                                 vd.misc = append(vd.misc, s...)
399                                                 vd.includeExclude[string(vd.misc)] = struct{}{}
400                                         }
401
402                                         vd.misc = append(vd.misc, '.')
403                                 }
404                         }
405                 }
406         }
407
408         vd.validateStruct(ctx, top, val, typ, vd.ns[0:0], vd.actualNs[0:0], nil)
409
410         if len(vd.errs) > 0 {
411                 err = vd.errs
412                 vd.errs = nil
413         }
414
415         v.pool.Put(vd)
416
417         return
418 }
419
420 // StructExcept validates all fields except the ones passed in.
421 // Fields may be provided in a namespaced fashion relative to the  struct provided
422 // i.e. NestedStruct.Field or NestedArrayField[0].Struct.Name
423 //
424 // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
425 // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
426 func (v *Validate) StructExcept(s interface{}, fields ...string) error {
427         return v.StructExceptCtx(context.Background(), s, fields...)
428 }
429
430 // StructExceptCtx validates all fields except the ones passed in and allows passing of contextual
431 // validation validation information via context.Context
432 // Fields may be provided in a namespaced fashion relative to the  struct provided
433 // i.e. NestedStruct.Field or NestedArrayField[0].Struct.Name
434 //
435 // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
436 // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
437 func (v *Validate) StructExceptCtx(ctx context.Context, s interface{}, fields ...string) (err error) {
438         val := reflect.ValueOf(s)
439         top := val
440
441         if val.Kind() == reflect.Ptr && !val.IsNil() {
442                 val = val.Elem()
443         }
444
445         if val.Kind() != reflect.Struct || val.Type() == timeType {
446                 return &InvalidValidationError{Type: reflect.TypeOf(s)}
447         }
448
449         // good to validate
450         vd := v.pool.Get().(*validate)
451         vd.top = top
452         vd.isPartial = true
453         vd.ffn = nil
454         vd.hasExcludes = true
455         vd.includeExclude = make(map[string]struct{})
456
457         typ := val.Type()
458         name := typ.Name()
459
460         for _, key := range fields {
461
462                 vd.misc = vd.misc[0:0]
463
464                 if len(name) > 0 {
465                         vd.misc = append(vd.misc, name...)
466                         vd.misc = append(vd.misc, '.')
467                 }
468
469                 vd.misc = append(vd.misc, key...)
470                 vd.includeExclude[string(vd.misc)] = struct{}{}
471         }
472
473         vd.validateStruct(ctx, top, val, typ, vd.ns[0:0], vd.actualNs[0:0], nil)
474
475         if len(vd.errs) > 0 {
476                 err = vd.errs
477                 vd.errs = nil
478         }
479
480         v.pool.Put(vd)
481
482         return
483 }
484
485 // Var validates a single variable using tag style validation.
486 // eg.
487 // var i int
488 // validate.Var(i, "gt=1,lt=10")
489 //
490 // WARNING: a struct can be passed for validation eg. time.Time is a struct or
491 // if you have a custom type and have registered a custom type handler, so must
492 // allow it; however unforseen validations will occur if trying to validate a
493 // struct that is meant to be passed to 'validate.Struct'
494 //
495 // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
496 // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
497 // validate Array, Slice and maps fields which may contain more than one error
498 func (v *Validate) Var(field interface{}, tag string) error {
499         return v.VarCtx(context.Background(), field, tag)
500 }
501
502 // VarCtx validates a single variable using tag style validation and allows passing of contextual
503 // validation validation information via context.Context.
504 // eg.
505 // var i int
506 // validate.Var(i, "gt=1,lt=10")
507 //
508 // WARNING: a struct can be passed for validation eg. time.Time is a struct or
509 // if you have a custom type and have registered a custom type handler, so must
510 // allow it; however unforseen validations will occur if trying to validate a
511 // struct that is meant to be passed to 'validate.Struct'
512 //
513 // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
514 // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
515 // validate Array, Slice and maps fields which may contain more than one error
516 func (v *Validate) VarCtx(ctx context.Context, field interface{}, tag string) (err error) {
517         if len(tag) == 0 || tag == skipValidationTag {
518                 return nil
519         }
520
521         // find cached tag
522         ctag, ok := v.tagCache.Get(tag)
523         if !ok {
524                 v.tagCache.lock.Lock()
525                 defer v.tagCache.lock.Unlock()
526
527                 // could have been multiple trying to access, but once first is done this ensures tag
528                 // isn't parsed again.
529                 ctag, ok = v.tagCache.Get(tag)
530                 if !ok {
531                         ctag, _ = v.parseFieldTagsRecursive(tag, "", "", false)
532                         v.tagCache.Set(tag, ctag)
533                 }
534         }
535
536         val := reflect.ValueOf(field)
537
538         vd := v.pool.Get().(*validate)
539         vd.top = val
540         vd.isPartial = false
541
542         vd.traverseField(ctx, val, val, vd.ns[0:0], vd.actualNs[0:0], defaultCField, ctag)
543
544         if len(vd.errs) > 0 {
545                 err = vd.errs
546                 vd.errs = nil
547         }
548
549         v.pool.Put(vd)
550
551         return
552 }
553
554 // VarWithValue validates a single variable, against another variable/field's value using tag style validation
555 // eg.
556 // s1 := "abcd"
557 // s2 := "abcd"
558 // validate.VarWithValue(s1, s2, "eqcsfield") // returns true
559 //
560 // WARNING: a struct can be passed for validation eg. time.Time is a struct or
561 // if you have a custom type and have registered a custom type handler, so must
562 // allow it; however unforseen validations will occur if trying to validate a
563 // struct that is meant to be passed to 'validate.Struct'
564 //
565 // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
566 // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
567 // validate Array, Slice and maps fields which may contain more than one error
568 func (v *Validate) VarWithValue(field interface{}, other interface{}, tag string) error {
569         return v.VarWithValueCtx(context.Background(), field, other, tag)
570 }
571
572 // VarWithValueCtx validates a single variable, against another variable/field's value using tag style validation and
573 // allows passing of contextual validation validation information via context.Context.
574 // eg.
575 // s1 := "abcd"
576 // s2 := "abcd"
577 // validate.VarWithValue(s1, s2, "eqcsfield") // returns true
578 //
579 // WARNING: a struct can be passed for validation eg. time.Time is a struct or
580 // if you have a custom type and have registered a custom type handler, so must
581 // allow it; however unforseen validations will occur if trying to validate a
582 // struct that is meant to be passed to 'validate.Struct'
583 //
584 // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
585 // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
586 // validate Array, Slice and maps fields which may contain more than one error
587 func (v *Validate) VarWithValueCtx(ctx context.Context, field interface{}, other interface{}, tag string) (err error) {
588         if len(tag) == 0 || tag == skipValidationTag {
589                 return nil
590         }
591
592         // find cached tag
593         ctag, ok := v.tagCache.Get(tag)
594         if !ok {
595                 v.tagCache.lock.Lock()
596                 defer v.tagCache.lock.Unlock()
597
598                 // could have been multiple trying to access, but once first is done this ensures tag
599                 // isn't parsed again.
600                 ctag, ok = v.tagCache.Get(tag)
601                 if !ok {
602                         ctag, _ = v.parseFieldTagsRecursive(tag, "", "", false)
603                         v.tagCache.Set(tag, ctag)
604                 }
605         }
606
607         otherVal := reflect.ValueOf(other)
608
609         vd := v.pool.Get().(*validate)
610         vd.top = otherVal
611         vd.isPartial = false
612
613         vd.traverseField(ctx, otherVal, reflect.ValueOf(field), vd.ns[0:0], vd.actualNs[0:0], defaultCField, ctag)
614
615         if len(vd.errs) > 0 {
616                 err = vd.errs
617                 vd.errs = nil
618         }
619
620         v.pool.Put(vd)
621
622         return
623 }