diff --git a/Cargo.lock b/Cargo.lock index 0eb0b74a07..ea8cb56aed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2808,6 +2808,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "tokio" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83f0c8e7c0addab50b663055baf787d0af7f413a46e6e7fb9559a4e4db7137a5" +dependencies = [ + "autocfg 1.0.1", + "pin-project-lite", +] + [[package]] name = "toml" version = "0.5.8" @@ -3041,6 +3051,16 @@ version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +[[package]] +name = "wasi-cap-std-async" +version = "0.26.0" +dependencies = [ + "tokio", + "wasi-cap-std-sync", + "wasi-common", + "wiggle", +] + [[package]] name = "wasi-cap-std-sync" version = "0.26.0" @@ -3059,6 +3079,7 @@ dependencies = [ "tracing", "unsafe-io", "wasi-common", + "wiggle", "winapi", ] diff --git a/Cargo.toml b/Cargo.toml index ffff6d865e..7c8c352b48 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -78,6 +78,7 @@ members = [ "crates/wiggle/wasmtime", "crates/wasi-common", "crates/wasi-common/cap-std-sync", + "crates/wasi-common/cap-std-async", "examples/fib-debug/wasm", "examples/wasi/wasm", "fuzz", diff --git a/crates/wasi-common/cap-std-async/Cargo.toml b/crates/wasi-common/cap-std-async/Cargo.toml new file mode 100644 index 0000000000..471ca5640b --- /dev/null +++ b/crates/wasi-common/cap-std-async/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "wasi-cap-std-async" +version = "0.26.0" +authors = ["The Wasmtime Project Developers"] +description = "WASI implementation in Rust" +license = "Apache-2.0 WITH LLVM-exception" +categories = ["wasm"] +keywords = ["webassembly", "wasm"] +repository = "https://github.com/bytecodealliance/wasmtime" +readme = "README.md" +edition = "2018" +include = ["src/**/*", "LICENSE" ] + +[dependencies] +wasi-common = { path = "../", version = "0.26.0" } +wasi-cap-std-sync = { path = "../cap-std-sync", version = "0.26.0" } +wiggle = { path = "../../wiggle", version = "0.26.0" } +tokio = { version = "1.5.0", features = [ "rt", "time" ] } diff --git a/crates/wasi-common/cap-std-async/src/lib.rs b/crates/wasi-common/cap-std-async/src/lib.rs new file mode 100644 index 0000000000..f01d832c8f --- /dev/null +++ b/crates/wasi-common/cap-std-async/src/lib.rs @@ -0,0 +1,111 @@ +use std::cell::RefCell; +use std::path::Path; +use std::rc::Rc; +pub use wasi_cap_std_sync::{clocks_ctx, random_ctx, Dir}; +use wasi_common::{Table, WasiCtx}; + +pub fn sched_ctx() -> Box { + use wasi_common::{ + sched::{Duration, Poll, WasiSched}, + Error, + }; + struct AsyncSched; + + #[wiggle::async_trait] + impl WasiSched for AsyncSched { + async fn poll_oneoff<'a>(&self, _poll: &'_ Poll<'a>) -> Result<(), Error> { + todo!() + } + async fn sched_yield(&self) -> Result<(), Error> { + tokio::task::yield_now().await; + Ok(()) + } + async fn sleep(&self, duration: Duration) -> Result<(), Error> { + tokio::time::sleep(duration).await; + Ok(()) + } + } + + Box::new(AsyncSched) +} + +pub struct WasiCtxBuilder(wasi_common::WasiCtxBuilder); + +impl WasiCtxBuilder { + pub fn new() -> Self { + WasiCtxBuilder(WasiCtx::builder( + random_ctx(), + clocks_ctx(), + sched_ctx(), + Rc::new(RefCell::new(Table::new())), + )) + } + pub fn env(self, var: &str, value: &str) -> Result { + let s = self.0.env(var, value)?; + Ok(WasiCtxBuilder(s)) + } + pub fn envs(self, env: &[(String, String)]) -> Result { + let mut s = self; + for (k, v) in env { + s = s.env(k, v)?; + } + Ok(s) + } + pub fn inherit_env(self) -> Result { + let mut s = self.0; + for (key, value) in std::env::vars() { + s = s.env(&key, &value)?; + } + Ok(WasiCtxBuilder(s)) + } + pub fn arg(self, arg: &str) -> Result { + let s = self.0.arg(arg)?; + Ok(WasiCtxBuilder(s)) + } + pub fn args(self, arg: &[String]) -> Result { + let mut s = self; + for a in arg { + s = s.arg(&a)?; + } + Ok(s) + } + pub fn inherit_args(self) -> Result { + let mut s = self.0; + for arg in std::env::args() { + s = s.arg(&arg)?; + } + Ok(WasiCtxBuilder(s)) + } + pub fn stdin(self, f: Box) -> Self { + WasiCtxBuilder(self.0.stdin(f)) + } + pub fn stdout(self, f: Box) -> Self { + WasiCtxBuilder(self.0.stdout(f)) + } + pub fn stderr(self, f: Box) -> Self { + WasiCtxBuilder(self.0.stderr(f)) + } + pub fn inherit_stdin(self) -> Self { + self.stdin(Box::new(wasi_cap_std_sync::stdio::stdin())) + } + pub fn inherit_stdout(self) -> Self { + self.stdout(Box::new(wasi_cap_std_sync::stdio::stdout())) + } + pub fn inherit_stderr(self) -> Self { + self.stderr(Box::new(wasi_cap_std_sync::stdio::stderr())) + } + pub fn inherit_stdio(self) -> Self { + self.inherit_stdin().inherit_stdout().inherit_stderr() + } + pub fn preopened_dir( + self, + dir: Dir, + guest_path: impl AsRef, + ) -> Result { + let dir = Box::new(wasi_cap_std_sync::dir::Dir::from_cap_std(dir)); + Ok(WasiCtxBuilder(self.0.preopened_dir(dir, guest_path)?)) + } + pub fn build(self) -> Result { + self.0.build() + } +}