Attribute Macro sledgehammer_bindgen::bindgen

source ·
Expand description

Generates bindings for batched calls to js functions. The generated code is a Buffer struct with methods for each function.

The function calls to the generated methods are queued and only executed when flush is called.

Some of the code generated uses the sledgehammer_utils crate, so you need to add that crate as a dependency.

mod js {
    // You can define a struct to hold the data for the batched calls.
    struct Buffer;

    // JS is a special constatant that defines initialization javascript. It can be used to set up the js environment and define the code that wasm-bindgen binds to.
    const JS: &str = r#"
        const text = ["hello"];

        export function get(id) {
            console.log("got", text[id]);
            return text[id];

    // extern blocks allow communicating with wasm-bindgen. The javascript linked is the JS constant above.
    extern "C" {
        fn get(id: u32) -> String;

    // valid number types are u8, u16, u32.
    fn takes_numbers(n1: u8, n2: u16, n3: u32) {
        // this is the js code that is executed when takes_numbers is called.
        // dollar signs around the arguments mark that the arguments are safe to inline (they only appear once).
        // you can escape dollar signs with a backslash.
        r#"console.log($n1$, $n2$, $n3$, "\$");"#

    // valid string types are &str<u8>, &str<u16>, &str<u32>.
    // the generic parameter is the type of the length of the string. u32 is the default.
    fn takes_strings(str1: &str, str2: &str<u8>) {
        "console.log($str1$, $str2$);"

    // you can also use the &str<SIZE, cache_name> syntax to cache the string in a js variable.
    // each cache has a name that can be reused throughout the bindings so that different functions can share the same cache.
    // the cache has a size of 128 values.
    // caches on static strings use the pointer to hash the string which is faster than hashing the string itself.
    fn takes_cachable_strings(str1: &str<u8, cache1>, str2: &'static str<u16, cache2>) {
        "console.log($str1$, $str2$);"

    // Writable allows you to pass in any type that implements the Writable trait.
    // Because all strings are encoded in a sequental buffer, every string needs to be copied to the new buffer.
    // If you only create a single string from a Arguments<'_> or number, you can use the Writable trait to avoid allocting a string and then copying it.
    // the generic parameter is the type of the length of the resulting string. u32 is the default.
    fn takes_writable(writable: impl Writable<u8>) {

    // valid types are &[u8], &[u16], &[u32].
    // the generic parameter is the type of the length of the array. u32 is the default.
    fn takes_slices(slice1: &[u8], slice2: &[u8<u16>]) {
        "console.log($slice1$, $slice2$);"

let mut channel1 = Buffer::default();
let mut channel2 = Buffer::default();
channel1.takes_strings("hello", "world");
channel1.takes_numbers(1, 2, 3);
channel1.takes_cachable_strings("hello", "world");
channel1.takes_cachable_strings("hello", "world");
channel1.takes_cachable_strings("hello", "world");
channel1.takes_writable(format_args!("hello {}", "world"));
// append can be used to append the calls from one channel to another.
channel2.takes_slices(&[1, 2, 3], &[4, 5, 6]);
// flush executes all the queued calls and clears the queue.
assert_eq!(get(0), "hello");