use crate::WasmiGuestMemory;
use std::{
pin::Pin,
task::{Context, RawWaker, RawWakerVTable, Waker},
};
use wasi_common::{Error, snapshots::preview_1::wasi_snapshot_preview1::WasiSnapshotPreview1};
use wasmi::{Caller, Extern, ImportType, Linker};
// Creates a dummy `RawWaker`. We can only create Wakers from `RawWaker`s
fn dummy_raw_waker() -> RawWaker {
fn no_op(_: *const ()) {}
// returns a new RawWaker by calling dummy_raw_waker again
fn clone(_: *const ()) -> RawWaker {
dummy_raw_waker()
}
// RawWakerVTable specifies the functions that should be called when the RawWaker is cloned, woken, or dropped.
let vtable = &RawWakerVTable::new(clone, no_op, no_op, no_op);
RawWaker::new(std::ptr::null::<()>(), vtable)
}
// Creates a dummy waker which does *nothing*, as the future itself polls to ready at first poll
// A waker is needed to do any polling at all, as it is the primary constituent of the `Context` for polling
fn run_in_dummy_executor<F: std::future::Future>(f: F) -> Result<F::Output, wasmi::Error> {
let mut f = Pin::from(Box::new(f));
let waker = unsafe { Waker::from_raw(dummy_raw_waker()) };
let mut cx = Context::from_waker(&waker);
match f.as_mut().poll(&mut cx) {
std::task::Poll::Ready(val) => Ok(val),
std::task::Poll::Pending => Err(wasmi::Error::new("Cannot wait on pending future")),
}
}
/// Implemented by Wasmi [`Linker`] to populate them with WASI definitions.
///
/// [`Linker`]: wasmi::Linker
pub trait AddWasi<T> {
/// Add Wasi preview1 definitions to `self`.
fn add_wasi<U>(
&mut self,
wasi_ctx: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static,
) -> Result<(), Error>
where
U: 'static,
T: Send + 'static,
U: WasiSnapshotPreview1;
}
/// Adds the entire WASI API to the Wasmi [`Linker`].
///
/// Once linked, users can make use of all the low-level functionalities that `WASI` provides.
///
/// You could call them `syscall`s and you'd be correct, because they mirror
/// what a non-os-dependent set of syscalls would look like.
/// You now have access to resources such as files, directories, random number generators,
/// and certain parts of the networking stack.
///
/// # Note
///
/// `WASI` is versioned in snapshots. It's still a WIP. Currently, this crate supports `preview_1`
/// Look [here](https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md) for more details.
pub fn add_wasi_snapshot_preview1_to_linker<T, U>(
linker: &mut Linker<T>,
get_ctx: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static,
) -> Result<(), Error>
where
U: 'static,
T: Send + 'static,
U: WasiSnapshotPreview1,
{
<Linker<T> as AddWasi<T>>::add_wasi(linker, get_ctx)
}
macro_rules! wrap_wasi_funcs {
(
$(
$( #[$docs:meta] )*
fn $fname:ident ($( $arg:ident : $typ:ty ),* $(,)? ) -> $ret:tt
);+ $(;)?
) => {
$(
$(#[$docs])*
pub fn $fname<T, U>(
get_ctx: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static,
) -> impl Fn(Caller<'_, T> $(, $typ)* ) -> Result<$ret, wasmi::Error>
where
U: 'static,
T: Send + 'static,
U: WasiSnapshotPreview1,
{
move |mut caller: Caller<'_, T>, $($arg : $typ,)*| -> Result<$ret, wasmi::Error> {
let result = async {
let Some(Extern::Memory(memory)) = caller.get_export("memory") else {
return Err(wasmi::Error::new(String::from("missing required WASI memory export")))
};
let(memory, ctx) = memory.data_and_store_mut(&mut caller);
let ctx = get_ctx(ctx);
let mut memory = WasmiGuestMemory::Unshared(memory);
match wasi_common::snapshots::preview_1::wasi_snapshot_preview1::$fname(ctx, &mut memory, $($arg,)*).await {
Ok(r) => Ok(<$ret>::from(r)),
Err(e) => match e.downcast::<wasi_common::I32Exit>() {
Ok(wasi_common::I32Exit(status)) => Err(wasmi::Error::i32_exit(status)),
Err(e) => Err(wasmi::Error::new(e.to_string())),
}
}
};
run_in_dummy_executor(result)?
}
}
)*
};
}
macro_rules! add_funcs_to_linker {
(
$(
$( #[$docs:meta] )*
fn $fname:ident ($( $arg:ident : $typ:ty ),* $(,)? ) -> $ret:tt
);+ $(;)?
) => {
impl<T> AddWasi<T> for wasmi::Linker<T> {
fn add_wasi<U>(
&mut self,
get_ctx: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static,
) -> Result<(), Error>
where
U: 'static,
T: Send + 'static,
U: WasiSnapshotPreview1,
{
$(
self.func_wrap(
"wasi_snapshot_preview1",
stringify!($fname),
wrapped::$fname::<T, U>(get_ctx),
).map_err(wiggle::anyhow::Error::from).map_err(wasi_common::Error::trap)?;
)*
Ok(())
}
}
}
}
/// Error returned by [`add_to_externals`] when encountering invalid Wasi imports.
#[derive(Debug)]
pub struct InvalidWasiImport {
/// The module name of the invalid import.
module: Box<str>,
/// The field name of the invalid import.
name: Box<str>,
}
impl std::fmt::Display for InvalidWasiImport {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "invalid Wasi import: {}::{}", self.module, self.name)
}
}
impl std::error::Error for InvalidWasiImport {}
impl InvalidWasiImport {
/// Creates a new [`InvalidWasiImport`] from the given [`ImportType`].
#[cold]
fn new(import: ImportType<'_>) -> Self {
Self {
module: import.module().into(),
name: import.name().into(),
}
}
}
macro_rules! add_funcs_to_externals {
(
$(
$( #[$docs:meta] )*
fn $fname:ident ($( $arg:ident : $typ:ty ),* $(,)? ) -> $ret:tt
);+ $(;)?
) => {
/// Add Wasi APIs imported by `module` to the `externals` buffer.
///
/// # Note
///
/// - This only supports Wasi (preview 1) or `wasip1`.
/// - The `externals` buffer is cleared before being populated.
/// - This API is technically more efficient than [`add_to_linker`](crate::add_to_linker).
///
/// # Errors
///
/// If invalid or unknown Wasi imports are encountered.
pub fn add_to_externals<T, U>(
mut ctx: impl wasmi::AsContextMut<Data = T>,
module: &wasmi::Module,
externals: &mut Vec<wasmi::Extern>,
get_ctx: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static,
) -> Result<(), InvalidWasiImport>
where
U: 'static,
T: Send + 'static,
U: WasiSnapshotPreview1,
{
let imports = module.imports();
externals.clear();
externals.reserve(imports.len());
for import in imports {
if import.module() != "wasi_snapshot_preview1" {
return Err(InvalidWasiImport::new(import))
}
let external = match import.name() {
$(
std::stringify!($fname) => {
wasmi::Func::wrap(&mut ctx, wrapped::$fname::<T, U>(get_ctx))
}
)*
_ => return Err(InvalidWasiImport::new(import))
};
externals.push(Extern::from(external));
}
Ok(())
}
}
}
macro_rules! apply_wasi_definitions {
($mac:ident) => {
$mac! {
/// Read command-line argument data.
///
/// # Note
///
/// The size of the array should match that returned by `args_sizes_get`.
/// Each argument is expected to be \0 terminated.
fn args_get(argv: i32, argv_buf: i32) -> i32;
/// Return command-line argument data sizes.
///
/// # Note
///
/// Returns the number of arguments and the size of the argument string data, or an error.
/// Note that `offset0` and `offset1` are offsets into memory where the two results are stored
fn args_sizes_get(offset0: i32, offset1: i32) -> i32;
/// Read environment variable data.
///
/// # Note
///
/// The sizes of the buffers should match that returned by `environ_sizes_get`.
/// Key/value pairs are expected to be joined with =s, and terminated with \0s.
fn environ_get(environ: i32, environ_buf: i32) -> i32;
/// Returns the number of environment variables.
///
/// # Note
///
/// Returns the number of environment variable arguments and the size of the environment variable data.
/// Note that `offset0` and `offset1` are offsets into memory where the two results are stored.
fn environ_sizes_get(offset0: i32, offset1: i32) -> i32;
/// Return the resolution of a clock.
///
/// Implementations are required to provide a non-zero value for supported clocks.
/// For unsupported clocks, return `errno::inval`.
///
/// # Note
///
/// This is similar to `clock_getres` in POSIX.
/// The `id` is the `ClockID` and `offset0` is the offset into memory where the result is written.
fn clock_res_get(id: i32, offset0: i32) -> i32;
/// Return the time value of a clock.
///
/// # Note
///
/// This is similar to `clock_gettime` in POSIX. The result is stored in `offset0`.
fn clock_time_get(id: i32, precision: i64, offset0: i32) -> i32;
/// Provide file advisory information on a file descriptor.
///
/// # Note
///
/// This is similar to `posix_fadvise` in POSIX.
///
/// # Parameters
///
/// - `fd`: The file descriptor.
/// - `offset`: The offset within the file to which the advisory applies.
/// - `len`: The length of the region to which the advisory applies.
/// - `advice`: The advice.
fn fd_advise(fd: i32, offset: i64, len: i64, advice: i32) -> i32;
/// Force the allocation of space in a file.
///
/// # Note
///
/// This is similar to `posix_fallocate` in `POSIX`.
///
/// # Parameters
///
/// - `fd`: The file descriptor.
/// - `offset`: The offset at which to start the allocation.
/// - `len`: The length of the area that is allocated.
fn fd_allocate(fd: i32, offset: i64, len: i64) -> i32;
/// Close a file descriptor.
///
/// # Note
///
/// This is similar to `close` in POSIX.
///
/// # Parameters
///
/// - `fd`: The file descriptor that shall be closed.
fn fd_close(fd: i32) -> i32;
/// Synchronize the data of a file to disk.
///
/// # Note
///
/// This is similar to `fdatasync` in POSIX.
///
/// # Parameters
///
/// - `fd`: The file descriptor of the file to be synchronized to disk.
fn fd_datasync(fd: i32) -> i32;
/// Get the attributes of a file descriptor.
///
/// # Note
///
/// This returns similar flags to `fsync(fd, F_GETFL)` in POSIX, as well as additional fields.
///
/// # Parameters
///
/// - `fd`: The file descriptor.
/// - `offset0`: The offset into memory where the result is written to.
fn fd_fdstat_get(fd: i32, offset0: i32) -> i32;
/// Adjust the flags associated with a file descriptor.
///
/// # Note
///
/// This is similar to `fcntl(fd, F_SETFL, flags)` in POSIX.
///
/// # Parameters
///
/// - `fd`: The file descriptor.
/// - `flags`: The desired values of the file descriptor flags.
fn fd_fdstat_set_flags(fd: i32, flags: i32) -> i32;
/// Adjust the rights associated with a file descriptor.
///
/// # Note
///
/// This can only be used to remove rights, and returns `errno::notcapable`
/// if called in a way that would attempt to add rights.
///
/// # Parameters
///
/// - `fd`: The file descriptor.
/// - `fs_rights_base`: The desired rights of the file descriptor.
/// - `fs_rights_inheriting`: The inherited rights.
fn fd_fdstat_set_rights(fd: i32, fs_rights_base: i64, fs_rights_inheriting: i64) -> i32;
/// Returns the attributes of an open file.
///
/// # Parameters
///
/// - `fd`: The file descriptor.
/// - `offset0`: The offset into memory where the buffer of the file's attributes is written.
fn fd_filestat_get(fd: i32, offset0: i32) -> i32;
/// Adjust the size of an open file.
///
/// # Note
///
/// - If this increases the file's size, the extra bytes are filled with zeros.
/// - This is similar to `ftruncate` in POSIX.
///
/// # Parameters
///
/// - `fd`: The file descriptor.
/// - `size`: The desired file size.
fn fd_filestat_set_size(fd: i32, size: i64) -> i32;
/// Adjust the timestamps of an open file or directory.
///
/// # Note
///
/// This is similar to `futimens` in POSIX.
///
/// # Parameters
///
/// - `fd`: The file descriptor.
/// - `atim`: The desired values of the data access timestamp.
/// - `mtim`: The desired values of the data modification timestamp.
/// - `fst_flags`: A bitmask indicating which timestamps to adjust.
fn fd_filestat_set_times(fd: i32, atim: i64, mtim: i64, fst_flags: i32) -> i32;
/// Read from a file descriptor, without using and updating the file descriptor's offset.
///
/// # Note
///
/// This is similar to `preadv` in POSIX.
///
/// # Parameters
///
/// - `fd`: The file descriptor.
/// - `iov_buf`, `iov_buf_len`: Used to create `iovec`,
/// which is the list of scatter/gather vectors in which to store data.
/// - `offset`: The offset within the file at which to read.
/// - `offsset0`: The size of bytes read is written here.
fn fd_pread(fd: i32, iov_buf: i32, iov_buf_len: i32, offset: i64, offset0: i32) -> i32;
/// Return a description of the given preopened file descriptor.
///
/// # Parameters
///
/// - `fd`: The file descriptor.
/// - `offset0`: The location in the memory where the buffer that stores the description is written.
fn fd_prestat_get(fd: i32, offset0: i32) -> i32;
/// Return a description of the given preopened file descriptor.
///
/// # Parameters
///
/// - `fd`: The file descriptor.
/// - `path`: A buffer into which to write the preopened directory name.
/// - `path_len`: The length of the `path` buffer.
fn fd_prestat_dir_name(fd: i32, path: i32, path_len: i32) -> i32;
/// Write to a file descriptor, without using and updating the file descriptor's offset.
///
/// # Note
///
/// This is similar to `pwritev` in POSIX.
///
/// # Parameters
///
/// - `fd`: file descriptor
/// - `ciov_buf`, `ciov_buf_len`: Used to create `ciovec`,
/// which is the list of scatter/gather vectors from which to retrieve data.
/// - `offset`: The offset within the file at which to write.
/// - `offsset0`: The size of bytes written is written here.
fn fd_pwrite(fd: i32, ciov_buf: i32, ciov_buf_len: i32, offset: i64, offset0: i32) -> i32;
/// Read from a file descriptor. Note: This is similar to readv in POSIX.
///
/// # Parameters
///
/// - `fd`: The file descriptor.
/// - `iov_buf`, `iov_buf_len`: used to create iovec, which is the list of scatter/gather vectors in which to store data.
/// - `offset`: The offset within the file at which to read.
/// - `offsset0`: size of bytes read is written here
fn fd_read(fd: i32, iov_buf: i32, iov_buf_len: i32, offset1: i32) -> i32;
/// Read directory entries from a directory.
///
/// # Note
///
/// - When successful, the contents of the output buffer consist of a sequence of directory entries.
/// - Each directory entry consists of a `dirent` object,
/// followed by `dirent::d_namlen` bytes holding the name of the directory entry.
/// - This function fills the output buffer as much as possible,
/// potentially truncating the last directory entry.
/// - This allows the caller to grow its read buffer size in case it's too small
/// to fit a single large directory entry, or skip the oversized directory entry.
///
/// # Parameters
///
/// - `fd`: The file descriptor.
/// - `buf`: The buffer where directory entries are stored.
/// - `buf_len`: The length of the `buf` buffer.
/// - `cookie`: The location within the directory to start reading.
/// - `offset0`: The result, i.e. the number of bytes stored in the read buffer, is stored at this offset in memory
/// if less than the size of the read buffer, the end of the directory has been reached.
fn fd_readdir(fd: i32, buf: i32, buf_len: i32, cookie: i64, offset0: i32) -> i32;
/// Atomically replace a file descriptor by renumbering another file descriptor.
///
/// # Note
///
/// - Due to the strong focus on thread safety, this environment does not provide a mechanism
/// to duplicate or renumber a file descriptor to an arbitrary number, like `dup2()`.
/// This would be prone to race conditions, as an actual file descriptor with the same number
/// could be allocated by a different thread at the same time.
/// - This function provides a way to atomically renumber file descriptors,
/// which would disappear if `dup2()` were to be removed entirely.
///
/// # Parameters
///
/// - `fd`: The file descriptor.
/// - `to`: The file descriptor to overwrite.
fn fd_renumber(fd: i32, to: i32) -> i32;
/// Move the offset of a file descriptor.
///
/// # Note
///
/// This is similar to `lseek` in POSIX.
///
/// # Parameters
///
/// - `fd`: The file descriptor.
/// - `offset`: The number of bytes to move.
/// - `whence`: The base from which the offset is relative
/// - `offset0`: The memory location to which the new offset of the file descriptor,
/// relative to the start of the file is stored.
fn fd_seek(fd: i32, offset: i64, whence: i32, offset0: i32) -> i32;
/// Synchronize the data and metadata of a file to disk.
///
/// # Note
///
/// This is similar to `fsync` in POSIX.
///
/// # Parameters
///
/// - `fd`: The file descriptor.
fn fd_sync(fd: i32) -> i32;
/// Return the current offset of a file descriptor.
///
/// # Note
///
/// This is similar to `lseek(fd, 0, SEEK_CUR)` in POSIX.
///
/// # Parameters
///
/// - `fd`: The file descriptor.
/// - `offset0`: Offset into the memory where result is stored upon success.
/// - `result`: The current offset of the file descriptor, relative to the start of the file.
fn fd_tell(fd: i32, offset0: i32) -> i32;
/// Write to a file descriptor.
///
/// # Note
///
/// This is similar to `writev` in POSIX.
///
/// # Parameters
///
/// - `fd`: The file descriptor.
/// - `ciov_buf`, `ciov_buf_len`: used to create ciovec, which is the list of
/// scatter/gather vectors from which to retrieve data.
/// - `offset0`: The offset into the memory where result (size written) is stored
fn fd_write(fd: i32, ciov_buf: i32, ciov_buf_len: i32, offset0: i32) -> i32;
/// Create a directory.
///
/// # Note
///
/// This is similar to `mkdirat` in POSIX.
///
/// # Parameters
///
/// - `fd`: The file descriptor.
/// - `offset`, `length`: The offset/length pair used to create a guest pointer into host memory.
/// This pointer references the path string at which to create the directory.
fn path_create_directory(fd: i32, offset: i32, length: i32) -> i32;
/// Return the attributes of a file or directory.
///
/// # Note
///
/// This is similar to `stat` in POSIX.
///
/// # Parameters
///
/// - `fd`: The file descriptor.
/// - `flags`: Flags determining the method of how the path is resolved.
/// - `offset`, `length`: The offset/length pair used to create a guest pointer into host memory.
/// This pointer references the path string of the file or directory to inspect.
/// - `offset0`: The buffer where the file's attributes are stored.
fn path_filestat_get(fd: i32, flags: i32, offset: i32, length: i32, offset0: i32) -> i32;
/// Adjust the timestamps of a file or directory.
///
/// # Note
///
/// This is similar to `utimensat` in POSIX.
///
/// # Parameters
///
/// - `fd`: The file descriptor.
/// - `flags`: Flags determining the method of how the path is resolved.
/// - `offset`, `length`: The offset/length pair used to create a guest pointer into host memory.
/// This pointer references the path string of the file or directory to operate on.
/// - `atim`: The desired values of the data access timestamp.
/// - `mtim`: The desired values of the data modification timestamp.
/// - `fst_flags`: A bitmask indicating which timestamps to adjust.
fn path_filestat_set_times(
fd: i32,
flags: i32,
offset: i32,
length: i32,
atim: i64,
mtim: i64,
fst_flags: i32,
) -> i32;
/// Create a hard link.
///
/// # Note
///
/// This is similar to `linkat` in POSIX.
///
/// # Parameters
///
/// - `old_fd`: file descriptor
/// - `old_flags`: Flags determining the method of how the path is resolved.
/// - `old_offset`, `old_length`: The offset/length pair used to create a guest pointer into host memory.
/// This pointer references the path string source path from which to link.
/// - `new_fd`: The working directory at which the resolution of the new path starts.
/// - `new_offset`, `new_length`: The offset/length pair used to create a guest pointer into host memory.
/// This pointer references the path string, i.e. ehe destination path at
/// which to create the hard link.
fn path_link(
old_fd: i32,
old_flags: i32,
old_offset: i32,
old_length: i32,
new_fd: i32,
new_offset: i32,
new_length: i32,
) -> i32;
/// Open a file or directory.
///
/// # Note
///
/// - The returned file descriptor is not guaranteed to be the lowest-numbered file descriptor not currently open;
/// it is randomized to prevent applications from depending on making assumptions about indexes,
/// since this is error-prone in multi-threaded contexts.
/// - The returned file descriptor is guaranteed to be less than 2^31.
/// - This is similar to `openat` in POSIX.
///
/// # Parameters
///
/// - `fd`: The file descriptor.
/// - `dirflags`: Flags determining the method of how the path is resolved.
/// - `offset`, `length`: The offset/length pair used to create a guest pointer into host memory.
/// This pointer references the relative path of the file or directory to open,
/// relative to the `path_open::fd` directory.
/// - `oflags`: The method by which to open the file.
/// - `fs_rights_base`: The initial rights of the newly created file descriptor
/// - `fs_rights_inheriting`: The rights to inherit.
/// - `fdflags`: The file descriptor flags.
/// - `offset0`: The offset into memory where result is stored.
/// The result is the file descriptor of the file that has been opened.
fn path_open(
fd: i32,
dirflags: i32,
offset: i32,
length: i32,
oflags: i32,
fs_rights_base: i64,
fdflags: i64,
fs_rights_inheriting: i32,
offset0: i32,
) -> i32;
/// Read the contents of a symbolic link.
///
/// # Note
///
/// This is similar to `readlinkat` in POSIX.
///
/// # Parameters
///
/// - `fd`: The file descriptor.
/// - `offset`, `length`: The offset/length pair used to create a guest pointer into host memory.
/// This pointer references the path of the symbolic link from which to read.
/// - `buf`: The buffer to which to write the contents of the symbolic link.
/// - `buf_len`: The length of the `buf` buffer.
/// - `offset0`: The offset into memory where result is stored.
/// The result is the number of bytes placed in the buffer.
fn path_readlink(
fd: i32,
offset: i32,
length: i32,
buf: i32,
buf_len: i32,
offset0: i32,
) -> i32;
/// Remove a directory.
///
/// # Note
///
/// - Returns `errno::notempty` if the directory is not empty.
/// - This is similar to `unlinkat(fd, path, AT_REMOVEDIR)` in POSIX.
///
/// # Parameters
///
/// - `fd`: The file descriptor.
/// - `offset`, `length`: The offset/length pair used to create a guest pointer into host memory.
/// This pointer references the path to the directory to remove.
fn path_remove_directory(fd: i32, offset: i32, length: i32) -> i32;
/// Rename a file or directory.
///
/// # Note
///
/// - This is similar to `renameat` in POSIX.
/// - This is similar to `unlinkat(fd, path, AT_REMOVEDIR)` in POSIX.
///
/// # Parameters
///
/// - `fd`: The file descriptor.
/// - `old_offset`, `old_length`: The offset/length pair used to create a guest pointer into host memory.
/// This pointer references the source path of the file or directory to rename.
/// - `new_fd`: The working directory at which the resolution of the new path starts.
/// - `new_offset`, `new_length`: The offset/length pair used to create a guest pointer into host memory.
/// This pointer references the destination path to which to rename the file or directory.
fn path_rename(
fd: i32,
old_offset: i32,
old_length: i32,
new_fd: i32,
new_offset: i32,
new_length: i32,
) -> i32;
/// Create a symbolic link.
///
/// # Note
///
/// This is similar to `symlinkat` in POSIX.
///
/// # Parameters
///
/// - `old_offset`, `old_length`: The offset/length pair used to create a guest pointer into host memory.
/// This pointer references the path to the contents of the symbolic link.
/// - `fd`: The file descriptor.
/// - `new_offset`, `new_length`: The offset/length pair used to create a guest pointer into host memory.
/// This pointer references the destination path at which to create the symbolic link.
fn path_symlink(
old_offset: i32,
old_length: i32,
fd: i32,
new_offset: i32,
new_length: i32,
) -> i32;
/// Unlink a file.
///
/// # Note
///
/// - Returns `errno::isdir` if the path refers to a directory.
/// - This is similar to `unlinkat(fd, path, 0)` in POSIX.
///
/// # Parameters
///
/// - `fd`: The file descriptor.
/// - `offset`, `length`: The offset/length pair used to create a guest pointer into host memory.
/// This pointer references the path to a file to unlink.
fn path_unlink_file(fd: i32, offset: i32, length: i32) -> i32;
/// Concurrently poll for the occurrence of a set of events.
///
/// # Parameters
///
/// - `in_`: The events to which to subscribe.
/// - `out`: The events that have occurred.
/// - `nsubscriptions`: Both the number of subscriptions and events.
/// - `offset0`: The offset into memory where the number of events is stored.
fn poll_oneoff(in_: i32, out: i32, nsubscriptions: i32, offset0: i32) -> i32;
/// Terminate the process normally.
///
/// # Note
///
/// An exit code of 0 indicates successful termination of the program.
/// The meanings of other values is dependent on the environment.
///
/// # Parameters
///
/// - `rval`: The exit code returned by the process.
fn proc_exit(rval: i32) -> ();
/// Send a signal to the process of the calling thread.
/// Note: This is similar to `raise` in POSIX.
/// # Parameters
///
/// sig: The signal condition to trigger.
fn proc_raise(sig: i32) -> i32;
/// Temporarily yield execution of the calling thread.
///
/// # Note
///
/// This is similar to sched_yield in POSIX.
fn sched_yield() -> i32;
/// Write high-quality random data into a buffer.
///
/// # Parameters
///
/// - `buf`: The buffer to fill with random data.
/// - `buf_len`: The length of the `buf` buffer.
fn random_get(buf: i32, buf_len: i32) -> i32;
/// Accept a new incoming connection.
///
/// # Note
///
/// This is similar to `accept` in POSIX.
///
/// # Parameters
///
/// - `fd`: The listening socket.
/// - `flags`: The desired values of the file descriptor flags.
/// - `offset0`: The offset into memory where the new socket connection `fd` is stored.
fn sock_accept(fd: i32, flags: i32, offset0: i32) -> i32;
/// Receive a message from a socket.
///
/// # Note
///
/// This is similar to `recv` in POSIX, though it also supports reading
/// the data into multiple buffers in the manner of `readv`.
///
/// # Parameters
///
/// - `fd`: The file descriptor.
/// - `iov_buf`, `iov_buf_len`: Used to create `iovec`, which is the list of scatter/gather
/// vectors in which to store data.
/// - `ri_flags`: The message flags.
/// - `offset0`, `offset1`: The offset into memory where the number of
/// bytes in `ri_data` and message flags are stored.
fn sock_recv(
fd: i32,
iov_buf: i32,
iov_buf_len: i32,
ri_flags: i32,
offset0: i32,
offset1: i32,
) -> i32;
/// Send a message on a socket.
///
/// # Note
///
/// This is similar to `send` in POSIX, though it also supports writing
/// the data from multiple buffers in the manner of `writev`.
///
/// # Parameters
///
/// - `fd`: The file descriptor.
/// - `ciov_buf`, `ciov_buf_len`: Used to create ciovec, which is the list of
/// scatter/gather vectors from which to retrieve data.
/// - `si_flags`: The message flags.
/// - `offset0`: The offset into memory where number of bytes transmitted is stored.
fn sock_send(fd: i32, ciov_buf: i32, ciov_buf_len: i32, si_flags: i32, offset0: i32) -> i32;
/// Shut down socket send and receive channels.
///
/// # Note
///
/// This is similar to `shutdown` in POSIX.
///
/// # Parameters
///
/// - `fd`: The file descriptor.
/// - `how`: Which channels on the socket to shut down.
fn sock_shutdown(fd: i32, how: i32) -> i32;
}
};
}
pub mod wrapped {
use super::*;
apply_wasi_definitions!(wrap_wasi_funcs);
}
apply_wasi_definitions!(add_funcs_to_linker);
apply_wasi_definitions!(add_funcs_to_externals);
use crateWasmiGuestMemory;
use ;
use ;
use ;
// Creates a dummy `RawWaker`. We can only create Wakers from `RawWaker`s
// Creates a dummy waker which does *nothing*, as the future itself polls to ready at first poll
// A waker is needed to do any polling at all, as it is the primary constituent of the `Context` for polling
/// Implemented by Wasmi [`Linker`] to populate them with WASI definitions.
///
/// [`Linker`]: wasmi::Linker