Move examples and adapt.

This commit is contained in:
Sergey Pepyakin 2019-01-25 13:00:24 +01:00
parent 3bd8f8a250
commit e9a414d504
3 changed files with 45 additions and 64 deletions

View File

@ -1,18 +1,23 @@
//! A simple tic tac toe implementation.
//!
//! You specify two wasm modules with a certain ABI and this
//! program instantiates these modules and runs a module
//! on turn-by-turn basis.
//!
extern crate parity_wasm; extern crate parity_wasm;
extern crate wasmi; extern crate wasmi;
extern crate wasmi_derive;
use std::env; use std::env;
use std::fmt; use std::fmt;
use std::fs::File; use std::fs::File;
use wasmi::{ use wasmi::{Error as InterpreterError, HostError, ImportsBuilder, ModuleInstance, ModuleRef};
Error as InterpreterError, Externals, FuncInstance, FuncRef, HostError, ImportsBuilder,
ModuleImportResolver, ModuleInstance, ModuleRef, RuntimeArgs, RuntimeValue, Signature, Trap,
ValueType,
};
#[derive(Debug)] #[derive(Debug)]
pub enum Error { pub enum Error {
OutOfRange, OutOfRange,
AlreadyPlayed,
AlreadyOccupied, AlreadyOccupied,
Interpreter(InterpreterError), Interpreter(InterpreterError),
} }
@ -46,16 +51,6 @@ mod tictactoe {
Won(Player), Won(Player),
} }
impl Player {
pub fn into_i32(maybe_player: Option<Player>) -> i32 {
match maybe_player {
None => 0,
Some(Player::X) => 1,
Some(Player::O) => 2,
}
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct Game { pub struct Game {
board: [Option<Player>; 9], board: [Option<Player>; 9],
@ -133,59 +128,40 @@ mod tictactoe {
struct Runtime<'a> { struct Runtime<'a> {
player: tictactoe::Player, player: tictactoe::Player,
made_turn: bool,
game: &'a mut tictactoe::Game, game: &'a mut tictactoe::Game,
} }
const SET_FUNC_INDEX: usize = 0; #[wasmi_derive::derive_externals]
const GET_FUNC_INDEX: usize = 1; impl<'a> Runtime<'a> {
/// Puts a mark of the current player on the given cell.
///
/// Traps if the index is out of bounds of game field or if the player
/// already made it's turn.
pub fn set(&mut self, idx: i32) -> Result<(), Error> {
if self.made_turn {
return Err(Error::AlreadyPlayed);
}
impl<'a> Externals for Runtime<'a> {
fn invoke_index(
&mut self,
index: usize,
args: RuntimeArgs,
) -> Result<Option<RuntimeValue>, Trap> {
match index {
SET_FUNC_INDEX => {
let idx: i32 = args.nth(0);
self.game.set(idx, self.player)?; self.game.set(idx, self.player)?;
Ok(None) Ok(())
} }
GET_FUNC_INDEX => {
let idx: i32 = args.nth(0);
let val: i32 = tictactoe::Player::into_i32(self.game.get(idx)?);
Ok(Some(val.into()))
}
_ => panic!("unknown function index"),
}
}
}
struct RuntimeModuleImportResolver; /// Returns the player index at the specified cell.
///
/// 0 - unoccupied
/// 1 - player X
/// 2 - player O
///
/// Traps if the index is out of bounds of game field.
pub fn get(&self, idx: i32) -> Result<i32, Error> {
use tictactoe::Player;
impl<'a> ModuleImportResolver for RuntimeModuleImportResolver { Ok(match self.game.get(idx)? {
fn resolve_func( None => 0,
&self, Some(Player::X) => 1,
field_name: &str, Some(Player::O) => 2,
_signature: &Signature, })
) -> Result<FuncRef, InterpreterError> {
let func_ref = match field_name {
"set" => FuncInstance::alloc_host(
Signature::new(&[ValueType::I32][..], None),
SET_FUNC_INDEX,
),
"get" => FuncInstance::alloc_host(
Signature::new(&[ValueType::I32][..], Some(ValueType::I32)),
GET_FUNC_INDEX,
),
_ => {
return Err(InterpreterError::Function(format!(
"host module doesn't export function with name {}",
field_name
)));
}
};
Ok(func_ref)
} }
} }
@ -198,10 +174,14 @@ fn instantiate(path: &str) -> Result<ModuleRef, Error> {
wasmi::Module::from_buffer(&wasm_buf)? wasmi::Module::from_buffer(&wasm_buf)?
}; };
let mut imports = ImportsBuilder::new(); let instance = {
imports.push_resolver("env", &RuntimeModuleImportResolver); let resolver = Runtime::resolver();
let instance = ModuleInstance::new(&module, &imports)?.assert_no_start(); let mut imports = ImportsBuilder::new();
imports.push_resolver("env", &resolver);
ModuleInstance::new(&module, &imports)?.assert_no_start()
};
Ok(instance) Ok(instance)
} }
@ -222,6 +202,7 @@ fn play(
let mut runtime = Runtime { let mut runtime = Runtime {
player: turn_of, player: turn_of,
game: game, game: game,
made_turn: false,
}; };
let _ = instance.invoke_export("mk_turn", &[], &mut runtime)?; let _ = instance.invoke_export("mk_turn", &[], &mut runtime)?;
} }