Module: Ruby::Rego::Builtins::Numbers
- Extended by:
- RegistryHelpers
- Defined in:
- lib/ruby/rego/builtins/numbers.rb
Overview
Built-in numeric helpers (abs, round, ceil, floor, numbers.range, numbers.range_step).
Constant Summary collapse
- NUMBER_FUNCTIONS =
{ "abs" => { arity: 1, handler: :abs }, "round" => { arity: 1, handler: :round }, "ceil" => { arity: 1, handler: :ceil }, "floor" => { arity: 1, handler: :floor }, "numbers.range" => { arity: 2, handler: :range }, "numbers.range_step" => { arity: 3, handler: :range_step } }.freeze
- MAX_RANGE_SIZE =
Upper bound on
numbers.rangelength. OPA halts large ranges via context cancellation; this pure-Ruby evaluator has no such escape valve, so an untrusted policy could otherwise force unbounded allocation. Exceeding the limit yields an undefined result rather than exhausting memory. 1_000_000
Class Method Summary collapse
-
.abs(value) ⇒ Ruby::Rego::NumberValue
-
.ceil(value) ⇒ Ruby::Rego::NumberValue
-
.floor(value) ⇒ Ruby::Rego::NumberValue
-
.range(start_value, end_value) ⇒ Ruby::Rego::ArrayValue
Inclusive integer range, ascending or descending.
-
.range_step(start_value, end_value, step_value) ⇒ Ruby::Rego::ArrayValue
numbers.range_step(low, high, step): like numbers.range but advancing by a positive integer step; the endpoint is included only when it lands exactly on a step.
-
.register! ⇒ Ruby::Rego::Builtins::BuiltinRegistry
-
.round(value) ⇒ Ruby::Rego::NumberValue
Methods included from RegistryHelpers
Class Method Details
.abs(value) ⇒ Ruby::Rego::NumberValue
42 43 44 |
# File 'lib/ruby/rego/builtins/numbers.rb', line 42 def self.abs(value) NumberValue.new(normalize(numeric(value, "abs").abs)) end |
.ceil(value) ⇒ Ruby::Rego::NumberValue
54 55 56 |
# File 'lib/ruby/rego/builtins/numbers.rb', line 54 def self.ceil(value) NumberValue.new(numeric(value, "ceil").ceil) end |
.floor(value) ⇒ Ruby::Rego::NumberValue
60 61 62 |
# File 'lib/ruby/rego/builtins/numbers.rb', line 60 def self.floor(value) NumberValue.new(numeric(value, "floor").floor) end |
.range(start_value, end_value) ⇒ Ruby::Rego::ArrayValue
Inclusive integer range, ascending or descending.
Matches OPA: integer-valued floats (e.g. 3.0) are accepted as bounds, while a non-integer bound (e.g. 1.5) yields an undefined result.
72 73 74 75 76 77 78 |
# File 'lib/ruby/rego/builtins/numbers.rb', line 72 def self.range(start_value, end_value) start_bound = NumericHelpers.integer_value(start_value, context: "numbers.range") end_bound = NumericHelpers.integer_value(end_value, context: "numbers.range") ensure_size_within_limit((end_bound - start_bound).abs + 1, "numbers.range") ArrayValue.new(range_elements(start_bound, end_bound).map { |number| NumberValue.new(number) }) end |
.range_step(start_value, end_value, step_value) ⇒ Ruby::Rego::ArrayValue
numbers.range_step(low, high, step): like numbers.range but advancing by a positive integer step; the endpoint is included only when it lands exactly on a step. A non-positive or non-integer step yields undefined (matching OPA).
:reek:TooManyStatements
89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/ruby/rego/builtins/numbers.rb', line 89 def self.range_step(start_value, end_value, step_value) start_bound = NumericHelpers.integer_value(start_value, context: "numbers.range_step") end_bound = NumericHelpers.integer_value(end_value, context: "numbers.range_step") step = NumericHelpers.integer_value(step_value, context: "numbers.range_step") # ensure_positive_step must precede step_count, which divides by step. ensure_positive_step(step) ensure_size_within_limit(step_count(start_bound, end_bound, step), "numbers.range_step") elements = step_elements(start_bound, end_bound, step) ArrayValue.new(elements.map { |number| NumberValue.new(number) }) end |
.register! ⇒ Ruby::Rego::Builtins::BuiltinRegistry
32 33 34 35 36 |
# File 'lib/ruby/rego/builtins/numbers.rb', line 32 def self.register! registry = BuiltinRegistry.instance register_configured_functions(registry, NUMBER_FUNCTIONS) registry end |
.round(value) ⇒ Ruby::Rego::NumberValue
48 49 50 |
# File 'lib/ruby/rego/builtins/numbers.rb', line 48 def self.round(value) NumberValue.new(numeric(value, "round").round) end |