Basic groundwork for viperid, a fantasy console

This commit is contained in:
Pyrex 2024-04-21 22:10:48 -07:00
commit 13b61a6def
23 changed files with 1541 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

129
Cargo.lock generated Normal file
View File

@ -0,0 +1,129 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "anyhow"
version = "1.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519"
[[package]]
name = "autocfg"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
[[package]]
name = "downcast-rs"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2"
[[package]]
name = "editor"
version = "0.1.0"
dependencies = [
"anyhow",
"player",
"viperid",
]
[[package]]
name = "indexmap-nostd"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e04e2fd2b8188ea827b32ef11de88377086d690286ab35747ef7f9bf3ccb590"
[[package]]
name = "libm"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
[[package]]
name = "minifb_host"
version = "0.1.0"
[[package]]
name = "num-traits"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
dependencies = [
"autocfg",
]
[[package]]
name = "paste"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
[[package]]
name = "player"
version = "0.1.0"
dependencies = [
"anyhow",
"viperid",
"wasmi",
]
[[package]]
name = "smallvec"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "spin"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
[[package]]
name = "viperid"
version = "0.1.0"
dependencies = [
"anyhow",
]
[[package]]
name = "wasmi"
version = "0.31.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77a8281d1d660cdf54c76a3efa9ddd0c270cada1383a995db3ccb43d166456c7"
dependencies = [
"smallvec",
"spin",
"wasmi_arena",
"wasmi_core",
"wasmparser-nostd",
]
[[package]]
name = "wasmi_arena"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "104a7f73be44570cac297b3035d76b169d6599637631cf37a1703326a0727073"
[[package]]
name = "wasmi_core"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcf1a7db34bff95b85c261002720c00c3a6168256dcb93041d3fa2054d19856a"
dependencies = [
"downcast-rs",
"libm",
"num-traits",
"paste",
]
[[package]]
name = "wasmparser-nostd"
version = "0.100.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5a015fe95f3504a94bb1462c717aae75253e39b9dd6c3fb1062c934535c64aa"
dependencies = [
"indexmap-nostd",
]

16
Cargo.toml Normal file
View File

@ -0,0 +1,16 @@
[package]
name = "viperid"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "1.0.82"
[workspace]
members = [
"crates/editor",
"crates/minifb_host",
"crates/player"
]

6
README.md Normal file
View File

@ -0,0 +1,6 @@
To launch the editor:
```
$ cargo run --manifest-path crates\editor\Cargo.toml
```

1
crates/editor/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
target/

24
crates/editor/Cargo.lock generated Normal file
View File

@ -0,0 +1,24 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "anyhow"
version = "1.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519"
[[package]]
name = "editor"
version = "0.1.0"
dependencies = [
"anyhow",
"shared",
]
[[package]]
name = "shared"
version = "0.1.0"
dependencies = [
"anyhow",
]

11
crates/editor/Cargo.toml Normal file
View File

@ -0,0 +1,11 @@
[package]
name = "editor"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "1.0.82"
player = { path = "../player" }
viperid = { path = "../.." }

View File

@ -0,0 +1,80 @@
use std::{fs::File, io::Read, path::{Path, PathBuf}, process::Command};
use viperid::VResult;
pub struct GoBuilder {
project_directory: PathBuf,
entry_point: PathBuf
}
impl GoBuilder {
pub fn new(project_directory: &Path) -> VResult<GoBuilder> {
// make sure Go is a supported version
let output = Command::new("go").arg("version").output()?;
if !output.status.success() {
anyhow::bail!("Go is not installed or did not start: {:?}", output.status)
}
// TODO: Support more Go versions
let text = output.stdout;
if !text.starts_with(b"go version go1.21") {
anyhow::bail!("unsupported Go version (must be 1.21): {}", String::from_utf8_lossy(&text).trim())
}
// make sure the project is really here
if !project_directory.exists() {
anyhow::bail!("project directory must exist: {}", project_directory.to_string_lossy())
}
let entry_point = project_directory.join("main.go");
if !entry_point.exists() {
anyhow::bail!("entry point must exist: {}", entry_point.to_string_lossy())
}
// OK, we should be able to do things with Go without any errors
Ok(GoBuilder {
project_directory: PathBuf::from(project_directory),
entry_point
})
}
pub fn build(&self) -> VResult<Vec<u8>> {
// NOTE: We've checked that the project directory exists
if !self.project_directory.exists() {
anyhow::bail!(
"project directory disappeared: {}",
self.project_directory.to_string_lossy()
);
}
if !self.entry_point.exists() {
anyhow::bail!(
"entry point disappeared: {}",
self.entry_point.to_string_lossy()
);
}
let project_directory = &self.project_directory;
let entry_point = &self.entry_point;
let build_directory = project_directory.join("build");
let wasm_name = build_directory.join("game.wasm");
let mut child = Command::new("go")
.args(["build", "-o"]).arg(&wasm_name)
.env("GOOS", "wasip1")
.env("GOARCH", "wasm")
.arg("-trimpath")
.arg(entry_point)
.spawn()?;
let status = child.wait()?;
if !status.success() {
anyhow::bail!("go failed");
}
let mut buf = vec![];
File::open(wasm_name)?.read_to_end(&mut buf)?;
Ok(buf)
}
}

