8 // IsFalse determines if an object is false based on the JMESPath spec.
9 // JMESPath defines false values to be any of:
10 // - An empty string array, or hash.
11 // - The boolean value false.
13 func isFalse(value interface{}) bool {
14 switch v := value.(type) {
19 case map[string]interface{}:
26 // Try the reflection cases before returning false.
27 rv := reflect.ValueOf(value)
30 // A struct type will never be false, even if
31 // all of its values are the zero type.
33 case reflect.Slice, reflect.Map:
39 // If it's a pointer type, we'll try to deref the pointer
40 // and evaluate the pointer value for isFalse.
42 return isFalse(element.Interface())
47 // ObjsEqual is a generic object equality check.
48 // It will take two arbitrary objects and recursively determine
50 func objsEqual(left interface{}, right interface{}) bool {
51 return reflect.DeepEqual(left, right)
54 // SliceParam refers to a single part of a slice.
55 // A slice consists of a start, a stop, and a step, similar to
57 type sliceParam struct {
62 // Slice supports [start:stop:step] style slicing that's supported in JMESPath.
63 func slice(slice []interface{}, parts []sliceParam) ([]interface{}, error) {
64 computed, err := computeSliceParams(len(slice), parts)
68 start, stop, step := computed[0], computed[1], computed[2]
69 result := []interface{}{}
71 for i := start; i < stop; i += step {
72 result = append(result, slice[i])
75 for i := start; i > stop; i += step {
76 result = append(result, slice[i])
82 func computeSliceParams(length int, parts []sliceParam) ([]int, error) {
83 var start, stop, step int
84 if !parts[2].Specified {
86 } else if parts[2].N == 0 {
87 return nil, errors.New("Invalid slice, step cannot be 0")
91 var stepValueNegative bool
93 stepValueNegative = true
95 stepValueNegative = false
98 if !parts[0].Specified {
99 if stepValueNegative {
105 start = capSlice(length, parts[0].N, step)
108 if !parts[1].Specified {
109 if stepValueNegative {
115 stop = capSlice(length, parts[1].N, step)
117 return []int{start, stop, step}, nil
120 func capSlice(length int, actual int, step int) int {
130 } else if actual >= length {
140 // ToArrayNum converts an empty interface type to a slice of float64.
141 // If any element in the array cannot be converted, then nil is returned
142 // along with a second value of false.
143 func toArrayNum(data interface{}) ([]float64, bool) {
144 // Is there a better way to do this with reflect?
145 if d, ok := data.([]interface{}); ok {
146 result := make([]float64, len(d))
147 for i, el := range d {
148 item, ok := el.(float64)
159 // ToArrayStr converts an empty interface type to a slice of strings.
160 // If any element in the array cannot be converted, then nil is returned
161 // along with a second value of false. If the input data could be entirely
162 // converted, then the converted data, along with a second value of true,
164 func toArrayStr(data interface{}) ([]string, bool) {
165 // Is there a better way to do this with reflect?
166 if d, ok := data.([]interface{}); ok {
167 result := make([]string, len(d))
168 for i, el := range d {
169 item, ok := el.(string)
180 func isSliceType(v interface{}) bool {
184 return reflect.TypeOf(v).Kind() == reflect.Slice