The material is borrowed from Hello, Rust!
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>
factorial(<input type="number" id="n" value="10" min="0" max="65">)=
<output id="f">3628800</output>
</body>
</html>
window.onload = function() {
window.exports = {};
let n = document.querySelector('#n'),
f = document.querySelector('#f'),
fact_str;
let calc = function() {
f.value = fact_str(n.value);
};
n.oninput = calc;
fetchAndInstantiate("build/main.wasm")
.then(mod => {
exports = mod.exports;
fact_str = function(n) {
let outptr = exports.fact_str(n);
let result = copyCStr(exports, outptr);
return result;
};
});
};
use std::mem;
use std::ffi::CString;
use std::os::raw::{c_char, c_void};
fn main() {}
#[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 fact(n: u32) -> u64 {
let mut n = n as u64;
let mut result = 1;
while n > 0 {
result = result * n;
n = n - 1;
}
result
}
#[no_mangle]
pub fn fact_str(n: u32) -> *mut c_char {
let res = fact(n);
let s = format!("{}", res);
let s = CString::new(s).unwrap();
s.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
The helper functions are defined in bundle.js.
Result
WebAssembly text format with fn fact(n: u32) -> u64 only
(module
(type $t0 (func (param i32) (result i64)))
(func $fact (export "fact") (type $t0) (param $p0 i32) (result i64)
(local $l0 i64) (local $l1 i64)
(block $B0
(block $B1
(br_if $B1
(i32.eqz
(get_local $p0)))
(set_local $l0
(i64.extend_u/i32
(get_local $p0)))
(set_local $l1
(i64.const 1))
(loop $L2
(set_local $l1
(i64.mul
(get_local $l0)
(get_local $l1)))
(br_if $L2
(i32.eqz
(i64.eqz
(tee_local $l0
(i64.add
(get_local $l0)
(i64.const -1))))))
(br $B0))
(unreachable))
(set_local $l1
(i64.const 1)))
(get_local $l1))
(table $T0 0 anyfunc)
(memory $memory (export "memory") 17)
(data (i32.const 4) "\10\00\10\00"))