The maintainer of this website has a Spotify Coding Playlist of their Lo-fi Hip Hop beats!
Outra funcionalidade do WebAssembly é a memória linear. A memória linear é um faixa contínua de bytes sem sinal que podem ser lidos e escritos tanto pelo Wasm como pelo Javascript. Em outras palavras, a memória do Wasm é uma matriz expansível de bytes que podem ser lidas e modificadas de forma síncrona. A memória linear pode ser usada para muitas coisas, uma delas é passar valores de lá para cá e de cá para lá entre o Wasm e o Javascript.
Em rust, as ferramentas como o wasm-bindgen, que é parte do fluxo de trabalho do wasm-pack, abstraem o uso da memória linear, e permite usar estruturas de dados nativas entre o rust e o Javascript. Mas neste exemplo vamos usar espaços de memória e ponteiros (índices de matrix de memória do Wasm) de um único byte (um inteiro de 8-bit sem sinal) como uma maneira mais simples de movimentar a memória e exibir o conceito.
Vejamos como podemos usar a memória linear:
Primeiro, adicionamos o seguinte ao arquivo src/lib.rs
:
// The wasm-pack uses wasm-bindgen to build and generate JavaScript binding file.
// Import the wasm-bindgen crate.
use wasm_bindgen::prelude::*;
// Create a static mutable byte buffer.
// We will use for passing memory between js and wasm.
// NOTE: global `static mut` means we will have "unsafe" code
// but for passing memory between js and wasm should be fine.
const WASM_MEMORY_BUFFER_SIZE: usize = 2;
static mut WASM_MEMORY_BUFFER: [u8; WASM_MEMORY_BUFFER_SIZE] = [0; WASM_MEMORY_BUFFER_SIZE];
// Function to store the passed value at index 0,
// in our buffer
#[wasm_bindgen]
pub fn store_value_in_wasm_memory_buffer_index_zero(value: u8) {
unsafe {
WASM_MEMORY_BUFFER[0] = value;
}
}
// Function to return a pointer to our buffer
// in wasm memory
#[wasm_bindgen]
pub fn get_wasm_memory_buffer_pointer() -> *const u8 {
let pointer: *const u8;
unsafe {
pointer = WASM_MEMORY_BUFFER.as_ptr();
}
return pointer;
}
// Function to read from index 1 of our buffer
// And return the value at the index
#[wasm_bindgen]
pub fn read_wasm_memory_buffer_and_return_index_one() -> u8 {
let value: u8;
unsafe {
value = WASM_MEMORY_BUFFER[1];
}
return value;
}
Então, compilamos com o wasm-pack, que vai criar um diretório pkg/
:
wasm-pack build --target web
Depois, criamos um arquivo index.js
para carregar e executar o wasm que foi gerado. E vamos importar o módulo de inicialização do pkg/webassembly_linear_memory.js
que também foi gerado pelo wasm-pack. Então, vamos invocar o módulo passando a localização do nosso arquivo wasm pkg/webassembly_linear_memory_bg.wasm
, também gerado pelo wasm-pack. A seguir, vamos ler e escrever na memória tanto a partir do Wasm como do JS. Por favor leia os comentários para ter mais contexto. E não deixe de ler a nota no final deste exemplo de código. Vamos nos aprofundar no nosso index.js
final:
const runWasm = async () => {
const rustWasm = await wasmInit("./pkg/webassembly_linear_memory_bg.wasm");
/**
* Part one: Write in Wasm, Read in JS
*/
console.log("Write in Wasm, Read in Js, Index 0:");
// First, let's have wasm write to our buffer
rustWasm.store_value_in_wasm_memory_buffer_index_zero(24);
// Next, let's create a Uint8Array of our wasm memory
let wasmMemory = new Uint8Array(rustWasm.memory.buffer);
// Then, let's get the pointer to our buffer that is within wasmMemory
let bufferPointer = rustWasm.get_wasm_memory_buffer_pointer();
// Then, let's read the written value at index zero of the buffer,
// by accessing the index of wasmMemory[bufferPointer + bufferIndex]
console.log(wasmMemory[bufferPointer + 0]); // Should log "24"
/**
* Part two: Write in JS, Read in Wasm
*/
console.log("Write in JS, Read in Wasm, Index 1:");
// First, let's write to index one of our buffer
wasmMemory[bufferPointer + 1] = 15;
// Then, let's have wasm read index one of the buffer,
// and return the result
console.log(rustWasm.read_wasm_memory_buffer_and_return_index_one()); // Should log "15"
/**
* NOTE: if we were to continue reading and writing memory,
* depending on how the memory is grown by rust, you may have
* to re-create the Uint8Array since memory layout could change.
* For example, `let wasmMemory = new Uint8Array(rustWasm.memory.buffer);`
* In this example, we did not, but be aware this may happen :)
*/
};
runWasm();
Finalmente, vamos carregar o nosso Módulo ES6, o arquivo Javascript index.js
, no nosso index.html
. E você deveria obter um resultado similar à demo (Código Fonte) abaixo!
A seguir, vamos ver Como Importar Funçōes do JavaScript no WebAssembly.