14
crates/editor/src/main.rs Normal file
View File

@ -0,0 +1,14 @@
use std::path::PathBuf;
use viperid::VResult;
use crate::go_builder::GoBuilder;
mod go_builder;
fn main() -> VResult<()> {
let builder = GoBuilder::new(&PathBuf::from("example_project"))?;
let wasm = builder.build()?;
player::run_entry_point(&wasm)?;
Ok(())
}

View File

@ -0,0 +1,8 @@
[package]
name = "minifb_host"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View File

11
crates/player/Cargo.toml Normal file
View File

@ -0,0 +1,11 @@
[package]
name = "player"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "1.0.82"
viperid = { path = "../.." }
wasmi = "0.31.2"

View File

@ -0,0 +1,37 @@
use viperid::VResult;
use wasmi::{Engine, Linker, Module, Store};
use crate::wasi::{self, StockWasi};
struct ExecutorState {
wasi: wasi::StockWasi
}
impl ExecutorState {
fn new() -> Self {
ExecutorState {
wasi: StockWasi::new()
}
}
}
pub fn run_entry_point(wasm: &[u8]) -> VResult<()> {
let engine = Engine::default();
let module = Module::new(&engine, wasm)?;
let mut store = Store::new(&engine, ExecutorState::new());
let mut linker = <Linker<ExecutorState>>::new(&engine);
wasi::integrate(&mut linker, |hs| &mut hs.wasi)?;
let instance = linker
.instantiate(&mut store, &module)?
.start(&mut store)?;
let main = instance.get_typed_func::<(), ()>(&store, "_start")?;
main.call(&mut store, ())?;
Ok(())
}

4
crates/player/src/lib.rs Normal file
View File

@ -0,0 +1,4 @@
mod executor;
mod wasi;
pub use executor::run_entry_point;

View File

