Typesafe language bindings generator for the Tauri IPC bridge
APACHE-2.0 License
Bot releases are visible (Hide)
As part of the ongoing IPC improvements for Tauri, we're working on a new IPC router that is faster, simpler, offers a better developer experience than the current one and brings new features to the table that weren't possible before.
This release let's you play with a preview WIP version of this router (re-exported as tauri_bindgen_host::ipc_router_wip
).
Defining commands looks like this now:
use tauri_bindgen_host::ipc_router_wip::{Router, BuilderExt};
fn main() {
// notice that router is generic, this is the so called "Context"
// for this simple example we don't need to worry about it
let mut router = Router::new(());
router.func_wrap("app", "foo", || -> tauri_bindgen_host::Result<()> {
println!("foo");
Ok(())
});
router.func_wrap("app", "add", |a: u32, b: u32| -> tauri_bindgen_host::Result<u32> {
Ok(a + b)
});
tauri::Builder::default()
.ipc_router(router)
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
The Router
keeps track of all the commands defined within it, as well as maintaining "Context" data that your commands can access:
use tauri_bindgen_host::ipc_router_wip::{Router, Caller, BuilderExt};
fn main() {
#[derive(Default)]
struct Context {
ch: Option<char>
}
let mut router = Router::new(Context::default());
router.func_wrap("app", "take_char", |ctx:: Caller<Context>, ch: char| -> tauri_bindgen_host::Result<()> {
ctx.data_mut().ch = Some(ch);
Ok(())
})
router.func_wrap("app", "return_char", |ctx:: Caller<Context>| -> tauri_bindgen_host::Result<Option<ch>> {
Ok(ctx.data_mut().ch.take())
})
tauri::Builder::default()
.ipc_router(router)
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
When using tauri-bindgen
s code generation, the generated module exports an add_to_router
function that takes care of defining your commands for you:
use tauri_bindgen_host::ipc_router_wip::{Router, Caller, BuilderExt};
tauri_bindgen_host::generate!({
path: "example/chars.wit"
});
#[derive(Default)]
struct CharsCtx {
ch: Option<char>
}
impl chars::Chars for CharsCtx {
fn take_char(&mut self, ch: char) -> tauri_bindgen_host::Result<()> {
self.ch = Some(ch);
Ok(())
}
fn return_char(&mut self) -> tauri_bindgen_host::Result<Option<char>> {
Ok(self.ch.take())
}
}
fn main() {
#[derive(Default)]
struct Context {
chars_ctx: CharsCtx
}
let mut router = Router::new(Context::default());
chars::add_to_router(&mut router, |ctx| ctx.chars_ctx)
tauri::Builder::default()
.ipc_router(router)
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
Note All of this is subject to change over time, feel free to give feedback!
This WIP IPC router implementation also packs another cool punch: It uses a custom protocol to transmit messages between the Webview and Core. This means that performance will be much better and we finally have support for sending arbitrary binary payloads something we make use of for the next feature:
One bottleneck we identified is that dues to web view limitations the current IPC system is limited to sending JSON. This caused many problems, for one JSON can't encode arbitrary binary data, so sending bytes across the IPC boundary was a big performance issue. Another problem is the the overly simplistic type system of JSON, we would love to send Option<T>
or Result<T, E>
values across the IPC boundary and have them be preserved correctly, but not with JSON.
That's why this release also switches to a new data serialisation format: postcard
. This means IPC messages are much smaller, support sending binary data without overhead and allow more expressive types.
host
, guest rust
, guest javascript
, and guest typescript
Codegen TargetsAll these changes means that almost all of this project is now in a state where I would consider it usable. So all targets except for markdown doc generation will be enabled by default now.
guest javascript
and guest typescript
Currently the javascript targets have a couple known issues pertaining to the encoding and decoding:
BigInt
would be the suitable type for u64
, but for s64
?), take a look at #122option<T>
types as T | null
but that means that means nested options aren't preserved. If you have ideas around this take a look at #123Published by JonasKruckenberg over 1 year ago
resource
implementationThis adds the initial implementation of the resource
type.
A resource
represents a handle to a resource owned by the Host - similar to a file descriptor in posix - resources
have associated methods that allow Guests to interact with them.
A resource
is essentially just syntactic sugar for a u64
. This identifier is guaranteed to be unique and will be used by the Host to index into a ResourceTable
to retrieve the actual data backing the resource
.
interface foo {
resource bar {
func greet(name: string) -> string
}
func get_bar() -> bar
}
This represents an important addition to the type system of tauri-bindgen
as resource
s allow us to better model many real-world situations (like Tauri's Window
objects) while minimising the amount of data being sent over the IPC bridge as well as restricting Guests access to system resources.
To try this initial implementation, enable the unstable
feature flag.
Previously in some situations functions that didn't return anything (func foo(x: string)
) would generate code that returned an empty tuple. This version doesn't generate these empty tuples anymore, making generated code easier to use.
Files containing deprecated or discouraged unicode code points will now be rejected, this makes .wit
files more portable and reliable as a IDL format.
Previously parsing a .wit
file with comments that contained non-latin unicode code points would cause a panic. This version fixes that issue which means comments can be written in all scripts supported by unicode.
Published by JonasKruckenberg over 1 year ago
There is now an online version of this tool!
It always reflects the latest developments and allows you to play around with the interface definition language and see the code generated results or any produced errors. It is very bare bones right now, but it will receive more features and better design as time goes on.
Visit bindgen.tauri.tech to check it out!
check
subcommandThe tauri-bindgen
command let's you check .wit
files for errors.
Currently check
makes sure no identifier is undefined or defined twice, that types aren't recursively referring to themselves and that no type definitions are unused.
This release also stabilized the syntax and grammar of .wit
files.
This means that no breaking changes in the file format are expected! You can find details about the interface definition language in the docs
subfolder.
The rust code generation has been completely rewritten from scratch to use the quote
, proc_macro2
and syn
crates.
This makes rust code generation much more maintainable, easier to reason about and much more future proof than the old string based approach. The refactor is not yet complete though, so for the time being all code generation is hidden behind the unstable
flag. Stay tuned to a future release when this restriction is lifted.