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
21 "github.com/go-openapi/errors"
22 "github.com/go-openapi/spec"
23 "github.com/go-openapi/strfmt"
24 )
25
26
27 type EntityValidator interface {
28 Validate(interface{}) *Result
29 }
30
31 type valueValidator interface {
32 SetPath(path string)
33 Applies(interface{}, reflect.Kind) bool
34 Validate(interface{}) *Result
35 }
36
37 type itemsValidator struct {
38 items *spec.Items
39 root interface{}
40 path string
41 in string
42 validators [6]valueValidator
43 KnownFormats strfmt.Registry
44 Options *SchemaValidatorOptions
45 }
46
47 func newItemsValidator(path, in string, items *spec.Items, root interface{}, formats strfmt.Registry, opts *SchemaValidatorOptions) *itemsValidator {
48 if opts == nil {
49 opts = new(SchemaValidatorOptions)
50 }
51
52 var iv *itemsValidator
53 if opts.recycleValidators {
54 iv = pools.poolOfItemsValidators.BorrowValidator()
55 } else {
56 iv = new(itemsValidator)
57 }
58
59 iv.path = path
60 iv.in = in
61 iv.items = items
62 iv.root = root
63 iv.KnownFormats = formats
64 iv.Options = opts
65 iv.validators = [6]valueValidator{
66 iv.typeValidator(),
67 iv.stringValidator(),
68 iv.formatValidator(),
69 iv.numberValidator(),
70 iv.sliceValidator(),
71 iv.commonValidator(),
72 }
73 return iv
74 }
75
76 func (i *itemsValidator) Validate(index int, data interface{}) *Result {
77 if i.Options.recycleValidators {
78 defer func() {
79 i.redeemChildren()
80 i.redeem()
81 }()
82 }
83
84 tpe := reflect.TypeOf(data)
85 kind := tpe.Kind()
86 var result *Result
87 if i.Options.recycleResult {
88 result = pools.poolOfResults.BorrowResult()
89 } else {
90 result = new(Result)
91 }
92
93 path := fmt.Sprintf("%s.%d", i.path, index)
94
95 for idx, validator := range i.validators {
96 if !validator.Applies(i.root, kind) {
97 if i.Options.recycleValidators {
98
99 if redeemableChildren, ok := validator.(interface{ redeemChildren() }); ok {
100 redeemableChildren.redeemChildren()
101 }
102 if redeemable, ok := validator.(interface{ redeem() }); ok {
103 redeemable.redeem()
104 }
105 i.validators[idx] = nil
106 }
107
108 continue
109 }
110
111 validator.SetPath(path)
112 err := validator.Validate(data)
113 if i.Options.recycleValidators {
114 i.validators[idx] = nil
115 }
116 if err != nil {
117 result.Inc()
118 if err.HasErrors() {
119 result.Merge(err)
120
121 break
122 }
123
124 result.Merge(err)
125 }
126 }
127
128 return result
129 }
130
131 func (i *itemsValidator) typeValidator() valueValidator {
132 return newTypeValidator(
133 i.path,
134 i.in,
135 spec.StringOrArray([]string{i.items.Type}),
136 i.items.Nullable,
137 i.items.Format,
138 i.Options,
139 )
140 }
141
142 func (i *itemsValidator) commonValidator() valueValidator {
143 return newBasicCommonValidator(
144 "",
145 i.in,
146 i.items.Default,
147 i.items.Enum,
148 i.Options,
149 )
150 }
151
152 func (i *itemsValidator) sliceValidator() valueValidator {
153 return newBasicSliceValidator(
154 "",
155 i.in,
156 i.items.Default,
157 i.items.MaxItems,
158 i.items.MinItems,
159 i.items.UniqueItems,
160 i.items.Items,
161 i.root,
162 i.KnownFormats,
163 i.Options,
164 )
165 }
166
167 func (i *itemsValidator) numberValidator() valueValidator {
168 return newNumberValidator(
169 "",
170 i.in,
171 i.items.Default,
172 i.items.MultipleOf,
173 i.items.Maximum,
174 i.items.ExclusiveMaximum,
175 i.items.Minimum,
176 i.items.ExclusiveMinimum,
177 i.items.Type,
178 i.items.Format,
179 i.Options,
180 )
181 }
182
183 func (i *itemsValidator) stringValidator() valueValidator {
184 return newStringValidator(
185 "",
186 i.in,
187 i.items.Default,
188 false,
189 false,
190 i.items.MaxLength,
191 i.items.MinLength,
192 i.items.Pattern,
193 i.Options,
194 )
195 }
196
197 func (i *itemsValidator) formatValidator() valueValidator {
198 return newFormatValidator(
199 "",
200 i.in,
201 i.items.Format,
202 i.KnownFormats,
203 i.Options,
204 )
205 }
206
207 func (i *itemsValidator) redeem() {
208 pools.poolOfItemsValidators.RedeemValidator(i)
209 }
210
211 func (i *itemsValidator) redeemChildren() {
212 for idx, validator := range i.validators {
213 if validator == nil {
214 continue
215 }
216 if redeemableChildren, ok := validator.(interface{ redeemChildren() }); ok {
217 redeemableChildren.redeemChildren()
218 }
219 if redeemable, ok := validator.(interface{ redeem() }); ok {
220 redeemable.redeem()
221 }
222 i.validators[idx] = nil
223 }
224 }
225
226 type basicCommonValidator struct {
227 Path string
228 In string
229 Default interface{}
230 Enum []interface{}
231 Options *SchemaValidatorOptions
232 }
233
234 func newBasicCommonValidator(path, in string, def interface{}, enum []interface{}, opts *SchemaValidatorOptions) *basicCommonValidator {
235 if opts == nil {
236 opts = new(SchemaValidatorOptions)
237 }
238
239 var b *basicCommonValidator
240 if opts.recycleValidators {
241 b = pools.poolOfBasicCommonValidators.BorrowValidator()
242 } else {
243 b = new(basicCommonValidator)
244 }
245
246 b.Path = path
247 b.In = in
248 b.Default = def
249 b.Enum = enum
250 b.Options = opts
251
252 return b
253 }
254
255 func (b *basicCommonValidator) SetPath(path string) {
256 b.Path = path
257 }
258
259 func (b *basicCommonValidator) Applies(source interface{}, _ reflect.Kind) bool {
260 switch source.(type) {
261 case *spec.Parameter, *spec.Schema, *spec.Header:
262 return true
263 default:
264 return false
265 }
266 }
267
268 func (b *basicCommonValidator) Validate(data interface{}) (res *Result) {
269 if b.Options.recycleValidators {
270 defer func() {
271 b.redeem()
272 }()
273 }
274
275 if len(b.Enum) == 0 {
276 return nil
277 }
278
279 for _, enumValue := range b.Enum {
280 actualType := reflect.TypeOf(enumValue)
281 if actualType == nil {
282 continue
283 }
284
285 expectedValue := reflect.ValueOf(data)
286 if expectedValue.IsValid() &&
287 expectedValue.Type().ConvertibleTo(actualType) &&
288 reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), enumValue) {
289 return nil
290 }
291 }
292
293 return errorHelp.sErr(errors.EnumFail(b.Path, b.In, data, b.Enum), b.Options.recycleResult)
294 }
295
296 func (b *basicCommonValidator) redeem() {
297 pools.poolOfBasicCommonValidators.RedeemValidator(b)
298 }
299
300
301 type HeaderValidator struct {
302 name string
303 header *spec.Header
304 validators [6]valueValidator
305 KnownFormats strfmt.Registry
306 Options *SchemaValidatorOptions
307 }
308
309
310 func NewHeaderValidator(name string, header *spec.Header, formats strfmt.Registry, options ...Option) *HeaderValidator {
311 opts := new(SchemaValidatorOptions)
312 for _, o := range options {
313 o(opts)
314 }
315
316 return newHeaderValidator(name, header, formats, opts)
317 }
318
319 func newHeaderValidator(name string, header *spec.Header, formats strfmt.Registry, opts *SchemaValidatorOptions) *HeaderValidator {
320 if opts == nil {
321 opts = new(SchemaValidatorOptions)
322 }
323
324 var p *HeaderValidator
325 if opts.recycleValidators {
326 p = pools.poolOfHeaderValidators.BorrowValidator()
327 } else {
328 p = new(HeaderValidator)
329 }
330
331 p.name = name
332 p.header = header
333 p.KnownFormats = formats
334 p.Options = opts
335 p.validators = [6]valueValidator{
336 newTypeValidator(
337 name,
338 "header",
339 spec.StringOrArray([]string{header.Type}),
340 header.Nullable,
341 header.Format,
342 p.Options,
343 ),
344 p.stringValidator(),
345 p.formatValidator(),
346 p.numberValidator(),
347 p.sliceValidator(),
348 p.commonValidator(),
349 }
350
351 return p
352 }
353
354
355 func (p *HeaderValidator) Validate(data interface{}) *Result {
356 if p.Options.recycleValidators {
357 defer func() {
358 p.redeemChildren()
359 p.redeem()
360 }()
361 }
362
363 if data == nil {
364 return nil
365 }
366
367 var result *Result
368 if p.Options.recycleResult {
369 result = pools.poolOfResults.BorrowResult()
370 } else {
371 result = new(Result)
372 }
373
374 tpe := reflect.TypeOf(data)
375 kind := tpe.Kind()
376
377 for idx, validator := range p.validators {
378 if !validator.Applies(p.header, kind) {
379 if p.Options.recycleValidators {
380
381 if redeemableChildren, ok := validator.(interface{ redeemChildren() }); ok {
382 redeemableChildren.redeemChildren()
383 }
384 if redeemable, ok := validator.(interface{ redeem() }); ok {
385 redeemable.redeem()
386 }
387 p.validators[idx] = nil
388 }
389
390 continue
391 }
392
393 err := validator.Validate(data)
394 if p.Options.recycleValidators {
395 p.validators[idx] = nil
396 }
397 if err != nil {
398 if err.HasErrors() {
399 result.Merge(err)
400 break
401 }
402 result.Merge(err)
403 }
404 }
405
406 return result
407 }
408
409 func (p *HeaderValidator) commonValidator() valueValidator {
410 return newBasicCommonValidator(
411 p.name,
412 "response",
413 p.header.Default,
414 p.header.Enum,
415 p.Options,
416 )
417 }
418
419 func (p *HeaderValidator) sliceValidator() valueValidator {
420 return newBasicSliceValidator(
421 p.name,
422 "response",
423 p.header.Default,
424 p.header.MaxItems,
425 p.header.MinItems,
426 p.header.UniqueItems,
427 p.header.Items,
428 p.header,
429 p.KnownFormats,
430 p.Options,
431 )
432 }
433
434 func (p *HeaderValidator) numberValidator() valueValidator {
435 return newNumberValidator(
436 p.name,
437 "response",
438 p.header.Default,
439 p.header.MultipleOf,
440 p.header.Maximum,
441 p.header.ExclusiveMaximum,
442 p.header.Minimum,
443 p.header.ExclusiveMinimum,
444 p.header.Type,
445 p.header.Format,
446 p.Options,
447 )
448 }
449
450 func (p *HeaderValidator) stringValidator() valueValidator {
451 return newStringValidator(
452 p.name,
453 "response",
454 p.header.Default,
455 true,
456 false,
457 p.header.MaxLength,
458 p.header.MinLength,
459 p.header.Pattern,
460 p.Options,
461 )
462 }
463
464 func (p *HeaderValidator) formatValidator() valueValidator {
465 return newFormatValidator(
466 p.name,
467 "response",
468 p.header.Format,
469 p.KnownFormats,
470 p.Options,
471 )
472 }
473
474 func (p *HeaderValidator) redeem() {
475 pools.poolOfHeaderValidators.RedeemValidator(p)
476 }
477
478 func (p *HeaderValidator) redeemChildren() {
479 for idx, validator := range p.validators {
480 if validator == nil {
481 continue
482 }
483 if redeemableChildren, ok := validator.(interface{ redeemChildren() }); ok {
484 redeemableChildren.redeemChildren()
485 }
486 if redeemable, ok := validator.(interface{ redeem() }); ok {
487 redeemable.redeem()
488 }
489 p.validators[idx] = nil
490 }
491 }
492
493
494 type ParamValidator struct {
495 param *spec.Parameter
496 validators [6]valueValidator
497 KnownFormats strfmt.Registry
498 Options *SchemaValidatorOptions
499 }
500
501
502 func NewParamValidator(param *spec.Parameter, formats strfmt.Registry, options ...Option) *ParamValidator {
503 opts := new(SchemaValidatorOptions)
504 for _, o := range options {
505 o(opts)
506 }
507
508 return newParamValidator(param, formats, opts)
509 }
510
511 func newParamValidator(param *spec.Parameter, formats strfmt.Registry, opts *SchemaValidatorOptions) *ParamValidator {
512 if opts == nil {
513 opts = new(SchemaValidatorOptions)
514 }
515
516 var p *ParamValidator
517 if opts.recycleValidators {
518 p = pools.poolOfParamValidators.BorrowValidator()
519 } else {
520 p = new(ParamValidator)
521 }
522
523 p.param = param
524 p.KnownFormats = formats
525 p.Options = opts
526 p.validators = [6]valueValidator{
527 newTypeValidator(
528 param.Name,
529 param.In,
530 spec.StringOrArray([]string{param.Type}),
531 param.Nullable,
532 param.Format,
533 p.Options,
534 ),
535 p.stringValidator(),
536 p.formatValidator(),
537 p.numberValidator(),
538 p.sliceValidator(),
539 p.commonValidator(),
540 }
541
542 return p
543 }
544
545
546 func (p *ParamValidator) Validate(data interface{}) *Result {
547 if data == nil {
548 return nil
549 }
550
551 var result *Result
552 if p.Options.recycleResult {
553 result = pools.poolOfResults.BorrowResult()
554 } else {
555 result = new(Result)
556 }
557
558 tpe := reflect.TypeOf(data)
559 kind := tpe.Kind()
560
561 if p.Options.recycleValidators {
562 defer func() {
563 p.redeemChildren()
564 p.redeem()
565 }()
566 }
567
568
569 for idx, validator := range p.validators {
570 if !validator.Applies(p.param, kind) {
571 if p.Options.recycleValidators {
572
573 if redeemableChildren, ok := validator.(interface{ redeemChildren() }); ok {
574 redeemableChildren.redeemChildren()
575 }
576 if redeemable, ok := validator.(interface{ redeem() }); ok {
577 redeemable.redeem()
578 }
579 p.validators[idx] = nil
580 }
581
582 continue
583 }
584
585 err := validator.Validate(data)
586 if p.Options.recycleValidators {
587 p.validators[idx] = nil
588 }
589 if err != nil {
590 if err.HasErrors() {
591 result.Merge(err)
592 break
593 }
594 result.Merge(err)
595 }
596 }
597
598 return result
599 }
600
601 func (p *ParamValidator) commonValidator() valueValidator {
602 return newBasicCommonValidator(
603 p.param.Name,
604 p.param.In,
605 p.param.Default,
606 p.param.Enum,
607 p.Options,
608 )
609 }
610
611 func (p *ParamValidator) sliceValidator() valueValidator {
612 return newBasicSliceValidator(
613 p.param.Name,
614 p.param.In,
615 p.param.Default,
616 p.param.MaxItems,
617 p.param.MinItems,
618 p.param.UniqueItems,
619 p.param.Items,
620 p.param,
621 p.KnownFormats,
622 p.Options,
623 )
624 }
625
626 func (p *ParamValidator) numberValidator() valueValidator {
627 return newNumberValidator(
628 p.param.Name,
629 p.param.In,
630 p.param.Default,
631 p.param.MultipleOf,
632 p.param.Maximum,
633 p.param.ExclusiveMaximum,
634 p.param.Minimum,
635 p.param.ExclusiveMinimum,
636 p.param.Type,
637 p.param.Format,
638 p.Options,
639 )
640 }
641
642 func (p *ParamValidator) stringValidator() valueValidator {
643 return newStringValidator(
644 p.param.Name,
645 p.param.In,
646 p.param.Default,
647 p.param.Required,
648 p.param.AllowEmptyValue,
649 p.param.MaxLength,
650 p.param.MinLength,
651 p.param.Pattern,
652 p.Options,
653 )
654 }
655
656 func (p *ParamValidator) formatValidator() valueValidator {
657 return newFormatValidator(
658 p.param.Name,
659 p.param.In,
660 p.param.Format,
661 p.KnownFormats,
662 p.Options,
663 )
664 }
665
666 func (p *ParamValidator) redeem() {
667 pools.poolOfParamValidators.RedeemValidator(p)
668 }
669
670 func (p *ParamValidator) redeemChildren() {
671 for idx, validator := range p.validators {
672 if validator == nil {
673 continue
674 }
675 if redeemableChildren, ok := validator.(interface{ redeemChildren() }); ok {
676 redeemableChildren.redeemChildren()
677 }
678 if redeemable, ok := validator.(interface{ redeem() }); ok {
679 redeemable.redeem()
680 }
681 p.validators[idx] = nil
682 }
683 }
684
685 type basicSliceValidator struct {
686 Path string
687 In string
688 Default interface{}
689 MaxItems *int64
690 MinItems *int64
691 UniqueItems bool
692 Items *spec.Items
693 Source interface{}
694 KnownFormats strfmt.Registry
695 Options *SchemaValidatorOptions
696 }
697
698 func newBasicSliceValidator(
699 path, in string,
700 def interface{}, maxItems, minItems *int64, uniqueItems bool, items *spec.Items,
701 source interface{}, formats strfmt.Registry,
702 opts *SchemaValidatorOptions) *basicSliceValidator {
703 if opts == nil {
704 opts = new(SchemaValidatorOptions)
705 }
706
707 var s *basicSliceValidator
708 if opts.recycleValidators {
709 s = pools.poolOfBasicSliceValidators.BorrowValidator()
710 } else {
711 s = new(basicSliceValidator)
712 }
713
714 s.Path = path
715 s.In = in
716 s.Default = def
717 s.MaxItems = maxItems
718 s.MinItems = minItems
719 s.UniqueItems = uniqueItems
720 s.Items = items
721 s.Source = source
722 s.KnownFormats = formats
723 s.Options = opts
724
725 return s
726 }
727
728 func (s *basicSliceValidator) SetPath(path string) {
729 s.Path = path
730 }
731
732 func (s *basicSliceValidator) Applies(source interface{}, kind reflect.Kind) bool {
733 switch source.(type) {
734 case *spec.Parameter, *spec.Items, *spec.Header:
735 return kind == reflect.Slice
736 default:
737 return false
738 }
739 }
740
741 func (s *basicSliceValidator) Validate(data interface{}) *Result {
742 if s.Options.recycleValidators {
743 defer func() {
744 s.redeem()
745 }()
746 }
747 val := reflect.ValueOf(data)
748
749 size := int64(val.Len())
750 if s.MinItems != nil {
751 if err := MinItems(s.Path, s.In, size, *s.MinItems); err != nil {
752 return errorHelp.sErr(err, s.Options.recycleResult)
753 }
754 }
755
756 if s.MaxItems != nil {
757 if err := MaxItems(s.Path, s.In, size, *s.MaxItems); err != nil {
758 return errorHelp.sErr(err, s.Options.recycleResult)
759 }
760 }
761
762 if s.UniqueItems {
763 if err := UniqueItems(s.Path, s.In, data); err != nil {
764 return errorHelp.sErr(err, s.Options.recycleResult)
765 }
766 }
767
768 if s.Items == nil {
769 return nil
770 }
771
772 for i := 0; i < int(size); i++ {
773 itemsValidator := newItemsValidator(s.Path, s.In, s.Items, s.Source, s.KnownFormats, s.Options)
774 ele := val.Index(i)
775 if err := itemsValidator.Validate(i, ele.Interface()); err != nil {
776 if err.HasErrors() {
777 return err
778 }
779 if err.wantsRedeemOnMerge {
780 pools.poolOfResults.RedeemResult(err)
781 }
782 }
783 }
784
785 return nil
786 }
787
788 func (s *basicSliceValidator) redeem() {
789 pools.poolOfBasicSliceValidators.RedeemValidator(s)
790 }
791
792 type numberValidator struct {
793 Path string
794 In string
795 Default interface{}
796 MultipleOf *float64
797 Maximum *float64
798 ExclusiveMaximum bool
799 Minimum *float64
800 ExclusiveMinimum bool
801
802 Type string
803 Format string
804 Options *SchemaValidatorOptions
805 }
806
807 func newNumberValidator(
808 path, in string, def interface{},
809 multipleOf, maximum *float64, exclusiveMaximum bool, minimum *float64, exclusiveMinimum bool,
810 typ, format string,
811 opts *SchemaValidatorOptions) *numberValidator {
812 if opts == nil {
813 opts = new(SchemaValidatorOptions)
814 }
815
816 var n *numberValidator
817 if opts.recycleValidators {
818 n = pools.poolOfNumberValidators.BorrowValidator()
819 } else {
820 n = new(numberValidator)
821 }
822
823 n.Path = path
824 n.In = in
825 n.Default = def
826 n.MultipleOf = multipleOf
827 n.Maximum = maximum
828 n.ExclusiveMaximum = exclusiveMaximum
829 n.Minimum = minimum
830 n.ExclusiveMinimum = exclusiveMinimum
831 n.Type = typ
832 n.Format = format
833 n.Options = opts
834
835 return n
836 }
837
838 func (n *numberValidator) SetPath(path string) {
839 n.Path = path
840 }
841
842 func (n *numberValidator) Applies(source interface{}, kind reflect.Kind) bool {
843 switch source.(type) {
844 case *spec.Parameter, *spec.Schema, *spec.Items, *spec.Header:
845 isInt := kind >= reflect.Int && kind <= reflect.Uint64
846 isFloat := kind == reflect.Float32 || kind == reflect.Float64
847 return isInt || isFloat
848 default:
849 return false
850 }
851 }
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874 func (n *numberValidator) Validate(val interface{}) *Result {
875 if n.Options.recycleValidators {
876 defer func() {
877 n.redeem()
878 }()
879 }
880
881 var res, resMultiple, resMinimum, resMaximum *Result
882 if n.Options.recycleResult {
883 res = pools.poolOfResults.BorrowResult()
884 } else {
885 res = new(Result)
886 }
887
888
889
890 data := valueHelp.asFloat64(val)
891
892
893 res.AddErrors(IsValueValidAgainstRange(val, n.Type, n.Format, "Checked", n.Path))
894
895 if n.MultipleOf != nil {
896 resMultiple = pools.poolOfResults.BorrowResult()
897
898
899 resMultiple.AddErrors(IsValueValidAgainstRange(*n.MultipleOf, n.Type, n.Format, "MultipleOf", n.Path))
900 if resMultiple.IsValid() {
901
902 if err := MultipleOfNativeType(n.Path, n.In, val, *n.MultipleOf); err != nil {
903 resMultiple.Merge(errorHelp.sErr(err, n.Options.recycleResult))
904 }
905 } else {
906
907 if err := MultipleOf(n.Path, n.In, data, *n.MultipleOf); err != nil {
908 resMultiple.Merge(errorHelp.sErr(err, n.Options.recycleResult))
909 }
910 }
911 }
912
913 if n.Maximum != nil {
914 resMaximum = pools.poolOfResults.BorrowResult()
915
916
917 resMaximum.AddErrors(IsValueValidAgainstRange(*n.Maximum, n.Type, n.Format, "Maximum boundary", n.Path))
918 if resMaximum.IsValid() {
919
920 if err := MaximumNativeType(n.Path, n.In, val, *n.Maximum, n.ExclusiveMaximum); err != nil {
921 resMaximum.Merge(errorHelp.sErr(err, n.Options.recycleResult))
922 }
923 } else {
924
925 if err := Maximum(n.Path, n.In, data, *n.Maximum, n.ExclusiveMaximum); err != nil {
926 resMaximum.Merge(errorHelp.sErr(err, n.Options.recycleResult))
927 }
928 }
929 }
930
931 if n.Minimum != nil {
932 resMinimum = pools.poolOfResults.BorrowResult()
933
934
935 resMinimum.AddErrors(IsValueValidAgainstRange(*n.Minimum, n.Type, n.Format, "Minimum boundary", n.Path))
936 if resMinimum.IsValid() {
937
938 if err := MinimumNativeType(n.Path, n.In, val, *n.Minimum, n.ExclusiveMinimum); err != nil {
939 resMinimum.Merge(errorHelp.sErr(err, n.Options.recycleResult))
940 }
941 } else {
942
943 if err := Minimum(n.Path, n.In, data, *n.Minimum, n.ExclusiveMinimum); err != nil {
944 resMinimum.Merge(errorHelp.sErr(err, n.Options.recycleResult))
945 }
946 }
947 }
948 res.Merge(resMultiple, resMinimum, resMaximum)
949 res.Inc()
950
951 return res
952 }
953
954 func (n *numberValidator) redeem() {
955 pools.poolOfNumberValidators.RedeemValidator(n)
956 }
957
958 type stringValidator struct {
959 Path string
960 In string
961 Default interface{}
962 Required bool
963 AllowEmptyValue bool
964 MaxLength *int64
965 MinLength *int64
966 Pattern string
967 Options *SchemaValidatorOptions
968 }
969
970 func newStringValidator(
971 path, in string,
972 def interface{}, required, allowEmpty bool, maxLength, minLength *int64, pattern string,
973 opts *SchemaValidatorOptions) *stringValidator {
974 if opts == nil {
975 opts = new(SchemaValidatorOptions)
976 }
977
978 var s *stringValidator
979 if opts.recycleValidators {
980 s = pools.poolOfStringValidators.BorrowValidator()
981 } else {
982 s = new(stringValidator)
983 }
984
985 s.Path = path
986 s.In = in
987 s.Default = def
988 s.Required = required
989 s.AllowEmptyValue = allowEmpty
990 s.MaxLength = maxLength
991 s.MinLength = minLength
992 s.Pattern = pattern
993 s.Options = opts
994
995 return s
996 }
997
998 func (s *stringValidator) SetPath(path string) {
999 s.Path = path
1000 }
1001
1002 func (s *stringValidator) Applies(source interface{}, kind reflect.Kind) bool {
1003 switch source.(type) {
1004 case *spec.Parameter, *spec.Schema, *spec.Items, *spec.Header:
1005 return kind == reflect.String
1006 default:
1007 return false
1008 }
1009 }
1010
1011 func (s *stringValidator) Validate(val interface{}) *Result {
1012 if s.Options.recycleValidators {
1013 defer func() {
1014 s.redeem()
1015 }()
1016 }
1017
1018 data, ok := val.(string)
1019 if !ok {
1020 return errorHelp.sErr(errors.InvalidType(s.Path, s.In, stringType, val), s.Options.recycleResult)
1021 }
1022
1023 if s.Required && !s.AllowEmptyValue && (s.Default == nil || s.Default == "") {
1024 if err := RequiredString(s.Path, s.In, data); err != nil {
1025 return errorHelp.sErr(err, s.Options.recycleResult)
1026 }
1027 }
1028
1029 if s.MaxLength != nil {
1030 if err := MaxLength(s.Path, s.In, data, *s.MaxLength); err != nil {
1031 return errorHelp.sErr(err, s.Options.recycleResult)
1032 }
1033 }
1034
1035 if s.MinLength != nil {
1036 if err := MinLength(s.Path, s.In, data, *s.MinLength); err != nil {
1037 return errorHelp.sErr(err, s.Options.recycleResult)
1038 }
1039 }
1040
1041 if s.Pattern != "" {
1042 if err := Pattern(s.Path, s.In, data, s.Pattern); err != nil {
1043 return errorHelp.sErr(err, s.Options.recycleResult)
1044 }
1045 }
1046 return nil
1047 }
1048
1049 func (s *stringValidator) redeem() {
1050 pools.poolOfStringValidators.RedeemValidator(s)
1051 }
1052
View as plain text