From eaa833f36ca791a8f735e5740231dfd864e8b857 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 15 Oct 2026 13:43:10 +0900 Subject: [PATCH 01/15] Add Shuttle core prototype under native/ Rust workspace with shuttle-core (Machine, firmware ABI draft 0.1 host functions, snapshot format) and shuttle-runner (headless emulator with a capture/restore verification mode), plus minimal C guests (BIOS, OS, child). Depends on akkiserver-dev/weave branch shuttle-host-hooks. Java side is untouched; JNI comes in a later step. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01WE6jR1fQDhj3HTdNWb73L9 --- native/.gitignore | 2 + native/Cargo.lock | 1826 +++++++++++++++++++++ native/Cargo.toml | 24 + native/README.md | 92 ++ native/crates/shuttle-core/Cargo.toml | 14 + native/crates/shuttle-core/src/abi.rs | 109 ++ native/crates/shuttle-core/src/codec.rs | 373 +++++ native/crates/shuttle-core/src/imports.rs | 597 +++++++ native/crates/shuttle-core/src/lib.rs | 137 ++ native/crates/shuttle-core/src/machine.rs | 363 ++++ native/crates/shuttle-runner/Cargo.toml | 8 + native/crates/shuttle-runner/src/main.rs | 187 +++ native/guests/bios.c | 73 + native/guests/build.sh | 12 + native/guests/child.c | 57 + native/guests/os.c | 137 ++ native/guests/shuttle.h | 123 ++ 17 files changed, 4134 insertions(+) create mode 100644 native/.gitignore create mode 100644 native/Cargo.lock create mode 100644 native/Cargo.toml create mode 100644 native/README.md create mode 100644 native/crates/shuttle-core/Cargo.toml create mode 100644 native/crates/shuttle-core/src/abi.rs create mode 100644 native/crates/shuttle-core/src/codec.rs create mode 100644 native/crates/shuttle-core/src/imports.rs create mode 100644 native/crates/shuttle-core/src/lib.rs create mode 100644 native/crates/shuttle-core/src/machine.rs create mode 100644 native/crates/shuttle-runner/Cargo.toml create mode 100644 native/crates/shuttle-runner/src/main.rs create mode 100644 native/guests/bios.c create mode 100644 native/guests/build.sh create mode 100644 native/guests/child.c create mode 100644 native/guests/os.c create mode 100644 native/guests/shuttle.h diff --git a/native/.gitignore b/native/.gitignore new file mode 100644 index 0000000..e33c020 --- /dev/null +++ b/native/.gitignore @@ -0,0 +1,2 @@ +/target/ +/guests/out/ diff --git a/native/Cargo.lock b/native/Cargo.lock new file mode 100644 index 0000000..677e565 --- /dev/null +++ b/native/Cargo.lock @@ -0,0 +1,1826 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "addr2line" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59317f77929f0e679d39364702289274de2f0f0b22cbf50b2b8cff2169a0b27a" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "anyhow" +version = "1.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" + +[[package]] +name = "arbitrary" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bc62ac97cc33321f50863d514c3bc38a453947a8f9e781137e47c7401020aed" + +[[package]] +name = "async-trait" +version = "0.1.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.9", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "2.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" +dependencies = [ + "allocator-api2", +] + +[[package]] +name = "cc" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6651c9ed80effdc7db0ff72512157f901af5e3549e341e24b1dd4887d836d838" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" + +[[package]] +name = "cobs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" +dependencies = [ + "thiserror 2.0.21", +] + +[[package]] +name = "core_detect" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f8f80099a98041a3d1622845c271458a2d73e688351bf3cb999266764b81d48" + +[[package]] +name = "cpp_demangle" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2bb79cb74d735044c972aae58ed0aaa9a837e85b01106a54c39e42e97f62253" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "cranelift-assembler-x64" +version = "0.133.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aadfd45214f09461ba0406f7dacecce5cac39bf0bdb4890eeb468f4ef090e07" +dependencies = [ + "cranelift-assembler-x64-meta", +] + +[[package]] +name = "cranelift-assembler-x64-meta" +version = "0.133.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57069faede9bd1f926364b4cf69ccc9bebc6f4af5ab897083581b7bc991bf20a" +dependencies = [ + "cranelift-srcgen", +] + +[[package]] +name = "cranelift-bforest" +version = "0.133.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b1221450f2f9efaa996d916bf53a0a4d13346a4a75468afb828390209a4fdd4" +dependencies = [ + "cranelift-entity", + "wasmtime-internal-core", +] + +[[package]] +name = "cranelift-bitset" +version = "0.133.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97706f2b466d67bdf0f69d1cf5c5c4a5cd31087cf1fa2e8e5fe0450dddc8661d" +dependencies = [ + "serde", + "serde_derive", + "wasmtime-internal-core", +] + +[[package]] +name = "cranelift-codegen" +version = "0.133.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "432246ee44b2fc0140b412dca55801d200d6fb25d2d7d18c44bb29e8cd71268b" +dependencies = [ + "bumpalo", + "cranelift-assembler-x64", + "cranelift-bforest", + "cranelift-bitset", + "cranelift-codegen-meta", + "cranelift-codegen-shared", + "cranelift-control", + "cranelift-entity", + "cranelift-isle", + "gimli", + "hashbrown 0.17.1", + "libm", + "log", + "postcard", + "pulley-interpreter", + "regalloc2", + "rustc-hash", + "serde", + "serde_derive", + "sha2", + "smallvec", + "target-lexicon", + "wasmtime-internal-core", +] + +[[package]] +name = "cranelift-codegen-meta" +version = "0.133.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aa51eff0949f06a5c8f3d5adefef94a12ea99f71cd8985047b91d45f367150" +dependencies = [ + "cranelift-assembler-x64-meta", + "cranelift-codegen-shared", + "cranelift-srcgen", + "heck", + "pulley-interpreter", +] + +[[package]] +name = "cranelift-codegen-shared" +version = "0.133.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6095e7095930b6169490138b4262fe7ec24290d3f604d7fe62e1e3138e740daa" + +[[package]] +name = "cranelift-control" +version = "0.133.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e61dfa0766c0eadf42b3febd145a35f81f31086e207f534e5fb406fc3d08fc47" +dependencies = [ + "arbitrary", +] + +[[package]] +name = "cranelift-entity" +version = "0.133.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e93867a79a06dd5d9ffeb96f7563dc7b6b142b5d89e42ab77e458a408a8aa9d5" +dependencies = [ + "cranelift-bitset", + "serde", + "serde_derive", + "wasmtime-internal-core", +] + +[[package]] +name = "cranelift-frontend" +version = "0.133.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1991dc32fefa54f14d2a63570d1e963826257605e478558733f83450b7e7661" +dependencies = [ + "cranelift-codegen", + "hashbrown 0.17.1", + "log", + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cranelift-isle" +version = "0.133.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784546de9988ff6e1df0fd4d2450760469a7607344156c661e69ec28082c5da4" + +[[package]] +name = "cranelift-native" +version = "0.133.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7107a4ae4a2ba48b5df8648365e638b08322fa1da11e86206bf5eddb862b21dd" +dependencies = [ + "cranelift-codegen", + "libc", + "target-lexicon", +] + +[[package]] +name = "cranelift-srcgen" +version = "0.133.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b3f161aa81ee5dd8d7b0eb8828988f57baf2f78d288e62b6b3714b37aa6d6a1" + +[[package]] +name = "crc32fast" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01a7799fd6b852db0e61728dde9a204c423b44d689dbd432522543614b490e78" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622f3fc73690be383c7214310406f28a90e6edeadc3cea882f9d71e495b9711a" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc74980687109a3b14c72fd458107bf0baa1da1a1a805e178d15501ba9b86d9d" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31eee39dddec8330830986fcd7625edb5a24ec90ea038215273bbc3adb08ac6" + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "debugid" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" +dependencies = [ + "uuid", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "directories-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339ee130d97a610ea5a5872d2bbb130fdf68884ff09d3028b81bec8a1ac23bbc" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "either" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e9c71c2167ca323c882b99918929403426e2373ea17242ff5653e0d5e1058be" + +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + +[[package]] +name = "encoding_rs" +version = "0.8.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e985e0451871ad22fb8d2b6b076e2028a502a0d3950998c2c5c0a4f9b5d9679" +dependencies = [ + "cfg-if", + "core_detect", + "multiversion_no_op", + "rustversion", + "scopeguard", + "simdutf8", +] + +[[package]] +name = "equivalent" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00d174d5400e5e8fd687ad1049e2f578285fa914201b1af7e8b112a4546bd826" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fastrand" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" + +[[package]] +name = "find-msvc-tools" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aedcfb3409746eddb02b9e19ebda1c3394f759a152e48ee875a0844d1b955484" + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "flate2" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e634e2e0ebac1ee034020da1ca582e17ffe4e0f5e985823721e168928136dcb" +dependencies = [ + "crc32fast", + "miniz_oxide", + "zlib-rs", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "futures" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a31d2a3fbaaeb2af2368bbdd904aa8e812d3c04a1ee10d3171f52d556e5d0a3" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" + +[[package]] +name = "futures-io" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed" + +[[package]] +name = "futures-sink" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1944426bf7d03f1d14f708785e4b33efd750b36d48a157b836b3efc15ede8e1d" + +[[package]] +name = "futures-task" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" + +[[package]] +name = "futures-util" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "slab", +] + +[[package]] +name = "fxprof-processed-profile" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25234f20a3ec0a962a61770cfe39ecf03cb529a6e474ad8cff025ed497eda557" +dependencies = [ + "bitflags", + "debugid", + "rustc-hash", + "serde", + "serde_derive", + "serde_json", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[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.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", +] + +[[package]] +name = "gimli" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf7f043f89559805f8c7cacc432749b2fa0d0a0a9ee46ce47164ed5ba7f126c" +dependencies = [ + "fnv", + "hashbrown 0.16.1", + "indexmap", + "stable_deref_trait", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "foldhash", + "serde", + "serde_core", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "indexmap" +version = "2.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855" +dependencies = [ + "equivalent", + "hashbrown 0.17.1", + "serde", + "serde_core", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "ittapi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b996fe614c41395cdaedf3cf408a9534851090959d90d54a535f675550b64b1" +dependencies = [ + "anyhow", + "ittapi-sys", + "log", +] + +[[package]] +name = "ittapi-sys" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52f5385394064fa2c886205dba02598013ce83d3e92d33dbdc0c52fe0e7bf4fc" +dependencies = [ + "cc", +] + +[[package]] +name = "jobserver" +version = "0.1.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3" +dependencies = [ + "getrandom 0.4.3", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7883d941dae510fb2d978fc3fe018c71c9e2892fd38854de3e8b92c2e5ad9cc5" +dependencies = [ + "cfg-if", + "futures-util", + "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.190" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce5d3ddc6d3fa000eb1536d85e147bfe31aacaba692ed6a876f95cb7c855be78" + +[[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.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61ff90caf6077a803a240f62fdbe88645a890bbca49ef8174c3cb0404362171d" +dependencies = [ + "libc", +] + +[[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.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" + +[[package]] +name = "mach2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dae608c151f68243f2b000364e1f7b186d9c29845f7d2d85bd31b9ad77ad552b" + +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "memfd" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57804b2c9b69967f1536a56f86297e367a33b19e98852ed624b84551cdbc0d90" +dependencies = [ + "rustix", +] + +[[package]] +name = "miniz_oxide" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63fbc4a50860e98e7b2aa7804ded1db5cbc3aff9193adaff57a6931bf7c4b4c" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "multiversion_no_op" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743fb55ba31b18fb1ecef6bdc9aa2743314978ac084044301a7eee33fb99a20d" + +[[package]] +name = "object" +version = "0.39.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e5a6c098c7a3b6547378093f5cc30bc54fd361ce711e05293a5cc589562739b" +dependencies = [ + "crc32fast", + "hashbrown 0.17.1", + "indexmap", + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[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.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548" + +[[package]] +name = "postcard" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" +dependencies = [ + "cobs", + "embedded-io 0.4.0", + "embedded-io 0.6.1", + "serde", +] + +[[package]] +name = "proc-macro2" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "pulley-interpreter" +version = "46.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f647f8aefd39efd5e38b484a8b7a926dd035ae366127df75c1d94d196f0a4ba" +dependencies = [ + "cranelift-bitset", + "log", + "pulley-macros", + "wasmtime-internal-core", +] + +[[package]] +name = "pulley-macros" +version = "46.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e902032e329008b189b67498b1be7784d5849276f32402eca17441df08a6bcb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "quote" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +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 = "rayon" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom 0.2.17", + "libredox", + "thiserror 1.0.69", +] + +[[package]] +name = "regalloc2" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "757712e8e61590d6d4f5d563483755538b5aa13467837a3b41cd9832509a7f85" +dependencies = [ + "allocator-api2", + "bumpalo", + "hashbrown 0.17.1", + "log", + "rustc-hash", + "serde", + "smallvec", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b74b56ffa8bb2830709a538c2cbcae9aa062db0d2a42563bfb09bdaae44020eb" + +[[package]] +name = "rustc-hash" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" + +[[package]] +name = "rustix" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891efababe418670775f199f0d233d84843c227a0949a883ce15b37c78d6629d" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "rustversion" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "serde" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.9", +] + +[[package]] +name = "serde_json" +version = "1.0.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7e9cc8b1b85264074fbcc02a88680c4096b1e47df8f739dceb03bf482f04bd6" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_spanned" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7523beb55eece201a2356bee0bbca0d1ab466c14c07703b2e0ee6d42cb0c2c" +dependencies = [ + "serde_core", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + +[[package]] +name = "shuttle-core" +version = "0.1.0" +dependencies = [ + "flate2", + "wasmparser 0.261.0", + "wasmtime", + "weave-core", + "weave-host", + "weave-transform", + "weave-wasmtime", +] + +[[package]] +name = "shuttle-runner" +version = "0.1.0" +dependencies = [ + "shuttle-core", +] + +[[package]] +name = "simd-adler32" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea" + +[[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.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b3dc8af474f516a851ff4bd12db780f948b9250ad37211e4eec0bccea54e01b" +dependencies = [ + "serde", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "syn" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d78c8dee4c7bf0e14673097256fed6142ce9d3b85a408189d07482442145823b" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "target-lexicon" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" + +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom 0.4.3", + "once_cell", + "rustix", + "windows-sys", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[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.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09e52cb86a36cede5cb101bf8908837b3e4c6e5e59fe7fd85c23fb56200d189e" +dependencies = [ + "thiserror-impl 2.0.21", +] + +[[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 2.0.119", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.9", +] + +[[package]] +name = "toml" +version = "0.9.12+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime", + "toml_parser", + "toml_writer", + "winnow 0.7.15", +] + +[[package]] +name = "toml_datetime" +version = "0.7.5+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_parser" +version = "1.1.5+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baa693a8032d7e1cada7d0041e96126df243179ff061456783ac7f12bda4744c" +dependencies = [ + "winnow 1.0.4", +] + +[[package]] +name = "toml_writer" +version = "1.1.3+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06bdbd8cfc056b8d2e2e85f29b56a3bdbecb527cef81eb39e3e7b98af4652770" + +[[package]] +name = "typenum" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + +[[package]] +name = "unicode-ident" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2c754d6c33795a1c324727428e5a7dedb5b06195f9890bdbcba760d3e246563" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "uuid" +version = "1.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cc1186384beb7dd8eedea376413fd654937285ea6c9cfbb928dc3043ea4b606" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.4+wasi-0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.129" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb54f33acc68fd454578d9820b0bde1a1a3d17aa17bb7b6595806d02886d409" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.129" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e29d0c35b16e224a7eeb5cd2d25e3e1968fbd65604117b44d3b789d00ee8535" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.129" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f501a8bc3719dba86ef8ae4728879c08001bea749eb1333ac5b91e040e2a6b7" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 3.0.9", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.129" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23f0c9c52aa7cd7d77769a4cfe2a9adb1b331f489a41d912ce14513d5ab995c6" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-compose" +version = "0.251.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b089037d7eb453ed57b560fe7833de0707411c8b9fdc429745ced77e2a1bacb9" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "log", + "petgraph", + "smallvec", + "wasm-encoder 0.251.0", + "wasmparser 0.251.0", + "wat", +] + +[[package]] +name = "wasm-encoder" +version = "0.251.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a879a421bd17c528b74721b2abf4c62e8f1d1889c2ba8c3c50d02deaf2ce395" +dependencies = [ + "leb128fmt", + "wasmparser 0.251.0", +] + +[[package]] +name = "wasm-encoder" +version = "0.261.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2608e8bb6d67fd68f5a8d0eb1363d6e7bcbc1f8ded5a0bd3a1e382462b876b22" +dependencies = [ + "leb128fmt", + "wasmparser 0.261.0", +] + +[[package]] +name = "wasm-encoder" +version = "0.262.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4495a6f85dd94c411c749303efcbc5defade0b0cbdbc0541495241ab917a9b5a" +dependencies = [ + "leb128fmt", + "wasmparser 0.262.0", +] + +[[package]] +name = "wasmparser" +version = "0.251.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "437970b35b1a85cfde9c74b2398352d8d653f3bd8e3a3db0c063ea8f5b4b36ff" +dependencies = [ + "bitflags", + "hashbrown 0.17.1", + "indexmap", + "semver", + "serde", +] + +[[package]] +name = "wasmparser" +version = "0.261.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f20f20e44f7e8aeb6744823ea9d869ede51e51be4fdaedede2852282e54d2d8" +dependencies = [ + "bitflags", + "hashbrown 0.17.1", + "indexmap", + "semver", + "serde", +] + +[[package]] +name = "wasmparser" +version = "0.262.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "974d643b125b272607e2fff8012ea14a8328acd7621e4bafa7afb32500052b1b" +dependencies = [ + "bitflags", + "indexmap", + "semver", +] + +[[package]] +name = "wasmprinter" +version = "0.251.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8798c1a699bd25648b6708eefe94d97c6f9891febb94b42cca1f7a4b086ea64e" +dependencies = [ + "anyhow", + "termcolor", + "wasmparser 0.251.0", +] + +[[package]] +name = "wasmtime" +version = "46.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d39226663bd765601279a79b88645a7c4a4d3c2fe73040afdc27bead02ee6659" +dependencies = [ + "addr2line", + "async-trait", + "bitflags", + "bumpalo", + "cc", + "cfg-if", + "encoding_rs", + "futures", + "fxprof-processed-profile", + "gimli", + "ittapi", + "libc", + "log", + "mach2", + "memfd", + "object", + "once_cell", + "postcard", + "pulley-interpreter", + "rayon", + "rustix", + "semver", + "serde", + "serde_derive", + "serde_json", + "smallvec", + "target-lexicon", + "tempfile", + "wasm-compose", + "wasm-encoder 0.251.0", + "wasmparser 0.251.0", + "wasmtime-environ", + "wasmtime-internal-cache", + "wasmtime-internal-component-macro", + "wasmtime-internal-component-util", + "wasmtime-internal-core", + "wasmtime-internal-cranelift", + "wasmtime-internal-fiber", + "wasmtime-internal-jit-debug", + "wasmtime-internal-jit-icache-coherence", + "wasmtime-internal-unwinder", + "wasmtime-internal-versioned-export-macros", + "wat", + "windows-sys", + "wit-parser", +] + +[[package]] +name = "wasmtime-environ" +version = "46.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2595a168541e8a7faeacf21e3d59da93628ee71468cd69fee9fc2a92c9b1c7d8" +dependencies = [ + "anyhow", + "cpp_demangle", + "cranelift-bforest", + "cranelift-bitset", + "cranelift-entity", + "gimli", + "hashbrown 0.17.1", + "indexmap", + "log", + "object", + "postcard", + "rustc-demangle", + "semver", + "serde", + "serde_derive", + "sha2", + "smallvec", + "target-lexicon", + "wasm-encoder 0.251.0", + "wasmparser 0.251.0", + "wasmprinter", + "wasmtime-internal-component-util", + "wasmtime-internal-core", +] + +[[package]] +name = "wasmtime-internal-cache" +version = "46.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a37d629957320219db11336663e0947e19afe77150403509cac21c47ead60c69" +dependencies = [ + "base64", + "directories-next", + "log", + "postcard", + "rustix", + "serde", + "serde_derive", + "sha2", + "toml", + "wasmtime-environ", + "windows-sys", + "zstd", +] + +[[package]] +name = "wasmtime-internal-component-macro" +version = "46.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9abf0fb4ce458eb6edbfaf6cbf13fcbf4216eac5a85febfe90224a1f6064c990" +dependencies = [ + "anyhow", + "proc-macro2", + "quote", + "syn 2.0.119", + "wasmtime-internal-component-util", + "wasmtime-internal-wit-bindgen", + "wit-parser", +] + +[[package]] +name = "wasmtime-internal-component-util" +version = "46.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e50df18c9a8e0deec353ad1e6364ef50538231719a12d80fa5dcb300be8d36b" + +[[package]] +name = "wasmtime-internal-core" +version = "46.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93b097389e5fad89c8ff8ee0aeafd16447b5a288d52aa1131f17ab4c19fd5be3" +dependencies = [ + "anyhow", + "hashbrown 0.17.1", + "libm", + "serde", +] + +[[package]] +name = "wasmtime-internal-cranelift" +version = "46.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08b3e909115836655b83c8bdef7c2e20a34293e785218d9f71a4e5382a09c6b0" +dependencies = [ + "cfg-if", + "cranelift-codegen", + "cranelift-control", + "cranelift-entity", + "cranelift-frontend", + "cranelift-native", + "gimli", + "itertools", + "log", + "object", + "pulley-interpreter", + "smallvec", + "target-lexicon", + "thiserror 2.0.21", + "wasmparser 0.251.0", + "wasmtime-environ", + "wasmtime-internal-core", + "wasmtime-internal-unwinder", + "wasmtime-internal-versioned-export-macros", +] + +[[package]] +name = "wasmtime-internal-fiber" +version = "46.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a000d1124dd40417ce8433d07de1063ecc9be7cac21745c8de7f9cf7684c3ead" +dependencies = [ + "cc", + "cfg-if", + "libc", + "rustix", + "wasmtime-environ", + "wasmtime-internal-versioned-export-macros", + "windows-sys", +] + +[[package]] +name = "wasmtime-internal-jit-debug" +version = "46.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7439956e78ba68e2cd766f34c3f056d625fad9a055eafb0c4569ac91c09e6b4" +dependencies = [ + "cc", + "object", + "rustix", + "wasmtime-internal-versioned-export-macros", +] + +[[package]] +name = "wasmtime-internal-jit-icache-coherence" +version = "46.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee3a381a9dd1ffe3893507733300b420605f465655d78c7a75a965a09d7b43d5" +dependencies = [ + "cfg-if", + "libc", + "wasmtime-internal-core", + "windows-sys", +] + +[[package]] +name = "wasmtime-internal-unwinder" +version = "46.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22f951f78a1a09001547838fa557522d56655385db97e47307d0f582ca866974" +dependencies = [ + "cfg-if", + "cranelift-codegen", + "log", + "object", + "wasmtime-environ", +] + +[[package]] +name = "wasmtime-internal-versioned-export-macros" +version = "46.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51e06f9fabbe647e5c2ed186e6920ab1fb48174688d7d3fdadbda537b8499b51" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "wasmtime-internal-wit-bindgen" +version = "46.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f49ac5121036c2255bdc203b1b75a1c04544744cd5f51c93240b58bddca9f0f1" +dependencies = [ + "anyhow", + "bitflags", + "heck", + "indexmap", + "wit-parser", +] + +[[package]] +name = "wast" +version = "262.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30612a0c29249b5f185888a107e8a519d920226b7d07f9d351fd094e9f75eb23" +dependencies = [ + "bumpalo", + "leb128fmt", + "memchr", + "unicode-width", + "wasm-encoder 0.262.0", +] + +[[package]] +name = "wat" +version = "1.262.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e228027f2b07bbaf946980ebbe2437fca73be6f54c40c2a8d4f42f277075f8d1" +dependencies = [ + "wast", +] + +[[package]] +name = "weave-core" +version = "0.1.0" +source = "git+https://github.com/akkiserver-dev/weave?rev=677cce64cf9728485849af21f7bf36f801175d4f#677cce64cf9728485849af21f7bf36f801175d4f" +dependencies = [ + "getrandom 0.3.4", + "serde", + "serde_json", + "wasmtime", +] + +[[package]] +name = "weave-host" +version = "0.1.0" +source = "git+https://github.com/akkiserver-dev/weave?rev=677cce64cf9728485849af21f7bf36f801175d4f#677cce64cf9728485849af21f7bf36f801175d4f" +dependencies = [ + "wasmtime", + "weave-core", +] + +[[package]] +name = "weave-transform" +version = "0.1.0" +source = "git+https://github.com/akkiserver-dev/weave?rev=677cce64cf9728485849af21f7bf36f801175d4f#677cce64cf9728485849af21f7bf36f801175d4f" +dependencies = [ + "wasm-encoder 0.261.0", + "wasmparser 0.261.0", + "wasmtime", + "weave-core", +] + +[[package]] +name = "weave-wasmtime" +version = "0.1.0" +source = "git+https://github.com/akkiserver-dev/weave?rev=677cce64cf9728485849af21f7bf36f801175d4f#677cce64cf9728485849af21f7bf36f801175d4f" +dependencies = [ + "wasmparser 0.261.0", + "wasmtime", + "weave-core", + "weave-host", + "weave-transform", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "winnow" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" + +[[package]] +name = "winnow" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "wit-parser" +version = "0.251.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e960732e824fab95099971a09e638979347c94ca48568d3c854c945729196947" +dependencies = [ + "anyhow", + "hashbrown 0.17.1", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser 0.251.0", +] + +[[package]] +name = "zlib-rs" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b268e58e7c693d7c271f93ffc4ba3b380412554231c85bf61ca7af91042a4112" + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" + +[[package]] +name = "zstd" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64d80649ab6db9d9f6f9c80a40becd948eda4714a0a5ac8c4d157a32231c7882" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.1.1+zstd.1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aeec9eaf2dffbbd09201e23bd0ffcbaa33bb8e9266a10734fd7ed90a85eca078" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/native/Cargo.toml b/native/Cargo.toml new file mode 100644 index 0000000..460739b --- /dev/null +++ b/native/Cargo.toml @@ -0,0 +1,24 @@ +[workspace] +resolver = "2" +members = ["crates/shuttle-core", "crates/shuttle-runner"] + +[workspace.package] +version = "0.1.0" +edition = "2024" +license = "Apache-2.0" + +[workspace.dependencies] +wasmtime = { version = "46", default-features = false, features = ["cranelift", "runtime", "gc", "gc-drc", "threads", "parallel-compilation"] } +weave-core = { git = "https://github.com/akkiserver-dev/weave", rev = "677cce64cf9728485849af21f7bf36f801175d4f" } +weave-transform = { git = "https://github.com/akkiserver-dev/weave", rev = "677cce64cf9728485849af21f7bf36f801175d4f" } +weave-host = { git = "https://github.com/akkiserver-dev/weave", rev = "677cce64cf9728485849af21f7bf36f801175d4f" } +weave-wasmtime = { git = "https://github.com/akkiserver-dev/weave", rev = "677cce64cf9728485849af21f7bf36f801175d4f" } +flate2 = "1" +shuttle-core = { path = "crates/shuttle-core" } + +[profile.dev] +opt-level = 1 +debug = 0 + +[profile.dev.package."*"] +opt-level = 2 diff --git a/native/README.md b/native/README.md new file mode 100644 index 0000000..66e25c4 --- /dev/null +++ b/native/README.md @@ -0,0 +1,92 @@ +# Shuttle (prototype) + +Native core of the Shuttle computer mod: runs Wasm guests (BIOS → OS kernel → +child programs) on Wasmtime 46, makes them checkpointable with Weave, and +implements the firmware ABI draft 0.1 (`fw.*`, `co.*`, `sys.call`). +Nothing here depends on Minecraft or Java yet. + +## Layout + +``` +crates/shuttle-core the engine: image cache, Machine, ABI host functions, snapshot format +crates/shuttle-runner headless emulator (run / verify) +guests/shuttle.h ABI header for C guests (freestanding wasm32) +guests/bios.c finds a bootable disk, image_load, exec +guests/os.c loads a program from the other disk, runs it as a child, serves sys.call +guests/child.c user program: Hello, 5 rounds of deep-recursive work, sleep, exit(42) +``` + +Weave comes from `akkiserver-dev/weave`, branch `shuttle-host-hooks` +(commit `677cce6`), which adds two embedding hooks on top of the Wasmtime 46 +update: + +- **yielding imports** (`TransformOptions::yielding_imports` + + `weave_wasmtime::request_unwind`): a host function can suspend the guest from + inside the call; on resume the call runs again and returns the result. +- **memory limits** (`WeaveInstance::set_memory_limit`, `Ctx::set_memory_limit`): + a Wasmtime `StoreLimits` limiter, so `memory.grow` past the cap returns -1. + +## Build and run + +```sh +sh guests/build.sh # run inside native/; needs clang + wasm-ld (no wasi-sdk needed) +cargo build +./target/debug/shuttle-runner run guests/out/bios.wasm guests/out/os.wasm guests/out/child.wasm +./target/debug/shuttle-runner verify guests/out/bios.wasm guests/out/os.wasm guests/out/child.wasm +``` + +`run` boots and prints the log until power-off. `verify` runs once without +interruption, then once per tick boundary with capture → restore into a +brand-new Machine → continue, and compares the log streams. A control run +drops the host-side child table on restore and must diverge. + +## Results (2026-10-15, Linux x86_64, 2 cores, dev profile) + +| Check | Result | +| --- | --- | +| Boot chain BIOS → `exec` → OS → `co_create` → child | works, 27 ticks to power-off | +| Restore at every tick boundary (1–26) | 26/26 identical logs | +| Control: child table dropped on restore | 24/24 diverged (the check is real) | +| Snapshot size (whole machine, gzip) | 5.2–7.7 KB | +| Module without `shuttle.abi` | rejected with `E_VERSION` (-8) | +| SIMD module on a CPU without `simd` | rejected with `E_UNSUPPORTED` (-7) | +| `co_create` reserving more than the CPU's memory | `E_NOMEM` (-6) | +| Child `memory.grow` past its `mem_limit` | returns -1, child keeps running | +| `dev_call` result larger than `rcap` | size returned, result fetched once with `dev_result(-1)` | + +Restore points cover the child in the middle of a 32-deep recursive +computation, the kernel halted in `hlt` (child sleeping), and a pending +`sys.call` waiting for its return value. + +## Implemented vs. the ABI draft + +Implemented: `cpuid` (string and numeric leaves), `hlt`, `yield`, `time`, +`log` (rate-limited), `shutdown`, `reboot`, `dev_slots`, `dev_info`, +`dev_describe` (empty), `dev_call`, `dev_submit`/`dev_result` (completed at +the next tick start, `COMPLETE` event), `poll_event` (with `OVERFLOW`), +`image_load` (ABI + feature check, cached by hash), `image_free`, `exec`, +`boot_args`, all `co_*`, `sys.call`. + +Resolved since the first prototype: + +1. **Exit-type calls are plain imports.** `hlt`, `yield`, `exec`, + `shutdown`, `reboot` and `sys.call` are Weave yielding imports: the first + call records the request and unwinds; on resume the call is executed again + and returns the result (`fw.hlt` returns 1/0, `sys.call` returns the + kernel's `retval`). Children import only `sys.call`, as the ABI says. +2. **Memory limits are enforced.** Each child's linear memory (including + Weave's shadow stack) is capped at its `mem_limit`. The kernel may grow + into whatever the children have not reserved; `co_create` fails with + `E_NOMEM` if kernel memory + reservations + the new limit exceed the CPU. +3. **`dev_call` keeps results that do not fit.** It returns the needed size, + and the result is held (one slot, replaced by the next `dev_call`) until + it is fetched with `dev_result(-1, ret, rcap)`. + +Other notes: `poll_event` reports `OVERFLOW` first when events were dropped; +queued `dev_submit` requests are saved in snapshots and run after restore. + +## Next steps + +- JNI layer in wasmtime-ng exposing `ShuttleEngine` / `Machine` (`tick`, + `capture`, `restore`, `Device.invoke` callback). +- Measure with a real OS-sized module (transform/compile time, disk cache). diff --git a/native/crates/shuttle-core/Cargo.toml b/native/crates/shuttle-core/Cargo.toml new file mode 100644 index 0000000..d274a78 --- /dev/null +++ b/native/crates/shuttle-core/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "shuttle-core" +version.workspace = true +edition.workspace = true +license.workspace = true + +[dependencies] +wasmtime.workspace = true +weave-core.workspace = true +weave-transform.workspace = true +weave-wasmtime.workspace = true +weave-host.workspace = true +flate2.workspace = true +wasmparser = "0.261.0" diff --git a/native/crates/shuttle-core/src/abi.rs b/native/crates/shuttle-core/src/abi.rs new file mode 100644 index 0000000..306f8d6 --- /dev/null +++ b/native/crates/shuttle-core/src/abi.rs @@ -0,0 +1,109 @@ +//! Constants of the firmware ABI draft 0.1 and load-time checks. + +use crate::CpuSpec; +use wasmparser::{Parser, Payload, Validator, WasmFeatures}; + +pub const ABI_MAJOR: u32 = 0; +pub const ABI_MINOR: u32 = 1; +pub const ABI_SECTION: &str = "shuttle.abi"; + +/// Imports that stop the guest. Weave turns their call sites into unwind +/// points; on resume the call runs again and returns the result. +pub const YIELDING_IMPORTS: &[(&str, &str)] = &[ + ("fw", "hlt"), + ("fw", "yield"), + ("fw", "exec"), + ("fw", "shutdown"), + ("fw", "reboot"), + ("sys", "call"), +]; + +/// `dev_result` ticket that fetches a synchronous `dev_call` result which +/// did not fit the caller's buffer. +pub const HELD_RESULT: i32 = -1; + +pub const E_INVAL: i32 = -1; +pub const E_FAULT: i32 = -2; +pub const E_NODEV: i32 = -3; +pub const E_NOMETHOD: i32 = -4; +pub const E_BADHANDLE: i32 = -5; +pub const E_NOMEM: i32 = -6; +pub const E_UNSUPPORTED: i32 = -7; +pub const E_VERSION: i32 = -8; +pub const E_AGAIN: i32 = -9; +pub const E_NOPOWER: i32 = -10; +pub const E_IO: i32 = -11; + +pub const CO_YIELD: i32 = 0; +pub const CO_CALL: i32 = 1; +pub const CO_DONE: i32 = 2; +pub const CO_DEAD: i32 = 3; + +pub const STATUS_SUSPENDED: i32 = 0; +pub const STATUS_DONE: i32 = 1; +pub const STATUS_DEAD: i32 = 2; + +pub const EV_ATTACH: u16 = 1; +pub const EV_DETACH: u16 = 2; +pub const EV_COMPLETE: u16 = 3; +pub const EV_SIGNAL: u16 = 4; +pub const EV_POWER: u16 = 5; +pub const EV_OVERFLOW: u16 = 6; + +pub const EVENT_QUEUE_MAX: usize = 256; +pub const EXEC_ARGS_MAX: usize = 4096; +pub const ASYNC_MAX: usize = 16; +pub const CPUID_STR_MAX: usize = 64; +pub const LOG_LINES_PER_TICK: usize = 64; +pub const LOG_LINE_MAX: usize = 1024; + +/// The `shuttle.abi` custom section must exist and be compatible. +pub fn check_abi_section(raw: &[u8]) -> Result<(), i32> { + let mut found = None; + for payload in Parser::new(0).parse_all(raw) { + match payload.map_err(|_| E_INVAL)? { + Payload::CustomSection(c) if c.name() == ABI_SECTION => { + let d = c.data(); + if d.len() != 8 { + return Err(E_VERSION); + } + let major = u32::from_le_bytes(d[0..4].try_into().unwrap()); + let minor = u32::from_le_bytes(d[4..8].try_into().unwrap()); + found = Some((major, minor)); + } + _ => {} + } + } + match found { + Some((ABI_MAJOR, minor)) if minor <= ABI_MINOR => Ok(()), + _ => Err(E_VERSION), + } +} + +/// Reject modules that use Wasm features the CPU does not have. +pub fn check_features(raw: &[u8], cpu: &CpuSpec) -> Result<(), i32> { + // Always available: the MVP plus the small extensions every toolchain emits. + let mut f = WasmFeatures::MUTABLE_GLOBAL + | WasmFeatures::SIGN_EXTENSION + | WasmFeatures::SATURATING_FLOAT_TO_INT + | WasmFeatures::MULTI_VALUE + | WasmFeatures::FLOATS; + if cpu.has_feature("bulk-memory") { + f |= WasmFeatures::BULK_MEMORY | WasmFeatures::REFERENCE_TYPES; + } + if cpu.has_feature("simd") { + f |= WasmFeatures::SIMD; + } + if Validator::new_with_features(f).validate_all(raw).is_ok() { + return Ok(()); + } + // Distinguish "uses a feature this CPU lacks" from "not valid at all". + if Validator::new_with_features(WasmFeatures::default()) + .validate_all(raw) + .is_ok() + { + Err(E_UNSUPPORTED) + } else { + Err(E_INVAL) + } +} diff --git a/native/crates/shuttle-core/src/codec.rs b/native/crates/shuttle-core/src/codec.rs new file mode 100644 index 0000000..dc2f972 --- /dev/null +++ b/native/crates/shuttle-core/src/codec.rs @@ -0,0 +1,373 @@ +//! Machine snapshot format (gzip-compressed, versioned). +//! +//! Layout (all integers little-endian), before compression: +//! magic "SHTL", u16 format +//! cpu: vendor, model, arch, features (str), clock u64, max_memory u64 +//! tick u64, state u8 (+ u64 until / str message), +//! exit_reply (opt i64), held_result (opt bytes) +//! boot_args bytes, dropped_events u32, events [bytes] +//! next_ticket i32, async results [(ticket i32, ok u8, bytes|code)], +//! async queue [(ticket, slot, method, args)] +//! image store [(hash, raw bytes)] -- every image referenced below +//! eeprom hash, kernel image (opt hash), kernel snapshot (opt bytes) +//! image table [opt hash] +//! children [opt (hash, status i32, mem_limit i64, pending call, reply, snapshot)] +//! +//! Device state is not included: the embedder saves it (Device.save on the +//! Java side). Queued `dev_submit` requests are saved and run after restore. + +use crate::imports; +use crate::machine::{ + AsyncReq, ChildCtl, Child, KernelCtl, Machine, MachineState, kernel_ctl_slot, +}; +use crate::{CpuSpec, Device, Image, ShuttleEngine}; +use flate2::Compression; +use flate2::read::GzDecoder; +use flate2::write::GzEncoder; +use std::collections::{BTreeMap, VecDeque}; +use std::io::{Read, Write}; +use std::sync::Arc; +use wasmtime::error::{bail, format_err, Result}; +use weave_core::snapshot::Snapshot; +use weave_wasmtime::WeaveInstance; + +const MAGIC: &[u8; 4] = b"SHTL"; +const FORMAT: u16 = 2; + +struct W(Vec); +impl W { + fn u8(&mut self, v: u8) { self.0.push(v); } + fn u16(&mut self, v: u16) { self.0.extend_from_slice(&v.to_le_bytes()); } + fn u32(&mut self, v: u32) { self.0.extend_from_slice(&v.to_le_bytes()); } + fn u64(&mut self, v: u64) { self.0.extend_from_slice(&v.to_le_bytes()); } + fn i32(&mut self, v: i32) { self.0.extend_from_slice(&v.to_le_bytes()); } + fn i64(&mut self, v: i64) { self.0.extend_from_slice(&v.to_le_bytes()); } + fn bytes(&mut self, b: &[u8]) { self.u32(b.len() as u32); self.0.extend_from_slice(b); } + fn str(&mut self, s: &str) { self.bytes(s.as_bytes()); } + fn hash(&mut self, h: &[u8; 32]) { self.0.extend_from_slice(h); } +} + +struct R<'a>(&'a [u8]); +impl<'a> R<'a> { + fn take(&mut self, n: usize) -> Result<&'a [u8]> { + if self.0.len() < n { + bail!("snapshot truncated"); + } + let (a, b) = self.0.split_at(n); + self.0 = b; + Ok(a) + } + fn u8(&mut self) -> Result { Ok(self.take(1)?[0]) } + fn u16(&mut self) -> Result { Ok(u16::from_le_bytes(self.take(2)?.try_into()?)) } + fn u32(&mut self) -> Result { Ok(u32::from_le_bytes(self.take(4)?.try_into()?)) } + fn u64(&mut self) -> Result { Ok(u64::from_le_bytes(self.take(8)?.try_into()?)) } + fn i32(&mut self) -> Result { Ok(i32::from_le_bytes(self.take(4)?.try_into()?)) } + fn i64(&mut self) -> Result { Ok(i64::from_le_bytes(self.take(8)?.try_into()?)) } + fn bytes(&mut self) -> Result> { let n = self.u32()? as usize; Ok(self.take(n)?.to_vec()) } + fn str(&mut self) -> Result { Ok(String::from_utf8(self.bytes()?)?) } + fn hash(&mut self) -> Result<[u8; 32]> { Ok(self.take(32)?.try_into()?) } +} + +impl Machine { + /// Capture the whole computer at a tick boundary as gzip bytes + /// (fits an NBT ByteArrayTag). + pub fn capture(&mut self) -> Result> { + let eeprom = self.eeprom.clone(); + let kernel_image = self.kernel_image.clone(); + let state = self.state.clone(); + let kernel_snap = match self.kernel.as_mut() { + Some(k) => Some(k.checkpoint()?.encode()), + None => None, + }; + let ctl = self.ctl(); + + // Every image the machine refers to, deduplicated by hash. + let mut store: BTreeMap<[u8; 32], Arc> = BTreeMap::new(); + store.insert(eeprom.hash, eeprom.clone()); + if let Some(k) = &kernel_image { + store.insert(k.hash, k.clone()); + } + for img in ctl.images.iter().flatten() { + store.insert(img.hash, img.clone()); + } + for ch in ctl.children.iter().flatten() { + store.insert(ch.image.hash, ch.image.clone()); + } + + let mut w = W(Vec::new()); + w.0.extend_from_slice(MAGIC); + w.u16(FORMAT); + w.str(&ctl.cpu.vendor); + w.str(&ctl.cpu.model); + w.str(&ctl.cpu.arch); + w.str(&ctl.cpu.features); + w.u64(ctl.cpu.clock); + w.u64(ctl.cpu.max_memory); + w.u64(ctl.tick); + match &state { + MachineState::Running => w.u8(0), + MachineState::Halted { until } => { w.u8(1); w.u64(*until); } + MachineState::Off => w.u8(2), + MachineState::Crashed(m) => { w.u8(3); w.str(m); } + } + match ctl.exit_reply { + Some(v) => { w.u8(1); w.i64(v); } + None => w.u8(0), + } + match &ctl.held_result { + Some(b) => { w.u8(1); w.bytes(b); } + None => w.u8(0), + } + w.bytes(&ctl.boot_args); + w.u32(ctl.dropped_events); + w.u32(ctl.events.len() as u32); + for e in &ctl.events { + w.bytes(e); + } + w.i32(ctl.next_ticket); + w.u32(ctl.async_results.len() as u32); + for (t, r) in &ctl.async_results { + w.i32(*t); + match r { + Ok(b) => { w.u8(1); w.bytes(b); } + Err(c) => { w.u8(0); w.i32(*c); } + } + } + w.u32(ctl.async_queue.len() as u32); + for q in &ctl.async_queue { + w.i32(q.ticket); + w.i32(q.slot); + w.i32(q.method); + w.bytes(&q.args); + } + w.u32(store.len() as u32); + for (h, img) in &store { + w.hash(h); + w.bytes(&img.raw); + } + w.hash(&eeprom.hash); + match (&kernel_image, &kernel_snap) { + (Some(img), Some(snap)) => { w.u8(1); w.hash(&img.hash); w.bytes(snap); } + _ => w.u8(0), + } + w.u32(ctl.images.len() as u32); + for img in &ctl.images { + match img { + Some(i) => { w.u8(1); w.hash(&i.hash); } + None => w.u8(0), + } + } + let n_children = ctl.children.len(); + w.u32(n_children as u32); + for i in 0..n_children { + let ctl = self.ctl(); + let ch = match ctl.children[i].as_mut() { + Some(ch) => ch, + None => { w.u8(0); continue; } + }; + w.u8(1); + w.hash(&ch.image.hash); + w.i32(ch.status); + w.i64(ch.mem_limit); + match ch.inst.as_mut() { + Some(inst) => { + let (call, reply) = { + let cc = inst.ctx_mut().service_state::(0); + (cc.pending_call, cc.reply) + }; + match call { + Some((no, a)) => { + w.u8(1); + w.i32(no); + for v in a { w.i64(v); } + } + None => w.u8(0), + } + match reply { + Some(v) => { w.u8(1); w.i64(v); } + None => w.u8(0), + } + w.u8(1); + w.bytes(&inst.checkpoint()?.encode()); + } + None => { + w.u8(0); // no pending call + w.u8(0); // no reply + w.u8(0); // no instance + } + } + } + + let mut gz = GzEncoder::new(Vec::new(), Compression::default()); + gz.write_all(&w.0)?; + Ok(gz.finish()?) + } + + /// Rebuild a computer from [`Machine::capture`] output. Devices are + /// supplied again by the embedder, in the same slot order. + pub fn restore( + engine: &Arc, + bytes: &[u8], + devices: Vec>, + ) -> Result { + let mut raw = Vec::new(); + GzDecoder::new(bytes).read_to_end(&mut raw)?; + let mut r = R(&raw); + if r.take(4)? != MAGIC { + bail!("not a Shuttle snapshot"); + } + let format = r.u16()?; + if format != FORMAT { + bail!("unsupported snapshot format {format}"); + } + let cpu = CpuSpec { + vendor: r.str()?, + model: r.str()?, + arch: r.str()?, + features: r.str()?, + clock: r.u64()?, + max_memory: r.u64()?, + }; + let tick = r.u64()?; + let state = match r.u8()? { + 0 => MachineState::Running, + 1 => MachineState::Halted { until: r.u64()? }, + 2 => MachineState::Off, + 3 => MachineState::Crashed(r.str()?), + s => bail!("bad machine state {s}"), + }; + let exit_reply = if r.u8()? == 1 { Some(r.i64()?) } else { None }; + let held_result = if r.u8()? == 1 { Some(r.bytes()?) } else { None }; + let boot_args = r.bytes()?; + let dropped_events = r.u32()?; + let mut events = VecDeque::new(); + for _ in 0..r.u32()? { + events.push_back(r.bytes()?); + } + let next_ticket = r.i32()?; + let mut async_results = BTreeMap::new(); + for _ in 0..r.u32()? { + let t = r.i32()?; + let v = if r.u8()? == 1 { Ok(r.bytes()?) } else { Err(r.i32()?) }; + async_results.insert(t, v); + } + let mut async_queue = Vec::new(); + for _ in 0..r.u32()? { + async_queue.push(AsyncReq { + ticket: r.i32()?, + slot: r.i32()?, + method: r.i32()?, + args: r.bytes()?, + }); + } + let mut store: BTreeMap<[u8; 32], Arc> = BTreeMap::new(); + for _ in 0..r.u32()? { + let h = r.hash()?; + let bytes = r.bytes()?; + let img = engine + .load_unchecked(&bytes) + .map_err(|c| format_err!("image failed to load on restore ({c})"))?; + if img.hash != h { + bail!("image hash mismatch in snapshot"); + } + store.insert(h, img); + } + let get = |h: &[u8; 32]| store.get(h).cloned().ok_or_else(|| format_err!("snapshot refers to a missing image")); + let eeprom = get(&r.hash()?)?; + let kernel_part = if r.u8()? == 1 { + Some((get(&r.hash()?)?, r.bytes()?)) + } else { + None + }; + let mut images = Vec::new(); + for _ in 0..r.u32()? { + images.push(if r.u8()? == 1 { Some(get(&r.hash()?)?) } else { None }); + } + + let mut ctl = Box::new(KernelCtl { + engine: engine.clone(), + cpu, + devices: devices.into_iter().map(Some).collect(), + images, + children: Vec::new(), + events, + dropped_events, + tick, + logs: Vec::new(), + log_lines_this_tick: 0, + exit: None, + exit_reply, + held_result, + boot_args, + next_ticket, + async_queue, + async_results, + }); + + for _ in 0..r.u32()? { + if r.u8()? == 0 { + ctl.children.push(None); + continue; + } + let image = get(&r.hash()?)?; + let status = r.i32()?; + let mem_limit = r.i64()?; + let pending_call = if r.u8()? == 1 { + let no = r.i32()?; + let mut a = [0i64; 4]; + for v in &mut a { + *v = r.i64()?; + } + Some((no, a)) + } else { + None + }; + let reply = if r.u8()? == 1 { Some(r.i64()?) } else { None }; + let inst = if r.u8()? == 1 { + let snap = Snapshot::decode(&r.bytes()?)?; + let mut inst = WeaveInstance::new_restored( + &engine.engine, + &image.module, + vec![], + vec![Box::new(ChildCtl { pending_call, reply })], + imports::child_linker(), + )?; + inst.restore(&snap)?; + inst.set_memory_limit(Some(mem_limit as usize)); + Some(inst) + } else { + None + }; + ctl.children.push(Some(Child { image, inst, status, mem_limit })); + } + if !r.0.is_empty() { + bail!("trailing bytes in snapshot"); + } + + let (kernel, kernel_image, spare_ctl) = match kernel_part { + Some((image, snap)) => { + let snap = Snapshot::decode(&snap)?; + let mut inst = WeaveInstance::new_restored( + &engine.engine, + &image.module, + vec![], + vec![Box::new(Some(ctl))], + imports::kernel_linker(), + )?; + inst.restore(&snap)?; + let ctl = kernel_ctl_slot(&mut inst).as_ref().expect("kernel ctl"); + let free = (ctl.cpu.max_memory as i64 - ctl.memory_in_use()).max(0) as usize; + inst.set_memory_limit(Some(free)); + (Some(inst), Some(image), None) + } + None => (None, None, Some(ctl)), + }; + Ok(Machine { + eeprom, + kernel, + kernel_image, + spare_ctl, + state, + }) + } +} diff --git a/native/crates/shuttle-core/src/imports.rs b/native/crates/shuttle-core/src/imports.rs new file mode 100644 index 0000000..7d278cb --- /dev/null +++ b/native/crates/shuttle-core/src/imports.rs @@ -0,0 +1,597 @@ +//! Host functions of the firmware ABI: `fw.*` and `co.*` for the top level, +//! `sys.call` for children. +//! +//! Calls that stop the guest (hlt, yield, exec, shutdown, reboot, sys.call) +//! are Weave *yielding imports*: the first call records the request and asks +//! Weave to unwind right after it returns. When the guest is resumed, Weave +//! runs the same call again; that second call returns the result (the +//! `*_reply` fields) without stopping. + +use crate::abi::*; +use crate::machine::{AsyncReq, Child, ChildCtl, Exit, KernelCtl}; +use wasmtime::{Caller, Linker, Memory}; +use weave_core::names; +use weave_host::MemRead; +use weave_wasmtime::{request_unwind, Ctx, LinkFn, Poller, WeaveInstance, WorkResult}; + +type C<'a> = Caller<'a, Ctx>; + +fn ctl<'a>(caller: &'a mut C<'_>) -> &'a mut KernelCtl { + caller + .data_mut() + .service_state::>>(0) + .as_mut() + .expect("top-level instance without ctl") +} + +fn memory(caller: &mut C<'_>) -> Option { + caller.get_export("memory").and_then(|e| e.into_memory()) +} + +fn read_bytes(caller: &mut C<'_>, ptr: i32, len: i32) -> Result, i32> { + if len < 0 { + return Err(E_INVAL); + } + let mem = memory(caller).ok_or(E_FAULT)?; + let data = mem.data(&caller); + let start = ptr as u32 as usize; + let end = start.checked_add(len as usize).ok_or(E_FAULT)?; + data.get(start..end).map(|s| s.to_vec()).ok_or(E_FAULT) +} + +fn write_bytes(caller: &mut C<'_>, ptr: i32, bytes: &[u8]) -> Result<(), i32> { + let mem = memory(caller).ok_or(E_FAULT)?; + let data = mem.data_mut(&mut *caller); + let start = ptr as u32 as usize; + let end = start.checked_add(bytes.len()).ok_or(E_FAULT)?; + data.get_mut(start..end).ok_or(E_FAULT)?.copy_from_slice(bytes); + Ok(()) +} + +/// The variable-length output rule: write only if it fits; always return the +/// size needed. +fn write_out(caller: &mut C<'_>, out: i32, cap: i32, bytes: &[u8]) -> i32 { + if cap < 0 { + return E_INVAL; + } + if bytes.len() <= cap as usize { + if let Err(e) = write_bytes(caller, out, bytes) { + return e; + } + } + bytes.len() as i32 +} + +/// Make the guest unwind as soon as the current (yielding) import returns. +fn request_exit(caller: &mut C<'_>) { + // Only fails during module initialization, where no exit can be served; + // the call then simply returns its placeholder. + let _ = request_unwind(caller); +} + +fn err_code(r: Result) -> i32 { + match r { + Ok(v) => v, + Err(e) => e, + } +} + +// --------------------------------------------------------------------------- + +pub(crate) fn kernel_linker() -> LinkFn { + Box::new(|linker: &mut Linker| { + link_fw_cpu(linker)?; + link_fw_dev(linker)?; + link_fw_image(linker)?; + link_co(linker)?; + Ok(()) + }) +} + +pub(crate) fn child_linker() -> LinkFn { + Box::new(|linker: &mut Linker| { + linker.func_wrap( + "sys", + "call", + |mut caller: C<'_>, no: i32, a0: i64, a1: i64, a2: i64, a3: i64| -> i64 { + let cc = caller.data_mut().service_state::(0); + if let Some(v) = cc.reply.take() { + return v; // re-executed after resume: deliver the result + } + cc.pending_call = Some((no, [a0, a1, a2, a3])); + request_exit(&mut caller); + 0 + }, + )?; + Ok(()) + }) +} + +fn link_fw_cpu(linker: &mut Linker) -> wasmtime::Result<()> { + linker.func_wrap("fw", "cpuid", |mut caller: C<'_>, leaf: i32, out: i32, cap: i32| -> i32 { + let cpu = ctl(&mut caller).cpu.clone(); + let bytes: Vec = match leaf { + 0 => cpu.vendor.into_bytes(), + 1 => cpu.model.into_bytes(), + 2 => cpu.arch.into_bytes(), + 3 => cpu.features.into_bytes(), + 0x100 => cpu.clock.to_le_bytes().to_vec(), + 0x101 => cpu.max_memory.to_le_bytes().to_vec(), + _ => return E_INVAL, + }; + let mut bytes = bytes; + bytes.truncate(CPUID_STR_MAX); + write_out(&mut caller, out, cap, &bytes) + })?; + linker.func_wrap("fw", "time", |mut caller: C<'_>| -> i64 { ctl(&mut caller).tick as i64 })?; + linker.func_wrap("fw", "log", |mut caller: C<'_>, ptr: i32, len: i32| { + let len = len.min(LOG_LINE_MAX as i32); + if let Ok(bytes) = read_bytes(&mut caller, ptr, len) { + let text = String::from_utf8_lossy(&bytes).into_owned(); + ctl(&mut caller).log(text); + } + })?; + linker.func_wrap("fw", "hlt", |mut caller: C<'_>, timeout: i64| -> i32 { + let c = ctl(&mut caller); + if let Some(v) = c.exit_reply.take() { + return v as i32; // woken up: 1 = event, 0 = timeout + } + if !c.events.is_empty() { + return 1; // an event is already waiting: do not stop + } + c.exit = Some(Exit::Hlt(timeout)); + request_exit(&mut caller); + 0 + })?; + linker.func_wrap("fw", "yield", |mut caller: C<'_>| { + let c = ctl(&mut caller); + if c.exit_reply.take().is_some() { + return; + } + c.exit = Some(Exit::Yield); + request_exit(&mut caller); + })?; + linker.func_wrap("fw", "shutdown", |mut caller: C<'_>| { + ctl(&mut caller).exit = Some(Exit::Shutdown); + request_exit(&mut caller); + })?; + linker.func_wrap("fw", "reboot", |mut caller: C<'_>| { + ctl(&mut caller).exit = Some(Exit::Reboot); + request_exit(&mut caller); + })?; + Ok(()) +} + +fn link_fw_dev(linker: &mut Linker) -> wasmtime::Result<()> { + linker.func_wrap("fw", "dev_slots", |mut caller: C<'_>| -> i32 { + ctl(&mut caller).devices.len() as i32 + })?; + linker.func_wrap("fw", "dev_info", |mut caller: C<'_>, slot: i32, out: i32, cap: i32| -> i32 { + let info = match ctl(&mut caller).devices.get(slot as usize).and_then(Option::as_ref) { + Some(d) => d.info(), + None => return E_NODEV, + }; + let mut b = Vec::with_capacity(24); + b.extend_from_slice(&info.class.to_le_bytes()); + b.extend_from_slice(&info.vendor.to_le_bytes()); + b.extend_from_slice(&info.device.to_le_bytes()); + b.extend_from_slice(&info.flags.to_le_bytes()); + b.extend_from_slice(&info.address); + write_out(&mut caller, out, cap, &b) + })?; + linker.func_wrap("fw", "dev_describe", |mut caller: C<'_>, slot: i32, out: i32, cap: i32| -> i32 { + let desc = match ctl(&mut caller).devices.get(slot as usize).and_then(Option::as_ref) { + Some(d) => d.describe(), + None => return E_NODEV, + }; + write_out(&mut caller, out, cap, &desc) + })?; + linker.func_wrap( + "fw", + "dev_call", + |mut caller: C<'_>, slot: i32, method: i32, args: i32, alen: i32, ret: i32, rcap: i32| -> i32 { + let args = match read_bytes(&mut caller, args, alen) { + Ok(a) => a, + Err(e) => return e, + }; + let result = match ctl(&mut caller).devices.get_mut(slot as usize).and_then(Option::as_mut) { + Some(d) => d.call(method, &args), + None => return E_NODEV, + }; + match result { + Ok(bytes) => { + // The device has already run: a result that does not fit is + // kept for dev_result(-1) instead of being thrown away. + let n = write_out(&mut caller, ret, rcap, &bytes); + let fits = n >= 0 && (n as usize) <= rcap.max(0) as usize; + ctl(&mut caller).held_result = if fits || n < 0 { None } else { Some(bytes) }; + n + } + Err(e) => { + ctl(&mut caller).held_result = None; + e + } + } + }, + )?; + linker.func_wrap( + "fw", + "dev_submit", + |mut caller: C<'_>, slot: i32, method: i32, args: i32, alen: i32| -> i32 { + let args = match read_bytes(&mut caller, args, alen) { + Ok(a) => a, + Err(e) => return e, + }; + let c = ctl(&mut caller); + if c.devices.get(slot as usize).and_then(Option::as_ref).is_none() { + return E_NODEV; + } + if c.async_queue.len() + c.async_results.len() >= ASYNC_MAX { + return E_AGAIN; + } + let ticket = c.next_ticket; + c.next_ticket = c.next_ticket.wrapping_add(1) & 0x7fff_ffff; + c.async_queue.push(AsyncReq { ticket, slot, method, args }); + ticket + }, + )?; + linker.func_wrap("fw", "dev_result", |mut caller: C<'_>, ticket: i32, ret: i32, rcap: i32| -> i32 { + if ticket == HELD_RESULT { + let held = match ctl(&mut caller).held_result.clone() { + Some(b) => b, + None => return E_BADHANDLE, + }; + let n = write_out(&mut caller, ret, rcap, &held); + if n >= 0 && (n as usize) <= rcap.max(0) as usize { + ctl(&mut caller).held_result = None; + } + return n; + } + let result = match ctl(&mut caller).async_results.get(&ticket) { + Some(r) => r.clone(), + None => return E_BADHANDLE, + }; + match result { + Ok(bytes) => { + let n = write_out(&mut caller, ret, rcap, &bytes); + if n >= 0 && (n as usize) <= rcap.max(0) as usize { + ctl(&mut caller).async_results.remove(&ticket); + } + n + } + Err(e) => { + ctl(&mut caller).async_results.remove(&ticket); + e + } + } + })?; + linker.func_wrap("fw", "poll_event", |mut caller: C<'_>, out: i32, cap: i32| -> i32 { + let c = ctl(&mut caller); + if c.dropped_events > 0 && c.events.len() < EVENT_QUEUE_MAX { + let n = c.dropped_events; + c.dropped_events = 0; + c.post_event(EV_OVERFLOW, 0, n, &[]); + // OVERFLOW goes first so the program knows to resync. + let e = c.events.pop_back().unwrap(); + c.events.push_front(e); + } + let ev = match c.events.front() { + Some(e) => e.clone(), + None => return 0, + }; + let n = write_out(&mut caller, out, cap, &ev); + if n > 0 && (n as usize) <= cap.max(0) as usize { + ctl(&mut caller).events.pop_front(); + } + n + })?; + Ok(()) +} + +fn link_fw_image(linker: &mut Linker) -> wasmtime::Result<()> { + linker.func_wrap("fw", "image_load", |mut caller: C<'_>, ptr: i32, len: i32| -> i32 { + let raw = match read_bytes(&mut caller, ptr, len) { + Ok(r) => r, + Err(e) => return e, + }; + let c = ctl(&mut caller); + let engine = c.engine.clone(); + match engine.load_image(&raw, &c.cpu) { + Ok(img) => { + let slot = c.images.iter().position(Option::is_none); + match slot { + Some(i) => { + c.images[i] = Some(img); + i as i32 + } + None => { + c.images.push(Some(img)); + (c.images.len() - 1) as i32 + } + } + } + Err(e) => e, + } + })?; + linker.func_wrap("fw", "image_free", |mut caller: C<'_>, image: i32| -> i32 { + match ctl(&mut caller).images.get_mut(image as usize) { + Some(slot @ Some(_)) => { + *slot = None; + 0 + } + _ => E_BADHANDLE, + } + })?; + linker.func_wrap("fw", "exec", |mut caller: C<'_>, image: i32, args: i32, alen: i32| -> i32 { + if alen < 0 || alen as usize > EXEC_ARGS_MAX { + return E_INVAL; + } + let args = match read_bytes(&mut caller, args, alen) { + Ok(a) => a, + Err(e) => return e, + }; + let c = ctl(&mut caller); + let img = match c.images.get(image as usize).and_then(Option::clone) { + Some(i) => i, + None => return E_BADHANDLE, + }; + c.exit = Some(Exit::Exec { image: img, args }); + request_exit(&mut caller); + 0 + })?; + linker.func_wrap("fw", "boot_args", |mut caller: C<'_>, out: i32, cap: i32| -> i32 { + let args = ctl(&mut caller).boot_args.clone(); + write_out(&mut caller, out, cap, &args) + })?; + Ok(()) +} + +// --------------------------------------------------------------------------- + +fn trap_kind(e: &wasmtime::Error) -> i32 { + use wasmtime::Trap; + match e.downcast_ref::() { + Some(Trap::UnreachableCodeReached) => 1, + Some(Trap::MemoryOutOfBounds) => 2, + Some(Trap::IntegerDivisionByZero) => 3, + Some(Trap::IntegerOverflow) => 4, + Some(Trap::StackOverflow) => 5, + Some(Trap::IndirectCallToNull) => 6, + Some(Trap::BadSignature) => 7, + Some(Trap::TableOutOfBounds) => 8, + Some(Trap::BadConversionToInteger) => 9, + _ => 0, + } +} + +/// Create a child instance and run it up to its first poll, so it is +/// checkpointable from the start. +pub(crate) fn instantiate_child( + c: &KernelCtl, + image: &crate::Image, + mem_limit: i64, +) -> wasmtime::Result { + let mut inst = WeaveInstance::new_fresh( + &c.engine.engine, + &image.module, + vec![], + vec![Box::new(ChildCtl::default())], + child_linker(), + )?; + // Fails here (and co_create reports E_NOMEM) if the program's initial + // memory plus Weave's shadow stack already exceeds the limit. + let size = inst.mem_view().map(|v| v.size(0)).unwrap_or(0); + if size as i64 > mem_limit { + wasmtime::error::bail!("initial memory {size} exceeds the child's limit {mem_limit}"); + } + inst.set_memory_limit(Some(mem_limit as usize)); + inst.set_global_i32(names::G_CTR, 0)?; + inst.set_poller(Poller::UnwindNext); + inst.call_entry("_start", &[])?; + Ok(inst) +} + +/// The kernel may use whatever memory its children have not reserved. +fn update_kernel_limit(caller: &mut C<'_>) { + let c = ctl(caller); + let free = (c.cpu.max_memory as i64 - c.memory_in_use()).max(0) as usize; + caller.data_mut().set_memory_limit(Some(free)); +} + +fn child_mut<'a>(c: &'a mut KernelCtl, h: i32) -> Option<&'a mut Child> { + c.children.get_mut(h as usize).and_then(Option::as_mut) +} + +fn link_co(linker: &mut Linker) -> wasmtime::Result<()> { + linker.func_wrap("co", "co_create", |mut caller: C<'_>, image: i32, mem_limit: i64| -> i32 { + let c = ctl(&mut caller); + let img = match c.images.get(image as usize).and_then(Option::clone) { + Some(i) => i, + None => return E_BADHANDLE, + }; + if mem_limit <= 0 { + return E_INVAL; + } + let kernel_size = memory(&mut caller).map(|m| m.data_size(&caller)).unwrap_or(0) as i64; + let c = ctl(&mut caller); + let max = c.cpu.max_memory as i64; + if kernel_size + c.memory_in_use() + mem_limit > max { + return E_NOMEM; + } + let inst = match instantiate_child(c, &img, mem_limit) { + Ok(i) => i, + Err(_) => return E_NOMEM, + }; + let child = Child { + image: img, + inst: Some(inst), + status: STATUS_SUSPENDED, + mem_limit, + }; + let h = match c.children.iter().position(Option::is_none) { + Some(i) => { + c.children[i] = Some(child); + i as i32 + } + None => { + c.children.push(Some(child)); + (c.children.len() - 1) as i32 + } + }; + update_kernel_limit(&mut caller); + h + })?; + + linker.func_wrap( + "co", + "co_resume", + |mut caller: C<'_>, h: i32, budget: i64, retval: i64, info: i32| -> i32 { + // The child's budget comes out of the kernel's remaining budget. + let remaining = match &caller.data().poller { + Poller::UnwindAfter(n) => *n, + _ => 0, + }; + let given = (budget.max(0) as u64).min(remaining); + + let mut record = [0i64; 6]; // reason/code packed below + let mut args = [0i64; 4]; + let mut used = 0u64; + let reason; + { + let c = ctl(&mut caller); + let child = match child_mut(c, h) { + Some(ch) => ch, + None => return E_BADHANDLE, + }; + if child.status != STATUS_SUSPENDED { + reason = if child.status == STATUS_DONE { CO_DONE } else { CO_DEAD }; + record[0] = reason as i64; + } else { + let inst = child.inst.as_mut().expect("suspended child without instance"); + { + let cc = inst.ctx_mut().service_state::(0); + if cc.pending_call.take().is_some() { + cc.reply = Some(retval); + } + } + inst.set_poller(Poller::UnwindAfter(given)); + let outcome = inst.resume(); + let left = match inst.take_poller() { + Poller::UnwindAfter(n) => n, + _ => 0, + }; + used = given.saturating_sub(left); + match outcome { + Ok(WorkResult::Unwound) => { + let cc = inst.ctx_mut().service_state::(0); + match cc.pending_call { + Some((no, a)) => { + reason = CO_CALL; + record[1] = no as i64; + args = a; + } + None => reason = CO_YIELD, + } + } + Ok(WorkResult::Done(_)) => { + reason = CO_DONE; + child.status = STATUS_DONE; + child.inst = None; + } + Err(e) => { + reason = CO_DEAD; + record[1] = trap_kind(&e) as i64; + child.status = STATUS_DEAD; + child.inst = None; + } + } + record[0] = reason as i64; + } + } + caller.data_mut().poller = Poller::UnwindAfter(remaining.saturating_sub(used)); + + let mut b = Vec::with_capacity(48); + b.extend_from_slice(&(record[0] as i32).to_le_bytes()); + b.extend_from_slice(&(record[1] as i32).to_le_bytes()); + for a in args { + b.extend_from_slice(&a.to_le_bytes()); + } + b.extend_from_slice(&(used as i64).to_le_bytes()); + if let Err(e) = write_bytes(&mut caller, info, &b) { + return e; + } + reason + }, + )?; + + linker.func_wrap("co", "co_status", |mut caller: C<'_>, h: i32| -> i32 { + match child_mut(ctl(&mut caller), h) { + Some(ch) => ch.status, + None => E_BADHANDLE, + } + })?; + + linker.func_wrap("co", "co_peek", |mut caller: C<'_>, h: i32, addr: i32, buf: i32, len: i32| -> i32 { + if len < 0 { + return E_INVAL; + } + let bytes = { + let c = ctl(&mut caller); + let inst = match child_mut(c, h).and_then(|ch| ch.inst.as_mut()) { + Some(i) => i, + None => return E_BADHANDLE, + }; + let view = match inst.mem_view() { + Ok(v) => v, + Err(_) => return E_FAULT, + }; + let start = addr as u32 as usize; + let end = match start.checked_add(len as usize) { + Some(e) if e <= view.size(0) => e, + _ => return E_FAULT, + }; + let mut out = vec![0u8; end - start]; + view.read(0, start, &mut out); + out + }; + err_code(write_bytes(&mut caller, buf, &bytes).map(|()| len)) + })?; + + linker.func_wrap("co", "co_poke", |mut caller: C<'_>, h: i32, addr: i32, buf: i32, len: i32| -> i32 { + let bytes = match read_bytes(&mut caller, buf, len) { + Ok(b) => b, + Err(e) => return e, + }; + let c = ctl(&mut caller); + let inst = match child_mut(c, h).and_then(|ch| ch.inst.as_mut()) { + Some(i) => i, + None => return E_BADHANDLE, + }; + let size = match inst.mem_view() { + Ok(v) => v.size(0), + Err(_) => return E_FAULT, + }; + let start = addr as u32 as usize; + match start.checked_add(bytes.len()) { + Some(end) if end <= size => {} + _ => return E_FAULT, + } + match inst.write_mem(0, start, &bytes) { + Ok(()) => len, + Err(_) => E_FAULT, + } + })?; + + linker.func_wrap("co", "co_close", |mut caller: C<'_>, h: i32| -> i32 { + let r = match ctl(&mut caller).children.get_mut(h as usize) { + Some(slot @ Some(_)) => { + *slot = None; + 0 + } + _ => E_BADHANDLE, + }; + update_kernel_limit(&mut caller); + r + })?; + Ok(()) +} diff --git a/native/crates/shuttle-core/src/lib.rs b/native/crates/shuttle-core/src/lib.rs new file mode 100644 index 0000000..da6e3cc --- /dev/null +++ b/native/crates/shuttle-core/src/lib.rs @@ -0,0 +1,137 @@ +//! shuttle-core: the native engine behind the Shuttle computer mod. +//! +//! It runs Wasm guests (BIOS, OS kernel, child programs) on Wasmtime, makes +//! them checkpointable with Weave, and implements the firmware ABI draft 0.1 +//! (`fw.*`, `co.*`, `sys.call`). Nothing in this crate knows about Minecraft: +//! devices are plugged in through the [`Device`] trait. + +pub mod abi; +mod codec; +mod imports; +mod machine; + +pub use machine::{LogLine, Machine, MachineState}; + +use std::collections::HashMap; +use std::sync::{Arc, Mutex}; +use wasmtime::Engine; +use weave_transform::TransformOptions; +use weave_wasmtime::WeaveModule; + +/// The CPU as built in the assembler: names chosen by the player, the rest +/// decided by the parts. +#[derive(Clone, Debug)] +pub struct CpuSpec { + pub vendor: String, + pub model: String, + pub arch: String, + /// Comma separated Wasm feature names, e.g. `"simd,bulk-memory"`. + pub features: String, + /// Budget per tick, counted in Weave polls. + pub clock: u64, + /// Total memory for the kernel and all children, in bytes. + pub max_memory: u64, +} + +impl CpuSpec { + pub fn has_feature(&self, name: &str) -> bool { + self.features.split(',').any(|f| f.trim() == name) + } +} + +impl Default for CpuSpec { + fn default() -> Self { + CpuSpec { + vendor: "Akki Semiconductor".into(), + model: "AK-486 Turbo".into(), + arch: "wasm32".into(), + features: "bulk-memory".into(), + clock: 2000, + max_memory: 64 * 1024 * 1024, + } + } +} + +/// Basic identity of a device, as returned by `fw.dev_info`. +#[derive(Clone, Copy, Debug)] +pub struct DevInfo { + pub class: u16, + pub vendor: u16, + pub device: u16, + pub flags: u16, + pub address: [u8; 16], +} + +/// A device plugged into a bus slot. On the Java side this is backed by +/// `Device.invoke`; here it is a plain Rust trait. +pub trait Device: Send { + fn info(&self) -> DevInfo; + /// Method table as returned by `fw.dev_describe` (format not fixed yet). + fn describe(&self) -> Vec { + Vec::new() + } + /// Run one method. `Ok` carries the result bytes, `Err` an error code. + fn call(&mut self, method: i32, args: &[u8]) -> Result, i32>; +} + +/// A loaded program: the original bytes plus its Weave-transformed module. +pub struct Image { + pub hash: [u8; 32], + pub raw: Arc>, + pub module: WeaveModule, +} + +/// Process-wide engine: one Wasmtime engine and the image cache shared by +/// every machine. +pub struct ShuttleEngine { + pub(crate) engine: Engine, + cache: Mutex>>, + transform: TransformOptions, +} + +impl ShuttleEngine { + pub fn new() -> wasmtime::Result> { + Ok(Arc::new(ShuttleEngine { + engine: weave_wasmtime::default_engine()?, + cache: Mutex::new(HashMap::new()), + transform: TransformOptions { + poll_period: 64, + stack_pages: 4, + yielding_imports: abi::YIELDING_IMPORTS + .iter() + .map(|(m, n)| (m.to_string(), n.to_string())) + .collect(), + }, + })) + } + + /// Number of distinct images transformed so far. + pub fn cached_images(&self) -> usize { + self.cache.lock().unwrap().len() + } + + /// Check, transform and cache a guest program for a given CPU. + /// Errors are ABI error codes (`E_INVAL`, `E_VERSION`, `E_UNSUPPORTED`). + pub fn load_image(&self, raw: &[u8], cpu: &CpuSpec) -> Result, i32> { + abi::check_abi_section(raw)?; + abi::check_features(raw, cpu)?; + self.load_unchecked(raw) + } + + /// Transform without ABI checks (used on restore, where the image was + /// accepted before it was saved). + pub(crate) fn load_unchecked(&self, raw: &[u8]) -> Result, i32> { + let hash = weave_core::sha256::sha256(raw); + if let Some(img) = self.cache.lock().unwrap().get(&hash) { + return Ok(img.clone()); + } + let module = WeaveModule::from_raw(raw, &self.transform).map_err(|_| abi::E_INVAL)?; + let img = Arc::new(Image { + hash, + raw: Arc::new(raw.to_vec()), + module, + }); + self.cache.lock().unwrap().insert(hash, img.clone()); + Ok(img) + } +} diff --git a/native/crates/shuttle-core/src/machine.rs b/native/crates/shuttle-core/src/machine.rs new file mode 100644 index 0000000..3494c0b --- /dev/null +++ b/native/crates/shuttle-core/src/machine.rs @@ -0,0 +1,363 @@ +//! One computer: the top-level guest (BIOS, then OS), its children, devices, +//! events and the per-tick scheduler. + +use crate::abi::*; +use crate::imports; +use crate::{CpuSpec, Device, Image, ShuttleEngine}; +use std::collections::{BTreeMap, VecDeque}; +use std::sync::Arc; +use wasmtime::Result; +use weave_core::names; +use weave_wasmtime::{InstanceState, Poller, WeaveInstance, WorkResult}; + +/// What a stopped guest asked the firmware to do. +pub(crate) enum Exit { + Hlt(i64), + Yield, + Exec { image: Arc, args: Vec }, + Shutdown, + Reboot, +} + +/// Per-child host state, stored in the child's own Store. +#[derive(Default)] +pub(crate) struct ChildCtl { + /// Set by the first `sys.call`; reported by the kernel's `co_resume`. + pub pending_call: Option<(i32, [i64; 4])>, + /// Result for the re-executed `sys.call` after resume. + pub reply: Option, +} + +pub(crate) struct Child { + pub image: Arc, + pub inst: Option, + pub status: i32, + pub mem_limit: i64, +} + +pub(crate) struct AsyncReq { + pub ticket: i32, + pub slot: i32, + pub method: i32, + pub args: Vec, +} + +/// Machine-wide host state. While a top-level guest exists it lives inside +/// that guest's Store (so host functions can reach it); otherwise the +/// [`Machine`] keeps it. +pub(crate) struct KernelCtl { + pub engine: Arc, + pub cpu: CpuSpec, + pub devices: Vec>>, + pub images: Vec>>, + pub children: Vec>, + pub events: VecDeque>, + pub dropped_events: u32, + pub tick: u64, + pub logs: Vec, + pub log_lines_this_tick: usize, + pub exit: Option, + /// Result for the re-executed exit call (hlt, yield) after resume. + pub exit_reply: Option, + /// A `dev_call` result that did not fit; fetched with `dev_result(-1)`. + pub held_result: Option>, + pub boot_args: Vec, + pub next_ticket: i32, + pub async_queue: Vec, + pub async_results: BTreeMap, i32>>, +} + +impl KernelCtl { + pub fn post_event(&mut self, kind: u16, slot: u16, param: u32, payload: &[u8]) { + if self.events.len() >= EVENT_QUEUE_MAX { + self.dropped_events += 1; + return; + } + let mut e = Vec::with_capacity(20 + payload.len()); + e.extend_from_slice(&kind.to_le_bytes()); + e.extend_from_slice(&slot.to_le_bytes()); + e.extend_from_slice(¶m.to_le_bytes()); + e.extend_from_slice(&(self.tick as i64).to_le_bytes()); + e.extend_from_slice(&(payload.len() as u32).to_le_bytes()); + e.extend_from_slice(payload); + self.events.push_back(e); + } + + pub fn log(&mut self, text: String) { + if self.log_lines_this_tick >= LOG_LINES_PER_TICK { + return; + } + self.log_lines_this_tick += 1; + self.logs.push(LogLine { + tick: self.tick, + text, + }); + } + + pub fn memory_in_use(&self) -> i64 { + self.children + .iter() + .flatten() + .filter(|c| c.status == STATUS_SUSPENDED) + .map(|c| c.mem_limit) + .sum() + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct LogLine { + pub tick: u64, + pub text: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum MachineState { + /// Runs every tick. + Running, + /// Stopped in `hlt` until an event arrives or the given tick (0 = never). + Halted { until: u64 }, + Off, + Crashed(String), +} + +pub struct Machine { + pub(crate) eeprom: Arc, + pub(crate) kernel: Option, + pub(crate) kernel_image: Option>, + /// Holds the ctl while no top-level instance exists. + pub(crate) spare_ctl: Option>, + pub(crate) state: MachineState, +} + +impl Machine { + /// Build a powered-off computer. `eeprom` is the BIOS program. + pub fn new( + engine: &Arc, + cpu: CpuSpec, + eeprom: &[u8], + devices: Vec>, + ) -> std::result::Result { + let eeprom = engine.load_image(eeprom, &cpu)?; + let ctl = KernelCtl { + engine: engine.clone(), + cpu, + devices: devices.into_iter().map(Some).collect(), + images: Vec::new(), + children: Vec::new(), + events: VecDeque::new(), + dropped_events: 0, + tick: 0, + logs: Vec::new(), + log_lines_this_tick: 0, + exit: None, + exit_reply: None, + held_result: None, + boot_args: Vec::new(), + next_ticket: 0, + async_queue: Vec::new(), + async_results: BTreeMap::new(), + }; + Ok(Machine { + eeprom, + kernel: None, + kernel_image: None, + spare_ctl: Some(Box::new(ctl)), + state: MachineState::Off, + }) + } + + pub fn state(&self) -> &MachineState { + &self.state + } + + pub(crate) fn ctl(&mut self) -> &mut KernelCtl { + match self.kernel.as_mut() { + Some(k) => kernel_ctl_slot(k).as_mut().expect("kernel lost its ctl"), + None => self.spare_ctl.as_mut().expect("machine lost its ctl"), + } + } + + pub fn tick_count(&mut self) -> u64 { + self.ctl().tick + } + + /// Lines written with `fw.log` since the last call. + pub fn drain_log(&mut self) -> Vec { + std::mem::take(&mut self.ctl().logs) + } + + /// Test hook for control experiments: forget the host-side child table, + /// as a broken restore would. Never used by real embedders. + #[doc(hidden)] + pub fn debug_drop_children(&mut self) { + self.ctl().children.clear(); + } + + /// Queue an event as a device would (key press, redstone change, ...). + pub fn post_event(&mut self, kind: u16, slot: u16, param: u32, payload: &[u8]) { + self.ctl().post_event(kind, slot, param, payload); + } + + /// Turn the computer on: the firmware starts the BIOS from the EEPROM. + pub fn power_on(&mut self) -> Result<()> { + if !matches!(self.state, MachineState::Off | MachineState::Crashed(_)) { + return Ok(()); + } + let bios = self.eeprom.clone(); + self.start_top_level(bios, Vec::new()) + } + + /// Detach the ctl from the current top-level instance (dropping it). + fn take_ctl(&mut self) -> Box { + match self.kernel.take() { + Some(mut k) => kernel_ctl_slot(&mut k).take().expect("kernel lost its ctl"), + None => self.spare_ctl.take().expect("machine lost its ctl"), + } + } + + /// Replace the top-level program (power on, `exec`, reboot). Memory and + /// all children are discarded; images stay loaded. + fn start_top_level(&mut self, image: Arc, boot_args: Vec) -> Result<()> { + let mut ctl = self.take_ctl(); + ctl.children.clear(); + ctl.exit = None; + ctl.exit_reply = None; + ctl.held_result = None; + ctl.boot_args = boot_args; + let max_memory = ctl.cpu.max_memory as usize; + let engine = ctl.engine.engine.clone(); + let mut inst = match WeaveInstance::new_fresh( + &engine, + &image.module, + vec![], + vec![Box::new(Some(ctl))], + imports::kernel_linker(), + ) { + Ok(i) => i, + Err(e) => { + // The ctl went down with the failed instantiation; rebuild it + // is not possible here, so this is fatal for the prototype. + return Err(e.context("instantiating top-level program")); + } + }; + inst.set_memory_limit(Some(max_memory)); + // Run up to the first poll so the instance is checkpointable at once. + inst.set_global_i32(names::G_CTR, 0)?; + inst.set_poller(Poller::UnwindNext); + match inst.call_entry("_start", &[])? { + WorkResult::Unwound => {} + WorkResult::Done(_) => {} + } + kernel_ctl_slot(&mut inst).as_mut().unwrap().exit = None; + self.kernel = Some(inst); + self.kernel_image = Some(image); + self.state = MachineState::Running; + Ok(()) + } + + fn power_off(&mut self, state: MachineState) { + let mut ctl = self.take_ctl(); + ctl.children.clear(); + ctl.exit = None; + self.spare_ctl = Some(ctl); + self.kernel_image = None; + self.state = state; + } + + /// Advance one tick. + pub fn tick(&mut self) -> Result<&MachineState> { + { + let ctl = self.ctl(); + ctl.tick += 1; + ctl.log_lines_this_tick = 0; + } + self.run_async_requests(); + + match self.state.clone() { + MachineState::Off | MachineState::Crashed(_) => return Ok(&self.state), + MachineState::Halted { until } => { + let tick = self.ctl().tick; + let has_event = !self.ctl().events.is_empty(); + if has_event { + self.ctl().exit_reply = Some(1); + } else if until != 0 && tick >= until { + self.ctl().exit_reply = Some(0); + } else { + return Ok(&self.state); + } + self.state = MachineState::Running; + } + MachineState::Running => {} + } + + let clock = self.ctl().cpu.clock; + let kernel = self.kernel.as_mut().expect("running machine without a kernel"); + kernel.set_poller(Poller::UnwindAfter(clock)); + let outcome = if kernel.state() == InstanceState::Paused { + kernel.resume() + } else { + kernel.call_entry("_start", &[]) + }; + + match outcome { + Err(e) => { + let msg = format!("{e:#}"); + self.ctl().log(format!("firmware: kernel panic: {msg}")); + self.power_off(MachineState::Crashed(msg)); + } + Ok(WorkResult::Done(_)) => { + self.ctl().log("firmware: top-level program returned".into()); + self.power_off(MachineState::Off); + } + Ok(WorkResult::Unwound) => { + let exit = self.ctl().exit.take(); + match exit { + None => {} + Some(Exit::Yield) => self.ctl().exit_reply = Some(0), + Some(Exit::Hlt(timeout)) => { + let tick = self.ctl().tick; + let until = if timeout <= 0 { 0 } else { tick + timeout as u64 }; + self.state = MachineState::Halted { until }; + } + Some(Exit::Exec { image, args }) => { + self.start_top_level(image, args)?; + } + Some(Exit::Shutdown) => { + self.ctl().log("firmware: power off".into()); + self.power_off(MachineState::Off); + } + Some(Exit::Reboot) => { + self.ctl().log("firmware: reboot".into()); + let bios = self.eeprom.clone(); + self.start_top_level(bios, Vec::new())?; + } + } + } + } + Ok(&self.state) + } + + /// Complete queued `dev_submit` calls. In the mod this happens on the + /// server thread; here it simply runs at the start of the next tick. + fn run_async_requests(&mut self) { + let ctl = self.ctl(); + let queue = std::mem::take(&mut ctl.async_queue); + for req in queue { + let result = match ctl.devices.get_mut(req.slot as usize).and_then(Option::as_mut) { + Some(dev) => dev.call(req.method, &req.args), + None => Err(E_NODEV), + }; + let status = match &result { + Ok(bytes) => bytes.len() as i32, + Err(code) => *code, + }; + ctl.async_results.insert(req.ticket, result); + ctl.post_event(EV_COMPLETE, req.slot as u16, req.ticket as u32, &status.to_le_bytes()); + } + } +} + +/// The ctl slot inside a top-level instance's Store. +pub(crate) fn kernel_ctl_slot(k: &mut WeaveInstance) -> &mut Option> { + k.ctx_mut().service_state::>>(0) +} diff --git a/native/crates/shuttle-runner/Cargo.toml b/native/crates/shuttle-runner/Cargo.toml new file mode 100644 index 0000000..db2d325 --- /dev/null +++ b/native/crates/shuttle-runner/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "shuttle-runner" +version.workspace = true +edition.workspace = true +license.workspace = true + +[dependencies] +shuttle-core.workspace = true diff --git a/native/crates/shuttle-runner/src/main.rs b/native/crates/shuttle-runner/src/main.rs new file mode 100644 index 0000000..d26730e --- /dev/null +++ b/native/crates/shuttle-runner/src/main.rs @@ -0,0 +1,187 @@ +//! Headless Shuttle emulator. +//! +//! shuttle-runner run [disk1 ...] +//! shuttle-runner verify [disk1 ...] +//! +//! `run` boots the computer and prints its log until it powers off. +//! `verify` runs the same boot once without interruption, then again with a +//! capture -> restore (into a brand-new machine) at several tick boundaries, +//! and checks that the log streams are identical. + +use shuttle_core::{CpuSpec, DevInfo, Device, LogLine, Machine, MachineState, ShuttleEngine}; +use std::sync::Arc; +use std::time::Instant; + +const MAX_TICKS: u64 = 2000; + +/// Read-only disk. Methods: 0 = size() -> u64, 1 = read(off: u64, len: u32). +struct RomDisk { + data: Arc>, + address: [u8; 16], +} + +impl RomDisk { + fn new(data: Arc>, index: u8) -> RomDisk { + let mut address = [0u8; 16]; + // deterministic pseudo-UUID derived from contents and position + let mut h: u64 = 0xcbf29ce484222325 ^ index as u64; + for b in data.iter() { + h = (h ^ *b as u64).wrapping_mul(0x100000001b3); + } + address[..8].copy_from_slice(&h.to_le_bytes()); + address[8..].copy_from_slice(&(h.rotate_left(17) ^ 0x5bd1e995).to_le_bytes()); + RomDisk { data, address } + } +} + +impl Device for RomDisk { + fn info(&self) -> DevInfo { + DevInfo { class: 0x03, vendor: 0x0001, device: 0x0001, flags: 0, address: self.address } + } + fn call(&mut self, method: i32, args: &[u8]) -> Result, i32> { + match method { + 0 => Ok((self.data.len() as u64).to_le_bytes().to_vec()), + 1 => { + if args.len() != 12 { + return Err(-1); + } + let off = u64::from_le_bytes(args[0..8].try_into().unwrap()) as usize; + let len = u32::from_le_bytes(args[8..12].try_into().unwrap()) as usize; + let end = off.checked_add(len).ok_or(-1)?; + self.data.get(off..end).map(|s| s.to_vec()).ok_or(-11) + } + _ => Err(-4), + } + } +} + +fn devices(disks: &[Arc>]) -> Vec> { + disks + .iter() + .enumerate() + .map(|(i, d)| Box::new(RomDisk::new(d.clone(), i as u8)) as Box) + .collect() +} + +fn finished(state: &MachineState) -> bool { + matches!(state, MachineState::Off | MachineState::Crashed(_)) +} + +/// Boot and run to power-off. If `restore_at` is set, capture after that +/// tick and continue on a restored copy. Returns the log and snapshot size. +fn run( + engine: &Arc, + bios: &[u8], + disks: &[Arc>], + restore_at: Option, + echo: bool, + drop_children: bool, +) -> (Vec, Option, u64) { + let mut m = Machine::new(engine, CpuSpec::default(), bios, devices(disks)) + .unwrap_or_else(|e| panic!("BIOS rejected: {e}")); + m.power_on().expect("power on"); + let mut log = m.drain_log(); + let mut snap_size = None; + let mut ticks = 0; + for t in 1..=MAX_TICKS { + let state = m.tick().expect("tick").clone(); + ticks = t; + let lines = m.drain_log(); + if echo { + for l in &lines { + println!("[{:>4}] {}", l.tick, l.text); + } + } + log.extend(lines); + if finished(&state) { + break; + } + if restore_at == Some(t) { + let bytes = m.capture().expect("capture"); + snap_size = Some(bytes.len()); + drop(m); + m = Machine::restore(engine, &bytes, devices(disks)).expect("restore"); + if drop_children { + m.debug_drop_children(); + } + } + } + (log, snap_size, ticks) +} + +fn main() { + let args: Vec = std::env::args().collect(); + if args.len() < 4 || (args[1] != "run" && args[1] != "verify") { + eprintln!("usage: shuttle-runner run|verify [disk1 ...]"); + std::process::exit(2); + } + let bios = std::fs::read(&args[2]).expect("read bios"); + let disks: Vec>> = args[3..] + .iter() + .map(|p| Arc::new(std::fs::read(p).expect("read disk"))) + .collect(); + let engine = ShuttleEngine::new().expect("engine"); + + let t0 = Instant::now(); + let (golden, _, ticks) = run(&engine, &bios, &disks, None, args[1] == "run", false); + println!( + "-- uninterrupted run: {} log lines, {} ticks, {:.1} ms (incl. transform/compile)", + golden.len(), + ticks, + t0.elapsed().as_secs_f64() * 1e3 + ); + if args[1] == "run" { + return; + } + + let points: Vec = (1..ticks).collect(); + let mut ok = 0; + for &p in &points { + let t = Instant::now(); + let (log, size, _) = run(&engine, &bios, &disks, Some(p), false, false); + let same = log == golden; + if same { + ok += 1; + } + println!( + "restore after tick {:>4}: snapshot {:>6} bytes (gzip), log {} ({:.1} ms)", + p, + size.unwrap_or(0), + if same { "identical" } else { "DIFFERENT" }, + t.elapsed().as_secs_f64() * 1e3 + ); + if !same { + for (i, (a, b)) in golden.iter().zip(log.iter()).enumerate() { + if a != b { + println!(" first difference at line {i}: {:?} vs {:?}", a, b); + break; + } + } + if golden.len() != log.len() { + println!(" lengths differ: {} vs {}", golden.len(), log.len()); + } + } + } + println!("-- {ok}/{} restore points identical; images cached: {}", points.len(), engine.cached_images()); + + // Control: a restore that loses the host-side child table must diverge, + // otherwise the comparison above would prove nothing. + let mut caught = 0; + let control_points: Vec = points.iter().copied().filter(|&p| p >= 3).collect(); + for &p in &control_points { + let (log, _, _) = run(&engine, &bios, &disks, Some(p), false, true); + if log != golden { + caught += 1; + } + } + println!( + "-- control (child table dropped on restore): {caught}/{} runs diverged as expected", + control_points.len() + ); + if caught != control_points.len() { + std::process::exit(1); + } + if ok != points.len() { + std::process::exit(1); + } +} diff --git a/native/guests/bios.c b/native/guests/bios.c new file mode 100644 index 0000000..9608100 --- /dev/null +++ b/native/guests/bios.c @@ -0,0 +1,73 @@ +/* bios.c - minimal BIOS: find a bootable disk, load the OS image, exec it. */ +#include "shuttle.h" + +SHUTTLE_ABI_DECLARE(); + +#define CLASS_STORAGE 0x03 +#define DISK_SIZE 0 /* () -> u64 */ +#define DISK_READ 1 /* (u64 off, u32 len) -> bytes */ + +static u8 os_buf[512 * 1024]; + +static void log_num(const char *prefix, i64 v) { + char line[96]; + i32 n = 0; + while (prefix[n]) { line[n] = prefix[n]; n++; } + n += sh_itoa(v, line + n); + fw_log_raw(line, n); +} + +static i64 disk_size(i32 slot) { + u64 size = 0; + i32 r = fw_dev_call(slot, DISK_SIZE, 0, 0, &size, 8); + return r == 8 ? (i64)size : r; +} + +static i32 disk_read(i32 slot, u64 off, void *dst, u32 len) { + u8 args[12]; + for (i32 i = 0; i < 8; i++) args[i] = (u8)(off >> (8 * i)); + for (i32 i = 0; i < 4; i++) args[8 + i] = (u8)(len >> (8 * i)); + return fw_dev_call(slot, DISK_READ, args, 12, dst, (i32)len); +} + +void _start(void) { + char line[96]; + fw_log("BIOS: power on"); + /* "BIOS: CPU " */ + i32 n = 0; + const char *p = "BIOS: CPU "; + while (*p) line[n++] = *p++; + i32 v = fw_cpuid(0, line + n, 40); + if (v > 0 && v <= 40) n += v; + line[n++] = ' '; + i32 m = fw_cpuid(1, line + n, 40); + if (m > 0 && m <= 40) n += m; + fw_log_raw(line, n); + + i32 slots = fw_dev_slots(); + for (i32 slot = 0; slot < slots; slot++) { + u8 info[24]; + if (fw_dev_info(slot, info, sizeof info) != 24) continue; + u16 cls = (u16)(info[0] | (info[1] << 8)); + if (cls != CLASS_STORAGE) continue; + + i64 size = disk_size(slot); + if (size < 8 || size > (i64)sizeof os_buf) continue; + if (disk_read(slot, 0, os_buf, (u32)size) != size) continue; + /* bootable = a Wasm module on the disk */ + if (os_buf[0] != 0 || os_buf[1] != 'a' || os_buf[2] != 's' || os_buf[3] != 'm') continue; + + log_num("BIOS: booting from slot ", slot); + i32 image = fw_image_load(os_buf, (i32)size); + if (image < 0) { log_num("BIOS: image_load failed: ", image); continue; } + + /* boot args: the boot slot (u32) followed by the disk address (16 bytes) */ + u8 args[20]; + for (i32 i = 0; i < 4; i++) args[i] = (u8)((u32)slot >> (8 * i)); + for (i32 i = 0; i < 16; i++) args[4 + i] = info[8 + i]; + i32 r = fw_exec(image, args, sizeof args); + log_num("BIOS: exec failed: ", r); + } + fw_log("BIOS: no bootable disk"); + fw_shutdown(); +} diff --git a/native/guests/build.sh b/native/guests/build.sh new file mode 100644 index 0000000..e371f07 --- /dev/null +++ b/native/guests/build.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# Build the C guests into freestanding wasm32 modules. +set -e +cd "$(dirname "$0")" +mkdir -p out +for prog in bios os child; do + clang --target=wasm32 -O2 -nostdlib -ffreestanding \ + -Wall -Wno-unused-function \ + -Wl,--no-entry -Wl,--export=_start -Wl,-z,stack-size=65536 \ + -o "out/$prog.wasm" "$prog.c" +done +ls -l out diff --git a/native/guests/child.c b/native/guests/child.c new file mode 100644 index 0000000..0e6f0b3 --- /dev/null +++ b/native/guests/child.c @@ -0,0 +1,57 @@ +/* child.c - a user program: it can only talk to the kernel through sys.call. */ +#include "shuttle.h" + +SHUTTLE_ABI_DECLARE(); + +#define SYS_WRITE 1 +#define SYS_TIME 2 +#define SYS_EXIT 3 +#define SYS_SLEEP 4 + +static char buf[128]; + +static void print(const char *s, i32 len) { sys_call(SYS_WRITE, (i64)(usize)s, len, 0, 0); } + +static i32 append(i32 n, const char *s) { + while (*s) buf[n++] = *s++; + return n; +} + +/* deliberately recursive so the call stack is deep when a tick ends */ +static u64 work(u32 depth, u64 acc) { + if (depth == 0) { + /* volatile keeps clang from folding the loop away */ + volatile u64 x = acc; + for (u32 i = 0; i < 2000000; i++) x = x * 6364136223846793005ULL + 1442695040888963407ULL; + return x; + } + return work(depth - 1, acc ^ depth) + depth; +} + +void _start(void) { + print("Hello from the child program!", 29); + { + /* the kernel gave this child 2 MiB (32 pages) in total */ + i32 big = __builtin_wasm_memory_grow(0, 64); + i32 small = __builtin_wasm_memory_grow(0, 1); + i32 n = append(0, "memory.grow(64 pages) = "); + n += sh_itoa(big, buf + n); + n = append(n, ", memory.grow(1 page) = "); + n += sh_itoa(small, buf + n); + print(buf, n); + } + u64 acc = 1; + for (i32 round = 1; round <= 5; round++) { + acc = work(32, acc); + i64 now = sys_call(SYS_TIME, 0, 0, 0, 0); + i32 n = append(0, "round "); + n += sh_itoa(round, buf + n); + n = append(n, " at tick "); + n += sh_itoa(now, buf + n); + n = append(n, ", acc = "); + n += sh_itoa((i64)(acc % 1000000007ULL), buf + n); + print(buf, n); + sys_call(SYS_SLEEP, 2, 0, 0, 0); + } + sys_call(SYS_EXIT, 42, 0, 0, 0); +} diff --git a/native/guests/os.c b/native/guests/os.c new file mode 100644 index 0000000..3e6dcc2 --- /dev/null +++ b/native/guests/os.c @@ -0,0 +1,137 @@ +/* os.c - minimal kernel: load one child program and serve its system calls. */ +#include "shuttle.h" + +SHUTTLE_ABI_DECLARE(); + +#define CLASS_STORAGE 0x03 +#define DISK_SIZE 0 +#define DISK_READ 1 + +/* system call numbers (defined by this OS, not by the ABI) */ +#define SYS_WRITE 1 /* (ptr, len) -> len */ +#define SYS_TIME 2 /* () -> tick */ +#define SYS_EXIT 3 /* (code) */ +#define SYS_SLEEP 4 /* (ticks) */ + +static u8 prog_buf[256 * 1024]; +static char line[512]; + +static i32 append(i32 n, const char *s) { + while (*s && n < (i32)sizeof line - 1) line[n++] = *s++; + return n; +} +static void log_num(const char *prefix, i64 v) { + i32 n = append(0, prefix); + n += sh_itoa(v, line + n); + fw_log_raw(line, n); +} + +static i64 disk_size(i32 slot) { + u64 size = 0; + i32 r = fw_dev_call(slot, DISK_SIZE, 0, 0, &size, 8); + return r == 8 ? (i64)size : r; +} +static i32 disk_read(i32 slot, u64 off, void *dst, u32 len) { + u8 args[12]; + for (i32 i = 0; i < 8; i++) args[i] = (u8)(off >> (8 * i)); + for (i32 i = 0; i < 4; i++) args[8 + i] = (u8)(len >> (8 * i)); + return fw_dev_call(slot, DISK_READ, args, 12, dst, (i32)len); +} + +/* Load the first Wasm program found on a storage device other than the boot disk. */ +static i32 load_program(i32 boot_slot) { + i32 slots = fw_dev_slots(); + for (i32 slot = 0; slot < slots; slot++) { + if (slot == boot_slot) continue; + u8 info[24]; + if (fw_dev_info(slot, info, sizeof info) != 24) continue; + if ((info[0] | (info[1] << 8)) != CLASS_STORAGE) continue; + i64 size = disk_size(slot); + if (size < 8 || size > (i64)sizeof prog_buf) continue; + if (disk_read(slot, 0, prog_buf, (u32)size) != size) continue; + log_num("OS: loading program from slot ", slot); + return fw_image_load(prog_buf, (i32)size); + } + return E_NODEV; +} + +void _start(void) { + u8 args[20]; + i32 boot_slot = -1; + if (fw_boot_args(args, sizeof args) == 20) + boot_slot = (i32)(args[0] | (args[1] << 8) | (args[2] << 16) | ((u32)args[3] << 24)); + log_num("OS: kernel started, boot slot = ", boot_slot); + + /* self-test: a dev_call result larger than the buffer is held, not lost */ + { + u64 size = 0; + i32 need = fw_dev_call(boot_slot, DISK_SIZE, 0, 0, &size, 4); + i32 got = fw_dev_result(DEV_HELD_RESULT, &size, 8); + i32 again = fw_dev_result(DEV_HELD_RESULT, &size, 8); + i32 n = append(0, "OS: held result: need "); + n += sh_itoa(need, line + n); + n = append(n, ", fetched "); + n += sh_itoa(got, line + n); + n = append(n, " (disk size "); + n += sh_itoa((i64)size, line + n); + n = append(n, "), second fetch "); + n += sh_itoa(again, line + n); + fw_log_raw(line, n); + } + + i32 image = load_program(boot_slot); + if (image < 0) { log_num("OS: no program: ", image); fw_shutdown(); } + + /* self-test: reservations beyond the CPU's memory are refused */ + log_num("OS: co_create with 1 GiB -> ", co_create(image, 1024LL * 1024 * 1024)); + + i32 child = co_create(image, 2 * 1024 * 1024); + if (child < 0) { log_num("OS: co_create failed: ", child); fw_shutdown(); } + log_num("OS: started child, handle = ", child); + + co_info info; + i64 retval = 0; + i64 total_used = 0; + for (;;) { + i32 why = co_resume(child, 400, retval, &info); + total_used += info.used; + retval = 0; + if (why == CO_YIELD) continue; /* budget used up: keep going */ + if (why == CO_DONE) { fw_log("OS: child returned"); break; } + if (why == CO_DEAD) { log_num("OS: child trapped, kind = ", info.code); break; } + if (why < 0) { log_num("OS: co_resume failed: ", why); break; } + + /* CO_CALL */ + switch (info.code) { + case SYS_WRITE: { + i32 len = (i32)info.a[1]; + if (len > 400) len = 400; + i32 n = append(0, "[child] "); + if (co_peek(child, (i32)info.a[0], line + n, len) == len) { + fw_log_raw(line, n + len); + retval = len; + } else { + retval = E_FAULT; + } + break; + } + case SYS_TIME: + retval = fw_time(); + break; + case SYS_SLEEP: + /* single-tasking kernel: just halt the whole CPU */ + fw_hlt(info.a[0]); + break; + case SYS_EXIT: + log_num("OS: child exited with code ", info.a[0]); + co_close(child); + log_num("OS: budget used by child = ", total_used); + fw_log("OS: shutting down"); + fw_shutdown(); + break; + default: + retval = E_INVAL; + } + } + fw_shutdown(); +} diff --git a/native/guests/shuttle.h b/native/guests/shuttle.h new file mode 100644 index 0000000..7e29289 --- /dev/null +++ b/native/guests/shuttle.h @@ -0,0 +1,123 @@ +/* + * shuttle.h - Shuttle firmware ABI for C guests (freestanding, wasm32). + * + * Draft ABI 0.1. Every program must include SHUTTLE_ABI_DECLARE() exactly once + * (it emits the `shuttle.abi` custom section the firmware checks at load). + * + * Calls that stop the CPU (hlt, yield, exec, shutdown, reboot, sys.call) are + * plain imports: the firmware registers them as Weave "yielding imports", so + * the guest is suspended inside the call and the call returns its result when + * the guest is resumed. No wrappers or hidden imports are needed. + */ +#ifndef SHUTTLE_H +#define SHUTTLE_H + +typedef signed char i8; +typedef unsigned char u8; +typedef short i16; +typedef unsigned short u16; +typedef int i32; +typedef unsigned int u32; +typedef long long i64; +typedef unsigned long long u64; +typedef unsigned long usize; + +#define SHUTTLE_ABI_MAJOR 0 +#define SHUTTLE_ABI_MINOR 1 + +/* Emits the 8-byte `shuttle.abi` custom section: major (u32 LE), minor (u32 LE). */ +#define SHUTTLE_STR2(x) #x +#define SHUTTLE_STR(x) SHUTTLE_STR2(x) +#define SHUTTLE_ABI_DECLARE() \ + __asm__(".section .custom_section.shuttle.abi,\"\",@\n" \ + ".int32 " SHUTTLE_STR(SHUTTLE_ABI_MAJOR) "\n" \ + ".int32 " SHUTTLE_STR(SHUTTLE_ABI_MINOR) "\n" \ + ".text\n") + +#define IMPORT(mod, name) __attribute__((import_module(mod), import_name(name))) + +/* ---- error codes ---- */ +#define E_INVAL (-1) +#define E_FAULT (-2) +#define E_NODEV (-3) +#define E_NOMETHOD (-4) +#define E_BADHANDLE (-5) +#define E_NOMEM (-6) +#define E_UNSUPPORTED (-7) +#define E_VERSION (-8) +#define E_AGAIN (-9) +#define E_NOPOWER (-10) +#define E_IO (-11) + +/* ---- fw: CPU ---- */ +IMPORT("fw", "cpuid") i32 fw_cpuid(i32 leaf, void *out, i32 cap); +IMPORT("fw", "time") i64 fw_time(void); +IMPORT("fw", "log") void fw_log_raw(const void *ptr, i32 len); +IMPORT("fw", "hlt") i32 fw_hlt(i64 timeout); /* 1 = event, 0 = timeout */ +IMPORT("fw", "yield") void fw_yield(void); +IMPORT("fw", "shutdown") __attribute__((noreturn)) void fw_shutdown(void); +IMPORT("fw", "reboot") __attribute__((noreturn)) void fw_reboot(void); + +/* ---- fw: devices ---- */ +IMPORT("fw", "dev_slots") i32 fw_dev_slots(void); +IMPORT("fw", "dev_info") i32 fw_dev_info(i32 slot, void *out, i32 cap); +IMPORT("fw", "dev_describe") i32 fw_dev_describe(i32 slot, void *out, i32 cap); +IMPORT("fw", "dev_call") i32 fw_dev_call(i32 slot, i32 method, const void *args, i32 alen, void *ret, i32 rcap); +IMPORT("fw", "dev_submit") i32 fw_dev_submit(i32 slot, i32 method, const void *args, i32 alen); +IMPORT("fw", "dev_result") i32 fw_dev_result(i32 ticket, void *ret, i32 rcap); +/* ticket for a dev_call result that did not fit its buffer */ +#define DEV_HELD_RESULT (-1) + +/* ---- fw: events ---- */ +IMPORT("fw", "poll_event") i32 fw_poll_event(void *out, i32 cap); + +/* ---- fw: images ---- */ +IMPORT("fw", "image_load") i32 fw_image_load(const void *ptr, i32 len); +IMPORT("fw", "image_free") i32 fw_image_free(i32 image); +IMPORT("fw", "exec") i32 fw_exec(i32 image, const void *args, i32 alen); /* returns only on failure */ +IMPORT("fw", "boot_args") i32 fw_boot_args(void *out, i32 cap); + +/* ---- co: virtualization ---- */ +#define CO_YIELD 0 +#define CO_CALL 1 +#define CO_DONE 2 +#define CO_DEAD 3 + +typedef struct { + i32 reason; + i32 code; /* syscall number (CALL) or trap kind (DEAD) */ + i64 a[4]; + i64 used; +} co_info; + +IMPORT("co", "co_create") i32 co_create(i32 image, i64 mem_limit); +IMPORT("co", "co_resume") i32 co_resume(i32 h, i64 budget, i64 retval, co_info *info); +IMPORT("co", "co_status") i32 co_status(i32 h); +IMPORT("co", "co_peek") i32 co_peek(i32 h, i32 addr, void *buf, i32 len); +IMPORT("co", "co_poke") i32 co_poke(i32 h, i32 addr, const void *buf, i32 len); +IMPORT("co", "co_close") i32 co_close(i32 h); + +/* ---- sys: the only import a child program sees ---- */ +IMPORT("sys", "call") i64 sys_call(i32 no, i64 a0, i64 a1, i64 a2, i64 a3); + +/* ---- tiny freestanding helpers ---- */ +static inline usize sh_strlen(const char *s) { + usize n = 0; + while (s[n]) n++; + return n; +} +static inline void fw_log(const char *s) { fw_log_raw(s, (i32)sh_strlen(s)); } + +/* Write the decimal form of v into buf (at least 21 bytes); returns length. */ +static inline i32 sh_itoa(i64 v, char *buf) { + char tmp[24]; + i32 n = 0, len = 0; + u64 u = v < 0 ? (u64)(-(v + 1)) + 1 : (u64)v; + do { tmp[n++] = (char)('0' + u % 10); u /= 10; } while (u); + if (v < 0) buf[len++] = '-'; + while (n) buf[len++] = tmp[--n]; + buf[len] = 0; + return len; +} + +#endif From e6bab53ba648e303a635310cd36b653b3e6da7c8 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 15 Oct 2026 13:56:46 +0900 Subject: [PATCH 02/15] Add native build scripts (Windows, Linux/WSL2) and a 6-platform CI - native/scripts/build.ps1: Windows; builds guests, workspace, runs verify - native/scripts/build.sh: Linux/WSL2; same, plus --cross via cross - .github/workflows/native.yml: guests built once on Linux, then build + verify on Linux/Windows/macOS x86_64 and arm64 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01WE6jR1fQDhj3HTdNWb73L9 --- .github/workflows/native.yml | 59 ++++++++++++++++++++++++++++++++++++ native/README.md | 24 ++++++++++++++- native/scripts/build.ps1 | 56 ++++++++++++++++++++++++++++++++++ native/scripts/build.sh | 59 ++++++++++++++++++++++++++++++++++++ 4 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/native.yml create mode 100644 native/scripts/build.ps1 create mode 100755 native/scripts/build.sh diff --git a/.github/workflows/native.yml b/.github/workflows/native.yml new file mode 100644 index 0000000..e4be225 --- /dev/null +++ b/.github/workflows/native.yml @@ -0,0 +1,59 @@ +# Builds the Shuttle native workspace (native/) on all six target platforms +# and runs the capture/restore verification on each. +name: Native (Shuttle) + +on: + push: + branches: [main] + paths: ["native/**", ".github/workflows/native.yml"] + pull_request: + paths: ["native/**", ".github/workflows/native.yml"] + workflow_dispatch: + +jobs: + # The C guests are plain wasm32 and identical everywhere: build them once. + guests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + - name: Install clang and lld + run: sudo apt-get update && sudo apt-get install -y clang lld + - name: Build guests + run: sh native/guests/build.sh + - uses: actions/upload-artifact@v4 + with: + name: guests + path: native/guests/out/*.wasm + + build: + needs: guests + strategy: + fail-fast: false + matrix: + include: + - { name: linux-x86_64, os: ubuntu-latest } + - { name: linux-aarch64, os: ubuntu-24.04-arm } + - { name: windows-x86_64, os: windows-latest } + - { name: windows-aarch64, os: windows-11-arm } + - { name: macos-x86_64, os: macos-15-intel } + - { name: macos-aarch64, os: macos-latest } + name: build (${{ matrix.name }}) + runs-on: ${{ matrix.os }} + defaults: + run: + shell: bash + working-directory: native + steps: + - uses: actions/checkout@v5 + - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + cache-workspaces: native + rustflags: "" + - uses: actions/download-artifact@v4 + with: + name: guests + path: native/guests/out + - name: Build + run: cargo build --locked --release + - name: Verify capture/restore + run: ./target/release/shuttle-runner verify guests/out/bios.wasm guests/out/os.wasm guests/out/child.wasm diff --git a/native/README.md b/native/README.md index 66e25c4..5004ecf 100644 --- a/native/README.md +++ b/native/README.md @@ -28,13 +28,35 @@ update: ## Build and run +Scripts (they build the guests, build the workspace and run `verify`): + +```sh +./native/scripts/build.sh # Linux / WSL2: dev build + verify +./native/scripts/build.sh --release # release build + verify +./native/scripts/build.sh --cross aarch64 # Linux arm64 via `cross` (build only) +``` +```powershell +.\native\scripts\build.ps1 # Windows: dev build + verify +.\native\scripts\build.ps1 -Release +``` + +Requirements: Rust (rustup); clang + wasm-ld (`sudo apt install clang lld` +on Linux/WSL2, the LLVM installer on Windows); `cross` + Docker only for +`--cross`. + +By hand, inside `native/`: + ```sh -sh guests/build.sh # run inside native/; needs clang + wasm-ld (no wasi-sdk needed) +sh guests/build.sh cargo build ./target/debug/shuttle-runner run guests/out/bios.wasm guests/out/os.wasm guests/out/child.wasm ./target/debug/shuttle-runner verify guests/out/bios.wasm guests/out/os.wasm guests/out/child.wasm ``` +CI (`.github/workflows/native.yml`) builds the guests once on Linux, then +builds and runs `verify` on Linux, Windows and macOS, each on x86_64 and +arm64. + `run` boots and prints the log until power-off. `verify` runs once without interruption, then once per tick boundary with capture → restore into a brand-new Machine → continue, and compares the log streams. A control run diff --git a/native/scripts/build.ps1 b/native/scripts/build.ps1 new file mode 100644 index 0000000..81c2fc8 --- /dev/null +++ b/native/scripts/build.ps1 @@ -0,0 +1,56 @@ +# Build and verify the Shuttle native workspace on Windows (PowerShell). +# +# .\native\scripts\build.ps1 dev build + verify +# .\native\scripts\build.ps1 -Release release build + verify +# .\native\scripts\build.ps1 -SkipVerify build only +# +# Needs: Rust (rustup), and LLVM for clang + wasm-ld +# (installer: https://github.com/llvm/llvm-project/releases). +param( + [switch]$Release, + [switch]$SkipVerify +) +$ErrorActionPreference = 'Stop' + +$Native = Resolve-Path (Join-Path $PSScriptRoot '..') +Set-Location $Native + +$Profile = if ($Release) { 'release' } else { 'dev' } +$ProfileDir = if ($Release) { 'release' } else { 'debug' } + +function Need($cmd, $hint) { + if (-not (Get-Command $cmd -ErrorAction SilentlyContinue)) { + throw "'$cmd' not found. $hint" + } +} + +# The LLVM installer does not always add itself to PATH. +$llvm = Join-Path $env:ProgramFiles 'LLVM\bin' +if (-not (Get-Command clang -ErrorAction SilentlyContinue) -and (Test-Path $llvm)) { + $env:PATH = "$llvm;$env:PATH" +} + +Write-Host '== guests (C -> wasm32)' +Need clang 'Install LLVM from https://github.com/llvm/llvm-project/releases' +Need wasm-ld 'wasm-ld comes with the LLVM installer' +New-Item -ItemType Directory -Force -Path 'guests\out' | Out-Null +foreach ($prog in 'bios', 'os', 'child') { + # same flags as guests/build.sh + & clang --target=wasm32 -O2 -nostdlib -ffreestanding ` + -Wall -Wno-unused-function ` + '-Wl,--no-entry' '-Wl,--export=_start' '-Wl,-z,stack-size=65536' ` + -o "guests\out\$prog.wasm" "guests\$prog.c" + if ($LASTEXITCODE -ne 0) { throw "clang failed for $prog.c" } +} + +Need cargo 'Install Rust from https://rustup.rs' +Write-Host "== cargo build ($Profile)" +& cargo build --locked --profile $Profile +if ($LASTEXITCODE -ne 0) { throw 'cargo build failed' } + +if (-not $SkipVerify) { + Write-Host '== verify (capture/restore at every tick)' + & ".\target\$ProfileDir\shuttle-runner.exe" verify ` + guests\out\bios.wasm guests\out\os.wasm guests\out\child.wasm + if ($LASTEXITCODE -ne 0) { throw 'verify failed' } +} diff --git a/native/scripts/build.sh b/native/scripts/build.sh new file mode 100755 index 0000000..7ec2cd6 --- /dev/null +++ b/native/scripts/build.sh @@ -0,0 +1,59 @@ +#!/usr/bin/env bash +# Build and verify the Shuttle native workspace on Linux / WSL2. +# +# ./native/scripts/build.sh dev build + verify +# ./native/scripts/build.sh --release release build + verify +# ./native/scripts/build.sh --cross aarch64 build for Linux arm64 with `cross` (no verify) +# ./native/scripts/build.sh --skip-verify build only +# +# Needs: Rust (rustup), clang and lld (`sudo apt install clang lld`). +# `--cross` also needs `cargo install cross` and a running Docker. +set -euo pipefail + +NATIVE="$(cd "$(dirname "$0")/.." && pwd)" +cd "$NATIVE" + +PROFILE=dev +PROFILE_DIR=debug +CROSS_ARCH="" +VERIFY=1 + +while [ $# -gt 0 ]; do + case "$1" in + --release) PROFILE=release; PROFILE_DIR=release ;; + --cross) CROSS_ARCH="${2:?--cross needs an architecture, e.g. aarch64}"; shift ;; + --skip-verify) VERIFY=0 ;; + -h|--help) sed -n '2,11p' "$0"; exit 0 ;; + *) echo "unknown option: $1" >&2; exit 2 ;; + esac + shift +done + +need() { + command -v "$1" >/dev/null 2>&1 || { echo "error: '$1' not found. $2" >&2; exit 1; } +} + +echo "== guests (C -> wasm32)" +need clang "Install it with: sudo apt install clang lld" +need wasm-ld "Install it with: sudo apt install lld" +sh guests/build.sh + +if [ -n "$CROSS_ARCH" ]; then + need cross "Install it with: cargo install cross (Docker must be running)" + TARGET="${CROSS_ARCH}-unknown-linux-gnu" + echo "== cross build for $TARGET ($PROFILE)" + cross build --locked --profile "$PROFILE" --target "$TARGET" + echo "built: target/$TARGET/$PROFILE_DIR/" + echo "(verify is skipped for cross builds: the binary is for another CPU)" + exit 0 +fi + +need cargo "Install Rust from https://rustup.rs" +echo "== cargo build ($PROFILE)" +cargo build --locked --profile "$PROFILE" + +if [ "$VERIFY" = 1 ]; then + echo "== verify (capture/restore at every tick)" + "target/$PROFILE_DIR/shuttle-runner" verify \ + guests/out/bios.wasm guests/out/os.wasm guests/out/child.wasm +fi From fc75ca75c9ca48c2e28749c041bb10c6c25eb106 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 15 Oct 2026 14:16:39 +0900 Subject: [PATCH 03/15] Add native/HANDOFF.md: context for continuing in Claude Code Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01WE6jR1fQDhj3HTdNWb73L9 --- native/HANDOFF.md | 101 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 native/HANDOFF.md diff --git a/native/HANDOFF.md b/native/HANDOFF.md new file mode 100644 index 0000000..2b12772 --- /dev/null +++ b/native/HANDOFF.md @@ -0,0 +1,101 @@ +# Handoff notes (from the claude.ai chat, 2026-10-15) + +Read this first when continuing the work in Claude Code. Follow CLAUDE.md: +ask before deciding anything, and explain concretely. + +## 1. What the project is + +A Minecraft computer mod (like OpenComputers / CC:Tweaked) whose computers +run **WebAssembly** programs. Everything the player runs is Wasm: a BIOS +(stored in an EEPROM item), an OS kernel, and the OS's child programs. + +- Runtime: **Wasmtime**, made checkpointable with **Weave** (a Wasm + transformer that can unwind a running program into its linear memory and + rebuild it later). This is how a computer is saved with the world and + resumes mid-execution after a reload. +- Layers: firmware (provided by the mod) -> BIOS (player-made) -> OS + (player-made) -> child programs. The firmware talks to guests only + through the firmware ABI, never through Wasmtime APIs. +- Native code: Rust (Wasmtime + Weave + JNI). Mod side: Java (NeoForge). +- Targets: Windows, macOS, Linux, each x86_64 and arm64. + +## 2. Where things are + +| What | Where | +| --- | --- | +| This repo | `akkiserver-dev/shuttle` (renamed from `wasmtime-ng`), Java Wasmtime binding + `native/` | +| Weave fork | `akkiserver-dev/weave`, branch `shuttle-host-hooks` (commit `677cce6`) | +| Shuttle core prototype | branch `feature/shuttle-core` (`native/`) | +| Build scripts + CI | branch `feature/native-build` (on top of `feature/shuttle-core`) | +| Draft PR (CI check only, not for merging) | `akkiserver-dev/shuttle` PR #1 | +| Firmware ABI spec (Japanese) | https://claude.ai/code/artifact/05272d17-ac4c-4f56-933a-374281672f79 | + +`native/README.md` explains the prototype, how to build it, and the results. + +## 3. Current state + +- `native/` boots BIOS -> `exec` -> OS -> `co_create` -> child -> exit, in a + headless runner. Capture/restore at every tick boundary gives identical + logs (26/26), and a control run that drops the host-side child table + diverges (24/24), so the check is meaningful. Snapshots are 5-8 KB gzip. +- CI (`.github/workflows/native.yml`) passed on all six platforms on PR #1. +- `native/scripts/build.ps1` (Windows) has **never been run**. Test it first. +- "Java CI with Maven" fails, also on `main` itself (commit `d400a75`), so it + is not caused by `native/`. The log could not be read from the chat + sandbox; check it locally. +- **`main` moved on**: commit `d400a75 "Weave JNI"` (by the owner) added a + Weave JNI layer in `wasmtimejavang` (`WeaveModule`, `WeaveInstance`, + `weave.rs`, ...) pinned to Weave `0f26893`, i.e. *without* the + `shuttle-host-hooks` patch. The feature branches are based on `917ffd6`, + before that commit. How this JNI layer and `native/shuttle-core` fit + together has **not been discussed yet**. + +## 4. Decided with the owner + +- Rust/Java boundary: Weave, `co_*`, VM exits, memory pool and snapshot + capture live in Rust. Device implementations live in Java and are called + directly from Rust (JNI) on worker threads; world-touching work is queued + to the server thread. Mod code sees a high-level Machine API only. +- Threads: Rust owns a worker pool (reliable stack sizes for + `max_wasm_stack`). Saving is split: capture on the worker at a tick + boundary, compress and write on a separate save thread. +- Persistence: NBT/DataComponents hold only a UUID and small metadata; the + snapshot and file systems are separate files in the world folder. +- ABI shape (see the spec): balanced realism. Kept: `cpuid` strings, slots + on a bus, `hlt`, `exec`, `co_*` VM exits. Dropped: register I/O, manual + DMA rings. Device calls are OC-like method calls, sync (`dev_call`) and + async (`dev_submit` + completion event). Interrupts are polled. +- `cpuid` vendor and model names are set by the player in the assembler; + other CPU properties come from parts. Feature flags map to Wasm features. +- Runtimes are switchable through an OC-style Architecture abstraction. Lua + comes later (Wasm-hosted Lua preferred; JNLua as a compatibility option). +- Build: option C. Local scripts for Windows and WSL2 build the host target; + release binaries for all six platforms come from CI. +- Weave may be modified freely. +- Branches: `feature/` and `fix/`. CLAUDE.md lives on `main`. + +## 5. NOT approved yet (decided by Claude without asking; review each) + +1. `dev_call` result that does not fit `rcap`: held in one slot and fetched + with `dev_result(-1, ...)`; replaced by the next `dev_call`. +2. Kernel memory: the kernel may use whatever its children have not + reserved; `co_create` fails with `E_NOMEM` when kernel memory + + reservations + the new limit exceed the CPU's memory. +3. Weave API names: `TransformOptions::yielding_imports`, + `weave_wasmtime::request_unwind`, `WeaveInstance::set_memory_limit`, + `Ctx::set_memory_limit`; branch name `shuttle-host-hooks`. +4. Prototype values: `poll_period` 64, `stack_pages` 4, default CPU + (clock 2000 polls/tick, 64 MiB), event queue 256, `exec` args 4 KiB, + 16 async requests, log 64 lines/tick, the guests' syscall numbers, and + the snapshot format (`SHTL`, format 2). +5. `native/` layout details (`crates/`, `guests/`, `scripts/`), and that + built `.wasm` files are not committed. + +## 6. Next steps (in order, ask before each) + +1. Run `native/scripts/build.ps1` on Windows and `build.sh` on WSL2. +2. Look at why "Java CI with Maven" fails on `main`. +3. Review the unapproved items in section 5. +4. Decide how the `d400a75` Weave JNI layer and `native/shuttle-core` + relate, then design the JNI layer for the Machine API. +5. Rebase the feature branches onto the current `main`. From af5d40eb4b53aebeb200b5fe93142d0984f6a98c Mon Sep 17 00:00:00 2001 From: akki <151368291+akki697222@users.noreply.github.com> Date: Thu, 15 Oct 2026 14:56:09 +0900 Subject: [PATCH 04/15] README: rewrite for Shuttle, keep binding docs as a section Co-Authored-By: Claude Opus 5.5 --- README.md | 97 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 73 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 45a6d96..d319d34 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,57 @@ -[![CI](https://github.com/StefanRichterHuber/wasmtime-ng/actions/workflows/maven.yml/badge.svg?branch=main)](https://github.com/StefanRichterHuber/wasmtime-ng/actions/workflows/maven.yml) +[![Native (Shuttle)](https://github.com/akkiserver-dev/shuttle/actions/workflows/native.yml/badge.svg)](https://github.com/akkiserver-dev/shuttle/actions/workflows/native.yml) -# Wasmtime-java-ng +# Shuttle -> **Disclaimer:** This project is an independent community effort and is not affiliated with, maintained, or endorsed by the original [Wasmtime project](https://github.com/bytecodealliance/wasmtime) or the Bytecode Alliance. +> **Status:** early prototype. Nothing here is playable yet; the native core runs headless only. + +Shuttle is a Minecraft (NeoForge) mod that adds programmable computers, in the spirit of OpenComputers and CC:Tweaked. Unlike those mods, everything a Shuttle computer runs is **WebAssembly**: + +``` +firmware (provided by the mod) + └─ BIOS player-made Wasm, stored on an EEPROM item + └─ OS kernel player-made Wasm, started by the BIOS with `exec` + └─ child programs started by the kernel with `co_create` +``` + +The firmware talks to guests only through the **firmware ABI** (`fw.*`, `co.*`, `sys.call`). Device calls look like OpenComputers method calls, either synchronous (`dev_call`) or asynchronous (`dev_submit` + a completion event). + +## How it works + +- **Runtime:** [Wasmtime](https://github.com/bytecodealliance/wasmtime), made checkpointable with [Weave](https://github.com/akkiserver-dev/weave) (branch `shuttle-host-hooks`). Weave transforms a Wasm module so that a running program can be unwound into its linear memory and rebuilt later. This lets a computer be saved with the world and continue mid-execution after a reload. +- **Native core (Rust):** Wasmtime, Weave, the `co_*` machinery, memory limits and snapshot capture. It runs guests on its own worker thread pool. +- **Mod (Java):** device implementations and the high-level Machine API, connected to the native core through JNI. +- **Targets:** Windows, macOS and Linux, each on x86_64 and arm64. + +## Repository layout + +| Path | What | +| --- | --- | +| [`native/`](native) | Shuttle native core (Rust): `shuttle-core`, the headless `shuttle-runner`, and C test guests. See [`native/README.md`](native/README.md). | +| [`wasmtimejavang/`](wasmtimejavang) | Java bindings for Wasmtime (see [below](#wasmtime-java-binding-wasmtimejavang)). | +| [`wit-parser/`](wit-parser), [`wit-codegen-maven-plugin/`](wit-codegen-maven-plugin) | Build-time WIT tooling for the Java bindings. | + +## Building the native core + +Requirements: Rust (rustup), and clang + wasm-ld for the C guests (the [LLVM installer](https://github.com/llvm/llvm-project/releases) on Windows, `sudo apt install clang lld` on Linux/WSL2). + +```powershell +.\native\scripts\build.ps1 # Windows: build guests + workspace, then verify +``` +```sh +./native/scripts/build.sh # Linux / WSL2 +``` + +`verify` boots BIOS → OS → child, then repeats the run with capture → restore into a fresh machine at every tick boundary and checks that the logs are identical. Release binaries for all six platforms are built by CI ([`.github/workflows/native.yml`](.github/workflows/native.yml)). + +## Credits and license + +The Java Wasmtime bindings in this repository are a fork of [StefanRichterHuber/wasmtime-ng](https://github.com/StefanRichterHuber/wasmtime-ng) (MIT, © 2024 Stefan Richter-Huber). See [LICENSE](LICENSE). + +> **Disclaimer:** This project is an independent community effort and is not affiliated with, maintained, or endorsed by the [Wasmtime project](https://github.com/bytecodealliance/wasmtime), the Bytecode Alliance, Mojang or Microsoft. + +## Wasmtime Java binding (wasmtimejavang) + +The rest of this document comes from the upstream project and describes the Java bindings. > **AI Disclaimer:** Parts of this project were vibe-coded or written with the help of an AI assistant (Claude); the remaining parts were written by hand. @@ -10,7 +59,7 @@ Wasmtime-java-ng provides Java bindings for [Wasmtime](https://github.com/byteco This project allows Java applications to execute WebAssembly modules, interact with linear memory, and leverage the WebAssembly System Interface (WASI) through a native bridge built on Rust. -## Project Structure +### Project Structure This repository is a Maven multi-module reactor. As of this version, `wasmtimejavang` is a **core** artifact (Wasmtime primitives, the Component Model plumbing, WASI Preview 1) plus one artifact per WASI Preview 2 "world" — so a consumer only pulls in the WASI Preview 2 support they actually use, instead of everything at once: @@ -21,7 +70,7 @@ This repository is a Maven multi-module reactor. As of this version, `wasmtimeja Pick only the artifacts you need: depending on `wasmtimejavang` alone gets you core-wasm + WASI Preview 1, with no Component Model support at all; add whichever `wasmtimejavang-wasi-*` artifacts you actually need (each transitively pulls in `wasmtimejavang-wasi-io` where required) — e.g. just `wasmtimejavang-wasi-http` for an outgoing-HTTP-only guest, or `wasmtimejavang-wasi-cli` + `wasmtimejavang-wasi-filesystem` for a sandboxed-filesystem CLI tool. -## Prerequisites +### Prerequisites Building this project requires both Rust and Java toolchains: @@ -29,7 +78,7 @@ Building this project requires both Rust and Java toolchains: * **Rust** and **Cargo** * **[cross-rs](https://github.com/cross-rs/cross)** and **Docker** (required for cross-platform native builds) -## Building +### Building The project uses Maven to orchestrate both the Java compilation and the Rust native build. To build the entire project for Linux x86_64: @@ -37,7 +86,7 @@ The project uses Maven to orchestrate both the Java compilation and the Rust nat mvn clean install ``` -### Multi-Platform Builds +#### Multi-Platform Builds By default, only the native library for Linux x86_64 is built. You can target specific platforms using Maven profiles: @@ -57,7 +106,7 @@ For production environments, the `release` profile optimizes the Rust binaries f mvn -P release,build-linux-x86-64,build-linux-aarch64,build-windows-x86_64 clean install ``` -## Usage +### Usage Include the core dependency into your project `pom.xml` (the published artifact contains native libraries for Linux x86_64, Linux aarch64 and Windows x86_64): @@ -79,7 +128,7 @@ This alone gets you core-wasm execution and WASI Preview 1 — no WASI Preview 2 ``` -### Function Imports +#### Function Imports You can import Java methods into the WebAssembly context, allowing WASM modules to invoke native Java code. @@ -111,7 +160,7 @@ try ( } ``` -### Supported WASM Types +#### Supported WASM Types All type conversions are bi-directional if not mentioned otherwise. @@ -125,7 +174,7 @@ All type conversions are bi-directional if not mentioned otherwise. | **`FuncRef`** | `io.github.stefanrichterhuber.wasmtimejavang.WasmtimeFunction` | Callable function reference. Currently export from wasm to java supported | | **`ExternRef`** | any java object | Any java object can be passed through the wasm runtime as extern ref | -### Memory Interaction +#### Memory Interaction The `WasmtimeMemory` class provides efficient access to the WASM linear memory by mapping it directly to a `java.nio.ByteBuffer`. @@ -164,11 +213,11 @@ try (WasmtimeInstance instance = new WasmtimeInstance(store, module, linker)) { } ``` -## WASI Snapshot Preview 1 +### WASI Snapshot Preview 1 While Wasmtime provides built-in WASI support, this library implements WASI Preview 1 directly on the Java side (`WasiPI1Context`). This approach reduces indirection and allows WASM modules to interact directly with Java objects, such as `InputStream`, `OutputStream`, and virtual filesystems. -### Virtualized Filesystem +#### Virtualized Filesystem To protect the host system, you can use a virtual filesystem like [JimFS](https://github.com/google/jimfs) to provide a sandboxed environment for the WASM module. @@ -189,7 +238,7 @@ try (FileSystem fs = Jimfs.newFileSystem(Configuration.unix())) { } ``` -### Supported WASI Functions +#### Supported WASI Functions | Category | Functions | Status | Configuration | | :--- | :--- | :---: | :--- | @@ -204,7 +253,7 @@ try (FileSystem fs = Jimfs.newFileSystem(Configuration.unix())) { | **Network** | `sock_accept`, `sock_recv`, `sock_send`, `sock_shutdown` | ✅ | `withSocket()`, `withServerSocket()` | | **Polling** | `poll_oneoff` | 🟡 | Clock events supported | -### Configuration Options +#### Configuration Options `WasiPI1Context` provides a fluent API for resource virtualization: @@ -214,7 +263,7 @@ try (FileSystem fs = Jimfs.newFileSystem(Configuration.unix())) { * `withSocket(java.net.Socket)`: Pre-opens a client socket. * `withServerSocket(java.net.ServerSocket)`: Pre-opens a listening socket. -### WASI threads +#### WASI threads There is some preliminary support for WASI threads using the additional context `WasiThreadContext`. @@ -250,7 +299,7 @@ There is some preliminary support for WASI threads using the additional context > **Info:** As of now, nightly toolchain is required to properly build rust wasm wasip1 apps with thread support! -## WASI Preview 2 / Component Model (`wasm32-wasip2`) +### WASI Preview 2 / Component Model (`wasm32-wasip2`) Alongside core-module WASI Preview 1, this library supports the [Component Model](https://component-model.bytecodealliance.org/) (`wasm32-wasip2` binaries) — again with WASI implemented on the Java side rather than delegated to `wasmtime-wasi`. It's built from three pieces: @@ -282,7 +331,7 @@ try ( `linkRequired` only fills in interfaces nothing has already been linked for, so `linkContext(...)` calls made beforehand always take precedence — this is also the mechanism for overriding built-in behavior (see below). -### Supported WASI Preview 2 interfaces +#### Supported WASI Preview 2 interfaces Each interface group lives in its own `WasmComponentContext` implementation under the `wasip2` package, each in its own Maven artifact, and all seven are auto-discovered by `linkRequired(...)` with zero configuration as long as their artifact is on the classpath — see [Project Structure](#project-structure). @@ -330,7 +379,7 @@ linker.linkContext(new WasiHttpContext()); linker.linkRequired(component); // pulls in wasi-io, wasi-clocks, wasi-random ``` -### Implementing your own component context +#### Implementing your own component context This is the mechanism that matters most for actually using this library: WASI is just the *built-in* set of `WasmComponentContext` implementations, and any Java application can define its own to expose custom host functionality — database access, business logic, whatever — to a component's imports, the exact same way. There are two ways to implement one: hand-write it directly against `WasmComponentContext` (full control, shown first below), or generate a typed interface from a WIT file via `wit-codegen-maven-plugin` and implement just the typed methods (less boilerplate — no manual version-string wiring or `Object[]` casts). Both are shown below using the same example (its full source is in the repo and covered by `WasmtimeCustomComponentTest`, so it's guaranteed to stay in sync with the code, not just aspirational documentation). @@ -517,7 +566,7 @@ public void onDependenciesResolved(ComponentContextLookup lookup) { **Watch out:** `getProvidedInterfaces()` must be overridden (or, for a generated interface, already resolve correctly) even for a context that's *always* linked explicitly via `linkContext(...)` and never registered for `ServiceLoader` discovery — if that same call site also calls `linkRequired(...)` afterwards (as step 4 does), `linkRequired` has no other way to know the explicitly-linked context already satisfies the interface, and raises `IllegalStateException` for it. This is why the hand-written `GreetComponentContext` overrides `getProvidedInterfaces()` above even though it's never meant to be auto-discovered. -### Overriding a built-in WASI Preview 2 context +#### Overriding a built-in WASI Preview 2 context None of the `Wasi*Context` classes are `final`, and the built-ins are only ever *auto-linked* — never forced — so there are two ways to override one: @@ -537,11 +586,11 @@ public class Ipv6TcpSocketsContext extends WasiSocketsContext { These generated interfaces are regular public types shipped in the jar, under `io.github.stefanrichterhuber.wasmtimejavang.wasip2.generated.wasicli` — see [Implementing your own component context](#implementing-your-own-component-context) above for how they're produced and how to generate your own from a custom WIT interface. -### Version negotiation +#### Version negotiation Every `WasmComponentContext` tracks a `SemanticVersion` (`withVersion`/`getVersion`), used to build the actual versioned interface name (e.g. `"wasi:cli/environment@0.2.6"`) each import is registered under — `getProvidedInterfaces()` itself stays version-independent (bare names), so lookup/auto-discovery doesn't need to know a component's exact required version up front. `getMiniumVersion()`/`getMaximumVersion()` (defaulted to accept anything) bound what `supportsVersion(...)` — and therefore `ComponentContextLookup.resolve(...)` — accepts; the built-in WASI contexts default to `0.2.6` (what `cargo build --target wasm32-wasip2` on current stable Rust actually emits) and accept `[0.0.1, 0.3.0]`, so they're ready for the eventual WASI 0.3 interfaces without code changes once toolchains catch up, but can be pinned with `.withVersion(...)` if a component needs something else within that range. `WasiHttpContext` is the one exception, defaulting to `0.2.8` and accepting `[0.2.0, 0.3.0]` — `wasi:http` isn't part of what the stable target emits automatically, so there's no single "current" version to match; `0.2.8` is simply what this project's own `wasi-http` WIT sources declare. -## Architecture +### Architecture `wasmtimejavang` (the core artifact — see [Project Structure](#project-structure) above for the other modules) is structured into three distinct layers: @@ -551,13 +600,13 @@ Every `WasmComponentContext` tracks a `SemanticVersion` (`withVersion`/`getVersi All modules are tested using JUnit. Test coverage is measured with Jacoco. The neccessary wasm modules for testing are build with rust (see each module's own `src/test/rust`, where present). Using `exec-maven-plugin` these wasm modules are build in the `generate-test-resources` phase. -## Breaking changes +### Breaking changes * **Version 6.x.x**: Splitting the project into separate modules — three at first (`wasmtimejavang`, `wit-parser`, `wit-codegen-maven-plugin`), now further split so every WASI Preview 2 world ships as its own artifact depending on a `wasmtimejavang` core (`wasmtimejavang-wasi-{io,clocks,random,cli,filesystem,sockets,http}` — see [Project Structure](#project-structure)); Introduction of the wit-parser to automatically generate bindings for wasm32-wasip2; No changes for wasm32-wasip1 support * **Version 5.x.x**: Introduction of wasm32-wasip2 support; No changes for wasm32-wasip1 support * **Version 4.x.x**: Changed signature of Wasmfunction -## Comparison to Previous Work +### Comparison to Previous Work This implementation aims to be more maintainable and feature-complete than earlier attempts: From 7dbc5b83648a6d0ec08e08e38bb432c6a4dbfaaf Mon Sep 17 00:00:00 2001 From: akki <151368291+akki697222@users.noreply.github.com> Date: Thu, 15 Oct 2026 15:06:55 +0900 Subject: [PATCH 05/15] README: move AI disclaimer into the Shuttle credits section Co-Authored-By: Claude Opus 5.5 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d319d34..53a0584 100644 --- a/README.md +++ b/README.md @@ -49,12 +49,12 @@ The Java Wasmtime bindings in this repository are a fork of [StefanRichterHuber/ > **Disclaimer:** This project is an independent community effort and is not affiliated with, maintained, or endorsed by the [Wasmtime project](https://github.com/bytecodealliance/wasmtime), the Bytecode Alliance, Mojang or Microsoft. +> **AI Disclaimer:** Parts of this project were vibe-coded or written with the help of an AI assistant (Claude); the remaining parts were written by hand. + ## Wasmtime Java binding (wasmtimejavang) The rest of this document comes from the upstream project and describes the Java bindings. -> **AI Disclaimer:** Parts of this project were vibe-coded or written with the help of an AI assistant (Claude); the remaining parts were written by hand. - Wasmtime-java-ng provides Java bindings for [Wasmtime](https://github.com/bytecodealliance/wasmtime), a fast, secure, and highly configurable WebAssembly runtime. This project allows Java applications to execute WebAssembly modules, interact with linear memory, and leverage the WebAssembly System Interface (WASI) through a native bridge built on Rust. From 983dc259f77554c3f04c2ba3995da37a443a26d4 Mon Sep 17 00:00:00 2001 From: akki <151368291+akki697222@users.noreply.github.com> Date: Thu, 15 Oct 2026 15:21:42 +0900 Subject: [PATCH 06/15] Rename to Shuttle: modules, Maven coordinates and packages - Directories: wasmtimejavang -> shuttle-java, wasmtimejavang-example -> shuttle-java-example, wit-parser -> shuttle-wit-parser, wit-codegen-maven-plugin -> shuttle-wit-maven-plugin - Maven: groupId jp.akkiserver, parent artifactId shuttle, module artifactIds match the directory names; url/scm point to akkiserver-dev/shuttle - Java packages: io.github.stefanrichterhuber.wasmtimejavang -> jp.akkiserver.shuttle, .witparser -> jp.akkiserver.shuttle.wit.parser, .witcodegen -> jp.akkiserver.shuttle.wit.codegen - Rust JNI class-name strings, native library resource paths (pom copy targets and loaders), the code generator's import template and .idea module names updated to match Co-Authored-By: Claude Opus 5.5 --- .idea/compiler.xml | 12 ++++----- .idea/encodings.xml | 16 ++++++------ README.md | 2 +- pom.xml | 24 ++++++++--------- .../pom.xml | 14 +++++----- .../java/example/VirtualComputerExample.java | 8 +++--- .../src/main/resources/guest.wat | 0 {wasmtimejavang => shuttle-java}/pom.xml | 20 +++++++------- .../shuttle}/ComponentContextLookup.java | 4 +-- .../shuttle}/ComponentFunction.java | 4 +-- .../shuttle}/ResourceDestructor.java | 2 +- .../akkiserver/shuttle}/SemanticVersion.java | 2 +- .../ServiceLoaderComponentContextLookup.java | 6 ++--- .../java/jp/akkiserver/shuttle}/V128.java | 2 +- .../java/jp/akkiserver/shuttle}/ValType.java | 2 +- .../shuttle}/WasmComponentContext.java | 2 +- .../jp/akkiserver/shuttle}/WasmContext.java | 2 +- .../shuttle}/WasmRuntimeException.java | 2 +- .../shuttle}/WasmtimeComponent.java | 2 +- .../shuttle}/WasmtimeComponentInstance.java | 2 +- .../shuttle}/WasmtimeComponentLinker.java | 8 +++--- .../akkiserver/shuttle}/WasmtimeEngine.java | 4 +-- .../akkiserver/shuttle}/WasmtimeFunction.java | 2 +- .../akkiserver/shuttle}/WasmtimeInstance.java | 2 +- .../akkiserver/shuttle}/WasmtimeLinker.java | 4 +-- .../shuttle}/WasmtimeLocalMemory.java | 2 +- .../akkiserver/shuttle}/WasmtimeMemory.java | 2 +- .../akkiserver/shuttle}/WasmtimeModule.java | 2 +- .../shuttle}/WasmtimeSharedMemory.java | 2 +- .../jp/akkiserver/shuttle}/WasmtimeStore.java | 2 +- .../jp/akkiserver/shuttle}/WeaveCaller.java | 4 +-- .../shuttle}/WeaveHostFunction.java | 2 +- .../jp/akkiserver/shuttle}/WeaveImport.java | 2 +- .../jp/akkiserver/shuttle}/WeaveInstance.java | 2 +- .../jp/akkiserver/shuttle}/WeaveModule.java | 2 +- .../jp/akkiserver/shuttle}/WeaveNative.java | 2 +- .../jp/akkiserver/shuttle}/WeaveResult.java | 2 +- .../shuttle}/component/WitEnum.java | 2 +- .../shuttle}/component/WitResource.java | 2 +- .../shuttle}/component/WitResult.java | 2 +- .../shuttle}/component/WitVariant.java | 2 +- .../shuttle}/internal/WasmtimeFuncRef.java | 6 ++--- .../src/main/rust/wasmtime-binding/.gitignore | 0 .../src/main/rust/wasmtime-binding/Cargo.lock | 0 .../src/main/rust/wasmtime-binding/Cargo.toml | 0 .../wasmtime-binding/src/java_collections.rs | 0 .../rust/wasmtime-binding/src/java_maps.rs | 0 .../rust/wasmtime-binding/src/java_numbers.rs | 0 .../src/main/rust/wasmtime-binding/src/lib.rs | 0 .../main/rust/wasmtime-binding/src/logging.rs | 0 .../wasmtime-binding/src/wasmcomponent.rs | 4 +-- .../src/wasmcomponentinstance.rs | 8 +++--- .../src/wasmcomponentlinker.rs | 16 ++++++------ .../src/wasmcomponentvalue.rs | 8 +++--- .../rust/wasmtime-binding/src/wasmcontext.rs | 2 +- .../rust/wasmtime-binding/src/wasmengine.rs | 2 +- .../wasmtime-binding/src/wasmexception.rs | 2 +- .../rust/wasmtime-binding/src/wasminstance.rs | 14 +++++----- .../rust/wasmtime-binding/src/wasmlinker.rs | 10 +++---- .../rust/wasmtime-binding/src/wasmmemory.rs | 6 ++--- .../rust/wasmtime-binding/src/wasmmodule.rs | 4 +-- .../wasmtime-binding/src/wasmsharedmemory.rs | 2 +- .../rust/wasmtime-binding/src/wasmstore.rs | 4 +-- .../wasmtime-binding/src/wasmtime_v128.rs | 2 +- .../wasmtime-binding/src/wasmtime_valtype.rs | 2 +- .../wasmtime-binding/src/wasmtimefuncref.rs | 6 ++--- .../wasmtime-binding/src/wasmtimefunction.rs | 4 +-- .../main/rust/wasmtime-binding/src/weave.rs | 12 ++++----- .../shuttle}/SemanticVersionTest.java | 2 +- .../java/jp/akkiserver/shuttle}/V128Test.java | 2 +- .../shuttle}/WasmtimeComponentTest.java | 2 +- .../shuttle}/WasmtimeEngineTest.java | 2 +- .../shuttle}/WasmtimeMemoryTest.java | 2 +- .../shuttle}/WasmtimeValueTest.java | 2 +- .../jp/akkiserver/shuttle}/WeaveTest.java | 2 +- .../test/resources/junit-platform.properties | 0 .../src/test/resources/log4j2.xml | 0 .../src/test/rust/valuetest/Cargo.lock | 0 .../src/test/rust/valuetest/Cargo.toml | 0 .../src/test/rust/valuetest/src/lib.rs | 0 .../pom.xml | 18 ++++++------- .../wit/codegen}/GenerateWitSourcesMojo.java | 6 ++--- .../wit/codegen}/WitCodeGenerator.java | 26 +++++++++---------- .../codegen}/GenerateWitSourcesMojoTest.java | 14 +++++----- .../GenerateWitSourcesMojoWorldTest.java | 9 ++++--- .../src/test/resources/wit/greet.wit | 0 .../resources/wit/wasi-cli/wit/command.wit | 0 .../test/resources/wit/wasi-cli/wit/deps.toml | 0 .../wit/deps/clocks/monotonic-clock.wit | 0 .../wit/wasi-cli/wit/deps/clocks/timezone.wit | 0 .../wasi-cli/wit/deps/clocks/wall-clock.wit | 0 .../wit/wasi-cli/wit/deps/clocks/world.wit | 0 .../wasi-cli/wit/deps/filesystem/preopens.wit | 0 .../wasi-cli/wit/deps/filesystem/types.wit | 0 .../wasi-cli/wit/deps/filesystem/world.wit | 0 .../wit/wasi-cli/wit/deps/io/error.wit | 0 .../wit/wasi-cli/wit/deps/io/poll.wit | 0 .../wit/wasi-cli/wit/deps/io/streams.wit | 0 .../wit/wasi-cli/wit/deps/io/world.wit | 0 .../wit/deps/random/insecure-seed.wit | 0 .../wit/wasi-cli/wit/deps/random/insecure.wit | 0 .../wit/wasi-cli/wit/deps/random/random.wit | 0 .../wit/wasi-cli/wit/deps/random/world.wit | 0 .../wit/deps/sockets/instance-network.wit | 0 .../wit/deps/sockets/ip-name-lookup.wit | 0 .../wit/wasi-cli/wit/deps/sockets/network.wit | 0 .../wit/deps/sockets/tcp-create-socket.wit | 0 .../wit/wasi-cli/wit/deps/sockets/tcp.wit | 0 .../wit/deps/sockets/udp-create-socket.wit | 0 .../wit/wasi-cli/wit/deps/sockets/udp.wit | 0 .../wit/wasi-cli/wit/deps/sockets/world.wit | 0 .../wit/wasi-cli/wit/environment.wit | 0 .../test/resources/wit/wasi-cli/wit/exit.wit | 0 .../resources/wit/wasi-cli/wit/imports.wit | 0 .../test/resources/wit/wasi-cli/wit/run.wit | 0 .../test/resources/wit/wasi-cli/wit/stdio.wit | 0 .../resources/wit/wasi-cli/wit/terminal.wit | 0 .../test/resources/wit/wasi-sockets/deps.lock | 0 .../test/resources/wit/wasi-sockets/deps.toml | 0 .../deps/clocks/monotonic-clock.wit | 0 .../wit/wasi-sockets/deps/clocks/timezone.wit | 0 .../wasi-sockets/deps/clocks/wall-clock.wit | 0 .../wit/wasi-sockets/deps/clocks/world.wit | 0 .../wit/wasi-sockets/deps/io/error.wit | 0 .../wit/wasi-sockets/deps/io/poll.wit | 0 .../wit/wasi-sockets/deps/io/streams.wit | 0 .../wit/wasi-sockets/deps/io/world.wit | 0 .../wit/wasi-sockets/instance-network.wit | 0 .../wit/wasi-sockets/ip-name-lookup.wit | 0 .../resources/wit/wasi-sockets/network.wit | 0 .../wit/wasi-sockets/tcp-create-socket.wit | 0 .../test/resources/wit/wasi-sockets/tcp.wit | 0 .../wit/wasi-sockets/udp-create-socket.wit | 0 .../test/resources/wit/wasi-sockets/udp.wit | 0 .../test/resources/wit/wasi-sockets/world.wit | 0 {wit-parser => shuttle-wit-parser}/pom.xml | 14 +++++----- .../shuttle/wit/parser}/WitFunction.java | 2 +- .../shuttle/wit/parser}/WitInterface.java | 2 +- .../shuttle/wit/parser}/WitParam.java | 2 +- .../shuttle/wit/parser}/WitParser.java | 4 +-- .../shuttle/wit/parser}/WitTypeKind.java | 2 +- .../shuttle/wit/parser}/WitValueType.java | 2 +- .../main/rust/wit-parser-binding/Cargo.lock | 0 .../main/rust/wit-parser-binding/Cargo.toml | 0 .../main/rust/wit-parser-binding/src/lib.rs | 14 +++++----- .../shuttle/wit/parser}/WitParserTest.java | 2 +- .../src/test/resources/wit/greet.wit | 0 .../resources/wit/wasi-cli/wit/command.wit | 0 .../test/resources/wit/wasi-cli/wit/deps.toml | 0 .../wit/deps/clocks/monotonic-clock.wit | 0 .../wit/wasi-cli/wit/deps/clocks/timezone.wit | 0 .../wasi-cli/wit/deps/clocks/wall-clock.wit | 0 .../wit/wasi-cli/wit/deps/clocks/world.wit | 0 .../wasi-cli/wit/deps/filesystem/preopens.wit | 0 .../wasi-cli/wit/deps/filesystem/types.wit | 0 .../wasi-cli/wit/deps/filesystem/world.wit | 0 .../wit/wasi-cli/wit/deps/io/error.wit | 0 .../wit/wasi-cli/wit/deps/io/poll.wit | 0 .../wit/wasi-cli/wit/deps/io/streams.wit | 0 .../wit/wasi-cli/wit/deps/io/world.wit | 0 .../wit/deps/random/insecure-seed.wit | 0 .../wit/wasi-cli/wit/deps/random/insecure.wit | 0 .../wit/wasi-cli/wit/deps/random/random.wit | 0 .../wit/wasi-cli/wit/deps/random/world.wit | 0 .../wit/deps/sockets/instance-network.wit | 0 .../wit/deps/sockets/ip-name-lookup.wit | 0 .../wit/wasi-cli/wit/deps/sockets/network.wit | 0 .../wit/deps/sockets/tcp-create-socket.wit | 0 .../wit/wasi-cli/wit/deps/sockets/tcp.wit | 0 .../wit/deps/sockets/udp-create-socket.wit | 0 .../wit/wasi-cli/wit/deps/sockets/udp.wit | 0 .../wit/wasi-cli/wit/deps/sockets/world.wit | 0 .../wit/wasi-cli/wit/environment.wit | 0 .../test/resources/wit/wasi-cli/wit/exit.wit | 0 .../resources/wit/wasi-cli/wit/imports.wit | 0 .../test/resources/wit/wasi-cli/wit/run.wit | 0 .../test/resources/wit/wasi-cli/wit/stdio.wit | 0 .../resources/wit/wasi-cli/wit/terminal.wit | 0 .../test/resources/wit/wasi-sockets/deps.lock | 0 .../test/resources/wit/wasi-sockets/deps.toml | 0 .../deps/clocks/monotonic-clock.wit | 0 .../wit/wasi-sockets/deps/clocks/timezone.wit | 0 .../wasi-sockets/deps/clocks/wall-clock.wit | 0 .../wit/wasi-sockets/deps/clocks/world.wit | 0 .../wit/wasi-sockets/deps/io/error.wit | 0 .../wit/wasi-sockets/deps/io/poll.wit | 0 .../wit/wasi-sockets/deps/io/streams.wit | 0 .../wit/wasi-sockets/deps/io/world.wit | 0 .../wit/wasi-sockets/instance-network.wit | 0 .../wit/wasi-sockets/ip-name-lookup.wit | 0 .../resources/wit/wasi-sockets/network.wit | 0 .../wit/wasi-sockets/tcp-create-socket.wit | 0 .../test/resources/wit/wasi-sockets/tcp.wit | 0 .../wit/wasi-sockets/udp-create-socket.wit | 0 .../test/resources/wit/wasi-sockets/udp.wit | 0 .../test/resources/wit/wasi-sockets/world.wit | 0 196 files changed, 213 insertions(+), 214 deletions(-) rename {wasmtimejavang-example => shuttle-java-example}/pom.xml (78%) rename {wasmtimejavang-example => shuttle-java-example}/src/main/java/example/VirtualComputerExample.java (96%) rename {wasmtimejavang-example => shuttle-java-example}/src/main/resources/guest.wat (100%) rename {wasmtimejavang => shuttle-java}/pom.xml (96%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/ComponentContextLookup.java (95%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/ComponentFunction.java (88%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/ResourceDestructor.java (90%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/SemanticVersion.java (96%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/ServiceLoaderComponentContextLookup.java (93%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/V128.java (99%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/ValType.java (84%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/WasmComponentContext.java (99%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/WasmContext.java (97%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/WasmRuntimeException.java (95%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/WasmtimeComponent.java (98%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/WasmtimeComponentInstance.java (98%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/WasmtimeComponentLinker.java (97%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/WasmtimeEngine.java (97%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/WasmtimeFunction.java (97%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/WasmtimeInstance.java (98%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/WasmtimeLinker.java (98%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/WasmtimeLocalMemory.java (98%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/WasmtimeMemory.java (99%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/WasmtimeModule.java (99%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/WasmtimeSharedMemory.java (98%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/WasmtimeStore.java (98%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/WeaveCaller.java (95%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/WeaveHostFunction.java (89%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/WeaveImport.java (95%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/WeaveInstance.java (99%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/WeaveModule.java (98%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/WeaveNative.java (97%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/WeaveResult.java (97%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/component/WitEnum.java (83%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/component/WitResource.java (97%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/component/WitResult.java (94%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/component/WitVariant.java (87%) rename {wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/main/java/jp/akkiserver/shuttle}/internal/WasmtimeFuncRef.java (90%) rename {wasmtimejavang => shuttle-java}/src/main/rust/wasmtime-binding/.gitignore (100%) rename {wasmtimejavang => shuttle-java}/src/main/rust/wasmtime-binding/Cargo.lock (100%) rename {wasmtimejavang => shuttle-java}/src/main/rust/wasmtime-binding/Cargo.toml (100%) rename {wasmtimejavang => shuttle-java}/src/main/rust/wasmtime-binding/src/java_collections.rs (100%) rename {wasmtimejavang => shuttle-java}/src/main/rust/wasmtime-binding/src/java_maps.rs (100%) rename {wasmtimejavang => shuttle-java}/src/main/rust/wasmtime-binding/src/java_numbers.rs (100%) rename {wasmtimejavang => shuttle-java}/src/main/rust/wasmtime-binding/src/lib.rs (100%) rename {wasmtimejavang => shuttle-java}/src/main/rust/wasmtime-binding/src/logging.rs (100%) rename {wasmtimejavang => shuttle-java}/src/main/rust/wasmtime-binding/src/wasmcomponent.rs (97%) rename {wasmtimejavang => shuttle-java}/src/main/rust/wasmtime-binding/src/wasmcomponentinstance.rs (96%) rename {wasmtimejavang => shuttle-java}/src/main/rust/wasmtime-binding/src/wasmcomponentlinker.rs (94%) rename {wasmtimejavang => shuttle-java}/src/main/rust/wasmtime-binding/src/wasmcomponentvalue.rs (98%) rename {wasmtimejavang => shuttle-java}/src/main/rust/wasmtime-binding/src/wasmcontext.rs (52%) rename {wasmtimejavang => shuttle-java}/src/main/rust/wasmtime-binding/src/wasmengine.rs (98%) rename {wasmtimejavang => shuttle-java}/src/main/rust/wasmtime-binding/src/wasmexception.rs (98%) rename {wasmtimejavang => shuttle-java}/src/main/rust/wasmtime-binding/src/wasminstance.rs (96%) rename {wasmtimejavang => shuttle-java}/src/main/rust/wasmtime-binding/src/wasmlinker.rs (95%) rename {wasmtimejavang => shuttle-java}/src/main/rust/wasmtime-binding/src/wasmmemory.rs (96%) rename {wasmtimejavang => shuttle-java}/src/main/rust/wasmtime-binding/src/wasmmodule.rs (96%) rename {wasmtimejavang => shuttle-java}/src/main/rust/wasmtime-binding/src/wasmsharedmemory.rs (98%) rename {wasmtimejavang => shuttle-java}/src/main/rust/wasmtime-binding/src/wasmstore.rs (98%) rename {wasmtimejavang => shuttle-java}/src/main/rust/wasmtime-binding/src/wasmtime_v128.rs (97%) rename {wasmtimejavang => shuttle-java}/src/main/rust/wasmtime-binding/src/wasmtime_valtype.rs (97%) rename {wasmtimejavang => shuttle-java}/src/main/rust/wasmtime-binding/src/wasmtimefuncref.rs (94%) rename {wasmtimejavang => shuttle-java}/src/main/rust/wasmtime-binding/src/wasmtimefunction.rs (59%) rename {wasmtimejavang => shuttle-java}/src/main/rust/wasmtime-binding/src/weave.rs (97%) rename {wasmtimejavang/src/test/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/test/java/jp/akkiserver/shuttle}/SemanticVersionTest.java (97%) rename {wasmtimejavang/src/test/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/test/java/jp/akkiserver/shuttle}/V128Test.java (99%) rename {wasmtimejavang/src/test/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/test/java/jp/akkiserver/shuttle}/WasmtimeComponentTest.java (98%) rename {wasmtimejavang/src/test/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/test/java/jp/akkiserver/shuttle}/WasmtimeEngineTest.java (99%) rename {wasmtimejavang/src/test/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/test/java/jp/akkiserver/shuttle}/WasmtimeMemoryTest.java (98%) rename {wasmtimejavang/src/test/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/test/java/jp/akkiserver/shuttle}/WasmtimeValueTest.java (99%) rename {wasmtimejavang/src/test/java/io/github/stefanrichterhuber/wasmtimejavang => shuttle-java/src/test/java/jp/akkiserver/shuttle}/WeaveTest.java (99%) rename {wasmtimejavang => shuttle-java}/src/test/resources/junit-platform.properties (100%) rename {wasmtimejavang => shuttle-java}/src/test/resources/log4j2.xml (100%) rename {wasmtimejavang => shuttle-java}/src/test/rust/valuetest/Cargo.lock (100%) rename {wasmtimejavang => shuttle-java}/src/test/rust/valuetest/Cargo.toml (100%) rename {wasmtimejavang => shuttle-java}/src/test/rust/valuetest/src/lib.rs (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/pom.xml (84%) rename {wit-codegen-maven-plugin/src/main/java/io/github/stefanrichterhuber/witcodegen => shuttle-wit-maven-plugin/src/main/java/jp/akkiserver/shuttle/wit/codegen}/GenerateWitSourcesMojo.java (97%) rename {wit-codegen-maven-plugin/src/main/java/io/github/stefanrichterhuber/witcodegen => shuttle-wit-maven-plugin/src/main/java/jp/akkiserver/shuttle/wit/codegen}/WitCodeGenerator.java (93%) rename {wit-codegen-maven-plugin/src/test/java/io/github/stefanrichterhuber/witcodegen => shuttle-wit-maven-plugin/src/test/java/jp/akkiserver/shuttle/wit/codegen}/GenerateWitSourcesMojoTest.java (89%) rename {wit-codegen-maven-plugin/src/test/java/io/github/stefanrichterhuber/witcodegen => shuttle-wit-maven-plugin/src/test/java/jp/akkiserver/shuttle/wit/codegen}/GenerateWitSourcesMojoWorldTest.java (94%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/greet.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/command.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/deps.toml (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/deps/clocks/monotonic-clock.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/deps/clocks/timezone.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/deps/clocks/wall-clock.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/deps/clocks/world.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/deps/filesystem/preopens.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/deps/filesystem/types.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/deps/filesystem/world.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/deps/io/error.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/deps/io/poll.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/deps/io/streams.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/deps/io/world.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/deps/random/insecure-seed.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/deps/random/insecure.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/deps/random/random.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/deps/random/world.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/deps/sockets/instance-network.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/deps/sockets/ip-name-lookup.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/deps/sockets/network.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/deps/sockets/tcp-create-socket.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/deps/sockets/tcp.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/deps/sockets/udp-create-socket.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/deps/sockets/udp.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/deps/sockets/world.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/environment.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/exit.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/imports.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/run.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/stdio.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-cli/wit/terminal.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-sockets/deps.lock (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-sockets/deps.toml (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-sockets/deps/clocks/monotonic-clock.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-sockets/deps/clocks/timezone.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-sockets/deps/clocks/wall-clock.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-sockets/deps/clocks/world.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-sockets/deps/io/error.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-sockets/deps/io/poll.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-sockets/deps/io/streams.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-sockets/deps/io/world.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-sockets/instance-network.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-sockets/ip-name-lookup.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-sockets/network.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-sockets/tcp-create-socket.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-sockets/tcp.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-sockets/udp-create-socket.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-sockets/udp.wit (100%) rename {wit-codegen-maven-plugin => shuttle-wit-maven-plugin}/src/test/resources/wit/wasi-sockets/world.wit (100%) rename {wit-parser => shuttle-wit-parser}/pom.xml (92%) rename {wit-parser/src/main/java/io/github/stefanrichterhuber/witparser => shuttle-wit-parser/src/main/java/jp/akkiserver/shuttle/wit/parser}/WitFunction.java (97%) rename {wit-parser/src/main/java/io/github/stefanrichterhuber/witparser => shuttle-wit-parser/src/main/java/jp/akkiserver/shuttle/wit/parser}/WitInterface.java (96%) rename {wit-parser/src/main/java/io/github/stefanrichterhuber/witparser => shuttle-wit-parser/src/main/java/jp/akkiserver/shuttle/wit/parser}/WitParam.java (92%) rename {wit-parser/src/main/java/io/github/stefanrichterhuber/witparser => shuttle-wit-parser/src/main/java/jp/akkiserver/shuttle/wit/parser}/WitParser.java (96%) rename {wit-parser/src/main/java/io/github/stefanrichterhuber/witparser => shuttle-wit-parser/src/main/java/jp/akkiserver/shuttle/wit/parser}/WitTypeKind.java (98%) rename {wit-parser/src/main/java/io/github/stefanrichterhuber/witparser => shuttle-wit-parser/src/main/java/jp/akkiserver/shuttle/wit/parser}/WitValueType.java (91%) rename {wit-parser => shuttle-wit-parser}/src/main/rust/wit-parser-binding/Cargo.lock (100%) rename {wit-parser => shuttle-wit-parser}/src/main/rust/wit-parser-binding/Cargo.toml (100%) rename {wit-parser => shuttle-wit-parser}/src/main/rust/wit-parser-binding/src/lib.rs (97%) rename {wit-parser/src/test/java/io/github/stefanrichterhuber/witparser => shuttle-wit-parser/src/test/java/jp/akkiserver/shuttle/wit/parser}/WitParserTest.java (99%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/greet.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/command.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/deps.toml (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/deps/clocks/monotonic-clock.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/deps/clocks/timezone.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/deps/clocks/wall-clock.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/deps/clocks/world.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/deps/filesystem/preopens.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/deps/filesystem/types.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/deps/filesystem/world.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/deps/io/error.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/deps/io/poll.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/deps/io/streams.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/deps/io/world.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/deps/random/insecure-seed.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/deps/random/insecure.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/deps/random/random.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/deps/random/world.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/deps/sockets/instance-network.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/deps/sockets/ip-name-lookup.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/deps/sockets/network.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/deps/sockets/tcp-create-socket.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/deps/sockets/tcp.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/deps/sockets/udp-create-socket.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/deps/sockets/udp.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/deps/sockets/world.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/environment.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/exit.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/imports.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/run.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/stdio.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-cli/wit/terminal.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-sockets/deps.lock (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-sockets/deps.toml (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-sockets/deps/clocks/monotonic-clock.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-sockets/deps/clocks/timezone.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-sockets/deps/clocks/wall-clock.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-sockets/deps/clocks/world.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-sockets/deps/io/error.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-sockets/deps/io/poll.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-sockets/deps/io/streams.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-sockets/deps/io/world.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-sockets/instance-network.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-sockets/ip-name-lookup.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-sockets/network.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-sockets/tcp-create-socket.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-sockets/tcp.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-sockets/udp-create-socket.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-sockets/udp.wit (100%) rename {wit-parser => shuttle-wit-parser}/src/test/resources/wit/wasi-sockets/world.wit (100%) diff --git a/.idea/compiler.xml b/.idea/compiler.xml index b7de367..e00ef80 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -6,17 +6,17 @@ - - - - + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml index dc1a9f4..58d834c 100644 --- a/.idea/encodings.xml +++ b/.idea/encodings.xml @@ -3,13 +3,13 @@ - - - - - - - - + + + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index 53a0584..94c31a3 100644 --- a/README.md +++ b/README.md @@ -483,7 +483,7 @@ Argument/return types follow the value bridge described above — here just `Str ``` -This generates `com.example.generated.GreetContext` — an **interface**, not an abstract class (so a class can implement several generated interfaces at once — see "Combining interfaces" below), extending `WasmComponentContext` with `getImportFunctions()`/`getImportResources()`/`getProvidedInterfaces()`/`name()` already wired as `default` methods and one typed abstract method per WIT function (see [`WitCodeGenerator`](wit-codegen-maven-plugin/src/main/java/io/github/stefanrichterhuber/witcodegen/WitCodeGenerator.java) for the full WIT-to-Java type mapping). Implement it directly instead of hand-rolling `WasmComponentContext`: +This generates `com.example.generated.GreetContext` — an **interface**, not an abstract class (so a class can implement several generated interfaces at once — see "Combining interfaces" below), extending `WasmComponentContext` with `getImportFunctions()`/`getImportResources()`/`getProvidedInterfaces()`/`name()` already wired as `default` methods and one typed abstract method per WIT function (see [`WitCodeGenerator`](wit-codegen-maven-plugin/src/main/java/jp/akkiserver/shuttle/wit/codegen/WitCodeGenerator.java) for the full WIT-to-Java type mapping). Implement it directly instead of hand-rolling `WasmComponentContext`: ```java public class MyGreetContext implements com.example.generated.GreetContext { diff --git a/pom.xml b/pom.xml index ff88fb9..97aadcf 100644 --- a/pom.xml +++ b/pom.xml @@ -3,14 +3,14 @@ 4.0.0 - io.github.stefanrichterhuber - wasmtimejavang-parent + jp.akkiserver + shuttle 6.0.1-SNAPSHOT pom - wasmtime-java-ng (parent) - Java bindings for Wasmtime via a native Rust bridge, and the WIT-driven code generation tooling around it. - https://github.com/StefanRichterHuber/wasmtime-java-ng + shuttle + Shuttle: a Minecraft computer mod that runs WebAssembly. Java bindings for Wasmtime/Weave via a native Rust bridge, plus WIT tooling. + https://github.com/akkiserver-dev/shuttle @@ -29,10 +29,10 @@ - wasmtimejavang - wasmtimejavang-example - wit-parser - wit-codegen-maven-plugin + shuttle-java + shuttle-java-example + shuttle-wit-parser + shuttle-wit-maven-plugin @@ -53,9 +53,9 @@ - scm:git:https://github.com/StefanRichterHuber/wasmtime-ng - scm:git:https://github.com/StefanRichterHuber/wasmtime-ng - https://github.com/StefanRichterHuber/wasmtime-ng + scm:git:https://github.com/akkiserver-dev/shuttle + scm:git:https://github.com/akkiserver-dev/shuttle + https://github.com/akkiserver-dev/shuttle v4.0.1 diff --git a/wasmtimejavang-example/pom.xml b/shuttle-java-example/pom.xml similarity index 78% rename from wasmtimejavang-example/pom.xml rename to shuttle-java-example/pom.xml index ad93218..8ce357f 100644 --- a/wasmtimejavang-example/pom.xml +++ b/shuttle-java-example/pom.xml @@ -4,20 +4,20 @@ 4.0.0 - io.github.stefanrichterhuber - wasmtimejavang-parent + jp.akkiserver + shuttle 6.0.1-SNAPSHOT ../pom.xml - wasmtimejavang-example - wasmtime-java-ng (weave example) + shuttle-java-example + shuttle-java (weave example) Weaveによる「中断・保存・再開できる仮想コンピュータ」のサンプル(日本語コメント付き)。 - io.github.stefanrichterhuber - wasmtimejavang + jp.akkiserver + shuttle-java ${project.version} @@ -31,7 +31,7 @@ - + org.codehaus.mojo exec-maven-plugin diff --git a/wasmtimejavang-example/src/main/java/example/VirtualComputerExample.java b/shuttle-java-example/src/main/java/example/VirtualComputerExample.java similarity index 96% rename from wasmtimejavang-example/src/main/java/example/VirtualComputerExample.java rename to shuttle-java-example/src/main/java/example/VirtualComputerExample.java index 4c52cba..250b522 100644 --- a/wasmtimejavang-example/src/main/java/example/VirtualComputerExample.java +++ b/shuttle-java-example/src/main/java/example/VirtualComputerExample.java @@ -1,9 +1,9 @@ package example; -import io.github.stefanrichterhuber.wasmtimejavang.WasmtimeEngine; -import io.github.stefanrichterhuber.wasmtimejavang.WeaveInstance; -import io.github.stefanrichterhuber.wasmtimejavang.WeaveModule; -import io.github.stefanrichterhuber.wasmtimejavang.WeaveResult; +import jp.akkiserver.shuttle.WasmtimeEngine; +import jp.akkiserver.shuttle.WeaveInstance; +import jp.akkiserver.shuttle.WeaveModule; +import jp.akkiserver.shuttle.WeaveResult; import java.io.IOException; import java.io.InputStream; diff --git a/wasmtimejavang-example/src/main/resources/guest.wat b/shuttle-java-example/src/main/resources/guest.wat similarity index 100% rename from wasmtimejavang-example/src/main/resources/guest.wat rename to shuttle-java-example/src/main/resources/guest.wat diff --git a/wasmtimejavang/pom.xml b/shuttle-java/pom.xml similarity index 96% rename from wasmtimejavang/pom.xml rename to shuttle-java/pom.xml index c9127ca..58f3ece 100644 --- a/wasmtimejavang/pom.xml +++ b/shuttle-java/pom.xml @@ -4,17 +4,17 @@ 4.0.0 - io.github.stefanrichterhuber - wasmtimejavang-parent + jp.akkiserver + shuttle 6.0.1-SNAPSHOT ../pom.xml - wasmtimejavang + shuttle-java - wasmtime-java-ng + shuttle-java Java bindings for Wasmtime via a native Rust bridge. - https://github.com/StefanRichterHuber/wasmtime-java-ng + https://github.com/akkiserver-dev/shuttle @@ -169,7 +169,7 @@ - ${project.build.directory}/classes/io/github/stefanrichterhuber/wasmtimejavang/libs/linux-x86-64 + ${project.build.directory}/classes/jp/akkiserver/shuttle/libs/linux-x86-64 @@ -244,7 +244,7 @@ - ${project.build.directory}/classes/io/github/stefanrichterhuber/wasmtimejavang/libs/linux-aarch64 + ${project.build.directory}/classes/jp/akkiserver/shuttle/libs/linux-aarch64 @@ -316,7 +316,7 @@ copy-resources - ${project.build.directory}/classes/io/github/stefanrichterhuber/wasmtimejavang/libs/win32-x86-64 + ${project.build.directory}/classes/jp/akkiserver/shuttle/libs/win32-x86-64 ${project.build.directory}/rust/x86_64-pc-windows-msvc/${cargo.profile.folder} @@ -387,7 +387,7 @@ copy-resources - ${project.build.directory}/classes/io/github/stefanrichterhuber/wasmtimejavang/libs/win32-x86-64 + ${project.build.directory}/classes/jp/akkiserver/shuttle/libs/win32-x86-64 ${project.build.directory}/rust/x86_64-pc-windows-msvc/${cargo.profile.folder} @@ -457,7 +457,7 @@ copy-resources - ${project.build.directory}/classes/io/github/stefanrichterhuber/wasmtimejavang/libs/win32-aarch64 + ${project.build.directory}/classes/jp/akkiserver/shuttle/libs/win32-aarch64 ${project.build.directory}/rust/aarch64-pc-windows-msvc/${cargo.profile.folder} diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/ComponentContextLookup.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/ComponentContextLookup.java similarity index 95% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/ComponentContextLookup.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/ComponentContextLookup.java index 9acb524..f983ff8 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/ComponentContextLookup.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/ComponentContextLookup.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; import java.util.Optional; @@ -16,7 +16,7 @@ * The linker resolves which strategy to use itself via * {@link java.util.ServiceLoader} * (a - * {@code META-INF/services/io.github.stefanrichterhuber.wasmtimejavang.ComponentContextLookup} + * {@code META-INF/services/jp.akkiserver.shuttle.ComponentContextLookup} * provider), falling back to {@link ServiceLoaderComponentContextLookup} if * none is registered -- so overriding it is a matter of registering a * provider, not calling a setter. diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/ComponentFunction.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/ComponentFunction.java similarity index 88% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/ComponentFunction.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/ComponentFunction.java index 2b9eb05..47562e9 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/ComponentFunction.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/ComponentFunction.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; /** * Functional interface for a Java implementation of a function imported into @@ -11,7 +11,7 @@ * {@link String}, {@code byte[]} (list<u8>), {@link java.util.List} * (list/map), {@code Object[]} (tuple), {@link java.util.Map} (record), * {@link java.util.Optional} (option), {@link java.util.Set} (flags), or the - * small wrapper types in {@link io.github.stefanrichterhuber.wasmtimejavang.component} + * small wrapper types in {@link jp.akkiserver.shuttle.component} * ({@code WitVariant}, {@code WitEnum}, {@code WitResult}, {@code WitResource}). */ @FunctionalInterface diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/ResourceDestructor.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/ResourceDestructor.java similarity index 90% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/ResourceDestructor.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/ResourceDestructor.java index c90f9c9..51b5211 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/ResourceDestructor.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/ResourceDestructor.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; /** * Callback invoked when a guest drops an owned component resource instance. diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/SemanticVersion.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/SemanticVersion.java similarity index 96% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/SemanticVersion.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/SemanticVersion.java index f04d82e..eff468d 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/SemanticVersion.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/SemanticVersion.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; /** * diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/ServiceLoaderComponentContextLookup.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/ServiceLoaderComponentContextLookup.java similarity index 93% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/ServiceLoaderComponentContextLookup.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/ServiceLoaderComponentContextLookup.java index 13d710f..bdf6ad6 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/ServiceLoaderComponentContextLookup.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/ServiceLoaderComponentContextLookup.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; import java.util.Optional; import java.util.ServiceLoader; @@ -7,7 +7,7 @@ * Default {@link ComponentContextLookup}: discovers every * {@link WasmComponentContext} registered as a {@link ServiceLoader} provider * of the {@code WasmComponentContext} service type (via - * {@code META-INF/services/io.github.stefanrichterhuber.wasmtimejavang.WasmComponentContext} + * {@code META-INF/services/jp.akkiserver.shuttle.WasmComponentContext} * files, or module {@code provides ... with ...} declarations) and returns * the first one whose {@link WasmComponentContext#name()} matches. *
@@ -32,7 +32,7 @@ * * Callers that want something else entirely (explicit wiring, Spring, ...) * can implement {@link ComponentContextLookup} directly and register it as a - * {@code META-INF/services/io.github.stefanrichterhuber.wasmtimejavang.ComponentContextLookup} + * {@code META-INF/services/jp.akkiserver.shuttle.ComponentContextLookup} * provider -- {@link WasmtimeComponentLinker} resolves its own dependency * lookup strategy the same SPI way, falling back to this class if none is * registered. diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/V128.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/V128.java similarity index 99% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/V128.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/V128.java index 8682d0a..1dbe818 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/V128.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/V128.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; import java.math.BigInteger; import java.nio.ByteBuffer; diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/ValType.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/ValType.java similarity index 84% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/ValType.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/ValType.java index c30875f..396f961 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/ValType.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/ValType.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; /** * Represents the value types in WebAssembly. diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmComponentContext.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmComponentContext.java similarity index 99% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmComponentContext.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmComponentContext.java index 2dd44b8..7ef30b5 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmComponentContext.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmComponentContext.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; import java.util.List; import java.util.Set; diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmContext.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmContext.java similarity index 97% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmContext.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmContext.java index c8899e3..ff86e14 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmContext.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmContext.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; import java.util.List; diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmRuntimeException.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmRuntimeException.java similarity index 95% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmRuntimeException.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmRuntimeException.java index f99b5d6..7e9ebe5 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmRuntimeException.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmRuntimeException.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; /** * This represents any exception thrown from the native wasm context. It diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeComponent.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeComponent.java similarity index 98% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeComponent.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeComponent.java index 0880fa2..e21ccdc 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeComponent.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeComponent.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; import java.io.IOException; import java.io.InputStream; diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeComponentInstance.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeComponentInstance.java similarity index 98% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeComponentInstance.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeComponentInstance.java index d828896..bfce41b 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeComponentInstance.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeComponentInstance.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; import java.lang.ref.Cleaner; import java.util.Map; diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeComponentLinker.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeComponentLinker.java similarity index 97% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeComponentLinker.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeComponentLinker.java index afe22de..9f62593 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeComponentLinker.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeComponentLinker.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; import java.lang.ref.Cleaner; import java.util.ArrayList; @@ -15,8 +15,8 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import io.github.stefanrichterhuber.wasmtimejavang.WasmComponentContext.ComponentImportFunction; -import io.github.stefanrichterhuber.wasmtimejavang.WasmComponentContext.ComponentImportResource; +import jp.akkiserver.shuttle.WasmComponentContext.ComponentImportFunction; +import jp.akkiserver.shuttle.WasmComponentContext.ComponentImportResource; /** * Used to resolve imports for a WebAssembly component. @@ -53,7 +53,7 @@ public final class WasmtimeComponentLinker implements AutoCloseable { * providers looked up by {@link #linkRequired(WasmtimeComponent)}. *
* Itself resolved via {@link ServiceLoader}: registering a - * {@code META-INF/services/io.github.stefanrichterhuber.wasmtimejavang.ComponentContextLookup} + * {@code META-INF/services/jp.akkiserver.shuttle.ComponentContextLookup} * provider overrides the strategy for every {@code WasmtimeComponentLinker} * without any call site needing to know about it, the same "swap the * default via SPI, not a setter" approach used for diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeEngine.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeEngine.java similarity index 97% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeEngine.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeEngine.java index 326b85f..fa49970 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeEngine.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeEngine.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; import io.questdb.jar.jni.JarJniLoader; @@ -52,7 +52,7 @@ public void run() { JarJniLoader.loadLib( WasmtimeEngine.class, // A platform-specific path is automatically suffixed to path below. - "/io/github/stefanrichterhuber/wasmtimejavang/libs", + "/jp/akkiserver/shuttle/libs", // The "lib" prefix and ".so|.dynlib|.dll" suffix are added automatically as // needed. "wasmtimebinding"); diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeFunction.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeFunction.java similarity index 97% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeFunction.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeFunction.java index 31357f1..e172296 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeFunction.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeFunction.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; import java.util.Objects; import java.util.function.Function; diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeInstance.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeInstance.java similarity index 98% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeInstance.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeInstance.java index a9d3dab..e136e34 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeInstance.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeInstance.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; import java.lang.ref.Cleaner; import java.util.Map; diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeLinker.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeLinker.java similarity index 98% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeLinker.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeLinker.java index 60ef238..2cbe8d8 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeLinker.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeLinker.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; import java.lang.ref.Cleaner; import java.util.ArrayList; @@ -8,7 +8,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import io.github.stefanrichterhuber.wasmtimejavang.WasmContext.Importmemory; +import jp.akkiserver.shuttle.WasmContext.Importmemory; /** * Used to resolve imports for a WebAssembly module. diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeLocalMemory.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeLocalMemory.java similarity index 98% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeLocalMemory.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeLocalMemory.java index 5791704..d564ce1 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeLocalMemory.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeLocalMemory.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; import java.nio.ByteBuffer; import java.nio.ByteOrder; diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeMemory.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeMemory.java similarity index 99% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeMemory.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeMemory.java index 22c3599..9ad407d 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeMemory.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeMemory.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; import java.nio.ByteBuffer; import java.nio.charset.Charset; diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeModule.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeModule.java similarity index 99% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeModule.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeModule.java index e07f879..6fffbbc 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeModule.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeModule.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; import java.io.FileInputStream; import java.io.IOException; diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeSharedMemory.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeSharedMemory.java similarity index 98% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeSharedMemory.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeSharedMemory.java index eb597d0..2709f28 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeSharedMemory.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeSharedMemory.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; import java.lang.ref.Cleaner; import java.nio.ByteBuffer; diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeStore.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeStore.java similarity index 98% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeStore.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeStore.java index fbd4088..fe81804 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeStore.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WasmtimeStore.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; import java.lang.ref.Cleaner; import java.util.Map; diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WeaveCaller.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WeaveCaller.java similarity index 95% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WeaveCaller.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/WeaveCaller.java index 212211e..9ec63a9 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WeaveCaller.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WeaveCaller.java @@ -1,6 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; - -import java.nio.ByteBuffer; +package jp.akkiserver.shuttle; /** * Handle to the guest during a host call: read/write guest memory, request a diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WeaveHostFunction.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WeaveHostFunction.java similarity index 89% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WeaveHostFunction.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/WeaveHostFunction.java index d659fef..44fdd59 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WeaveHostFunction.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WeaveHostFunction.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; /** * A Java function imported into a woven guest. Arguments and results are raw diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WeaveImport.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WeaveImport.java similarity index 95% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WeaveImport.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/WeaveImport.java index 34e2745..83f5413 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WeaveImport.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WeaveImport.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; import java.util.List; diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WeaveInstance.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WeaveInstance.java similarity index 99% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WeaveInstance.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/WeaveInstance.java index a4ef595..a686ffe 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WeaveInstance.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WeaveInstance.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WeaveModule.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WeaveModule.java similarity index 98% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WeaveModule.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/WeaveModule.java index 85bd886..e60a497 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WeaveModule.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WeaveModule.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; import java.util.Objects; diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WeaveNative.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WeaveNative.java similarity index 97% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WeaveNative.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/WeaveNative.java index 4d34db3..ab920c7 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WeaveNative.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WeaveNative.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; import java.nio.ByteBuffer; import java.util.List; diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WeaveResult.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WeaveResult.java similarity index 97% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WeaveResult.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/WeaveResult.java index 6b65d7b..968fda3 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/WeaveResult.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/WeaveResult.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; import java.util.Arrays; diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/component/WitEnum.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/component/WitEnum.java similarity index 83% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/component/WitEnum.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/component/WitEnum.java index ac2eb3b..f879847 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/component/WitEnum.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/component/WitEnum.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang.component; +package jp.akkiserver.shuttle.component; /** * Represents a WIT {@code enum} value crossing the Rust/Java boundary. diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/component/WitResource.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/component/WitResource.java similarity index 97% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/component/WitResource.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/component/WitResource.java index dea4ef6..0788ec2 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/component/WitResource.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/component/WitResource.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang.component; +package jp.akkiserver.shuttle.component; /** * Represents a WIT resource handle crossing the Rust/Java boundary. diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/component/WitResult.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/component/WitResult.java similarity index 94% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/component/WitResult.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/component/WitResult.java index 00ad0f6..563e475 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/component/WitResult.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/component/WitResult.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang.component; +package jp.akkiserver.shuttle.component; /** * Represents a WIT {@code result<ok, err>} value crossing the diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/component/WitVariant.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/component/WitVariant.java similarity index 87% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/component/WitVariant.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/component/WitVariant.java index 99d44f7..a85e659 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/component/WitVariant.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/component/WitVariant.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang.component; +package jp.akkiserver.shuttle.component; /** * Represents a WIT {@code variant} value crossing the Rust/Java boundary. diff --git a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/internal/WasmtimeFuncRef.java b/shuttle-java/src/main/java/jp/akkiserver/shuttle/internal/WasmtimeFuncRef.java similarity index 90% rename from wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/internal/WasmtimeFuncRef.java rename to shuttle-java/src/main/java/jp/akkiserver/shuttle/internal/WasmtimeFuncRef.java index 3f4f67a..1c2fb17 100644 --- a/wasmtimejavang/src/main/java/io/github/stefanrichterhuber/wasmtimejavang/internal/WasmtimeFuncRef.java +++ b/shuttle-java/src/main/java/jp/akkiserver/shuttle/internal/WasmtimeFuncRef.java @@ -1,9 +1,9 @@ -package io.github.stefanrichterhuber.wasmtimejavang.internal; +package jp.akkiserver.shuttle.internal; import java.lang.ref.Cleaner; -import io.github.stefanrichterhuber.wasmtimejavang.WasmtimeFunction; -import io.github.stefanrichterhuber.wasmtimejavang.WasmtimeInstance; +import jp.akkiserver.shuttle.WasmtimeFunction; +import jp.akkiserver.shuttle.WasmtimeInstance; final class WasmtimeFuncRef implements WasmtimeFunction, AutoCloseable { private long funcPtr; diff --git a/wasmtimejavang/src/main/rust/wasmtime-binding/.gitignore b/shuttle-java/src/main/rust/wasmtime-binding/.gitignore similarity index 100% rename from wasmtimejavang/src/main/rust/wasmtime-binding/.gitignore rename to shuttle-java/src/main/rust/wasmtime-binding/.gitignore diff --git a/wasmtimejavang/src/main/rust/wasmtime-binding/Cargo.lock b/shuttle-java/src/main/rust/wasmtime-binding/Cargo.lock similarity index 100% rename from wasmtimejavang/src/main/rust/wasmtime-binding/Cargo.lock rename to shuttle-java/src/main/rust/wasmtime-binding/Cargo.lock diff --git a/wasmtimejavang/src/main/rust/wasmtime-binding/Cargo.toml b/shuttle-java/src/main/rust/wasmtime-binding/Cargo.toml similarity index 100% rename from wasmtimejavang/src/main/rust/wasmtime-binding/Cargo.toml rename to shuttle-java/src/main/rust/wasmtime-binding/Cargo.toml diff --git a/wasmtimejavang/src/main/rust/wasmtime-binding/src/java_collections.rs b/shuttle-java/src/main/rust/wasmtime-binding/src/java_collections.rs similarity index 100% rename from wasmtimejavang/src/main/rust/wasmtime-binding/src/java_collections.rs rename to shuttle-java/src/main/rust/wasmtime-binding/src/java_collections.rs diff --git a/wasmtimejavang/src/main/rust/wasmtime-binding/src/java_maps.rs b/shuttle-java/src/main/rust/wasmtime-binding/src/java_maps.rs similarity index 100% rename from wasmtimejavang/src/main/rust/wasmtime-binding/src/java_maps.rs rename to shuttle-java/src/main/rust/wasmtime-binding/src/java_maps.rs diff --git a/wasmtimejavang/src/main/rust/wasmtime-binding/src/java_numbers.rs b/shuttle-java/src/main/rust/wasmtime-binding/src/java_numbers.rs similarity index 100% rename from wasmtimejavang/src/main/rust/wasmtime-binding/src/java_numbers.rs rename to shuttle-java/src/main/rust/wasmtime-binding/src/java_numbers.rs diff --git a/wasmtimejavang/src/main/rust/wasmtime-binding/src/lib.rs b/shuttle-java/src/main/rust/wasmtime-binding/src/lib.rs similarity index 100% rename from wasmtimejavang/src/main/rust/wasmtime-binding/src/lib.rs rename to shuttle-java/src/main/rust/wasmtime-binding/src/lib.rs diff --git a/wasmtimejavang/src/main/rust/wasmtime-binding/src/logging.rs b/shuttle-java/src/main/rust/wasmtime-binding/src/logging.rs similarity index 100% rename from wasmtimejavang/src/main/rust/wasmtime-binding/src/logging.rs rename to shuttle-java/src/main/rust/wasmtime-binding/src/logging.rs diff --git a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmcomponent.rs b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmcomponent.rs similarity index 97% rename from wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmcomponent.rs rename to shuttle-java/src/main/rust/wasmtime-binding/src/wasmcomponent.rs index 768220d..21bad3f 100644 --- a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmcomponent.rs +++ b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmcomponent.rs @@ -48,12 +48,12 @@ impl From for jlong { bind_java_type! { rust_type = pub JWasmtimeComponent, - java_type = "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeComponent", + java_type = "jp.akkiserver.shuttle.WasmtimeComponent", type_map = { unsafe EngineHandle => long, unsafe ComponentHandle => long, - JWasmtimeEngine => "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeEngine" + JWasmtimeEngine => "jp.akkiserver.shuttle.WasmtimeEngine" }, fields = { diff --git a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmcomponentinstance.rs b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmcomponentinstance.rs similarity index 96% rename from wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmcomponentinstance.rs rename to shuttle-java/src/main/rust/wasmtime-binding/src/wasmcomponentinstance.rs index a6c139a..bb8b95c 100644 --- a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmcomponentinstance.rs +++ b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmcomponentinstance.rs @@ -56,16 +56,16 @@ impl From for jlong { bind_java_type! { rust_type = pub JWasmtimeComponentInstance, - java_type = "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeComponentInstance", + java_type = "jp.akkiserver.shuttle.WasmtimeComponentInstance", type_map = { unsafe StoreHandle => long, unsafe ComponentHandle => long, unsafe ComponentLinkerHandle => long, unsafe ComponentInstanceHandle => long, - JWasmtimeStore => "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeStore", - JWasmtimeComponentLinker => "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeComponentLinker", - JWasmtimeComponent => "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeComponent", + JWasmtimeStore => "jp.akkiserver.shuttle.WasmtimeStore", + JWasmtimeComponentLinker => "jp.akkiserver.shuttle.WasmtimeComponentLinker", + JWasmtimeComponent => "jp.akkiserver.shuttle.WasmtimeComponent", }, constructors { diff --git a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmcomponentlinker.rs b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmcomponentlinker.rs similarity index 94% rename from wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmcomponentlinker.rs rename to shuttle-java/src/main/rust/wasmtime-binding/src/wasmcomponentlinker.rs index 2d8e609..e279c6e 100644 --- a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmcomponentlinker.rs +++ b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmcomponentlinker.rs @@ -47,10 +47,10 @@ impl From for jlong { bind_java_type! { rust_type = pub JComponentFunction, - java_type = "io.github.stefanrichterhuber.wasmtimejavang.ComponentFunction", + java_type = "jp.akkiserver.shuttle.ComponentFunction", type_map = { - crate::wasmcomponentinstance::JWasmtimeComponentInstance => "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeComponentInstance", + crate::wasmcomponentinstance::JWasmtimeComponentInstance => "jp.akkiserver.shuttle.WasmtimeComponentInstance", }, methods = { @@ -60,7 +60,7 @@ bind_java_type! { bind_java_type! { rust_type = pub JResourceDestructor, - java_type = "io.github.stefanrichterhuber.wasmtimejavang.ResourceDestructor", + java_type = "jp.akkiserver.shuttle.ResourceDestructor", methods = { fn drop_resource { @@ -72,16 +72,16 @@ bind_java_type! { bind_java_type! { rust_type = pub JWasmtimeComponentLinker, - java_type = "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeComponentLinker", + java_type = "jp.akkiserver.shuttle.WasmtimeComponentLinker", type_map = { unsafe crate::wasmengine::EngineHandle => long, unsafe ComponentLinkerHandle => long, unsafe StoreHandle => long, - crate::wasmengine::JWasmtimeEngine => "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeEngine", - crate::wasmstore::JWasmtimeStore => "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeStore", - JComponentFunction => "io.github.stefanrichterhuber.wasmtimejavang.ComponentFunction", - JResourceDestructor => "io.github.stefanrichterhuber.wasmtimejavang.ResourceDestructor", + crate::wasmengine::JWasmtimeEngine => "jp.akkiserver.shuttle.WasmtimeEngine", + crate::wasmstore::JWasmtimeStore => "jp.akkiserver.shuttle.WasmtimeStore", + JComponentFunction => "jp.akkiserver.shuttle.ComponentFunction", + JResourceDestructor => "jp.akkiserver.shuttle.ResourceDestructor", }, fields = { diff --git a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmcomponentvalue.rs b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmcomponentvalue.rs similarity index 98% rename from wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmcomponentvalue.rs rename to shuttle-java/src/main/rust/wasmtime-binding/src/wasmcomponentvalue.rs index bb62ae3..31ea14a 100644 --- a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmcomponentvalue.rs +++ b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmcomponentvalue.rs @@ -20,7 +20,7 @@ use crate::wasmstore::StoreContent; bind_java_type! { rust_type = pub JWitVariant, - java_type = "io.github.stefanrichterhuber.wasmtimejavang.component.WitVariant", + java_type = "jp.akkiserver.shuttle.component.WitVariant", constructors { fn new(case_name: JString, value: JObject), @@ -34,7 +34,7 @@ bind_java_type! { bind_java_type! { rust_type = pub JWitEnum, - java_type = "io.github.stefanrichterhuber.wasmtimejavang.component.WitEnum", + java_type = "jp.akkiserver.shuttle.component.WitEnum", constructors { fn new(name: JString), @@ -47,7 +47,7 @@ bind_java_type! { bind_java_type! { rust_type = pub JWitResult, - java_type = "io.github.stefanrichterhuber.wasmtimejavang.component.WitResult", + java_type = "jp.akkiserver.shuttle.component.WitResult", constructors { fn new(ok: jboolean, value: JObject), @@ -61,7 +61,7 @@ bind_java_type! { bind_java_type! { rust_type = pub JWitResource, - java_type = "io.github.stefanrichterhuber.wasmtimejavang.component.WitResource", + java_type = "jp.akkiserver.shuttle.component.WitResource", constructors { fn new(resource_name: JString, rep: jint, owned: jboolean), diff --git a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmcontext.rs b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmcontext.rs similarity index 52% rename from wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmcontext.rs rename to shuttle-java/src/main/rust/wasmtime-binding/src/wasmcontext.rs index a471151..35d4929 100644 --- a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmcontext.rs +++ b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmcontext.rs @@ -2,7 +2,7 @@ use jni::bind_java_type; bind_java_type! { rust_type = pub JWasmContext, - java_type = "io.github.stefanrichterhuber.wasmtimejavang.WasmContext", + java_type = "jp.akkiserver.shuttle.WasmContext", } diff --git a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmengine.rs b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmengine.rs similarity index 98% rename from wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmengine.rs rename to shuttle-java/src/main/rust/wasmtime-binding/src/wasmengine.rs index b5762a0..7ff4e66 100644 --- a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmengine.rs +++ b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmengine.rs @@ -44,7 +44,7 @@ impl From for jlong { bind_java_type! { rust_type = pub JWasmtimeEngine, - java_type = "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeEngine", + java_type = "jp.akkiserver.shuttle.WasmtimeEngine", type_map = { unsafe EngineHandle => long, diff --git a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmexception.rs b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmexception.rs similarity index 98% rename from wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmexception.rs rename to shuttle-java/src/main/rust/wasmtime-binding/src/wasmexception.rs index 7ca56aa..471b899 100644 --- a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmexception.rs +++ b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmexception.rs @@ -9,7 +9,7 @@ use log::debug; bind_java_type! { rust_type = pub JWasmRuntimeException, - java_type = "io.github.stefanrichterhuber.wasmtimejavang.WasmRuntimeException", + java_type = "jp.akkiserver.shuttle.WasmRuntimeException", constructors { pub fn new_with_msg(msg: JString), diff --git a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasminstance.rs b/shuttle-java/src/main/rust/wasmtime-binding/src/wasminstance.rs similarity index 96% rename from wasmtimejavang/src/main/rust/wasmtime-binding/src/wasminstance.rs rename to shuttle-java/src/main/rust/wasmtime-binding/src/wasminstance.rs index e494ab1..093ff5f 100644 --- a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasminstance.rs +++ b/shuttle-java/src/main/rust/wasmtime-binding/src/wasminstance.rs @@ -71,7 +71,7 @@ impl From for jlong { bind_java_type! { rust_type = pub JWasmtimeInstance, - java_type = "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeInstance", + java_type = "jp.akkiserver.shuttle.WasmtimeInstance", type_map = { unsafe EngineHandle => long, @@ -79,12 +79,12 @@ bind_java_type! { unsafe ModuleHandle => long, unsafe LinkerHandle => long, unsafe InstanceHandle => long, - JWasmtimeStore => "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeStore", - JWasmtimeLinker => "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeLinker", - JWasmtimeModule => "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeModule", - JWasmtimeFunction => "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeFunction", - JWasmtimeLocalMemory => "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeLocalMemory", - JWasmtimeFuncRef => "io.github.stefanrichterhuber.wasmtimejavang.internal.WasmtimeFuncRef", + JWasmtimeStore => "jp.akkiserver.shuttle.WasmtimeStore", + JWasmtimeLinker => "jp.akkiserver.shuttle.WasmtimeLinker", + JWasmtimeModule => "jp.akkiserver.shuttle.WasmtimeModule", + JWasmtimeFunction => "jp.akkiserver.shuttle.WasmtimeFunction", + JWasmtimeLocalMemory => "jp.akkiserver.shuttle.WasmtimeLocalMemory", + JWasmtimeFuncRef => "jp.akkiserver.shuttle.internal.WasmtimeFuncRef", }, constructors { diff --git a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmlinker.rs b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmlinker.rs similarity index 95% rename from wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmlinker.rs rename to shuttle-java/src/main/rust/wasmtime-binding/src/wasmlinker.rs index 9b10bb2..2542855 100644 --- a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmlinker.rs +++ b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmlinker.rs @@ -53,17 +53,17 @@ impl From for jlong { bind_java_type! { rust_type = pub JWasmtimeLinker, - java_type = "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeLinker", + java_type = "jp.akkiserver.shuttle.WasmtimeLinker", type_map = { unsafe EngineHandle => long, unsafe LinkerHandle => long, unsafe StoreHandle => long, unsafe SharedMemoryHandle => long, - JWasmtimeEngine => "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeEngine", - JWasmtimeStore => "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeStore", - JWasmContext => "io.github.stefanrichterhuber.wasmtimejavang.WasmContext", - JWasmtimeFunction => "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeFunction", + JWasmtimeEngine => "jp.akkiserver.shuttle.WasmtimeEngine", + JWasmtimeStore => "jp.akkiserver.shuttle.WasmtimeStore", + JWasmContext => "jp.akkiserver.shuttle.WasmContext", + JWasmtimeFunction => "jp.akkiserver.shuttle.WasmtimeFunction", }, fields = { diff --git a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmmemory.rs b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmmemory.rs similarity index 96% rename from wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmmemory.rs rename to shuttle-java/src/main/rust/wasmtime-binding/src/wasmmemory.rs index 26b5d87..cfbd92f 100644 --- a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmmemory.rs +++ b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmmemory.rs @@ -9,13 +9,13 @@ use wasmtime::Extern; bind_java_type! { rust_type = pub JWasmtimeLocalMemory, - java_type = "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeLocalMemory", + java_type = "jp.akkiserver.shuttle.WasmtimeLocalMemory", type_map = { unsafe StoreHandle => long, unsafe InstanceHandle => long, - JWasmtimeStore => "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeStore", - JWasmtimeInstance => "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeInstance", + JWasmtimeStore => "jp.akkiserver.shuttle.WasmtimeStore", + JWasmtimeInstance => "jp.akkiserver.shuttle.WasmtimeInstance", }, fields { diff --git a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmmodule.rs b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmmodule.rs similarity index 96% rename from wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmmodule.rs rename to shuttle-java/src/main/rust/wasmtime-binding/src/wasmmodule.rs index b6def58..b04158c 100644 --- a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmmodule.rs +++ b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmmodule.rs @@ -43,12 +43,12 @@ impl From for jlong { bind_java_type! { rust_type = pub JWasmtimeModule, - java_type = "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeModule", + java_type = "jp.akkiserver.shuttle.WasmtimeModule", type_map = { unsafe EngineHandle => long, unsafe ModuleHandle => long, - JWasmtimeEngine => "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeEngine" + JWasmtimeEngine => "jp.akkiserver.shuttle.WasmtimeEngine" }, fields = { diff --git a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmsharedmemory.rs b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmsharedmemory.rs similarity index 98% rename from wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmsharedmemory.rs rename to shuttle-java/src/main/rust/wasmtime-binding/src/wasmsharedmemory.rs index 4d54cc6..43357fb 100644 --- a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmsharedmemory.rs +++ b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmsharedmemory.rs @@ -44,7 +44,7 @@ impl From for jlong { bind_java_type! { rust_type = pub JWasmtimeSharedMemory, - java_type = "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeSharedMemory", + java_type = "jp.akkiserver.shuttle.WasmtimeSharedMemory", type_map = { unsafe EngineHandle => long, diff --git a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmstore.rs b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmstore.rs similarity index 98% rename from wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmstore.rs rename to shuttle-java/src/main/rust/wasmtime-binding/src/wasmstore.rs index 7917a73..2483e53 100644 --- a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmstore.rs +++ b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmstore.rs @@ -198,12 +198,12 @@ impl From for jlong { bind_java_type! { rust_type = pub JWasmtimeStore, - java_type = "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeStore", + java_type = "jp.akkiserver.shuttle.WasmtimeStore", type_map = { unsafe EngineHandle => long, unsafe StoreHandle => long, - JWasmtimeEngine => "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeEngine", + JWasmtimeEngine => "jp.akkiserver.shuttle.WasmtimeEngine", }, fields { diff --git a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmtime_v128.rs b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmtime_v128.rs similarity index 97% rename from wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmtime_v128.rs rename to shuttle-java/src/main/rust/wasmtime-binding/src/wasmtime_v128.rs index 57a3a7c..da13d15 100644 --- a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmtime_v128.rs +++ b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmtime_v128.rs @@ -5,7 +5,7 @@ use wasmtime::V128; bind_java_type! { rust_type = pub JV128, - java_type = io.github.stefanrichterhuber.wasmtimejavang.V128, + java_type = jp.akkiserver.shuttle.V128, type_map = { JNumber => "java.lang.Number" diff --git a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmtime_valtype.rs b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmtime_valtype.rs similarity index 97% rename from wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmtime_valtype.rs rename to shuttle-java/src/main/rust/wasmtime-binding/src/wasmtime_valtype.rs index 2946766..45cb898 100644 --- a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmtime_valtype.rs +++ b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmtime_valtype.rs @@ -4,7 +4,7 @@ use wasmtime::{RefType, ValType}; bind_java_type! { rust_type = pub JValType, - java_type = "io.github.stefanrichterhuber.wasmtimejavang.ValType", + java_type = "jp.akkiserver.shuttle.ValType", methods { fn name() -> JString, diff --git a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmtimefuncref.rs b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmtimefuncref.rs similarity index 94% rename from wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmtimefuncref.rs rename to shuttle-java/src/main/rust/wasmtime-binding/src/wasmtimefuncref.rs index 1361150..6c8d0ec 100644 --- a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmtimefuncref.rs +++ b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmtimefuncref.rs @@ -48,13 +48,13 @@ impl From for jlong { bind_java_type! { rust_type = pub JWasmtimeFuncRef, - java_type = "io.github.stefanrichterhuber.wasmtimejavang.internal.WasmtimeFuncRef", + java_type = "jp.akkiserver.shuttle.internal.WasmtimeFuncRef", type_map = { unsafe FuncHandle => long, unsafe StoreHandle => long, - JWasmtimeInstance => "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeInstance", - JWasmtimeFunction => "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeFunction", + JWasmtimeInstance => "jp.akkiserver.shuttle.WasmtimeInstance", + JWasmtimeFunction => "jp.akkiserver.shuttle.WasmtimeFunction", }, constructors { diff --git a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmtimefunction.rs b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmtimefunction.rs similarity index 59% rename from wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmtimefunction.rs rename to shuttle-java/src/main/rust/wasmtime-binding/src/wasmtimefunction.rs index e76ede3..e7eec3d 100644 --- a/wasmtimejavang/src/main/rust/wasmtime-binding/src/wasmtimefunction.rs +++ b/shuttle-java/src/main/rust/wasmtime-binding/src/wasmtimefunction.rs @@ -3,10 +3,10 @@ use jni::bind_java_type; bind_java_type! { rust_type = pub JWasmtimeFunction, - java_type = "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeFunction", + java_type = "jp.akkiserver.shuttle.WasmtimeFunction", type_map = { - JWasmtimeInstance => "io.github.stefanrichterhuber.wasmtimejavang.WasmtimeInstance", + JWasmtimeInstance => "jp.akkiserver.shuttle.WasmtimeInstance", }, methods = { diff --git a/wasmtimejavang/src/main/rust/wasmtime-binding/src/weave.rs b/shuttle-java/src/main/rust/wasmtime-binding/src/weave.rs similarity index 97% rename from wasmtimejavang/src/main/rust/wasmtime-binding/src/weave.rs rename to shuttle-java/src/main/rust/wasmtime-binding/src/weave.rs index d2ebbb9..6cfb02e 100644 --- a/wasmtimejavang/src/main/rust/wasmtime-binding/src/weave.rs +++ b/shuttle-java/src/main/rust/wasmtime-binding/src/weave.rs @@ -29,24 +29,24 @@ use crate::wasmtime_valtype::convert_val_type_enum_list_to_vec; bind_java_type! { rust_type = pub JWeaveCaller, - java_type = "io.github.stefanrichterhuber.wasmtimejavang.WeaveCaller", + java_type = "jp.akkiserver.shuttle.WeaveCaller", constructors { fn new(ptr: jlong) }, } bind_java_type! { rust_type = pub JWeaveHostFunction, - java_type = "io.github.stefanrichterhuber.wasmtimejavang.WeaveHostFunction", + java_type = "jp.akkiserver.shuttle.WeaveHostFunction", type_map = { - JWeaveCaller => "io.github.stefanrichterhuber.wasmtimejavang.WeaveCaller", + JWeaveCaller => "jp.akkiserver.shuttle.WeaveCaller", }, methods { fn call(caller: JWeaveCaller, args: jlong[]) -> jlong[] }, } bind_java_type! { rust_type = pub JWeaveImport, - java_type = "io.github.stefanrichterhuber.wasmtimejavang.WeaveImport", + java_type = "jp.akkiserver.shuttle.WeaveImport", type_map = { - JWeaveHostFunction => "io.github.stefanrichterhuber.wasmtimejavang.WeaveHostFunction", + JWeaveHostFunction => "jp.akkiserver.shuttle.WeaveHostFunction", }, methods { fn module() -> JString, @@ -59,7 +59,7 @@ bind_java_type! { bind_java_type! { rust_type = pub JWeaveNative, - java_type = "io.github.stefanrichterhuber.wasmtimejavang.WeaveNative", + java_type = "jp.akkiserver.shuttle.WeaveNative", native_methods { extern static fn module_create(raw: JByteBuffer, poll_period: jint, stack_pages: jint) -> jlong, extern static fn module_close(handle: jlong), diff --git a/wasmtimejavang/src/test/java/io/github/stefanrichterhuber/wasmtimejavang/SemanticVersionTest.java b/shuttle-java/src/test/java/jp/akkiserver/shuttle/SemanticVersionTest.java similarity index 97% rename from wasmtimejavang/src/test/java/io/github/stefanrichterhuber/wasmtimejavang/SemanticVersionTest.java rename to shuttle-java/src/test/java/jp/akkiserver/shuttle/SemanticVersionTest.java index 5bed32c..4cf3dcb 100644 --- a/wasmtimejavang/src/test/java/io/github/stefanrichterhuber/wasmtimejavang/SemanticVersionTest.java +++ b/shuttle-java/src/test/java/jp/akkiserver/shuttle/SemanticVersionTest.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; diff --git a/wasmtimejavang/src/test/java/io/github/stefanrichterhuber/wasmtimejavang/V128Test.java b/shuttle-java/src/test/java/jp/akkiserver/shuttle/V128Test.java similarity index 99% rename from wasmtimejavang/src/test/java/io/github/stefanrichterhuber/wasmtimejavang/V128Test.java rename to shuttle-java/src/test/java/jp/akkiserver/shuttle/V128Test.java index 148a48e..e65443e 100644 --- a/wasmtimejavang/src/test/java/io/github/stefanrichterhuber/wasmtimejavang/V128Test.java +++ b/shuttle-java/src/test/java/jp/akkiserver/shuttle/V128Test.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/wasmtimejavang/src/test/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeComponentTest.java b/shuttle-java/src/test/java/jp/akkiserver/shuttle/WasmtimeComponentTest.java similarity index 98% rename from wasmtimejavang/src/test/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeComponentTest.java rename to shuttle-java/src/test/java/jp/akkiserver/shuttle/WasmtimeComponentTest.java index cac140f..83b7505 100644 --- a/wasmtimejavang/src/test/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeComponentTest.java +++ b/shuttle-java/src/test/java/jp/akkiserver/shuttle/WasmtimeComponentTest.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/wasmtimejavang/src/test/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeEngineTest.java b/shuttle-java/src/test/java/jp/akkiserver/shuttle/WasmtimeEngineTest.java similarity index 99% rename from wasmtimejavang/src/test/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeEngineTest.java rename to shuttle-java/src/test/java/jp/akkiserver/shuttle/WasmtimeEngineTest.java index 594824c..39cde41 100644 --- a/wasmtimejavang/src/test/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeEngineTest.java +++ b/shuttle-java/src/test/java/jp/akkiserver/shuttle/WasmtimeEngineTest.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; diff --git a/wasmtimejavang/src/test/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeMemoryTest.java b/shuttle-java/src/test/java/jp/akkiserver/shuttle/WasmtimeMemoryTest.java similarity index 98% rename from wasmtimejavang/src/test/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeMemoryTest.java rename to shuttle-java/src/test/java/jp/akkiserver/shuttle/WasmtimeMemoryTest.java index 7ea3cc7..3d12efe 100644 --- a/wasmtimejavang/src/test/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeMemoryTest.java +++ b/shuttle-java/src/test/java/jp/akkiserver/shuttle/WasmtimeMemoryTest.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; diff --git a/wasmtimejavang/src/test/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeValueTest.java b/shuttle-java/src/test/java/jp/akkiserver/shuttle/WasmtimeValueTest.java similarity index 99% rename from wasmtimejavang/src/test/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeValueTest.java rename to shuttle-java/src/test/java/jp/akkiserver/shuttle/WasmtimeValueTest.java index 80181b2..9a358d8 100644 --- a/wasmtimejavang/src/test/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeValueTest.java +++ b/shuttle-java/src/test/java/jp/akkiserver/shuttle/WasmtimeValueTest.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/wasmtimejavang/src/test/java/io/github/stefanrichterhuber/wasmtimejavang/WeaveTest.java b/shuttle-java/src/test/java/jp/akkiserver/shuttle/WeaveTest.java similarity index 99% rename from wasmtimejavang/src/test/java/io/github/stefanrichterhuber/wasmtimejavang/WeaveTest.java rename to shuttle-java/src/test/java/jp/akkiserver/shuttle/WeaveTest.java index 64f7cd5..6fb1be8 100644 --- a/wasmtimejavang/src/test/java/io/github/stefanrichterhuber/wasmtimejavang/WeaveTest.java +++ b/shuttle-java/src/test/java/jp/akkiserver/shuttle/WeaveTest.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.wasmtimejavang; +package jp.akkiserver.shuttle; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/wasmtimejavang/src/test/resources/junit-platform.properties b/shuttle-java/src/test/resources/junit-platform.properties similarity index 100% rename from wasmtimejavang/src/test/resources/junit-platform.properties rename to shuttle-java/src/test/resources/junit-platform.properties diff --git a/wasmtimejavang/src/test/resources/log4j2.xml b/shuttle-java/src/test/resources/log4j2.xml similarity index 100% rename from wasmtimejavang/src/test/resources/log4j2.xml rename to shuttle-java/src/test/resources/log4j2.xml diff --git a/wasmtimejavang/src/test/rust/valuetest/Cargo.lock b/shuttle-java/src/test/rust/valuetest/Cargo.lock similarity index 100% rename from wasmtimejavang/src/test/rust/valuetest/Cargo.lock rename to shuttle-java/src/test/rust/valuetest/Cargo.lock diff --git a/wasmtimejavang/src/test/rust/valuetest/Cargo.toml b/shuttle-java/src/test/rust/valuetest/Cargo.toml similarity index 100% rename from wasmtimejavang/src/test/rust/valuetest/Cargo.toml rename to shuttle-java/src/test/rust/valuetest/Cargo.toml diff --git a/wasmtimejavang/src/test/rust/valuetest/src/lib.rs b/shuttle-java/src/test/rust/valuetest/src/lib.rs similarity index 100% rename from wasmtimejavang/src/test/rust/valuetest/src/lib.rs rename to shuttle-java/src/test/rust/valuetest/src/lib.rs diff --git a/wit-codegen-maven-plugin/pom.xml b/shuttle-wit-maven-plugin/pom.xml similarity index 84% rename from wit-codegen-maven-plugin/pom.xml rename to shuttle-wit-maven-plugin/pom.xml index 108385d..2117a42 100644 --- a/wit-codegen-maven-plugin/pom.xml +++ b/shuttle-wit-maven-plugin/pom.xml @@ -4,18 +4,18 @@ 4.0.0 - io.github.stefanrichterhuber - wasmtimejavang-parent + jp.akkiserver + shuttle 6.0.1-SNAPSHOT .. - wit-codegen-maven-plugin + shuttle-wit-maven-plugin maven-plugin - wit-codegen-maven-plugin + shuttle-wit-maven-plugin Maven plugin generating abstract WasmComponentContext implementations from WIT interfaces, so custom component contexts only need to implement typed abstract methods instead of hand-writing the interface/version/getImportFunctions plumbing. - https://github.com/StefanRichterHuber/wasmtime-java-ng + https://github.com/akkiserver-dev/shuttle 3.15.1 @@ -23,8 +23,8 @@ - io.github.stefanrichterhuber - wit-parser + jp.akkiserver + shuttle-wit-parser ${project.version} @@ -56,8 +56,8 @@ - io.github.stefanrichterhuber - wasmtimejavang + jp.akkiserver + shuttle-java ${project.version} test diff --git a/wit-codegen-maven-plugin/src/main/java/io/github/stefanrichterhuber/witcodegen/GenerateWitSourcesMojo.java b/shuttle-wit-maven-plugin/src/main/java/jp/akkiserver/shuttle/wit/codegen/GenerateWitSourcesMojo.java similarity index 97% rename from wit-codegen-maven-plugin/src/main/java/io/github/stefanrichterhuber/witcodegen/GenerateWitSourcesMojo.java rename to shuttle-wit-maven-plugin/src/main/java/jp/akkiserver/shuttle/wit/codegen/GenerateWitSourcesMojo.java index 814ecfc..197e99c 100644 --- a/wit-codegen-maven-plugin/src/main/java/io/github/stefanrichterhuber/witcodegen/GenerateWitSourcesMojo.java +++ b/shuttle-wit-maven-plugin/src/main/java/jp/akkiserver/shuttle/wit/codegen/GenerateWitSourcesMojo.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.witcodegen; +package jp.akkiserver.shuttle.wit.codegen; import java.io.File; import java.io.IOException; @@ -16,8 +16,8 @@ import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.project.MavenProject; -import io.github.stefanrichterhuber.witparser.WitInterface; -import io.github.stefanrichterhuber.witparser.WitParser; +import jp.akkiserver.shuttle.wit.parser.WitInterface; +import jp.akkiserver.shuttle.wit.parser.WitParser; /** * Generates one abstract {@code WasmComponentContext} implementation per WIT diff --git a/wit-codegen-maven-plugin/src/main/java/io/github/stefanrichterhuber/witcodegen/WitCodeGenerator.java b/shuttle-wit-maven-plugin/src/main/java/jp/akkiserver/shuttle/wit/codegen/WitCodeGenerator.java similarity index 93% rename from wit-codegen-maven-plugin/src/main/java/io/github/stefanrichterhuber/witcodegen/WitCodeGenerator.java rename to shuttle-wit-maven-plugin/src/main/java/jp/akkiserver/shuttle/wit/codegen/WitCodeGenerator.java index b6e6384..565eecc 100644 --- a/wit-codegen-maven-plugin/src/main/java/io/github/stefanrichterhuber/witcodegen/WitCodeGenerator.java +++ b/shuttle-wit-maven-plugin/src/main/java/jp/akkiserver/shuttle/wit/codegen/WitCodeGenerator.java @@ -1,15 +1,15 @@ -package io.github.stefanrichterhuber.witcodegen; +package jp.akkiserver.shuttle.wit.codegen; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.TreeSet; -import io.github.stefanrichterhuber.witparser.WitFunction; -import io.github.stefanrichterhuber.witparser.WitInterface; -import io.github.stefanrichterhuber.witparser.WitParam; -import io.github.stefanrichterhuber.witparser.WitTypeKind; -import io.github.stefanrichterhuber.witparser.WitValueType; +import jp.akkiserver.shuttle.wit.parser.WitFunction; +import jp.akkiserver.shuttle.wit.parser.WitInterface; +import jp.akkiserver.shuttle.wit.parser.WitParam; +import jp.akkiserver.shuttle.wit.parser.WitTypeKind; +import jp.akkiserver.shuttle.wit.parser.WitValueType; /** * Generates a {@code WasmComponentContext}-extending interface from a single @@ -141,11 +141,11 @@ public static String generate(String targetPackage, WitInterface iface) { import java.util.Set; %s - import io.github.stefanrichterhuber.wasmtimejavang.WasmComponentContext; - import io.github.stefanrichterhuber.wasmtimejavang.WasmtimeComponentInstance; + import jp.akkiserver.shuttle.WasmComponentContext; + import jp.akkiserver.shuttle.WasmtimeComponentInstance; /** - * Generated from WIT interface "%s" by wit-codegen-maven-plugin. + * Generated from WIT interface "%s" by shuttle-wit-maven-plugin. * Do not edit directly -- implement this interface (alongside any others, * on the same class if they belong to the same bundle) instead. */ @@ -202,16 +202,16 @@ private static Set requiredImports(WitInterface iface) { imports.add("import java.util.Map;"); } if (kinds.contains(WitTypeKind.VARIANT)) { - imports.add("import io.github.stefanrichterhuber.wasmtimejavang.component.WitVariant;"); + imports.add("import component.jp.akkiserver.shuttle.WitVariant;"); } if (kinds.contains(WitTypeKind.ENUM)) { - imports.add("import io.github.stefanrichterhuber.wasmtimejavang.component.WitEnum;"); + imports.add("import component.jp.akkiserver.shuttle.WitEnum;"); } if (kinds.contains(WitTypeKind.RESULT)) { - imports.add("import io.github.stefanrichterhuber.wasmtimejavang.component.WitResult;"); + imports.add("import component.jp.akkiserver.shuttle.WitResult;"); } if (kinds.contains(WitTypeKind.RESOURCE)) { - imports.add("import io.github.stefanrichterhuber.wasmtimejavang.component.WitResource;"); + imports.add("import component.jp.akkiserver.shuttle.WitResource;"); } return imports; } diff --git a/wit-codegen-maven-plugin/src/test/java/io/github/stefanrichterhuber/witcodegen/GenerateWitSourcesMojoTest.java b/shuttle-wit-maven-plugin/src/test/java/jp/akkiserver/shuttle/wit/codegen/GenerateWitSourcesMojoTest.java similarity index 89% rename from wit-codegen-maven-plugin/src/test/java/io/github/stefanrichterhuber/witcodegen/GenerateWitSourcesMojoTest.java rename to shuttle-wit-maven-plugin/src/test/java/jp/akkiserver/shuttle/wit/codegen/GenerateWitSourcesMojoTest.java index 3988fdd..ff52c0c 100644 --- a/wit-codegen-maven-plugin/src/test/java/io/github/stefanrichterhuber/witcodegen/GenerateWitSourcesMojoTest.java +++ b/shuttle-wit-maven-plugin/src/test/java/jp/akkiserver/shuttle/wit/codegen/GenerateWitSourcesMojoTest.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.witcodegen; +package jp.akkiserver.shuttle.wit.codegen; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -22,13 +22,13 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -import io.github.stefanrichterhuber.wasmtimejavang.WasmComponentContext; -import io.github.stefanrichterhuber.wasmtimejavang.WasmComponentContext.ComponentImportFunction; +import jp.akkiserver.shuttle.WasmComponentContext; +import jp.akkiserver.shuttle.WasmComponentContext.ComponentImportFunction; /** * End-to-end verification: runs {@link GenerateWitSourcesMojo} against the * same {@code greet} interface {@code GreetComponentContext} (in the - * {@code wasmtimejavang} module) hand-implements, then actually compiles the + * {@code shuttle-java} module) hand-implements, then actually compiles the * generated interface plus a small implementing class and drives it exactly * like {@code WasmtimeCustomComponentTest} drives the hand-written version -- * confirming the generated plumbing produces the same wiring a human would @@ -43,7 +43,7 @@ */ class GenerateWitSourcesMojoTest { - private static final String TARGET_PACKAGE = "io.github.stefanrichterhuber.witcodegen.generated"; + private static final String TARGET_PACKAGE = "jp.akkiserver.shuttle.wit.codegen.generated"; @TempDir Path tempDir; @@ -82,12 +82,12 @@ void generatesCompilableAbstractContext() throws Exception { public class GreetContextImpl implements GreetContext { @Override - public String greetHello(io.github.stefanrichterhuber.wasmtimejavang.WasmtimeComponentInstance instance, String name) { + public String greetHello(jp.akkiserver.shuttle.WasmtimeComponentInstance instance, String name) { return "Hello, " + name + "!"; } @Override - public int greetAdd(io.github.stefanrichterhuber.wasmtimejavang.WasmtimeComponentInstance instance, int a, int b) { + public int greetAdd(jp.akkiserver.shuttle.WasmtimeComponentInstance instance, int a, int b) { return a + b; } } diff --git a/wit-codegen-maven-plugin/src/test/java/io/github/stefanrichterhuber/witcodegen/GenerateWitSourcesMojoWorldTest.java b/shuttle-wit-maven-plugin/src/test/java/jp/akkiserver/shuttle/wit/codegen/GenerateWitSourcesMojoWorldTest.java similarity index 94% rename from wit-codegen-maven-plugin/src/test/java/io/github/stefanrichterhuber/witcodegen/GenerateWitSourcesMojoWorldTest.java rename to shuttle-wit-maven-plugin/src/test/java/jp/akkiserver/shuttle/wit/codegen/GenerateWitSourcesMojoWorldTest.java index 55a615b..082df96 100644 --- a/wit-codegen-maven-plugin/src/test/java/io/github/stefanrichterhuber/witcodegen/GenerateWitSourcesMojoWorldTest.java +++ b/shuttle-wit-maven-plugin/src/test/java/jp/akkiserver/shuttle/wit/codegen/GenerateWitSourcesMojoWorldTest.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.witcodegen; +package jp.akkiserver.shuttle.wit.codegen; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -14,6 +14,7 @@ import javax.tools.JavaCompiler; import javax.tools.ToolProvider; +import jp.akkiserver.shuttle.wit.parser.WitParser; import org.apache.maven.project.MavenProject; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -28,7 +29,7 @@ * worlds) and the standalone {@code wasi:sockets@0.2.8} package's own * "imports" world (which shares its world *name* -- "imports" -- with * every other individual WASI sub-package, exercising the package-scoped - * world lookup {@link io.github.stefanrichterhuber.witparser.WitParser#resolveWorld} + * world lookup {@link WitParser#resolveWorld} * needs to disambiguate). This is deliberately a compile-only check: full * behavioral verification of every generated function already exists for * the hand-written {@code wasip2} contexts; the bar here is "produces @@ -36,9 +37,9 @@ */ class GenerateWitSourcesMojoWorldTest { - private static final String CLI_TARGET_PACKAGE = "io.github.stefanrichterhuber.witcodegen.generated.wasicli"; + private static final String CLI_TARGET_PACKAGE = "jp.akkiserver.shuttle.wit.codegen.generated.wasicli"; private static final String SOCKETS_TARGET_PACKAGE = - "io.github.stefanrichterhuber.witcodegen.generated.wasisockets"; + "jp.akkiserver.shuttle.wit.codegen.generated.wasisockets"; @TempDir Path tempDir; diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/greet.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/greet.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/greet.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/greet.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/command.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/command.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/command.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/command.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps.toml b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps.toml similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps.toml rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps.toml diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/clocks/monotonic-clock.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/clocks/monotonic-clock.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/clocks/monotonic-clock.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/clocks/monotonic-clock.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/clocks/timezone.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/clocks/timezone.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/clocks/timezone.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/clocks/timezone.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/clocks/wall-clock.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/clocks/wall-clock.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/clocks/wall-clock.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/clocks/wall-clock.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/clocks/world.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/clocks/world.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/clocks/world.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/clocks/world.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/filesystem/preopens.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/filesystem/preopens.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/filesystem/preopens.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/filesystem/preopens.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/filesystem/types.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/filesystem/types.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/filesystem/types.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/filesystem/types.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/filesystem/world.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/filesystem/world.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/filesystem/world.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/filesystem/world.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/io/error.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/io/error.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/io/error.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/io/error.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/io/poll.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/io/poll.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/io/poll.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/io/poll.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/io/streams.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/io/streams.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/io/streams.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/io/streams.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/io/world.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/io/world.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/io/world.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/io/world.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/random/insecure-seed.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/random/insecure-seed.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/random/insecure-seed.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/random/insecure-seed.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/random/insecure.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/random/insecure.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/random/insecure.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/random/insecure.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/random/random.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/random/random.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/random/random.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/random/random.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/random/world.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/random/world.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/random/world.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/random/world.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/instance-network.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/instance-network.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/instance-network.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/instance-network.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/ip-name-lookup.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/ip-name-lookup.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/ip-name-lookup.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/ip-name-lookup.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/network.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/network.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/network.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/network.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/tcp-create-socket.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/tcp-create-socket.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/tcp-create-socket.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/tcp-create-socket.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/tcp.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/tcp.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/tcp.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/tcp.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/udp-create-socket.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/udp-create-socket.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/udp-create-socket.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/udp-create-socket.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/udp.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/udp.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/udp.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/udp.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/world.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/world.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/world.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/deps/sockets/world.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/environment.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/environment.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/environment.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/environment.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/exit.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/exit.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/exit.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/exit.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/imports.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/imports.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/imports.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/imports.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/run.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/run.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/run.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/run.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/stdio.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/stdio.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/stdio.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/stdio.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/terminal.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/terminal.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-cli/wit/terminal.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-cli/wit/terminal.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/deps.lock b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/deps.lock similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/deps.lock rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/deps.lock diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/deps.toml b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/deps.toml similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/deps.toml rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/deps.toml diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/deps/clocks/monotonic-clock.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/deps/clocks/monotonic-clock.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/deps/clocks/monotonic-clock.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/deps/clocks/monotonic-clock.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/deps/clocks/timezone.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/deps/clocks/timezone.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/deps/clocks/timezone.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/deps/clocks/timezone.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/deps/clocks/wall-clock.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/deps/clocks/wall-clock.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/deps/clocks/wall-clock.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/deps/clocks/wall-clock.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/deps/clocks/world.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/deps/clocks/world.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/deps/clocks/world.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/deps/clocks/world.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/deps/io/error.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/deps/io/error.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/deps/io/error.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/deps/io/error.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/deps/io/poll.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/deps/io/poll.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/deps/io/poll.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/deps/io/poll.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/deps/io/streams.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/deps/io/streams.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/deps/io/streams.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/deps/io/streams.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/deps/io/world.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/deps/io/world.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/deps/io/world.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/deps/io/world.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/instance-network.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/instance-network.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/instance-network.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/instance-network.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/ip-name-lookup.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/ip-name-lookup.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/ip-name-lookup.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/ip-name-lookup.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/network.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/network.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/network.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/network.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/tcp-create-socket.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/tcp-create-socket.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/tcp-create-socket.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/tcp-create-socket.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/tcp.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/tcp.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/tcp.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/tcp.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/udp-create-socket.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/udp-create-socket.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/udp-create-socket.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/udp-create-socket.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/udp.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/udp.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/udp.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/udp.wit diff --git a/wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/world.wit b/shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/world.wit similarity index 100% rename from wit-codegen-maven-plugin/src/test/resources/wit/wasi-sockets/world.wit rename to shuttle-wit-maven-plugin/src/test/resources/wit/wasi-sockets/world.wit diff --git a/wit-parser/pom.xml b/shuttle-wit-parser/pom.xml similarity index 92% rename from wit-parser/pom.xml rename to shuttle-wit-parser/pom.xml index 6bfccb2..a10c212 100644 --- a/wit-parser/pom.xml +++ b/shuttle-wit-parser/pom.xml @@ -4,17 +4,17 @@ 4.0.0 - io.github.stefanrichterhuber - wasmtimejavang-parent + jp.akkiserver + shuttle 6.0.1-SNAPSHOT .. - wit-parser + shuttle-wit-parser - wit-parser + shuttle-wit-parser JNI binding to the Rust wit-parser crate, resolving a WIT file's interfaces and functions into Java objects. Build-time only -- not used at WASM runtime. - https://github.com/StefanRichterHuber/wasmtime-java-ng + https://github.com/akkiserver-dev/shuttle @@ -53,7 +53,7 @@ build wit-parser-binding @@ -96,7 +96,7 @@ - ${project.build.directory}/classes/io/github/stefanrichterhuber/witparser/libs/linux-x86-64 + ${project.build.directory}/classes/jp/akkiserver/shuttle/wit/parser/libs/linux-x86-64 diff --git a/wit-parser/src/main/java/io/github/stefanrichterhuber/witparser/WitFunction.java b/shuttle-wit-parser/src/main/java/jp/akkiserver/shuttle/wit/parser/WitFunction.java similarity index 97% rename from wit-parser/src/main/java/io/github/stefanrichterhuber/witparser/WitFunction.java rename to shuttle-wit-parser/src/main/java/jp/akkiserver/shuttle/wit/parser/WitFunction.java index 636067d..c4254cd 100644 --- a/wit-parser/src/main/java/io/github/stefanrichterhuber/witparser/WitFunction.java +++ b/shuttle-wit-parser/src/main/java/jp/akkiserver/shuttle/wit/parser/WitFunction.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.witparser; +package jp.akkiserver.shuttle.wit.parser; import java.util.Arrays; import java.util.List; diff --git a/wit-parser/src/main/java/io/github/stefanrichterhuber/witparser/WitInterface.java b/shuttle-wit-parser/src/main/java/jp/akkiserver/shuttle/wit/parser/WitInterface.java similarity index 96% rename from wit-parser/src/main/java/io/github/stefanrichterhuber/witparser/WitInterface.java rename to shuttle-wit-parser/src/main/java/jp/akkiserver/shuttle/wit/parser/WitInterface.java index ac89a72..09701a4 100644 --- a/wit-parser/src/main/java/io/github/stefanrichterhuber/witparser/WitInterface.java +++ b/shuttle-wit-parser/src/main/java/jp/akkiserver/shuttle/wit/parser/WitInterface.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.witparser; +package jp.akkiserver.shuttle.wit.parser; import java.util.Arrays; import java.util.List; diff --git a/wit-parser/src/main/java/io/github/stefanrichterhuber/witparser/WitParam.java b/shuttle-wit-parser/src/main/java/jp/akkiserver/shuttle/wit/parser/WitParam.java similarity index 92% rename from wit-parser/src/main/java/io/github/stefanrichterhuber/witparser/WitParam.java rename to shuttle-wit-parser/src/main/java/jp/akkiserver/shuttle/wit/parser/WitParam.java index df6f429..2447483 100644 --- a/wit-parser/src/main/java/io/github/stefanrichterhuber/witparser/WitParam.java +++ b/shuttle-wit-parser/src/main/java/jp/akkiserver/shuttle/wit/parser/WitParam.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.witparser; +package jp.akkiserver.shuttle.wit.parser; /** * A single parameter of a {@link WitFunction}. diff --git a/wit-parser/src/main/java/io/github/stefanrichterhuber/witparser/WitParser.java b/shuttle-wit-parser/src/main/java/jp/akkiserver/shuttle/wit/parser/WitParser.java similarity index 96% rename from wit-parser/src/main/java/io/github/stefanrichterhuber/witparser/WitParser.java rename to shuttle-wit-parser/src/main/java/jp/akkiserver/shuttle/wit/parser/WitParser.java index 45963c4..1fcdd7b 100644 --- a/wit-parser/src/main/java/io/github/stefanrichterhuber/witparser/WitParser.java +++ b/shuttle-wit-parser/src/main/java/jp/akkiserver/shuttle/wit/parser/WitParser.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.witparser; +package jp.akkiserver.shuttle.wit.parser; import java.nio.file.Path; import java.util.Arrays; @@ -23,7 +23,7 @@ public final class WitParser { static { JarJniLoader.loadLib( WitParser.class, - "/io/github/stefanrichterhuber/witparser/libs", + "/jp/akkiserver/shuttle/wit/parser/libs", "witparserbinding"); } diff --git a/wit-parser/src/main/java/io/github/stefanrichterhuber/witparser/WitTypeKind.java b/shuttle-wit-parser/src/main/java/jp/akkiserver/shuttle/wit/parser/WitTypeKind.java similarity index 98% rename from wit-parser/src/main/java/io/github/stefanrichterhuber/witparser/WitTypeKind.java rename to shuttle-wit-parser/src/main/java/jp/akkiserver/shuttle/wit/parser/WitTypeKind.java index de53f82..8698411 100644 --- a/wit-parser/src/main/java/io/github/stefanrichterhuber/witparser/WitTypeKind.java +++ b/shuttle-wit-parser/src/main/java/jp/akkiserver/shuttle/wit/parser/WitTypeKind.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.witparser; +package jp.akkiserver.shuttle.wit.parser; /** * Every WIT type-system shape this pipeline understands, classified down to diff --git a/wit-parser/src/main/java/io/github/stefanrichterhuber/witparser/WitValueType.java b/shuttle-wit-parser/src/main/java/jp/akkiserver/shuttle/wit/parser/WitValueType.java similarity index 91% rename from wit-parser/src/main/java/io/github/stefanrichterhuber/witparser/WitValueType.java rename to shuttle-wit-parser/src/main/java/jp/akkiserver/shuttle/wit/parser/WitValueType.java index ccb7f7f..3a392c9 100644 --- a/wit-parser/src/main/java/io/github/stefanrichterhuber/witparser/WitValueType.java +++ b/shuttle-wit-parser/src/main/java/jp/akkiserver/shuttle/wit/parser/WitValueType.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.witparser; +package jp.akkiserver.shuttle.wit.parser; /** * The WIT type of a {@link WitParam} or a {@link WitFunction}'s result, diff --git a/wit-parser/src/main/rust/wit-parser-binding/Cargo.lock b/shuttle-wit-parser/src/main/rust/wit-parser-binding/Cargo.lock similarity index 100% rename from wit-parser/src/main/rust/wit-parser-binding/Cargo.lock rename to shuttle-wit-parser/src/main/rust/wit-parser-binding/Cargo.lock diff --git a/wit-parser/src/main/rust/wit-parser-binding/Cargo.toml b/shuttle-wit-parser/src/main/rust/wit-parser-binding/Cargo.toml similarity index 100% rename from wit-parser/src/main/rust/wit-parser-binding/Cargo.toml rename to shuttle-wit-parser/src/main/rust/wit-parser-binding/Cargo.toml diff --git a/wit-parser/src/main/rust/wit-parser-binding/src/lib.rs b/shuttle-wit-parser/src/main/rust/wit-parser-binding/src/lib.rs similarity index 97% rename from wit-parser/src/main/rust/wit-parser-binding/src/lib.rs rename to shuttle-wit-parser/src/main/rust/wit-parser-binding/src/lib.rs index 81701cf..2df68b5 100644 --- a/wit-parser/src/main/rust/wit-parser-binding/src/lib.rs +++ b/shuttle-wit-parser/src/main/rust/wit-parser-binding/src/lib.rs @@ -11,7 +11,7 @@ use wit_parser::{Handle, Interface, Resolve, Type, TypeDefKind, TypeId, WorldIte bind_java_type! { rust_type = pub JWitParam, - java_type = "io.github.stefanrichterhuber.witparser.WitParam", + java_type = "jp.akkiserver.shuttle.wit.parser.WitParam", constructors { fn new(name: JString, type_tag: JString, resource_name: JString), @@ -20,7 +20,7 @@ bind_java_type! { bind_java_type! { rust_type = pub JWitFunction, - java_type = "io.github.stefanrichterhuber.witparser.WitFunction", + java_type = "jp.akkiserver.shuttle.wit.parser.WitFunction", constructors { fn new(name: JString, params: JObject[], result_tag: JString, result_resource_name: JString), @@ -29,7 +29,7 @@ bind_java_type! { bind_java_type! { rust_type = pub JWitInterface, - java_type = "io.github.stefanrichterhuber.witparser.WitInterface", + java_type = "jp.akkiserver.shuttle.wit.parser.WitInterface", constructors { fn new(name: JString, functions: JObject[], resources: JObject[]), @@ -38,7 +38,7 @@ bind_java_type! { bind_java_type! { rust_type = pub JWitParser, - java_type = "io.github.stefanrichterhuber.witparser.WitParser", + java_type = "jp.akkiserver.shuttle.wit.parser.WitParser", native_methods { extern static fn parse_wit_file(path: JString) -> JObject[], @@ -392,21 +392,21 @@ fn build_interfaces_array<'local>( ) -> Result, jni::errors::Error> { let interfaces_array = env.new_object_array( parsed.len() as jsize, - jni_str!("io.github.stefanrichterhuber.witparser.WitInterface"), + jni_str!("jp.akkiserver.shuttle.wit.parser.WitInterface"), JObject::null(), )?; for (i, iface) in parsed.iter().enumerate() { let functions_array = env.new_object_array( iface.functions.len() as jsize, - jni_str!("io.github.stefanrichterhuber.witparser.WitFunction"), + jni_str!("jp.akkiserver.shuttle.wit.parser.WitFunction"), JObject::null(), )?; for (j, func) in iface.functions.iter().enumerate() { let params_array = env.new_object_array( func.params.len() as jsize, - jni_str!("io.github.stefanrichterhuber.witparser.WitParam"), + jni_str!("jp.akkiserver.shuttle.wit.parser.WitParam"), JObject::null(), )?; diff --git a/wit-parser/src/test/java/io/github/stefanrichterhuber/witparser/WitParserTest.java b/shuttle-wit-parser/src/test/java/jp/akkiserver/shuttle/wit/parser/WitParserTest.java similarity index 99% rename from wit-parser/src/test/java/io/github/stefanrichterhuber/witparser/WitParserTest.java rename to shuttle-wit-parser/src/test/java/jp/akkiserver/shuttle/wit/parser/WitParserTest.java index f291ef1..8d0c115 100644 --- a/wit-parser/src/test/java/io/github/stefanrichterhuber/witparser/WitParserTest.java +++ b/shuttle-wit-parser/src/test/java/jp/akkiserver/shuttle/wit/parser/WitParserTest.java @@ -1,4 +1,4 @@ -package io.github.stefanrichterhuber.witparser; +package jp.akkiserver.shuttle.wit.parser; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; diff --git a/wit-parser/src/test/resources/wit/greet.wit b/shuttle-wit-parser/src/test/resources/wit/greet.wit similarity index 100% rename from wit-parser/src/test/resources/wit/greet.wit rename to shuttle-wit-parser/src/test/resources/wit/greet.wit diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/command.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/command.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/command.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/command.wit diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/deps.toml b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps.toml similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/deps.toml rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps.toml diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/deps/clocks/monotonic-clock.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/clocks/monotonic-clock.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/deps/clocks/monotonic-clock.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/clocks/monotonic-clock.wit diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/deps/clocks/timezone.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/clocks/timezone.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/deps/clocks/timezone.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/clocks/timezone.wit diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/deps/clocks/wall-clock.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/clocks/wall-clock.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/deps/clocks/wall-clock.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/clocks/wall-clock.wit diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/deps/clocks/world.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/clocks/world.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/deps/clocks/world.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/clocks/world.wit diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/deps/filesystem/preopens.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/filesystem/preopens.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/deps/filesystem/preopens.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/filesystem/preopens.wit diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/deps/filesystem/types.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/filesystem/types.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/deps/filesystem/types.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/filesystem/types.wit diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/deps/filesystem/world.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/filesystem/world.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/deps/filesystem/world.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/filesystem/world.wit diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/deps/io/error.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/io/error.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/deps/io/error.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/io/error.wit diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/deps/io/poll.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/io/poll.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/deps/io/poll.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/io/poll.wit diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/deps/io/streams.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/io/streams.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/deps/io/streams.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/io/streams.wit diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/deps/io/world.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/io/world.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/deps/io/world.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/io/world.wit diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/deps/random/insecure-seed.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/random/insecure-seed.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/deps/random/insecure-seed.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/random/insecure-seed.wit diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/deps/random/insecure.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/random/insecure.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/deps/random/insecure.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/random/insecure.wit diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/deps/random/random.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/random/random.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/deps/random/random.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/random/random.wit diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/deps/random/world.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/random/world.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/deps/random/world.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/random/world.wit diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/instance-network.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/instance-network.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/instance-network.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/instance-network.wit diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/ip-name-lookup.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/ip-name-lookup.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/ip-name-lookup.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/ip-name-lookup.wit diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/network.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/network.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/network.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/network.wit diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/tcp-create-socket.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/tcp-create-socket.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/tcp-create-socket.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/tcp-create-socket.wit diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/tcp.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/tcp.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/tcp.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/tcp.wit diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/udp-create-socket.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/udp-create-socket.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/udp-create-socket.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/udp-create-socket.wit diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/udp.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/udp.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/udp.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/udp.wit diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/world.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/world.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/world.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/deps/sockets/world.wit diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/environment.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/environment.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/environment.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/environment.wit diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/exit.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/exit.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/exit.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/exit.wit diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/imports.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/imports.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/imports.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/imports.wit diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/run.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/run.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/run.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/run.wit diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/stdio.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/stdio.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/stdio.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/stdio.wit diff --git a/wit-parser/src/test/resources/wit/wasi-cli/wit/terminal.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/terminal.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-cli/wit/terminal.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-cli/wit/terminal.wit diff --git a/wit-parser/src/test/resources/wit/wasi-sockets/deps.lock b/shuttle-wit-parser/src/test/resources/wit/wasi-sockets/deps.lock similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-sockets/deps.lock rename to shuttle-wit-parser/src/test/resources/wit/wasi-sockets/deps.lock diff --git a/wit-parser/src/test/resources/wit/wasi-sockets/deps.toml b/shuttle-wit-parser/src/test/resources/wit/wasi-sockets/deps.toml similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-sockets/deps.toml rename to shuttle-wit-parser/src/test/resources/wit/wasi-sockets/deps.toml diff --git a/wit-parser/src/test/resources/wit/wasi-sockets/deps/clocks/monotonic-clock.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-sockets/deps/clocks/monotonic-clock.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-sockets/deps/clocks/monotonic-clock.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-sockets/deps/clocks/monotonic-clock.wit diff --git a/wit-parser/src/test/resources/wit/wasi-sockets/deps/clocks/timezone.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-sockets/deps/clocks/timezone.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-sockets/deps/clocks/timezone.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-sockets/deps/clocks/timezone.wit diff --git a/wit-parser/src/test/resources/wit/wasi-sockets/deps/clocks/wall-clock.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-sockets/deps/clocks/wall-clock.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-sockets/deps/clocks/wall-clock.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-sockets/deps/clocks/wall-clock.wit diff --git a/wit-parser/src/test/resources/wit/wasi-sockets/deps/clocks/world.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-sockets/deps/clocks/world.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-sockets/deps/clocks/world.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-sockets/deps/clocks/world.wit diff --git a/wit-parser/src/test/resources/wit/wasi-sockets/deps/io/error.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-sockets/deps/io/error.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-sockets/deps/io/error.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-sockets/deps/io/error.wit diff --git a/wit-parser/src/test/resources/wit/wasi-sockets/deps/io/poll.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-sockets/deps/io/poll.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-sockets/deps/io/poll.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-sockets/deps/io/poll.wit diff --git a/wit-parser/src/test/resources/wit/wasi-sockets/deps/io/streams.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-sockets/deps/io/streams.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-sockets/deps/io/streams.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-sockets/deps/io/streams.wit diff --git a/wit-parser/src/test/resources/wit/wasi-sockets/deps/io/world.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-sockets/deps/io/world.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-sockets/deps/io/world.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-sockets/deps/io/world.wit diff --git a/wit-parser/src/test/resources/wit/wasi-sockets/instance-network.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-sockets/instance-network.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-sockets/instance-network.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-sockets/instance-network.wit diff --git a/wit-parser/src/test/resources/wit/wasi-sockets/ip-name-lookup.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-sockets/ip-name-lookup.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-sockets/ip-name-lookup.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-sockets/ip-name-lookup.wit diff --git a/wit-parser/src/test/resources/wit/wasi-sockets/network.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-sockets/network.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-sockets/network.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-sockets/network.wit diff --git a/wit-parser/src/test/resources/wit/wasi-sockets/tcp-create-socket.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-sockets/tcp-create-socket.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-sockets/tcp-create-socket.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-sockets/tcp-create-socket.wit diff --git a/wit-parser/src/test/resources/wit/wasi-sockets/tcp.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-sockets/tcp.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-sockets/tcp.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-sockets/tcp.wit diff --git a/wit-parser/src/test/resources/wit/wasi-sockets/udp-create-socket.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-sockets/udp-create-socket.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-sockets/udp-create-socket.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-sockets/udp-create-socket.wit diff --git a/wit-parser/src/test/resources/wit/wasi-sockets/udp.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-sockets/udp.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-sockets/udp.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-sockets/udp.wit diff --git a/wit-parser/src/test/resources/wit/wasi-sockets/world.wit b/shuttle-wit-parser/src/test/resources/wit/wasi-sockets/world.wit similarity index 100% rename from wit-parser/src/test/resources/wit/wasi-sockets/world.wit rename to shuttle-wit-parser/src/test/resources/wit/wasi-sockets/world.wit From 21dfd3b39125b0354505ee37b3431600dccaa851 Mon Sep 17 00:00:00 2001 From: akki <151368291+akki697222@users.noreply.github.com> Date: Thu, 15 Oct 2026 15:22:02 +0900 Subject: [PATCH 07/15] pom: add maintainer, keep upstream author with role Co-Authored-By: Claude Opus 5.5 --- pom.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pom.xml b/pom.xml index 97aadcf..786260f 100644 --- a/pom.xml +++ b/pom.xml @@ -20,11 +20,22 @@
+ + akki + akkiserver-dev + https://github.com/akkiserver-dev + + maintainer + + Stefan Richter-Huber stefan@richter-huber.de Stefan Richter-Huber https://github.com/StefanRichterHuber + + original author (wasmtime-java-ng) + From 94fa2136b97357a374c03aca039ce7a8416b1dad Mon Sep 17 00:00:00 2001 From: akki <151368291+akki697222@users.noreply.github.com> Date: Thu, 15 Oct 2026 15:22:11 +0900 Subject: [PATCH 08/15] HANDOFF: add old-to-new name mapping after the rename Co-Authored-By: Claude Opus 5.5 --- native/HANDOFF.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/native/HANDOFF.md b/native/HANDOFF.md index 2b12772..ec141f0 100644 --- a/native/HANDOFF.md +++ b/native/HANDOFF.md @@ -32,6 +32,24 @@ run **WebAssembly** programs. Everything the player runs is Wasm: a BIOS `native/README.md` explains the prototype, how to build it, and the results. +### Renamed on 2026-10-15 (commit `983dc25`) + +The text below keeps the old names as they were when it was written. Map them as follows: + +| Old | New | +| --- | --- | +| `wasmtimejavang/` (artifact `wasmtimejavang`) | `shuttle-java/` | +| `wasmtimejavang-example/` | `shuttle-java-example/` | +| `wit-parser/` | `shuttle-wit-parser/` | +| `wit-codegen-maven-plugin/` | `shuttle-wit-maven-plugin/` | +| groupId `io.github.stefanrichterhuber`, parent `wasmtimejavang-parent` | groupId `jp.akkiserver`, parent `shuttle` | +| package `io.github.stefanrichterhuber.wasmtimejavang` | `jp.akkiserver.shuttle` | +| package `io.github.stefanrichterhuber.witparser` / `.witcodegen` | `jp.akkiserver.shuttle.wit.parser` / `.wit.codegen` | + +`native/` keeps its name. The feature branches were also rebased onto +`main` (on top of `d400a75`), so section 3's note about them being based +on `917ffd6` is out of date. + ## 3. Current state - `native/` boots BIOS -> `exec` -> OS -> `co_create` -> child -> exit, in a From 021371ee9688263b518fc5de9eb50a12e718831e Mon Sep 17 00:00:00 2001 From: akki <151368291+akki697222@users.noreply.github.com> Date: Thu, 15 Oct 2026 15:38:55 +0900 Subject: [PATCH 09/15] Docs: rewrite README for Shuttle as a runtime library, move details to docs/ The root README now describes Shuttle as a Wasm runtime library for computer mods (OC via an addon, a new Retro Computing mod by default) and links to docs/: building.md, java-binding.md (incl. the Weave JNI layer), wit-codegen.md. Upstream material for removed modules (WASI, wasmtimejavang-wasi-*) and upstream release notes were dropped. Co-Authored-By: Claude Opus 5.5 --- README.md | 608 +++---------------------------------------- docs/README.md | 10 + docs/building.md | 146 +++++++++++ docs/java-binding.md | 292 +++++++++++++++++++++ docs/wit-codegen.md | 188 +++++++++++++ 5 files changed, 670 insertions(+), 574 deletions(-) create mode 100644 docs/README.md create mode 100644 docs/building.md create mode 100644 docs/java-binding.md create mode 100644 docs/wit-codegen.md diff --git a/README.md b/README.md index 94c31a3..d50efd2 100644 --- a/README.md +++ b/README.md @@ -2,37 +2,43 @@ # Shuttle -> **Status:** early prototype. Nothing here is playable yet; the native core runs headless only. +> **Status:** early prototype. The native core runs headless only; no mod uses Shuttle yet. -Shuttle is a Minecraft (NeoForge) mod that adds programmable computers, in the spirit of OpenComputers and CC:Tweaked. Unlike those mods, everything a Shuttle computer runs is **WebAssembly**: +Shuttle is a WebAssembly runtime library for Minecraft computer mods. It is not a mod itself: computer mods use it to run the programs on their in-game computers. Two consumers are planned: OpenComputers (OC), through a separate addon mod, and a new Retro Computing mod, which will include Shuttle by default. Neither integration exists yet. + +On behalf of the host mod, Shuttle runs a stack of Wasm guests: ``` -firmware (provided by the mod) - └─ BIOS player-made Wasm, stored on an EEPROM item +firmware implemented by Shuttle's native core + └─ BIOS player-made Wasm (for example stored on an EEPROM item) └─ OS kernel player-made Wasm, started by the BIOS with `exec` └─ child programs started by the kernel with `co_create` ``` -The firmware talks to guests only through the **firmware ABI** (`fw.*`, `co.*`, `sys.call`). Device calls look like OpenComputers method calls, either synchronous (`dev_call`) or asynchronous (`dev_submit` + a completion event). +The firmware talks to guests only through the **firmware ABI** (`fw.*`, `co.*`, `sys.call`). Device calls look like OpenComputers method calls, either synchronous (`dev_call`) or asynchronous (`dev_submit` + a completion event). The ABI is specified in a separate draft document (draft 0.1, not published in this repository); [`native/README.md`](native/README.md) lists which parts of it are implemented. ## How it works -- **Runtime:** [Wasmtime](https://github.com/bytecodealliance/wasmtime), made checkpointable with [Weave](https://github.com/akkiserver-dev/weave) (branch `shuttle-host-hooks`). Weave transforms a Wasm module so that a running program can be unwound into its linear memory and rebuilt later. This lets a computer be saved with the world and continue mid-execution after a reload. -- **Native core (Rust):** Wasmtime, Weave, the `co_*` machinery, memory limits and snapshot capture. It runs guests on its own worker thread pool. -- **Mod (Java):** device implementations and the high-level Machine API, connected to the native core through JNI. +- **Runtime:** [Wasmtime](https://github.com/bytecodealliance/wasmtime), made checkpointable with [Weave](https://github.com/akkiserver-dev/weave) (branch `shuttle-host-hooks`). Weave transforms a Wasm module so that a running program can be unwound into its linear memory and rebuilt later. This lets a host mod save a computer with the world and continue it mid-execution after a reload. +- **Native core (Rust, `native/`):** Wasmtime, Weave, the firmware ABI, the `co_*` machinery, memory limits and snapshot capture. Today it is driven by the headless `shuttle-runner`. +- **Java binding (`shuttle-java`):** Java API over Wasmtime and Weave through JNI, for the host mod to call. A high-level Machine API on top of the native core is planned but not written yet. - **Targets:** Windows, macOS and Linux, each on x86_64 and arm64. ## Repository layout | Path | What | | --- | --- | -| [`native/`](native) | Shuttle native core (Rust): `shuttle-core`, the headless `shuttle-runner`, and C test guests. See [`native/README.md`](native/README.md). | -| [`wasmtimejavang/`](wasmtimejavang) | Java bindings for Wasmtime (see [below](#wasmtime-java-binding-wasmtimejavang)). | -| [`wit-parser/`](wit-parser), [`wit-codegen-maven-plugin/`](wit-codegen-maven-plugin) | Build-time WIT tooling for the Java bindings. | +| [`native/`](native) | Shuttle native core (Rust): `shuttle-core`, the headless `shuttle-runner`, and C test guests in `native/guests`. See [`native/README.md`](native/README.md). | +| [`shuttle-java/`](shuttle-java) | Java bindings for Wasmtime plus the Weave (checkpointable Wasm) JNI layer. See [docs/java-binding.md](docs/java-binding.md). | +| [`shuttle-java-example/`](shuttle-java-example) | Runnable Weave example: run a guest a few "ticks" at a time, snapshot it, restore it and continue. | +| [`shuttle-wit-parser/`](shuttle-wit-parser), [`shuttle-wit-maven-plugin/`](shuttle-wit-maven-plugin) | Build-time WIT tooling: generate Java component-context interfaces from WIT files. See [docs/wit-codegen.md](docs/wit-codegen.md). | +| [`docs/`](docs) | Documentation. Start at [docs/README.md](docs/README.md). | + +The Java modules form one Maven reactor: groupId `jp.akkiserver`, parent artifactId `shuttle`, one artifact per directory (`shuttle-java`, `shuttle-java-example`, `shuttle-wit-parser`, `shuttle-wit-maven-plugin`). The version is set in the root [`pom.xml`](pom.xml). -## Building the native core +## Quick start -Requirements: Rust (rustup), and clang + wasm-ld for the C guests (the [LLVM installer](https://github.com/llvm/llvm-project/releases) on Windows, `sudo apt install clang lld` on Linux/WSL2). +Native core (requires Rust, plus clang and wasm-ld for the C guests): ```powershell .\native\scripts\build.ps1 # Windows: build guests + workspace, then verify @@ -41,574 +47,28 @@ Requirements: Rust (rustup), and clang + wasm-ld for the C guests (the [LLVM ins ./native/scripts/build.sh # Linux / WSL2 ``` -`verify` boots BIOS → OS → child, then repeats the run with capture → restore into a fresh machine at every tick boundary and checks that the logs are identical. Release binaries for all six platforms are built by CI ([`.github/workflows/native.yml`](.github/workflows/native.yml)). - -## Credits and license - -The Java Wasmtime bindings in this repository are a fork of [StefanRichterHuber/wasmtime-ng](https://github.com/StefanRichterHuber/wasmtime-ng) (MIT, © 2024 Stefan Richter-Huber). See [LICENSE](LICENSE). - -> **Disclaimer:** This project is an independent community effort and is not affiliated with, maintained, or endorsed by the [Wasmtime project](https://github.com/bytecodealliance/wasmtime), the Bytecode Alliance, Mojang or Microsoft. - -> **AI Disclaimer:** Parts of this project were vibe-coded or written with the help of an AI assistant (Claude); the remaining parts were written by hand. - -## Wasmtime Java binding (wasmtimejavang) - -The rest of this document comes from the upstream project and describes the Java bindings. - -Wasmtime-java-ng provides Java bindings for [Wasmtime](https://github.com/bytecodealliance/wasmtime), a fast, secure, and highly configurable WebAssembly runtime. - -This project allows Java applications to execute WebAssembly modules, interact with linear memory, and leverage the WebAssembly System Interface (WASI) through a native bridge built on Rust. - -### Project Structure - -This repository is a Maven multi-module reactor. As of this version, `wasmtimejavang` is a **core** artifact (Wasmtime primitives, the Component Model plumbing, WASI Preview 1) plus one artifact per WASI Preview 2 "world" — so a consumer only pulls in the WASI Preview 2 support they actually use, instead of everything at once: - -* **[`wasmtimejavang`](wasmtimejavang)** — the core artifact everyone depends on: `WasmtimeEngine`/`WasmtimeModule`/`WasmtimeStore`/`WasmtimeInstance`/`WasmtimeLinker`/`WasmtimeMemory`/`WasmtimeFunction`, the Component Model plumbing (`WasmtimeComponent`, `WasmtimeComponentLinker`, `WasmtimeComponentInstance`, `WasmComponentContext`), the native Rust bridge (all platforms), and WASI Preview 1 (`WasiPI1Context`, WASI threads). See [Usage](#usage) below. -* **[`wasmtimejavang-wasi-io`](wasmtimejavang-wasi-io)** — WASI Preview 2 `wasi:io/poll,streams,error`. Nearly every other WASI Preview 2 artifact depends on this one, since it owns the shared stream/pollable tables they hand resources out of. -* **[`wasmtimejavang-wasi-clocks`](wasmtimejavang-wasi-clocks)**, **[`wasmtimejavang-wasi-random`](wasmtimejavang-wasi-random)**, **[`wasmtimejavang-wasi-cli`](wasmtimejavang-wasi-cli)**, **[`wasmtimejavang-wasi-filesystem`](wasmtimejavang-wasi-filesystem)**, **[`wasmtimejavang-wasi-sockets`](wasmtimejavang-wasi-sockets)**, **[`wasmtimejavang-wasi-http`](wasmtimejavang-wasi-http)** — one artifact per remaining WASI Preview 2 "world", each depending on `wasmtimejavang-wasi-io` where it needs shared streams/pollables (all but `wasi-random`, which needs nothing beyond core). -* **[`wit-parser`](wit-parser)** and **[`wit-codegen-maven-plugin`](wit-codegen-maven-plugin)** — build-time-only tooling, not a runtime dependency of anything above. Together they let a *consuming* project (or, as of this version, every one of this repository's own WASI Preview 2 artifacts) generate typed, Java component-context interfaces straight from a WIT file instead of hand-writing them — see [Implementing your own component context](#implementing-your-own-component-context). - -Pick only the artifacts you need: depending on `wasmtimejavang` alone gets you core-wasm + WASI Preview 1, with no Component Model support at all; add whichever `wasmtimejavang-wasi-*` artifacts you actually need (each transitively pulls in `wasmtimejavang-wasi-io` where required) — e.g. just `wasmtimejavang-wasi-http` for an outgoing-HTTP-only guest, or `wasmtimejavang-wasi-cli` + `wasmtimejavang-wasi-filesystem` for a sandboxed-filesystem CLI tool. - -### Prerequisites - -Building this project requires both Rust and Java toolchains: - -* **Java 21+** and **Maven** -* **Rust** and **Cargo** -* **[cross-rs](https://github.com/cross-rs/cross)** and **Docker** (required for cross-platform native builds) - -### Building - -The project uses Maven to orchestrate both the Java compilation and the Rust native build. To build the entire project for Linux x86_64: - -```shell -mvn clean install -``` - -#### Multi-Platform Builds - -By default, only the native library for Linux x86_64 is built. You can target specific platforms using Maven profiles: - -* `build-linux-x86-64`: Linux x86_64 -* `build-linux-aarch64`: Linux Arm64 -* `build-windows-x86_64`: Windows x86_64 - -To build a JAR containing native libraries for all supported platforms: - -```shell -mvn -P build-linux-x86-64,build-linux-aarch64,build-windows-x86_64 clean install -``` - -For production environments, the `release` profile optimizes the Rust binaries for performance and size: - -```shell -mvn -P release,build-linux-x86-64,build-linux-aarch64,build-windows-x86_64 clean install -``` - -### Usage - -Include the core dependency into your project `pom.xml` (the published artifact contains native libraries for Linux x86_64, Linux aarch64 and Windows x86_64): - -```xml - - io.github.stefanrichterhuber - wasmtimejavang - [Current Version] - -``` - -This alone gets you core-wasm execution and WASI Preview 1 — no WASI Preview 2 / Component Model support. To run `wasm32-wasip2` components, add the WASI Preview 2 artifact(s) you actually need (see [Project Structure](#project-structure) above), e.g. for `wasi:http`: - -```xml - - io.github.stefanrichterhuber - wasmtimejavang-wasi-http - [Current Version] - -``` - -#### Function Imports - -You can import Java methods into the WebAssembly context, allowing WASM modules to invoke native Java code. - -```java -String wat = """ - (module - (func $hello (import "env" "hello")) - (func (export "run") (call $hello)) - ) - """; - -try ( - WasmtimeEngine engine = new WasmtimeEngine(); - WasmtimeModule module = new WasmtimeModule(engine, wat); - WasmtimeStore store = new WasmtimeStore(engine); - WasmtimeLinker linker = new WasmtimeLinker(engine, store) -) { - store.getContext().put("greeting", "Hello world"); - - // Define a Java function for the WASM module to call - linker.importFunction("env", "hello", List.of(), List.of(), (instance, params) -> { - System.out.println("Java side: " + instance.getContext().get("greeting")); - return new Object[] {}; - }); - - try (WasmtimeInstance instance = new WasmtimeInstance(store, module, linker)) { - instance.invoke("run"); - } -} -``` - -#### Supported WASM Types - -All type conversions are bi-directional if not mentioned otherwise. - -| Wasm type | Java type | Comment | -| :--- | :--- | :---: | -| **`I32`** | `java.lang.Integer` | Numbers are always boxed | -| **`I64`** | `java.lang.Long` | Numbers are always boxed | -| **`F32`** | `java.lang.Float` | Numbers are always boxed | -| **`F64`** | `java.lang.Double` | Numbers are always boxed | -| **`V128`** | `io.github.stefanrichterhuber.wasmtimejavang.V128` | V128 is a wrapper around `byte[16]`. Build in conversion from /to `byte[]`, `short[]`, `int[]`, `long[]` and `BigInteger` | -| **`FuncRef`** | `io.github.stefanrichterhuber.wasmtimejavang.WasmtimeFunction` | Callable function reference. Currently export from wasm to java supported | -| **`ExternRef`** | any java object | Any java object can be passed through the wasm runtime as extern ref | - -#### Memory Interaction - -The `WasmtimeMemory` class provides efficient access to the WASM linear memory by mapping it directly to a `java.nio.ByteBuffer`. - -```java -try (WasmtimeInstance instance = new WasmtimeInstance(store, module, linker)) { - WasmtimeMemory mem = instance.getMemory("memory"); - - // Read 4 bytes from offset 0x1000 - byte[] data = mem.read(0x1000, 4); - - // Write a single byte to offset 0x1003 - mem.write(0x1003, (byte) 5); - - // Higher level memory interactions. Usually one would call some kind of native alloc - // function to allocate memory locations prior to use - mem.writeCString(0x1000, "Hello", StandardCharsets.UTF_8); - assertEquals("Hello", mem.readCString(0x1000, StandardCharsets.UTF_8)); - - mem.writeString(0x1000, "World", StandardCharsets.UTF_8); - assertEquals("World", mem.readString(0x1000, "World".getBytes().length, StandardCharsets.UTF_8)); - - mem.writeLong(0x1000, Long.MAX_VALUE); - assertEquals(Long.MAX_VALUE, mem.readLong(0x1000)); - - mem.writeInt(0x1000, Integer.MAX_VALUE); - assertEquals(Integer.MAX_VALUE, mem.readInt(0x1000)); - - mem.writeShort(0x1000, Short.MAX_VALUE); - assertEquals(Short.MAX_VALUE, mem.readShort(0x1000)); - - mem.write(0x1000, Byte.MAX_VALUE); - assertEquals(Byte.MAX_VALUE, mem.readByte(0x1000)); - - // Grow to memory to have another page - mem.grow(1); -} -``` - -### WASI Snapshot Preview 1 - -While Wasmtime provides built-in WASI support, this library implements WASI Preview 1 directly on the Java side (`WasiPI1Context`). This approach reduces indirection and allows WASM modules to interact directly with Java objects, such as `InputStream`, `OutputStream`, and virtual filesystems. - -#### Virtualized Filesystem - -To protect the host system, you can use a virtual filesystem like [JimFS](https://github.com/google/jimfs) to provide a sandboxed environment for the WASM module. - -```java -try (FileSystem fs = Jimfs.newFileSystem(Configuration.unix())) { - Path root = fs.getPath("/"); - Files.writeString(root.resolve("input.txt"), "Data for WASM"); - - WasiPI1Context wasi = new WasiPI1Context() - .withDirectory(root, ".") // Map virtual root to WASM current directory - .withStdOut(System.out); - - linker.link(wasi); - - try (WasmtimeInstance instance = new WasmtimeInstance(store, module, linker)) { - instance.start(); - } -} -``` - -#### Supported WASI Functions - -| Category | Functions | Status | Configuration | -| :--- | :--- | :---: | :--- | -| **Arguments** | `args_get`, `args_sizes_get` | ✅ | `withArguments(List)` | -| **Environment** | `environ_get`, `environ_sizes_get` | ✅ | `withEnvs(Map)` | -| **Clocks** | `clock_res_get`, `clock_time_get` | ✅ | `withClock(Clock)` | -| **Random** | `random_get` | ✅ | `withRandom(Random)` | -| **Process** | `proc_exit` | ✅ | Throws `ProcExitException` | -| | `proc_raise` | 🟡 | Returns `NOSYS` (Stub) | -| **Scheduler** | `sched_yield` | ✅ | Calls `Thread.yield()` | -| **Filesystem** | Full FD and Path operations | ✅ | `withDirectory(Path, String)` | -| **Network** | `sock_accept`, `sock_recv`, `sock_send`, `sock_shutdown` | ✅ | `withSocket()`, `withServerSocket()` | -| **Polling** | `poll_oneoff` | 🟡 | Clock events supported | - -#### Configuration Options - -`WasiPI1Context` provides a fluent API for resource virtualization: - -* **Standard I/O**: `withStdIn(InputStream)`, `withStdOut(OutputStream)`, `withStdErr(OutputStream)`. -* **Filesystem**: `withDirectory(Path host, String client)` to map host/virtual paths. -* **Networking**: - * `withSocket(java.net.Socket)`: Pre-opens a client socket. - * `withServerSocket(java.net.ServerSocket)`: Pre-opens a listening socket. - -#### WASI threads - -There is some preliminary support for WASI threads using the additional context `WasiThreadContext`. - -```java - try (FileInputStream fis = new FileInputStream(wasmPath.toFile()); - WasmtimeEngine engine = new WasmtimeEngine(); - WasmtimeModule module = new WasmtimeModule(engine, fis); - WasmtimeStore store = new WasmtimeStore(engine); - WasmtimeLinker linker = new WasmtimeLinker(engine, store); - // A shared memory is necessary to share memory between threads - WasmtimeSharedMemory sharedMemory = new WasmtimeSharedMemory(engine, 2, 256)) { - - WasiPI1Context wasiContext = new WasiPI1Context() - .withArguments(List.of("wasip1threadtest")) - .withStdOut(System.out) - .withStdErr(System.err); - - WasiThreadContext threadContext = new WasiThreadContext(); - - linker.defineSharedMemory("env", "memory", sharedMemory); - linker.link(wasiContext); - linker.link(threadContext); - - try (WasmtimeInstance instance = new WasmtimeInstance(store, module, linker)) { - instance.start(); - } - - // Give some time for threads to finish and print - Thread.sleep(1000); -} - -``` - -> **Info:** As of now, nightly toolchain is required to properly build rust wasm wasip1 apps with thread support! - -### WASI Preview 2 / Component Model (`wasm32-wasip2`) - -Alongside core-module WASI Preview 1, this library supports the [Component Model](https://component-model.bytecodealliance.org/) (`wasm32-wasip2` binaries) — again with WASI implemented on the Java side rather than delegated to `wasmtime-wasi`. It's built from three pieces: - -* `WasmtimeComponent` — compiles a component, and can introspect it *without instantiating it*: `getImportInterfaces()` / `getExportInterfaces()` read the interfaces a component needs/exports straight from the compiled binary, and `isCommand()` reports whether it exports `wasi:cli/run` (i.e. is runnable as a command, as opposed to e.g. a service with no entry point). -* `WasmtimeComponentLinker` — resolves imports, mirroring `WasmtimeLinker` but for the richer Component Model value/resource model. -* `WasmtimeComponentInstance` — an instantiated component; exported functions are invoked dynamically by interface + function name via `invoke(...)`, or via the `asCliRunnable()` convenience for a `wasi:cli/run` command. - -```java -try ( - FileInputStream fis = new FileInputStream("hello.wasm"); - WasmtimeEngine engine = new WasmtimeEngine(); - WasmtimeComponent component = new WasmtimeComponent(engine, fis); - WasmtimeStore store = new WasmtimeStore(engine); - WasmtimeComponentLinker linker = new WasmtimeComponentLinker(engine, store) -) { - // Link an explicitly-configured context (captures stdout)... - ByteArrayOutputStream stdout = new ByteArrayOutputStream(); - linker.linkContext(new WasiCliContext().withStdOut(stdout).withArguments(List.of("hello"))); - - // ...then auto-link whatever else the component actually needs (wasi:clocks, - // wasi:random, ...), discovered straight off the compiled component. - linker.linkRequired(component); - - try (WasmtimeComponentInstance instance = new WasmtimeComponentInstance(store, component, linker)) { - instance.asCliRunnable().call(); // invokes wasi:cli/run#run - } -} -``` - -`linkRequired` only fills in interfaces nothing has already been linked for, so `linkContext(...)` calls made beforehand always take precedence — this is also the mechanism for overriding built-in behavior (see below). - -#### Supported WASI Preview 2 interfaces - -Each interface group lives in its own `WasmComponentContext` implementation under the `wasip2` package, each in its own Maven artifact, and all seven are auto-discovered by `linkRequired(...)` with zero configuration as long as their artifact is on the classpath — see [Project Structure](#project-structure). - -| Interfaces | Class | Artifact | Status | Configuration | -| :--- | :--- | :--- | :---: | :--- | -| `wasi:cli/environment,exit,stdin,stdout,stderr,terminal-*` | `WasiCliContext` | `wasmtimejavang-wasi-cli` | ✅ | `withEnvs(Map)`, `withArguments(List)`, `withStdIn/StdOut/StdErr(...)`. `terminal-*` always reports "not a tty" | -| `wasi:clocks/monotonic-clock,wall-clock` | `WasiClocksContext` | `wasmtimejavang-wasi-clocks` | ✅ | none (uses `System.nanoTime()`/`System.currentTimeMillis()`) | -| `wasi:random/random,insecure,insecure-seed` | `WasiRandomContext` | `wasmtimejavang-wasi-random` | ✅ | `withSecureRandom(Random)`, `withRandom(Random)` (the insecure generator) | -| `wasi:io/poll,streams,error` | `WasiIoContext` | `wasmtimejavang-wasi-io` | ✅ | Owns the shared stream/pollable tables other contexts (`WasiCliContext`, `WasiClocksContext`, `WasiFilesystemContext`, `WasiSocketsContext`, `WasiHttpContext`) depend on. Both blocking and non-blocking reads/skips are implemented (`[method]input-stream.{blocking-,}read`/`{blocking-,}skip`, the batch `poll` function, `[method]pollable.ready`) | -| `wasi:filesystem/types,preopens` | `WasiFilesystemContext` | `wasmtimejavang-wasi-filesystem` | ✅ | `withDirectory(Path host, String client)` (repeatable). No symlink support by design: `symlink-at`/`readlink-at` report `unsupported`, and `path-flags.symlink-follow` is ignored — host paths always resolve following symlinks | -| `wasi:sockets/network,instance-network,tcp(-create-socket),udp(-create-socket),ip-name-lookup` | `WasiSocketsContext` | `wasmtimejavang-wasi-sockets` | ✅ | None — a guest creates/binds/connects/listens its own sockets, same as on a real host. IPv4 only (`ipv6` rejected as `not-supported`, `[method]{tcp,udp}-socket.address-family` always reports `ipv4`). Some options `java.net` has no equivalent for (TCP `hop-limit`, TCP keep-alive idle-time/interval/count, UDP `unicast-hop-limit`) are stored and returned as configured but not actually applied to the OS socket | -| `wasi:http/types,outgoing-handler` | `WasiHttpContext` | `wasmtimejavang-wasi-http` | 🟡 | None — a guest makes outgoing HTTP calls (`fetch()`-style) via a real, blocking `java.net.http.HttpClient` call. `request-options#between-bytes-timeout` has no `HttpClient` equivalent (stored but not applied). `wasi:http/incoming-handler` (a guest *exporting* a request handler, for reverse-proxy-style hosting) isn't implemented yet | - -`WasiFilesystemContext` mirrors WASI Preview 1's filesystem support (`WasiPI1Context` + `withDirectory`): preopened host directories are exposed as `descriptor` resources sandboxed the same way -- a guest path can never resolve outside its preopened directory, no matter how many `..` segments it contains. Reads/writes go through `wasi:io/streams` the same way `wasi:cli/stdout` does: `[method]descriptor.read-via-stream`/`write-via-stream`/`append-via-stream` hand out `input-stream`/`output-stream` resources from the shared `wasi-io` table (so it depends on `"wasi-io"` the same way `WasiCliContext` and `WasiClocksContext` do), rather than reading/writing bytes directly. - -```java -try (FileSystem fs = Jimfs.newFileSystem(Configuration.unix().toBuilder() - .setAttributeViews("basic", "owner", "posix", "unix").build())) { - Path root = fs.getPath("/"); - Files.writeString(root.resolve("input.txt"), "Data for WASM"); - - linker.linkContext(new WasiCliContext().withStdOut(System.out)); - linker.linkContext(new WasiFilesystemContext().withDirectory(root, ".")); // preopen "." -> root - linker.linkRequired(component); - - try (WasmtimeComponentInstance instance = new WasmtimeComponentInstance(store, component, linker)) { - instance.asCliRunnable().call(); - } -} -``` - -Unlike `WasiFilesystemContext`, `WasiSocketsContext` needs no configuration at all: WASI Preview 2 gives a guest full control over its own sockets (create, bind, connect/listen, accept, send/receive), so there's no host-side preopen step to wire up -- linking it is enough, and a guest creating a TCP or UDP socket behaves exactly as it would talking to a real OS network stack (loopback and outbound connections both work). The two-phase `start-x`/`finish-x` operations WASI defines for non-blocking bind/connect/listen are collapsed into one blocking `java.net` call apiece internally, since every host call in this bridge is already synchronous from the guest's perspective. - -```java -linker.linkContext(new WasiCliContext().withStdOut(System.out)); -linker.linkContext(new WasiSocketsContext()); -linker.linkRequired(component); // pulls in wasi-io, wasi-clocks, etc. as needed -``` - -`WasiHttpContext` likewise needs no configuration: `wasi:http/outgoing-handler` lets a guest make outbound HTTP requests, and every call is dispatched via a real `java.net.http.HttpClient`, synchronously, since (as with `WasiSocketsContext`'s two-phase operations) every host call in this bridge is already synchronous from the guest's perspective — there's no genuine asynchrony to preserve, so `future-incoming-response`/`future-trailers` are always already resolved by the time the guest polls them. `wasi:http` isn't part of `wasm32-wasip2`'s built-in WASI componentization the way `wasi:cli`/`wasi:clocks`/`wasi:sockets` are, so a guest needs `wit_bindgen::generate!` against the `wasi:http` WIT package to consume it (see [Implementing your own component context](#implementing-your-own-component-context) below for the general mechanism). - -```java -linker.linkContext(new WasiCliContext().withStdOut(System.out)); -linker.linkContext(new WasiHttpContext()); -linker.linkRequired(component); // pulls in wasi-io, wasi-clocks, wasi-random -``` - -#### Implementing your own component context - -This is the mechanism that matters most for actually using this library: WASI is just the *built-in* set of `WasmComponentContext` implementations, and any Java application can define its own to expose custom host functionality — database access, business logic, whatever — to a component's imports, the exact same way. There are two ways to implement one: hand-write it directly against `WasmComponentContext` (full control, shown first below), or generate a typed interface from a WIT file via `wit-codegen-maven-plugin` and implement just the typed methods (less boilerplate — no manual version-string wiring or `Object[]` casts). Both are shown below using the same example (its full source is in the repo and covered by `WasmtimeCustomComponentTest`, so it's guaranteed to stay in sync with the code, not just aspirational documentation). - -**1. Define the interface in WIT.** This is the contract the guest and the host agree on — a Java-side `WasmComponentContext` needs no WIT file itself (it's built against the fully dynamic `component::Val` API), but the *component being compiled* does, since Rust needs it to generate typed bindings. [`wasmtimejavang-wasi-cli/src/test/rust/wasip2customtest/wit/world.wit`](wasmtimejavang-wasi-cli/src/test/rust/wasip2customtest/wit/world.wit): - -```wit -package my:custom@1.0.0; - -interface greet { - hello: func(name: string) -> string; - add: func(a: u32, b: u32) -> u32; -} - -world custom-world { - import greet; -} -``` - -**2. Consume it from the guest.** Any language with Component Model tooling works; the test fixture is Rust using [`wit-bindgen`](https://github.com/bytecodealliance/wit-bindgen) (one of two test fixtures in this repo that need it, alongside `wasi:http`'s — every WASI-only fixture otherwise relies solely on `wasm32-wasip2`'s built-in componentization). [`wasmtimejavang-wasi-cli/src/test/rust/wasip2customtest/src/main.rs`](wasmtimejavang-wasi-cli/src/test/rust/wasip2customtest/src/main.rs): - -```rust -wit_bindgen::generate!({ - world: "custom-world", - path: "wit", -}); - -use my::custom::greet; - -fn main() { - let greeting = greet::hello("Wasmtime-Java"); - println!("GREETING={}", greeting); - - let sum = greet::add(19, 23); - println!("SUM={}", sum); -} -``` - -**3. Implement it in Java.** Two ways — hand-write it directly against `WasmComponentContext`, or generate a typed interface from the same WIT file and implement that instead. - -**Hand-written**, to provide `hello`/`add` directly. [`GreetComponentContext`](wasmtimejavang-wasi-cli/src/test/java/io/github/stefanrichterhuber/wasmtimejavang/GreetComponentContext.java): - -```java -public class GreetComponentContext implements WasmComponentContext { - private static final String INTERFACE = "my:custom/greet"; - - private SemanticVersion version = new SemanticVersion(1, 0, 0); - - @Override - public String name() { return "greet"; } // stable id, referenced by getDependencies() - - @Override - public List getImportFunctions() { - String versioned = INTERFACE + "@" + version; - return List.of( - new ComponentImportFunction(versioned, "hello", this::hello), - new ComponentImportFunction(versioned, "add", this::add)); - } - - @Override - public List getImportResources() { return List.of(); } - - @Override - public Set getProvidedInterfaces() { return Set.of(INTERFACE); } // see "Auto-discovery" below - - private Object[] hello(WasmtimeComponentInstance instance, Object... args) { - return new Object[] { "Hello, " + (String) args[0] + "!" }; - } - - private Object[] add(WasmtimeComponentInstance instance, Object... args) { - return new Object[] { (Integer) args[0] + (Integer) args[1] }; - } +`verify` boots BIOS → OS → child, then repeats the run with capture → restore into a fresh machine at every tick boundary and checks that the logs are identical. - @Override - public WasmComponentContext withVersion(SemanticVersion version) { this.version = version; return this; } +Java bindings on Windows (requires JDK 21, Maven and Rust; no Docker): - @Override - public SemanticVersion getVersion() { return version; } -} -``` - -Argument/return types follow the value bridge described above — here just `String` and `Integer` (WIT `u32`), but the same context could just as well take/return a `Map` (`record`), `List`/`Object[]` (`list`/`tuple`), `byte[]` (`list`), or a resource. - -**Or generated**, via `wit-codegen-maven-plugin`'s `generate-wit-sources` goal (bound to `generate-sources` by default). Add the plugin to your `pom.xml`, pointing `witSourceDirectory` at a directory containing the same `greet.wit` from step 1 (every `.wit` file directly in it is generated from independently): - -```xml - - io.github.stefanrichterhuber - wit-codegen-maven-plugin - [Current Version] - - - - generate-wit-sources - - - ${project.basedir}/src/main/wit - com.example.generated - - - - -``` - -This generates `com.example.generated.GreetContext` — an **interface**, not an abstract class (so a class can implement several generated interfaces at once — see "Combining interfaces" below), extending `WasmComponentContext` with `getImportFunctions()`/`getImportResources()`/`getProvidedInterfaces()`/`name()` already wired as `default` methods and one typed abstract method per WIT function (see [`WitCodeGenerator`](wit-codegen-maven-plugin/src/main/java/jp/akkiserver/shuttle/wit/codegen/WitCodeGenerator.java) for the full WIT-to-Java type mapping). Implement it directly instead of hand-rolling `WasmComponentContext`: - -```java -public class MyGreetContext implements com.example.generated.GreetContext { - @Override - public String hello(WasmtimeComponentInstance instance, String name) { - return "Hello, " + name + "!"; - } - - @Override - public int add(WasmtimeComponentInstance instance, int a, int b) { - return a + b; - } -} -``` - -To generate from a real, multi-file WIT **world** instead of one interface (a package directory, optionally with a `deps/` subfolder) — e.g. to regenerate the scaffolding this project's own `Wasi*Context` classes are built on — configure `worldSourceDirectory` + `worldName` instead of (or alongside) `witSourceDirectory`: - -```xml - - ${project.basedir}/src/main/wit/wasi-cli/wit - command - com.example.generated.wasicli - -``` - -This generates one interface per interface the world's imports flatten to (27 for `wasi:cli`'s `command` world). Exports are intentionally not modeled — `WasmComponentContext` only represents host-provided imports; call an export dynamically via `WasmtimeComponentInstance.invoke(...)` instead. - -**Combining interfaces.** Implementing several generated interfaces on one class (useful when they share state, e.g. two interfaces that both hand out a resource type minted by a shared table — this is exactly what every built-in `Wasi*Context` does) requires overriding `getImportFunctions()`/`getImportResources()`/`getProvidedInterfaces()` to combine each interface's own `default` implementation — Java requires this override whenever two implemented interfaces disagree on a `default` method's body, which any two distinct generated interfaces always do: - -```java -public class MyBundledContext implements FooContext, BarContext { - @Override - public List getImportFunctions() { - List result = new ArrayList<>(); - result.addAll(FooContext.super.getImportFunctions()); - result.addAll(BarContext.super.getImportFunctions()); - return result; - } - // ...same pattern for getImportResources()/getProvidedInterfaces(); withVersion()/getVersion() - // stay this class's own responsibility (a plain field) since interfaces can't hold state. -} -``` - -**Note:** the plugin can't be wired into `wasmtimejavang` (the core artifact) itself this way — that would be a circular module dependency within this repository's reactor, since the plugin's own tests depend on core. Every one of this repository's own WASI Preview 2 artifacts (`wasmtimejavang-wasi-io`, `-wasi-clocks`, `-wasi-random`, `-wasi-cli`, `-wasi-filesystem`, `-wasi-sockets`, `-wasi-http`) demonstrates the pattern instead: a *separate* artifact depending on core, using the plugin as a normal `generate-sources` build step (see e.g. [`wasmtimejavang-wasi-http/pom.xml`](wasmtimejavang-wasi-http/pom.xml)). Your own project, depending on any of these artifacts as an ordinary library, never has this constraint. `wit-parser`, a JNI binding around the [`wit-parser`](https://crates.io/crates/wit-parser) Rust crate, handles the actual WIT parsing behind the plugin. - -**4. Link it and run.** (identical either way — only the implementing class differs). [`WasmtimeCustomComponentTest`](wasmtimejavang-wasi-cli/src/test/java/io/github/stefanrichterhuber/wasmtimejavang/WasmtimeCustomComponentTest.java): - -```java -try (FileInputStream fis = new FileInputStream(wasmPath); - WasmtimeEngine engine = new WasmtimeEngine(); - WasmtimeComponent component = new WasmtimeComponent(engine, fis); - WasmtimeStore store = new WasmtimeStore(engine); - WasmtimeComponentLinker linker = new WasmtimeComponentLinker(engine, store)) { - - linker.linkContext(new WasiCliContext().withStdOut(System.out)); - linker.linkContext(new GreetComponentContext()); - linker.linkRequired(component); // pulls in wasi-io for stdout; nothing to do for "my:custom/greet" - - try (WasmtimeComponentInstance instance = new WasmtimeComponentInstance(store, component, linker)) { - instance.asCliRunnable().call(); // prints "GREETING=Hello, Wasmtime-Java!" / "SUM=42" - } -} -``` - -`linker.linkContext(...)` links a context explicitly and unconditionally; `linkRequired(component)` only fills in interfaces *nothing has already claimed* (see above), so the two compose freely — explicit calls always take precedence. - -**Depending on another context.** To share state with another context (e.g. `WasiIoContext`'s stream table), declare it by bare name in `getDependencies()` and resolve it in `onDependenciesResolved(ComponentContextLookup)` — `WasmtimeComponentLinker` links declared dependencies first and guarantees they're available by the time it's called: - -```java -@Override -public List getDependencies() { return List.of(WasiIoContext.NAME); } - -@Override -public void onDependenciesResolved(ComponentContextLookup lookup) { - this.io = (WasiIoResources) lookup.resolve(WasiIoContext.NAME, getVersion()).orElseThrow(); -} -``` - -**Auto-discovery.** To make a context discoverable by `linkRequired(component)` instead of linking it explicitly, declare the (bare, version-independent) interface names it implements via `getProvidedInterfaces()` (as `GreetComponentContext` already does above — a generated interface has this pre-wired as a `default` method already, so a generated-based implementer gets it for free) and register the class as a `WasmComponentContext` [`ServiceLoader`](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/ServiceLoader.html) provider (a `META-INF/services/io.github.stefanrichterhuber.wasmtimejavang.WasmComponentContext` file listing the class, which needs a public no-arg constructor or a public static `provider()` method) — this is exactly how the seven built-in `Wasi*Context` classes register themselves. - -**Watch out:** `getProvidedInterfaces()` must be overridden (or, for a generated interface, already resolve correctly) even for a context that's *always* linked explicitly via `linkContext(...)` and never registered for `ServiceLoader` discovery — if that same call site also calls `linkRequired(...)` afterwards (as step 4 does), `linkRequired` has no other way to know the explicitly-linked context already satisfies the interface, and raises `IllegalStateException` for it. This is why the hand-written `GreetComponentContext` overrides `getProvidedInterfaces()` above even though it's never meant to be auto-discovered. - -#### Overriding a built-in WASI Preview 2 context - -None of the `Wasi*Context` classes are `final`, and the built-ins are only ever *auto-linked* — never forced — so there are two ways to override one: - -1. **Per-linker, explicit**: call `linker.linkContext(...)` with your own instance (a subclass, or an unrelated implementation) using the *same* `name()` (e.g. `"wasi-cli"`) before calling `linkRequired(...)`. Since `linkRequired` only auto-links interfaces nothing has claimed yet, your explicitly-linked context wins and the built-in provider is never consulted. -2. **Global, via lookup strategy**: register your own `ComponentContextLookup` (e.g. a `RegistryComponentContextLookup` populated with your preferred instances, or a custom implementation) as a `META-INF/services/io.github.stefanrichterhuber.wasmtimejavang.ComponentContextLookup` provider. `WasmtimeComponentLinker` resolves its dependency-lookup strategy the same SPI way, falling back to `ServiceLoaderComponentContextLookup` (which is what discovers the built-ins) only if nothing else is registered — so this replaces resolution for every linker in the process, not just one. - -Each `Wasi*Context` implements one small, generated **interface per WIT interface** it covers (e.g. `WasiSocketsContext implements NetworkContext, InstanceNetworkContext, TcpCreateSocketContext, TcpContext, UdpCreateSocketContext, UdpContext, IpNameLookupContext`), with every WIT function as a plain typed method — so overriding one function's behavior in a subclass needs nothing beyond overriding that one method: - -```java -public class Ipv6TcpSocketsContext extends WasiSocketsContext { - @Override - public WitEnum tcpSocketAddressFamily(WasmtimeComponentInstance instance, WitResource self) { - return new WitEnum("ipv6"); // the built-in implementation is IPv4-only - } -} +```powershell +mvn -P build-host-windows-x86_64 -pl shuttle-java,shuttle-java-example -am install +mvn -pl shuttle-java-example exec:java ``` -These generated interfaces are regular public types shipped in the jar, under `io.github.stefanrichterhuber.wasmtimejavang.wasip2.generated.wasicli` — see [Implementing your own component context](#implementing-your-own-component-context) above for how they're produced and how to generate your own from a custom WIT interface. - -#### Version negotiation - -Every `WasmComponentContext` tracks a `SemanticVersion` (`withVersion`/`getVersion`), used to build the actual versioned interface name (e.g. `"wasi:cli/environment@0.2.6"`) each import is registered under — `getProvidedInterfaces()` itself stays version-independent (bare names), so lookup/auto-discovery doesn't need to know a component's exact required version up front. `getMiniumVersion()`/`getMaximumVersion()` (defaulted to accept anything) bound what `supportsVersion(...)` — and therefore `ComponentContextLookup.resolve(...)` — accepts; the built-in WASI contexts default to `0.2.6` (what `cargo build --target wasm32-wasip2` on current stable Rust actually emits) and accept `[0.0.1, 0.3.0]`, so they're ready for the eventual WASI 0.3 interfaces without code changes once toolchains catch up, but can be pinned with `.withVersion(...)` if a component needs something else within that range. `WasiHttpContext` is the one exception, defaulting to `0.2.8` and accepting `[0.2.0, 0.3.0]` — `wasi:http` isn't part of what the stable target emits automatically, so there's no single "current" version to match; `0.2.8` is simply what this project's own `wasi-http` WIT sources declare. - -### Architecture +The second command runs the Weave example. Linux builds, the other Maven profiles, CI and known problems are covered in [docs/building.md](docs/building.md). -`wasmtimejavang` (the core artifact — see [Project Structure](#project-structure) above for the other modules) is structured into three distinct layers: +## Documentation -1. **Java API**: A type-safe wrapper that represents Wasmtime concepts (Engine, Module, Store, Instance) in Java. It uses `jar-jni` for automatic native library loading. Log4j2 is used as logging framework. All called external functions (wasm32-wasip1) or components (wasm32-wasip2) are written in Java with a configurable dependency injection so that any function could be modified or rewritten by a java developer without knowledge about wasm. -2. **JNI Layer (Rust)**: Built using the [jni-rs](https://crates.io/crates/jni) crate. It manages the lifecycle of native Wasmtime objects and facilitates data exchange between the JVM and Rust. This layer also redirects Rust `log` crate output to Java's Log4j2. "Classic" Java JNI was preferred over the newer "Foreign Function and Memory API", due to the native library is only planned to be used with Java so it could be tailored to its use. This allows more direct Rust - Java interactions like easily calling Java methods on objects or even create new Java objects using their constructor. A "Foreign Function an Memory API" approach would have resulted in a thinner native layer with far higher implementation effort on the Java side for all the type conversion, especially sacrificing the type and lifetime safety the current rust layer provides for the runtime. -3. **Wasmtime Core**: The underlying [wasmtime](https://crates.io/crates/wasmtime) Rust crate. +- [docs/building.md](docs/building.md): building the native core and the Maven modules, CI, requirements, known issues +- [docs/java-binding.md](docs/java-binding.md): the `shuttle-java` API (Wasmtime and Weave) and its architecture +- [docs/wit-codegen.md](docs/wit-codegen.md): generating Java component contexts from WIT +- [native/README.md](native/README.md): the native core prototype, its results and its ABI coverage -All modules are tested using JUnit. Test coverage is measured with Jacoco. The neccessary wasm modules for testing are build with rust (see each module's own `src/test/rust`, where present). Using `exec-maven-plugin` these wasm modules are build in the `generate-test-resources` phase. - -### Breaking changes - -* **Version 6.x.x**: Splitting the project into separate modules — three at first (`wasmtimejavang`, `wit-parser`, `wit-codegen-maven-plugin`), now further split so every WASI Preview 2 world ships as its own artifact depending on a `wasmtimejavang` core (`wasmtimejavang-wasi-{io,clocks,random,cli,filesystem,sockets,http}` — see [Project Structure](#project-structure)); Introduction of the wit-parser to automatically generate bindings for wasm32-wasip2; No changes for wasm32-wasip1 support -* **Version 5.x.x**: Introduction of wasm32-wasip2 support; No changes for wasm32-wasip1 support -* **Version 4.x.x**: Changed signature of Wasmfunction +## Credits and license -### Comparison to Previous Work +The Java Wasmtime bindings in this repository are a fork of [StefanRichterHuber/wasmtime-ng](https://github.com/StefanRichterHuber/wasmtime-ng) (MIT, © 2024 Stefan Richter-Huber). See [LICENSE](LICENSE). Upstream names these earlier Java bindings as prior work: [bluejekyll/wasmtime-java](https://github.com/bluejekyll/wasmtime-java) and [kawamuray/wasmtime-java](https://github.com/kawamuray/wasmtime-java). -This implementation aims to be more maintainable and feature-complete than earlier attempts: +> **Disclaimer:** This project is an independent community effort and is not affiliated with, maintained, or endorsed by the [Wasmtime project](https://github.com/bytecodealliance/wasmtime), the Bytecode Alliance, Mojang or Microsoft. -* [bluejekyll/wasmtime-java](https://github.com/bluejekyll/wasmtime-java) -* [kawamuray/wasmtime-java](https://github.com/kawamuray/wasmtime-java) +> **AI Disclaimer:** Parts of this project were vibe-coded or written with the help of an AI assistant (Claude); the remaining parts were written by hand. diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..6aa1c89 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,10 @@ +# Shuttle documentation + +| Document | Contents | +| --- | --- | +| [building.md](building.md) | Requirements; building the native core (`native/scripts/build.ps1`, `build.sh`, what `verify` checks); building the Maven modules and their profiles; CI workflows; known issues. | +| [java-binding.md](java-binding.md) | The `shuttle-java` module: Wasmtime API (engine, module, store, linker, instance, memory, functions), value types, Component Model support, the Weave JNI layer for checkpointable guests, and the architecture (Java API / JNI layer in Rust / Wasmtime). | +| [wit-codegen.md](wit-codegen.md) | `shuttle-wit-parser` and `shuttle-wit-maven-plugin`: generating Java component-context interfaces from WIT files. | +| [../native/README.md](../native/README.md) | The native core prototype (`shuttle-core`, `shuttle-runner`, C guests): layout, build, test results, and which parts of the firmware ABI draft are implemented. | + +Back to the [project README](../README.md). diff --git a/docs/building.md b/docs/building.md new file mode 100644 index 0000000..710d10d --- /dev/null +++ b/docs/building.md @@ -0,0 +1,146 @@ +# Building + +The repository has two independent builds: + +- **`native/`**: a Cargo workspace (the Shuttle native core). Built with the scripts in `native/scripts/`. +- **The Maven reactor** (root `pom.xml`): `shuttle-java`, `shuttle-java-example`, `shuttle-wit-parser`, `shuttle-wit-maven-plugin`. Maven also drives the Rust builds of the two JNI libraries inside `shuttle-java` and `shuttle-wit-parser`. + +Neither build depends on the other. + +## Requirements + +| Tool | Needed for | +| --- | --- | +| Rust via [rustup](https://rustup.rs) (stable) | everything | +| clang + wasm-ld | the C guests in `native/guests`. Windows: the [LLVM installer](https://github.com/llvm/llvm-project/releases). Linux/WSL2: `sudo apt install clang lld` | +| JDK 21 and Maven | the Maven reactor (`maven.compiler.release` is 21) | +| Rust target `wasm32-unknown-unknown` | the `shuttle-java` tests (the `valuetest` fixture is built for it): `rustup target add wasm32-unknown-unknown` | +| [cross](https://github.com/cross-rs/cross) + Docker | only the Maven profiles that cross-compile (see below), and `build.sh --cross` | + +## Native core (`native/`) + +The scripts build the three C guests (`bios`, `os`, `child`) into freestanding wasm32 modules under `native/guests/out/`, run `cargo build --locked`, and then run `shuttle-runner verify`. + +Windows (PowerShell): + +```powershell +.\native\scripts\build.ps1 # dev build + verify +.\native\scripts\build.ps1 -Release # release build + verify +.\native\scripts\build.ps1 -SkipVerify # build only +``` + +If `clang` is not on `PATH`, `build.ps1` adds `%ProgramFiles%\LLVM\bin`, because the LLVM installer does not always do this. + +Linux / WSL2: + +```sh +./native/scripts/build.sh # dev build + verify +./native/scripts/build.sh --release # release build + verify +./native/scripts/build.sh --cross aarch64 # Linux arm64 via cross (build only, no verify) +./native/scripts/build.sh --skip-verify # build only +``` + +By hand, inside `native/`: + +```sh +sh guests/build.sh +cargo build +./target/debug/shuttle-runner run guests/out/bios.wasm guests/out/os.wasm guests/out/child.wasm +./target/debug/shuttle-runner verify guests/out/bios.wasm guests/out/os.wasm guests/out/child.wasm +``` + +### What `verify` checks + +`run` boots BIOS → `exec` → OS → `co_create` → child and prints the log until power-off. + +`verify` does the following: + +1. Runs the machine once without interruption and records the log. +2. For every tick boundary *N*, runs again, captures a snapshot at tick *N*, restores it into a brand-new machine, continues to power-off, and compares the log with step 1. All must be identical. +3. A control run drops the host-side child table on restore. That run must diverge, which shows that the comparison actually detects lost state. + +The results of the last measured run are in [native/README.md](../native/README.md#results-2026-10-15-linux-x86_64-2-cores-dev-profile). + +## Maven reactor + +### Profiles + +The native library of `shuttle-java` (`wasmtime-binding`, built as `wasmtimebinding`) is compiled during the `compile` phase by a profile, and copied into the jar under `jp/akkiserver/shuttle/libs//`, where [jar-jni](https://github.com/questdb/jar-jni) finds it at runtime. Profiles defined in [`shuttle-java/pom.xml`](../shuttle-java/pom.xml): + +| Profile | Rust target | Built with | Jar folder | +| --- | --- | --- | --- | +| `build-linux-x86-64` (**active by default**) | `x86_64-unknown-linux-gnu` | `cross` (Docker) | `linux-x86-64` | +| `build-linux-aarch64` | `aarch64-unknown-linux-gnu` | `cross` (Docker) | `linux-aarch64` | +| `build-windows-x86_64` | `x86_64-pc-windows-msvc` | `cross` (Docker) | `win32-x86-64` | +| `build-windows-aarch64` | `aarch64-pc-windows-msvc` | `cross` (Docker) | `win32-aarch64` | +| `build-host-windows-x86_64` | `x86_64-pc-windows-msvc` | local `cargo` (no Docker) | `win32-x86-64` | + +There is no macOS profile yet, so `shuttle-java` cannot currently be packaged with a macOS library. + +Maven turns off an `activeByDefault` profile as soon as another profile of the same POM is selected with `-P`. So `-P build-host-windows-x86_64` builds only the Windows library and does not call `cross`. + +Profiles defined in the root [`pom.xml`](../pom.xml): + +| Profile | Effect | +| --- | --- | +| `release` (also activated by `-DperformRelease=true`) | Sets the Cargo profile to `release`, and adds GPG signing, source and javadoc jars, and the release plugin. GPG signing runs in the `verify` phase, so `install` with this profile needs a configured GPG key. | +| `spotbugs` | Runs SpotBugs with FindSecBugs in the `test` phase (`spotbugs.failOnError` is `false`). | + +To get optimized Rust libraries without the release-publishing steps, set the two Cargo properties directly, as CI does: + +```sh +mvn -Dcargo.profile=release -Dcargo.profile.folder=release install +``` + +### Commands + +Windows, local cargo only: + +```powershell +# shuttle-java and the example (with shuttle-java's tests) +mvn -P build-host-windows-x86_64 -pl shuttle-java,shuttle-java-example -am install + +# the whole reactor, skipping tests (see Known issues for why) +mvn -P build-host-windows-x86_64 -DskipTests install +``` + +Linux, default profile (needs `cross` and a running Docker): + +```sh +mvn install +``` + +Several platforms in one jar: + +```sh +mvn -P build-linux-x86-64,build-linux-aarch64,build-windows-x86_64 install +``` + +Run the Weave example (after `shuttle-java` is installed in the local repository): + +```sh +mvn -pl shuttle-java-example exec:java +``` + +### `shuttle-wit-parser` + +`shuttle-wit-parser` always builds its JNI library (`witparserbinding`) with a plain host `cargo build`, without `cross` or a profile, because it only runs on the build machine while the WIT plugin is generating sources. + +### Tests + +- `shuttle-java`: JUnit 5 tests (`WeaveTest`, `WasmtimeValueTest`, `WasmtimeComponentTest`, `WasmtimeMemoryTest`, ...). In `generate-test-resources`, `exec-maven-plugin` builds the Rust fixture `src/test/rust/valuetest` for `wasm32-unknown-unknown` into `target/rust-test/valuetest`. The other fixtures are inline WAT or inline Wasm bytes. +- `shuttle-wit-parser` and `shuttle-wit-maven-plugin`: parse the WIT files under `src/test/resources/wit` (`greet.wit`, `wasi-cli`, `wasi-sockets`) and compile the generated sources. +- Coverage is recorded with JaCoCo (`prepare-agent`, report in `prepare-package`). + +## CI + +| Workflow | Trigger | What it does | +| --- | --- | --- | +| [`native.yml`](../.github/workflows/native.yml) "Native (Shuttle)" | push to `main` or PR touching `native/**` or the workflow; manual dispatch | Builds the C guests once on Ubuntu and uploads them as an artifact. Then, on Linux, Windows and macOS (x86_64 and arm64 each, six jobs): `cargo build --locked --release` and `shuttle-runner verify`. | +| [`maven.yml`](../.github/workflows/maven.yml) "Java CI with Maven" | push or PR to `main` | Ubuntu, JDK 21 (Temurin): installs `cross`, then runs `mvn -P build-linux-x86-64,build-linux-aarch64,build-windows-x86_64 -Dcargo.profile=release -Dcargo.profile.folder=release -B package`. | + +## Known issues + +- **`shuttle-wit-parser` tests fail on Windows.** Its `pom.xml` only copies the Linux x86_64 library (`*.so` into `jp/akkiserver/shuttle/wit/parser/libs/linux-x86-64`). On Windows the DLL is built but never copied into the jar folder, so loading fails with `cannot find .../win32-x86-64/witparserbinding.dll`. The `shuttle-wit-maven-plugin` tests use the parser too. On Windows, skip tests for these modules (`-DskipTests`) or build only `shuttle-java` (`-pl shuttle-java -am`). +- **"Java CI with Maven" is failing**, also on `main`. The cause has not been investigated yet. Possible factors: the workflow installs `wasm32-wasip1`/`wasm32-wasip2` targets (left over from the removed WASI modules) but not `wasm32-unknown-unknown`, which the `valuetest` fixture needs, and it cross-compiles `x86_64-pc-windows-msvc` with `cross`. +- **No macOS Maven profile.** `native/` builds on macOS in CI, but `shuttle-java` has no profile that builds or packages a macOS library. diff --git a/docs/java-binding.md b/docs/java-binding.md new file mode 100644 index 0000000..7b244ad --- /dev/null +++ b/docs/java-binding.md @@ -0,0 +1,292 @@ +# Java binding (`shuttle-java`) + +`shuttle-java` is the Java side of Shuttle that a host mod calls. It has two parts: + +1. **Wasmtime bindings** (inherited from the upstream wasmtime-ng project): engine, modules, stores, linkers, instances, linear memory, host functions, and the Component Model. +2. **The Weave layer**: load a core Wasm module in *woven* (checkpointable) form, run it in slices, snapshot it into a byte array, and restore it later, possibly in another JVM. + +All classes are in the package `jp.akkiserver.shuttle` (WIT value wrappers are in `jp.akkiserver.shuttle.component`). The native code is one Rust library, `wasmtimebinding` (source: [`shuttle-java/src/main/rust/wasmtime-binding`](../shuttle-java/src/main/rust/wasmtime-binding)). It is packaged inside the jar and loaded automatically. + +How to build the jar, including which native platforms end up inside it, is described in [building.md](building.md). + +## Dependency + +The project is not published to a Maven repository yet. Install it locally (see [building.md](building.md)) and depend on: + +```xml + + jp.akkiserver + shuttle-java + 6.0.1-SNAPSHOT + +``` + +Runtime dependencies: `org.questdb:jar-jni` (loads the native library) and `log4j-api`. Native log output from Rust is forwarded to Log4j2. A Log4j2 implementation is not included; inside Minecraft the game's own Log4j2 is used. + +## Wasmtime API + +| Class | Role | +| --- | --- | +| `WasmtimeEngine` | Wasmtime engine. Shared and reused across modules. `precompile(...)` produces a precompiled (`.cwasm`) image. | +| `WasmtimeModule` | Compiled core module. Constructors take a WAT `String`, `byte[]`, `ByteBuffer` or `InputStream` (binary or text). `fromPrecompiled(...)` loads a `.cwasm` image. | +| `WasmtimeStore` | Wasmtime store. Holds a user context `Map` (`getContext()`), reachable from host functions through the instance. | +| `WasmtimeLinker` | Defines imports: `linkFunction(...)`, `linkContext(WasmContext)`, `linkMemory(...)`. (`importFunction`, `link` and `defineSharedMemory` are deprecated aliases.) | +| `WasmtimeInstance` | Instantiated module: `invoke(name, args...)`, `start()` (calls `_start`), `getFunction(name)`, `getMemory(name)`. | +| `WasmtimeMemory` | Linear memory view over a `java.nio.ByteBuffer` (implemented by `WasmtimeLocalMemory` and `WasmtimeSharedMemory`). | +| `WasmtimeFunction` | Functional interface `Object[] call(WasmtimeInstance instance, Object... args)` used for host functions and for exported function references. | +| `WasmContext` | A reusable bundle of import functions (`ImportFunction`) and shared memories (`Importmemory`) for `linkContext`. | + +All native-backed classes implement `AutoCloseable`. Use try-with-resources. + +### Host functions + +A host function is a Java method that a Wasm module imports: + +```java +import java.util.List; +import jp.akkiserver.shuttle.*; + +String wat = """ + (module + (func $hello (import "env" "hello")) + (func (export "run") (call $hello)) + ) + """; + +try ( + WasmtimeEngine engine = new WasmtimeEngine(); + WasmtimeModule module = new WasmtimeModule(engine, wat); + WasmtimeStore store = new WasmtimeStore(engine); + WasmtimeLinker linker = new WasmtimeLinker(engine, store) +) { + store.getContext().put("greeting", "Hello world"); + + // env.hello: no parameters, no results + linker.linkFunction("env", "hello", List.of(), List.of(), (instance, params) -> { + System.out.println("Java side: " + instance.getContext().get("greeting")); + return new Object[] {}; + }); + + try (WasmtimeInstance instance = new WasmtimeInstance(store, module, linker)) { + instance.invoke("run"); // prints "Java side: Hello world" + } +} +``` + +Parameter and result types are given as `ValType` values: `I32`, `I64`, `F32`, `F64`, `V128`, `Ref` (externref). + +### Supported value types + +Conversions work in both directions unless noted otherwise. + +| Wasm type | Java type | Notes | +| :--- | :--- | :--- | +| `i32` | `java.lang.Integer` | Numbers are always boxed. | +| `i64` | `java.lang.Long` | | +| `f32` | `java.lang.Float` | | +| `f64` | `java.lang.Double` | | +| `v128` | `jp.akkiserver.shuttle.V128` | Wrapper around `byte[16]`, with conversions from and to `byte[]`, `short[]`, `int[]`, `long[]` and `BigInteger`. | +| `funcref` | `jp.akkiserver.shuttle.WasmtimeFunction` | Callable function reference. Only Wasm → Java (exported function references) is supported. | +| `externref` | any Java object | Any Java object can be passed through Wasm as an externref (`ValType.Ref`). | + +### Memory + +`WasmtimeMemory` maps linear memory directly to a `java.nio.ByteBuffer`: + +```java +try (WasmtimeInstance instance = new WasmtimeInstance(store, module, linker)) { + WasmtimeMemory mem = instance.getMemory("memory"); + + byte[] data = mem.read(0x1000, 4); // 4 bytes from offset 0x1000 + mem.write(0x1003, (byte) 5); // one byte at 0x1003 + + // Normally the guest's own allocator would hand out these addresses. + mem.writeCString(0x1000, "Hello", StandardCharsets.UTF_8); // NUL-terminated + mem.readCString(0x1000, StandardCharsets.UTF_8); // "Hello" + + mem.writeString(0x1000, "World", StandardCharsets.UTF_8); // no terminator + mem.readString(0x1000, 5, StandardCharsets.UTF_8); // "World" + + mem.writeLong(0x1000, Long.MAX_VALUE); mem.readLong(0x1000); + mem.writeInt(0x1000, Integer.MAX_VALUE); mem.readInt(0x1000); + mem.writeShort(0x1000, Short.MAX_VALUE); mem.readShort(0x1000); + mem.write(0x1000, Byte.MAX_VALUE); mem.readByte(0x1000); + + mem.grow(1); // add one 64 KiB page +} +``` + +`createView(address, length)` returns a `WasmtimeMemory` over a sub-range. `WasmtimeSharedMemory(engine, initialPages, maxPages)` creates a shared memory that can be imported with `linker.linkMemory(module, name, memory)`. + +### WASI + +`shuttle-java` currently contains **no WASI implementation**. Upstream implemented WASI Preview 1 (`WasiPI1Context`, `WasiThreadContext`) and WASI Preview 2 (`wasmtimejavang-wasi-*` modules) in Java. All of these were removed in commit `44c4363` ("remove wasi components"). Shuttle guests talk to the host through the firmware ABI instead of WASI. A module that imports WASI functions only links if the host provides those imports itself, for example with `linkFunction`. + +## Component Model + +The Component Model plumbing is still present, without any built-in interfaces: + +| Class | Role | +| --- | --- | +| `WasmtimeComponent` | Compiled component (WAT or binary from `String` bytes, `byte[]`, `ByteBuffer`, `InputStream`). `getImportInterfaces()` / `getExportInterfaces()` read the named interfaces straight from the compiled component, without instantiating it. | +| `WasmtimeComponentLinker` | `linkContext(WasmComponentContext)` links one context (after its declared dependencies). `linkRequired(component)` links a provider for every import interface not already covered, found through a `ComponentContextLookup`. It throws `IllegalStateException` if an interface stays unresolved. | +| `WasmtimeComponentInstance` | Instantiated component. `invoke(interfaceName, funcName, args...)` calls an export; use `""` as the interface name for root-level exports. | +| `WasmComponentContext` | A host-side implementation of one or more component interfaces. | + +### Component values + +| WIT type | Java type | +| :--- | :--- | +| `bool` | `Boolean` | +| `s8`, `u8`, `s16`, `u16`, `s32`, `u32` | `Integer` | +| `s64`, `u64` | `Long` | +| `f32` / `f64` | `Float` / `Double` | +| `char` | `Character` | +| `string` | `String` | +| `list` | `byte[]` | +| `list` | `List` | +| `tuple<...>` | `Object[]` | +| `record` | `Map` (field name → value) | +| `variant` | `jp.akkiserver.shuttle.component.WitVariant(caseName, value)` | +| `enum` | `jp.akkiserver.shuttle.component.WitEnum(name)` | +| `option` | `Optional` | +| `result` | `jp.akkiserver.shuttle.component.WitResult(ok, value)` | +| `flags` | `Set` | +| resource handle | `jp.akkiserver.shuttle.component.WitResource(resourceName, rep, owned)` | + +Unsigned values use the signed Java type of the same width (a `u32` above `Integer.MAX_VALUE` arrives as a negative `Integer`). + +### Writing a `WasmComponentContext` + +`WasmComponentContext` methods: + +| Method | Default | Purpose | +| --- | --- | --- | +| `getImportFunctions()` | (abstract) | `ComponentImportFunction(interfaceName, funcName, ComponentFunction)` entries. `interfaceName` is the versioned name, e.g. `my:custom/greet@1.0.0`, or `""` for root imports. | +| `getImportResources()` | (abstract) | `ComponentImportResource(interfaceName, resourceName, ResourceDestructor)` entries. The destructor gets the resource `rep` when the guest drops an owned handle. | +| `name()` | (abstract) | Stable id. Used as the linker's cache key and as the name other contexts depend on. | +| `getDependencies()` | empty | Names of other contexts that must be linked first. | +| `onDependenciesResolved(lookup)` | no-op | Called after the dependencies are linked; look them up by name here. | +| `getProvidedInterfaces()` | empty | Bare (unversioned) interface names this context implements. `linkRequired` uses it to see what is already covered and to auto-discover providers. | +| `withVersion` / `getVersion` | no-op / `0.2.6` | The version used to build versioned interface names. | +| `getMiniumVersion` / `getMaximumVersion` | `0.0.0` / max | Range accepted by `supportsVersion(...)`. (The misspelling `Minium` is the actual method name.) | + +Example, taken from `WasmtimeComponentTest`: a component imports `is-even(u32) -> bool` at the root and re-exports it as `run`. The Java side implements `is-even`. + +```java +try ( + WasmtimeEngine engine = new WasmtimeEngine(); + WasmtimeComponent component = new WasmtimeComponent(engine, COMPONENT_WAT.getBytes(StandardCharsets.UTF_8)); + WasmtimeStore store = new WasmtimeStore(engine); + WasmtimeComponentLinker linker = new WasmtimeComponentLinker(engine, store) +) { + linker.linkContext(new WasmComponentContext() { + @Override + public List getImportFunctions() { + return List.of(new ComponentImportFunction("", "is-even", (instance, args) -> { + int x = (Integer) args[0]; + return new Object[] { x % 2 == 0 }; + })); + } + + @Override + public List getImportResources() { return List.of(); } + + @Override + public String name() { return "test-context"; } + }); + + try (WasmtimeComponentInstance instance = new WasmtimeComponentInstance(store, component, linker)) { + instance.invoke("", "run", 4); // -> [true] + instance.invoke("", "run", 5); // -> [false] + } +} +``` + +To avoid writing `getImportFunctions()` and the casts by hand, generate a typed interface from a WIT file with `shuttle-wit-maven-plugin`. See [wit-codegen.md](wit-codegen.md). + +### Discovery and overriding + +- **Auto-discovery:** `linkRequired(component)` asks the configured `ComponentContextLookup`. The default, `ServiceLoaderComponentContextLookup`, loads every class listed in `META-INF/services/jp.akkiserver.shuttle.WasmComponentContext` and picks the first whose `getProvidedInterfaces()` contains the bare interface name and whose `supportsVersion(...)` accepts the version requested by the component. A provider class needs a public no-arg constructor or a public static `provider()` method. +- **Explicit wins:** `linkRequired` skips every interface already covered by a context linked with `linkContext(...)`. That means an explicitly linked context with the same interfaces always takes precedence. It also means an explicitly linked context must declare `getProvidedInterfaces()`, otherwise `linkRequired` cannot see that the interface is covered and throws. +- **Global override:** register your own `ComponentContextLookup` in `META-INF/services/jp.akkiserver.shuttle.ComponentContextLookup`. The linker uses it instead of `ServiceLoaderComponentContextLookup`. + +## Weave: checkpointable guests + +The Weave layer lets a host run a guest a little at a time, stop it at any *poll point* (Weave inserts polls at loop back-edges and calls), save the complete guest state, and continue later from exactly that point. This is what lets a computer survive a world save and reload. + +| Class | Role | +| --- | --- | +| `WeaveModule` | `WeaveModule.load(engine, wasm)` or `load(engine, wasm, pollPeriod, stackPages)`. Takes a core module, binary or WAT (no components), and transforms and compiles it once. `pollPeriod` is the number of back-edges/calls between polls and `stackPages` the shadow-stack size in Wasm pages (`<= 0` means the Weave default for either). `hash()` identifies the transformed module; `entries()` lists the exports as `name -> "params>results"`; `instance()` returns a builder. | +| `WeaveInstance.Builder` | `define(module, name, signature, WeaveHostFunction)` adds a host import. `build()` creates a fresh instance (runs the start function); `restore(snapshot)` creates one from a snapshot. | +| `WeaveInstance` | A running guest (not thread-safe). `call(entry, args...)`, `resume()`, `unwindNext()`, `unwindAfter(polls)`, `snapshot()`, `state()`, `readMemory`/`writeMemory`, `cancellation()`. | +| `WeaveInstance.State` | `READY`, `RESTORE_TARGET`, `RESTORING`, `RUNNING`, `PAUSED`, `COMPLETED`, `RETIRED`, `FAILED`. | +| `WeaveInstance.Cancellation` | Thread-safe handle: `cancel()` makes the guest unwind at its next poll. Close it before closing the instance. | +| `WeaveHostFunction` | `long[] call(WeaveCaller caller, long[] args)`. Arguments and results are raw bits. Return one value per declared result, or `null` when there are none. | +| `WeaveCaller` | Valid only during a host call: `read`, `write`, `readString` (UTF-8) on the guest's primary memory, and `requestUnwind()` to suspend the guest at its next poll. Static helpers `asFloat`/`asDouble`/`fromFloat`/`fromDouble` convert between floats and raw bits. | +| `WeaveResult` | Result of `call`/`resume`: `isUnwound()` / `isDone()`, `values()` (`Integer`/`Long`/`Float`/`Double`), `intValue()`, `longValue()`. | + +**Signatures** are written `params>results` with one character per value: `i` = i32, `l` = i64, `f` = f32, `d` = f64. Examples: `"ii>i"` takes two i32 and returns one i32; `"i>"` takes one i32 and returns nothing. `entries()` may also show `v` (v128) and `r` (funcref), which `define` and `call` do not support. `call` accepts `Integer`, `Long`, `Float` and `Double` arguments only. + +**Raw bits:** an i32 arrives sign-extended in a `long`, so `(int) a[0]` recovers it. An f32 is passed as its IEEE bit pattern; use `WeaveCaller.asFloat(a[0])`, and `WeaveCaller.fromFloat(x)` for results. + +### Example: run in tick slices, save, restore + +Condensed from [`VirtualComputerExample`](../shuttle-java-example/src/main/java/example/VirtualComputerExample.java). Its guest [`guest.wat`](../shuttle-java-example/src/main/resources/guest.wat) exports `main(n)`, which loops `n` times, calls `sys.print` and adds the loop counter through `sys.add`. + +```java +static WeaveInstance.Builder builder(WeaveModule module) { + return module.instance() + .define("sys", "print", "ii>", (caller, a) -> { // (ptr, len) + System.out.println(caller.readString(a[0], (int) a[1])); + return null; + }) + .define("sys", "add", "ii>i", (caller, a) -> new long[] { (int) a[0] + (int) a[1] }); +} + +try (WasmtimeEngine engine = new WasmtimeEngine(); + WeaveModule module = WeaveModule.load(engine, wasm, 1, 0)) { // poll on every back-edge + + byte[] snapshot; + try (WeaveInstance vm = builder(module).build()) { + vm.unwindAfter(2); // budget for this tick: 2 polls + WeaveResult r = vm.call("main", 12); + if (r.isUnwound()) { // stopped mid-loop + snapshot = vm.snapshot(); // gzip-compressed byte[] + } else { + return; // finished within one tick + } + } + + // Later, possibly in another JVM: same module, same host imports. + try (WeaveInstance vm = builder(module).restore(snapshot)) { + WeaveResult r; + do { + vm.unwindAfter(2); // one tick + r = vm.resume(); + } while (r.isUnwound()); + System.out.println(r.intValue()); // 66 = 0 + 1 + ... + 11 + } +} +``` + +Run the full example with `mvn -pl shuttle-java-example exec:java`. Its comments are in Japanese. + +Rules that follow from the API: + +- `snapshot()` only works while the guest is paused (unwound). The snapshot is gzip-compressed and small enough to store as a byte array, for example in an NBT `ByteArrayTag`. +- A snapshot only restores into a module with the same `hash()`, and `restore` must be given the same host function definitions as the original instance. +- State kept on the Java side, such as fields captured by host function lambdas, is **not** part of the snapshot. +- Ways to stop a guest: `unwindNext()` / `unwindAfter(n)` before `call`/`resume` (a budget), `caller.requestUnwind()` from inside a host function (a yield), or `cancellation().cancel()` from another thread (a power-off). + +### Relation to `native/` + +The Weave layer in `shuttle-java` and the native core in `native/` are separate. `shuttle-java` pins Weave commit `0f26893`, which does not have the `shuttle-host-hooks` additions (yielding imports, memory limits). `native/` pins `677cce6` on branch `shuttle-host-hooks`. How the Java layer will connect to `shuttle-core` (a Machine API over JNI) has not been designed yet. + +## Architecture + +`shuttle-java` has three layers: + +1. **Java API**: type-safe wrappers for the Wasmtime and Weave concepts above. `jar-jni` loads the platform library from `jp/akkiserver/shuttle/libs//` inside the jar. Log4j2 is the logging API. Native handles are released by `close()`, with a `Cleaner` as a fallback for the Wasmtime classes. +2. **JNI layer (Rust)**: built with the [jni](https://crates.io/crates/jni) crate (`bind_java_type!`). It owns the native Wasmtime objects, converts values between the JVM and Rust (for example `wasmcomponentvalue.rs` for component values), and forwards Rust `log` output to Log4j2. Classic JNI was chosen over the Foreign Function and Memory API because the library is only used from Java: Rust can call Java methods and construct Java objects directly, and keeps type and lifetime checks on the native side. [`weave.rs`](../shuttle-java/src/main/rust/wasmtime-binding/src/weave.rs) is the Weave part. Weave uses its own store and linker; only the `Engine` is shared with `WasmtimeEngine`. All values cross the boundary as raw `long` bits, so no boxing is needed. A host function call attaches the current thread to the JVM and calls `WeaveHostFunction.call`. +3. **Wasmtime**: the [wasmtime](https://crates.io/crates/wasmtime) crate (version 46), plus the `weave-*` crates from [akkiserver-dev/weave](https://github.com/akkiserver-dev/weave). diff --git a/docs/wit-codegen.md b/docs/wit-codegen.md new file mode 100644 index 0000000..94f468c --- /dev/null +++ b/docs/wit-codegen.md @@ -0,0 +1,188 @@ +# WIT code generation + +Two build-time modules generate typed Java interfaces from [WIT](https://component-model.bytecodealliance.org/design/wit.html) files (WIT is the interface description language of the WebAssembly Component Model). You implement the generated interface instead of writing a `WasmComponentContext` by hand (see [java-binding.md](java-binding.md#component-model)). + +| Module | Role | +| --- | --- | +| [`shuttle-wit-parser`](../shuttle-wit-parser) | JNI binding (`witparserbinding`) to the Rust [`wit-parser`](https://crates.io/crates/wit-parser) crate. Package `jp.akkiserver.shuttle.wit.parser`. | +| [`shuttle-wit-maven-plugin`](../shuttle-wit-maven-plugin) | Maven plugin with the goal `generate-wit-sources`. Package `jp.akkiserver.shuttle.wit.codegen`. | + +Neither module is needed at runtime: generated code only depends on `shuttle-java`. + +## `shuttle-wit-parser` + +```java +import jp.akkiserver.shuttle.wit.parser.*; + +// One .wit file, or every .wit file directly in a directory (with an optional deps/ folder) +List ifaces = WitParser.parse(Path.of("src/main/wit/greet.wit")); + +// The flattened, transitive imports of a world in a WIT package directory +List world = WitParser.resolveWorld(Path.of("wit/wasi-cli/wit"), "command"); +``` + +The result types are records: + +- `WitInterface(name, functions, resources)`: `name` is the bare interface name, e.g. `my:custom/greet`. +- `WitFunction(name, params, result)` +- `WitParam(name, type)` +- `WitValueType(kind, resourceName)`, where `kind` is a `WitTypeKind` + +Supported: records, variants, enums, flags, options, results, tuples, lists, resources and all scalar types. Unsupported constructs throw: the WIT 0.3 async surface, `stream`/`future`, `map`, and fixed-length lists. + +The native library is only packaged for Linux x86_64. On Windows the parser cannot load it (see [building.md](building.md#known-issues)). + +## `shuttle-wit-maven-plugin` + +### Goal `generate-wit-sources` + +The goal is bound to the `generate-sources` phase by default. Parameters: + +| Parameter | Default | Meaning | +| --- | --- | --- | +| `targetPackage` (property `witCodegen.targetPackage`) | required | Java package of the generated interfaces. | +| `witSourceDirectory` | `${project.basedir}/src/main/wit` | Every `.wit` file directly in this directory is parsed and generated on its own. A missing directory is not an error. | +| `worldSourceDirectory` | none | A WIT package directory (optionally with `deps/`) to resolve a world from. Must be set together with `worldName`. | +| `worldName` | none | Bare world name, e.g. `command`. One interface is generated per interface that the world's imports flatten to. Exports are not modeled. | +| `outputDirectory` | `${project.build.directory}/generated-sources/wit-components` | Output folder. It is added as a compile source root when anything was generated. | + +Plugin declaration: + +```xml + + jp.akkiserver + shuttle-wit-maven-plugin + 6.0.1-SNAPSHOT + + + + generate-wit-sources + + + ${project.basedir}/src/main/wit + com.example.generated + + + + +``` + +World mode instead of (or in addition to) single files: + +```xml + + ${project.basedir}/src/main/wit/wasi-cli/wit + command + com.example.generated.wasicli + +``` + +The plugin's tests generate 27 interfaces from `wasi:cli`'s `command` world this way. + +From the command line, the full coordinates always work: + +```sh +mvn jp.akkiserver:shuttle-wit-maven-plugin:6.0.1-SNAPSHOT:generate-wit-sources -DwitCodegen.targetPackage=com.example.generated +``` + +The plugin prefix is `shuttle-wit` (from the artifactId). `mvn shuttle-wit:generate-wit-sources` only resolves when the plugin is declared in the project's POM or `jp.akkiserver` is listed under `` in `settings.xml`. + +### What gets generated + +Input, [`greet.wit`](../shuttle-wit-maven-plugin/src/test/resources/wit/greet.wit): + +```wit +package my:custom@1.0.0; + +interface greet { + hello: func(name: string) -> string; + add: func(a: u32, b: u32) -> u32; +} +``` + +Output: `com.example.generated.GreetContext`. The class name is the interface name in PascalCase + `Context`. It is an **interface** that extends `WasmComponentContext`. It has: + +- `INTERFACE = "my:custom/greet"`, and `name()` returning `"greet"` +- `default` implementations of `getImportFunctions()`, `getImportResources()` and `getProvidedInterfaces()`. Import names are built as `INTERFACE + "@" + getVersion()`. +- one abstract typed method per WIT function, with a `WasmtimeComponentInstance instance` first parameter +- one abstract `void drop(int rep)` per resource + +Method names: + +- Free functions are prefixed with the interface name, so `hello` becomes `greetHello` and `add` becomes `greetAdd`. This avoids clashes when one class implements several interfaces that declare a function with the same name (for example `now` in both `monotonic-clock` and `wall-clock`). +- Resource methods are prefixed with the resource name, so `[method]input-stream.read` becomes `inputStreamRead`. +- Parameter names that are Java keywords get a trailing `_`. + +Implementation: + +```java +public class MyGreetContext implements com.example.generated.GreetContext { + @Override + public String greetHello(WasmtimeComponentInstance instance, String name) { + return "Hello, " + name + "!"; + } + + @Override + public int greetAdd(WasmtimeComponentInstance instance, int a, int b) { + return a + b; + } + + // The generated interface does not track the WIT package version. + // WasmComponentContext.getVersion() defaults to 0.2.6, so return the + // package version here or the imports are registered as + // "my:custom/greet@0.2.6" instead of "@1.0.0". + @Override + public SemanticVersion getVersion() { + return new SemanticVersion(1, 0, 0); + } +} +``` + +Link it like any other context: `linker.linkContext(new MyGreetContext())`. + +### Type mapping + +| WIT | Parameter / result type | +| --- | --- | +| `bool` | `boolean` | +| `s8` `u8` `s16` `u16` `s32` `u32` | `int` | +| `s64` `u64` | `long` | +| `f32` / `f64` | `float` / `double` | +| `char` | `char` | +| `string` | `String` | +| `list` | `byte[]` | +| `list` | `List` | +| `option` | `Optional` | +| `result` | `WitResult` | +| `tuple` | `Object[]` | +| `record` | `Map` | +| `variant` | `WitVariant` | +| `enum` | `WitEnum` | +| `flags` | `Set` | +| resource | `WitResource` | + +Nested types (record fields, variant payloads and so on) are not reflected in the signature. The values arrive as the runtime types listed in [java-binding.md](java-binding.md#component-values). + +### Combining interfaces + +Interfaces were chosen over abstract classes so that one class can implement several generated interfaces and share state between them. Java then requires you to override the `default` methods that conflict, and to combine them: + +```java +public class MyBundledContext implements FooContext, BarContext { + @Override + public List getImportFunctions() { + List result = new ArrayList<>(); + result.addAll(FooContext.super.getImportFunctions()); + result.addAll(BarContext.super.getImportFunctions()); + return result; + } + // Same pattern for getImportResources(), getProvidedInterfaces() and name(). + // withVersion()/getVersion() stay this class's job (a plain field), since + // interfaces cannot hold state. +} +``` + +## Known issues + +- **Generated imports for `variant`, `enum`, `result` and resources are broken.** The rename turned the import lines in `WitCodeGenerator.requiredImports` into `import component.jp.akkiserver.shuttle.WitVariant;` (and the same for `WitEnum`, `WitResult`, `WitResource`). The correct package is `jp.akkiserver.shuttle.component`. Generated code that uses any of these types does not compile until this is fixed. `greet.wit` is not affected. +- The parser only loads on Linux x86_64 (see [building.md](building.md#known-issues)). From 3f43d1cb5671ddda514fd4381f223d8d34d31663 Mon Sep 17 00:00:00 2001 From: akki <151368291+akki697222@users.noreply.github.com> Date: Thu, 15 Oct 2026 15:39:23 +0900 Subject: [PATCH 10/15] fix: correct component imports emitted by the WIT code generator The rename left the generated import lines as `import component.jp.akkiserver.shuttle.WitVariant;` (and WitEnum, WitResult, WitResource), which does not compile. They now read `jp.akkiserver.shuttle.component.*`. Co-Authored-By: Claude Opus 5.5 --- .../akkiserver/shuttle/wit/codegen/WitCodeGenerator.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/shuttle-wit-maven-plugin/src/main/java/jp/akkiserver/shuttle/wit/codegen/WitCodeGenerator.java b/shuttle-wit-maven-plugin/src/main/java/jp/akkiserver/shuttle/wit/codegen/WitCodeGenerator.java index 565eecc..3a02842 100644 --- a/shuttle-wit-maven-plugin/src/main/java/jp/akkiserver/shuttle/wit/codegen/WitCodeGenerator.java +++ b/shuttle-wit-maven-plugin/src/main/java/jp/akkiserver/shuttle/wit/codegen/WitCodeGenerator.java @@ -202,16 +202,16 @@ private static Set requiredImports(WitInterface iface) { imports.add("import java.util.Map;"); } if (kinds.contains(WitTypeKind.VARIANT)) { - imports.add("import component.jp.akkiserver.shuttle.WitVariant;"); + imports.add("import jp.akkiserver.shuttle.component.WitVariant;"); } if (kinds.contains(WitTypeKind.ENUM)) { - imports.add("import component.jp.akkiserver.shuttle.WitEnum;"); + imports.add("import jp.akkiserver.shuttle.component.WitEnum;"); } if (kinds.contains(WitTypeKind.RESULT)) { - imports.add("import component.jp.akkiserver.shuttle.WitResult;"); + imports.add("import jp.akkiserver.shuttle.component.WitResult;"); } if (kinds.contains(WitTypeKind.RESOURCE)) { - imports.add("import component.jp.akkiserver.shuttle.WitResource;"); + imports.add("import jp.akkiserver.shuttle.component.WitResource;"); } return imports; } From f92e25135373eff6e020892049200674db583772 Mon Sep 17 00:00:00 2001 From: akki <151368291+akki697222@users.noreply.github.com> Date: Thu, 15 Oct 2026 15:39:23 +0900 Subject: [PATCH 11/15] Describe Shuttle as a runtime library; generator makes interfaces - pom, native/README.md, shuttle-core docs: Shuttle is a Wasm runtime library for computer mods, not a mod - native/README.md: the JNI layer goes into shuttle-java - shuttle-wit-maven-plugin: description and Mojo javadoc said it generates abstract classes; it generates sub-interfaces Co-Authored-By: Claude Opus 5.5 --- native/README.md | 4 ++-- native/crates/shuttle-core/src/lib.rs | 2 +- pom.xml | 2 +- shuttle-wit-maven-plugin/pom.xml | 2 +- .../shuttle/wit/codegen/GenerateWitSourcesMojo.java | 6 +++--- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/native/README.md b/native/README.md index 5004ecf..b23109c 100644 --- a/native/README.md +++ b/native/README.md @@ -1,6 +1,6 @@ # Shuttle (prototype) -Native core of the Shuttle computer mod: runs Wasm guests (BIOS → OS kernel → +Native core of Shuttle, the Wasm runtime library for computer mods: runs Wasm guests (BIOS → OS kernel → child programs) on Wasmtime 46, makes them checkpointable with Weave, and implements the firmware ABI draft 0.1 (`fw.*`, `co.*`, `sys.call`). Nothing here depends on Minecraft or Java yet. @@ -109,6 +109,6 @@ queued `dev_submit` requests are saved in snapshots and run after restore. ## Next steps -- JNI layer in wasmtime-ng exposing `ShuttleEngine` / `Machine` (`tick`, +- JNI layer in shuttle-java exposing `ShuttleEngine` / `Machine` (`tick`, `capture`, `restore`, `Device.invoke` callback). - Measure with a real OS-sized module (transform/compile time, disk cache). diff --git a/native/crates/shuttle-core/src/lib.rs b/native/crates/shuttle-core/src/lib.rs index da6e3cc..690340c 100644 --- a/native/crates/shuttle-core/src/lib.rs +++ b/native/crates/shuttle-core/src/lib.rs @@ -1,4 +1,4 @@ -//! shuttle-core: the native engine behind the Shuttle computer mod. +//! shuttle-core: the native engine of the Shuttle runtime library. //! //! It runs Wasm guests (BIOS, OS kernel, child programs) on Wasmtime, makes //! them checkpointable with Weave, and implements the firmware ABI draft 0.1 diff --git a/pom.xml b/pom.xml index 786260f..b0f9f54 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ pom shuttle - Shuttle: a Minecraft computer mod that runs WebAssembly. Java bindings for Wasmtime/Weave via a native Rust bridge, plus WIT tooling. + Shuttle: a WebAssembly runtime library for Minecraft computer mods. Java bindings for Wasmtime/Weave via a native Rust bridge, plus WIT tooling. https://github.com/akkiserver-dev/shuttle diff --git a/shuttle-wit-maven-plugin/pom.xml b/shuttle-wit-maven-plugin/pom.xml index 2117a42..6b5abbd 100644 --- a/shuttle-wit-maven-plugin/pom.xml +++ b/shuttle-wit-maven-plugin/pom.xml @@ -14,7 +14,7 @@ maven-plugin shuttle-wit-maven-plugin - Maven plugin generating abstract WasmComponentContext implementations from WIT interfaces, so custom component contexts only need to implement typed abstract methods instead of hand-writing the interface/version/getImportFunctions plumbing. + Maven plugin generating WasmComponentContext sub-interfaces from WIT interfaces, so custom component contexts only need to implement typed methods instead of hand-writing the interface/version/getImportFunctions plumbing. https://github.com/akkiserver-dev/shuttle diff --git a/shuttle-wit-maven-plugin/src/main/java/jp/akkiserver/shuttle/wit/codegen/GenerateWitSourcesMojo.java b/shuttle-wit-maven-plugin/src/main/java/jp/akkiserver/shuttle/wit/codegen/GenerateWitSourcesMojo.java index 197e99c..d5efb0d 100644 --- a/shuttle-wit-maven-plugin/src/main/java/jp/akkiserver/shuttle/wit/codegen/GenerateWitSourcesMojo.java +++ b/shuttle-wit-maven-plugin/src/main/java/jp/akkiserver/shuttle/wit/codegen/GenerateWitSourcesMojo.java @@ -20,9 +20,9 @@ import jp.akkiserver.shuttle.wit.parser.WitParser; /** - * Generates one abstract {@code WasmComponentContext} implementation per WIT - * interface, so callers only need to extend the generated class and - * implement its (typed) abstract methods -- see {@link WitCodeGenerator} for + * Generates one {@code WasmComponentContext} sub-interface per WIT + * interface, so callers only need to implement the generated interface and + * its (typed) abstract methods -- see {@link WitCodeGenerator} for * the generated shape. Two independent, optional sources of interfaces to * generate from, either or both of which may be configured: *
    From d49201e2c92b31ae1c0d96bd2b7f377563b290c4 Mon Sep 17 00:00:00 2001 From: akki <151368291+akki697222@users.noreply.github.com> Date: Thu, 15 Oct 2026 15:40:55 +0900 Subject: [PATCH 12/15] Update HANDOFF and CLAUDE.md after the rename and docs rewrite HANDOFF: Shuttle is a runtime library (OC via addon, RC by default), new module/package names, Windows build and Maven results, decisions made today, and a list of known issues. CLAUDE.md: language rule, project overview and Windows build/test notes. Co-Authored-By: Claude Opus 5.5 --- CLAUDE.md | 33 ++++++++++ native/HANDOFF.md | 165 ++++++++++++++++++++++++++++------------------ 2 files changed, 134 insertions(+), 64 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 74cf7b9..631e4cf 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -23,3 +23,36 @@ ## Branches - New features: `feature/` - Fixes: `fix/` + +## Language +- Talk to the user in Japanese. +- Files in the repository (code, comments, docs, commit messages) are + written in English unless the user says otherwise. + +# Project + +Shuttle is a WebAssembly runtime library (Java binding + native Rust: +Wasmtime + Weave) for Minecraft computer mods. It is not a mod itself. +OpenComputers will use it through an addon; a new Retro Computing mod +will include it by default. Current status and open decisions: +`native/HANDOFF.md`. Overview and docs: `README.md`, `docs/`. + +| Path | What | +| --- | --- | +| `native/` | Rust workspace: `shuttle-core`, `shuttle-runner`, C test guests | +| `shuttle-java/` | `jp.akkiserver.shuttle`: Wasmtime + Weave JNI binding | +| `shuttle-java-example/` | Weave example | +| `shuttle-wit-parser/`, `shuttle-wit-maven-plugin/` | WIT tooling | + +## Build and test (Windows) +- Native core: `.\native\scripts\build.ps1` (needs LLVM for clang and + wasm-ld). Do not redirect its output; under Windows PowerShell 5.1 that + makes cargo's progress output abort the script. +- Maven: there is no `mvn` on PATH. Use IntelliJ's bundled Maven, + `%LOCALAPPDATA%\Programs\IntelliJ IDEA\plugins\maven-plugin\lib\maven3\bin\mvn.cmd`, + with `JAVA_HOME=%USERPROFILE%\.jdks\temurin-25.0.4` (the global + `JAVA_HOME` points at `bin\` and is wrong), and the profile + `-P build-host-windows-x86_64`. The default profile uses cross + Docker. +- JNI class names are also written as strings in Rust (`java_type = "..."`). + After renaming Java classes or packages, grep the `.rs` files and run the + tests: a wrong name compiles but fails at run time. diff --git a/native/HANDOFF.md b/native/HANDOFF.md index ec141f0..1147c6b 100644 --- a/native/HANDOFF.md +++ b/native/HANDOFF.md @@ -1,79 +1,90 @@ -# Handoff notes (from the claude.ai chat, 2026-10-15) +# Handoff notes -Read this first when continuing the work in Claude Code. Follow CLAUDE.md: -ask before deciding anything, and explain concretely. +Started in a claude.ai chat (2026-10-15), continued in Claude Code the same +day. Read this first when continuing the work. Follow CLAUDE.md: ask before +deciding anything, and explain concretely. Talk to the owner in Japanese; +files in the repo stay in English. ## 1. What the project is -A Minecraft computer mod (like OpenComputers / CC:Tweaked) whose computers -run **WebAssembly** programs. Everything the player runs is Wasm: a BIOS -(stored in an EEPROM item), an OS kernel, and the OS's child programs. +Shuttle is a **WebAssembly runtime library** (Java binding + native Rust) +for Minecraft computer mods. It is **not a mod itself**. Planned consumers: + +- **OpenComputers (OC)**, through a separate addon mod. +- **A new Retro Computing mod (RC)** by the owner, which includes Shuttle + by default. + +Neither integration exists yet. Everything a computer runs is Wasm: a BIOS +(player-made, e.g. stored on an EEPROM item), an OS kernel, and the OS's +child programs. - Runtime: **Wasmtime**, made checkpointable with **Weave** (a Wasm transformer that can unwind a running program into its linear memory and - rebuild it later). This is how a computer is saved with the world and - resumes mid-execution after a reload. -- Layers: firmware (provided by the mod) -> BIOS (player-made) -> OS - (player-made) -> child programs. The firmware talks to guests only - through the firmware ABI, never through Wasmtime APIs. -- Native code: Rust (Wasmtime + Weave + JNI). Mod side: Java (NeoForge). + rebuild it later). This is how a host mod saves a computer with the world + and resumes it mid-execution after a reload. +- Layers: firmware (implemented by Shuttle) -> BIOS -> OS -> child programs. + The firmware talks to guests only through the firmware ABI, never through + Wasmtime APIs. +- Native code: Rust (Wasmtime + Weave + JNI). Java side: `shuttle-java`. - Targets: Windows, macOS, Linux, each x86_64 and arm64. ## 2. Where things are | What | Where | | --- | --- | -| This repo | `akkiserver-dev/shuttle` (renamed from `wasmtime-ng`), Java Wasmtime binding + `native/` | +| This repo | `akkiserver-dev/shuttle` (forked from StefanRichterHuber/wasmtime-ng) | +| Working branch | `feature/native-build`, rebased onto `main` (on top of `d400a75`) | +| Draft PR (CI check only, not for merging yet) | `akkiserver-dev/shuttle` PR #1 | | Weave fork | `akkiserver-dev/weave`, branch `shuttle-host-hooks` (commit `677cce6`) | -| Shuttle core prototype | branch `feature/shuttle-core` (`native/`) | -| Build scripts + CI | branch `feature/native-build` (on top of `feature/shuttle-core`) | -| Draft PR (CI check only, not for merging) | `akkiserver-dev/shuttle` PR #1 | | Firmware ABI spec (Japanese) | https://claude.ai/code/artifact/05272d17-ac4c-4f56-933a-374281672f79 | - -`native/README.md` explains the prototype, how to build it, and the results. - -### Renamed on 2026-10-15 (commit `983dc25`) - -The text below keeps the old names as they were when it was written. Map them as follows: - -| Old | New | -| --- | --- | -| `wasmtimejavang/` (artifact `wasmtimejavang`) | `shuttle-java/` | -| `wasmtimejavang-example/` | `shuttle-java-example/` | -| `wit-parser/` | `shuttle-wit-parser/` | -| `wit-codegen-maven-plugin/` | `shuttle-wit-maven-plugin/` | -| groupId `io.github.stefanrichterhuber`, parent `wasmtimejavang-parent` | groupId `jp.akkiserver`, parent `shuttle` | -| package `io.github.stefanrichterhuber.wasmtimejavang` | `jp.akkiserver.shuttle` | -| package `io.github.stefanrichterhuber.witparser` / `.witcodegen` | `jp.akkiserver.shuttle.wit.parser` / `.wit.codegen` | - -`native/` keeps its name. The feature branches were also rebased onto -`main` (on top of `d400a75`), so section 3's note about them being based -on `917ffd6` is out of date. - -## 3. Current state - -- `native/` boots BIOS -> `exec` -> OS -> `co_create` -> child -> exit, in a - headless runner. Capture/restore at every tick boundary gives identical - logs (26/26), and a control run that drops the host-side child table - diverges (24/24), so the check is meaningful. Snapshots are 5-8 KB gzip. -- CI (`.github/workflows/native.yml`) passed on all six platforms on PR #1. -- `native/scripts/build.ps1` (Windows) has **never been run**. Test it first. -- "Java CI with Maven" fails, also on `main` itself (commit `d400a75`), so it - is not caused by `native/`. The log could not be read from the chat - sandbox; check it locally. -- **`main` moved on**: commit `d400a75 "Weave JNI"` (by the owner) added a - Weave JNI layer in `wasmtimejavang` (`WeaveModule`, `WeaveInstance`, - `weave.rs`, ...) pinned to Weave `0f26893`, i.e. *without* the - `shuttle-host-hooks` patch. The feature branches are based on `917ffd6`, - before that commit. How this JNI layer and `native/shuttle-core` fit - together has **not been discussed yet**. +| Docs | `README.md` (overview), `docs/` (building, java-binding, wit-codegen), `native/README.md` | + +Modules (Maven groupId `jp.akkiserver`, parent artifactId `shuttle`): + +| Directory | Java package | What | +| --- | --- | --- | +| `native/` | - | Rust workspace: `shuttle-core`, `shuttle-runner`, C test guests | +| `shuttle-java/` | `jp.akkiserver.shuttle` | Wasmtime + Weave JNI binding (`wasmtime-binding` crate inside) | +| `shuttle-java-example/` | `example` | Weave example (tick slices, snapshot, restore) | +| `shuttle-wit-parser/` | `jp.akkiserver.shuttle.wit.parser` | JNI binding to the Rust wit-parser crate | +| `shuttle-wit-maven-plugin/` | `jp.akkiserver.shuttle.wit.codegen` | WIT -> Java interface generator | + +Old names (before commit `983dc25`): `wasmtimejavang`, `wasmtimejavang-example`, +`wit-parser`, `wit-codegen-maven-plugin`, groupId `io.github.stefanrichterhuber`, +packages `io.github.stefanrichterhuber.{wasmtimejavang,witparser,witcodegen}`. +`feature/shuttle-core` on the remote is an older subset of `feature/native-build`. + +## 3. Current state (2026-10-15) + +- **Windows native build verified.** `native/scripts/build.ps1`: clang 23.1.3, + rustc 1.99.0, `cargo build` 2m13s; verify 26/26 identical, control 24/24 + diverged. Re-run after the rebase: same result. + - Snapshots on Windows are 5.6 KB (tick 1) and about 9.3 KB later; the + Linux numbers in `native/README.md` are 5.2-7.7 KB. Not investigated. + - `build.ps1` dies if its output is redirected (`*>&1`) under Windows + PowerShell 5.1: cargo's stderr becomes an error record and + `$ErrorActionPreference='Stop'` aborts. A plain run works. Not fixed. +- **WSL2 native build not run yet.** Ubuntu-26.04 has only git; it needs + `sudo apt install clang lld build-essential` and rustup (owner runs sudo). + Plan: clone the repo into the WSL home and build there, so Linux and + Windows artifacts do not share `native/target/`. +- **Maven on Windows** (IntelliJ's bundled Maven, JDK 25, + `-P build-host-windows-x86_64`): `shuttle-java` 64/64 tests pass (incl. + WeaveTest 12). `shuttle-wit-parser` fails on Windows because its pom only + copies the Linux native library; `shuttle-wit-maven-plugin` was therefore + not tested locally. +- Rename to Shuttle, docs rewrite and a code-generator import fix are + committed. Pushed up to `7dbc5b8`; later commits are local only. +- **Two Weave versions coexist**: `shuttle-java` pins `0f26893` (no + `shuttle-host-hooks`), `native/` pins `677cce6`. How the `d400a75` Weave + JNI layer and `native/shuttle-core` fit together is **not decided**. ## 4. Decided with the owner - Rust/Java boundary: Weave, `co_*`, VM exits, memory pool and snapshot capture live in Rust. Device implementations live in Java and are called directly from Rust (JNI) on worker threads; world-touching work is queued - to the server thread. Mod code sees a high-level Machine API only. + to the server thread. Host mod code sees a high-level Machine API only. - Threads: Rust owns a worker pool (reliable stack sizes for `max_wasm_stack`). Saving is split: capture on the worker at a tick boundary, compress and write on a separate save thread. @@ -90,7 +101,14 @@ on `917ffd6` is out of date. - Build: option C. Local scripts for Windows and WSL2 build the host target; release binaries for all six platforms come from CI. - Weave may be modified freely. -- Branches: `feature/` and `fix/`. CLAUDE.md lives on `main`. +- Branches: `feature/` and `fix/`. +- Names (2026-10-15): modules, groupId and packages as in section 2; + `native/` keeps its name. WIT tooling stays as two modules. +- Docs layout: root README = overview; `docs/building.md`, + `docs/java-binding.md`, `docs/wit-codegen.md`, `docs/README.md` (index). + WASI material was dropped because WASI was removed upstream (`44c4363`). +- pom ``: akki (maintainer) + Stefan Richter-Huber (original + author). ## 5. NOT approved yet (decided by Claude without asking; review each) @@ -109,11 +127,30 @@ on `917ffd6` is out of date. 5. `native/` layout details (`crates/`, `guests/`, `scripts/`), and that built `.wasm` files are not committed. -## 6. Next steps (in order, ask before each) - -1. Run `native/scripts/build.ps1` on Windows and `build.sh` on WSL2. -2. Look at why "Java CI with Maven" fails on `main`. -3. Review the unapproved items in section 5. -4. Decide how the `d400a75` Weave JNI layer and `native/shuttle-core` - relate, then design the JNI layer for the Machine API. -5. Rebase the feature branches onto the current `main`. +## 6. Known issues (found 2026-10-15, not fixed) + +- **`.github/workflows/maven.yml`** (probably why "Java CI with Maven" + fails): installs `wasm32-wasip1`/`wasip2`/nightly `wasip1-threads` + (leftovers from removed WASI modules) but not `wasm32-unknown-unknown`, + which the `valuetest` fixture needs; cross-compiles + `x86_64-pc-windows-msvc` with `cross`, which has no official msvc image. +- `shuttle-wit-parser` has no Windows/macOS native library copy step. +- No macOS profile in `shuttle-java/pom.xml`. +- Generated WIT contexts default to version `0.2.6` + (`WasmComponentContext.DEFAULT_VERSION`); a WIT package at `@1.0.0` is + registered under the wrong version unless `getVersion()` is overridden. +- `wasmcomponentvalue.rs`: an empty `list` becomes a Java `List`, not + `byte[]`; WIT `char` is narrowed with `as u16` (breaks code points above + U+FFFF). +- `WeaveModule.entries()` can report `v`/`r` type chars that + `Builder.define` rejects, although its javadoc says "as in define". +- Public API typo: `getMiniumVersion` (with `getMaximumVersion`). +- The `linkContext` dependency lookup lambda ignores the version. +- `shuttle-java-example`'s pom description and comments are in Japanese. + +## 7. Next steps (ask before each) + +See the end of the 2026-10-15 Claude Code session; the owner picks the +order. Candidates: WSL2 build, fixing `maven.yml`, reviewing section 5, and +deciding how the Weave JNI layer and `native/shuttle-core` relate (then +designing the Machine API JNI layer). From 8d3b9d996aa7c3557cb02bdc2b1568634a60c7ba Mon Sep 17 00:00:00 2001 From: akki <151368291+akki697222@users.noreply.github.com> Date: Thu, 15 Oct 2026 16:08:09 +0900 Subject: [PATCH 13/15] fix: make Java CI build again (jni deprecation, wasm target, Windows job) - Allow `deprecated` in the two JNI crates: jni 0.22.4's `bind_java_type!` expands to `AtomicBool::fetch_update`, deprecated in Rust 1.99, and setup-rust-toolchain builds with -D warnings (jni-rs/jni-rs#846). - Install wasm32-unknown-unknown (valuetest fixture) instead of the wasip targets left over from the removed WASI modules. - Linux job: drop build-windows-x86_64 (cross has no MSVC image). - New Windows job: host build of shuttle-java and the example, with tests. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/maven.yml | 40 ++++++++++++++----- .../src/main/rust/wasmtime-binding/src/lib.rs | 4 ++ .../main/rust/wit-parser-binding/src/lib.rs | 4 ++ 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 0e4f73f..e99000b 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -1,10 +1,11 @@ -# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time -# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven - -# This workflow uses actions that are not certified by GitHub. -# They are provided by a third-party and are governed by -# separate terms of service, privacy policy, and support -# documentation. +# Builds the Maven reactor (shuttle-java, the example and the WIT tooling) +# and runs its tests. +# +# - linux: native libraries for Linux x86_64 and aarch64 via `cross`; all modules. +# - windows: native library built on the host (MSVC); shuttle-java and the example +# only, because shuttle-wit-parser has no Windows native library yet. +# +# setup-rust-toolchain sets RUSTFLAGS=-D warnings, so Rust warnings fail the build. name: Java CI with Maven @@ -15,11 +16,13 @@ on: branches: [main] jobs: - build: + linux: runs-on: ubuntu-latest timeout-minutes: 30 steps: - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + target: wasm32-unknown-unknown # for the valuetest fixture - uses: actions/checkout@v5 - name: Set up JDK 21 uses: actions/setup-java@v5 @@ -27,9 +30,24 @@ jobs: java-version: "21" distribution: temurin cache: maven - - name: Install additional wasm targets for rust - run: rustup target add wasm32-wasip1 wasm32-wasip2 && rustup target add wasm32-wasip1-threads --toolchain nightly - name: Install cargo cross run: cargo install cross - name: Build with Maven - run: mvn -P build-linux-x86-64,build-linux-aarch64,build-windows-x86_64 -Dcargo.profile=release -Dcargo.profile.folder=release -B package --file pom.xml + run: mvn -P build-linux-x86-64,build-linux-aarch64 -Dcargo.profile=release -Dcargo.profile.folder=release -B package --file pom.xml + + windows: + runs-on: windows-latest + timeout-minutes: 30 + steps: + - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + target: wasm32-unknown-unknown # for the valuetest fixture + - uses: actions/checkout@v5 + - name: Set up JDK 21 + uses: actions/setup-java@v5 + with: + java-version: "21" + distribution: temurin + cache: maven + - name: Build with Maven + run: mvn -P build-host-windows-x86_64 -pl shuttle-java,shuttle-java-example -am -Dcargo.profile=release -Dcargo.profile.folder=release -B package --file pom.xml diff --git a/shuttle-java/src/main/rust/wasmtime-binding/src/lib.rs b/shuttle-java/src/main/rust/wasmtime-binding/src/lib.rs index 55e3a41..fe642b0 100644 --- a/shuttle-java/src/main/rust/wasmtime-binding/src/lib.rs +++ b/shuttle-java/src/main/rust/wasmtime-binding/src/lib.rs @@ -1,3 +1,7 @@ +// jni 0.22.4's `bind_java_type!` expands to `AtomicBool::fetch_update`, deprecated +// since Rust 1.99. Remove once jni ships a fix (jni-rs/jni-rs#846). +#![allow(deprecated)] + pub mod java_numbers; pub mod java_collections; pub mod java_maps; diff --git a/shuttle-wit-parser/src/main/rust/wit-parser-binding/src/lib.rs b/shuttle-wit-parser/src/main/rust/wit-parser-binding/src/lib.rs index 2df68b5..cbd2450 100644 --- a/shuttle-wit-parser/src/main/rust/wit-parser-binding/src/lib.rs +++ b/shuttle-wit-parser/src/main/rust/wit-parser-binding/src/lib.rs @@ -1,3 +1,7 @@ +// jni 0.22.4's `bind_java_type!` expands to `AtomicBool::fetch_update`, deprecated +// since Rust 1.99. Remove once jni ships a fix (jni-rs/jni-rs#846). +#![allow(deprecated)] + use std::collections::HashSet; use std::path::Path; From 2ebc97488b6ef67bb8a5f2a34e6c1fc117508de1 Mon Sep 17 00:00:00 2001 From: akki <151368291+akki697222@users.noreply.github.com> Date: Thu, 15 Oct 2026 16:08:09 +0900 Subject: [PATCH 14/15] Keep LF endings for shell scripts (.gitattributes) Co-Authored-By: Claude Opus 5.5 --- .gitattributes | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..164f159 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +# Shell scripts must keep LF endings, also in Windows checkouts with +# core.autocrlf=true, so they run under WSL and Linux. +*.sh text eol=lf From 03508ff1683570ab37b338a4a23e29cb12e17751 Mon Sep 17 00:00:00 2001 From: akki <151368291+akki697222@users.noreply.github.com> Date: Thu, 15 Oct 2026 17:01:50 +0900 Subject: [PATCH 15/15] fix: run the Windows Maven step in bash PowerShell splits -Dcargo.profile=release into -Dcargo and .profile=release, which Maven then rejects as an unknown lifecycle phase. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/maven.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index e99000b..601b405 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -50,4 +50,6 @@ jobs: distribution: temurin cache: maven - name: Build with Maven + # bash, not PowerShell: PowerShell splits -Dcargo.profile=release at the dot + shell: bash run: mvn -P build-host-windows-x86_64 -pl shuttle-java,shuttle-java-example -am -Dcargo.profile=release -Dcargo.profile.folder=release -B package --file pom.xml