web-rpc
Bidirectional RPC for browsing contexts, web workers, and message channels. Inspired by Google's tarpc: define a service as a trait, annotate, and the macro generates the client and server. JS-bearing types (anything AsRef<JsValue>) are auto-routed through postMessage; everything else through bincode. Put the trait definition in a shared crate so both ends share it.
The macro generates CalculatorClient, CalculatorService, and a Calculator trait you implement on the server side:
;
Wire up over a MessageChannel (or a Worker / MessagePort):
let channel = new.unwrap;
let = join.await;
let server = new
.
.build;
spawn_local;
let client = new
.
.build;
assert_eq!;
Features
- Auto-routing of JS vs serializable types: types implementing
AsRef<JsValue>(e.g.JsString,OffscreenCanvas) are posted; everything else is serialized using bincode. Option/Resultwrappers (and nested): each variant routes independently, so types likeResult<JsT, RustError>andResult<Option<JsT>, _>just work.- Bidirectional RPC over a single channel, with both ends simultaneously acting as client and server.
- Streaming RPCs via
impl Stream<Item = T>returns, with abort-on-drop and close-and-drain. - Transfer semantics via
#[transfer(...)]: bare params, derived expressions (data => data.buffer()), refutable closures (return => |Ok(buf)| buf.buffer()), ormatch-blocks. - Async or sync server methods, with per-request cancellation when the client drops the future of an RPC method that returns.
- Notifications: methods with no return type are fire-and-forget.
- Borrowed
&str/&[u8]: zero-copy deserialization on the server side.
See the crate documentation for the full feature reference. Need help with your latest project? Get in touch via contact@allwright.io. I'm available for new assignments.