...
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/spec"
22 "github.com/go-openapi/strfmt"
23 )
24
25 type schemaSliceValidator struct {
26 Path string
27 In string
28 MaxItems *int64
29 MinItems *int64
30 UniqueItems bool
31 AdditionalItems *spec.SchemaOrBool
32 Items *spec.SchemaOrArray
33 Root interface{}
34 KnownFormats strfmt.Registry
35 Options *SchemaValidatorOptions
36 }
37
38 func newSliceValidator(path, in string,
39 maxItems, minItems *int64, uniqueItems bool,
40 additionalItems *spec.SchemaOrBool, items *spec.SchemaOrArray,
41 root interface{}, formats strfmt.Registry, opts *SchemaValidatorOptions) *schemaSliceValidator {
42 if opts == nil {
43 opts = new(SchemaValidatorOptions)
44 }
45
46 var v *schemaSliceValidator
47 if opts.recycleValidators {
48 v = pools.poolOfSliceValidators.BorrowValidator()
49 } else {
50 v = new(schemaSliceValidator)
51 }
52
53 v.Path = path
54 v.In = in
55 v.MaxItems = maxItems
56 v.MinItems = minItems
57 v.UniqueItems = uniqueItems
58 v.AdditionalItems = additionalItems
59 v.Items = items
60 v.Root = root
61 v.KnownFormats = formats
62 v.Options = opts
63
64 return v
65 }
66
67 func (s *schemaSliceValidator) SetPath(path string) {
68 s.Path = path
69 }
70
71 func (s *schemaSliceValidator) Applies(source interface{}, kind reflect.Kind) bool {
72 _, ok := source.(*spec.Schema)
73 r := ok && kind == reflect.Slice
74 return r
75 }
76
77 func (s *schemaSliceValidator) Validate(data interface{}) *Result {
78 if s.Options.recycleValidators {
79 defer func() {
80 s.redeem()
81 }()
82 }
83
84 var result *Result
85 if s.Options.recycleResult {
86 result = pools.poolOfResults.BorrowResult()
87 } else {
88 result = new(Result)
89 }
90 if data == nil {
91 return result
92 }
93 val := reflect.ValueOf(data)
94 size := val.Len()
95
96 if s.Items != nil && s.Items.Schema != nil {
97 for i := 0; i < size; i++ {
98 validator := newSchemaValidator(s.Items.Schema, s.Root, s.Path, s.KnownFormats, s.Options)
99 validator.SetPath(fmt.Sprintf("%s.%d", s.Path, i))
100 value := val.Index(i)
101 result.mergeForSlice(val, i, validator.Validate(value.Interface()))
102 }
103 }
104
105 itemsSize := 0
106 if s.Items != nil && len(s.Items.Schemas) > 0 {
107 itemsSize = len(s.Items.Schemas)
108 for i := 0; i < itemsSize; i++ {
109 if size <= i {
110 break
111 }
112
113 validator := newSchemaValidator(&s.Items.Schemas[i], s.Root, fmt.Sprintf("%s.%d", s.Path, i), s.KnownFormats, s.Options)
114 result.mergeForSlice(val, i, validator.Validate(val.Index(i).Interface()))
115 }
116 }
117 if s.AdditionalItems != nil && itemsSize < size {
118 if s.Items != nil && len(s.Items.Schemas) > 0 && !s.AdditionalItems.Allows {
119 result.AddErrors(arrayDoesNotAllowAdditionalItemsMsg())
120 }
121 if s.AdditionalItems.Schema != nil {
122 for i := itemsSize; i < size-itemsSize+1; i++ {
123 validator := newSchemaValidator(s.AdditionalItems.Schema, s.Root, fmt.Sprintf("%s.%d", s.Path, i), s.KnownFormats, s.Options)
124 result.mergeForSlice(val, i, validator.Validate(val.Index(i).Interface()))
125 }
126 }
127 }
128
129 if s.MinItems != nil {
130 if err := MinItems(s.Path, s.In, int64(size), *s.MinItems); err != nil {
131 result.AddErrors(err)
132 }
133 }
134 if s.MaxItems != nil {
135 if err := MaxItems(s.Path, s.In, int64(size), *s.MaxItems); err != nil {
136 result.AddErrors(err)
137 }
138 }
139 if s.UniqueItems {
140 if err := UniqueItems(s.Path, s.In, val.Interface()); err != nil {
141 result.AddErrors(err)
142 }
143 }
144 result.Inc()
145 return result
146 }
147
148 func (s *schemaSliceValidator) redeem() {
149 pools.poolOfSliceValidators.RedeemValidator(s)
150 }
151
View as plain text