前に「Vue.jsでwasm-bindgen(Rust+WebAssembly)の入出力を扱う」という記事を書いたが、CSVで読み込めた方が色々と楽だ。
作成中のプログラムからCSVに関するところだけ抜き取ったので動作保証はできないが、雰囲気だけ感じていただければと思う。
環境構築は、こちらを参考に。
変更はConfit.tomlにcsvを追加するぐらいかな。
CSVは、こんな感じの形式。
name,cost
ピカチュウ,10
イーブイ,9
前回と同じようにVue.jsでボタンを押すと発動するようにしておく。今回は手抜きでRust側からconsole.log()を呼ぶためにlog()という関数を定義しておく。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>wasm_csv_test</title>
</head>
<body>
<div id="app">
<button v-on:click="csvtest">test</button>
</div>
<script src="//unpkg.com/vue@latest/dist/vue.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="index.js" type="module"></script>
<script>
const log = (val) => {console.log(val);}
</script>
</body>
</html>
index.jsではmounted:
の中でCSVファイルを読み込んでおき、ボタンを押したらRustで定義したcsv_test()
にCSVの中身を渡す。
import * as mod from "./wasm.js";
(async () => {
await mod.default();
var app = new Vue({
el: '#app',
data: {
csv: null
},
mounted: function(){
axios.get("./monster.csv").then(
response => ( this.csv = response.data )
);
},
methods:{
csvtest: function(event){
mod.csv_test(this.csv);
}
}
})
})();
次にRust側。Monster(単体)とMonsters(複数)のstructを作っておく。
#[derive(Clone)]
pub struct Monster {
pub id: usize,
pub name: String,
pub cost: usize,
}
#[derive(Clone)]
pub struct Monsters {
pub monsters: Vec<Monster>
}
impl Monsters {
pub fn new() -> Self {
Monsters {
monsters: Vec::new()
}
}
pub fn add_monster(&mut self, m: Monster){
self.monsters.push(m);
}
}
lib.rsではcsv::ReaderBuilder::new().delimiter(b',').from_reader(data.as_bytes())
でCSVファイルを読み込み、Monsterに格納しながらlog()
経由でブラウザのconsole.log()に出力する。
pub mod monster;
use wasm_bindgen::prelude::*;
use crate::monster::*;
#[wasm_bindgen]
pub fn csv_test(data: &str) {
let mut m = Monsters::new();
let mut r = csv::ReaderBuilder::new().delimiter(b',').from_reader(data.as_bytes());
let mut id :usize = 0;
for record in r.records(){
let record = record.unwrap();
m.add_monster(
Monster {
id: id,
name: record[0].to_string(),
cost: record[1].parse().unwrap(),
}
);
id = id + 1;
log(&format!("{}",&record[0]));
}
}
#[wasm_bindgen]
extern {
pub fn log(s: &str);
}
今回はidの値をCSVと外で生成しているが、もしCSVの形式とstructが完全一致であればSerdeのdeserializeで一気に格納することもできる。
この仕組みを使って、ドラクエウォークのモンスターの最適な組み合わせを計算するサイトを作ってみたので、参考にしていただきたい。