create a 'common-api' crate to make it easier to work with the ecs world
This commit is contained in:
parent
af1ec73fb5
commit
27c8f93611
|
@ -136,6 +136,26 @@ version = "3.16.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
|
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytemuck"
|
||||||
|
version = "1.15.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytemuck_derive"
|
||||||
|
version = "1.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4da9a32f3fed317401fa3c862968128267c3106685286e15d5aaa3d7389c2f60"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
|
@ -241,6 +261,15 @@ version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "common-api"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
"thiserror",
|
||||||
|
"wit-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core-foundation-sys"
|
name = "core-foundation-sys"
|
||||||
version = "0.8.6"
|
version = "0.8.6"
|
||||||
|
@ -370,7 +399,7 @@ dependencies = [
|
||||||
"itertools",
|
"itertools",
|
||||||
"log",
|
"log",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"wasmparser",
|
"wasmparser 0.201.0",
|
||||||
"wasmtime-types",
|
"wasmtime-types",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -690,6 +719,9 @@ name = "heck"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-segmentation",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
|
@ -1297,6 +1329,15 @@ dependencies = [
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spdx"
|
||||||
|
version = "0.10.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "29ef1a0fa1e39ac22972c8db23ff89aea700ab96aa87114e1fb55937a631a0c9"
|
||||||
|
dependencies = [
|
||||||
|
"smallvec",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sptr"
|
name = "sptr"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
|
@ -1499,6 +1540,12 @@ dependencies = [
|
||||||
"tinyvec",
|
"tinyvec",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-segmentation"
|
||||||
|
version = "1.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-width"
|
name = "unicode-width"
|
||||||
version = "0.1.11"
|
version = "0.1.11"
|
||||||
|
@ -1612,6 +1659,22 @@ dependencies = [
|
||||||
"leb128",
|
"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 0.202.0",
|
||||||
|
"wasmparser 0.202.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasmparser"
|
name = "wasmparser"
|
||||||
version = "0.201.0"
|
version = "0.201.0"
|
||||||
|
@ -1623,6 +1686,17 @@ dependencies = [
|
||||||
"semver",
|
"semver",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasmparser"
|
||||||
|
version = "0.202.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d6998515d3cf3f8b980ef7c11b29a9b1017d4cf86b99ae93b546992df9931413"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.5.0",
|
||||||
|
"indexmap",
|
||||||
|
"semver",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasmprinter"
|
name = "wasmprinter"
|
||||||
version = "0.201.0"
|
version = "0.201.0"
|
||||||
|
@ -1630,7 +1704,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a67e66da702706ba08729a78e3c0079085f6bfcb1a62e4799e97bbf728c2c265"
|
checksum = "a67e66da702706ba08729a78e3c0079085f6bfcb1a62e4799e97bbf728c2c265"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"wasmparser",
|
"wasmparser 0.201.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1663,7 +1737,7 @@ dependencies = [
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"target-lexicon",
|
"target-lexicon",
|
||||||
"wasm-encoder 0.201.0",
|
"wasm-encoder 0.201.0",
|
||||||
"wasmparser",
|
"wasmparser 0.201.0",
|
||||||
"wasmtime-cache",
|
"wasmtime-cache",
|
||||||
"wasmtime-component-macro",
|
"wasmtime-component-macro",
|
||||||
"wasmtime-component-util",
|
"wasmtime-component-util",
|
||||||
|
@ -1720,7 +1794,7 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
"wasmtime-component-util",
|
"wasmtime-component-util",
|
||||||
"wasmtime-wit-bindgen",
|
"wasmtime-wit-bindgen",
|
||||||
"wit-parser",
|
"wit-parser 0.201.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1748,7 +1822,7 @@ dependencies = [
|
||||||
"object",
|
"object",
|
||||||
"target-lexicon",
|
"target-lexicon",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"wasmparser",
|
"wasmparser 0.201.0",
|
||||||
"wasmtime-cranelift-shared",
|
"wasmtime-cranelift-shared",
|
||||||
"wasmtime-environ",
|
"wasmtime-environ",
|
||||||
"wasmtime-versioned-export-macros",
|
"wasmtime-versioned-export-macros",
|
||||||
|
@ -1790,7 +1864,7 @@ dependencies = [
|
||||||
"target-lexicon",
|
"target-lexicon",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"wasm-encoder 0.201.0",
|
"wasm-encoder 0.201.0",
|
||||||
"wasmparser",
|
"wasmparser 0.201.0",
|
||||||
"wasmprinter",
|
"wasmprinter",
|
||||||
"wasmtime-component-util",
|
"wasmtime-component-util",
|
||||||
"wasmtime-types",
|
"wasmtime-types",
|
||||||
|
@ -1880,7 +1954,7 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"wasmparser",
|
"wasmparser 0.201.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1936,7 +2010,7 @@ dependencies = [
|
||||||
"gimli",
|
"gimli",
|
||||||
"object",
|
"object",
|
||||||
"target-lexicon",
|
"target-lexicon",
|
||||||
"wasmparser",
|
"wasmparser 0.201.0",
|
||||||
"wasmtime-cranelift-shared",
|
"wasmtime-cranelift-shared",
|
||||||
"wasmtime-environ",
|
"wasmtime-environ",
|
||||||
"winch-codegen",
|
"winch-codegen",
|
||||||
|
@ -1951,7 +2025,7 @@ dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"heck",
|
"heck",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"wit-parser",
|
"wit-parser 0.201.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2067,7 +2141,7 @@ dependencies = [
|
||||||
"regalloc2",
|
"regalloc2",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"target-lexicon",
|
"target-lexicon",
|
||||||
"wasmparser",
|
"wasmparser 0.201.0",
|
||||||
"wasmtime-environ",
|
"wasmtime-environ",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2238,6 +2312,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9fb4e7653763780be47e38f479e9aa83c768aa6a3b2ed086dc2826fdbbb7e7f5"
|
checksum = "9fb4e7653763780be47e38f479e9aa83c768aa6a3b2ed086dc2826fdbbb7e7f5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"wit-bindgen-rt",
|
"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 0.202.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2249,6 +2334,53 @@ dependencies = [
|
||||||
"bitflags 2.5.0",
|
"bitflags 2.5.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[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 2.5.0",
|
||||||
|
"indexmap",
|
||||||
|
"log",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"serde_json",
|
||||||
|
"wasm-encoder 0.202.0",
|
||||||
|
"wasm-metadata",
|
||||||
|
"wasmparser 0.202.0",
|
||||||
|
"wit-parser 0.202.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wit-parser"
|
name = "wit-parser"
|
||||||
version = "0.201.0"
|
version = "0.201.0"
|
||||||
|
@ -2264,13 +2396,33 @@ dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
"wasmparser",
|
"wasmparser 0.201.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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 0.202.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "witguest"
|
name = "witguest"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
"common-api",
|
||||||
"wit-bindgen",
|
"wit-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2279,6 +2431,7 @@ name = "wittest"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
"common-api",
|
||||||
"lyra-ecs",
|
"lyra-ecs",
|
||||||
"slab",
|
"slab",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
workspace = { members = ["witguest"] }
|
workspace = { members = [ "common-api","witguest"] }
|
||||||
[package]
|
[package]
|
||||||
name = "wittest"
|
name = "wittest"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -14,3 +14,5 @@ wasmtime-wasi = "19.0.2"
|
||||||
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"
|
||||||
|
|
||||||
|
common-api = { path = "./common-api" }
|
|
@ -0,0 +1,14 @@
|
||||||
|
[package]
|
||||||
|
name = "common-api"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
bytemuck = "1.15.0"
|
||||||
|
thiserror = "1.0.58"
|
||||||
|
#bytemuck = "1.15.0"
|
||||||
|
#wasmtime = "19.0.2"
|
||||||
|
wit-bindgen = "0.24.0"
|
||||||
|
#wit-bindgen = { version = "0.24.0", default-features = false, features = ["realloc"] }
|
|
@ -0,0 +1,162 @@
|
||||||
|
/* pub mod bindings {
|
||||||
|
wasmtime::component::bindgen!({
|
||||||
|
world: "example",
|
||||||
|
path: "../witguest/wit/world.wit",
|
||||||
|
//tracing: true,
|
||||||
|
async: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
use bindings::{component::witguest::ecs::EcsWorld, *}; */
|
||||||
|
|
||||||
|
use std::{alloc::Layout, any::TypeId, marker::PhantomData, mem};
|
||||||
|
|
||||||
|
pub use bytemuck;
|
||||||
|
|
||||||
|
wit_bindgen::generate!({
|
||||||
|
world: "api",
|
||||||
|
path: "wit",
|
||||||
|
});
|
||||||
|
|
||||||
|
use lyra::api::ecs::{ComponentInfo, EcsDynamicView, EcsWorld, Entity, WasmTypeId};
|
||||||
|
|
||||||
|
impl WasmTypeId {
|
||||||
|
pub fn of<T: 'static>() -> Self {
|
||||||
|
Self {
|
||||||
|
inner: unsafe { mem::transmute(TypeId::of::<T>()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ComponentInfo {
|
||||||
|
pub fn of<C: Component>() -> Self {
|
||||||
|
let layout = Layout::new::<C>();
|
||||||
|
Self {
|
||||||
|
size: layout.size() as _,
|
||||||
|
alignment: layout.align() as _,
|
||||||
|
type_id: WasmTypeId::of::<C>(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ComponentSerializationMethod {
|
||||||
|
/// Serializes the component into bytes using [`bytemuck::bytes_of`].
|
||||||
|
Bytemuck,
|
||||||
|
/// Serializes the component into bytes using
|
||||||
|
/// [bincode](https://github.com/bincode-org/bincode).
|
||||||
|
Bincode
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
pub enum ComponentSerializationError {
|
||||||
|
#[error("{0}")]
|
||||||
|
Bytemuck(bytemuck::PodCastError),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Component: Sized + 'static {
|
||||||
|
const SERIALIZATION: ComponentSerializationMethod;
|
||||||
|
|
||||||
|
fn component_info() -> ComponentInfo;
|
||||||
|
fn to_bytes(&self) -> Result<Vec<u8>, ComponentSerializationError>;
|
||||||
|
fn to_bytes_into(&self, target: &mut Vec<u8>) -> Result<(), ComponentSerializationError>;
|
||||||
|
|
||||||
|
fn from_bytes(bytes: &[u8]) -> Result<Self, ComponentSerializationError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! bytemuck_component_impl {
|
||||||
|
($type:ident) => {
|
||||||
|
impl common_api::Component for $type {
|
||||||
|
const SERIALIZATION: common_api::ComponentSerializationMethod = common_api::ComponentSerializationMethod::Bytemuck;
|
||||||
|
|
||||||
|
fn component_info() -> common_api::lyra::api::ecs::ComponentInfo {
|
||||||
|
common_api::lyra::api::ecs::ComponentInfo::of::<$type>()
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct ComponentBundle {
|
||||||
|
bundle: Vec<u8>,
|
||||||
|
infos: Vec<ComponentInfo>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ComponentBundle {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push<C: Component>(&mut self, c: C) {
|
||||||
|
let info = C::component_info();
|
||||||
|
self.infos.push(info);
|
||||||
|
|
||||||
|
c.to_bytes_into(&mut self.bundle);
|
||||||
|
/* self.bundle.reserve(info.size as _);
|
||||||
|
self.bundle.extend(comp_bytes.into_iter()); */
|
||||||
|
|
||||||
|
// dont call the destructor on C to avo
|
||||||
|
//mem::forget(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct World {
|
||||||
|
inner: EcsWorld,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl World {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
inner: EcsWorld::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn spawn(&self, components: ComponentBundle) -> Entity {
|
||||||
|
self.inner.spawn(&components.bundle, &components.infos)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn view(&self, components: &[ComponentInfo]) -> View {
|
||||||
|
View::from(self.inner.view(components))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct View {
|
||||||
|
inner: EcsDynamicView,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<EcsDynamicView> for View {
|
||||||
|
fn from(value: EcsDynamicView) -> Self {
|
||||||
|
Self {
|
||||||
|
inner: value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl View {
|
||||||
|
pub fn next<C: Component>(&mut self) -> Option<C> {
|
||||||
|
let row = self.inner.next();
|
||||||
|
|
||||||
|
if let Some(row) = row {
|
||||||
|
Some(C::from_bytes(&row).unwrap())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package lyra:api;
|
||||||
|
|
||||||
|
interface ecs {
|
||||||
|
record entity-id {
|
||||||
|
id: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
record entity {
|
||||||
|
id: entity-id,
|
||||||
|
generation: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
record wasm-type-id {
|
||||||
|
inner: tuple<u64, u64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
record component-info {
|
||||||
|
size: u64,
|
||||||
|
alignment: u64,
|
||||||
|
type-id: wasm-type-id, // a u128
|
||||||
|
}
|
||||||
|
|
||||||
|
resource ecs-dynamic-view {
|
||||||
|
constructor(wrld: borrow<ecs-world>, component-infos: list<component-info>);
|
||||||
|
|
||||||
|
next: func() -> option<list<u8>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
resource ecs-world {
|
||||||
|
constructor();
|
||||||
|
|
||||||
|
// expects components to be tightly packed in the same order of component-infos
|
||||||
|
spawn: func(components: list<u8>, component-infos: list<component-info>) -> entity;
|
||||||
|
view: func(component-infos: list<component-info>) -> ecs-dynamic-view;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package lyra:api;
|
||||||
|
|
||||||
|
world api {
|
||||||
|
import ecs;
|
||||||
|
}
|
|
@ -22,6 +22,7 @@ pkgs.mkShell.override {
|
||||||
rust
|
rust
|
||||||
] ++ (with pkgs; [
|
] ++ (with pkgs; [
|
||||||
cargo-component wasmtime wasm-tools
|
cargo-component wasmtime wasm-tools
|
||||||
|
cargo-expand
|
||||||
]);
|
]);
|
||||||
LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath buildInputs;
|
LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath buildInputs;
|
||||||
}
|
}
|
79
src/main.rs
79
src/main.rs
|
@ -1,11 +1,8 @@
|
||||||
use std::alloc::Layout;
|
use std::alloc::Layout;
|
||||||
use std::any::TypeId;
|
|
||||||
use std::mem;
|
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use component::witguest::ecs::WasmTypeId;
|
use component::witguest::math;
|
||||||
use component::witguest::{ecs as wasm_ecs, math};
|
|
||||||
use ecs::query::dynamic::{DynamicViewState, DynamicViewStateIter, QueryDynamicType};
|
use ecs::query::dynamic::{DynamicViewState, DynamicViewStateIter, QueryDynamicType};
|
||||||
use lyra_ecs::Component;
|
use lyra_ecs::Component;
|
||||||
|
|
||||||
|
@ -13,7 +10,7 @@ use lyra_ecs as ecs;
|
||||||
|
|
||||||
use slab::Slab;
|
use slab::Slab;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use wasmtime_wasi::WasiView;
|
use wasmtime_wasi::{ResourceTable, WasiCtx, WasiCtxBuilder, WasiView};
|
||||||
|
|
||||||
use wasmtime::component::Resource as WasmResource;
|
use wasmtime::component::Resource as WasmResource;
|
||||||
|
|
||||||
|
@ -22,35 +19,18 @@ pub(crate) mod lyra_engine {
|
||||||
pub use lyra_ecs as ecs;
|
pub use lyra_ecs as ecs;
|
||||||
}
|
}
|
||||||
|
|
||||||
wasmtime::component::bindgen!({
|
use lyra::api::ecs as wasm_ecs;
|
||||||
world: "example",
|
|
||||||
path: "witguest/wit/world.wit",
|
|
||||||
//tracing: true,
|
|
||||||
async: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
impl WasmTypeId {
|
impl Into<ecs::DynTypeId> for wasm_ecs::WasmTypeId {
|
||||||
pub fn of<T: 'static>() -> Self {
|
|
||||||
Self {
|
|
||||||
inner: unsafe { mem::transmute(TypeId::of::<T>()) },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Into<ecs::DynTypeId> for WasmTypeId {
|
|
||||||
fn into(self) -> ecs::DynTypeId {
|
fn into(self) -> ecs::DynTypeId {
|
||||||
// SAFETY: the memory layout of (u64, u64) is the same as u128
|
ecs::DynTypeId::Unknown(unsafe { std::mem::transmute(self.inner) })
|
||||||
ecs::DynTypeId::Unknown(unsafe { mem::transmute(self.inner) })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Into<ecs::ComponentInfo> for wasm_ecs::ComponentInfo {
|
impl Into<ecs::ComponentInfo> for wasm_ecs::ComponentInfo {
|
||||||
fn into(self) -> ecs::ComponentInfo {
|
fn into(self) -> ecs::ComponentInfo {
|
||||||
ecs::ComponentInfo::new_unknown(
|
let layout = Layout::from_size_align(self.size as _, self.alignment as _).unwrap();
|
||||||
None,
|
ecs::ComponentInfo::new_unknown(None, self.type_id, layout)
|
||||||
self.type_id,
|
|
||||||
Layout::from_size_align(self.size as _, self.alignment as _).unwrap(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,6 +43,31 @@ impl From<ecs::Entity> for wasm_ecs::Entity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Into<ecs::Entity> for wasm_ecs::Entity {
|
||||||
|
fn into(self) -> ecs::Entity {
|
||||||
|
let mut id = ecs::EntityId(self.id.id);
|
||||||
|
ecs::Entity::new(id, self.generation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wasmtime::component::bindgen!({
|
||||||
|
world: "api",
|
||||||
|
path: "common-api/wit",
|
||||||
|
//tracing: true,
|
||||||
|
async: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
wasmtime::component::bindgen!({
|
||||||
|
world: "example",
|
||||||
|
path: "witguest/wit",
|
||||||
|
//tracing: true,
|
||||||
|
async: true,
|
||||||
|
|
||||||
|
with: {
|
||||||
|
"lyra:api": lyra::api,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Component)]
|
#[derive(Debug, Clone, Copy, PartialEq, Component)]
|
||||||
struct Vec3 {
|
struct Vec3 {
|
||||||
|
@ -88,15 +93,18 @@ unsafe impl Send for DynamicViewEntry {}
|
||||||
struct Imports {
|
struct Imports {
|
||||||
world_slab: Slab<WorldEntry>,
|
world_slab: Slab<WorldEntry>,
|
||||||
world_views_slab: Slab<DynamicViewEntry>,
|
world_views_slab: Slab<DynamicViewEntry>,
|
||||||
|
|
||||||
|
ctx: WasiCtx,
|
||||||
|
table: ResourceTable,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WasiView for Imports {
|
impl WasiView for Imports {
|
||||||
fn table(&mut self) -> &mut wasmtime_wasi::ResourceTable {
|
fn table(&mut self) -> &mut wasmtime_wasi::ResourceTable {
|
||||||
todo!()
|
&mut self.table
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ctx(&mut self) -> &mut wasmtime_wasi::WasiCtx {
|
fn ctx(&mut self) -> &mut wasmtime_wasi::WasiCtx {
|
||||||
todo!()
|
&mut self.ctx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,8 +116,6 @@ impl ExampleImports for Imports {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl math::Host for Imports {}
|
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum WasmError {
|
pub enum WasmError {
|
||||||
#[error("an invalid '{0}' resource handle was used by the guest")]
|
#[error("an invalid '{0}' resource handle was used by the guest")]
|
||||||
|
@ -181,6 +187,8 @@ impl wasm_ecs::HostEcsWorld for Imports {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl math::Host for Imports {}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl wasm_ecs::HostEcsDynamicView for Imports {
|
impl wasm_ecs::HostEcsDynamicView for Imports {
|
||||||
async fn new(
|
async fn new(
|
||||||
|
@ -284,7 +292,10 @@ async fn main() -> wasmtime::Result<()> {
|
||||||
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::bindings::Imports::add_to_linker(&mut linker, |s| s)?;
|
||||||
Example::add_to_linker(&mut linker, |s| s)?;
|
Example::add_to_linker(&mut linker, |s| s)?;
|
||||||
|
Api::add_to_linker(&mut linker, |s| s)?;
|
||||||
|
|
||||||
|
let mut builder = WasiCtxBuilder::new();
|
||||||
|
builder.inherit_stdio();
|
||||||
// memory per instance
|
// memory per instance
|
||||||
let mut store = wasmtime::Store::new(
|
let mut store = wasmtime::Store::new(
|
||||||
&engine,
|
&engine,
|
||||||
|
@ -293,6 +304,8 @@ async fn main() -> wasmtime::Result<()> {
|
||||||
// wants another world for some reason.
|
// wants another world for some reason.
|
||||||
world_slab: Slab::with_capacity(1),
|
world_slab: Slab::with_capacity(1),
|
||||||
world_views_slab: Slab::with_capacity(10),
|
world_views_slab: Slab::with_capacity(10),
|
||||||
|
ctx: builder.build(),
|
||||||
|
table: ResourceTable::new(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -303,8 +316,8 @@ async fn main() -> wasmtime::Result<()> {
|
||||||
// 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, _instance) = Example::instantiate_async(&mut store, &component, &linker).await?;
|
||||||
let result = example.call_on_init(&mut store).await?.unwrap();
|
example.call_on_init(&mut store).await?.unwrap();
|
||||||
println!("Guest returned: {}", result);
|
println!("Guest is done");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,9 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wit-bindgen = { version = "0.24.0", default-features = false, features = ["realloc"] }
|
wit-bindgen = { version = "0.24.0", default-features = false, features = ["realloc"] }
|
||||||
|
common-api = { path = "../common-api" }
|
||||||
|
bytemuck = { version = "1.15.0", features = ["derive"] }
|
||||||
|
#bytemuck = { version = "1.15.0", features = ["derive"] }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
crate-type = ["cdylib"]
|
crate-type = ["cdylib"]
|
||||||
|
@ -15,3 +18,6 @@ crate-type = ["cdylib"]
|
||||||
package = "component:witguest"
|
package = "component:witguest"
|
||||||
|
|
||||||
[package.metadata.component.dependencies]
|
[package.metadata.component.dependencies]
|
||||||
|
|
||||||
|
[package.metadata.component.target.dependencies]
|
||||||
|
#"lyra:api" = { path = "../common-api/wit" }
|
|
@ -45,29 +45,16 @@ const _: () = {
|
||||||
wit_bindgen::rt::run_ctors_once();
|
wit_bindgen::rt::run_ctors_once();
|
||||||
|
|
||||||
let result0 = <_GuestImpl as Guest>::on_init();
|
let result0 = <_GuestImpl as Guest>::on_init();
|
||||||
let ptr1 = _RET_AREA.0.as_mut_ptr() as i32;
|
let result1 = match result0 {
|
||||||
match result0 {
|
Ok(_) => { 0i32 },
|
||||||
Ok(e) => { {
|
Err(_) => { 1i32 },
|
||||||
*((ptr1 + 0) as *mut u8) = (0i32) as u8;
|
};result1
|
||||||
*((ptr1 + 1) as *mut u8) = (wit_bindgen::rt::as_i32(e)) as u8;
|
|
||||||
} },
|
|
||||||
Err(_) => { {
|
|
||||||
*((ptr1 + 0) as *mut u8) = (1i32) as u8;
|
|
||||||
} },
|
|
||||||
};ptr1
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
use super::Component as _GuestImpl;
|
use super::Component as _GuestImpl;
|
||||||
pub trait Guest {
|
pub trait Guest {
|
||||||
fn on_init() -> Result<u8,()>;
|
fn on_init() -> Result<(),()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
|
||||||
use wit_bindgen::rt::{alloc, vec::Vec, string::String};
|
|
||||||
|
|
||||||
#[repr(align(1))]
|
|
||||||
struct _RetArea([u8; 2]);
|
|
||||||
static mut _RET_AREA: _RetArea = _RetArea([0; 2]);
|
|
||||||
pub mod component {
|
pub mod component {
|
||||||
pub mod witguest {
|
pub mod witguest {
|
||||||
|
|
||||||
|
@ -80,301 +67,13 @@ pub mod component {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[allow(clippy::all)]
|
|
||||||
pub mod ecs {
|
|
||||||
#[used]
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
static __FORCE_SECTION_REF: fn() = super::super::super::__link_section;
|
|
||||||
/// use math.{vec3};
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
pub struct EntityId {
|
|
||||||
pub id: u64,
|
|
||||||
}
|
|
||||||
impl ::core::fmt::Debug for EntityId {
|
|
||||||
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
|
|
||||||
f.debug_struct("EntityId").field("id", &self.id).finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
pub struct Entity {
|
|
||||||
pub id: EntityId,
|
|
||||||
pub generation: u64,
|
|
||||||
}
|
|
||||||
impl ::core::fmt::Debug for Entity {
|
|
||||||
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
|
|
||||||
f.debug_struct("Entity").field("id", &self.id).field("generation", &self.generation).finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
pub struct WasmTypeId {
|
|
||||||
pub inner: (u64,u64,),
|
|
||||||
}
|
|
||||||
impl ::core::fmt::Debug for WasmTypeId {
|
|
||||||
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
|
|
||||||
f.debug_struct("WasmTypeId").field("inner", &self.inner).finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
pub struct ComponentInfo {
|
|
||||||
pub size: u64,
|
|
||||||
pub alignment: u64,
|
|
||||||
pub type_id: WasmTypeId,
|
|
||||||
}
|
|
||||||
impl ::core::fmt::Debug for ComponentInfo {
|
|
||||||
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
|
|
||||||
f.debug_struct("ComponentInfo").field("size", &self.size).field("alignment", &self.alignment).field("type-id", &self.type_id).finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
#[repr(transparent)]
|
|
||||||
pub struct EcsDynamicView{
|
|
||||||
handle: wit_bindgen::rt::Resource<EcsDynamicView>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EcsDynamicView{
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub unsafe fn from_handle(handle: u32) -> Self {
|
|
||||||
Self {
|
|
||||||
handle: wit_bindgen::rt::Resource::from_handle(handle),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub fn handle(&self) -> u32 {
|
|
||||||
wit_bindgen::rt::Resource::handle(&self.handle)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
unsafe impl wit_bindgen::rt::WasmResource for EcsDynamicView{
|
|
||||||
#[inline]
|
|
||||||
unsafe fn drop(_handle: u32) {
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
unreachable!();
|
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
{
|
|
||||||
#[link(wasm_import_module = "component:witguest/ecs")]
|
|
||||||
extern "C" {
|
|
||||||
#[link_name = "[resource-drop]ecs-dynamic-view"]
|
|
||||||
fn drop(_: u32);
|
|
||||||
}
|
|
||||||
|
|
||||||
drop(_handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
#[repr(transparent)]
|
|
||||||
pub struct EcsWorld{
|
|
||||||
handle: wit_bindgen::rt::Resource<EcsWorld>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EcsWorld{
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub unsafe fn from_handle(handle: u32) -> Self {
|
|
||||||
Self {
|
|
||||||
handle: wit_bindgen::rt::Resource::from_handle(handle),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub fn handle(&self) -> u32 {
|
|
||||||
wit_bindgen::rt::Resource::handle(&self.handle)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
unsafe impl wit_bindgen::rt::WasmResource for EcsWorld{
|
|
||||||
#[inline]
|
|
||||||
unsafe fn drop(_handle: u32) {
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
unreachable!();
|
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
{
|
|
||||||
#[link(wasm_import_module = "component:witguest/ecs")]
|
|
||||||
extern "C" {
|
|
||||||
#[link_name = "[resource-drop]ecs-world"]
|
|
||||||
fn drop(_: u32);
|
|
||||||
}
|
|
||||||
|
|
||||||
drop(_handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EcsDynamicView {
|
|
||||||
#[allow(unused_unsafe, clippy::all)]
|
|
||||||
pub fn new(wrld: &EcsWorld,component_infos: &[ComponentInfo],) -> Self{
|
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
|
||||||
use wit_bindgen::rt::{alloc, vec::Vec, string::String};
|
|
||||||
unsafe {
|
|
||||||
let vec0 = component_infos;
|
|
||||||
let ptr0 = vec0.as_ptr() as i32;
|
|
||||||
let len0 = vec0.len() as i32;
|
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
#[link(wasm_import_module = "component:witguest/ecs")]
|
|
||||||
extern "C" {
|
|
||||||
#[link_name = "[constructor]ecs-dynamic-view"]
|
|
||||||
fn wit_import(_: i32, _: i32, _: i32, ) -> i32;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
fn wit_import(_: i32, _: i32, _: i32, ) -> i32{ unreachable!() }
|
|
||||||
let ret = wit_import((wrld).handle() as i32, ptr0, len0);
|
|
||||||
EcsDynamicView::from_handle(ret as u32)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl EcsDynamicView {
|
|
||||||
#[allow(unused_unsafe, clippy::all)]
|
|
||||||
pub fn next(&self,) -> Option<wit_bindgen::rt::vec::Vec::<u8>>{
|
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
|
||||||
use wit_bindgen::rt::{alloc, vec::Vec, string::String};
|
|
||||||
unsafe {
|
|
||||||
|
|
||||||
#[repr(align(4))]
|
|
||||||
struct RetArea([u8; 12]);
|
|
||||||
let mut ret_area = ::core::mem::MaybeUninit::<RetArea>::uninit();
|
|
||||||
let ptr0 = ret_area.as_mut_ptr() as i32;
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
#[link(wasm_import_module = "component:witguest/ecs")]
|
|
||||||
extern "C" {
|
|
||||||
#[link_name = "[method]ecs-dynamic-view.next"]
|
|
||||||
fn wit_import(_: i32, _: i32, );
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
fn wit_import(_: i32, _: i32, ){ unreachable!() }
|
|
||||||
wit_import((self).handle() as i32, ptr0);
|
|
||||||
let l1 = i32::from(*((ptr0 + 0) as *const u8));
|
|
||||||
match l1 {
|
|
||||||
0 => None,
|
|
||||||
1 => {
|
|
||||||
let e = {
|
|
||||||
let l2 = *((ptr0 + 4) as *const i32);
|
|
||||||
let l3 = *((ptr0 + 8) as *const i32);
|
|
||||||
let len4 = l3 as usize;
|
|
||||||
|
|
||||||
Vec::from_raw_parts(l2 as *mut _, len4, len4)
|
|
||||||
};
|
|
||||||
Some(e)
|
|
||||||
}
|
|
||||||
_ => wit_bindgen::rt::invalid_enum_discriminant(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl EcsWorld {
|
|
||||||
#[allow(unused_unsafe, clippy::all)]
|
|
||||||
pub fn new() -> Self{
|
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
|
||||||
use wit_bindgen::rt::{alloc, vec::Vec, string::String};
|
|
||||||
unsafe {
|
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
#[link(wasm_import_module = "component:witguest/ecs")]
|
|
||||||
extern "C" {
|
|
||||||
#[link_name = "[constructor]ecs-world"]
|
|
||||||
fn wit_import() -> i32;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
fn wit_import() -> i32{ unreachable!() }
|
|
||||||
let ret = wit_import();
|
|
||||||
EcsWorld::from_handle(ret as u32)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl EcsWorld {
|
|
||||||
#[allow(unused_unsafe, clippy::all)]
|
|
||||||
/// expects components to be tightly packed in the same order of component-infos
|
|
||||||
pub fn spawn(&self,components: &[u8],component_infos: &[ComponentInfo],) -> Entity{
|
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
|
||||||
use wit_bindgen::rt::{alloc, vec::Vec, string::String};
|
|
||||||
unsafe {
|
|
||||||
|
|
||||||
#[repr(align(8))]
|
|
||||||
struct RetArea([u8; 16]);
|
|
||||||
let mut ret_area = ::core::mem::MaybeUninit::<RetArea>::uninit();
|
|
||||||
let vec0 = components;
|
|
||||||
let ptr0 = vec0.as_ptr() as i32;
|
|
||||||
let len0 = vec0.len() as i32;
|
|
||||||
let vec1 = component_infos;
|
|
||||||
let ptr1 = vec1.as_ptr() as i32;
|
|
||||||
let len1 = vec1.len() as i32;
|
|
||||||
let ptr2 = ret_area.as_mut_ptr() as i32;
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
#[link(wasm_import_module = "component:witguest/ecs")]
|
|
||||||
extern "C" {
|
|
||||||
#[link_name = "[method]ecs-world.spawn"]
|
|
||||||
fn wit_import(_: i32, _: i32, _: i32, _: i32, _: i32, _: i32, );
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
fn wit_import(_: i32, _: i32, _: i32, _: i32, _: i32, _: i32, ){ unreachable!() }
|
|
||||||
wit_import((self).handle() as i32, ptr0, len0, ptr1, len1, ptr2);
|
|
||||||
let l3 = *((ptr2 + 0) as *const i64);
|
|
||||||
let l4 = *((ptr2 + 8) as *const i64);
|
|
||||||
Entity{
|
|
||||||
id: EntityId{
|
|
||||||
id: l3 as u64,
|
|
||||||
},
|
|
||||||
generation: l4 as u64,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl EcsWorld {
|
|
||||||
#[allow(unused_unsafe, clippy::all)]
|
|
||||||
pub fn view(&self,component_infos: &[ComponentInfo],) -> EcsDynamicView{
|
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
|
||||||
use wit_bindgen::rt::{alloc, vec::Vec, string::String};
|
|
||||||
unsafe {
|
|
||||||
let vec0 = component_infos;
|
|
||||||
let ptr0 = vec0.as_ptr() as i32;
|
|
||||||
let len0 = vec0.len() as i32;
|
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
#[link(wasm_import_module = "component:witguest/ecs")]
|
|
||||||
extern "C" {
|
|
||||||
#[link_name = "[method]ecs-world.view"]
|
|
||||||
fn wit_import(_: i32, _: i32, _: i32, ) -> i32;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
fn wit_import(_: i32, _: i32, _: i32, ) -> i32{ unreachable!() }
|
|
||||||
let ret = wit_import((self).handle() as i32, ptr0, len0);
|
|
||||||
EcsDynamicView::from_handle(ret as u32)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
#[link_section = "component-type:example"]
|
#[link_section = "component-type:example"]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 745] = [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, 236, 4, 1, 65, 2, 1, 65, 9, 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, 66, 28, 1, 114, 1, 2, 105, 100, 119, 4, 0, 9, 101, 110, 116, 105, 116, 121, 45, 105, 100, 3, 0, 0, 1, 114, 2, 2, 105, 100, 1, 10, 103, 101, 110, 101, 114, 97, 116, 105, 111, 110, 119, 4, 0, 6, 101, 110, 116, 105, 116, 121, 3, 0, 2, 1, 111, 2, 119, 119, 1, 114, 1, 5, 105, 110, 110, 101, 114, 4, 4, 0, 12, 119, 97, 115, 109, 45, 116, 121, 112, 101, 45, 105, 100, 3, 0, 5, 1, 114, 3, 4, 115, 105, 122, 101, 119, 9, 97, 108, 105, 103, 110, 109, 101, 110, 116, 119, 7, 116, 121, 112, 101, 45, 105, 100, 6, 4, 0, 14, 99, 111, 109, 112, 111, 110, 101, 110, 116, 45, 105, 110, 102, 111, 3, 0, 7, 4, 0, 16, 101, 99, 115, 45, 100, 121, 110, 97, 109, 105, 99, 45, 118, 105, 101, 119, 3, 1, 4, 0, 9, 101, 99, 115, 45, 119, 111, 114, 108, 100, 3, 1, 1, 104, 10, 1, 112, 8, 1, 105, 9, 1, 64, 2, 4, 119, 114, 108, 100, 11, 15, 99, 111, 109, 112, 111, 110, 101, 110, 116, 45, 105, 110, 102, 111, 115, 12, 0, 13, 4, 0, 29, 91, 99, 111, 110, 115, 116, 114, 117, 99, 116, 111, 114, 93, 101, 99, 115, 45, 100, 121, 110, 97, 109, 105, 99, 45, 118, 105, 101, 119, 1, 14, 1, 104, 9, 1, 112, 125, 1, 107, 16, 1, 64, 1, 4, 115, 101, 108, 102, 15, 0, 17, 4, 0, 29, 91, 109, 101, 116, 104, 111, 100, 93, 101, 99, 115, 45, 100, 121, 110, 97, 109, 105, 99, 45, 118, 105, 101, 119, 46, 110, 101, 120, 116, 1, 18, 1, 105, 10, 1, 64, 0, 0, 19, 4, 0, 22, 91, 99, 111, 110, 115, 116, 114, 117, 99, 116, 111, 114, 93, 101, 99, 115, 45, 119, 111, 114, 108, 100, 1, 20, 1, 64, 3, 4, 115, 101, 108, 102, 11, 10, 99, 111, 109, 112, 111, 110, 101, 110, 116, 115, 16, 15, 99, 111, 109, 112, 111, 110, 101, 110, 116, 45, 105, 110, 102, 111, 115, 12, 0, 3, 4, 0, 23, 91, 109, 101, 116, 104, 111, 100, 93, 101, 99, 115, 45, 119, 111, 114, 108, 100, 46, 115, 112, 97, 119, 110, 1, 21, 1, 64, 2, 4, 115, 101, 108, 102, 11, 15, 99, 111, 109, 112, 111, 110, 101, 110, 116, 45, 105, 110, 102, 111, 115, 12, 0, 13, 4, 0, 22, 91, 109, 101, 116, 104, 111, 100, 93, 101, 99, 115, 45, 119, 111, 114, 108, 100, 46, 118, 105, 101, 119, 1, 22, 3, 1, 22, 99, 111, 109, 112, 111, 110, 101, 110, 116, 58, 119, 105, 116, 103, 117, 101, 115, 116, 47, 101, 99, 115, 5, 1, 1, 64, 1, 3, 109, 115, 103, 115, 1, 0, 3, 0, 10, 104, 111, 115, 116, 45, 112, 114, 105, 110, 116, 1, 2, 1, 106, 1, 125, 0, 1, 64, 0, 0, 3, 4, 0, 7, 111, 110, 45, 105, 110, 105, 116, 1, 4, 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];
|
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];
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
|
|
@ -1,20 +1,14 @@
|
||||||
#[allow(warnings)]
|
#[allow(warnings)]
|
||||||
mod bindings;
|
mod bindings;
|
||||||
|
|
||||||
use bindings::{component::witguest::ecs::{ComponentInfo, EcsWorld, Entity, WasmTypeId}, Guest};
|
use bindings::Guest;
|
||||||
|
//use bindings::{component::witguest::ecs::{ComponentInfo, EcsWorld, Entity, WasmTypeId}, Guest};
|
||||||
|
use common_api::{bytemuck_component_impl, Component as EcsComponent, ComponentBundle, World};
|
||||||
|
|
||||||
use std::{alloc::Layout, any::TypeId, mem};
|
use std::{alloc::Layout, any::TypeId, mem};
|
||||||
|
|
||||||
impl WasmTypeId {
|
|
||||||
pub fn of<T: 'static>() -> Self {
|
|
||||||
Self {
|
|
||||||
inner: unsafe { mem::transmute(TypeId::of::<T>()) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable)]
|
||||||
struct Vec3 {
|
struct Vec3 {
|
||||||
x: f32,
|
x: f32,
|
||||||
y: f32,
|
y: f32,
|
||||||
|
@ -27,45 +21,28 @@ impl Vec3 {
|
||||||
x, y, z
|
x, y, z
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn component_info() -> ComponentInfo {
|
|
||||||
let layout = Layout::new::<Vec3>();
|
|
||||||
ComponentInfo {
|
|
||||||
size: layout.size() as u64,
|
|
||||||
alignment: layout.align() as u64,
|
|
||||||
type_id: WasmTypeId::of::<Vec3>(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bytemuck_component_impl!(Vec3);
|
||||||
|
|
||||||
struct Component;
|
struct Component;
|
||||||
|
|
||||||
impl Guest for Component {
|
impl Guest for Component {
|
||||||
fn on_init() -> Result<u8, ()> {
|
fn on_init() -> Result<(), ()> {
|
||||||
let world = EcsWorld::new();
|
let world = World::new();
|
||||||
spawn_vec3(&world, Vec3::new(7.0, 30.0, 18.0));
|
|
||||||
spawn_vec3(&world, Vec3::new(90.30, 65.0, 83.0));
|
|
||||||
|
|
||||||
bindings::host_print("Spawned entities");
|
let mut bundle = ComponentBundle::new();
|
||||||
|
bundle.push(Vec3::new(7.0, 30.0, 18.0));
|
||||||
|
let en = world.spawn(bundle);
|
||||||
|
|
||||||
let view = world.view(&[Vec3::component_info()]);
|
println!("guest spawned {:?}", en);
|
||||||
while let Some(mut buffer) = view.next() {
|
|
||||||
bindings::host_print(&format!("Retrieved vec3 of {} bytes long", buffer.len()));
|
|
||||||
let fetched_vec = unsafe { std::ptr::read(buffer.as_mut_ptr().cast::<Vec3>()) };
|
let mut view = world.view(&[Vec3::component_info()]);
|
||||||
bindings::host_print(&format!("Retrieved vec3: {:?}", fetched_vec));
|
while let Some(c) = view.next::<Vec3>() {
|
||||||
|
println!("Retrieved vec3: {:?}", c);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(0)
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spawn_vec3(world: &EcsWorld, v: Vec3) -> Entity {
|
|
||||||
let comps = &mut [v,];
|
|
||||||
let info = &[Vec3::component_info()];
|
|
||||||
|
|
||||||
// no fucking clue if this will work, but lets try and it see
|
|
||||||
let comps = comps.as_mut_ptr().cast::<u8>();
|
|
||||||
let comps = unsafe { Vec::from_raw_parts(comps, mem::size_of::<Vec3>(), 1) };
|
|
||||||
|
|
||||||
world.spawn(&comps, info)
|
|
||||||
}
|
|
|
@ -8,48 +8,10 @@ interface math {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ecs {
|
|
||||||
//use math.{vec3};
|
|
||||||
|
|
||||||
record entity-id {
|
|
||||||
id: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
record entity {
|
|
||||||
id: entity-id,
|
|
||||||
generation: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
record wasm-type-id {
|
|
||||||
inner: tuple<u64, u64>,
|
|
||||||
}
|
|
||||||
|
|
||||||
record component-info {
|
|
||||||
size: u64,
|
|
||||||
alignment: u64,
|
|
||||||
type-id: wasm-type-id, // a u128
|
|
||||||
}
|
|
||||||
|
|
||||||
resource ecs-dynamic-view {
|
|
||||||
constructor(wrld: borrow<ecs-world>, component-infos: list<component-info>);
|
|
||||||
|
|
||||||
next: func() -> option<list<u8>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
resource ecs-world {
|
|
||||||
constructor();
|
|
||||||
|
|
||||||
// expects components to be tightly packed in the same order of component-infos
|
|
||||||
spawn: func(components: list<u8>, component-infos: list<component-info>) -> entity;
|
|
||||||
view: func(component-infos: list<component-info>) -> ecs-dynamic-view;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An example world for the component to target.
|
/// An example world for the component to target.
|
||||||
world example {
|
world example {
|
||||||
import math;
|
import math;
|
||||||
import ecs;
|
|
||||||
|
|
||||||
import host-print: func(msg: string);
|
import host-print: func(msg: string);
|
||||||
export on-init: func() -> result<u8>;
|
export on-init: func() -> result;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue