feat(I203/M6): WASM Phase-2a callee streaming ABI #1

Merged
buildagent merged 1 commit from feat/i203-m6-wasm-callee-streaming into main 2026-05-29 17:03:28 +02:00
Member

Mission I203 / M6 — implements the WASM Phase-2a callee (server-stream) streaming ABI that sdk/ixt-public/wasm/ixt-wasm.h already declares but this crate didn't export.

  • extern "C" host imports byte-matched to the header + runtime (crates/ixt-core/src/runtime/wasm/host_functions.rs): stream_send_data(stream_id_ptr,len,payload_ptr,len)→i32, stream_send_close(...,reason)→i32, stream_send_error(...,code,msg_ptr,len)→i32.
  • Module export ixt_module_handle_server_stream(payload_ptr,len)→i32 (confirmed in built wasm).
  • Safe wrapper (src/streaming.rs): StreamSender (send_data/close/error → Result<(),i32>), StreamErrorCode (incl. Rejected=4), CloseReason, zero-copy StreamFrame::parse, ServerStreamHandler trait + dispatch_server_stream + ixt_wasm_server_stream! macro routing Open/Data/Close/Cancel/Error. #![no_std]+alloc, MIT-clean (no runtime-crate dep).
  • Callee/server-stream only per I203 scope (no WASM-side open_stream, no BidiStream initiation).
  • examples/stream_echo.rs builds to wasm.

Validation: cargo build --target wasm32-unknown-unknown (lib + examples) + cargo clippy --target wasm32 -- -D warnings clean. No header-vs-runtime mismatch (import names/params/return codes agree exactly). Note: host stream_send_data ABI has no end_of_message field (host sequences per call) — the callee send_data(payload, end_of_message) keeps it as an advisory param, documented.

(host-target cargo test/clippy --all-targets N/A — pre-existing custom panic_impl lang-item collides with the std test harness; not introduced here.)

🤖 Generated with Claude Code

Mission I203 / M6 — implements the WASM Phase-2a **callee** (server-stream) streaming ABI that `sdk/ixt-public/wasm/ixt-wasm.h` already declares but this crate didn't export. - `extern "C"` host imports byte-matched to the header + runtime (`crates/ixt-core/src/runtime/wasm/host_functions.rs`): `stream_send_data(stream_id_ptr,len,payload_ptr,len)→i32`, `stream_send_close(...,reason)→i32`, `stream_send_error(...,code,msg_ptr,len)→i32`. - Module export `ixt_module_handle_server_stream(payload_ptr,len)→i32` (confirmed in built wasm). - Safe wrapper (`src/streaming.rs`): `StreamSender` (send_data/close/error → `Result<(),i32>`), `StreamErrorCode` (incl. `Rejected=4`), `CloseReason`, zero-copy `StreamFrame::parse`, `ServerStreamHandler` trait + `dispatch_server_stream` + `ixt_wasm_server_stream!` macro routing Open/Data/Close/Cancel/Error. `#![no_std]`+alloc, MIT-clean (no runtime-crate dep). - **Callee/server-stream only** per I203 scope (no WASM-side `open_stream`, no BidiStream initiation). - `examples/stream_echo.rs` builds to wasm. **Validation:** `cargo build --target wasm32-unknown-unknown` (lib + examples) + `cargo clippy --target wasm32 -- -D warnings` clean. **No header-vs-runtime mismatch** (import names/params/return codes agree exactly). Note: host `stream_send_data` ABI has no `end_of_message` field (host sequences per call) — the callee `send_data(payload, end_of_message)` keeps it as an advisory param, documented. (host-target `cargo test`/`clippy --all-targets` N/A — pre-existing custom `panic_impl` lang-item collides with the std test harness; not introduced here.) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Implement the callee/server-stream side of the spec 23 §11 Phase-2a streaming
ABI in the WASM SDK. Scope is callee-only: a module RECEIVES an inbound stream
Open and emits Data/Close/Error frames back. Caller-side open_stream and
BidiStream initiation are deferred to Phase 2b (per I203 "do NOT build").

Host-fn imports (ixt namespace, byte-matched to ixt-public/wasm/ixt-wasm.h and
crates/ixt-core/src/runtime/wasm/host_functions.rs):
  stream_send_data(stream_id_ptr, stream_id_len, payload_ptr, payload_len) -> i32
  stream_send_close(stream_id_ptr, stream_id_len, reason) -> i32
  stream_send_error(stream_id_ptr, stream_id_len, code, message_ptr, message_len) -> i32

Module export (dispatch entry the runtime invokes per frame):
  ixt_module_handle_server_stream(payload_ptr, payload_len) -> i32

Safe surface (src/streaming.rs):
  - StreamSender { send_data(&[u8], end_of_message), close(CloseReason),
    error(StreamErrorCode, &str) } over the raw host fns.
  - StreamErrorCode enum incl. Rejected (=4); CloseReason enum; FrameKind.
  - StreamFrame zero-copy parser for the framed payload (kind byte | 16-byte
    stream_id | kind-specific tail), pinned to the runtime wire ordinals.
  - ServerStreamHandler trait + ixt_wasm_server_stream! macro that generates
    the export and wires Open/Data/Close/Cancel/Error callbacks; OpenDecision
    maps Accept->IXT_OK and Reject(code)->non-zero (runtime issues Cancel{Callee}).
  - Added err::OK constant.

#![no_std]+alloc; no dependency on the proprietary runtime crate. New
examples/stream_echo.rs builds to wasm. cargo build --target
wasm32-unknown-unknown and cargo clippy --lib --examples -D warnings clean;
new files fmt-clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
h-dv/ixt-sdk-wasm!1
No description provided.