Module: Kobako::Codec::HandleWalk
- Defined in:
- lib/kobako/codec/handle_walk.rb,
sig/kobako/codec/handle_walk.rbs
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. 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 — signedint 64minimum through unsigneduint 64maximum (docs/wire-codec.md § Type Mapping #3, thefixint/int 8..64/uint 8..64union). 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).
Instance Method Summary collapse
- #self?.container_representable? ⇒ Boolean
- #self?.deep_restore ⇒ Object
- #self?.deep_wrap ⇒ Object
- #self?.primitive_type? ⇒ Boolean
- #self?.representable? ⇒ Boolean
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.
125 126 127 128 129 130 131 |
# File 'lib/kobako/codec/handle_walk.rb', line 125 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 wherever a guest→host payload carries
one — an invocation result, a yield-block result, or a dispatch
argument. 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.
96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/kobako/codec/handle_walk.rb', line 96 def deep_restore(value, handler) case value when ::Array then value.map { |element| HandleWalk.deep_restore(element, handler) } when ::Hash # Rebuilt with each key restored: two distinct Handle keys that # resolve to equal host objects collapse to the later pair, as in # any Ruby Hash. The guest authored this payload, so that collapse # is its own concern, not a fidelity guarantee the host owes it. 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).
71 72 73 74 75 76 77 78 |
# File 'lib/kobako/codec/handle_walk.rb', line 71 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.
113 114 115 116 117 118 119 |
# File 'lib/kobako/codec/handle_walk.rb', line 113 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.
45 46 47 |
# File 'lib/kobako/codec/handle_walk.rb', line 45 def representable?(value) primitive_type?(value) || container_representable?(value) end |
Instance Method Details
#self?.container_representable? ⇒ Boolean
14 |
# File 'sig/kobako/codec/handle_walk.rbs', line 14
def self?.container_representable?: (untyped value) -> bool
|
#self?.deep_restore ⇒ Object
10 |
# File 'sig/kobako/codec/handle_walk.rbs', line 10
def self?.deep_restore: (untyped value, Kobako::Catalog::Handles handler) -> untyped
|
#self?.deep_wrap ⇒ Object
8 |
# File 'sig/kobako/codec/handle_walk.rbs', line 8
def self?.deep_wrap: (untyped value, Kobako::Catalog::Handles handler) -> untyped
|
#self?.primitive_type? ⇒ Boolean
12 |
# File 'sig/kobako/codec/handle_walk.rbs', line 12
def self?.primitive_type?: (untyped value) -> bool
|
#self?.representable? ⇒ Boolean
6 |
# File 'sig/kobako/codec/handle_walk.rbs', line 6
def self?.representable?: (untyped value) -> bool
|