Rust+wasmで複雑なものを作ろうとするとJSON形式のデータは避けて通れないと思いますが、wasm-bindgenのドキュメントにあるJsValueを使うのがよさそうです。
[dependencies]
serde = { version = "1.0", features = ["derive"] }
wasm-bindgen = { version = "0.2", features = ["serde-serialize"] }
use wasm_bindgen::prelude::*;
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
pub struct Monster {
name: String,
value: String
}
#[wasm_bindgen]
extern {
pub fn alert(s: &str);
pub fn console_log(s: &str);
}
#[wasm_bindgen]
pub fn return_name(val: &JsValue){
let m: Monster = val.into_serde().unwrap();
//alert(&m.name);
console_log(&m.name);
console_log(&m.value);
}
dependenciesでwasm-bindgenのバージョンだけでなくserde-seriarizeというfeatureも指定する必要があります。(これを読み飛ばしてて、気付くまで時間かかった・・・)
return_nameの引数のval: &JsValue
が今回のキモです。今回はinto_serde()
でJSONを読み込んでますが、逆にRustの値をJSONにするfrom_serde()
というメソッドもサポートしてます。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>hello-wasm example</title>
</head>
<body>
<script type="module">
import * as mod from "./wasm.js";
let monster = {
"name":"pikachu",
"value":"100"
};
(async () => {
await mod.default();
mod.return_name(monster);
})();
</script>
<script>
const console_log = (val) => {
console.log(val);
}
</script>
</body>
</html>
次にJavaScript側です。wasm.jsから読み込んだRustの関数(return_name)にmonsterという値をそのまま渡します。
絵にすると、こんな感じです。Rustで書いたreturn_nameという関数をJavaScriptのasyncの中で呼び出し、そのreturn_nameではJavaScriptで書いたconsole_logという関数を呼び出しています。
これでJavaScriptで生成した大量のデータをwasmで処理できますね。
環境のインストールとビルドは、こちらの記事が参考になると思います。