use anyhow::{anyhow, Context as _};
use wasmtime::component::Resource;
use crate::engine::bindings::wasi::cli::{
environment, exit, stderr, stdin, stdout, terminal_input, terminal_output, terminal_stderr,
terminal_stdin, terminal_stdout,
};
use crate::engine::wasi::cli::{I32Exit, TerminalInput, TerminalOutput};
use crate::engine::wasi::io::{InputStream, OutputStream};
use crate::Ctx;
impl terminal_input::Host for Ctx {}
impl terminal_output::Host for Ctx {}
impl terminal_input::HostTerminalInput for Ctx {
fn drop(&mut self, rep: Resource<TerminalInput>) -> wasmtime::Result<()> {
self.table
.delete(rep)
.context("failed to delete input resource from table")?;
Ok(())
}
}
impl terminal_output::HostTerminalOutput for Ctx {
fn drop(&mut self, rep: Resource<TerminalOutput>) -> wasmtime::Result<()> {
self.table
.delete(rep)
.context("failed to delete output resource from table")?;
Ok(())
}
}
impl terminal_stdin::Host for Ctx {
fn get_terminal_stdin(&mut self) -> wasmtime::Result<Option<Resource<TerminalInput>>> {
if self.cli.stdin.is_terminal() {
let fd = self
.table
.push(TerminalInput)
.context("failed to push terminal resource to table")?;
Ok(Some(fd))
} else {
Ok(None)
}
}
}
impl terminal_stdout::Host for Ctx {
fn get_terminal_stdout(&mut self) -> wasmtime::Result<Option<Resource<TerminalOutput>>> {
if self.cli.stdout.is_terminal() {
let fd = self
.table
.push(TerminalOutput)
.context("failed to push terminal resource to table")?;
Ok(Some(fd))
} else {
Ok(None)
}
}
}
impl terminal_stderr::Host for Ctx {
fn get_terminal_stderr(&mut self) -> wasmtime::Result<Option<Resource<TerminalOutput>>> {
if self.cli.stderr.is_terminal() {
let fd = self
.table
.push(TerminalOutput)
.context("failed to push terminal resource to table")?;
Ok(Some(fd))
} else {
Ok(None)
}
}
}
impl stdin::Host for Ctx {
fn get_stdin(&mut self) -> wasmtime::Result<Resource<InputStream>> {
let stream = self
.table
.push(InputStream::Empty)
.context("failed to push input stream resource to table")?;
Ok(stream)
}
}
impl stdout::Host for Ctx {
fn get_stdout(&mut self) -> wasmtime::Result<Resource<OutputStream>> {
let stream = self
.table
.push(OutputStream::Stdout(std::io::stdout()))
.context("failed to push output stream resource to table")?;
Ok(stream)
}
}
impl stderr::Host for Ctx {
fn get_stderr(&mut self) -> wasmtime::Result<Resource<OutputStream>> {
let stream = self
.table
.push(OutputStream::Stderr(std::io::stderr()))
.context("failed to push output stream resource to table")?;
Ok(stream)
}
}
impl environment::Host for Ctx {
fn get_environment(&mut self) -> wasmtime::Result<Vec<(String, String)>> {
Ok(self.cli.environment.clone())
}
fn get_arguments(&mut self) -> wasmtime::Result<Vec<String>> {
Ok(self.cli.arguments.clone())
}
fn initial_cwd(&mut self) -> wasmtime::Result<Option<String>> {
Ok(self.cli.initial_cwd.clone())
}
}
impl exit::Host for Ctx {
fn exit(&mut self, status: Result<(), ()>) -> wasmtime::Result<()> {
let status = match status {
Ok(()) => 0,
Err(()) => 1,
};
Err(anyhow!(I32Exit(status)))
}
fn exit_with_code(&mut self, status_code: u8) -> wasmtime::Result<()> {
Err(anyhow!(I32Exit(status_code.into())))
}
}