@ -0,0 +1,346 @@
use std::time::SystemTime;
use wasmi::core::Trap;
use super::MinimalPreview1;
pub struct StockWasi {
}
impl StockWasi {
pub fn new() -> Self {
Self { }
}
}
// https://github.com/WebAssembly/wasi-libc/blob/main/libc-bottom-half/headers/public/wasi/api.h#L118
const BAD_DESCRIPTOR: i32 = 8;
const FUNCTION_NOT_IMPLEMENTED: i32 = 52;
// Implemented based on docs here
// https://wasix.org/docs/api-reference/wasi/fd_allocate
// https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/witx/wasi_snapshot_preview1.witx
impl MinimalPreview1 for StockWasi {
fn args_get(&mut self, _memory: &mut [u8], _argv: i32, _argv_buf: i32) -> super::MPResult<i32> {
Ok(0)
}
fn args_sizes_get(&mut self, memory: &mut [u8], argc: i32, argv_buf_size: i32) -> super::MPResult<i32> {
write_u32(memory, argc, 0);
write_u32(memory, argv_buf_size, 0);
Ok(0)
}
fn environ_get(&mut self, _memory: &mut [u8], _environ: i32, _environ_buf: i32) -> super::MPResult<i32> {
Ok(0)
}
fn environ_sizes_get(&mut self, memory: &mut [u8], environc: i32, environ_buf_size: i32) -> super::MPResult<i32> {
write_u32(memory, environc, 0);
write_u32(memory, environ_buf_size, 0);
Ok(0)
}
fn clock_res_get(&mut self, memory: &mut [u8], _id: i32, outptr: i32) -> super::MPResult<i32> {
write_u32(memory, outptr, 1000);
Ok(0)
}
fn clock_time_get(&mut self, memory: &mut [u8], id: i32, precision: i64, outptr: i32) -> super::MPResult<i32> {
println!("clock_time_get: {} {} {}", id, precision, outptr);
// TODO: Actually fetch time
let duration =
SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)
.expect("time must be post-epoch");
write_u64(memory, outptr, duration.as_nanos() as u64);
Ok(0)
}
fn fd_advise(&mut self, _memory: &mut [u8], _fd: i32, _offset: i64, _len: i64, _advice: i32) -> super::MPResult<i32> {
Ok(FUNCTION_NOT_IMPLEMENTED)
}
fn fd_allocate(&mut self, _memory: &mut [u8], _fd: i32, _offset: i64, _len: i64) -> super::MPResult<i32> {
Ok(FUNCTION_NOT_IMPLEMENTED)
}
fn fd_close(&mut self, _memory: &mut [u8], _fd: i32) -> super::MPResult<i32> {
Ok(FUNCTION_NOT_IMPLEMENTED)
}
fn fd_datasync(&mut self, _memory: &mut [u8], _fd: i32) -> super::MPResult<i32> {
Ok(FUNCTION_NOT_IMPLEMENTED)
}
fn fd_fdstat_get(&mut self, _memory: &mut [u8], _fd: i32, _offset0: i32) -> super::MPResult<i32> {
Ok(FUNCTION_NOT_IMPLEMENTED)
}
fn fd_fdstat_set_flags(&mut self, _memory: &mut [u8], _fd: i32, _flags: i32) -> super::MPResult<i32> {
Ok(FUNCTION_NOT_IMPLEMENTED)
}
fn fd_fdstat_set_rights(&mut self, _memory: &mut [u8], _fd: i32, _fs_rights_base: i64, _fs_rights_inheriting: i64) -> super::MPResult<i32> {
Ok(FUNCTION_NOT_IMPLEMENTED)
}
fn fd_filestat_get(&mut self, _memory: &mut [u8], _fd: i32, _offset0: i32) -> super::MPResult<i32> {
Ok(FUNCTION_NOT_IMPLEMENTED)
}
fn fd_filestat_set_size(&mut self, _memory: &mut [u8], _fd: i32, _size: i64) -> super::MPResult<i32> {
Ok(FUNCTION_NOT_IMPLEMENTED)
}
fn fd_filestat_set_times(&mut self, _memory: &mut [u8], _fd: i32, _atim: i64, _mtim: i64, _fst_flags: i32) -> super::MPResult<i32> {
Ok(FUNCTION_NOT_IMPLEMENTED)
}
fn fd_pread(&mut self, _memory: &mut [u8], _fd: i32, _iov_buf: i32, _iov_buf_len: i32, _offset: i64, _offset0: i32) -> super::MPResult<i32> {
Ok(FUNCTION_NOT_IMPLEMENTED)
}
fn fd_prestat_get(&mut self, _memory: &mut [u8], fd: i32, _offset0: i32) -> super::MPResult<i32> {
// for some reason TinyGo asks about fd 3 immediately
if fd == 3 {
return Ok(BAD_DESCRIPTOR);
}
Ok(FUNCTION_NOT_IMPLEMENTED)
}
fn fd_prestat_dir_name(&mut self, _memory: &mut [u8], _fd: i32, _path: i32, _path_len: i32) -> super::MPResult<i32> {
Ok(FUNCTION_NOT_IMPLEMENTED)
}
fn fd_pwrite(&mut self, _memory: &mut [u8], _fd: i32, _ciov_buf: i32, _ciov_buf_len: i32, _offset: i64, _offset0: i32) -> super::MPResult<i32> {
Ok(FUNCTION_NOT_IMPLEMENTED)
}
fn fd_read(&mut self, _memory: &mut [u8], _fd: i32, _iov_buf: i32, _iov_buf_len: i32, _offset1: i32) -> super::MPResult<i32> {
Ok(FUNCTION_NOT_IMPLEMENTED)
}
fn fd_readdir(&mut self, _memory: &mut [u8], _fd: i32, _buf: i32, _buf_len: i32, _cookie: i64, _offset0: i32) -> super::MPResult<i32> {
Ok(FUNCTION_NOT_IMPLEMENTED)
}
fn fd_renumber(&mut self, _memory: &mut [u8], _fd: i32, _to: i32) -> super::MPResult<i32> {
Ok(FUNCTION_NOT_IMPLEMENTED)
}
fn fd_seek(&mut self, _memory: &mut [u8], _fd: i32, _offset: i64, _whence: i32, _offset0: i32) -> super::MPResult<i32> {
Ok(FUNCTION_NOT_IMPLEMENTED)
}
fn fd_sync(&mut self, _memory: &mut [u8], _fd: i32) -> super::MPResult<i32> {
Ok(FUNCTION_NOT_IMPLEMENTED)
}
fn fd_tell(&mut self, _memory: &mut [u8], _fd: i32, _offset0: i32) -> super::MPResult<i32> {
Ok(FUNCTION_NOT_IMPLEMENTED)
}
fn fd_write(&mut self, memory: &mut [u8], fd: i32, ciov_buf: i32, ciov_buf_len: i32, n_written_ptr: i32) -> super::MPResult<i32> {
let mut out = vec![];
let mut n_written = 0;
for i in 0..ciov_buf_len {
let iov_ptr = ciov_buf + i * 8;
let ptr = read_u32(memory, iov_ptr);
let len = read_u32(memory, iov_ptr + 4);
n_written += len;
for b in 0..len {
out.push(memory[ptr as usize + b as usize]);
}
}
write_u32(memory, n_written_ptr, n_written);
if fd == 1 {
// stdout
println!("Written to stdout: {}", String::from_utf8_lossy(&out));
}
else if fd == 2 {
// stderr
println!("Written to stderr: {}", String::from_utf8_lossy(&out));
} else {
println!("Written to invalid FD {}: {}", fd, String::from_utf8_lossy(&out));
}
Ok(0)
}
fn path_create_directory(&mut self, _memory: &mut [u8], _fd: i32, _offset: i32, _length: i32) -> super::MPResult<i32> {
Ok(FUNCTION_NOT_IMPLEMENTED)
}
fn path_filestat_get(&mut self, _memory: &mut [u8], _fd: i32, _flags: i32, _offset: i32, _length: i32, _offset0: i32) -> super::MPResult<i32> {
Ok(FUNCTION_NOT_IMPLEMENTED)
}
fn path_filestat_set_times(
&mut self,
_memory: &mut [u8],
_fd: i32,
_flags: i32,
_offset: i32,
_length: i32,
_atim: i64,
_mtim: i64,
_fst_flags: i32,
) -> super::MPResult<i32> {
Ok(0)
}
fn path_link(
&mut self,
_memory: &mut [u8],
_old_fd: i32,
_old_flags: i32,
_old_offset: i32,
_old_length: i32,
_new_fd: i32,
_new_offset: i32,
_new_length: i32,
) -> super::MPResult<i32> {
Ok(0)
}
fn path_open(
&mut self,
_memory: &mut [u8],
_fd: i32,
_dirflags: i32,
_offset: i32,
_length: i32,
_oflags: i32,
_fs_rights_base: i64,
_fdflags: i64,
_fs_rights_inheriting: i32,
_offset0: i32,
) -> super::MPResult<i32> {
Ok(0)
}
fn path_readlink(
&mut self,
_memory: &mut [u8],
_fd: i32,
_offset: i32,
_length: i32,
_buf: i32,
_buf_len: i32,
_offset0: i32,
) -> super::MPResult<i32> {
Ok(0)
}
fn path_remove_directory(
&mut self,
_memory: &mut [u8],
_fd: i32, _offset: i32, _length: i32
) -> super::MPResult<i32> {
Ok(0)
}
fn path_rename(
&mut self,
_memory: &mut [u8],
_fd: i32,
_old_offset: i32,
_old_length: i32,
_new_fd: i32,
_new_offset: i32,
_new_length: i32,
) -> super::MPResult<i32> {
Ok(0)
}
fn path_symlink(
&mut self,
_memory: &mut [u8],
_old_offset: i32,
_old_length: i32,
_fd: i32,
_new_offset: i32,
_new_length: i32,
) -> super::MPResult<i32> {
Ok(0)
}
fn path_unlink_file(&mut self, _memory: &mut [u8], _fd: i32, _offset: i32, _length: i32) -> super::MPResult<i32> {
Ok(0)
}
fn poll_oneoff(&mut self, _memory: &mut [u8], _in_: i32, _out: i32, _nsubscriptions: i32, _offset0: i32) -> super::MPResult<i32> {
Ok(0)
}
fn proc_exit(&mut self, _memory: &mut [u8], rval: i32) -> super::MPResult<()> {
Err(Trap::i32_exit(rval))
}
fn proc_raise(&mut self, _memory: &mut [u8], _sig: i32) -> super::MPResult<i32> {
// TODO: Actually implement
Ok(0)
}
fn sched_yield(&mut self, _memory: &mut [u8]) -> super::MPResult<i32> {
Ok(0)
}
fn random_get(&mut self, _memory: &mut [u8], _buf: i32, _buf_len: i32) -> super::MPResult<i32> {
// TODO: Actually implement
Ok(0)
}
fn sock_accept(&mut self, _memory: &mut [u8], _fd: i32, _flags: i32, _offset0: i32) -> super::MPResult<i32> {
Ok(0)
}
fn sock_recv(
&mut self,
_memory: &mut [u8],
_fd: i32,
_iov_buf: i32,
_iov_buf_len: i32,
_ri_flags: i32,
_offset0: i32,
_offset1: i32,
) -> super::MPResult<i32> {
Ok(0)
}
fn sock_send(
&mut self,
_memory: &mut [u8],
_fd: i32, _ciov_buf: i32, _ciov_buf_len: i32, _si_flags: i32, _offset0: i32) -> super::MPResult<i32> {
Ok(0)
}
fn sock_shutdown(
&mut self,
_memory: &mut [u8],
_fd: i32, _how: i32) -> super::MPResult<i32> {
Ok(0)
}
}
fn read_u32(memory: &[u8], ptr: i32) -> u32 {
let ptr = ptr as usize;
let slice = &memory[ptr..ptr + 4];
let mut ary = [0; 4];
ary.copy_from_slice(slice);
return u32::from_le_bytes(ary)
}
fn write_u32(memory: &mut [u8], ptr: i32, value: u32) {
let ptr = ptr as usize;
(&mut memory[ptr..ptr + 4]).copy_from_slice(&value.to_le_bytes());
}
fn write_u64(memory: &mut [u8], ptr: i32, value: u64) {
let ptr = ptr as usize;
(&mut memory[ptr..ptr + 8]).copy_from_slice(&value.to_le_bytes());
}

