Class: Kobako::Catalog::Snippets
- Inherits:
-
Object
- Object
- Kobako::Catalog::Snippets
- Defined in:
- lib/kobako/catalog/snippets.rb
Overview
Kobako::Catalog::Snippets — per-Sandbox insertion-ordered registry of preloaded snippets.
Entries replay against the fresh mrb_state before per-invocation source / entrypoint resolution. Each Snippet::Source entry’s name is its canonical identity — the filename baked into the loaded IREP’s debug_info that surfaces in every backtrace frame originating from the snippet as (snippet:Name):line. Duplicate names within the code: form would produce ambiguous attribution and are rejected at registration time. Snippet::Binary entries carry no host-side name — their canonical name lives in the bytecode’s debug_info and is read by the guest at load time; the host does not extract it.
Sealing is governed by the owning Sandbox — the registry itself is append-only and exposes no mutation API beyond #register; the Sandbox guards #register behind the seal check before delegating.
Constant Summary collapse
- NAME_PATTERN =
Ruby constant-name pattern enforced on snippet names.
/\A[A-Z]\w*\z/
Instance Method Summary collapse
-
#encode ⇒ Object
Serialize the registered snippets to wire bytes.
-
#initialize ⇒ Snippets
constructor
A new instance of Snippets.
-
#register(code: nil, name: nil, binary: nil) ⇒ Object
Register one preloaded snippet in either of two forms.
Constructor Details
#initialize ⇒ Snippets
Returns a new instance of Snippets.
29 30 31 32 |
# File 'lib/kobako/catalog/snippets.rb', line 29 def initialize @entries = [] # : Array[Kobako::Snippet::Source | Kobako::Snippet::Binary] @encoded = nil # : String? end |
Instance Method Details
#encode ⇒ Object
Serialize the registered snippets to wire bytes. Each entry contributes a msgpack map shape; the collection rides as a single msgpack array. An empty registry serializes to an empty array, never absent. The wire codec is an implementation detail — callers receive a binary String that the Kobako::Runtime layer ships through the invocation channel. The entry value objects stay pure carriers — this collection-tier method reads their attributes externally via entry_payload rather than asking each entry to self-encode.
The bytes are memoized — the table is replayed verbatim on every invocation after sealing, so Frame 3 never changes between encodes; #register drops the memo while the table is still open.
47 48 49 50 51 |
# File 'lib/kobako/catalog/snippets.rb', line 47 def encode return @encoded if @encoded @encoded = Codec::Encoder.encode(@entries.map { |entry| entry_payload(entry) }).freeze end |
#register(code: nil, name: nil, binary: nil) ⇒ Object
Register one preloaded snippet in either of two forms.
* Source form +register(code: src, name: Name)+ — +src+ is the
mruby source as a String; the bytes are re-encoded as UTF-8
and detached from the caller's reference. +name+ is a Symbol
or String matching +NAME_PATTERN+. Returns the Symbol form
of +name+.
* Binary form +register(binary: bytes)+ — +bytes+ is
precompiled RITE bytecode as a String, duplicated and forced
to ASCII-8BIT so msgpack-ruby ships it as +bin+. Returns
+nil+ — bytecode entries are anonymous on the host side; any
structural validation is deferred to the guest at first replay.
The two forms are mutually exclusive: shape validation lives here so callers (chiefly Kobako::Sandbox#preload) collapse to a single delegation. Raises ArgumentError on mixed forms, missing keywords, wrong types, malformed name, or duplicate code: name.
71 72 73 74 75 76 77 78 79 80 |
# File 'lib/kobako/catalog/snippets.rb', line 71 def register(code: nil, name: nil, binary: nil) @encoded = nil if binary raise ArgumentError, "cannot combine binary: with code: / name:" if code || name register_binary!(binary) else register_source!(code, name) end end |