Let me ask how to pass an array holding uint8 elements from javascript to wasm in Rust fast?
I found one method in: As JsValue.
Though I wonder if there is some clearly faster one when all element values are same primitive type and in a particular range.
For example, you encode a uint8 array to a string then pass the string to wasm not through JsValue.
Or I wonder if you can pass any array of primitive element type to wasm not through JsValues.
Edit: After reading the first answer, I tried to follow the answer with my understanding as follows. It seems to be successful. Is my understanding correct?
import * as wasm from "../pkg";
import * as bg_wasm from '../pkg/PACKAGE_NAME_bg.wasm';
const RUST_STRUCT = wasm.RUST_STRUCT.new();
const cellsPtr = RUST_STRUCT.cells();
const cells = new Uint8Array(bg_wasm.memory.buffer, cellsPtr, 100);
console.log( cells[50]);// 0
for(let i=0;i<100;i++){cells[i]=i;}
console.log( cells[50]);//50
console.log( "end");
The WASM virtual machine has its own memory address space, that is seen from JS as a big ArrayBuffer
usually named wasm.memory
. Any value that you pass from JS to WASM has to be copied from its own variable to that memory.
But there is a nice trick. If you allocate a buffer from Rust side, such a Vec<u8>
, and then somehow pass a reference to it to JS, then the &mut [u8]
will become a JS Uint8Array
, that is actually a direct view of the Rust memory. Zero copy overhead.
You just have to be careful not to use the reference from JS in a way that breaks any Rust invariant, such as passing it back as another reference, such that you get two &mut _
to the same value. Also you have to keep this memory alive in Rust for as long as JS holds the reference. It may even be a good idea to call Vec::leak()
into your buffer so that its memory lives forever.