Class: Kobako::Snippet::Table

Inherits:
Object
  • Object
show all
Defined in:
lib/kobako/snippet/table.rb

Overview

Kobako::Snippet::Table — 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 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). 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 table 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

#initializeTable

Returns a new instance of Table.



34
35
36
# File 'lib/kobako/snippet/table.rb', line 34

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

Instance Method Details

#eachObject

Iterate over registered entries in insertion order. Yields each entry (a Kobako::Snippet::Source or Kobako::Snippet::Binary). Returns an Enumerator when no block is given.



84
85
86
# File 'lib/kobako/snippet/table.rb', line 84

def each(&)
  @entries.each(&)
end

#empty?Boolean

Whether no snippets are registered.

Returns:

  • (Boolean)


102
103
104
# File 'lib/kobako/snippet/table.rb', line 102

def empty?
  @entries.empty?
end

#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 table serializes to an empty array, never absent. The wire codec is an implementation detail — callers receive a binary String that the Kobako::Wasm layer ships through the invocation channel. Mirrors the Kobako::RPC.encode_request pattern: entry value objects stay pure carriers, this method reads their attributes externally.



46
47
48
# File 'lib/kobako/snippet/table.rb', line 46

def encode
  MessagePack.pack(@entries.map { |entry| entry_payload(entry) })
end

#namesObject

Canonical names of every registered Source entry, in insertion order. Binary entries are skipped — their names live in bytecode debug_info on the guest side and are not extracted by the host.



92
93
94
# File 'lib/kobako/snippet/table.rb', line 92

def names
  @entries.filter_map { |entry| entry.name if entry.is_a?(Source) }
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).



71
72
73
74
75
76
77
78
79
# File 'lib/kobako/snippet/table.rb', line 71

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

#sizeObject

Number of registered snippets.



97
98
99
# File 'lib/kobako/snippet/table.rb', line 97

def size
  @entries.size
end