wasi_common/tokio/
mod.rs

1mod dir;
2mod file;
3pub mod net;
4pub mod sched;
5pub mod stdio;
6
7use self::sched::sched_ctx;
8use crate::sync::net::Socket;
9pub use crate::sync::{clocks_ctx, random_ctx};
10use crate::{file::FileAccessMode, Error, Table, WasiCtx, WasiFile};
11pub use dir::Dir;
12pub use file::File;
13pub use net::*;
14use std::future::Future;
15use std::mem;
16use std::path::Path;
17
18pub struct WasiCtxBuilder {
19    ctx: WasiCtx,
20    built: bool,
21}
22
23impl WasiCtxBuilder {
24    pub fn new() -> Self {
25        WasiCtxBuilder {
26            ctx: WasiCtx::new(random_ctx(), clocks_ctx(), sched_ctx(), Table::new()),
27            built: false,
28        }
29    }
30    pub fn env(&mut self, var: &str, value: &str) -> Result<&mut Self, crate::StringArrayError> {
31        self.ctx.push_env(var, value)?;
32        Ok(self)
33    }
34    pub fn envs(&mut self, env: &[(String, String)]) -> Result<&mut Self, crate::StringArrayError> {
35        for (k, v) in env {
36            self.ctx.push_env(k, v)?;
37        }
38        Ok(self)
39    }
40    pub fn inherit_env(&mut self) -> Result<&mut Self, crate::StringArrayError> {
41        for (key, value) in std::env::vars() {
42            self.ctx.push_env(&key, &value)?;
43        }
44        Ok(self)
45    }
46    pub fn arg(&mut self, arg: &str) -> Result<&mut Self, crate::StringArrayError> {
47        self.ctx.push_arg(arg)?;
48        Ok(self)
49    }
50    pub fn args(&mut self, arg: &[String]) -> Result<&mut Self, crate::StringArrayError> {
51        for a in arg {
52            self.ctx.push_arg(&a)?;
53        }
54        Ok(self)
55    }
56    pub fn inherit_args(&mut self) -> Result<&mut Self, crate::StringArrayError> {
57        for arg in std::env::args() {
58            self.ctx.push_arg(&arg)?;
59        }
60        Ok(self)
61    }
62    pub fn stdin(&mut self, f: Box<dyn WasiFile>) -> &mut Self {
63        self.ctx.set_stdin(f);
64        self
65    }
66    pub fn stdout(&mut self, f: Box<dyn WasiFile>) -> &mut Self {
67        self.ctx.set_stdout(f);
68        self
69    }
70    pub fn stderr(&mut self, f: Box<dyn WasiFile>) -> &mut Self {
71        self.ctx.set_stderr(f);
72        self
73    }
74    pub fn inherit_stdin(&mut self) -> &mut Self {
75        self.stdin(Box::new(crate::tokio::stdio::stdin()))
76    }
77    pub fn inherit_stdout(&mut self) -> &mut Self {
78        self.stdout(Box::new(crate::tokio::stdio::stdout()))
79    }
80    pub fn inherit_stderr(&mut self) -> &mut Self {
81        self.stderr(Box::new(crate::tokio::stdio::stderr()))
82    }
83    pub fn inherit_stdio(&mut self) -> &mut Self {
84        self.inherit_stdin().inherit_stdout().inherit_stderr()
85    }
86    pub fn preopened_dir(
87        &mut self,
88        dir: cap_std::fs::Dir,
89        guest_path: impl AsRef<Path>,
90    ) -> Result<&mut Self, Error> {
91        let dir = Box::new(crate::tokio::dir::Dir::from_cap_std(dir));
92        self.ctx.push_preopened_dir(dir, guest_path)?;
93        Ok(self)
94    }
95    pub fn preopened_socket(
96        &mut self,
97        fd: u32,
98        socket: impl Into<Socket>,
99    ) -> Result<&mut Self, Error> {
100        let socket: Socket = socket.into();
101        let file: Box<dyn WasiFile> = socket.into();
102        self.ctx
103            .insert_file(fd, file, FileAccessMode::READ | FileAccessMode::WRITE);
104        Ok(self)
105    }
106
107    pub fn build(&mut self) -> WasiCtx {
108        assert!(!self.built);
109        let WasiCtxBuilder { ctx, .. } = mem::replace(self, Self::new());
110        self.built = true;
111        ctx
112    }
113}
114
115// Much of this mod is implemented in terms of `async` methods from the
116// wasmtime_wasi::sync module. These methods may be async in signature, however,
117// they are synchronous in implementation (always Poll::Ready on first poll)
118// and perform blocking syscalls.
119//
120// This function takes this blocking code and executes it using a dummy executor
121// to assert its immediate readiness. We tell tokio this is a blocking operation
122// with the block_in_place function.
123pub(crate) fn block_on_dummy_executor<'a, F, Fut, T>(f: F) -> Result<T, Error>
124where
125    F: FnOnce() -> Fut + Send + 'a,
126    Fut: Future<Output = Result<T, Error>>,
127    T: Send + 'static,
128{
129    tokio::task::block_in_place(move || {
130        wiggle::run_in_dummy_executor(f()).expect("wrapped operation should be synchronous")
131    })
132}
133
134#[cfg(feature = "wasmtime")]
135super::define_wasi!(async T: Send);