数当てを wasm-bindgen (Rust + javascript)で。

参考は、ここ「rust-wasm-book helloworld」と「rust-book guessing game」。今回はこの二つを混ぜた感じに。

準備

Dockerfile

FROM rustlang/rust:nightly
ENV PATH=/usr/local/cargo/bin:$PATH
RUN cargo install wasm-pack && cargo install cargo-generate
RUN set -x \
    && curl -sL https://deb.nodesource.com/setup_11.x | bash - \
    && apt-get install -y nodejs \
    && npm install npm@latest -g

dockerビルドと起動

docker build -t eg-rust .
docker run -it --rm -p 8080:8080 -e USER=$USER -v "$PWD":/usr/src/ -w /usr/src eg-rust /bin/bash

generate

次のgenerateコマンドを実行すると、プロジェクト名を決められるので、guessing-gameにしておく。

cargo generate --git https://github.com/rustwasm/wasm-pack-template

web側は npm init wasm-app で wwwフォルダに色々自動で生成

npm init wasm-app www

実装

今回編集するのは、index.html, index.js, lib.rs

www/index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Hello wasm-pack!</title>
  </head>
  <body>
    <input type="text" id="my_guess" />
    <button id="play">play</button>
    <script src="./bootstrap.js"></script>
  </body>
</html>

www/index.js

import * as wasm from "guessing-game";

const play_button = document.getElementById("play");
play_button.addEventListener("click", event => {
    let n = document.getElementById("my_guess").value
    let res = wasm.check(n);
    console.log(res);
});

lib/lib.rs

(※ static使うときはunsafe {} ってやらないといけないの?)

mod utils;
use cfg_if::cfg_if;

extern crate rand;
use rand::{thread_rng, Rng};

extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;

cfg_if::cfg_if! {
    // When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
    // allocator.
    if #[cfg(feature = "wee_alloc")] {
        #[global_allocator]
        static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
    }
}

static mut SECRET_NUMBER: u32 = 0;

pub fn create_secret() -> u32 {
    let i: u32  = thread_rng().gen_range(0, 50);
     unsafe {
        SECRET_NUMBER = i;
        return SECRET_NUMBER;
    };
}

use std::cmp::Ordering;

#[wasm_bindgen]
pub fn check(m_num: u32) -> String {
    unsafe {
        let n = &SECRET_NUMBER;
        match m_num.cmp(n) {
            Ordering::Less => "Less.".to_string(),
            Ordering::Greater => "Greater.".to_string(),
            Ordering::Equal => "Equal.".to_string(),
        }
    }
}

#[wasm_bindgen(start)]
pub fn run() -> Result<(), JsValue> {
    console_error_panic_hook::set_once();
    create_secret();
    Ok(())
}

Cargo.toml

rand = { version = “0.6”, features = [“wasm-bindgen”] }

ビルドとnpmのlink

まずは、rustをビルド

wasm-pack build

pkgフォルダに色々できるので、pkgの中に入って npm の link。そしたら、wwwの下に行って、今はったlinkを

cd pkg
npm link
cd ../www
npm link guessing-game

実行

wwwフォルダで、

npm start