I want to generate a vector of bytes (Vec<u8>
in Rust) and access it with JS as an Array
or Uint8Array
and send it to a WebSocket or to IndexedDB.
I found How can I pass an array from JavaScript to Rust that has been compiled with Emscripten?, which is the exact opposite of what I would like to do, but very relevant. Other than that, I am aware of the array type in Emscripten, but I am not aware how to correctly use it.
My best guess on how to get this working was to try returning the vector as_mut_ptr
, and use the pointer on the Module.HEAPU8
.
main.rs
#[no_mangle]
pub fn bytes() -> *mut u8 {
vec![1, 2, 3].as_mut_ptr()
}
fn main() {}
Part of index.html
var Module = {
wasmBinaryFile: "site.wasm",
onRuntimeInitialized: main,
};
function main() {
let ptr = Module._bytes();
console.log(ptr);
console.log(Module.HEAPU8.slice(ptr, ptr + 10));
console.log(Module.HEAPU8.subarray(ptr, ptr + 100));
let arr = Module.cwrap('bytes', 'array', []);
console.log(arr());
}
The results of the console ended up looking like this:
5260296 site:11:13
Uint8Array [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] site:12:13
Uint8Array [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90 more… ] site:13:13
5260296 site:15:13
The first issue is that both values represent empty arrays, and second the two separate calls are pointing to the same memory location. I have absolutely no idea how to access pointed to data on the heap, along with the length of the vector.
The two pointers pointing to the same memory location could be because Rust drops the Vec<u8>
write when it's lifetime ends, (end of the bytes
) function.
Sorry if I missed some basics of Wasm and Emscripten, I only built my first Wasm hello world today.