View File

@ -0,0 +1,699 @@
// Based closely on
// https://github.com/wasmi-labs/wasmi/blob/master/crates/wasi/src/sync/snapshots/preview_1.rs
use wasmi::{Caller, Extern, Linker};
// Creates the function item `add_wasi_snapshot_preview1_to_wasmi_linker` which when called adds all
// `wasi preview_1` functions to the linker
macro_rules! impl_add_to_linker_for_funcs {
(
$(
$( #[$docs:meta] )*
fn $fname:ident ($( $arg:ident : $typ:ty ),* $(,)? ) -> $ret:tt
);+ $(;)?
) => {
/// Adds the entire `WASI API` to the [`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/main/phases/snapshot/docs.md) for more details.
pub fn integrate<T, U>(
linker: &mut Linker<T>,
wasi_ctx: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static,
) -> Result<(), wasmi::Error>
where U: crate::wasi::MinimalPreview1
{
$(
// $(#[$docs])* // TODO: find place for docs
linker.func_wrap(
"wasi_snapshot_preview1",
stringify!($fname),
move |mut caller: Caller<'_, T>, $($arg : $typ,)*| -> Result<$ret, wasmi::core::Trap> {
let memory = match caller.get_export("memory") {
Some(Extern::Memory(m)) => m,
_ => return Err(wasmi::core::Trap::new(String::from("missing required WASI memory export"))),
};
let(memory, ctx) = memory.data_and_store_mut(&mut caller);
let ctx = wasi_ctx(ctx);
println!("syscall: {}", stringify!($fname));
let result = crate::wasi::MinimalPreview1::$fname(ctx, memory, $($arg,)*)?;
Ok(<$ret>::from(result))
}
)?;
)*
Ok(())
}
}
}
impl_add_to_linker_for_funcs!(
/// 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;
);

