Module: Ruby::Rego::Builtins::Bits

Extended by:
RegistryHelpers
Defined in:
lib/ruby/rego/builtins/bits.rb

Overview

Built-in bitwise helpers (bits.and/or/xor/negate/lsh/rsh). Operands are integers (integer-valued floats like 12.0 are accepted; non-integers yield an undefined result), and operations use two’s-complement infinite precision, matching OPA (Go big.Int).

Constant Summary collapse

BITS_FUNCTIONS =
{
  "bits.and" => { arity: 2, handler: :bits_and },
  "bits.or" => { arity: 2, handler: :bits_or },
  "bits.xor" => { arity: 2, handler: :bits_xor },
  "bits.negate" => { arity: 1, handler: :negate },
  "bits.lsh" => { arity: 2, handler: :lsh },
  "bits.rsh" => { arity: 2, handler: :rsh }
}.freeze
MAX_LSH_RESULT_BITS =

Upper bound on a left-shift result’s bit length. OPA computes arbitrarily large shifts (slowly), but this pure-Ruby evaluator has no cancellation, so an untrusted policy could otherwise force unbounded allocation. Exceeding the limit yields an undefined result rather than exhausting memory — a deliberate divergence from OPA, affecting only left shifts (the sole growth vector).

1 << 25

Class Method Summary collapse

Methods included from RegistryHelpers

register_configured_functions

Class Method Details

.bits_and(left, right) ⇒ Ruby::Rego::NumberValue

Parameters:

Returns:



46
47
48
# File 'lib/ruby/rego/builtins/bits.rb', line 46

def self.bits_and(left, right)
  NumberValue.new(integer(left, "bits.and") & integer(right, "bits.and"))
end

.bits_or(left, right) ⇒ Ruby::Rego::NumberValue

Parameters:

Returns:



53
54
55
# File 'lib/ruby/rego/builtins/bits.rb', line 53

def self.bits_or(left, right)
  NumberValue.new(integer(left, "bits.or") | integer(right, "bits.or"))
end

.bits_xor(left, right) ⇒ Ruby::Rego::NumberValue

Parameters:

Returns:



60
61
62
# File 'lib/ruby/rego/builtins/bits.rb', line 60

def self.bits_xor(left, right)
  NumberValue.new(integer(left, "bits.xor") ^ integer(right, "bits.xor"))
end

.lsh(value, shift) ⇒ Ruby::Rego::NumberValue

Parameters:

Returns:



73
74
75
76
77
78
# File 'lib/ruby/rego/builtins/bits.rb', line 73

def self.lsh(value, shift)
  base = integer(value, "bits.lsh")
  amount = shift_amount(shift, "bits.lsh")
  ensure_lsh_within_limit(base, amount)
  NumberValue.new(base << amount)
end

.negate(value) ⇒ Ruby::Rego::NumberValue

Parameters:

Returns:



66
67
68
# File 'lib/ruby/rego/builtins/bits.rb', line 66

def self.negate(value)
  NumberValue.new(~integer(value, "bits.negate"))
end

.register!Ruby::Rego::Builtins::BuiltinRegistry



35
36
37
38
39
# File 'lib/ruby/rego/builtins/bits.rb', line 35

def self.register!
  registry = BuiltinRegistry.instance
  register_configured_functions(registry, BITS_FUNCTIONS)
  registry
end

.rsh(value, shift) ⇒ Ruby::Rego::NumberValue

Parameters:

Returns:



83
84
85
# File 'lib/ruby/rego/builtins/bits.rb', line 83

def self.rsh(value, shift)
  NumberValue.new(integer(value, "bits.rsh") >> shift_amount(shift, "bits.rsh"))
end