github.com/MontFerret/ferret@v0.18.0/pkg/runtime/expressions/operators/array.go (about) 1 package operators 2 3 import ( 4 "context" 5 "strings" 6 7 "github.com/MontFerret/ferret/pkg/runtime/core" 8 "github.com/MontFerret/ferret/pkg/runtime/values" 9 "github.com/MontFerret/ferret/pkg/runtime/values/types" 10 ) 11 12 type ( 13 ArrayOperatorVariant int 14 15 ArrayOperator struct { 16 *baseOperator 17 variant ArrayOperatorVariant 18 comparator core.Predicate 19 } 20 ) 21 22 const ( 23 ArrayOperatorVariantAll ArrayOperatorVariant = iota 24 ArrayOperatorVariantAny 25 ArrayOperatorVariantNone 26 ) 27 28 func ToArrayOperatorVariant(name string) (ArrayOperatorVariant, error) { 29 switch strings.ToUpper(name) { 30 case "ALL": 31 return ArrayOperatorVariantAll, nil 32 case "ANY": 33 return ArrayOperatorVariantAny, nil 34 case "NONE": 35 return ArrayOperatorVariantNone, nil 36 default: 37 return ArrayOperatorVariant(-1), core.Error(core.ErrInvalidArgument, name) 38 } 39 } 40 41 func NewArrayOperator( 42 src core.SourceMap, 43 left core.Expression, 44 right core.Expression, 45 variantStr string, 46 comparator core.Predicate, 47 ) (*ArrayOperator, error) { 48 if left == nil { 49 return nil, core.Error(core.ErrMissedArgument, "left expression") 50 } 51 52 if right == nil { 53 return nil, core.Error(core.ErrMissedArgument, "right expression") 54 } 55 56 variant, err := ToArrayOperatorVariant(variantStr) 57 58 if err != nil { 59 return nil, err 60 } 61 62 if comparator == nil { 63 return nil, core.Error(core.ErrMissedArgument, "comparator expression") 64 } 65 66 base := &baseOperator{src, left, right} 67 68 return &ArrayOperator{base, variant, comparator}, nil 69 } 70 71 func (operator *ArrayOperator) Exec(ctx context.Context, scope *core.Scope) (core.Value, error) { 72 left, err := operator.left.Exec(ctx, scope) 73 74 if err != nil { 75 return values.False, core.SourceError(operator.src, err) 76 } 77 78 right, err := operator.right.Exec(ctx, scope) 79 80 if err != nil { 81 return values.False, core.SourceError(operator.src, err) 82 } 83 84 return operator.Eval(ctx, left, right) 85 } 86 87 func (operator *ArrayOperator) Eval(ctx context.Context, left, right core.Value) (core.Value, error) { 88 err := core.ValidateType(left, types.Array) 89 90 if err != nil { 91 // TODO: Return the error? AQL just returns false 92 return values.False, nil 93 } 94 95 arr := left.(*values.Array) 96 97 switch operator.variant { 98 case ArrayOperatorVariantAll: 99 return operator.all(ctx, arr, right) 100 case ArrayOperatorVariantAny: 101 return operator.any(ctx, arr, right) 102 default: 103 return operator.none(ctx, arr, right) 104 } 105 } 106 107 func (operator *ArrayOperator) all(ctx context.Context, arr *values.Array, value core.Value) (core.Value, error) { 108 result := values.False 109 var err error 110 111 arr.ForEach(func(el core.Value, _ int) bool { 112 out, e := operator.comparator.Eval(ctx, el, value) 113 114 if e != nil { 115 err = e 116 return false 117 } 118 119 if out == values.True { 120 result = values.True 121 } else { 122 result = values.False 123 return false 124 } 125 126 return true 127 }) 128 129 if err != nil { 130 return values.False, err 131 } 132 133 return result, nil 134 } 135 136 func (operator *ArrayOperator) any(ctx context.Context, arr *values.Array, value core.Value) (core.Value, error) { 137 result := values.False 138 var err error 139 140 arr.ForEach(func(el core.Value, _ int) bool { 141 out, e := operator.comparator.Eval(ctx, el, value) 142 143 if e != nil { 144 err = e 145 return false 146 } 147 148 if out == values.True { 149 result = values.True 150 return false 151 } 152 153 return true 154 }) 155 156 if err != nil { 157 return values.False, err 158 } 159 160 return result, nil 161 } 162 163 func (operator *ArrayOperator) none(ctx context.Context, arr *values.Array, value core.Value) (core.Value, error) { 164 result := values.False 165 var err error 166 167 arr.ForEach(func(el core.Value, _ int) bool { 168 out, e := operator.comparator.Eval(ctx, el, value) 169 170 if e != nil { 171 err = e 172 return false 173 } 174 175 if out == values.False { 176 result = values.True 177 } else { 178 result = values.False 179 return false 180 } 181 182 return true 183 }) 184 185 if err != nil { 186 return values.False, err 187 } 188 189 return result, nil 190 }