Rust+wasmでJSONを扱う(配列型にも対応)


昨日の続きです。

Rust+wasmでJSONを扱うにはwasm_bindgenのJsValue型が使えると書きましたが、JSONに格納されている配列のデータを扱うには、もうひと工夫が必要です。

lib.rs
use wasm_bindgen::prelude::*;
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
pub struct Monster {
    name: String,
    value: String
}

#[derive(Serialize, Deserialize)]
pub struct Monsters {
    monsters: Vec<Monster>
}

#[wasm_bindgen]
extern {
    pub fn alert(s: &str);
    pub fn console_log(s: &str);
}

#[wasm_bindgen]
pub fn return_name(val: &JsValue){
    let monsters: Monsters = val.into_serde().unwrap();
    let mut max_val: usize = 0;
    let mut max_val_monster = Monster{
        name: String::new(),
        value: String::new()        
    };
    let mut monster_name = String::new();

    for monster in monsters.monsters {
        let val: usize = monster.value.parse().unwrap();
        if val > max_val {
            max_val = val;
            monster_name = monster.name;
        }
    }
    console_log(&format!("{}",monster_name));
    console_log(&format!("{}",max_val));
}

昨日のコードではMonsterというstructだけ用意しましたが、MonsterをメンバとするMonstersというstructを用意して、こちらにinto_serde()を使って読み込みます。

なお、昨日のコードではreturn_name()では名前だけ返してましたが、同じ関数ですがvalueが最大のモンスターの名前を返すことにしています。

index.html
<!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 monsters = {
          "monsters":[
            {"name":"pikachu","value":"10"},
            {"name":"eevee","value":"99"}
          ]
        };
        (async () => {
            await mod.default();
            mod.return_name(monsters);
        })();
    </script>
    <script>
      const console_log = (val) => {
        console.log(val);
      }
    </script>
  </body>
</html>

こちらでJSONに配列を入れてます。これで少しは汎用的になったでしょうか。