Skip to content

feat(codegen): native Rust generator (typed requests + events)#64

Draft
Ivansete-status wants to merge 3 commits into
native-eventsfrom
rust-native-codegen
Draft

feat(codegen): native Rust generator (typed requests + events)#64
Ivansete-status wants to merge 3 commits into
native-eventsfrom
rust-native-codegen

Conversation

@Ivansete-status

Copy link
Copy Markdown
Collaborator

What

Native (zero-serialization) Rust generator, emitted alongside the CBOR Rust crate — the Rust counterpart of the native C/Go/C++ work in this stack. rust.nim is split into rust_cbor.nim + rust_native.nim (mirroring cpp.nim/cpp_native.nim); the native and CBOR crates write to separate output dirs (rust_native_bindings vs rust_bindings).

  • <lib>_native crate (ffi.rs / types.rs / api.rs / lib.rs) with #[repr(C)] POD mirrors, idiomatic structs, and to_c/from_c.
  • Requests: scalars, strings, bools, floats, nested structs, sequences (Vec) and optionals (Option). to_c returns a holder owning the CStrings and C-array backing on the heap, so the C struct's raw pointers survive the move and stay valid for the call (the lib deep-copies). from_c reads seq via slice::from_raw_parts and Option via a present-flag.
  • Native typed events: per-event add_<wire>_listener(closure) registers through the bare native entry point; the extern "C" trampoline reads the raw C-POD payload and hands the consumer a borrowed idiomatic value via from_c — no CBOR on the hot path. The node owns the boxed closures in a Mutex<HashMap<id, Box<dyn Any>>>; remove_event_listener drops them.
  • -d:ffiMode gating + genbindings_rust_native nimble task. Also includes the _cbor request-export fix for the CBOR crate.

Builds on #62 (native event delivery).

Test

The generated demo round-trips version / echo / complex (seq-of-structs + seq-of-strings + two optionals) / schedule (three struct params), fires on_echo_fired inline delivering a typed EchoEvent with zero CBOR, and removes the listener cleanly — validated against the live dylib.

🤖 Generated with Claude Code

Ivansete-status and others added 3 commits May 31, 2026 18:51
…or.nim split

Splits the Rust codegen the way C++ is split: rename `rust.nim` -> `rust_cbor.nim`
(CBOR) and add `rust_native.nim` (native). Dispatch on `targetLang=rust` now
honours `-d:ffiMode` (native/cbor); the crates share file names so each mode
writes its own dir (rust_bindings vs rust_native_bindings).

`rust_native.nim` emits a `<lib>_native` crate — the Rust analogue of
`cpp_native`: `#[repr(C)]` POD mirrors + `extern "C"` native entry points
(ffi.rs); idiomatic structs with `to_c`/`from_c`, a holder owning the CStrings
for the call (types.rs); and a `<Lib>Node` whose methods marshal typed args in /
read typed struct returns out, blocking via std mpsc (api.rs).

First cut: scalar/string/bool/float/nested-struct fields (create/version/echo);
seq/Option params are SKIPPED, native events next. Verified end-to-end — the
generated crate builds and the demo round-trips a typed EchoResponse. Tasks:
genbindings_rust (CBOR), genbindings_rust_native.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extends the native Rust marshalling to sequences and optionals (the Rust
counterpart of the cpp_native increment): a field maps to Vec<T> / Option<T>,
the repr(C) mirror gains the matching `{ ptr, len }` / `{ present, value }`
fields, and `to_c` now returns a holder owning the CStrings + C-array backing
(Vec/CString live on the heap, so the C struct's raw pointers survive the move
and the call). `from_c` reads seq/Option back out via slice + present-flag.

Unblocks the timer's complex (seq-of-structs / seq-of-strings / two optionals)
and schedule (three struct params). Verified end-to-end — the demo round-trips
typed ComplexResponse / ScheduleResult.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds native (zero-CBOR) event support to the Rust generator, mirroring the
cpp_native / Go event path: a per-event `add_<wire>_listener` registrar takes a
closure, boxes it, and registers it through the bare `<lib>_add_event_listener`
(native) entry point. The extern "C" trampoline reads the payload as the raw
C-POD struct and hands the consumer a borrowed idiomatic value via from_c — no
serialization on the hot path.

The node owns the boxed closures in a Mutex<HashMap<id, Box<dyn Any>>> keyed by
listener id so they outlive the call, and `remove_event_listener` drops them and
calls the bare remove entry point. Event externs are only emitted when the
library declares events, so event-free crates stay minimal.

Verified end-to-end: the demo registers a listener, echo fires on_echo_fired
inline, the typed EchoEvent reaches the closure, and removal returns true.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant