Module: Cel::Macro
- Defined in:
- lib/cel/macro.rb
Class Method Summary collapse
- .all(collection, *identifiers, predicate, program:) ⇒ Object
- .exists(collection, *identifiers, predicate, program:) ⇒ Object
- .exists_one(collection, *identifiers, predicate, program:) ⇒ Object
- .filter(collection, *identifiers, predicate, program:) ⇒ Object
-
.has(invoke, program:) ⇒ Object
If e evaluates to a protocol buffers version 2 message and f is a defined field: If f is a repeated field or map field, has(e.f) indicates whether the field is non-empty.
- .map(collection, *identifiers, predicate, program:) ⇒ Object
- .matches(string, pattern, program: nil) ⇒ Object
- .size(literal, program: nil) ⇒ Object
- .with_context(collection, identifiers) ⇒ Object
Class Method Details
.all(collection, *identifiers, predicate, program:) ⇒ Object
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/cel/macro.rb', line 72 def all(collection, *identifiers, predicate, program:) identifiers = identifiers.map(&:to_sym) error = nil return_value = with_context(collection, identifiers).map do |context| program.with_extra_context(context).evaluate(predicate).value rescue StandardError => e error = e end has_false = return_value.include?(false) # if any predicate evaluates to false, the macro evaluates to false, ignoring any errors # from other predicates. raise error if error && !has_false Bool.cast(!has_false) end |
.exists(collection, *identifiers, predicate, program:) ⇒ Object
91 92 93 94 95 96 97 98 |
# File 'lib/cel/macro.rb', line 91 def exists(collection, *identifiers, predicate, program:) identifiers = identifiers.map(&:to_sym) return_value = with_context(collection, identifiers).any? do |context| program.with_extra_context(context).evaluate(predicate).value end Bool.cast(return_value) end |
.exists_one(collection, *identifiers, predicate, program:) ⇒ Object
100 101 102 103 104 105 106 107 108 109 |
# File 'lib/cel/macro.rb', line 100 def exists_one(collection, *identifiers, predicate, program:) identifiers = identifiers.map(&:to_sym) # This macro does not short-circuit in order to remain consistent with logical operators # being the only operators which can absorb errors within CEL. return_value = with_context(collection, identifiers).select do |context| program.with_extra_context(context).evaluate(predicate).value end Bool.cast(return_value.size == 1) end |
.filter(collection, *identifiers, predicate, program:) ⇒ Object
111 112 113 114 115 116 117 118 119 120 |
# File 'lib/cel/macro.rb', line 111 def filter(collection, *identifiers, predicate, program:) identifiers = identifiers.map(&:to_sym) return_value = with_context(collection, identifiers).filter_map do |context| next unless program.with_extra_context(context).evaluate(predicate).value context.values.last end List.new(return_value) end |
.has(invoke, program:) ⇒ Object
If e evaluates to a protocol buffers version 2 message and f is a defined field:
If f is a repeated field or map field, has(e.f) indicates whether the field is non-empty.
If f is a singular or oneof field, has(e.f) indicates whether the field is set.
If e evaluates to a protocol buffers version 3 message and f is a defined field:
If f is a repeated field or map field, has(e.f) indicates whether the field is non-empty.
If f is a oneof or singular field, has(e.f) indicates whether the field is set.
If f is some other singular field, has(e.f) indicates whether the field's value is its default
value (zero for numeric fields, false for booleans, empty for strings and bytes).
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/cel/macro.rb', line 15 def has(invoke, program:) func = invoke.func var = program.disable_cel_conversion do program.evaluate(invoke.var) end case var when Protobuf.base_class # If e evaluates to a message and f is not a declared field for the message, # has(e.f) raises a no_such_field error. raise NoSuchFieldError.new(var, func) unless var.respond_to?(func) value = var.public_send(func) field = var.class.descriptor.lookup(func.to_s) if field.label == :repeated # If f is a repeated field or map field, has(e.f) indicates whether the field is non-empty. Bool.cast(field.get(var).size.positive?) elsif field.has_presence? # If f is a oneof or singular message field, has(e.f) indicates whether the field is set. Bool.cast(field.has?(var)) else # If f is some other singular field, has(e.f) indicates whether the field's value is its # default value (zero for numeric fields, false for booleans, empty for strings and bytes). value = field.get(var) case field.type when :bool Bool.cast(value == true) when :string, :bytes Bool.cast(!value.empty?) when :enum Bool.cast(value != field.default) else Bool.cast(value != 0) end end when Map # If e evaluates to a map, then has(e.f) indicates whether the string f # is a key in the map (note that f must syntactically be an identifier). Bool.cast(var.respond_to?(func)) else # In all other cases, has(e.f) evaluates to an error. raise EvaluateError, "#{invoke} is not supported" end end |
.map(collection, *identifiers, predicate, program:) ⇒ Object
122 123 124 125 126 127 128 129 |
# File 'lib/cel/macro.rb', line 122 def map(collection, *identifiers, predicate, program:) identifiers = identifiers.map(&:to_sym) return_value = with_context(collection, identifiers).map do |context| program.with_extra_context(context).evaluate(predicate) end List.new(return_value) end |
.matches(string, pattern, program: nil) ⇒ Object
66 67 68 69 70 |
# File 'lib/cel/macro.rb', line 66 def matches(string, pattern, program: nil) pattern = program.evaluate(pattern) if program pattern = Regexp.new(pattern) Bool.cast(pattern.match?(string)) end |
.size(literal, program: nil) ⇒ Object
61 62 63 64 |
# File 'lib/cel/macro.rb', line 61 def size(literal, program: nil) literal = program.evaluate(literal) if program Cel::Number.new(:int, program.evaluate(literal).size) end |
.with_context(collection, identifiers) ⇒ Object
131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/cel/macro.rb', line 131 def with_context(collection, identifiers) case collection when Map raise EvaluateError, "can only support 2 identifiers" unless identifiers.size <= 2 else collection = collection.each_cons(identifiers.size) end collection.map do |elements| identifiers.zip(elements).to_h end end |