update wasm related dependencies, make it easier to create components on the guest

This commit is contained in:
SeanOMik 2024-07-24 20:32:59 -04:00
parent a58dcfb53d
commit f6933de559
Signed by: SeanOMik
GPG Key ID: FEC9E2FC15235964
16 changed files with 957 additions and 359 deletions

View File

@ -1,3 +1,7 @@
{ {
"nixEnvSelector.nixFile": "${workspaceFolder}/shell.nix" "nixEnvSelector.nixFile": "${workspaceFolder}/shell.nix",
"rust-analyzer.showUnlinkedFileNotification": false,
"rust-analyzer.check.extraArgs": [
"--target-dir=target/analyzer"
],
} }

485
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,5 @@
workspace = { members = [ "common-api","witguest"] } workspace = { members = [ "common-api", "witguest"] }
[package] [package]
name = "wittest" name = "wittest"
version = "0.1.0" version = "0.1.0"
@ -9,8 +10,8 @@ edition = "2021"
[dependencies] [dependencies]
async-trait = "0.1.80" async-trait = "0.1.80"
tokio = { version = "1.37.0", features = ["full"] } tokio = { version = "1.37.0", features = ["full"] }
wasmtime = "19.0.2" wasmtime = "23.0.1"
wasmtime-wasi = "19.0.2" wasmtime-wasi = "23.0.1"
lyra-ecs = { path = "./lyra-engine/lyra-ecs" } lyra-ecs = { path = "./lyra-engine/lyra-ecs" }
slab = "0.4.9" slab = "0.4.9"
thiserror = "1.0.58" thiserror = "1.0.58"

View File

@ -1,3 +1,26 @@
# lyra-wasm-scripting-test # lyra-wasm-scripting-test
A test zone for implementing WASM scripting into the Lyra engine A test zone for implementing WASM scripting into the Lyra engine
## Building
Install the `wasm32-wasip1` target:
```
rustup target add wasm32-wasip1
```
Install `wasm-tools`:
```
cargo install wasm-tools
```
Install [`cargo-component`](https://github.com/bytecodealliance/cargo-component):
```
cargo install wasm-tools
```
Build the `witguest` project:
```
cd witguest
cargo component build
```

350
common-api/Cargo.lock generated Normal file
View File

@ -0,0 +1,350 @@
# 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 = "api-derive"
version = "0.1.0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "bitflags"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
[[package]]
name = "bytemuck"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15"
[[package]]
name = "common-api"
version = "0.1.0"
dependencies = [
"bytemuck",
"thiserror",
"wit-bindgen",
]
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "hashbrown"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "id-arena"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005"
[[package]]
name = "indexmap"
version = "2.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
dependencies = [
"equivalent",
"hashbrown",
"serde",
]
[[package]]
name = "itoa"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "leb128"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67"
[[package]]
name = "log"
version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]]
name = "proc-macro2"
version = "1.0.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
dependencies = [
"proc-macro2",
]
[[package]]
name = "ryu"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
[[package]]
name = "semver"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca"
[[package]]
name = "serde"
version = "1.0.198"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.198"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.116"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "smallvec"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "spdx"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29ef1a0fa1e39ac22972c8db23ff89aea700ab96aa87114e1fb55937a631a0c9"
dependencies = [
"smallvec",
]
[[package]]
name = "syn"
version = "2.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-segmentation"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
[[package]]
name = "unicode-xid"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "wasm-encoder"
version = "0.202.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfd106365a7f5f7aa3c1916a98cbb3ad477f5ff96ddb130285a91c6e7429e67a"
dependencies = [
"leb128",
]
[[package]]
name = "wasm-metadata"
version = "0.202.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "094aea3cb90e09f16ee25a4c0e324b3e8c934e7fd838bfa039aef5352f44a917"
dependencies = [
"anyhow",
"indexmap",
"serde",
"serde_derive",
"serde_json",
"spdx",
"wasm-encoder",
"wasmparser",
]
[[package]]
name = "wasmparser"
version = "0.202.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6998515d3cf3f8b980ef7c11b29a9b1017d4cf86b99ae93b546992df9931413"
dependencies = [
"bitflags",
"indexmap",
"semver",
]
[[package]]
name = "wit-bindgen"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fb4e7653763780be47e38f479e9aa83c768aa6a3b2ed086dc2826fdbbb7e7f5"
dependencies = [
"wit-bindgen-rt",
"wit-bindgen-rust-macro",
]
[[package]]
name = "wit-bindgen-core"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b67e11c950041849a10828c7600ea62a4077c01e8af72e8593253575428f91b"
dependencies = [
"anyhow",
"wit-parser",
]
[[package]]
name = "wit-bindgen-rt"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b0780cf7046630ed70f689a098cd8d56c5c3b22f2a7379bbdb088879963ff96"
dependencies = [
"bitflags",
]
[[package]]
name = "wit-bindgen-rust"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30acbe8fb708c3a830a33c4cb705df82659bf831b492ec6ca1a17a369cfeeafb"
dependencies = [
"anyhow",
"heck",
"indexmap",
"wasm-metadata",
"wit-bindgen-core",
"wit-component",
]
[[package]]
name = "wit-bindgen-rust-macro"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b1b06eae85feaecdf9f2854f7cac124e00d5a6e5014bfb02eb1ecdeb5f265b9"
dependencies = [
"anyhow",
"proc-macro2",
"quote",
"syn",
"wit-bindgen-core",
"wit-bindgen-rust",
]
[[package]]
name = "wit-component"
version = "0.202.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c836b1fd9932de0431c1758d8be08212071b6bba0151f7bac826dbc4312a2a9"
dependencies = [
"anyhow",
"bitflags",
"indexmap",
"log",
"serde",
"serde_derive",
"serde_json",
"wasm-encoder",
"wasm-metadata",
"wasmparser",
"wit-parser",
]
[[package]]
name = "wit-parser"
version = "0.202.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "744237b488352f4f27bca05a10acb79474415951c450e52ebd0da784c1df2bcc"
dependencies = [
"anyhow",
"id-arena",
"indexmap",
"log",
"semver",
"serde",
"serde_derive",
"serde_json",
"unicode-xid",
"wasmparser",
]

