3
votes

I want to have a WebAssembly function (compiled from Rust) that takes a JavaScript Buffer as an argument and writes data to the buffer. I then want to be able to use this buffer and interact with the data from the JavaScript context.

I'm using wasm-bindgen to export the WebAssembly structs to JavaScript but I don't know how I can use the JavaScript Buffer inside the WebAssembly.

This is a simplified version of what I want the Rust source code to look like:

struct Element {
    a: u8,
    b: String,
}

impl Element {
    fn new(a: u8, b: &str) -> Element {
        Element {
            a: a,
            b: String::from(b),
        }
    }

    fn copy_into(&self, buffer: Buffer) {
        let mut offset = 0;
        buffer[offset] = self.a;
        offset += std::mem::size_of::<u8>();
        buffer[offset] = self.b;
    }
}

This is what I want to do in the JavaScript context:

// Code for importing Element and instantiating the wasm module omitted.

let element = new Element(1, 'abc');
let buffer = Buffer.allocUnsafe(4);
element.copy_into(buffer);

console.log(buffer.toString('hex'));

I want the console.log at the end of above code to print '01616263' to the console. I want to achieve this without having to allocate new memory in WebAssembly and copying the contents. Instead, I want to write directly to the JavaScript memory, where buffer is a pointer to that memory.

How can I accomplish this by somehow importing the Buffer to Rust?

1

1 Answers

2
votes

You can't import it directly, and the code you posted is the correct way to do it. WASM cannot touch JS buffers directly outside of its memory. That's how WASM is sandboxed, to protect the host environment (JS), for security reason.

You may be able to boost the speed of copy_into. You can write the copy operation in JS side, instead of walking through the buffer in Rust side. This will be faster especially for large buffer because JS will perform a block copy operation internally.