String to uppercase

04 Dec 2017 0 Comments

Lets create wasm module with to_uppercase function.

Our goal is to send the string from JavaScript to Rust, process the string in Rust and send back to JavaScript.

Files creation

<!DOCTYPE html>
<html lang="en">
  <head>
      <meta charset="utf-8">
      <title>WebAssembly</title>
      <script src="bundle.js"></script>
      <script src="script.js"></script>
  </head>
  <body>
    <input id="a">
    <output id="b"></output>
  </body>
</html>

window.onload = function() {
    window.exports = {};

    let a = document.querySelector('#a'),
        b = document.querySelector('#b');

    fetchAndInstantiate('build/main.wasm')
    .then(mod => {
        exports = mod.exports;

        let to_uppercase = s => {
          let outptr = exports.to_uppercase(newString(exports, s));
          return copyCStr(exports, outptr);
        };

        a.oninput = () =>
            b.value = to_uppercase(a.value);
    });
};

use std::mem;
use std::ffi::CString;
use std::os::raw::{c_char, c_void};

#[no_mangle]
pub extern "C" fn alloc(size: usize) -> *mut c_void {
    let mut buf = Vec::with_capacity(size);
    let ptr = buf.as_mut_ptr();
    mem::forget(buf);
    return ptr as *mut c_void;
}

#[no_mangle]
pub extern "C" fn dealloc_str(ptr: *mut c_char) {
    unsafe {
        let _ = CString::from_raw(ptr);
    }
}

#[no_mangle]
pub fn to_uppercase(ptr: *mut c_char) -> *mut c_char {
    let mut s: String;

    unsafe {
        s = CString::from_raw(ptr).into_string().unwrap();
    }
    
    s = s.to_uppercase();

    let c_string = CString::new(s).unwrap();
    c_string.into_raw()
}

Save this file as main.wasm in build folder.
Or generate this file by
rustc +nightly --target wasm32-unknown-unknown -O --crate-type=cdylib src\main.rs -o build\main.big.wasm

We need to encode the string, allocate some space in the exported memory buffer and copy over the string for sending the string from JavaScript to Rust. On return of the Rust function, we decode the new string from the memory buffer.

The good answer on the Stack Overflow.
The helper functions are defined in bundle.js.
Result