5
common-api/Cargo.toml Executable file → Normal file
View File

@ -6,9 +6,10 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
bytemuck = "1.15.0" bytemuck = { version = "1.15.0", features = ["derive"] }
thiserror = "1.0.58" thiserror = "1.0.58"
#bytemuck = "1.15.0" #bytemuck = "1.15.0"
#wasmtime = "19.0.2" #wasmtime = "19.0.2"
wit-bindgen = "0.24.0" wit-bindgen = "0.28.0"
#wit-bindgen = { version = "0.24.0", default-features = false, features = ["realloc"] } #wit-bindgen = { version = "0.24.0", default-features = false, features = ["realloc"] }
api-derive = { path = "./api-derive" }

View File

@ -0,0 +1,14 @@
[package]
name = "api-derive"
version = "0.1.0"
edition = "2021"
[lib]
proc-macro = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
proc-macro2 = "1.0.81"
quote = "1.0.36"
syn = "2.0.60"

View File

@ -0,0 +1,101 @@
use quote::quote;
use syn::{parse_macro_input, Token};
enum ComponentSerializationMethod {
Bytemuck
}
struct HostComponentDeriveInput {
pub type_path: syn::Path,
host_type_name: Option<String>,
serialize_method: Option<ComponentSerializationMethod>,
}
impl syn::parse::Parse for HostComponentDeriveInput {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let type_path: syn::Path = input.parse()?;
let mut s = Self {
type_path,
host_type_name: None,
serialize_method: None,
};
while input.peek(Token![,]) {
let _: Token![,] = input.parse()?;
//println!("Peeked a , ({:?})", input);
if input.peek(syn::Ident) {
let ident: syn::Ident = input.parse()?;
let ident_str = ident.to_string();
match ident_str.as_str() {
"host_type" => {
let _eq: syn::Token![=] = input.parse()?;
let ident: syn::LitStr = input.parse()?;
s.host_type_name = Some(ident.value());
},
"serialize" => {
let _eq: syn::Token![=] = input.parse()?;
let ident: syn::Ident = input.parse()?;
let ident_str = ident.to_string().to_lowercase();
match ident_str.as_str() {
"bytemuck" => {
s.serialize_method = Some(ComponentSerializationMethod::Bytemuck);
},
_ => return Err(syn::Error::new(ident.span(),
format!("unknown component serialization method `{}`",
ident_str))),
}
},
_ => return Err(syn::Error::new(ident.span(),
format!("unknown macro usage `{}`", ident_str))),
}
}
}
Ok(s)
}
}
#[proc_macro]
pub fn bytemuck_component_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input = parse_macro_input!(input as HostComponentDeriveInput);
let type_path = input.type_path;
let host_type_name = input.host_type_name.unwrap_or(type_path.segments.last().unwrap().ident.to_string());
let ser_method = match input.serialize_method.unwrap_or(ComponentSerializationMethod::Bytemuck) {
ComponentSerializationMethod::Bytemuck => quote!(Bytemuck),
};
quote! {
impl common_api::Component for #type_path {
const SERIALIZATION: common_api::ComponentSerializationMethod = common_api::ComponentSerializationMethod::#ser_method;
fn host_name() -> Option<&'static str> {
Some(#host_type_name)
}
fn component_info() -> common_api::bindings::lyra::api::ecs::ComponentInfo {
common_api::bindings::lyra::api::ecs::ComponentInfo::of::<Self>()
}
fn to_bytes(&self) -> Result<Vec<u8>, common_api::ComponentSerializationError> {
Ok(common_api::bytemuck::bytes_of(self).to_vec())
}
fn to_bytes_into(&self, target: &mut Vec<u8>) -> Result<(), common_api::ComponentSerializationError> {
let bytes = self.to_bytes()?;
target.extend(bytes.into_iter());
Ok(())
}
fn from_bytes(bytes: &[u8]) -> Result<Self, common_api::ComponentSerializationError> {
common_api::bytemuck::try_from_bytes::<Self>(&bytes)
.map_err(|e| common_api::ComponentSerializationError::Bytemuck(e))
.cloned()
}
}
}.into()
}

