Module: Kobako::Codec::HandleWalk
- Defined in:
- lib/kobako/codec/handle_walk.rb
Overview
Substitutes Capability Handles into and out of a Ruby value tree at the host↔guest boundary. HandleWalk.deep_wrap allocates a Kobako::Handle for each non-wire-representable leaf on the host→guest #run argument path; HandleWalk.deep_restore resolves each wire-decoded Handle back to its host object on every guest→host value path — the #eval / #run result and the yield-block result alike. HandleWalk.representable? is the by-value codec-type predicate that decides which leaves HandleWalk.deep_wrap must wrap: the closed 12-entry wire type set (docs/wire-codec.md § Type Mapping).
All helpers are pure except HandleWalk.deep_wrap, whose only side effect is allocating new Handle ids into the supplied table.
Constant Summary collapse
- MSGPACK_INT_RANGE =
Inclusive Integer range the msgpack gem encodes without raising
RangeErrorat encode time — signed int 64 minimum through unsigned uint 64 maximum (docs/wire-codec.md § Type Mapping #3, thefixint/ int 8..64 / uint 8..64 union). Anchored as aRangeso primitive_type? stays a single dispatch line. This is the codec’s encode domain — not to be confused with the Handle id range, which lives onKobako::HandleasMIN_ID/MAX_ID(1..2^31 − 1) and represents a different concept entirely. (-(2**63)..((2**64) - 1))
Class Method Summary collapse
-
.container_representable?(value) ⇒ Boolean
The container branch of HandleWalk.representable?: recurses into Array elements and Hash key+value pairs through the public HandleWalk.representable?.
-
.deep_restore(value, handler) ⇒ Object
Deep-walk Array / Hash containers in
valueand replace everyKobako::Handleleaf with the host-side objecthandlerresolves it to. -
.deep_wrap(value, handler) ⇒ Object
Deep-walk Array / Hash containers in
valueand replace every leaf that fails HandleWalk.representable? with aKobako::Handleallocated fromhandler. -
.primitive_type?(value) ⇒ Boolean
The non-container branch of HandleWalk.representable?: returns
truefor the scalar leaves and an existing Handle. -
.representable?(value) ⇒ Boolean
Codec-type predicate (docs/wire-codec.md § Type Mapping).
Class Method Details
.container_representable?(value) ⇒ Boolean
The container branch of representable?: recurses into Array elements and Hash key+value pairs through the public representable?. Not part of the public surface; reach for representable? instead.
122 123 124 125 126 127 128 |
# File 'lib/kobako/codec/handle_walk.rb', line 122 def container_representable?(value) case value when ::Array then value.all? { |element| HandleWalk.representable?(element) } when ::Hash then value.all? { |key, val| HandleWalk.representable?(key) && HandleWalk.representable?(val) } else false end end |
.deep_restore(value, handler) ⇒ Object
Deep-walk Array / Hash containers in value and replace every Kobako::Handle leaf with the host-side object handler resolves it to. The symmetric inverse of deep_wrap: that walk allocates objects into Handles on the host→guest argument path; this walk resolves Handles back to their objects on every guest→host value path — the #eval / #run result and the yield-block result alike. The walk descends through Array elements and Hash keys and values one structural level at a time; any non-Handle leaf passes through unchanged.
value is a decoded Ruby value (a Handle here is a wire-decoded Kobako::Handle, never a guest-forged one); handler must respond to #fetch(id) -> object (a host-side Kobako::Catalog::Handles). handler.fetch raises Kobako::SandboxError for an id with no live binding, the corrupted-runtime fallback.
97 98 99 100 101 102 103 104 105 |
# File 'lib/kobako/codec/handle_walk.rb', line 97 def deep_restore(value, handler) case value when ::Array then value.map { |element| HandleWalk.deep_restore(element, handler) } when ::Hash value.to_h { |key, val| [HandleWalk.deep_restore(key, handler), HandleWalk.deep_restore(val, handler)] } when Kobako::Handle then handler.fetch(value.id) else value end end |
.deep_wrap(value, handler) ⇒ Object
Deep-walk Array / Hash containers in value and replace every leaf that fails representable? with a Kobako::Handle allocated from handler. The walk only descends through representable container shapes (Array, Hash) one structural level at a time; a non-representable leaf is wrapped as-is without inspecting its internal structure. An existing Kobako::Handle is representable and passes through unchanged — auto-wrap never re-wraps a Handle.
value may be any Ruby value; handler must respond to #alloc(object) -> Kobako::Handle (a host-side Kobako::Catalog::Handles). Returns a structurally equivalent value whose leaves are either representable or Kobako::Handle tokens.
The block bodies spell HandleWalk.deep_wrap explicitly rather than the unqualified deep_wrap because module_function makes the instance copy of these helpers private; an implicit receiver inside a block would resolve against the enclosing self (still HandleWalk at definition time, but the qualified form keeps the dispatch readable when the recursive call sits inside a Proc captured from elsewhere).
72 73 74 75 76 77 78 79 |
# File 'lib/kobako/codec/handle_walk.rb', line 72 def deep_wrap(value, handler) case value when ::Array then value.map { |element| HandleWalk.deep_wrap(element, handler) } when ::Hash then value.transform_values { |val| HandleWalk.deep_wrap(val, handler) } else representable?(value) ? value : handler.alloc(value) end end |
.primitive_type?(value) ⇒ Boolean
The non-container branch of representable?: returns true for the scalar leaves and an existing Handle. Not part of the public surface; reach for representable? instead.
110 111 112 113 114 115 116 |
# File 'lib/kobako/codec/handle_walk.rb', line 110 def primitive_type?(value) case value when ::NilClass, ::TrueClass, ::FalseClass, ::Float, ::String, ::Symbol, Kobako::Handle then true when ::Integer then MSGPACK_INT_RANGE.cover?(value) else false end end |
.representable?(value) ⇒ Boolean
Codec-type predicate (docs/wire-codec.md § Type Mapping). Returns true when value belongs to the closed 12-entry codec type set — nil, TrueClass, FalseClass, Integer (in the i64..u64 value domain), Float, String, Symbol, Kobako::Handle, Array whose every element is itself representable, or Hash whose every key and value are representable. Integers outside the codec’s signed-64 / unsigned-64 union are rejected so the predicate agrees with the msgpack gem’s encode-time RangeError behaviour the codec already surfaces as UnsupportedType.
46 47 48 |
# File 'lib/kobako/codec/handle_walk.rb', line 46 def representable?(value) primitive_type?(value) || container_representable?(value) end |