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-codec.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-codec.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-codec.md § Ext Types → ext 0x01). Module-private — mirrors
codec::EXT_HANDLEon the Rust side. 0x01- EXT_ERRENV =
MessagePack ext type code reserved for Exception envelope (docs/wire-codec.md § Ext Types → ext 0x02). Module-private — mirrors
codec::EXT_ERRENVon the Rust side. 0x02
Class Method Summary collapse
-
.build_factory ⇒ Object
Assemble a
MessagePack::Factorywith the three kobako ext types registered, frozen because registration is its only mutation and happens exactly once. -
.pack_fault(fault, state) ⇒ Object
Encode the inner ext-0x02 map via Encoder (not the raw factory) so the embedded payload flows through the same boundary as a top-level encode — nested kobako values (Handle, nested Fault) reach the registered ext-type packers.
-
.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_fault(factory) ⇒ Object
- .register_handle(factory) ⇒ Object
- .register_symbol(factory) ⇒ Object
-
.unpack_fault(payload, state) ⇒ Object
Peel the embedded msgpack map and hand it to
Kobako::Fault.newinside Decoder.decode's block form, so the value-object'sArgumentErrorinvariants surface asInvalidTypethrough the decoder boundary. -
.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-layerInvalidTypevia 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_fault ⇒ String
- #self?.pack_handle ⇒ String
- #self?.pack_symbol ⇒ String
- #self?.register_fault ⇒ void
- #self?.register_handle ⇒ void
- #self?.register_symbol ⇒ void
- #self?.unpack_fault ⇒ Kobako::Fault
- #self?.unpack_handle ⇒ Kobako::Handle
- #self?.unpack_symbol ⇒ Symbol
Class Method Details
.build_factory ⇒ Object
Assemble a MessagePack::Factory with the three kobako ext types
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.
43 44 45 46 47 48 49 |
# File 'lib/kobako/codec/ext_types.rb', line 43 def build_factory factory = MessagePack::Factory.new register_symbol(factory) register_handle(factory) register_fault(factory) factory.freeze end |
.pack_fault(fault, state) ⇒ Object
Encode the inner ext-0x02 map via Encoder (not the raw factory) so
the embedded payload flows through the same boundary as a top-level
encode — nested kobako values (Handle, nested Fault) reach the
registered ext-type packers. A details chain nested past the
state depth cap has no wire representation and surfaces as
UnsupportedType. In a payload position (+state+ inside a
forbid_faults bracket) the envelope has no wire representation at
all, so the refusal routes the value into the position's
non-representable handling — the Dispatcher's auto-wrap rescue,
or a raise at the yield site.
102 103 104 105 106 107 108 109 110 |
# File 'lib/kobako/codec/ext_types.rb', line 102 def pack_fault(fault, state) if state.faults_forbidden? raise UnsupportedType, "Kobako::Fault has no wire representation in a payload position" end state.within_ext_frame(UnsupportedType) do Encoder.encode("type" => fault.type, "message" => fault., "details" => fault.details) end end |
.pack_handle(handle) ⇒ Object
Handle-id packer for the ext-0x01 registration: the fixext-4 big-endian id frame.
72 73 74 |
# File 'lib/kobako/codec/ext_types.rb', line 72 def pack_handle(handle) [handle.id].pack("N") end |
.pack_symbol(symbol) ⇒ Object
Symbol-to-name packer for the ext-0x00 registration.
52 53 54 |
# File 'lib/kobako/codec/ext_types.rb', line 52 def pack_symbol(symbol) symbol.name end |
.register_fault(factory) ⇒ Object
153 154 155 156 157 158 159 |
# File 'lib/kobako/codec/ext_types.rb', line 153 def register_fault(factory) factory.register_type( EXT_ERRENV, Kobako::Fault, packer: ->(fault) { ExtTypes.pack_fault(fault, State.current) }, unpacker: ->(payload) { ExtTypes.unpack_fault(payload, State.current) } ) end |
.register_handle(factory) ⇒ Object
145 146 147 148 149 150 151 |
# File 'lib/kobako/codec/ext_types.rb', line 145 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
137 138 139 140 141 142 143 |
# File 'lib/kobako/codec/ext_types.rb', line 137 def register_symbol(factory) factory.register_type( EXT_SYMBOL, Symbol, packer: ->(symbol) { ExtTypes.pack_symbol(symbol) }, unpacker: ->(payload) { ExtTypes.unpack_symbol(payload) } ) end |
.unpack_fault(payload, state) ⇒ Object
Peel the embedded msgpack map and hand it to Kobako::Fault.new
inside Decoder.decode's block form, so the value-object's
ArgumentError invariants surface as InvalidType through the
decoder boundary. Inner decode goes through Decoder (not the raw
factory) so the embedded str payloads flow through the same
UTF-8 validation as a top-level decode. A nested ext 0x02 in
details re-enters this method, so the state ext-frame guard
bounds the chain depth to keep it from exhausting the native stack.
In a payload position (+state+ inside a forbid_faults bracket) the
envelope is a wire violation outright — its sole legal position is
the Response fault field.
123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/kobako/codec/ext_types.rb', line 123 def unpack_fault(payload, state) if state.faults_forbidden? raise InvalidType, "Fault envelope (ext 0x02) is not a legal value in a payload position" end state.within_ext_frame(InvalidType) do Decoder.decode(payload) do |map| raise InvalidType, "Fault payload must be a map" unless map.is_a?(Hash) Kobako::Fault.new(type: map["type"], message: map["message"], details: map["details"]) end end 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 InvalidType 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.
83 84 85 86 87 88 89 90 |
# File 'lib/kobako/codec/ext_types.rb', line 83 def unpack_handle(payload, state) state.record_handle! bytes = payload.b raise InvalidType, "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
InvalidEncoding 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.
64 65 66 67 68 |
# File 'lib/kobako/codec/ext_types.rb', line 64 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_fault ⇒ String
18 |
# File 'sig/kobako/codec/ext_types.rbs', line 18
def self?.pack_fault: (Kobako::Fault fault, State state) -> String
|
#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_fault ⇒ void
This method returns an undefined value.
26 |
# File 'sig/kobako/codec/ext_types.rbs', line 26
def self?.register_fault: (MessagePack::Factory factory) -> void
|
#self?.register_handle ⇒ void
This method returns an undefined value.
24 |
# File 'sig/kobako/codec/ext_types.rbs', line 24
def self?.register_handle: (MessagePack::Factory factory) -> void
|
#self?.register_symbol ⇒ void
This method returns an undefined value.
22 |
# File 'sig/kobako/codec/ext_types.rbs', line 22
def self?.register_symbol: (MessagePack::Factory factory) -> void
|
#self?.unpack_fault ⇒ Kobako::Fault
20 |
# File 'sig/kobako/codec/ext_types.rbs', line 20
def self?.unpack_fault: (String payload, State state) -> Kobako::Fault
|
#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
|