View File

@ -6,6 +6,7 @@ impl ComponentInfo {
pub fn of<C: Component>() -> Self { pub fn of<C: Component>() -> Self {
let layout = Layout::new::<C>(); let layout = Layout::new::<C>();
Self { Self {
host_name: C::host_name().map(|s| s.to_string()),
size: layout.size() as _, size: layout.size() as _,
alignment: layout.align() as _, alignment: layout.align() as _,
type_id: WasmTypeId::of::<C>(), type_id: WasmTypeId::of::<C>(),
@ -33,6 +34,7 @@ pub enum ComponentSerializationError {
pub trait Component: Sized + 'static { pub trait Component: Sized + 'static {
const SERIALIZATION: ComponentSerializationMethod; const SERIALIZATION: ComponentSerializationMethod;
fn host_name() -> Option<&'static str>;
fn component_info() -> ComponentInfo; fn component_info() -> ComponentInfo;
fn to_bytes(&self) -> Result<Vec<u8>, ComponentSerializationError>; fn to_bytes(&self) -> Result<Vec<u8>, ComponentSerializationError>;
fn to_bytes_into(&self, target: &mut Vec<u8>) -> Result<(), ComponentSerializationError>; fn to_bytes_into(&self, target: &mut Vec<u8>) -> Result<(), ComponentSerializationError>;
@ -40,12 +42,16 @@ pub trait Component: Sized + 'static {
fn from_bytes(bytes: &[u8]) -> Result<Self, ComponentSerializationError>; fn from_bytes(bytes: &[u8]) -> Result<Self, ComponentSerializationError>;
} }
#[macro_export] /* #[macro_export]
macro_rules! bytemuck_component_impl { macro_rules! bytemuck_component_impl {
($type:ident) => { ($type:ident) => {
impl common_api::Component for $type { impl common_api::Component for $type {
const SERIALIZATION: common_api::ComponentSerializationMethod = common_api::ComponentSerializationMethod::Bytemuck; const SERIALIZATION: common_api::ComponentSerializationMethod = common_api::ComponentSerializationMethod::Bytemuck;
fn host_name() -> Option<&'static str> {
Some(stringify!($type))
}
fn component_info() -> common_api::bindings::lyra::api::ecs::ComponentInfo { fn component_info() -> common_api::bindings::lyra::api::ecs::ComponentInfo {
common_api::bindings::lyra::api::ecs::ComponentInfo::of::<$type>() common_api::bindings::lyra::api::ecs::ComponentInfo::of::<$type>()
} }
@ -67,4 +73,4 @@ macro_rules! bytemuck_component_impl {
} }
} }
}; };
} } */

View File

@ -8,6 +8,10 @@ pub use component::*;
mod bundle; mod bundle;
pub use bundle::*; pub use bundle::*;
pub mod math;
pub use api_derive as macros;
pub mod bindings { pub mod bindings {
wit_bindgen::generate!({ wit_bindgen::generate!({
world: "api", world: "api",

40
common-api/src/math.rs Normal file
View File

@ -0,0 +1,40 @@
use api_derive::bytemuck_component_impl;
use crate as common_api;
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable)]
pub struct Vec3 {
x: f32,
y: f32,
z: f32,
}
impl Vec3 {
pub fn new(x: f32, y: f32, z: f32) -> Self {
Self {
x, y, z
}
}
}
bytemuck_component_impl!(Vec3);
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable)]
pub struct Vec4 {
x: f32,
y: f32,
z: f32,
w: f32,
}
impl Vec4 {
pub fn new(x: f32, y: f32, z: f32, w: f32) -> Self {
Self {
x, y, z, w
}
}
}
bytemuck_component_impl!(Vec4);

View File

@ -16,6 +16,7 @@ interface ecs {
} }
record component-info { record component-info {
host-name: option<string>,
/// The size of the component in memory. /// The size of the component in memory.
size: u64, size: u64,
/// The alignment of the component in memory. /// The alignment of the component in memory.
@ -24,7 +25,7 @@ interface ecs {
/// ///
/// This must be unique between component types since its used to identify the components /// This must be unique between component types since its used to identify the components
/// in spawning and querying. /// in spawning and querying.
type-id: wasm-type-id, // a u128 type-id: wasm-type-id,
} }
resource ecs-dynamic-view { resource ecs-dynamic-view {

View File

@ -64,7 +64,7 @@ wasmtime::component::bindgen!({
async: true, async: true,
with: { with: {
"lyra:api": lyra::api, //"lyra:api": lyra::api,
} }
}); });
@ -110,9 +110,8 @@ impl WasiView for Imports {
#[async_trait] #[async_trait]
impl ExampleImports for Imports { impl ExampleImports for Imports {
async fn host_print(&mut self, msg: String) -> wasmtime::Result<()> { async fn host_print(&mut self, msg: String) {
println!("{}", msg); println!("{}", msg);
Ok(())
} }
} }
@ -124,13 +123,13 @@ pub enum WasmError {
#[async_trait] #[async_trait]
impl wasm_ecs::HostEcsWorld for Imports { impl wasm_ecs::HostEcsWorld for Imports {
async fn new(&mut self) -> wasmtime::Result<WasmResource<wasm_ecs::EcsWorld>> { async fn new(&mut self) -> WasmResource<wasm_ecs::EcsWorld> {
let entry = WorldEntry { let entry = WorldEntry {
world: lyra_ecs::World::new(), world: lyra_ecs::World::new(),
views: Slab::new(), views: Slab::new(),
}; };
let world = self.world_slab.insert(entry); let world = self.world_slab.insert(entry);
Ok(WasmResource::new_own(world as _)) WasmResource::new_own(world as _)
} }
async fn spawn( async fn spawn(
@ -138,11 +137,12 @@ impl wasm_ecs::HostEcsWorld for Imports {
this: WasmResource<wasm_ecs::EcsWorld>, this: WasmResource<wasm_ecs::EcsWorld>,
mut components: Vec<u8>, mut components: Vec<u8>,
infos: Vec<wasm_ecs::ComponentInfo>, infos: Vec<wasm_ecs::ComponentInfo>,
) -> wasmtime::Result<wasm_ecs::Entity> { ) -> wasm_ecs::Entity {
let world_entry = self let world_entry = self
.world_slab .world_slab
.get_mut(this.rep() as _) .get_mut(this.rep() as _)
.ok_or(WasmError::InvalidResourceHandle("EcsWorld"))?; .ok_or(WasmError::InvalidResourceHandle("EcsWorld"))
.unwrap();
let world = &mut world_entry.world; let world = &mut world_entry.world;
// add the components in the tightly packed `components` buffer into the dynamic bundle // add the components in the tightly packed `components` buffer into the dynamic bundle
@ -152,20 +152,20 @@ impl wasm_ecs::HostEcsWorld for Imports {
// SAFETY: The components are tightly packed, adding the offset to the pointer will // SAFETY: The components are tightly packed, adding the offset to the pointer will
// get the next component in the buffer. // get the next component in the buffer.
let data_ptr = unsafe { NonNull::new_unchecked(components.as_mut_ptr().add(offset)) }; let data_ptr = unsafe { NonNull::new_unchecked(components.as_mut_ptr().add(offset)) };
bundle.push_unknown(data_ptr, info.into()); bundle.push_unknown(data_ptr, info.clone().into());
offset += info.size as usize; offset += info.size as usize;
} }
let en = world.spawn(bundle); let en = world.spawn(bundle);
Ok(en.into()) en.into()
} }
async fn view( async fn view(
&mut self, &mut self,
this: wasmtime::component::Resource<wasm_ecs::EcsWorld>, this: wasmtime::component::Resource<wasm_ecs::EcsWorld>,
infos: Vec<wasm_ecs::ComponentInfo>, infos: Vec<wasm_ecs::ComponentInfo>,
) -> wasmtime::Result<wasmtime::component::Resource<wasm_ecs::EcsDynamicView>> { ) -> wasmtime::component::Resource<wasm_ecs::EcsDynamicView> {
<Self as wasm_ecs::HostEcsDynamicView>::new(self, this, infos).await <Self as wasm_ecs::HostEcsDynamicView>::new(self, this, infos).await
} }
@ -195,7 +195,7 @@ impl wasm_ecs::HostEcsDynamicView for Imports {
&mut self, &mut self,
world: WasmResource<wasm_ecs::EcsWorld>, world: WasmResource<wasm_ecs::EcsWorld>,
infos: Vec<wasm_ecs::ComponentInfo>, infos: Vec<wasm_ecs::ComponentInfo>,
) -> wasmtime::Result<wasmtime::component::Resource<wasm_ecs::EcsDynamicView>> { ) -> wasmtime::component::Resource<wasm_ecs::EcsDynamicView> {
// Create a dynamic view for querying for the components // Create a dynamic view for querying for the components
let mut view = DynamicViewState::new(); let mut view = DynamicViewState::new();
for info in infos.clone() { for info in infos.clone() {
@ -213,16 +213,17 @@ impl wasm_ecs::HostEcsDynamicView for Imports {
let world_entry = self let world_entry = self
.world_slab .world_slab
.get_mut(world.rep() as _) .get_mut(world.rep() as _)
.ok_or(WasmError::InvalidResourceHandle("EcsWorld"))?; .ok_or(WasmError::InvalidResourceHandle("EcsWorld"))
.unwrap();
world_entry.views.insert(view_index); world_entry.views.insert(view_index);
Ok(WasmResource::new_own(view_index as _)) WasmResource::new_own(view_index as _)
} }
async fn next( async fn next(
&mut self, &mut self,
view: WasmResource<wasm_ecs::EcsDynamicView>, view: WasmResource<wasm_ecs::EcsDynamicView>,
) -> wasmtime::Result<Option<Vec<u8>>> { ) -> Option<Vec<u8>> {
let view_entry = self.world_views_slab.get_mut(view.rep() as _).unwrap(); let view_entry = self.world_views_slab.get_mut(view.rep() as _).unwrap();
let world_entry = self.world_slab.get(view_entry.world_index).unwrap(); let world_entry = self.world_slab.get(view_entry.world_index).unwrap();
let view = &mut view_entry.view; let view = &mut view_entry.view;
@ -253,9 +254,9 @@ impl wasm_ecs::HostEcsDynamicView for Imports {
offset += comp_size; offset += comp_size;
} }
Ok(Some(row_buf)) Some(row_buf)
} else { } else {
Ok(None) None
} }
} }
@ -290,7 +291,10 @@ async fn main() -> wasmtime::Result<()> {
// Configure the linker // Configure the linker
let mut linker = wasmtime::component::Linker::new(&engine); let mut linker = wasmtime::component::Linker::new(&engine);
wasmtime_wasi::bindings::Imports::add_to_linker(&mut linker, |s| s)?;
//wasmtime_wasi::preview0::add_to_linker_sync(&mut linker, |s| s)?;
//wasmtime_wasi::bindings::Imports::add_to_linker(&mut linker, |s| s)?;
wasmtime_wasi::add_to_linker_async(&mut linker)?;
Example::add_to_linker(&mut linker, |s| s)?; Example::add_to_linker(&mut linker, |s| s)?;
Api::add_to_linker(&mut linker, |s| s)?; Api::add_to_linker(&mut linker, |s| s)?;
@ -310,12 +314,12 @@ async fn main() -> wasmtime::Result<()> {
); );
// Load the component from disk // Load the component from disk
let bytes = std::fs::read("target/wasm32-wasi/debug/witguest.wasm")?; let bytes = std::fs::read("target/wasm32-wasip1/debug/witguest.wasm")?;
let component = wasmtime::component::Component::new(&engine, bytes)?; let component = wasmtime::component::Component::new(&engine, bytes)?;
// Instantiate the component // Instantiate the component
println!("creating example"); println!("creating example");
let (example, _instance) = Example::instantiate_async(&mut store, &component, &linker).await?; let example = Example::instantiate_async(&mut store, &component, &linker).await?;
example.call_on_init(&mut store).await?.unwrap(); example.call_on_init(&mut store).await?.unwrap();
println!("Guest is done"); println!("Guest is done");

View File

@ -6,10 +6,10 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
wit-bindgen = { version = "0.24.0", default-features = false, features = ["realloc"] } #wit-bindgen = { version = "0.28.0", default-features = false, features = ["realloc"] }
wit-bindgen-rt = { version = "0.28.0", features = ["bitflags"] }
common-api = { path = "../common-api" } common-api = { path = "../common-api" }
bytemuck = { version = "1.15.0", features = ["derive"] } bytemuck = { version = "1.15.0", features = ["derive"] }
#bytemuck = { version = "1.15.0", features = ["derive"] }
[lib] [lib]
crate-type = ["cdylib"] crate-type = ["cdylib"]

View File

@ -1,81 +1,118 @@
// Generated by `wit-bindgen` 0.18.0. DO NOT EDIT! // Generated by `wit-bindgen` 0.25.0. DO NOT EDIT!
// Options used:
#[allow(unused_unsafe, clippy::all)] #[allow(unused_unsafe, clippy::all)]
pub fn host_print(msg: &str,){ pub fn host_print(msg: &str) {
#[allow(unused_imports)]
use wit_bindgen::rt::{alloc, vec::Vec, string::String};
unsafe { unsafe {
let vec0 = msg; let vec0 = msg;
let ptr0 = vec0.as_ptr() as i32; let ptr0 = vec0.as_ptr().cast::<u8>();
let len0 = vec0.len() as i32; let len0 = vec0.len();
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
#[link(wasm_import_module = "$root")] #[link(wasm_import_module = "$root")]
extern "C" { extern "C" {
#[link_name = "host-print"] #[link_name = "host-print"]
fn wit_import(_: i32, _: i32, ); fn wit_import(_: *mut u8, _: usize);
} }
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
fn wit_import(_: i32, _: i32, ){ unreachable!() } fn wit_import(_: *mut u8, _: usize) {
wit_import(ptr0, len0); unreachable!()
}
wit_import(ptr0.cast_mut(), len0);
} }
} }
const _: () = { #[doc(hidden)]
#[allow(non_snake_case)]
#[doc(hidden)] pub unsafe fn _export_on_init_cabi<T: Guest>() -> i32 {
#[export_name = "on-init"] #[cfg(target_arch = "wasm32")]
#[allow(non_snake_case)] _rt::run_ctors_once();
unsafe extern "C" fn __export_on_init() -> i32 { let result0 = T::on_init();
#[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>::on_init();
let result1 = match result0 { let result1 = match result0 {
Ok(_) => { 0i32 }, Ok(_) => 0i32,
Err(_) => { 1i32 }, Err(_) => 1i32,
};result1 };
} result1
};
use super::Component as _GuestImpl;
pub trait Guest {
fn on_init() -> Result<(),()>;
} }
pub mod component { pub trait Guest {
pub mod witguest { fn on_init() -> Result<(), ()>;
}
#[doc(hidden)]
#[allow(clippy::all)] macro_rules! __export_world_example_cabi{
($ty:ident with_types_in $($path_to_types:tt)*) => (const _: () = {
#[export_name = "on-init"]
unsafe extern "C" fn export_on_init() -> i32 {
$($path_to_types)*::_export_on_init_cabi::<$ty>()
}
};);
}
#[doc(hidden)]
pub(crate) use __export_world_example_cabi;
#[allow(dead_code)]
pub mod component {
#[allow(dead_code)]
pub mod witguest {
#[allow(dead_code, clippy::all)]
pub mod math { pub mod math {
#[used] #[used]
#[doc(hidden)] #[doc(hidden)]
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
static __FORCE_SECTION_REF: fn() = super::super::super::__link_section; static __FORCE_SECTION_REF: fn() =
super::super::super::__link_custom_section_describing_imports;
} }
}
}
mod _rt {
#[cfg(target_arch = "wasm32")]
pub fn run_ctors_once() {
wit_bindgen_rt::run_ctors_once();
} }
} }
#[cfg(target_arch = "wasm32")] /// Generates `#[no_mangle]` functions to export the specified type as the
#[link_section = "component-type:example"] /// root implementation of all generated traits.
///
/// For more information see the documentation of `wit_bindgen::generate!`.
///
/// ```rust
/// # macro_rules! export{ ($($t:tt)*) => (); }
/// # trait Guest {}
/// struct MyType;
///
/// impl Guest for MyType {
/// // ...
/// }
///
/// export!(MyType);
/// ```
#[allow(unused_macros)]
#[doc(hidden)] #[doc(hidden)]
pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 261] = [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, 136, 1, 1, 65, 2, 1, 65, 7, 1, 66, 2, 1, 114, 3, 1, 120, 118, 1, 121, 118, 1, 122, 118, 4, 0, 4, 118, 101, 99, 51, 3, 0, 0, 3, 1, 23, 99, 111, 109, 112, 111, 110, 101, 110, 116, 58, 119, 105, 116, 103, 117, 101, 115, 116, 47, 109, 97, 116, 104, 5, 0, 1, 64, 1, 3, 109, 115, 103, 115, 1, 0, 3, 0, 10, 104, 111, 115, 116, 45, 112, 114, 105, 110, 116, 1, 1, 1, 106, 0, 0, 1, 64, 0, 0, 2, 4, 0, 7, 111, 110, 45, 105, 110, 105, 116, 1, 3, 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];
macro_rules! __export_example_impl {
($ty:ident) => (self::export!($ty with_types_in self););
($ty:ident with_types_in $($path_to_types_root:tt)*) => (
$($path_to_types_root)*::__export_world_example_cabi!($ty with_types_in $($path_to_types_root)*);
)
}
#[doc(inline)]
pub(crate) use __export_example_impl as export;
#[cfg(target_arch = "wasm32")]
#[link_section = "component-type:wit-bindgen:0.25.0:example:encoded world"]
#[doc(hidden)]
pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 262] = *b"\
\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\x88\x01\x01A\x02\x01\
A\x07\x01B\x02\x01r\x03\x01xv\x01yv\x01zv\x04\0\x04vec3\x03\0\0\x03\x01\x17compo\
nent:witguest/math\x05\0\x01@\x01\x03msgs\x01\0\x03\0\x0ahost-print\x01\x01\x01j\
\0\0\x01@\0\0\x02\x04\0\x07on-init\x01\x03\x04\x01\x1acomponent:witguest/example\
\x04\0\x0b\x0d\x01\0\x07example\x03\0\0\0G\x09producers\x01\x0cprocessed-by\x02\x0d\
wit-component\x070.208.1\x10wit-bindgen-rust\x060.25.0";
#[inline(never)] #[inline(never)]
#[doc(hidden)] #[doc(hidden)]
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
pub fn __link_section() {} pub fn __link_custom_section_describing_imports() {
wit_bindgen_rt::maybe_link_cabi_realloc();
}

View File

@ -2,44 +2,7 @@
mod bindings; mod bindings;
use bindings::Guest; use bindings::Guest;
use common_api::{bytemuck_component_impl, World}; use common_api::{World, math::{Vec3, Vec4}};
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable)]
struct Vec3 {
x: f32,
y: f32,
z: f32,
}
impl Vec3 {
pub fn new(x: f32, y: f32, z: f32) -> Self {
Self {
x, y, z
}
}
}
bytemuck_component_impl!(Vec3);
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable)]
struct Vec4 {
x: f32,
y: f32,
z: f32,
w: f32,
}
impl Vec4 {
pub fn new(x: f32, y: f32, z: f32, w: f32) -> Self {
Self {
x, y, z, w
}
}
}
bytemuck_component_impl!(Vec4);
struct Component; struct Component;
@ -60,3 +23,5 @@ impl Guest for Component {
Ok(()) Ok(())
} }
} }
bindings::export!(Component with_types_in bindings);