1 unstable release
0.1.0 | May 1, 2023 |
---|
#1867 in Procedural macros
1,557 downloads per month
56KB
1.5K
SLoC
A crate to make working with wasm-bindgen
easier.
This crate contains the wasm_bindgen_struct
macro which
can be used to declare wasm_bindgen
types, and implement
getters/setter as if they were normal rust structs. It can
also be used to implement methods for the type, including inline
mapping to overcome wasm-bindgen-futures
limitations.
Example
// Or you can use this instead to avoid needing to import
// the macro throughout your crate
// #[macro_use]
// extern crate wasm_bindgen_struct;
use wasm_bindgen_struct::wasm_bindgen_struct;
#[wasm_bindgen_struct]
// `module` here means this type comes from the JS "my-module" module
// with the class name `aAnotherType`
#[opts(module = "my-module", js_name = "AnotherType")]
struct MyJsType {
// field names are automatically converted to `camelCase`
field_a: String,
// ...but can be manually specified if needed
#[opts(js_name = "field_b")]
field_b: String,
}
#[wasm_bindgen_struct]
#[opts(module = "my-module")]
impl MyJsType {
// Automatically gets the `static_method_of = MyJsType` applied,
// as well as `catch` due to the `Result`
fn apple() -> Result<String, JsValue>;
// `async` functions in `wasm-bindgen` can only currently return
// `()`, `JsValue`, or Result<_, JsValue>`, where `_` is one of
// the two previously mentioned types. We use `MapValue<T, U>`
// to tell the macro that the binding method should return `T`,
// but we'll map the value to `U`
async fn oranges(&self) -> MapValue<JsValue, String> {
self
.oranges_js()
.await
.unchecked_into::<js_sys::JsString>()
.into()
}
}
The above expands to:
// For getters/setters
#[wasm_bindgen(module = "my-module")]
extern "C" {
#[wasm_bindgen(js_name = "AnotherType")]
type MyJsType;
#[wasm_bindgen(
method,
getter,
js_class = "AnotherType",
js_name = "fieldA"
)]
fn field_a(this: &MyJsType) -> String;
#[wasm_bindgen(
method,
setter,
js_class = "AnotherType",
js_name = "fieldA"
)]
fn set_field_a(this: &MyJsType, value: String);
#[wasm_bindgen(
method,
getter,
js_class = "AnotherType",
js_name = "field_b"
)]
fn field_b(this: &MyJsType) -> String;
#[wasm_bindgen(
method,
setter,
js_class = "AnotherType",
js_name = "field_b"
)]
fn set_field_b(this: &MyJsType, value: String);
}
// And for methods
impl MyJsType {
fn apple() -> Result<String, JsValue> {
#[wasm_bindgen(module = "my-module")]
extern "C" {
#[wasm_bindgen(static_method_of = MyJsType, js_name = "apple")]
#[wasm_bindgen(catch)]
fn apple_js() -> Result<String, JsValue>;
}
Self::apple_js()
}
async fn oranges(&self) -> String {
#[wasm_bindgen(module = "my-module")]
extern "C" {
#[wasm_bindgen(method, js_name = "oranges")]
async fn oranges_js(this: &MyJsType) -> JsValue;
}
self
.oranges_js()
.await
.unchecked_into::<js_sys::JsString>()
.into()
}
}
#[opts(...)]
on structs
-
dbg:
bool
Show the formatted output of the macro as a warning
-
on:
Type
Allows using an existing type with the struct syntax.
Example
#[wasm_bindgen] extern "C" { type JsType; } #[wasm_bindgen_struct] #[opts(on = JsType)] // Struct can be named anything, it doesn't matter struct JsType { field_1: bool, }
-
<unknown>
Unknown attributes, such as doc comments, are forwarded to the
type MyType
declaration, or ignored in the case of usingon
.
#[opts(...)]
on struct fields
#[opts(...)]
on impl
-
dbg: bool
Show the formatted output of the macro as a warning
#[opts(...)]
on impl
methods
- constructor:
bool
- final_:
bool
- structural:
bool
- getter:
bool
- setter:
bool
- indexing_getter:
bool
- indexing_setter:
bool
- indexing_deleter:
bool
- js_name:
Lit
- variadic:
bool
Treatment of Special Types
-
Result<T, E>
Implies
catch
. -
MapValue<T, U>
Allows specifing the types of the generated
wasm-bindgen
binding, as well as the actual method type. This allows arbitrary transformations between the bound method and the output method.Example
#[wasm_bindgen_struct] struct JsType; #[wasm_bindgen_struct] impl JsType { async fn get_async_string(&self) -> MapValue<JsValue, String> { self .get_async_string_js() .await .unchecked_into::<js_sys::JsString>() .into() } }
Important note
MapValue
is a pseudo-type which only exists within the macro's scope. i.e., this type does not exist outside of#[wasm_bindgen_struct] impl { /* ... */ }
and therefore does not need to be imported.
Dependencies
~1–1.4MB
~30K SLoC