Simple PoC with Wit and WASMA

This commit is contained in:
SeanOMik 2024-04-11 19:03:39 -04:00
parent 808819adbf
commit 1c5a24c320
Signed by: SeanOMik
GPG Key ID: FEC9E2FC15235964
12 changed files with 2530 additions and 0 deletions

1
.envrc Normal file
View File

@ -0,0 +1 @@
use_nix

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"nixEnvSelector.nixFile": "${workspaceFolder}/shell.nix"
}

2294
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

13
Cargo.toml Normal file
View File

@ -0,0 +1,13 @@
workspace = { members = ["witguest"] }
[package]
name = "wittest"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
async-trait = "0.1.80"
tokio = { version = "1.37.0", features = ["full"] }
wasmtime = "19.0.2"
wasmtime-wasi = "19.0.2"

27
shell.nix Normal file
View File

@ -0,0 +1,27 @@
let
rust_overlay = import (builtins.fetchTarball "https://github.com/oxalica/rust-overlay/archive/master.tar.gz");
pkgs = import <nixpkgs> { overlays = [ rust_overlay ]; };
rust = pkgs.rust-bin.stable.latest.default.override {
targets = [
"x86_64-unknown-linux-gnu"
"wasm32-unknown-unknown"
"wasm32-wasi"
];
extensions = [
"rust-analyzer"
"rust-src"
#"miri-preview"
];
};
in
pkgs.mkShell.override {
stdenv = pkgs.stdenvAdapters.useMoldLinker pkgs.clangStdenv;
} rec {
buildInputs = [
rust
] ++ (with pkgs; [
cargo-component wasmtime wasm-tools
]);
LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath buildInputs;
}

58
src/main.rs Normal file
View File

@ -0,0 +1,58 @@
use async_trait::async_trait;
use wasmtime_wasi::WasiView;
wasmtime::component::bindgen!({
world: "example",
path: "witguest/wit/world.wit",
//tracing: true,
async: true,
});
struct Imports {
}
impl WasiView for Imports {
fn table(&mut self) -> &mut wasmtime_wasi::ResourceTable {
todo!()
}
fn ctx(&mut self) -> &mut wasmtime_wasi::WasiCtx {
todo!()
}
}
#[async_trait]
impl ExampleImports for Imports {
async fn host_test(&mut self,) -> wasmtime::Result<()> {
println!("This is the host saying hi from the guest!");
Ok(())
}
}
#[tokio::main]
async fn main() -> wasmtime::Result<()> {
// Instantiate the engine and store
let mut config = wasmtime::Config::default();
config.async_support(true);
let engine = wasmtime::Engine::new(&config)?;
let mut store = wasmtime::Store::new(&engine, Imports {});
// Load the component from disk
let bytes = std::fs::read("target/wasm32-wasi/debug/witguest.wasm")?;
let component = wasmtime::component::Component::new(&engine, bytes)?;
// Configure the linker
let mut linker = wasmtime::component::Linker::new(&engine);
wasmtime_wasi::bindings::Imports::add_to_linker(&mut linker, |s| s)?;
Example::add_to_linker(&mut linker, |s| s)?;
// Instantiate the component
println!("creating example");
let (example, _instance) = Example::instantiate_async(&mut store, &component, &linker).await?;
let result = example.call_hello_world(&mut store).await?;
println!("Guest says: {}", result);
Ok(())
}

10
witguest/.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,10 @@
{
"rust-analyzer.check.overrideCommand": [
"cargo",
"component",
"check",
"--workspace",
"--all-targets",
"--message-format=json"
],
}

17
witguest/Cargo.toml Normal file
View File

@ -0,0 +1,17 @@
[package]
name = "witguest"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
wit-bindgen = { version = "0.24.0", default-features = false, features = ["realloc"] }
[lib]
crate-type = ["cdylib"]
[package.metadata.component]
package = "component:witguest"
[package.metadata.component.dependencies]

86
witguest/src/bindings.rs Normal file
View File