View File

@ -0,0 +1,127 @@
pub type MPResult<T> = Result<T, wasmi::core::Trap>;
pub trait MinimalPreview1 {
fn args_get(&mut self, memory: &mut [u8], argv: i32, argv_buf: i32) -> MPResult<i32>;
fn args_sizes_get(&mut self, memory: &mut [u8], offset0: i32, offset1: i32) -> MPResult<i32>;
fn environ_get(&mut self, memory: &mut [u8], environ: i32, environ_buf: i32) -> MPResult<i32>;
fn environ_sizes_get(&mut self, memory: &mut [u8], offset0: i32, offset1: i32) -> MPResult<i32>;
fn clock_res_get(&mut self, memory: &mut [u8], id: i32, offset0: i32) -> MPResult<i32>;
fn clock_time_get(&mut self, memory: &mut [u8], id: i32, precision: i64, offset0: i32) -> MPResult<i32>;
fn fd_advise(&mut self, memory: &mut [u8], fd: i32, offset: i64, len: i64, advice: i32) -> MPResult<i32>;
fn fd_allocate(&mut self, memory: &mut [u8], fd: i32, offset: i64, len: i64) -> MPResult<i32>;
fn fd_close(&mut self, memory: &mut [u8], fd: i32) -> MPResult<i32>;
fn fd_datasync(&mut self, memory: &mut [u8], fd: i32) -> MPResult<i32>;
fn fd_fdstat_get(&mut self, memory: &mut [u8], fd: i32, offset0: i32) -> MPResult<i32>;
fn fd_fdstat_set_flags(&mut self, memory: &mut [u8], fd: i32, flags: i32) -> MPResult<i32>;
fn fd_fdstat_set_rights(&mut self, memory: &mut [u8], fd: i32, fs_rights_base: i64, fs_rights_inheriting: i64) -> MPResult<i32>;
fn fd_filestat_get(&mut self, memory: &mut [u8], fd: i32, offset0: i32) -> MPResult<i32>;
fn fd_filestat_set_size(&mut self, memory: &mut [u8], fd: i32, size: i64) -> MPResult<i32>;
fn fd_filestat_set_times(&mut self, memory: &mut [u8], fd: i32, atim: i64, mtim: i64, fst_flags: i32) -> MPResult<i32>;
fn fd_pread(&mut self, memory: &mut [u8], fd: i32, iov_buf: i32, iov_buf_len: i32, offset: i64, offset0: i32) -> MPResult<i32>;
fn fd_prestat_get(&mut self, memory: &mut [u8], fd: i32, offset0: i32) -> MPResult<i32>;
fn fd_prestat_dir_name(&mut self, memory: &mut [u8], fd: i32, path: i32, path_len: i32) -> MPResult<i32>;
fn fd_pwrite(&mut self, memory: &mut [u8], fd: i32, ciov_buf: i32, ciov_buf_len: i32, offset: i64, offset0: i32) -> MPResult<i32>;
fn fd_read(&mut self, memory: &mut [u8], fd: i32, iov_buf: i32, iov_buf_len: i32, offset1: i32) -> MPResult<i32>;
fn fd_readdir(&mut self, memory: &mut [u8], fd: i32, buf: i32, buf_len: i32, cookie: i64, offset0: i32) -> MPResult<i32>;
fn fd_renumber(&mut self, memory: &mut [u8], fd: i32, to: i32) -> MPResult<i32>;
fn fd_seek(&mut self, memory: &mut [u8], fd: i32, offset: i64, whence: i32, offset0: i32) -> MPResult<i32>;
fn fd_sync(&mut self, memory: &mut [u8], fd: i32) -> MPResult<i32>;
fn fd_tell(&mut self, memory: &mut [u8], fd: i32, offset0: i32) -> MPResult<i32>;
fn fd_write(&mut self, memory: &mut [u8], fd: i32, ciov_buf: i32, ciov_buf_len: i32, offset0: i32) -> MPResult<i32>;
fn path_create_directory(&mut self, memory: &mut [u8], fd: i32, offset: i32, length: i32) -> MPResult<i32>;
fn path_filestat_get(&mut self, memory: &mut [u8], fd: i32, flags: i32, offset: i32, length: i32, offset0: i32) -> MPResult<i32>;
fn path_filestat_set_times(
&mut self,
memory: &mut [u8],
fd: i32,
flags: i32,
offset: i32,
length: i32,
atim: i64,
mtim: i64,
fst_flags: i32,
) -> MPResult<i32>;
fn path_link(
&mut self,
memory: &mut [u8],
old_fd: i32,
old_flags: i32,
old_offset: i32,
old_length: i32,
new_fd: i32,
new_offset: i32,
new_length: i32,
) -> MPResult<i32>;
fn path_open(
&mut self,
memory: &mut [u8],
fd: i32,
dirflags: i32,
offset: i32,
length: i32,
oflags: i32,
fs_rights_base: i64,
fdflags: i64,
fs_rights_inheriting: i32,
offset0: i32,
) -> MPResult<i32>;
fn path_readlink(
&mut self,
memory: &mut [u8],
fd: i32,
offset: i32,
length: i32,
buf: i32,
buf_len: i32,
offset0: i32,
) -> MPResult<i32>;
fn path_remove_directory(
&mut self,
memory: &mut [u8],
fd: i32, offset: i32, length: i32
) -> MPResult<i32>;
fn path_rename(
&mut self,
memory: &mut [u8],
fd: i32,
old_offset: i32,
old_length: i32,
new_fd: i32,
new_offset: i32,
new_length: i32,
) -> MPResult<i32>;
fn path_symlink(
&mut self,
memory: &mut [u8],
old_offset: i32,
old_length: i32,
fd: i32,
new_offset: i32,
new_length: i32,
) -> MPResult<i32>;
fn path_unlink_file(&mut self, memory: &mut [u8], fd: i32, offset: i32, length: i32) -> MPResult<i32>;
fn poll_oneoff(&mut self, memory: &mut [u8], in_: i32, out: i32, nsubscriptions: i32, offset0: i32) -> MPResult<i32>;
fn proc_exit(&mut self, memory: &mut [u8], rval: i32) -> MPResult<()>;
fn proc_raise(&mut self, memory: &mut [u8], sig: i32) -> MPResult<i32>;
fn sched_yield(&mut self, memory: &mut [u8]) -> MPResult<i32>;
fn random_get(&mut self, memory: &mut [u8], buf: i32, buf_len: i32) -> MPResult<i32>;
fn sock_accept(&mut self, memory: &mut [u8], fd: i32, flags: i32, offset0: i32) -> MPResult<i32>;
fn sock_recv(
&mut self,
memory: &mut [u8],
fd: i32,
iov_buf: i32,
iov_buf_len: i32,
ri_flags: i32,
offset0: i32,
offset1: i32,
) -> MPResult<i32>;
fn sock_send(
&mut self,
memory: &mut [u8],
fd: i32, ciov_buf: i32, ciov_buf_len: i32, si_flags: i32, offset0: i32) -> MPResult<i32>;
fn sock_shutdown(
&mut self,
memory: &mut [u8],
fd: i32, how: i32) -> MPResult<i32>;
}

View File

@ -0,0 +1,7 @@
mod interface;
mod integration;
mod implementation;
pub use interface::{MPResult, MinimalPreview1};
pub use integration::integrate;
pub use implementation::StockWasi;

0
example_project/.gitignore vendored Normal file
View File

Binary file not shown.

3
example_project/go.mod Normal file
View File

@ -0,0 +1,3 @@
module example_project
go 1.21.5

16
example_project/main.go Normal file
View File

@ -0,0 +1,16 @@
package main
import (
"fmt"
"runtime/debug"
)
func main() {
count := 0
for {
fmt.Printf("Hello! %d", count)
count++
debug.PrintStack()
panic("pizza!")
}
}

1
src/lib.rs Normal file
View File

@ -0,0 +1 @@
pub type VResult<T> = Result<T, anyhow::Error>;