getrandom with *quad on WASM

Article originally posted on the discord by juh9870

Guide For those who want to use getrandom (mainly for rand or for ahash) with Macroquad.
This method utilizes crypto.getRandomValues for getting cryptographically strong random values, which are good to seed your PRNG (including quad_rand)

🔗Step 1

Add dependencies on getrandom crate with custom feature, and on sapp-jsutil crate for JS bridging

Example:

[target.'cfg(target_arch = "wasm32")'.dependencies]
getrandom = { version = "0.2", features = ["custom"] }
sapp-jsutils = { version = "0.1" }

🔗Step 2

Create a file somewhere in your project, and make it wasm-only.

#[cfg(target_arch = "wasm32")]
mod getrandom_on_web;

And use the following code

use sapp_jsutils::JsObject;

extern "C" {
    fn macroquad_js_get_random_buffer(length: usize) -> JsObject;
}

/// Required by `getrandom` crate.
fn getrandom(buf: &mut [u8]) -> Result<(), getrandom::Error> {
    let obj = unsafe { macroquad_js_get_random_buffer(buf.len()) };
    let mut bytes = Vec::with_capacity(buf.len());
    obj.to_byte_buffer(&mut bytes);

    for (target, data) in buf.iter_mut().zip(bytes) {
        *target = data;
    }
    Ok(())
}
getrandom::register_custom_getrandom!(getrandom);

🔗Step 3

Add the JS code to your project to define the function on JS side

// Plugin registration, see https://macroquad.rs/articles/wasm/ for more info
getrandom_plugin = function (importObject) {
    // make macroquad_js_get_random_buffer() function available to call from rust
    importObject.env.macroquad_js_get_random_buffer = macroquad_js_get_random_buffer;
}

miniquad_add_plugin({getrandom_plugin});

function macroquad_js_get_random_buffer(length) {
    const myArray = new Uint8Array(length);
    crypto.getRandomValues(myArray);
    return js_object(myArray);
}