@ -0,0 +1,86 @@
// Generated by `wit-bindgen` 0.18.0. DO NOT EDIT!
#[allow(unused_unsafe, clippy::all)]
pub fn host_test(){
#[allow(unused_imports)]
use wit_bindgen::rt::{alloc, vec::Vec, string::String};
unsafe {
#[cfg(target_arch = "wasm32")]
#[link(wasm_import_module = "$root")]
extern "C" {
#[link_name = "host-test"]
fn wit_import();
}
#[cfg(not(target_arch = "wasm32"))]
fn wit_import(){ unreachable!() }
wit_import();
}
}
const _: () = {
#[doc(hidden)]
#[export_name = "hello-world"]
#[allow(non_snake_case)]
unsafe extern "C" fn __export_hello_world() -> i32 {
#[allow(unused_imports)]
use wit_bindgen::rt::{alloc, vec::Vec, string::String};
// Before executing any other code, use this function to run all static
// constructors, if they have not yet been run. This is a hack required
// to work around wasi-libc ctors calling import functions to initialize
// the environment.
//
// This functionality will be removed once rust 1.69.0 is stable, at which
// point wasi-libc will no longer have this behavior.
//
// See
// https://github.com/bytecodealliance/preview2-prototyping/issues/99
// for more details.
#[cfg(target_arch="wasm32")]
wit_bindgen::rt::run_ctors_once();
let result0 = <_GuestImpl as Guest>::hello_world();
let ptr1 = _RET_AREA.0.as_mut_ptr() as i32;
let vec2 = (result0.into_bytes()).into_boxed_slice();
let ptr2 = vec2.as_ptr() as i32;
let len2 = vec2.len() as i32;
::core::mem::forget(vec2);
*((ptr1 + 4) as *mut i32) = len2;
*((ptr1 + 0) as *mut i32) = ptr2;
ptr1
}
const _: () = {
#[doc(hidden)]
#[export_name = "cabi_post_hello-world"]
#[allow(non_snake_case)]
unsafe extern "C" fn __post_return_hello_world(arg0: i32,) {
let l0 = *((arg0 + 0) as *const i32);
let l1 = *((arg0 + 4) as *const i32);
wit_bindgen::rt::dealloc(l0, (l1) as usize, 1);
}
};
};
use super::Component as _GuestImpl;
pub trait Guest {
fn hello_world() -> wit_bindgen::rt::string::String;
}
#[allow(unused_imports)]
use wit_bindgen::rt::{alloc, vec::Vec, string::String};
#[repr(align(4))]
struct _RetArea([u8; 8]);
static mut _RET_AREA: _RetArea = _RetArea([0; 8]);
#[cfg(target_arch = "wasm32")]
#[link_section = "component-type:example"]
#[doc(hidden)]
pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 201] = [0, 97, 115, 109, 13, 0, 1, 0, 0, 25, 22, 119, 105, 116, 45, 99, 111, 109, 112, 111, 110, 101, 110, 116, 45, 101, 110, 99, 111, 100, 105, 110, 103, 4, 0, 7, 77, 1, 65, 2, 1, 65, 4, 1, 64, 0, 1, 0, 3, 0, 9, 104, 111, 115, 116, 45, 116, 101, 115, 116, 1, 0, 1, 64, 0, 0, 115, 4, 0, 11, 104, 101, 108, 108, 111, 45, 119, 111, 114, 108, 100, 1, 1, 4, 1, 26, 99, 111, 109, 112, 111, 110, 101, 110, 116, 58, 119, 105, 116, 103, 117, 101, 115, 116, 47, 101, 120, 97, 109, 112, 108, 101, 4, 0, 11, 13, 1, 0, 7, 101, 120, 97, 109, 112, 108, 101, 3, 0, 0, 0, 70, 9, 112, 114, 111, 100, 117, 99, 101, 114, 115, 1, 12, 112, 114, 111, 99, 101, 115, 115, 101, 100, 45, 98, 121, 2, 13, 119, 105, 116, 45, 99, 111, 109, 112, 111, 110, 101, 110, 116, 6, 48, 46, 50, 49, 46, 48, 16, 119, 105, 116, 45, 98, 105, 110, 100, 103, 101, 110, 45, 114, 117, 115, 116, 6, 48, 46, 49, 56, 46, 48];
#[inline(never)]
#[doc(hidden)]
#[cfg(target_arch = "wasm32")]
pub fn __link_section() {}

13
witguest/src/lib.rs Normal file
View File

@ -0,0 +1,13 @@
mod bindings;
use bindings::Guest;
struct Component;
impl Guest for Component {
/// Say hello!
fn hello_world() -> String {
bindings::host_test();
"Hello, World!".to_string()
}
}

7
witguest/wit/world.wit Normal file
View File

@ -0,0 +1,7 @@
package component:witguest;
/// An example world for the component to target.
world example {
import host-test: func();
export hello-world: func() -> string;
}