summaryrefslogtreecommitdiff
path: root/crates/cli/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/cli/src')
-rw-r--r--crates/cli/src/bin.rs112
-rw-r--r--crates/cli/src/util.rs1
-rw-r--r--crates/cli/src/wat.rs10
3 files changed, 123 insertions, 0 deletions
diff --git a/crates/cli/src/bin.rs b/crates/cli/src/bin.rs
new file mode 100644
index 0000000..3615e4a
--- /dev/null
+++ b/crates/cli/src/bin.rs
@@ -0,0 +1,112 @@
+use std::str::FromStr;
+
+use argh::FromArgs;
+use color_eyre::eyre::Result;
+use log::info;
+use tinywasm::{self, Module};
+mod util;
+
+#[cfg(feature = "wat")]
+mod wat;
+
+#[derive(FromArgs)]
+/// TinyWasm CLI
+struct TinyWasmCli {
+ #[argh(subcommand)]
+ nested: TinyWasmSubcommand,
+
+ /// log level
+ #[argh(option, short = 'l', default = "\"info\".to_string()")]
+ log_level: String,
+}
+
+#[derive(FromArgs)]
+#[argh(subcommand)]
+enum TinyWasmSubcommand {
+ Run(Run),
+}
+
+enum Engine {
+ Main,
+}
+
+impl FromStr for Engine {
+ type Err = String;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ match s {
+ "main" => Ok(Self::Main),
+ _ => Err(format!("unknown engine: {}", s)),
+ }
+ }
+}
+
+#[derive(FromArgs)]
+/// run a wasm file
+#[argh(subcommand, name = "run")]
+struct Run {
+ /// wasm file to run
+ #[argh(positional)]
+ wasm_file: String,
+
+ /// engine to use
+ #[argh(option, short = 'e', default = "Engine::Main")]
+ engine: Engine,
+}
+
+fn main() -> Result<()> {
+ color_eyre::install()?;
+
+ let args: TinyWasmCli = argh::from_env();
+ let level = match args.log_level.as_str() {
+ "trace" => log::LevelFilter::Trace,
+ "debug" => log::LevelFilter::Debug,
+ "warn" => log::LevelFilter::Warn,
+ "error" => log::LevelFilter::Error,
+ "info" => log::LevelFilter::Info,
+ _ => log::LevelFilter::Info,
+ };
+
+ pretty_env_logger::formatted_builder()
+ .filter_level(level)
+ .init();
+
+ let cwd = std::env::current_dir()?;
+
+ match args.nested {
+ TinyWasmSubcommand::Run(Run { wasm_file, engine }) => {
+ let path = cwd.join(wasm_file.clone());
+ let module = match wasm_file.ends_with(".wat") {
+ #[cfg(feature = "wat")]
+ true => {
+ let wat = std::fs::read_to_string(path)?;
+ let wasm = wat::wat2wasm(&wat);
+ tinywasm::Module::parse_bytes(&wasm)?
+ }
+ #[cfg(not(feature = "wat"))]
+ true => {
+ return Err(color_eyre::eyre::eyre!(
+ "wat support is not enabled in this build"
+ ))
+ }
+ false => tinywasm::Module::parse_file(path)?,
+ };
+
+ match engine {
+ Engine::Main => run(module),
+ }
+ }
+ }
+}
+
+fn run(module: Module) -> Result<()> {
+ let mut store = tinywasm::Store::default();
+
+ let instance = module.instantiate(&mut store)?;
+
+ let func = instance.get_typed_func::<(i32, i32), (i32,)>(&store, "add")?;
+ let (res,) = func.call(&mut store, (2, 2))?;
+ info!("{res:?}");
+
+ Ok(())
+}
diff --git a/crates/cli/src/util.rs b/crates/cli/src/util.rs
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/crates/cli/src/util.rs
@@ -0,0 +1 @@
+
diff --git a/crates/cli/src/wat.rs b/crates/cli/src/wat.rs
new file mode 100644
index 0000000..fd00a8e
--- /dev/null
+++ b/crates/cli/src/wat.rs
@@ -0,0 +1,10 @@
+use wast::{
+ parser::{self, ParseBuffer},
+ Wat,
+};
+
+pub fn wat2wasm(wat: &str) -> Vec<u8> {
+ let buf = ParseBuffer::new(wat).expect("failed to create parse buffer");
+ let mut module = parser::parse::<Wat>(&buf).expect("failed to parse wat");
+ module.encode().expect("failed to encode wat")
+}