Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable "invocation" of WASI modules via stdio #54

Open
wants to merge 2 commits into
base: next_interface
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3,578 changes: 1,901 additions & 1,677 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[workspace]
members = [
"bin/*",
"wasm/",
"lib/*",
]

[workspace.package]
Expand Down
2 changes: 1 addition & 1 deletion bin/valor-run/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ version = "0.6.0"

[dependencies]
valor = {path = "../..", version = "0.6.0"}
wasm_runtime = {path = "../../wasm", version = "0.1.0"}
valor-runtime = {path = "../../lib/runtime", version = "0.1.0"}

clap = {version = "4.1.8", features = ["derive"]}
embassy-executor = {version = "0.1.0", features = ["log", "std", "nightly", "integrated-timers"]}
Expand Down
22 changes: 22 additions & 0 deletions lib/runtime/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[package]
edition = "2021"
name = "valor-runtime"
version = "0.1.0"

[features]
default = ["native"]
embedded = ["wasm3"]
native = ["wasmtime", "wasmtime-wasi", "wasi-common"]
web = ["wasmer", "wasmer-wasi"]

[dependencies]
anyhow = {version = "1.0.66", default-features = false}

wasm3 = {git = "https://github.com/wasm3/wasm3-rs.git", optional = true}

wasi-common = {version = "9.0.2", optional = true}
wasmtime = {version = "9.0.2", optional = true}
wasmtime-wasi = {version = "9.0.2", optional = true}

wasmer = {version = "2.3.0", optional = true, default-features = false, features = ["js", "std"]}
wasmer-wasi = {version = "2.3.0", optional = true, default-features = false, features = ["js"]}
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use wasm_runtime::{Runtime, Wasm};
use valor_runtime::{Runtime, Wasm};

fn main() {
let rt = Runtime::with_defaults();
Expand Down
69 changes: 67 additions & 2 deletions wasm/src/lib.rs → lib/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub trait Wasm {
fn with_defaults() -> Self;
fn load(&self, module: &[u8]) -> Result<Self::Module<'_>>;
fn run(&self, module: &Self::Module<'_>) -> Result<()>;
fn invoke(&self, module: &Self::Module<'_>, stdin: &[u8]) -> Result<Vec<u8>>;
}

#[cfg(feature = "embedded")]
Expand Down Expand Up @@ -43,13 +44,18 @@ mod wasm3 {
start.call().unwrap();
Ok(())
}

fn invoke(&self, module: &Self::Module<'_>, stdin: &[u8]) -> anyhow::Result<Vec<u8>> {
todo!("Implement WASI-stdio invocation for embedded devices here")
}
}
}

#[cfg(feature = "native")]
mod wasmtime {
use super::{Result, Wasm};
use std::cell::RefCell;
use wasi_common::pipe::{ReadPipe, WritePipe};
use wasmtime::{self, Engine, Linker, Store};
use wasmtime_wasi::{add_to_linker, WasiCtx, WasiCtxBuilder};

Expand Down Expand Up @@ -79,23 +85,57 @@ mod wasmtime {
.inherit_stdio()
.inherit_args()?
.build();

let mut linker = self.linker.borrow_mut();
let mut store = Store::new(linker.engine(), cx);
linker.module(&mut store, "", module)?;
linker
.get_default(&mut store, "")?
.typed::<(), (), _>(&store)?
.typed::<(), ()>(&store)?
.call(&mut store, ())?;
Ok(())
}

fn invoke(&self, module: &Self::Module<'_>, stdin: &[u8]) -> Result<Vec<u8>> {
let stdin = ReadPipe::from(stdin);
let stdout = WritePipe::new_in_memory();
let stderr = WritePipe::new_in_memory();

let cx = WasiCtxBuilder::new()
.stdin(Box::new(stdin.clone()))
.stdout(Box::new(stdout.clone()))
.stderr(Box::new(stderr.clone()))
.inherit_args()?
.build();

let mut linker = self.linker.borrow_mut();
let mut store = Store::new(linker.engine(), cx);
linker.module(&mut store, "", module)?;
linker
.get_default(&mut store, "")?
.typed::<(), ()>(&store)?
.call(&mut store, ())?;

if let Ok(err) = stderr.try_into_inner() {
let err_bytes = err.into_inner();
let err_message =
std::string::String::from_utf8(err_bytes).map_err(anyhow::Error::msg)?;

Err(anyhow::Error::msg(err_message))
} else if let Ok(out) = stdout.try_into_inner() {
Ok(out.into_inner())
} else {
Ok(vec![])
}
}
}
}

#[cfg(feature = "web")]
mod web {
use crate::{Result, Wasm};
use wasmer::{Instance, Module, Store};
use wasmer_wasi::WasiState;
use wasmer_wasi::{Pipe, WasiState, WasiStateBuilder};

pub struct Runtime(Store);

Expand Down Expand Up @@ -129,5 +169,30 @@ mod web {
// stdout.read_to_string(&mut out).unwrap();
Ok(())
}

fn invoke(&self, module: &Self::Module<'_>, stdin: &[u8]) -> Result<Vec<u8>> {
let stdin = Pipe::from(stdin);

let mut env = WasiState::new("service")
.stdin(stdin)
.finalize()
.map_err(anyhow::Error::msg)?;
let imports = env.import_object(&module).map_err(anyhow::Error::msg)?;

let _ = Instance::new(&module, &imports)
.map_err(anyhow::Error::msg)?
.exports
.get_function("_start")
.map_err(anyhow::Error::msg)?
.call(&[])
.map_err(anyhow::Error::msg)?;

let mut out = vec![];
let mut state = env.state();
let stdout = state.fs.stdout_mut().unwrap().as_mut().unwrap();
stdout.read_to_end(&mut out).unwrap();

Ok(out)
}
}
}
9 changes: 9 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1 +1,10 @@
#![feature(error_in_core)]
#![cfg_attr(not(feature = "std"), no_std)]

pub use valor_core::{map, structures};
pub use valor_proc::{extensions, method, module};

pub use lazy_static::lazy_static;

#[cfg(target_arch = "wasm32")]
pub use valor_core::interop;
21 changes: 0 additions & 21 deletions wasm/Cargo.toml

This file was deleted.

Binary file removed wasm/examples/hello_service.wasm
Binary file not shown.