feat(codegen): native Rust generator (typed requests + events)#64
Draft
Ivansete-status wants to merge 3 commits into
Draft
feat(codegen): native Rust generator (typed requests + events)#64Ivansete-status wants to merge 3 commits into
Ivansete-status wants to merge 3 commits into
Conversation
…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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.nimis split intorust_cbor.nim+rust_native.nim(mirroringcpp.nim/cpp_native.nim); the native and CBOR crates write to separate output dirs (rust_native_bindingsvsrust_bindings).<lib>_nativecrate (ffi.rs/types.rs/api.rs/lib.rs) with#[repr(C)]POD mirrors, idiomatic structs, andto_c/from_c.Vec) and optionals (Option).to_creturns a holder owning theCStrings 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_creads seq viaslice::from_raw_partsand Option via a present-flag.add_<wire>_listener(closure)registers through the bare native entry point; theextern "C"trampoline reads the raw C-POD payload and hands the consumer a borrowed idiomatic value viafrom_c— no CBOR on the hot path. The node owns the boxed closures in aMutex<HashMap<id, Box<dyn Any>>>;remove_event_listenerdrops them.-d:ffiModegating +genbindings_rust_nativenimble task. Also includes the_cborrequest-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), fireson_echo_firedinline delivering a typedEchoEventwith zero CBOR, and removes the listener cleanly — validated against the live dylib.🤖 Generated with Claude Code