From 5ed8982ad2cb4b348046aa11c527ce6a51f02e0e Mon Sep 17 00:00:00 2001 From: Henry Date: Sat, 2 May 2026 15:40:47 +0200 Subject: feat: add doom example, fix import argument order Signed-off-by: Henry --- .gitignore | 6 + Cargo.lock | 1699 +++++++++++++++++++++++- Cargo.toml | 2 +- crates/tinywasm/src/interpreter/executor.rs | 4 +- crates/tinywasm/src/reference.rs | 13 + crates/tinywasm/tests/host_import_arg_order.rs | 31 + examples/doom/Cargo.toml | 21 + examples/doom/README.md | 19 + examples/doom/build.sh | 55 + examples/doom/guest/tinywasm_puredoom.c | 203 +++ examples/doom/out/.gitkeep | 0 examples/doom/src/main.rs | 202 +++ examples/doom/src/runtime.rs | 348 +++++ 13 files changed, 2565 insertions(+), 38 deletions(-) create mode 100644 crates/tinywasm/tests/host_import_arg_order.rs create mode 100644 examples/doom/Cargo.toml create mode 100644 examples/doom/README.md create mode 100755 examples/doom/build.sh create mode 100644 examples/doom/guest/tinywasm_puredoom.c create mode 100644 examples/doom/out/.gitkeep create mode 100644 examples/doom/src/main.rs create mode 100644 examples/doom/src/runtime.rs diff --git a/.gitignore b/.gitignore index 807cb82..c812a70 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,12 @@ notes.md examples/rust/out/* examples/rust/target examples/rust/Cargo.lock +examples/doom/out/* +!examples/doom/out/.gitkeep +examples/doom/upstream/ +examples/doom/out/runtime/ +*.wad +*.WAD examples/wast/* perf.* flamegraph.svg diff --git a/Cargo.lock b/Cargo.lock index 4a5b589..bdab6e1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,35 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "ab_glyph" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01c0457472c38ea5bd1c3b5ada5e368271cb550be7a4ca4a0b4634e9913f6cc2" +dependencies = [ + "ab_glyph_rasterizer", + "owned_ttf_parser", +] + +[[package]] +name = "ab_glyph_rasterizer" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618" + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "getrandom 0.3.4", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.1.4" @@ -20,6 +49,31 @@ dependencies = [ "cc", ] +[[package]] +name = "android-activity" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f2a1bb052857d5dd49572219344a7332b31b76405648eabac5bc68978251bcd" +dependencies = [ + "android-properties", + "bitflags 2.11.1", + "cc", + "jni", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-sys", + "num_enum", + "thiserror 2.0.18", +] + +[[package]] +name = "android-properties" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" + [[package]] name = "anes" version = "0.1.6" @@ -62,7 +116,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -73,7 +127,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -82,6 +136,24 @@ version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "as-raw-xcb-connection" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" + [[package]] name = "assert_cmd" version = "2.2.1" @@ -97,18 +169,39 @@ dependencies = [ "wait-timeout", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "autocfg" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" +[[package]] +name = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2 0.5.2", +] + [[package]] name = "bstr" version = "1.12.1" @@ -126,6 +219,58 @@ version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" +[[package]] +name = "bytemuck" +version = "1.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + +[[package]] +name = "calloop" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" +dependencies = [ + "bitflags 2.11.1", + "log", + "polling", + "rustix 0.38.44", + "slab", + "thiserror 1.0.69", +] + +[[package]] +name = "calloop-wayland-source" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" +dependencies = [ + "calloop", + "rustix 0.38.44", + "wayland-backend", + "wayland-client", +] + [[package]] name = "cast" version = "0.3.0" @@ -139,6 +284,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" dependencies = [ "find-msvc-tools", + "jobserver", + "libc", "shlex", ] @@ -148,6 +295,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "ciborium" version = "0.2.2" @@ -230,7 +383,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" dependencies = [ - "thiserror", + "thiserror 2.0.18", ] [[package]] @@ -239,6 +392,65 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "core-graphics" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "libc", +] + [[package]] name = "criterion" version = "0.8.2" @@ -304,12 +516,110 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" +[[package]] +name = "ctor" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83cf0d42651b16c6dfe68685716d18480d18a9c39c62d76e8cf3eb6ed5d8bcbf" +dependencies = [ + "dtor", +] + +[[package]] +name = "cursor-icon" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" + [[package]] name = "difflib" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "dispatch2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" +dependencies = [ + "bitflags 2.11.1", + "objc2 0.6.4", +] + +[[package]] +name = "dlib" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab8ecd87370524b461f8557c119c405552c396ed91fc0a8eec68679eab26f94a" +dependencies = [ + "libloading", +] + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "dpi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" + +[[package]] +name = "drm" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80bc8c5c6c2941f70a55c15f8d9f00f9710ebda3ffda98075f996a0e6c92756f" +dependencies = [ + "bitflags 2.11.1", + "bytemuck", + "drm-ffi", + "drm-fourcc", + "libc", + "rustix 0.38.44", +] + +[[package]] +name = "drm-ffi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51a91c9b32ac4e8105dec255e849e0d66e27d7c34d184364fb93e469db08f690" +dependencies = [ + "drm-sys", + "rustix 1.1.4", +] + +[[package]] +name = "drm-fourcc" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aafbcdb8afc29c1a7ee5fbe53b5d62f4565b35a042a662ca9fecd0b54dae6f4" + +[[package]] +name = "drm-sys" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8e1361066d91f5ffccff060a3c3be9c3ecde15be2959c1937595f7a82a9f8" +dependencies = [ + "libc", + "linux-raw-sys 0.9.4", +] + +[[package]] +name = "dtor" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edf234dd1594d6dd434a8fb8cada51ddbbc593e40e4a01556a0b31c62da2775b" + [[package]] name = "either" version = "1.15.0" @@ -354,7 +664,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -394,6 +704,79 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "slab", +] + +[[package]] +name = "gethostname" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" +dependencies = [ + "rustix 1.1.4", + "windows-link", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi 5.3.0", + "wasip2", +] + [[package]] name = "getrandom" version = "0.4.2" @@ -402,7 +785,7 @@ checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if", "libc", - "r-efi", + "r-efi 6.0.0", "wasip2", "wasip3", ] @@ -502,7 +885,7 @@ checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi", "libc", - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -527,40 +910,193 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] -name = "leb128fmt" -version = "0.1.0" +name = "jni" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ + "cfg-if", + "combine", + "jni-macros", + "jni-sys 0.4.1", + "log", + "simd_cesu8", + "thiserror 2.0.18", + "walkdir", + "windows-link", +] [[package]] -name = "libc" -version = "0.2.186" +name = "jni-macros" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn", +] [[package]] -name = "libm" -version = "0.2.16" +name = "jni-sys" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", +] [[package]] -name = "linux-raw-sys" -version = "0.12.1" +name = "jni-sys" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] [[package]] -name = "log" -version = "0.4.29" +name = "jni-sys-macros" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn", +] [[package]] -name = "memchr" -version = "2.8.0" +name = "jobserver" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1840c94c045fbcf8ba2812c95db44499f7c64910a912551aaaa541decebcacf" +dependencies = [ + "cfg-if", + "futures-util", + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "libredox" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" +dependencies = [ + "bitflags 2.11.1", + "libc", + "plain", + "redox_syscall 0.7.4", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "memmap2" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" +dependencies = [ + "libc", +] + +[[package]] +name = "ndk" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +dependencies = [ + "bitflags 2.11.1", + "jni-sys 0.3.1", + "log", + "ndk-sys", + "num_enum", + "raw-window-handle", + "thiserror 1.0.69", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys 0.3.1", +] [[package]] name = "normalize-line-endings" @@ -577,6 +1113,298 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_enum" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "objc-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys", + "objc2-encode", +] + +[[package]] +name = "objc2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.11.1", + "block2", + "libc", + "objc2 0.5.2", + "objc2-core-data", + "objc2-core-image", + "objc2-foundation 0.2.2", + "objc2-quartz-core 0.2.2", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" +dependencies = [ + "bitflags 2.11.1", + "block2", + "objc2 0.5.2", + "objc2-core-location", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-contacts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.11.1", + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags 2.11.1", + "dispatch2", + "objc2 0.6.4", +] + +[[package]] +name = "objc2-core-graphics" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" +dependencies = [ + "bitflags 2.11.1", + "dispatch2", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-io-surface", +] + +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal", +] + +[[package]] +name = "objc2-core-location" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-contacts", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.11.1", + "block2", + "dispatch", + "libc", + "objc2 0.5.2", +] + +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags 2.11.1", + "objc2 0.6.4", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-io-surface" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" +dependencies = [ + "bitflags 2.11.1", + "objc2 0.6.4", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-link-presentation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-app-kit", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.11.1", + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.11.1", + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" +dependencies = [ + "bitflags 2.11.1", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-symbols" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" +dependencies = [ + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" +dependencies = [ + "bitflags 2.11.1", + "block2", + "objc2 0.5.2", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-image", + "objc2-core-location", + "objc2-foundation 0.2.2", + "objc2-link-presentation", + "objc2-quartz-core 0.2.2", + "objc2-symbols", + "objc2-uniform-type-identifiers", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-uniform-type-identifiers" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" +dependencies = [ + "bitflags 2.11.1", + "block2", + "objc2 0.5.2", + "objc2-core-location", + "objc2-foundation 0.2.2", +] + [[package]] name = "once_cell" version = "1.21.4" @@ -595,6 +1423,25 @@ version = "11.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" +[[package]] +name = "orbclient" +version = "0.3.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a570f6bca41d29acb2139229a7c873ec99bc9a313bd10804081d89bfac8ff329" +dependencies = [ + "libc", + "libredox", +] + +[[package]] +name = "owned_ttf_parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36820e9051aca1014ddc75770aab4d68bc1e9e632f0f5627c4086bc216fb583b" +dependencies = [ + "ttf-parser", +] + [[package]] name = "owo-colors" version = "4.3.0" @@ -611,6 +1458,64 @@ dependencies = [ "winapi", ] +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "pin-project" +version = "1.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "pkg-config" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" + +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix 1.1.4", + "windows-sys 0.61.2", +] + [[package]] name = "postcard" version = "1.1.3" @@ -673,6 +1578,15 @@ dependencies = [ "syn", ] +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit", +] + [[package]] name = "proc-macro2" version = "1.0.106" @@ -682,6 +1596,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "quick-xml" +version = "0.39.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "958f21e8e7ceb5a1aa7fa87fab28e7c75976e0bfe7e23ff069e0a260f894067d" +dependencies = [ + "memchr", +] + [[package]] name = "quote" version = "1.0.45" @@ -691,12 +1614,24 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + [[package]] name = "r-efi" version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + [[package]] name = "rayon" version = "1.12.0" @@ -717,6 +1652,33 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.11.1", +] + +[[package]] +name = "redox_syscall" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f450ad9c3b1da563fb6948a8e0fb0fb9269711c9c73d9ea1de5058c79c8d643a" +dependencies = [ + "bitflags 2.11.1", +] + [[package]] name = "regex" version = "1.12.3" @@ -746,19 +1708,47 @@ version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.11.1", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + [[package]] name = "rustix" version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags", + "bitflags 2.11.1", "errno", "libc", - "linux-raw-sys", - "windows-sys", + "linux-raw-sys 0.12.1", + "windows-sys 0.61.2", ] +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + [[package]] name = "same-file" version = "1.0.6" @@ -768,6 +1758,25 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "sctk-adwaita" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec" +dependencies = [ + "ab_glyph", + "log", + "memmap2", + "smithay-client-toolkit", + "tiny-skia", +] + [[package]] name = "semver" version = "1.0.28" @@ -821,7 +1830,107 @@ dependencies = [ name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "simd_cesu8" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version", + "simdutf8", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "smithay-client-toolkit" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" +dependencies = [ + "bitflags 2.11.1", + "calloop", + "calloop-wayland-source", + "cursor-icon", + "libc", + "log", + "memmap2", + "rustix 0.38.44", + "thiserror 1.0.69", + "wayland-backend", + "wayland-client", + "wayland-csd-frame", + "wayland-cursor", + "wayland-protocols", + "wayland-protocols-wlr", + "wayland-scanner", + "xkeysym", +] + +[[package]] +name = "smol_str" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" +dependencies = [ + "serde", +] + +[[package]] +name = "softbuffer" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aac18da81ebbf05109ab275b157c22a653bb3c12cf884450179942f81bcbf6c3" +dependencies = [ + "as-raw-xcb-connection", + "bytemuck", + "drm", + "fastrand", + "js-sys", + "memmap2", + "ndk", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation 0.3.2", + "objc2-quartz-core 0.3.2", + "raw-window-handle", + "redox_syscall 0.5.18", + "rustix 1.1.4", + "tiny-xlib", + "tracing", + "wasm-bindgen", + "wayland-backend", + "wayland-client", + "wayland-sys", + "web-sys", + "windows-sys 0.61.2", + "x11rb", +] + +[[package]] +name = "strict-num" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" [[package]] name = "strsim" @@ -847,10 +1956,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom", + "getrandom 0.4.2", "once_cell", - "rustix", - "windows-sys", + "rustix 1.1.4", + "windows-sys 0.61.2", ] [[package]] @@ -868,13 +1977,33 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + [[package]] name = "thiserror" version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl", + "thiserror-impl 2.0.18", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -888,6 +2017,44 @@ dependencies = [ "syn", ] +[[package]] +name = "tiny-skia" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" +dependencies = [ + "arrayref", + "arrayvec", + "bytemuck", + "cfg-if", + "log", + "tiny-skia-path", +] + +[[package]] +name = "tiny-skia-path" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" +dependencies = [ + "arrayref", + "bytemuck", + "strict-num", +] + +[[package]] +name = "tiny-xlib" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a90a0ca3ee6a69f2ad28fd11621a4c3f03b371f366be500b64df260c4ffbafb4" +dependencies = [ + "as-raw-xcb-connection", + "ctor", + "libloading", + "pkg-config", + "tracing", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -935,6 +2102,18 @@ dependencies = [ "wat", ] +[[package]] +name = "tinywasm-doom" +version = "0.0.0" +dependencies = [ + "eyre", + "log", + "pretty_env_logger", + "softbuffer", + "tinywasm", + "winit", +] + [[package]] name = "tinywasm-parser" version = "0.9.0-alpha.0" @@ -963,12 +2142,70 @@ dependencies = [ "serde", ] +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.25.11+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" +dependencies = [ + "indexmap", + "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +dependencies = [ + "winnow", +] + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" + +[[package]] +name = "ttf-parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" + [[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "unicode-segmentation" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" + [[package]] name = "unicode-width" version = "0.2.2" @@ -987,6 +2224,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + [[package]] name = "wait-timeout" version = "0.2.1" @@ -1024,6 +2267,61 @@ dependencies = [ "wit-bindgen 0.51.0", ] +[[package]] +name = "wasm-bindgen" +version = "0.2.120" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df52b6d9b87e0c74c9edfa1eb2d9bf85e5d63515474513aa50fa181b3c4f5db1" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af934872acec734c2d80e6617bbb5ff4f12b052dd8e6332b0817bce889516084" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.120" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b1041f495fb322e64aca85f5756b2172e35cd459376e67f2a6c9dffcedb103" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.120" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dcd0ff20416988a18ac686d4d4d0f6aae9ebf08a389ff5d29012b05af2a1b41" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.120" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49757b3c82ebf16c57d69365a142940b384176c24df52a087fb748e2085359ea" +dependencies = [ + "unicode-ident", +] + [[package]] name = "wasm-encoder" version = "0.244.0" @@ -1072,7 +2370,7 @@ version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ - "bitflags", + "bitflags 2.11.1", "hashbrown 0.15.5", "indexmap", "semver", @@ -1084,7 +2382,7 @@ version = "0.248.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4439c5eee9df71ee0c6efb37f63b1fcb1fec38f85f5142c54e7ed05d33091a" dependencies = [ - "bitflags", + "bitflags 2.11.1", "indexmap", "semver", ] @@ -1111,6 +2409,135 @@ dependencies = [ "wast", ] +[[package]] +name = "wayland-backend" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2857dd20b54e916ec7253b3d6b4d5c4d7d4ca2c33c2e11c6c76a99bd8744755d" +dependencies = [ + "cc", + "downcast-rs", + "rustix 1.1.4", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c7c96bb74690c3189b5c9cb4ca1627062bb23693a4fad9d8c3de958260144" +dependencies = [ + "bitflags 2.11.1", + "rustix 1.1.4", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-csd-frame" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" +dependencies = [ + "bitflags 2.11.1", + "cursor-icon", + "wayland-backend", +] + +[[package]] +name = "wayland-cursor" +version = "0.31.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a52d18780be9b1314328a3de5f930b73d2200112e3849ca6cb11822793fb34d" +dependencies = [ + "rustix 1.1.4", + "wayland-client", + "xcursor", +] + +[[package]] +name = "wayland-protocols" +version = "0.32.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "563a85523cade2429938e790815fd7319062103b9f4a2dc806e9b53b95982d8f" +dependencies = [ + "bitflags 2.11.1", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-plasma" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b6d8cf1eb2c1c31ed1f5643c88a6e53538129d4af80030c8cabd1f9fa884d91" +dependencies = [ + "bitflags 2.11.1", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-wlr" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb04e52f7836d7c7976c78ca0250d61e33873c34156a2a1fc9474828ec268234" +dependencies = [ + "bitflags 2.11.1", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c324a910fd86ebdc364a3e61ec1f11737d3b1d6c273c0239ee8ff4bc0d24b4a" +dependencies = [ + "proc-macro2", + "quick-xml", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.31.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8eab23fefc9e41f8e841df4a9c707e8a8c4ed26e944ef69297184de2785e3be" +dependencies = [ + "dlib", + "log", + "once_cell", + "pkg-config", +] + +[[package]] +name = "web-sys" +version = "0.3.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eadbac71025cd7b0834f20d1fe8472e8495821b4e9801eb0a60bd1f19827602" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "winapi" version = "0.3.9" @@ -1133,7 +2560,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -1148,6 +2575,24 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-sys" version = "0.61.2" @@ -1157,6 +2602,131 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winit" +version = "0.30.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6755fa58a9f8350bd1e472d4c3fcc25f824ec358933bba33306d0b63df5978d" +dependencies = [ + "ahash", + "android-activity", + "atomic-waker", + "bitflags 2.11.1", + "block2", + "bytemuck", + "calloop", + "cfg_aliases", + "concurrent-queue", + "core-foundation", + "core-graphics", + "cursor-icon", + "dpi", + "js-sys", + "libc", + "memmap2", + "ndk", + "objc2 0.5.2", + "objc2-app-kit", + "objc2-foundation 0.2.2", + "objc2-ui-kit", + "orbclient", + "percent-encoding", + "pin-project", + "raw-window-handle", + "redox_syscall 0.4.1", + "rustix 0.38.44", + "sctk-adwaita", + "smithay-client-toolkit", + "smol_str", + "tracing", + "unicode-segmentation", + "wasm-bindgen", + "wasm-bindgen-futures", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-protocols-plasma", + "web-sys", + "web-time", + "windows-sys 0.52.0", + "x11-dl", + "x11rb", + "xkbcommon-dl", +] + +[[package]] +name = "winnow" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0" +dependencies = [ + "memchr", +] + [[package]] name = "wit-bindgen" version = "0.51.0" @@ -1221,7 +2791,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", - "bitflags", + "bitflags 2.11.1", "indexmap", "log", "serde", @@ -1251,6 +2821,63 @@ dependencies = [ "wasmparser 0.244.0", ] +[[package]] +name = "x11-dl" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +dependencies = [ + "libc", + "once_cell", + "pkg-config", +] + +[[package]] +name = "x11rb" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414" +dependencies = [ + "as-raw-xcb-connection", + "gethostname", + "libc", + "libloading", + "once_cell", + "rustix 1.1.4", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" + +[[package]] +name = "xcursor" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b" + +[[package]] +name = "xkbcommon-dl" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" +dependencies = [ + "bitflags 2.11.1", + "dlib", + "log", + "once_cell", + "xkeysym", +] + +[[package]] +name = "xkeysym" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" + [[package]] name = "zerocopy" version = "0.8.48" diff --git a/Cargo.toml b/Cargo.toml index 15eb5fe..892c38f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members=["crates/*"] +members=["crates/*", "examples/doom"] default-members=[".", "crates/tinywasm", "crates/types", "crates/parser"] resolver="2" diff --git a/crates/tinywasm/src/interpreter/executor.rs b/crates/tinywasm/src/interpreter/executor.rs index b1178d8..4d862d6 100644 --- a/crates/tinywasm/src/interpreter/executor.rs +++ b/crates/tinywasm/src/interpreter/executor.rs @@ -6,6 +6,7 @@ use super::no_std_floats::NoStdFloatExt; use alloc::boxed::Box; use alloc::rc::Rc; +use alloc::vec::Vec; use alloc::sync::Arc; use interpreter::stack::CallFrame; @@ -969,7 +970,8 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> { } fn exec_call_host(&mut self, host_func: Rc) -> Result<(), Trap> { - let params = self.store.value_stack.pop_types(host_func.ty.params()).collect::>(); + let mut params = self.store.value_stack.pop_types(host_func.ty.params().iter().rev()).collect::>(); + params.reverse(); let res = match host_func.call(FuncContext { store: self.store, module_addr: self.module.idx() }, ¶ms) { Ok(res) => res, Err(err) => { diff --git a/crates/tinywasm/src/reference.rs b/crates/tinywasm/src/reference.rs index 44916b4..5f8d46f 100644 --- a/crates/tinywasm/src/reference.rs +++ b/crates/tinywasm/src/reference.rs @@ -261,6 +261,19 @@ impl Memory { }) } + /// Copies a nul-terminated C string into memory. + pub fn write_cstring(&self, store: &mut Store, offset: usize, string: &CString) -> Result<()> { + self.copy_from_slice(store, offset, string.as_bytes_with_nul()) + } + + /// Copies a UTF-8 string into memory and appends a trailing nul byte. + pub fn write_cstring_bytes(&self, store: &mut Store, offset: usize, string: &str) -> Result<()> { + let mut bytes = Vec::with_capacity(string.len() + 1); + bytes.extend_from_slice(string.as_bytes()); + bytes.push(0); + self.copy_from_slice(store, offset, &bytes) + } + /// Reads a C-style string from memory. pub fn read_cstring(&self, store: &Store, offset: usize, len: usize) -> Result { CString::from_vec_with_nul(self.read_vec(store, offset, len)?) diff --git a/crates/tinywasm/tests/host_import_arg_order.rs b/crates/tinywasm/tests/host_import_arg_order.rs new file mode 100644 index 0000000..2004641 --- /dev/null +++ b/crates/tinywasm/tests/host_import_arg_order.rs @@ -0,0 +1,31 @@ +use tinywasm::{HostFunction, Imports, ModuleInstance, Store}; + +#[test] +fn multi_arg_host_imports_preserve_source_order() { + let wasm = wat::parse_str( + r#" + (module + (import "env" "pair" (func $pair (param i32 i32) (result i32))) + (func (export "call_pair") (param i32 i32) (result i32) + local.get 0 + local.get 1 + call $pair)) + "#, + ) + .unwrap(); + + let module = tinywasm::parse_bytes(&wasm).unwrap(); + let mut store = Store::default(); + + let pair = HostFunction::from(&mut store, |_ctx, (left, right): (i32, i32)| -> tinywasm::Result { + Ok(left * 1000 + right) + }); + + let mut imports = Imports::new(); + imports.define("env", "pair", pair); + + let instance = ModuleInstance::instantiate(&mut store, &module, Some(imports)).unwrap(); + let func = instance.func::<(i32, i32), i32>(&store, "call_pair").unwrap(); + + assert_eq!(func.call(&mut store, (12, 34)).unwrap(), 12034); +} diff --git a/examples/doom/Cargo.toml b/examples/doom/Cargo.toml new file mode 100644 index 0000000..c1d0af4 --- /dev/null +++ b/examples/doom/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name="tinywasm-doom" +publish=false +edition.workspace=true +rust-version.workspace=true + +[dependencies] +eyre.workspace=true +pretty_env_logger.workspace=true +tinywasm={workspace=true, features=[ + "std", + "parser", + "log", + "archive", + "canonicalize-nans", + "debug", + "parallel-parser", +]} +log.workspace=true +softbuffer="0.4" +winit="0.30" diff --git a/examples/doom/README.md b/examples/doom/README.md new file mode 100644 index 0000000..f3bc60e --- /dev/null +++ b/examples/doom/README.md @@ -0,0 +1,19 @@ +# Doom Example + +This example builds a WebAssembly guest from [`PureDOOM`](https://github.com/Daivuk/PureDOOM) and runs it inside `tinywasm`. The host uses `winit` and `softbuffer` to present the framebuffer. + +## Prerequisites + +- `clang` +- `git` +- a Doom WAD that you provide yourself + +## Running the example + +```sh +# download & build `PureDOOM` +./examples/doom/build.sh + +# start doom with the WAD you want to use +cargo run -p tinywasm-doom --release -- /path/to/DOOM1.WAD +``` diff --git a/examples/doom/build.sh b/examples/doom/build.sh new file mode 100755 index 0000000..a6b6c01 --- /dev/null +++ b/examples/doom/build.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +set -euo pipefail + +cd "$(dirname "$0")" + +upstream_dir="upstream/PureDOOM" +out_dir="out" +wrapper_src="guest/tinywasm_puredoom.c" +output="$out_dir/puredoom.wasm" + +if ! command -v git >/dev/null 2>&1; then + printf 'missing required tool: git\n' >&2 + exit 1 +fi + +if ! command -v clang >/dev/null 2>&1; then + printf 'missing required tool: clang\n' >&2 + exit 1 +fi + +mkdir -p "upstream" "$out_dir" + +if [[ ! -d "$upstream_dir/.git" ]]; then + git clone --depth 1 https://github.com/Daivuk/PureDOOM.git "$upstream_dir" +else + git -C "$upstream_dir" pull --ff-only +fi + +clang \ + --target=wasm32-unknown-unknown \ + -O2 \ + -nostdlib \ + -fno-builtin \ + -w \ + -Wl,--no-entry \ + -Wl,--allow-undefined \ + -Wl,--export=tinywasm_doom_init \ + -Wl,--export=tinywasm_doom_update \ + -Wl,--export=tinywasm_doom_framebuffer \ + -Wl,--export=tinywasm_doom_sound_buffer \ + -Wl,--export=tinywasm_doom_tick_midi \ + -Wl,--export=tinywasm_doom_wad_path_buf \ + -Wl,--export=tinywasm_doom_key_down \ + -Wl,--export=tinywasm_doom_key_up \ + -Wl,--export=memory \ + -Wl,--export=__heap_base \ + -Wl,--export=__data_end \ + -Wl,--initial-memory=16777216 \ + -Wl,--max-memory=268435456 \ + -Wl,--stack-first \ + -I"$upstream_dir" \ + "$wrapper_src" \ + -o "$output" + +printf 'built %s\n' "$output" diff --git a/examples/doom/guest/tinywasm_puredoom.c b/examples/doom/guest/tinywasm_puredoom.c new file mode 100644 index 0000000..1e3e6bd --- /dev/null +++ b/examples/doom/guest/tinywasm_puredoom.c @@ -0,0 +1,203 @@ +#define DOOM_IMPLEMENTATION +#include "PureDOOM.h" + +#if defined(__clang__) +#define IMPORT(name) __attribute__((import_module("env"), import_name(name))) +#else +#define IMPORT(name) +#endif + +extern int host_open(const char *filename, const char *mode) IMPORT("host_open"); +extern void host_close(int handle) IMPORT("host_close"); +extern int host_read(int handle, void *buf, int count) IMPORT("host_read"); +extern int host_write(int handle, const void *buf, int count) IMPORT("host_write"); +extern int host_seek(int handle, int offset, int origin) IMPORT("host_seek"); +extern int host_tell(int handle) IMPORT("host_tell"); +extern int host_eof(int handle) IMPORT("host_eof"); +extern void host_gettime(int *sec, int *usec) IMPORT("host_gettime"); +extern void host_exit(int code) IMPORT("host_exit"); +extern void host_print(const char *text) IMPORT("host_print"); + +extern unsigned char __heap_base; + +static char g_wad_path[1024]; +static char g_home_dir[] = "."; +static char g_program_name[] = "puredoom"; +static char g_iwad_flag[] = "-iwad"; +static char *g_argv[] = {g_program_name, g_iwad_flag, g_wad_path, 0}; +static unsigned int g_heap_ptr; + +static unsigned int align_up(unsigned int value, unsigned int alignment) +{ + return (value + alignment - 1u) & ~(alignment - 1u); +} + +unsigned int strlen(const char *str) +{ + unsigned int len = 0; + while (str[len] != '\0') + ++len; + return len; +} + +static int str_eq(const char *left, const char *right) +{ + unsigned int i = 0; + for (;;) + { + if (left[i] != right[i]) + return 0; + if (left[i] == '\0') + return 1; + ++i; + } +} + +static void *guest_malloc(int size) +{ + unsigned int alloc_size; + unsigned int end; + unsigned int capacity; + unsigned int extra_pages; + void *result; + + if (size <= 0) + return 0; + + if (g_heap_ptr == 0) + g_heap_ptr = align_up((unsigned int)(unsigned long)&__heap_base, 16u); + + alloc_size = align_up((unsigned int)size, 16u); + end = g_heap_ptr + alloc_size; + capacity = __builtin_wasm_memory_size(0) * 65536u; + + if (end > capacity) + { + extra_pages = (end - capacity + 65535u) / 65536u; + if (__builtin_wasm_memory_grow(0, extra_pages) == (unsigned int)-1) + return 0; + } + + result = (void *)(unsigned long)g_heap_ptr; + g_heap_ptr = end; + return result; +} + +static void guest_free(void *ptr) +{ + (void)ptr; +} + +static void *guest_open(const char *filename, const char *mode) +{ + int handle = host_open(filename, mode); + if (handle < 0) + return 0; + return (void *)(unsigned long)(handle + 1); +} + +static int guest_handle(void *handle) +{ + return (int)(unsigned long)handle - 1; +} + +static void guest_close(void *handle) +{ + host_close(guest_handle(handle)); +} + +static int guest_read(void *handle, void *buf, int count) +{ + return host_read(guest_handle(handle), buf, count); +} + +static int guest_write(void *handle, const void *buf, int count) +{ + return host_write(guest_handle(handle), buf, count); +} + +static int guest_seek(void *handle, int offset, doom_seek_t origin) +{ + return host_seek(guest_handle(handle), offset, (int)origin); +} + +static int guest_tell(void *handle) +{ + return host_tell(guest_handle(handle)); +} + +static int guest_eof(void *handle) +{ + return host_eof(guest_handle(handle)); +} + +static void guest_gettime(int *sec, int *usec) +{ + host_gettime(sec, usec); +} + +static void guest_exit(int code) +{ + host_exit(code); +} + +static char *guest_getenv(const char *var) +{ + if (str_eq(var, "HOME")) + return g_home_dir; + return 0; +} + +unsigned int tinywasm_doom_wad_path_buf(void) +{ + return (unsigned int)(unsigned long)g_wad_path; +} + +void tinywasm_doom_init(void) +{ + doom_set_print(host_print); + doom_set_malloc(guest_malloc, guest_free); + doom_set_file_io(guest_open, guest_close, guest_read, guest_write, guest_seek, guest_tell, guest_eof); + doom_set_gettime(guest_gettime); + doom_set_exit(guest_exit); + doom_set_getenv(guest_getenv); + + doom_set_default_int("key_up", DOOM_KEY_W); + doom_set_default_int("key_down", DOOM_KEY_S); + doom_set_default_int("key_strafeleft", DOOM_KEY_A); + doom_set_default_int("key_straferight", DOOM_KEY_D); + doom_set_default_int("key_use", DOOM_KEY_E); + doom_set_resolution(320, 200); + + doom_init(3, g_argv, DOOM_FLAG_HIDE_MOUSE_OPTIONS | DOOM_FLAG_HIDE_SOUND_OPTIONS | DOOM_FLAG_HIDE_MUSIC_OPTIONS); +} + +void tinywasm_doom_update(void) +{ + doom_update(); +} + +unsigned int tinywasm_doom_framebuffer(void) +{ + return (unsigned int)(unsigned long)doom_get_framebuffer(4); +} + +unsigned int tinywasm_doom_sound_buffer(void) +{ + return (unsigned int)(unsigned long)doom_get_sound_buffer(); +} + +unsigned long tinywasm_doom_tick_midi(void) +{ + return doom_tick_midi(); +} + +void tinywasm_doom_key_down(int key) +{ + doom_key_down((doom_key_t)key); +} + +void tinywasm_doom_key_up(int key) +{ + doom_key_up((doom_key_t)key); +} diff --git a/examples/doom/out/.gitkeep b/examples/doom/out/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/examples/doom/src/main.rs b/examples/doom/src/main.rs new file mode 100644 index 0000000..095183d --- /dev/null +++ b/examples/doom/src/main.rs @@ -0,0 +1,202 @@ +mod runtime; + +use std::num::NonZeroU32; +use std::path::{Path, PathBuf}; +use std::rc::Rc; + +use eyre::{ContextCompat, Result, bail, eyre}; +use runtime::{Runtime, SCREEN_HEIGHT, SCREEN_WIDTH}; +use softbuffer::{Context as SoftbufferContext, Surface}; +use winit::application::ApplicationHandler; +use winit::dpi::{LogicalSize, Size}; +use winit::event::{ElementState, WindowEvent}; +use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop}; +use winit::keyboard::{KeyCode, PhysicalKey}; +use winit::window::{Window, WindowAttributes, WindowLevel}; + +const GUEST_MODULE: &str = "examples/doom/out/puredoom.wasm"; +const DEFAULT_TITLE: &str = "tinywasm doom"; + +fn main() -> Result<()> { + pretty_env_logger::init(); + + let wad_path = std::env::args().nth(1).map(PathBuf::from).context("usage: cargo run -p tinywasm-doom -- ")?; + if !wad_path.exists() { + bail!("WAD not found: {}", wad_path.display()); + } + + let guest_path = Path::new(GUEST_MODULE); + if !guest_path.exists() { + bail!("guest module missing: {}. Run ./examples/doom/build.sh first", guest_path.display()); + } + + let event_loop = EventLoop::new()?; + let mut app = DoomApp::new(wad_path, guest_path.to_path_buf())?; + event_loop.run_app(&mut app)?; + Ok(()) +} + +struct DoomApp { + runtime: Runtime, + window: Option>, + softbuffer_context: Option>>, + softbuffer_surface: Option, Rc>>, +} + +impl DoomApp { + fn new(wad_path: PathBuf, guest_path: PathBuf) -> Result { + Ok(Self { + runtime: Runtime::new(wad_path, guest_path)?, + window: None, + softbuffer_context: None, + softbuffer_surface: None, + }) + } + + fn present(&mut self) -> Result<()> { + let Some(surface) = self.softbuffer_surface.as_mut() else { + return Ok(()); + }; + + surface + .resize(NonZeroU32::new(SCREEN_WIDTH as u32).unwrap(), NonZeroU32::new(SCREEN_HEIGHT as u32).unwrap()) + .map_err(|err| eyre!(err.to_string()))?; + let mut buffer = surface.buffer_mut().map_err(|err| eyre!(err.to_string()))?; + self.runtime.write_framebuffer(&mut buffer)?; + buffer.present().map_err(|err| eyre!(err.to_string()))?; + Ok(()) + } +} + +impl ApplicationHandler for DoomApp { + fn resumed(&mut self, event_loop: &ActiveEventLoop) { + event_loop.set_control_flow(ControlFlow::Poll); + + let size = LogicalSize::new((SCREEN_WIDTH * 2) as f64, (SCREEN_HEIGHT * 2) as f64); + + let attributes = WindowAttributes::default() + .with_title(DEFAULT_TITLE) + .with_inner_size(Size::Logical(size)) + .with_resizable(false) + .with_window_level(if cfg!(target_os = "linux") { WindowLevel::AlwaysOnTop } else { WindowLevel::Normal }); + + let window = Rc::new(event_loop.create_window(attributes).expect("create window")); + let context = SoftbufferContext::new(window.clone()).expect("create softbuffer context"); + let surface = Surface::new(&context, window.clone()).expect("create softbuffer surface"); + + self.softbuffer_context = Some(context); + self.softbuffer_surface = Some(surface); + self.window = Some(window.clone()); + window.set_cursor_visible(false); + window.request_redraw(); + } + + fn window_event(&mut self, event_loop: &ActiveEventLoop, _window_id: winit::window::WindowId, event: WindowEvent) { + match event { + WindowEvent::CloseRequested => event_loop.exit(), + WindowEvent::RedrawRequested => { + if let Err(err) = self.present() { + log::error!("present failed: {err:?}"); + event_loop.exit(); + } + } + WindowEvent::KeyboardInput { event, .. } => { + if let Some(key) = doom_key(&event.physical_key) { + let result = if matches!(event.state, ElementState::Pressed) { + self.runtime.key_down(i32::from(key)) + } else { + self.runtime.key_up(i32::from(key)) + }; + + if let Err(err) = result { + log::error!("keyboard event failed: {err:?}"); + event_loop.exit(); + } + } + } + _ => {} + } + } + + fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) { + if let Err(err) = self.runtime.tick() { + log::error!("doom tick failed: {err:?}"); + event_loop.exit(); + return; + } + + if let Some(window) = &self.window { + window.request_redraw(); + } + + if self.runtime.host_state.borrow().exit_code.is_some() { + event_loop.exit(); + } + } +} + +fn doom_key(key: &PhysicalKey) -> Option { + let code = match key { + PhysicalKey::Code(KeyCode::Enter) => 13, + PhysicalKey::Code(KeyCode::Escape) => 27, + PhysicalKey::Code(KeyCode::ArrowLeft) => 0xac, + PhysicalKey::Code(KeyCode::ArrowRight) => 0xae, + PhysicalKey::Code(KeyCode::ArrowUp) => 0xad, + PhysicalKey::Code(KeyCode::ArrowDown) => 0xaf, + PhysicalKey::Code(KeyCode::ControlLeft | KeyCode::ControlRight) => 0x80 + 0x1d, + PhysicalKey::Code(KeyCode::ShiftLeft | KeyCode::ShiftRight) => 0xb6, + PhysicalKey::Code(KeyCode::AltLeft | KeyCode::AltRight) => 0xb8, + PhysicalKey::Code(KeyCode::Space) => b' ', + PhysicalKey::Code(KeyCode::F2) => 0x80 + 0x3c, + PhysicalKey::Code(KeyCode::F3) => 0x80 + 0x3d, + PhysicalKey::Code(KeyCode::F4) => 0x80 + 0x3e, + PhysicalKey::Code(KeyCode::F5) => 0x80 + 0x3f, + PhysicalKey::Code(KeyCode::F6) => 0x80 + 0x40, + PhysicalKey::Code(KeyCode::F7) => 0x80 + 0x41, + PhysicalKey::Code(KeyCode::F8) => 0x80 + 0x42, + PhysicalKey::Code(KeyCode::F9) => 0x80 + 0x43, + PhysicalKey::Code(KeyCode::F10) => 0x80 + 0x44, + PhysicalKey::Code(KeyCode::F11) => 0x80 + 0x57, + PhysicalKey::Code(KeyCode::Equal) => b'=', + PhysicalKey::Code(KeyCode::Minus) => b'-', + PhysicalKey::Code(KeyCode::KeyA) => b'a', + PhysicalKey::Code(KeyCode::KeyB) => b'b', + PhysicalKey::Code(KeyCode::KeyC) => b'c', + PhysicalKey::Code(KeyCode::KeyD) => b'd', + PhysicalKey::Code(KeyCode::KeyE) => b'e', + PhysicalKey::Code(KeyCode::KeyF) => b'f', + PhysicalKey::Code(KeyCode::KeyG) => b'g', + PhysicalKey::Code(KeyCode::KeyH) => b'h', + PhysicalKey::Code(KeyCode::KeyI) => b'i', + PhysicalKey::Code(KeyCode::KeyJ) => b'j', + PhysicalKey::Code(KeyCode::KeyK) => b'k', + PhysicalKey::Code(KeyCode::KeyL) => b'l', + PhysicalKey::Code(KeyCode::KeyM) => b'm', + PhysicalKey::Code(KeyCode::KeyN) => b'n', + PhysicalKey::Code(KeyCode::KeyO) => b'o', + PhysicalKey::Code(KeyCode::KeyP) => b'p', + PhysicalKey::Code(KeyCode::KeyQ) => b'q', + PhysicalKey::Code(KeyCode::KeyR) => b'r', + PhysicalKey::Code(KeyCode::KeyS) => b's', + PhysicalKey::Code(KeyCode::KeyT) => b't', + PhysicalKey::Code(KeyCode::KeyU) => b'u', + PhysicalKey::Code(KeyCode::KeyV) => b'v', + PhysicalKey::Code(KeyCode::KeyW) => b'w', + PhysicalKey::Code(KeyCode::KeyX) => b'x', + PhysicalKey::Code(KeyCode::KeyY) => b'y', + PhysicalKey::Code(KeyCode::KeyZ) => b'z', + PhysicalKey::Code(KeyCode::Digit0) => b'0', + PhysicalKey::Code(KeyCode::Digit1) => b'1', + PhysicalKey::Code(KeyCode::Digit2) => b'2', + PhysicalKey::Code(KeyCode::Digit3) => b'3', + PhysicalKey::Code(KeyCode::Digit4) => b'4', + PhysicalKey::Code(KeyCode::Digit5) => b'5', + PhysicalKey::Code(KeyCode::Digit6) => b'6', + PhysicalKey::Code(KeyCode::Digit7) => b'7', + PhysicalKey::Code(KeyCode::Digit8) => b'8', + PhysicalKey::Code(KeyCode::Digit9) => b'9', + _ => return None, + }; + + Some(code) +} diff --git a/examples/doom/src/runtime.rs b/examples/doom/src/runtime.rs new file mode 100644 index 0000000..980dc21 --- /dev/null +++ b/examples/doom/src/runtime.rs @@ -0,0 +1,348 @@ +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::fs::{File, OpenOptions, create_dir_all}; +use std::io::{Read, Seek, SeekFrom, Write}; +use std::path::{Path, PathBuf}; +use std::rc::Rc; +use std::time::Instant; + +use eyre::Result; +use tinywasm::{FuncContext, HostFunction, Imports, ModuleInstance, Store}; + +const IMPORT_MODULE: &str = "env"; +pub const SCREEN_WIDTH: usize = 320; +pub const SCREEN_HEIGHT: usize = 200; + +pub struct Runtime { + store: Store, + update: tinywasm::FunctionTyped<(), ()>, + framebuffer: tinywasm::FunctionTyped<(), i32>, + key_down: tinywasm::FunctionTyped, + key_up: tinywasm::FunctionTyped, + memory: tinywasm::Memory, + framebuffer_bytes: Vec, + pub host_state: Rc>, +} + +impl Runtime { + pub fn new(wad_path: PathBuf, guest_path: PathBuf) -> Result { + let module = tinywasm::parse_file(&guest_path)?; + let mut store = Store::default(); + let host_state = Rc::new(RefCell::new(HostState::new(wad_path))); + let imports = build_imports(&mut store, host_state.clone()); + let instance = ModuleInstance::instantiate(&mut store, &module, Some(imports))?; + + let wad_path_buf = instance.func::<(), i32>(&store, "tinywasm_doom_wad_path_buf")?; + let init = instance.func::<(), ()>(&store, "tinywasm_doom_init")?; + let update = instance.func::<(), ()>(&store, "tinywasm_doom_update")?; + let framebuffer = instance.func::<(), i32>(&store, "tinywasm_doom_framebuffer")?; + let key_down = instance.func::(&store, "tinywasm_doom_key_down")?; + let key_up = instance.func::(&store, "tinywasm_doom_key_up")?; + let memory = instance.memory("memory")?; + + let buf_ptr = wad_path_buf.call(&mut store, ())? as usize; + let wad_path_string = host_state.borrow().wad_path.to_string_lossy().into_owned(); + memory.write_cstring_bytes(&mut store, buf_ptr, &wad_path_string)?; + init.call(&mut store, ())?; + + let width = SCREEN_WIDTH; + let height = SCREEN_HEIGHT; + + Ok(Self { + store, + update, + framebuffer, + key_down, + key_up, + memory, + framebuffer_bytes: vec![0; width * height * 4], + host_state, + }) + } + + pub fn tick(&mut self) -> Result<()> { + self.update.call(&mut self.store, ())?; + Ok(()) + } + + pub fn write_framebuffer(&mut self, dst: &mut [u32]) -> Result<()> { + let ptr = self.framebuffer.call(&mut self.store, ())? as usize; + self.memory.read_exact(&self.store, ptr, &mut self.framebuffer_bytes)?; + for (index, pixel) in dst.iter_mut().enumerate() { + let byte_index = index * 4; + let chunk = &self.framebuffer_bytes[byte_index..byte_index + 4]; + *pixel = ((chunk[0] as u32) << 16) | ((chunk[1] as u32) << 8) | chunk[2] as u32; + } + Ok(()) + } + + pub fn key_down(&mut self, key: i32) -> Result<()> { + self.key_down.call(&mut self.store, key)?; + Ok(()) + } + + pub fn key_up(&mut self, key: i32) -> Result<()> { + self.key_up.call(&mut self.store, key)?; + Ok(()) + } +} + +pub struct HostState { + pub wad_path: PathBuf, + runtime_dir: PathBuf, + start: Instant, + files: BTreeMap, + next_file: i32, + pub exit_code: Option, +} + +impl HostState { + fn new(wad_path: PathBuf) -> Self { + let runtime_dir = PathBuf::from("examples/doom/out/runtime"); + let _ = create_dir_all(&runtime_dir); + Self { wad_path, runtime_dir, start: Instant::now(), files: BTreeMap::new(), next_file: 3, exit_code: None } + } + + fn resolve_path(&self, path: &str) -> PathBuf { + let candidate = Path::new(path); + if candidate.is_absolute() { candidate.to_path_buf() } else { self.runtime_dir.join(candidate) } + } + + fn should_redirect_to_wad(&self, requested: &str) -> bool { + let Some(file_name) = Path::new(requested).file_name().and_then(|name| name.to_str()) else { + return false; + }; + + let requested = file_name.to_ascii_lowercase(); + let provided = self.wad_path.file_name().and_then(|name| name.to_str()).map(|name| name.to_ascii_lowercase()); + + match provided.as_deref() { + Some("doom1.wad") => requested == "doom1.wad", + Some("doom.wad") => requested == "doom.wad", + Some("doomu.wad") => requested == "doomu.wad", + Some("doom2.wad") => requested == "doom2.wad", + Some("doom2f.wad") => requested == "doom2f.wad", + Some("plutonia.wad") => requested == "plutonia.wad", + Some("tnt.wad") => requested == "tnt.wad", + Some(provided_name) => requested == provided_name, + None => false, + } + } + + fn open_mode_options(mode: &str) -> OpenOptions { + let mut options = OpenOptions::new(); + let plus = mode.as_bytes().contains(&b'+'); + + match mode.as_bytes().first().copied() { + Some(b'r') => { + options.read(true); + if plus { + options.write(true); + } + } + Some(b'w') => { + options.write(true).create(true).truncate(true); + if plus { + options.read(true); + } + } + Some(b'a') => { + options.write(true).create(true).append(true); + if plus { + options.read(true); + } + } + _ => { + options.read(true); + } + } + + options + } +} + +fn build_imports(store: &mut Store, state: Rc>) -> Imports { + let mut imports = Imports::new(); + + { + let state = state.clone(); + imports.define( + IMPORT_MODULE, + "host_open", + HostFunction::from(store, move |ctx: FuncContext<'_>, (filename_ptr, mode_ptr): (i32, i32)| { + let memory = ctx.memory("memory")?; + let filename = memory.read_cstring_until_null(ctx.store(), filename_ptr as usize, 1024)?; + let mode = memory.read_cstring_until_null(ctx.store(), mode_ptr as usize, 16)?; + let filename = filename.to_string_lossy(); + let mode = mode.to_string_lossy(); + let mut state = state.borrow_mut(); + let path = if filename == state.wad_path.to_string_lossy() || state.should_redirect_to_wad(&filename) { + state.wad_path.clone() + } else { + state.resolve_path(&filename) + }; + + if path.is_dir() { + log::debug!("guest open rejected directory: path={} mode={}", path.display(), mode); + return Ok(-1); + } + + let file = match HostState::open_mode_options(&mode).open(&path) { + Ok(file) => file, + Err(err) => { + log::debug!("guest open failed: path={} mode={} err={err}", path.display(), mode); + return Ok(-1); + } + }; + + let handle = state.next_file; + state.next_file += 1; + state.files.insert(handle, file); + Ok(handle) + }), + ); + } + + { + let state = state.clone(); + imports.define( + IMPORT_MODULE, + "host_close", + HostFunction::from(store, move |_ctx: FuncContext<'_>, handle: i32| { + state.borrow_mut().files.remove(&handle); + Ok(()) + }), + ); + } + + { + let state = state.clone(); + imports.define( + IMPORT_MODULE, + "host_read", + HostFunction::from(store, move |mut ctx: FuncContext<'_>, (handle, buf_ptr, count): (i32, i32, i32)| { + let mut state = state.borrow_mut(); + let Some(file) = state.files.get_mut(&handle) else { + return Ok(0); + }; + let mut buffer = vec![0; count.max(0) as usize]; + let read = file.read(&mut buffer).map_err(|err| tinywasm::Error::Other(err.to_string()))?; + ctx.memory("memory")?.copy_from_slice(ctx.store_mut(), buf_ptr as usize, &buffer[..read])?; + Ok(read as i32) + }), + ); + } + + { + let state = state.clone(); + imports.define( + IMPORT_MODULE, + "host_write", + HostFunction::from(store, move |ctx: FuncContext<'_>, (handle, buf_ptr, count): (i32, i32, i32)| { + let data = ctx.memory("memory")?.read_vec(ctx.store(), buf_ptr as usize, count.max(0) as usize)?; + let mut state = state.borrow_mut(); + let Some(file) = state.files.get_mut(&handle) else { + return Ok(-1); + }; + let written = file.write(&data).map_err(|err| tinywasm::Error::Other(err.to_string()))?; + Ok(written as i32) + }), + ); + } + + { + let state = state.clone(); + imports.define( + IMPORT_MODULE, + "host_seek", + HostFunction::from(store, move |_ctx: FuncContext<'_>, (handle, offset, origin): (i32, i32, i32)| { + let seek_from = match origin { + 0 => SeekFrom::Start(offset.max(0) as u64), + 1 => SeekFrom::Current(offset as i64), + 2 => SeekFrom::End(offset as i64), + _ => return Err(tinywasm::Error::Other(format!("invalid seek origin: {origin}"))), + }; + let mut state = state.borrow_mut(); + let Some(file) = state.files.get_mut(&handle) else { + return Ok(-1); + }; + let pos = file.seek(seek_from).map_err(|err| tinywasm::Error::Other(err.to_string()))?; + Ok(pos.min(i32::MAX as u64) as i32) + }), + ); + } + + { + let state = state.clone(); + imports.define( + IMPORT_MODULE, + "host_tell", + HostFunction::from(store, move |_ctx: FuncContext<'_>, handle: i32| { + let mut state = state.borrow_mut(); + let Some(file) = state.files.get_mut(&handle) else { + return Ok(-1); + }; + let pos = file.stream_position().map_err(|err| tinywasm::Error::Other(err.to_string()))?; + Ok(pos.min(i32::MAX as u64) as i32) + }), + ); + } + + { + let state = state.clone(); + imports.define( + IMPORT_MODULE, + "host_eof", + HostFunction::from(store, move |_ctx: FuncContext<'_>, handle: i32| { + let mut state = state.borrow_mut(); + let Some(file) = state.files.get_mut(&handle) else { + return Ok(1); + }; + let pos = file.stream_position().map_err(|err| tinywasm::Error::Other(err.to_string()))?; + let len = file.metadata().map_err(|err| tinywasm::Error::Other(err.to_string()))?.len(); + Ok((pos >= len) as i32) + }), + ); + } + + { + let state = state.clone(); + imports.define( + IMPORT_MODULE, + "host_gettime", + HostFunction::from(store, move |mut ctx: FuncContext<'_>, (sec_ptr, usec_ptr): (i32, i32)| { + let elapsed = state.borrow().start.elapsed(); + let sec = elapsed.as_secs().min(i32::MAX as u64) as i32; + let usec = elapsed.subsec_micros() as i32; + let memory = ctx.memory("memory")?; + memory.copy_from_slice(ctx.store_mut(), sec_ptr as usize, &sec.to_le_bytes())?; + memory.copy_from_slice(ctx.store_mut(), usec_ptr as usize, &usec.to_le_bytes())?; + Ok(()) + }), + ); + } + + { + let state = state.clone(); + imports.define( + IMPORT_MODULE, + "host_exit", + HostFunction::from(store, move |_ctx: FuncContext<'_>, code: i32| { + state.borrow_mut().exit_code = Some(code); + Ok(()) + }), + ); + } + + imports.define( + IMPORT_MODULE, + "host_print", + HostFunction::from(store, move |ctx: FuncContext<'_>, ptr: i32| { + let text = ctx.memory("memory")?.read_cstring_until_null(ctx.store(), ptr as usize, 4096)?; + log::info!("guest: {}", text.to_string_lossy()); + Ok(()) + }), + ); + + imports +} -- cgit v1.3.1