Basic groundwork for viperid, a fantasy console
This commit is contained in:
commit
13b61a6def
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/target
|
129
Cargo.lock
generated
Normal file
129
Cargo.lock
generated
Normal 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
16
Cargo.toml
Normal 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
6
README.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
To launch the editor:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cargo run --manifest-path crates\editor\Cargo.toml
|
||||||
|
```
|
||||||
|
|
1
crates/editor/.gitignore
vendored
Normal file
1
crates/editor/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
target/
|
24
crates/editor/Cargo.lock
generated
Normal file
24
crates/editor/Cargo.lock
generated
Normal 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
11
crates/editor/Cargo.toml
Normal 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 = "../.." }
|
80
crates/editor/src/go_builder.rs
Normal file
80
crates/editor/src/go_builder.rs
Normal 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
14
crates/editor/src/main.rs
Normal 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(())
|
||||||
|
}
|
8
crates/minifb_host/Cargo.toml
Normal file
8
crates/minifb_host/Cargo.toml
Normal 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]
|
0
crates/minifb_host/src/lib.rs
Normal file
0
crates/minifb_host/src/lib.rs
Normal file
11
crates/player/Cargo.toml
Normal file
11
crates/player/Cargo.toml
Normal 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"
|
37
crates/player/src/executor.rs
Normal file
37
crates/player/src/executor.rs
Normal 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
4
crates/player/src/lib.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
mod executor;
|
||||||
|
mod wasi;
|
||||||
|
|
||||||
|
pub use executor::run_entry_point;
|
346
crates/player/src/wasi/implementation.rs
Normal file
346
crates/player/src/wasi/implementation.rs
Normal 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());
|
||||||
|
}
|
699
crates/player/src/wasi/integration.rs
Normal file
699
crates/player/src/wasi/integration.rs
Normal 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;
|
||||||
|
);
|
127
crates/player/src/wasi/interface.rs
Normal file
127
crates/player/src/wasi/interface.rs
Normal 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>;
|
||||||
|
}
|
7
crates/player/src/wasi/mod.rs
Normal file
7
crates/player/src/wasi/mod.rs
Normal 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
0
example_project/.gitignore
vendored
Normal file
BIN
example_project/build/game.wasm
Normal file
BIN
example_project/build/game.wasm
Normal file
Binary file not shown.
3
example_project/go.mod
Normal file
3
example_project/go.mod
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module example_project
|
||||||
|
|
||||||
|
go 1.21.5
|
16
example_project/main.go
Normal file
16
example_project/main.go
Normal 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
1
src/lib.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub type VResult<T> = Result<T, anyhow::Error>;
|
Loading…
Reference in New Issue
Block a user