]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/jmespath/go-jmespath/interpreter.go
Initial transfer of provider code
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / jmespath / go-jmespath / interpreter.go
1 package jmespath
2
3 import (
4 "errors"
5 "reflect"
6 "unicode"
7 "unicode/utf8"
8 )
9
10 /* This is a tree based interpreter. It walks the AST and directly
11 interprets the AST to search through a JSON document.
12 */
13
14 type treeInterpreter struct {
15 fCall *functionCaller
16 }
17
18 func newInterpreter() *treeInterpreter {
19 interpreter := treeInterpreter{}
20 interpreter.fCall = newFunctionCaller()
21 return &interpreter
22 }
23
24 type expRef struct {
25 ref ASTNode
26 }
27
28 // Execute takes an ASTNode and input data and interprets the AST directly.
29 // It will produce the result of applying the JMESPath expression associated
30 // with the ASTNode to the input data "value".
31 func (intr *treeInterpreter) Execute(node ASTNode, value interface{}) (interface{}, error) {
32 switch node.nodeType {
33 case ASTComparator:
34 left, err := intr.Execute(node.children[0], value)
35 if err != nil {
36 return nil, err
37 }
38 right, err := intr.Execute(node.children[1], value)
39 if err != nil {
40 return nil, err
41 }
42 switch node.value {
43 case tEQ:
44 return objsEqual(left, right), nil
45 case tNE:
46 return !objsEqual(left, right), nil
47 }
48 leftNum, ok := left.(float64)
49 if !ok {
50 return nil, nil
51 }
52 rightNum, ok := right.(float64)
53 if !ok {
54 return nil, nil
55 }
56 switch node.value {
57 case tGT:
58 return leftNum > rightNum, nil
59 case tGTE:
60 return leftNum >= rightNum, nil
61 case tLT:
62 return leftNum < rightNum, nil
63 case tLTE:
64 return leftNum <= rightNum, nil
65 }
66 case ASTExpRef:
67 return expRef{ref: node.children[0]}, nil
68 case ASTFunctionExpression:
69 resolvedArgs := []interface{}{}
70 for _, arg := range node.children {
71 current, err := intr.Execute(arg, value)
72 if err != nil {
73 return nil, err
74 }
75 resolvedArgs = append(resolvedArgs, current)
76 }
77 return intr.fCall.CallFunction(node.value.(string), resolvedArgs, intr)
78 case ASTField:
79 if m, ok := value.(map[string]interface{}); ok {
80 key := node.value.(string)
81 return m[key], nil
82 }
83 return intr.fieldFromStruct(node.value.(string), value)
84 case ASTFilterProjection:
85 left, err := intr.Execute(node.children[0], value)
86 if err != nil {
87 return nil, nil
88 }
89 sliceType, ok := left.([]interface{})
90 if !ok {
91 if isSliceType(left) {
92 return intr.filterProjectionWithReflection(node, left)
93 }
94 return nil, nil
95 }
96 compareNode := node.children[2]
97 collected := []interface{}{}
98 for _, element := range sliceType {
99 result, err := intr.Execute(compareNode, element)
100 if err != nil {
101 return nil, err
102 }
103 if !isFalse(result) {
104 current, err := intr.Execute(node.children[1], element)
105 if err != nil {
106 return nil, err
107 }
108 if current != nil {
109 collected = append(collected, current)
110 }
111 }
112 }
113 return collected, nil
114 case ASTFlatten:
115 left, err := intr.Execute(node.children[0], value)
116 if err != nil {
117 return nil, nil
118 }
119 sliceType, ok := left.([]interface{})
120 if !ok {
121 // If we can't type convert to []interface{}, there's
122 // a chance this could still work via reflection if we're
123 // dealing with user provided types.
124 if isSliceType(left) {
125 return intr.flattenWithReflection(left)
126 }
127 return nil, nil
128 }
129 flattened := []interface{}{}
130 for _, element := range sliceType {
131 if elementSlice, ok := element.([]interface{}); ok {
132 flattened = append(flattened, elementSlice...)
133 } else if isSliceType(element) {
134 reflectFlat := []interface{}{}
135 v := reflect.ValueOf(element)
136 for i := 0; i < v.Len(); i++ {
137 reflectFlat = append(reflectFlat, v.Index(i).Interface())
138 }
139 flattened = append(flattened, reflectFlat...)
140 } else {
141 flattened = append(flattened, element)
142 }
143 }
144 return flattened, nil
145 case ASTIdentity, ASTCurrentNode:
146 return value, nil
147 case ASTIndex:
148 if sliceType, ok := value.([]interface{}); ok {
149 index := node.value.(int)
150 if index < 0 {
151 index += len(sliceType)
152 }
153 if index < len(sliceType) && index >= 0 {
154 return sliceType[index], nil
155 }
156 return nil, nil
157 }
158 // Otherwise try via reflection.
159 rv := reflect.ValueOf(value)
160 if rv.Kind() == reflect.Slice {
161 index := node.value.(int)
162 if index < 0 {
163 index += rv.Len()
164 }
165 if index < rv.Len() && index >= 0 {
166 v := rv.Index(index)
167 return v.Interface(), nil
168 }
169 }
170 return nil, nil
171 case ASTKeyValPair:
172 return intr.Execute(node.children[0], value)
173 case ASTLiteral:
174 return node.value, nil
175 case ASTMultiSelectHash:
176 if value == nil {
177 return nil, nil
178 }
179 collected := make(map[string]interface{})
180 for _, child := range node.children {
181 current, err := intr.Execute(child, value)
182 if err != nil {
183 return nil, err
184 }
185 key := child.value.(string)
186 collected[key] = current
187 }
188 return collected, nil
189 case ASTMultiSelectList:
190 if value == nil {
191 return nil, nil
192 }
193 collected := []interface{}{}
194 for _, child := range node.children {
195 current, err := intr.Execute(child, value)
196 if err != nil {
197 return nil, err
198 }
199 collected = append(collected, current)
200 }
201 return collected, nil
202 case ASTOrExpression:
203 matched, err := intr.Execute(node.children[0], value)
204 if err != nil {
205 return nil, err
206 }
207 if isFalse(matched) {
208 matched, err = intr.Execute(node.children[1], value)
209 if err != nil {
210 return nil, err
211 }
212 }
213 return matched, nil
214 case ASTAndExpression:
215 matched, err := intr.Execute(node.children[0], value)
216 if err != nil {
217 return nil, err
218 }
219 if isFalse(matched) {
220 return matched, nil
221 }
222 return intr.Execute(node.children[1], value)
223 case ASTNotExpression:
224 matched, err := intr.Execute(node.children[0], value)
225 if err != nil {
226 return nil, err
227 }
228 if isFalse(matched) {
229 return true, nil
230 }
231 return false, nil
232 case ASTPipe:
233 result := value
234 var err error
235 for _, child := range node.children {
236 result, err = intr.Execute(child, result)
237 if err != nil {
238 return nil, err
239 }
240 }
241 return result, nil
242 case ASTProjection:
243 left, err := intr.Execute(node.children[0], value)
244 if err != nil {
245 return nil, err
246 }
247 sliceType, ok := left.([]interface{})
248 if !ok {
249 if isSliceType(left) {
250 return intr.projectWithReflection(node, left)
251 }
252 return nil, nil
253 }
254 collected := []interface{}{}
255 var current interface{}
256 for _, element := range sliceType {
257 current, err = intr.Execute(node.children[1], element)
258 if err != nil {
259 return nil, err
260 }
261 if current != nil {
262 collected = append(collected, current)
263 }
264 }
265 return collected, nil
266 case ASTSubexpression, ASTIndexExpression:
267 left, err := intr.Execute(node.children[0], value)
268 if err != nil {
269 return nil, err
270 }
271 return intr.Execute(node.children[1], left)
272 case ASTSlice:
273 sliceType, ok := value.([]interface{})
274 if !ok {
275 if isSliceType(value) {
276 return intr.sliceWithReflection(node, value)
277 }
278 return nil, nil
279 }
280 parts := node.value.([]*int)
281 sliceParams := make([]sliceParam, 3)
282 for i, part := range parts {
283 if part != nil {
284 sliceParams[i].Specified = true
285 sliceParams[i].N = *part
286 }
287 }
288 return slice(sliceType, sliceParams)
289 case ASTValueProjection:
290 left, err := intr.Execute(node.children[0], value)
291 if err != nil {
292 return nil, nil
293 }
294 mapType, ok := left.(map[string]interface{})
295 if !ok {
296 return nil, nil
297 }
298 values := make([]interface{}, len(mapType))
299 for _, value := range mapType {
300 values = append(values, value)
301 }
302 collected := []interface{}{}
303 for _, element := range values {
304 current, err := intr.Execute(node.children[1], element)
305 if err != nil {
306 return nil, err
307 }
308 if current != nil {
309 collected = append(collected, current)
310 }
311 }
312 return collected, nil
313 }
314 return nil, errors.New("Unknown AST node: " + node.nodeType.String())
315 }
316
317 func (intr *treeInterpreter) fieldFromStruct(key string, value interface{}) (interface{}, error) {
318 rv := reflect.ValueOf(value)
319 first, n := utf8.DecodeRuneInString(key)
320 fieldName := string(unicode.ToUpper(first)) + key[n:]
321 if rv.Kind() == reflect.Struct {
322 v := rv.FieldByName(fieldName)
323 if !v.IsValid() {
324 return nil, nil
325 }
326 return v.Interface(), nil
327 } else if rv.Kind() == reflect.Ptr {
328 // Handle multiple levels of indirection?
329 if rv.IsNil() {
330 return nil, nil
331 }
332 rv = rv.Elem()
333 v := rv.FieldByName(fieldName)
334 if !v.IsValid() {
335 return nil, nil
336 }
337 return v.Interface(), nil
338 }
339 return nil, nil
340 }
341
342 func (intr *treeInterpreter) flattenWithReflection(value interface{}) (interface{}, error) {
343 v := reflect.ValueOf(value)
344 flattened := []interface{}{}
345 for i := 0; i < v.Len(); i++ {
346 element := v.Index(i).Interface()
347 if reflect.TypeOf(element).Kind() == reflect.Slice {
348 // Then insert the contents of the element
349 // slice into the flattened slice,
350 // i.e flattened = append(flattened, mySlice...)
351 elementV := reflect.ValueOf(element)
352 for j := 0; j < elementV.Len(); j++ {
353 flattened = append(
354 flattened, elementV.Index(j).Interface())
355 }
356 } else {
357 flattened = append(flattened, element)
358 }
359 }
360 return flattened, nil
361 }
362
363 func (intr *treeInterpreter) sliceWithReflection(node ASTNode, value interface{}) (interface{}, error) {
364 v := reflect.ValueOf(value)
365 parts := node.value.([]*int)
366 sliceParams := make([]sliceParam, 3)
367 for i, part := range parts {
368 if part != nil {
369 sliceParams[i].Specified = true
370 sliceParams[i].N = *part
371 }
372 }
373 final := []interface{}{}
374 for i := 0; i < v.Len(); i++ {
375 element := v.Index(i).Interface()
376 final = append(final, element)
377 }
378 return slice(final, sliceParams)
379 }
380
381 func (intr *treeInterpreter) filterProjectionWithReflection(node ASTNode, value interface{}) (interface{}, error) {
382 compareNode := node.children[2]
383 collected := []interface{}{}
384 v := reflect.ValueOf(value)
385 for i := 0; i < v.Len(); i++ {
386 element := v.Index(i).Interface()
387 result, err := intr.Execute(compareNode, element)
388 if err != nil {
389 return nil, err
390 }
391 if !isFalse(result) {
392 current, err := intr.Execute(node.children[1], element)
393 if err != nil {
394 return nil, err
395 }
396 if current != nil {
397 collected = append(collected, current)
398 }
399 }
400 }
401 return collected, nil
402 }
403
404 func (intr *treeInterpreter) projectWithReflection(node ASTNode, value interface{}) (interface{}, error) {
405 collected := []interface{}{}
406 v := reflect.ValueOf(value)
407 for i := 0; i < v.Len(); i++ {
408 element := v.Index(i).Interface()
409 result, err := intr.Execute(node.children[1], element)
410 if err != nil {
411 return nil, err
412 }
413 if result != nil {
414 collected = append(collected, result)
415 }
416 }
417 return collected, nil
418 }