Module: Kobako::Codec::ExtTypes
- Defined in:
- lib/kobako/codec/ext_types.rb,
sig/kobako/codec/ext_types.rbs
Overview
The kobako wire ext-type conversions
(docs/wire/payload-msgpack.md § Ext Types)
as pure functions: per-operation decode state is threaded in as an
argument, so the module itself holds nothing. #build_factory assembles
the one MessagePack::Factory these conversions are registered on.
Constant Summary collapse
- EXT_SYMBOL =
MessagePack ext type code reserved for Symbol (docs/wire/payload-msgpack.md § Ext Types → ext 0x00). Module-private — mirrors
codec::EXT_SYMBOLon the Rust side. 0x00- EXT_HANDLE =
MessagePack ext type code reserved for Capability Handle (docs/wire/payload-msgpack.md § Ext Types → ext 0x01). Module-private — mirrors
codec::EXT_HANDLEon the Rust side. 0x01- UNREPRESENTABLE_GUARD_ID =
Inert ext id the unrepresentable-value guard registers under. It is never emitted (the guard's packer always raises) and never decoded (no unpacker is registered, so the id stays an UnknownExtTypeError on the wire), so it is not a wire ext type: deliberately not named
EXT_*like the two real ext codes, since it has no Rust-side mirror and must stay outside the wire-symmetry inventory. 0x7F
Class Method Summary collapse
-
.build_factory ⇒ Object
Assemble a
MessagePack::Factorywith the two kobako ext types plus the unrepresentable-value guard registered, frozen because registration is its only mutation and happens exactly once. -
.pack_handle(handle) ⇒ Object
Handle-id packer for the ext-0x01 registration: the fixext-4 big-endian id frame.
-
.pack_symbol(symbol) ⇒ Object
Symbol-to-name packer for the ext-0x00 registration.
- .register_handle(factory) ⇒ Object
- .register_symbol(factory) ⇒ Object
-
.register_unrepresentable(factory) ⇒ Object
A catch-all packer that rejects any value with no wire representation as
UnsupportedTypeError. -
.unpack_handle(payload, state) ⇒ Object
Peel off the fixext-4 frame, hand the bytes to the Host-Gem-internal
Kobako::Handle.restorefactory, and translate theArgumentErrorraised by Handle's invariants into a wire-layerInvalidTypeErrorvia Codec::Utils.with_boundary. -
.unpack_symbol(payload) ⇒ Object
Validate the ext-0x00 payload as UTF-8 and intern.
Instance Method Summary collapse
- #self?.build_factory ⇒ MessagePack::Factory
- #self?.pack_handle ⇒ String
- #self?.pack_symbol ⇒ String
- #self?.register_handle ⇒ void
- #self?.register_symbol ⇒ void
- #self?.register_unrepresentable ⇒ void
- #self?.unpack_handle ⇒ Kobako::Handle
- #self?.unpack_symbol ⇒ Symbol
Class Method Details
.build_factory ⇒ Object
Assemble a MessagePack::Factory with the two kobako ext types plus
the unrepresentable-value guard registered, frozen because
registration is its only mutation and happens exactly once. The
stateful conversions resolve their per-operation state at call time,
so one registered factory serves every thread.
46 47 48 49 50 51 52 |
# File 'lib/kobako/codec/ext_types.rb', line 46 def build_factory factory = MessagePack::Factory.new register_symbol(factory) register_handle(factory) register_unrepresentable(factory) factory.freeze end |
.pack_handle(handle) ⇒ Object
Handle-id packer for the ext-0x01 registration: the fixext-4 big-endian id frame.
75 76 77 |
# File 'lib/kobako/codec/ext_types.rb', line 75 def pack_handle(handle) [handle.id].pack("N") end |
.pack_symbol(symbol) ⇒ Object
Symbol-to-name packer for the ext-0x00 registration.
55 56 57 |
# File 'lib/kobako/codec/ext_types.rb', line 55 def pack_symbol(symbol) symbol.name end |
.register_handle(factory) ⇒ Object
103 104 105 106 107 108 109 |
# File 'lib/kobako/codec/ext_types.rb', line 103 def register_handle(factory) factory.register_type( EXT_HANDLE, Kobako::Handle, packer: ->(handle) { ExtTypes.pack_handle(handle) }, unpacker: ->(payload) { ExtTypes.unpack_handle(payload, State.current) } ) end |
.register_symbol(factory) ⇒ Object
95 96 97 98 99 100 101 |
# File 'lib/kobako/codec/ext_types.rb', line 95 def register_symbol(factory) factory.register_type( EXT_SYMBOL, Symbol, packer: ->(symbol) { ExtTypes.pack_symbol(symbol) }, unpacker: ->(payload) { ExtTypes.unpack_symbol(payload) } ) end |
.register_unrepresentable(factory) ⇒ Object
A catch-all packer that rejects any value with no wire representation
as UnsupportedTypeError. Registered on BasicObject so it also covers
BasicObject-based proxies; the narrower Symbol / Handle
registrations still win by most-specific match, and native types never
reach it. Packer-only: the guard never writes bytes, so its id is inert
and the decode surface stays fail-closed.
This makes the host's non-wire detection a positive allowlist — a value
outside the type set is rejected here rather than routed to to_msgpack
— matching the guest's classname allowlist and the Rust codec's closed
Value enum. Without it, a value with a permissive method_missing
answers the codec's to_msgpack probe and mis-encodes as nil instead
of crossing as a Capability Handle.
124 125 126 127 128 129 |
# File 'lib/kobako/codec/ext_types.rb', line 124 def register_unrepresentable(factory) factory.register_type( UNREPRESENTABLE_GUARD_ID, BasicObject, packer: ->(_value) { raise UnsupportedTypeError, "value has no wire representation" } ) end |
.unpack_handle(payload, state) ⇒ Object
Peel off the fixext-4 frame, hand the bytes to the
Host-Gem-internal Kobako::Handle.restore factory, and
translate the ArgumentError raised by Handle's invariants
into a wire-layer InvalidTypeError via Codec::Utils.with_boundary.
The Value Object owns the id-range contract; this method only
owns the frame shape. Records the Handle sighting on state so a
Handle-free decode can skip the downstream resolution walk.
86 87 88 89 90 91 92 93 |
# File 'lib/kobako/codec/ext_types.rb', line 86 def unpack_handle(payload, state) state.record_handle! bytes = payload.b raise InvalidTypeError, "Handle payload must be 4 bytes, got #{bytes.bytesize}" unless bytes.bytesize == 4 id = bytes.unpack1("N") # : Integer Codec::Utils.with_boundary { Kobako::Handle.restore(id) } end |
.unpack_symbol(payload) ⇒ Object
Validate the ext-0x00 payload as UTF-8 and intern. Raises
InvalidEncodingError on invalid bytes — SPEC forbids the
binary-encoding fallback that msgpack-gem's default unpacker
would otherwise apply. The re-tag step lives here because the
msgpack ext-type unpacker hands us binary bytes; the assertion
itself is shared with Decoder via Utils.assert_utf8!. The
"Symbol" label keeps the error message in Ruby vocabulary
rather than wire-ext-code vocabulary.
67 68 69 70 71 |
# File 'lib/kobako/codec/ext_types.rb', line 67 def unpack_symbol(payload) name = payload.b.force_encoding(Encoding::UTF_8) Utils.assert_utf8!(name, "Symbol payload") name.to_sym end |
Instance Method Details
#self?.build_factory ⇒ MessagePack::Factory
8 |
# File 'sig/kobako/codec/ext_types.rbs', line 8
def self?.build_factory: () -> MessagePack::Factory
|
#self?.pack_handle ⇒ String
14 |
# File 'sig/kobako/codec/ext_types.rbs', line 14
def self?.pack_handle: (Kobako::Handle handle) -> String
|
#self?.pack_symbol ⇒ String
10 |
# File 'sig/kobako/codec/ext_types.rbs', line 10
def self?.pack_symbol: (Symbol symbol) -> String
|
#self?.register_handle ⇒ void
This method returns an undefined value.
20 |
# File 'sig/kobako/codec/ext_types.rbs', line 20
def self?.register_handle: (MessagePack::Factory factory) -> void
|
#self?.register_symbol ⇒ void
This method returns an undefined value.
18 |
# File 'sig/kobako/codec/ext_types.rbs', line 18
def self?.register_symbol: (MessagePack::Factory factory) -> void
|
#self?.register_unrepresentable ⇒ void
This method returns an undefined value.
22 |
# File 'sig/kobako/codec/ext_types.rbs', line 22
def self?.register_unrepresentable: (MessagePack::Factory factory) -> void
|
#self?.unpack_handle ⇒ Kobako::Handle
16 |
# File 'sig/kobako/codec/ext_types.rbs', line 16
def self?.unpack_handle: (String payload, State state) -> Kobako::Handle
|
#self?.unpack_symbol ⇒ Symbol
12 |
# File 'sig/kobako/codec/ext_types.rbs', line 12
def self?.unpack_symbol: (String payload) -> Symbol
|