pub mod task_manager;
use crate::{http::DynHttpClient, os::TtyBridge, WasiTtyState};
pub use self::task_manager::{SpawnType, SpawnedMemory, VirtualTaskManager};
use std::{
fmt,
sync::{Arc, Mutex},
};
use derivative::Derivative;
use virtual_net::{DynVirtualNetworking, VirtualNetworking};
#[allow(unused_variables)]
pub trait WasiRuntime
where
Self: fmt::Debug + Sync,
{
fn networking(&self) -> &DynVirtualNetworking;
fn task_manager(&self) -> &Arc<dyn VirtualTaskManager>;
fn engine(&self) -> Option<wasmer::Engine> {
None
}
fn new_store(&self) -> wasmer::Store {
cfg_if::cfg_if! {
if #[cfg(feature = "sys")] {
if let Some(engine) = self.engine() {
wasmer::Store::new(engine)
} else {
wasmer::Store::default()
}
} else {
wasmer::Store::default()
}
}
}
fn http_client(&self) -> Option<&DynHttpClient> {
None
}
fn tty(&self) -> Option<&(dyn TtyBridge + Send + Sync)> {
None
}
}
#[derive(Debug, Default)]
pub struct DefaultTty {
state: Mutex<WasiTtyState>,
}
impl TtyBridge for DefaultTty {
fn reset(&self) {
let mut state = self.state.lock().unwrap();
state.echo = false;
state.line_buffered = false;
state.line_feeds = false
}
fn tty_get(&self) -> WasiTtyState {
let state = self.state.lock().unwrap();
state.clone()
}
fn tty_set(&self, tty_state: WasiTtyState) {
let mut state = self.state.lock().unwrap();
*state = tty_state;
}
}
#[derive(Clone, Derivative)]
#[derivative(Debug)]
pub struct PluggableRuntime {
pub rt: Arc<dyn VirtualTaskManager>,
pub networking: DynVirtualNetworking,
pub http_client: Option<DynHttpClient>,
pub engine: Option<wasmer::Engine>,
#[derivative(Debug = "ignore")]
pub tty: Option<Arc<dyn TtyBridge + Send + Sync>>,
}
impl PluggableRuntime {
pub fn new(rt: Arc<dyn VirtualTaskManager>) -> Self {
cfg_if::cfg_if! {
if #[cfg(feature = "host-vnet")] {
let networking = Arc::new(virtual_net::host::LocalNetworking::default());
} else {
let networking = Arc::new(virtual_net::UnsupportedVirtualNetworking::default());
}
}
cfg_if::cfg_if! {
if #[cfg(feature = "host-reqwest")] {
let http_client = Some(Arc::new(
crate::http::reqwest::ReqwestHttpClient::default()) as DynHttpClient
);
} else {
let http_client = None;
}
}
Self {
rt,
networking,
http_client,
engine: None,
tty: None,
}
}
pub fn set_networking_implementation<I>(&mut self, net: I)
where
I: VirtualNetworking + Sync,
{
self.networking = Arc::new(net)
}
pub fn set_engine(&mut self, engine: Option<wasmer::Engine>) {
self.engine = engine;
}
pub fn set_tty(&mut self, tty: Arc<dyn TtyBridge + Send + Sync>) {
self.tty = Some(tty);
}
}
impl WasiRuntime for PluggableRuntime {
fn networking(&self) -> &DynVirtualNetworking {
&self.networking
}
fn http_client(&self) -> Option<&DynHttpClient> {
self.http_client.as_ref()
}
fn engine(&self) -> Option<wasmer::Engine> {
self.engine.clone()
}
fn task_manager(&self) -> &Arc<dyn VirtualTaskManager> {
&self.rt
}
fn tty(&self) -> Option<&(dyn TtyBridge + Send + Sync)> {
self.tty.as_deref()
}
}