Files
hakorune/docs/reference/plugin-abi/nyash_abi_v2.md

6.6 KiB
Raw Blame History

Nyash Plugin ABI v2 (TypeBox)

Overview

  • Purpose: unify plugin invocation via perBox TypeBox exports and a simple TLV wire format.
  • Design: loader resolves a perBox dispatch function once, then calls by (instance_id, method_id, TLV args) → TLV result.
  • Stability: v2 opts for simplicity over backward compatibility. Migrate plugins to v2; legacy C ABI entry remains available only for bootstrapping during transition.

Error Codes

  • 0: OK
  • -1: E_SHORT (output buffer too small; twophase protocol)
  • -2: E_TYPE (invalid type for call)
  • -3: E_METHOD (unknown method id)
  • -4: E_ARGS (invalid/malformed args)
  • -5: E_PLUGIN (internal plugin error/missing TypeBox)
  • -8: E_HANDLE (invalid instance handle)

TLV Encoding (version=1)

  • Header: 2 bytes u16 version (1), 2 bytes u16 argc
  • Entries: repeated blocks [tag: u8, reserved: u8=0, size: u16 LE, payload: [size]]
  • Tags
    • 1: bool (size=1; 0/1)
    • 2: i32 (size=4; LE)
    • 3: i64 (size=8; LE)
    • 4: f32 (size=4; LE)
    • 5: f64 (size=8; LE)
    • 6: string (UTF8)
    • 7: bytes
    • 8: plugin handle (type_id:u32 + instance_id:u32)
    • 9: host handle (u64)

TwoPhase Result Protocol

  • On first call, host may pass result=NULL or a small buffer.
  • Plugin returns E_SHORT and writes required size to *result_len.
  • Host reallocates and retries; on success return 0 and fill result.

TypeBox Export

  • Each plugin Box publishes a single symbol: nyash_typebox_<BoxName> with C layout:

    struct NyashTypeBoxFfi { uint32_t abi_tag; // 'TYBX' = 0x54594258 uint16_t version; // 1 uint16_t struct_size; // sizeof(NyashTypeBoxFfi) const char* name; // "FileBox\0", etc. uint32_t (resolve)(const char method_name); // optional int32_t (invoke_id)(uint32_t instance_id, uint32_t method_id, const uint8_t args, size_t args_len, uint8_t* out, size_t* out_len); uint64_t capabilities; // reserved };

Naming Conventions

  • Symbol: nyash_typebox_<Box> where <Box> is the Box type (e.g., FileBox, RegexBox).
  • Methods: prefer lowerCamelCase in resolve names (e.g., setStatus, readBody, isMatch).
  • Boxes live in one shared library and are listed under [libraries."<libname>"].boxes in nyash.toml.

Examples

  • RegexBox (methods: birth/compile/isMatch/find/replaceAll/split/fini)

    • resolve → method_id → invoke_id: decode TLV → run regex → encode TLV
    • Export nyash_typebox_RegexBox with resolve and invoke_id pointers.
  • Net (Client/Response/Request minimal)

    • ClientBox: get(url), post(url, body) → returns Handle(Response)
    • ResponseBox: setStatus(i32), setHeader(name,value), write(bytes|string), getStatus(), readBody()
    • RequestBox: path(), readBody(), respond(Response)
    • Each Box exports its own TypeBox symbol (e.g., nyash_typebox_ClientBox).

nyash.toml Layout

  • Declare libraries and perBox metadata:

    [libraries] [libraries."libnyash_regex_plugin.so"] boxes = ["RegexBox"] path = "plugins/nyash-regex-plugin/target/release/libnyash_regex_plugin.so"

    [libraries."libnyash_regex_plugin.so".RegexBox] type_id = 52 abi_version = 1 [libraries."libnyash_regex_plugin.so".RegexBox.methods] birth = { method_id = 0 } compile = { method_id = 1 } isMatch = { method_id = 2 }

Error Handling Patterns

  • Twophase output (E_SHORT) is mandatory for large or variable results.
  • For invalid handles/args, return -8 / -4 respectively; host commonly wraps these into ResultBox in higher layers.

Invoke Semantics

  • Birth: method_id=0, instance_id=0. Returns 4byte LE instance_id (not TLV).
  • Fini: method_id=UINT32_MAX, instance_id=target. Should release resources and return OK with TLV void or 0entry TLV.
  • Regular methods: return TLV payloads per method contract.

Host Expectations

  • Host looks up perBox function from the TypeBox symbol and calls it via a librarylevel shim.
  • If no TypeBox is exported for a box, the call fails with E_PLUGIN.
  • Method ids and type ids are configured in nyash.toml under [libraries].

Minimal C Header

  • See include/nyash_abi.h for a readytouse header and constants.

Notes

  • Keep result payloads small; prefer handles (tag=8) for large data and stream APIs.
  • Use UTF8 strings (tag=6) for humanreadable values; use bytes (tag=7) otherwise.

Method Tables (TLV Contracts)

  • RegexBox

    • birth(0): returns handle (RegexBox)
    • compile(1): args [string pattern]; returns OK
    • isMatch(2): args [string text]; returns [bool]
    • find(3): args [string text]; returns [string match]
    • replaceAll(4): args [string text, string repl]; returns [string]
    • split(5): args [string text, i64 limit?]; returns [string joined by "\n"]
    • fini(MAX): returns OK
  • Net — Client/Response/Request

    • ClientBox
      • birth(0): returns handle (ClientBox)
      • get(1): args [string url]; returns handle (ResponseBox)
      • post(2): args [string url, bytes|string body]; returns handle (ResponseBox)
      • fini(MAX)
    • ResponseBox
      • birth(0)
      • setStatus(1): args [i32]
      • setHeader(2): args [string name, string value]
      • write(3): args [bytes|string]
      • readBody(4): returns [bytes]
      • getStatus(5): returns [i32]
      • getHeader(6): args [string name]; returns [string]
      • fini(MAX)
    • RequestBox
      • birth(0): returns handle (RequestBox)
      • path(1): returns [string]
      • readBody(2): returns [bytes]
      • respond(3): args [handle(ResponseBox)]
      • fini(MAX)

Phase12 Alignment & Roadmap

  • Alignment: The Phase12 “Unified TypeBox ABI” is a superset of this v2 minimal design. It shares the same core shape: perBox TypeBox export, method_id dispatch, and TLV arguments/results.
  • Current focus (v2 minimal): simplicity and portability for firstparty plugins (Regex/Net/File/Path/Math/Time/Python family). The loader probes nyash_typebox_<Box> and calls invoke_id with (instance_id, method_id, TLV).
  • Forward compatibility: hosts validate struct_size and version. Future minor extensions can add optional fields to NyashTypeBoxFfi while preserving existing layout. Keep capabilities=0 for now.
  • Planned extensions (Phase16/17 candidates):
    • create/destroy function pointers (birth/fini remain for backward safety)
    • get_type_info() style metadata discovery (can be added via a resolved method first)
    • method table slotting and stricter signature IDs for faster dispatch
    • NyValue bridge and BoxHeader/vtable integration for RC/GC cooperation and JIT IC
  • Guidance: implementers should target v2 minimal today. When Phase12 features land, they will be additive, with migration guides and host shims to keep existing v2 plugins working.