📘

cargo-wasixでファイルの読み書きをするWasmプログラムを作成する

2024/09/16に公開

この記事では、cargo-wasixを使用して、ファイルの読み書きを行うWebAssemblyプログラムを作成する方法を説明します。

https://github.com/wasix-org/cargo-wasix

cargo-wasixは、コマンドラインツールで、これは、WASIXをターゲットにしたアプリケーションのビルドが簡単できます。

WASIXは、WASI (WebAssembly System Interface) の機能を拡張し、ネットワーキングやスレッドなどの追加機能を含むWebAssembly (WASM) の拡張仕様です。Wasmer社によって開発されています。

cargo-wasixを通さなくても、WASIXに準拠したバイナリをビルドすることはできますが、システムコールの追加サポートやWASIX固有のライブラリとの互換性など、cargo-wasixが提供するビルドサポートを利用した方が簡単です。

WASIでは基本的なファイルの読み書きはサポートされています。Rustの標準ライブラリを使用してファイルの読み書きを行うプログラムを作成してwasmファイルをビルドし、Wasmerで実行します。

プロジェクトの作成

まず、新しいCargoプロジェクトを作成します。

cargo new wasix-io-example            
    Creating binary (application) `wasix-io-example` package
note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

次に、プロジェクトディレクトリに移動します。

cd wasix-io-example

Rustコードの作成

以下のコードをsrc/main.rsに追加します。このプログラムは、指定されたファイルの内容を読み取り、整数として解釈し、その値をインクリメントしてファイルに書き戻します。

src/main.rs
use std::fs::OpenOptions;
use std::io::{Read, Seek, SeekFrom, Write};
use std::{env, str};

fn increment_counter(file_path: &str) -> Result<i32, Box<dyn std::error::Error>> {
    let mut file = OpenOptions::new().read(true).write(true).open(file_path)?;
    let mut buffer = Vec::new();
    file.read_to_end(&mut buffer)?;

    let contents = str::from_utf8(&buffer)?;
    println!("File contents: {}", contents);

    let counter: i32 = contents.trim().parse()?;
    let new_counter = counter + 1;

    file.set_len(0)?;
    file.seek(SeekFrom::Start(0))?;
    file.write_all(new_counter.to_string().as_bytes())?;

    println!("Counter incremented to {}", new_counter);

    Ok(new_counter)
}

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        eprintln!("Usage: {} <file_path>", args[0]);
        std::process::exit(1);
    }
    let file_path = &args[1];
    match increment_counter(file_path) {
        Ok(_) => println!("Counter incremented successfully"),
        Err(e) => eprintln!("Failed to increment counter: {}", e),
    }
}

cargo-wasixのインストールとビルド

次に、cargo-wasixをインストールします。

cargo install cargo-wasix

プロジェクトをビルドします。

cargo wasix build        
   Compiling wasix-io-example v0.1.0 (wasix-io-example)
warning: unstable feature specified for `-Ctarget-feature`: `atomics`
  |
  = note: this feature is not stably supported; its behavior can change in the future

warning: `wasix-io-example` (bin "wasix-io-example") generated 1 warning
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.41s
info: Post-processing WebAssembly files
  Optimizing with wasm-opt

実行

カウンターファイルを作成し、初期値を設定します。

echo 0 > counter.txt

WebAssemblyプログラムを実行します。

❯ wasmer run target/wasm32-wasmer-wasi/debug/wasix-io-example.rustc.wasm ./counter.txt --dir .
File contents: 0

Counter incremented to 1
Counter incremented successfully

これで、ファイルの内容がインクリメントされ、結果が表示されます。

--dir .は、プログラムがファイルを読み書きするためのディレクトリを指定します。これはしないと、ファイルの読み書きができません。

❯ wasmer run target/wasm32-wasmer-wasi/debug/wasix-io-example.rustc.wasm ./counter.txt        
Failed to increment counter: No such file or directory (os error 44)

Discussion