Class: Kobako::Catalog::Snippets

Inherits:
Object
  • Object
show all
Defined in:
lib/kobako/catalog/snippets.rb

Overview

Kobako::Catalog::Snippets — per-Sandbox insertion-ordered registry of preloaded snippets (docs/behavior.md B-32 / B-33).

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 (docs/behavior.md E-33). 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 (B-33) 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 (docs/behavior.md E-34).

/\A[A-Z]\w*\z/

Instance Method Summary collapse

Constructor Details

#initializeSnippets

Returns a new instance of Snippets.



32
33
34
# File 'lib/kobako/catalog/snippets.rb', line 32

def initialize
  @entries = [] # : Array[Kobako::Snippet::Source | Kobako::Snippet::Binary]
end

Instance Method Details

#encodeObject

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.



45
46
47
# File 'lib/kobako/catalog/snippets.rb', line 45

def encode
  Codec::Encoder.encode(@entries.map { |entry| entry_payload(entry) })
end

#register(code: nil, name: nil, binary: nil) ⇒ Object

Register one preloaded snippet in either of two forms (docs/behavior.md B-32).

* 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
  ({docs/behavior.md E-37 / E-38}[link:../../../docs/behavior.md])
  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 (E-34), or duplicate code: name (E-33).



70
71
72
73
74
75
76
77
78
# File 'lib/kobako/catalog/snippets.rb', line 70

def register(code: nil, name: nil, binary: nil)
  if binary
    raise ArgumentError, "cannot combine binary: with code: / name:" if code || name

    register_binary!(binary)
  else
    register_source!(code, name)
  end
end