diff --git a/Cargo.lock b/Cargo.lock index bdf6e12..06e6124 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 4 [[package]] name = "addr2line" -version = "0.25.1" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" +checksum = "9698bf0769c641b18618039fe2ebd41eb3541f98433000f64e663fab7cea2c87" dependencies = [ "gimli", ] @@ -84,9 +84,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.100" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "arbitrary" @@ -119,9 +119,9 @@ checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" [[package]] name = "bitflags" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" [[package]] name = "bitmaps" @@ -143,18 +143,18 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.19.0" +version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" dependencies = [ "allocator-api2", ] [[package]] name = "bytes" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] name = "cap-fs-ext" @@ -176,7 +176,7 @@ checksum = "20a158160765c6a7d0d8c072a53d772e4cb243f38b04bfcf6b4939cfbe7482e7" dependencies = [ "cap-primitives", "cap-std", - "rustix 1.1.2", + "rustix 1.1.4", "smallvec", ] @@ -192,7 +192,7 @@ dependencies = [ "io-lifetimes", "ipnet", "maybe-owned", - "rustix 1.1.2", + "rustix 1.1.4", "rustix-linux-procfs", "windows-sys 0.59.0", "winx", @@ -217,7 +217,7 @@ dependencies = [ "cap-primitives", "io-extras", "io-lifetimes", - "rustix 1.1.2", + "rustix 1.1.4", ] [[package]] @@ -230,15 +230,15 @@ dependencies = [ "cap-primitives", "iana-time-zone", "once_cell", - "rustix 1.1.2", + "rustix 1.1.4", "winx", ] [[package]] name = "cc" -version = "1.2.46" +version = "1.2.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97463e1064cb1b1c1384ad0a0b9c8abd0988e2a91f52606c80ef14aadb63e36" +checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" dependencies = [ "find-msvc-tools", "jobserver", @@ -254,9 +254,9 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "clap" -version = "4.5.52" +version = "4.5.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa8120877db0e5c011242f96806ce3c94e0737ab8108532a76a3300a01db2ab8" +checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a" dependencies = [ "clap_builder", "clap_derive", @@ -264,9 +264,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.52" +version = "4.5.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02576b399397b659c26064fbc92a75fede9d18ffd5f80ca1cd74ddab167016e1" +checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876" dependencies = [ "anstream", "anstyle", @@ -276,9 +276,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.49" +version = "4.5.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" +checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" dependencies = [ "heck", "proc-macro2", @@ -288,9 +288,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.6" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" +checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" [[package]] name = "cobs" @@ -298,7 +298,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" dependencies = [ - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -333,46 +333,47 @@ dependencies = [ [[package]] name = "cranelift-assembler-x64" -version = "0.128.3" +version = "0.129.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0377b13bf002a0774fcccac4f1102a10f04893d24060cf4b7350c87e4cbb647c" +checksum = "40630d663279bc855bff805d6f5e8a0b6a1867f9df95b010511ac6dc894e9395" dependencies = [ "cranelift-assembler-x64-meta", ] [[package]] name = "cranelift-assembler-x64-meta" -version = "0.128.3" +version = "0.129.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfa027979140d023b25bf7509fb7ede3a54c3d3871fb5ead4673c4b633f671a2" +checksum = "3ee6aec5ceb55e5fdbcf7ef677d7c7195531360ff181ce39b2b31df11d57305f" dependencies = [ "cranelift-srcgen", ] [[package]] name = "cranelift-bforest" -version = "0.128.3" +version = "0.129.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "618e4da87d9179a70b3c2f664451ca8898987aa6eb9f487d16988588b5d8cc40" +checksum = "9a92d78cc3f087d7e7073828f08d98c7074a3a062b6b29a1b7783ce74305685e" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-bitset" -version = "0.128.3" +version = "0.129.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db53764b5dad233b37b8f5dc54d3caa9900c54579195e00f17ea21f03f71aaa7" +checksum = "edcc73d756f2e0d7eda6144fe64a2bc69c624de893cb1be51f1442aed77881d2" dependencies = [ "serde", "serde_derive", + "wasmtime-internal-core", ] [[package]] name = "cranelift-codegen" -version = "0.128.3" +version = "0.129.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae927f1d8c0abddaa863acd201471d56e7fc6c3925104f4861ed4dc3e28b421" +checksum = "683d94c2cd0d73b41369b88da1129589bc3a2d99cf49979af1d14751f35b7a1b" dependencies = [ "bumpalo", "cranelift-assembler-x64", @@ -385,6 +386,7 @@ dependencies = [ "cranelift-isle", "gimli", "hashbrown 0.15.5", + "libm", "log", "pulley-interpreter", "regalloc2", @@ -392,14 +394,14 @@ dependencies = [ "serde", "smallvec", "target-lexicon", - "wasmtime-internal-math", + "wasmtime-internal-core", ] [[package]] name = "cranelift-codegen-meta" -version = "0.128.3" +version = "0.129.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fcf1e3e6757834bd2584f4cbff023fcc198e9279dcb5d684b4bb27a9b19f54" +checksum = "235da0e52ee3a0052d0e944c3470ff025b1f4234f6ec4089d3109f2d2ffa6cbd" dependencies = [ "cranelift-assembler-x64-meta", "cranelift-codegen-shared", @@ -410,35 +412,36 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" -version = "0.128.3" +version = "0.129.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "205dcb9e6ccf9d368b7466be675ff6ee54a63e36da6fe20e72d45169cf6fd254" +checksum = "20c07c6c440bd1bf920ff7597a1e743ede1f68dcd400730bd6d389effa7662af" [[package]] name = "cranelift-control" -version = "0.128.3" +version = "0.129.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "108eca9fcfe86026054f931eceaf57b722c1b97464bf8265323a9b5877238817" +checksum = "8797c022e02521901e1aee483dea3ed3c67f2bf0a26405c9dd48e8ee7a70944b" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.128.3" +version = "0.129.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0d96496910065d3165f84ff8e1e393916f4c086f88ac8e1b407678bc78735aa" +checksum = "59d8e72637246edd2cba337939850caa8b201f6315925ec4c156fdd089999699" dependencies = [ "cranelift-bitset", "serde", "serde_derive", + "wasmtime-internal-core", ] [[package]] name = "cranelift-frontend" -version = "0.128.3" +version = "0.129.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e303983ad7e23c850f24d9c41fc3cb346e1b930f066d3966545e4c98dac5c9fb" +checksum = "4c31db0085c3dfa131e739c3b26f9f9c84d69a9459627aac1ac4ef8355e3411b" dependencies = [ "cranelift-codegen", "log", @@ -448,15 +451,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.128.3" +version = "0.129.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24b0cf8d867d891245836cac7abafb0a5b0ea040a019d720702b3b8bcba40bfa" +checksum = "524d804c1ebd8c542e6f64e71aa36934cec17c5da4a9ae3799796220317f5d23" [[package]] name = "cranelift-native" -version = "0.128.3" +version = "0.129.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e24b641e315443e27807b69c440fe766737d7e718c68beb665a2d69259c77bf3" +checksum = "dc9598f02540e382e1772416eba18e93c5275b746adbbf06ac1f3cf149415270" dependencies = [ "cranelift-codegen", "libc", @@ -465,9 +468,9 @@ dependencies = [ [[package]] name = "cranelift-srcgen" -version = "0.128.3" +version = "0.129.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4e378a54e7168a689486d67ee1f818b7e5356e54ae51a1d7a53f4f13f7f8b7a" +checksum = "d953932541249c91e3fa70a75ff1e52adc62979a2a8132145d4b9b3e6d1a9b6a" [[package]] name = "crc32fast" @@ -615,12 +618,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "fallible-iterator" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" - [[package]] name = "fastrand" version = "2.3.0" @@ -634,15 +631,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78" dependencies = [ "cfg-if", - "rustix 1.1.2", + "rustix 1.1.4", "windows-sys 0.59.0", ] [[package]] name = "find-msvc-tools" -version = "0.1.5" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] name = "fixedbitset" @@ -662,6 +659,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "form_urlencoded" version = "1.2.2" @@ -678,15 +681,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94e7099f6313ecacbe1256e8ff9d617b75d1bcb16a6fddef94866d225a01a14a" dependencies = [ "io-lifetimes", - "rustix 1.1.2", + "rustix 1.1.4", "windows-sys 0.59.0", ] [[package]] name = "futures" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" dependencies = [ "futures-channel", "futures-core", @@ -698,9 +701,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", "futures-sink", @@ -708,33 +711,33 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-channel", "futures-core", @@ -743,7 +746,6 @@ dependencies = [ "futures-task", "memchr", "pin-project-lite", - "pin-utils", "slab", ] @@ -773,9 +775,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "libc", @@ -794,13 +796,27 @@ dependencies = [ "wasip2", ] +[[package]] +name = "getrandom" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", + "wasip3", +] + [[package]] name = "gimli" -version = "0.32.3" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" +checksum = "0bf7f043f89559805f8c7cacc432749b2fa0d0a0a9ee46ce47164ed5ba7f126c" dependencies = [ - "fallible-iterator", + "fnv", + "hashbrown 0.16.1", "indexmap", "stable_deref_trait", ] @@ -811,7 +827,7 @@ version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ - "foldhash", + "foldhash 0.1.5", "serde", ] @@ -820,6 +836,9 @@ name = "hashbrown" version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "foldhash 0.2.0", +] [[package]] name = "heck" @@ -829,9 +848,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "iana-time-zone" -version = "0.1.64" +version = "0.1.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -899,9 +918,9 @@ checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" dependencies = [ "icu_collections", "icu_locale_core", @@ -913,9 +932,9 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" [[package]] name = "icu_provider" @@ -934,9 +953,9 @@ dependencies = [ [[package]] name = "id-arena" -version = "2.2.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" [[package]] name = "idna" @@ -1024,9 +1043,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "ittapi" @@ -1060,9 +1079,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.82" +version = "0.3.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" +checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" dependencies = [ "once_cell", "wasm-bindgen", @@ -1088,21 +1107,21 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.177" +version = "0.2.182" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" +checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" [[package]] name = "libm" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" +checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" dependencies = [ "bitflags", "libc", @@ -1116,9 +1135,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" @@ -1128,9 +1147,9 @@ checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "log" -version = "0.4.28" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "logos" @@ -1182,9 +1201,9 @@ checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4" [[package]] name = "memchr" -version = "2.7.6" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "memfd" @@ -1192,14 +1211,14 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad38eb12aea514a0466ea40a80fd8cc83637065948eb4a426e4aa46261175227" dependencies = [ - "rustix 1.1.2", + "rustix 1.1.4", ] [[package]] name = "mio" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" dependencies = [ "libc", "wasi", @@ -1248,15 +1267,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - -[[package]] -name = "pin-utils" -version = "0.1.0" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pkg-config" @@ -1306,9 +1319,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.103" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] @@ -1323,33 +1336,32 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "serde", - "serde_json", "syn", "tempfile", + "trace", "wasmtime", "wasmtime-wasi", - "wit-bindgen-core", - "wit-component", + "wit-bindgen-core 0.53.1", + "wit-component 0.245.1", ] [[package]] name = "pulley-interpreter" -version = "41.0.3" +version = "42.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01051a5b172e07f9197b85060e6583b942aec679dac08416647bf7e7dc916b65" +checksum = "bc2d61e068654529dc196437f8df0981db93687fdc67dec6a5de92363120b9da" dependencies = [ "cranelift-bitset", "log", "pulley-macros", - "wasmtime-internal-math", + "wasmtime-internal-core", ] [[package]] name = "pulley-macros" -version = "41.0.3" +version = "42.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cf194f5b1a415ef3a44ee35056f4009092cc4038a9f7e3c7c1e392f48ee7dbb" +checksum = "c3f210c61b6ecfaebbba806b6d9113a222519d4e5cc4ab2d5ecca047bb7927ae" dependencies = [ "proc-macro2", "quote", @@ -1358,9 +1370,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.42" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" dependencies = [ "proc-macro2", ] @@ -1398,7 +1410,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", ] [[package]] @@ -1434,8 +1446,8 @@ dependencies = [ name = "recorder" version = "0.1.0" dependencies = [ - "serde", "serde_json", + "trace", "wit-bindgen 0.52.0", ] @@ -1445,16 +1457,16 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", "libredox", "thiserror 1.0.69", ] [[package]] name = "regalloc2" -version = "0.13.3" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e249c660440317032a71ddac302f25f1d5dff387667bcc3978d1f77aa31ac34" +checksum = "08effbc1fa53aaebff69521a5c05640523fab037b34a4a2c109506bc938246fa" dependencies = [ "allocator-api2", "bumpalo", @@ -1466,15 +1478,15 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.8" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "rustc-demangle" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" +checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" [[package]] name = "rustc-hash" @@ -1497,14 +1509,14 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.2" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ "bitflags", "errno", "libc", - "linux-raw-sys 0.11.0", + "linux-raw-sys 0.12.1", "windows-sys 0.61.2", ] @@ -1515,7 +1527,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fc84bf7e9aa16c4f2c758f27412dc9841341e16aa682d9c7ac308fe3ee12056" dependencies = [ "once_cell", - "rustix 1.1.2", + "rustix 1.1.4", ] [[package]] @@ -1526,9 +1538,9 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.20" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] name = "semver" @@ -1572,15 +1584,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.145" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa", "memchr", - "ryu", "serde", "serde_core", + "zmij", ] [[package]] @@ -1649,9 +1661,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" dependencies = [ "libc", "windows-sys 0.60.2", @@ -1671,9 +1683,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.110" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -1709,20 +1721,20 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.13.3" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df7f62577c25e07834649fc3b39fafdc597c0a3527dc1c60129201ccfcbaa50c" +checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" [[package]] name = "tempfile" -version = "3.23.0" +version = "3.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +checksum = "82a72c767771b47409d2345987fda8628641887d5466101319899796367354a0" dependencies = [ "fastrand", - "getrandom 0.3.4", + "getrandom 0.4.1", "once_cell", - "rustix 1.1.2", + "rustix 1.1.4", "windows-sys 0.61.2", ] @@ -1746,11 +1758,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 2.0.17", + "thiserror-impl 2.0.18", ] [[package]] @@ -1766,9 +1778,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", @@ -1787,9 +1799,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.48.0" +version = "1.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" +checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" dependencies = [ "bytes", "libc", @@ -1825,9 +1837,9 @@ dependencies = [ [[package]] name = "toml_parser" -version = "1.0.7+spec-1.1.0" +version = "1.0.9+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "247eaa3197818b831697600aadf81514e577e0cba5eab10f7e064e78ae154df1" +checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4" dependencies = [ "winnow", ] @@ -1838,11 +1850,19 @@ version = "1.0.6+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" +[[package]] +name = "trace" +version = "0.1.0" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "tracing" -version = "0.1.41" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "pin-project-lite", "tracing-attributes", @@ -1851,9 +1871,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", @@ -1862,9 +1882,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.34" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", ] @@ -1877,9 +1897,9 @@ checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "unicode-ident" -version = "1.0.22" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-width" @@ -1901,9 +1921,9 @@ checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" [[package]] name = "url" -version = "2.5.7" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", "idna", @@ -1925,9 +1945,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.18.1" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" +checksum = "b672338555252d43fd2240c714dc444b8c6fb0a5c5335e65a07bba7742735ddb" dependencies = [ "js-sys", "wasm-bindgen", @@ -1947,18 +1967,27 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.1+wasi-0.2.4" +version = "1.0.2+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +dependencies = [ + "wit-bindgen 0.51.0", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ - "wit-bindgen 0.46.0", + "wit-bindgen 0.51.0", ] [[package]] name = "wasm-bindgen" -version = "0.2.105" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" +checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e" dependencies = [ "cfg-if", "once_cell", @@ -1969,9 +1998,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.105" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" +checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1979,9 +2008,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.105" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" +checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3" dependencies = [ "bumpalo", "proc-macro2", @@ -1992,18 +2021,18 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.105" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" +checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16" dependencies = [ "unicode-ident", ] [[package]] name = "wasm-compose" -version = "0.243.0" +version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af801b6f36459023eaec63fdbaedad2fd5a4ab7dc74ecc110a8b5d375c5775e4" +checksum = "92cda9c76ca8dcac01a8b497860c2cb15cd6f216dc07060517df5abbe82512ac" dependencies = [ "anyhow", "heck", @@ -2015,21 +2044,11 @@ dependencies = [ "serde_derive", "serde_yaml", "smallvec", - "wasm-encoder 0.243.0", - "wasmparser 0.243.0", + "wasm-encoder 0.244.0", + "wasmparser 0.244.0", "wat", ] -[[package]] -name = "wasm-encoder" -version = "0.243.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c55db9c896d70bd9fa535ce83cd4e1f2ec3726b0edd2142079f594fc3be1cb35" -dependencies = [ - "leb128fmt", - "wasmparser 0.243.0", -] - [[package]] name = "wasm-encoder" version = "0.244.0" @@ -2042,12 +2061,12 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.245.0" +version = "0.245.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95d568e113f706ee7a7df9b33547bb80721f55abffc79b3dc4d09c368690e662" +checksum = "3f9dca005e69bf015e45577e415b9af8c67e8ee3c0e38b5b0add5aa92581ed5c" dependencies = [ "leb128fmt", - "wasmparser 0.245.0", + "wasmparser 0.245.1", ] [[package]] @@ -2063,28 +2082,26 @@ dependencies = [ ] [[package]] -name = "wasm-wave" -version = "0.243.0" +name = "wasm-metadata" +version = "0.245.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bd23c879ec35d708f4eff3456f33c415d113363a2e38420098bf42976bacb31" +checksum = "da55e60097e8b37b475a0fa35c3420dd71d9eb7bd66109978ab55faf56a57efb" dependencies = [ + "anyhow", "indexmap", - "logos", - "thiserror 2.0.17", - "wit-parser 0.243.0", + "wasm-encoder 0.245.1", + "wasmparser 0.245.1", ] [[package]] -name = "wasmparser" -version = "0.243.0" +name = "wasm-wave" +version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6d8db401b0528ec316dfbe579e6ab4152d61739cfe076706d2009127970159d" +checksum = "d1c34a4c10a1b9260f8131929d680e36edf00836bb8e76524d3004522bd6f287" dependencies = [ - "bitflags", - "hashbrown 0.15.5", - "indexmap", - "semver", - "serde", + "logos", + "thiserror 2.0.18", + "wit-parser 0.244.0", ] [[package]] @@ -2097,38 +2114,39 @@ dependencies = [ "hashbrown 0.15.5", "indexmap", "semver", + "serde", ] [[package]] name = "wasmparser" -version = "0.245.0" +version = "0.245.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48a767a48974f0c8b66f211b96e01aa77feed58b8ccce4e7f0cff0ae55b174d4" +checksum = "4f08c9adee0428b7bddf3890fc27e015ac4b761cc608c822667102b8bfd6995e" dependencies = [ "bitflags", + "hashbrown 0.16.1", "indexmap", "semver", ] [[package]] name = "wasmprinter" -version = "0.243.0" +version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb2b6035559e146114c29a909a3232928ee488d6507a1504d8934e8607b36d7b" +checksum = "09390d7b2bd7b938e563e4bff10aa345ef2e27a3bc99135697514ef54495e68f" dependencies = [ "anyhow", "termcolor", - "wasmparser 0.243.0", + "wasmparser 0.244.0", ] [[package]] name = "wasmtime" -version = "41.0.3" +version = "42.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19f56cece843fa95dd929f5568ff8739c7e3873b530ceea9eda2aa02a0b4142" +checksum = "39bef52be4fb4c5b47d36f847172e896bc94b35c9c6a6f07117686bd16ed89a7" dependencies = [ "addr2line", - "anyhow", "async-trait", "bitflags", "bumpalo", @@ -2138,8 +2156,6 @@ dependencies = [ "futures", "fxprof-processed-profile", "gimli", - "hashbrown 0.15.5", - "indexmap", "ittapi", "libc", "log", @@ -2150,7 +2166,7 @@ dependencies = [ "postcard", "pulley-interpreter", "rayon", - "rustix 1.1.2", + "rustix 1.1.4", "semver", "serde", "serde_derive", @@ -2159,19 +2175,18 @@ dependencies = [ "target-lexicon", "tempfile", "wasm-compose", - "wasm-encoder 0.243.0", + "wasm-encoder 0.244.0", "wasm-wave", - "wasmparser 0.243.0", + "wasmparser 0.244.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-math", - "wasmtime-internal-slab", "wasmtime-internal-unwinder", "wasmtime-internal-versioned-export-macros", "wasmtime-internal-winch", @@ -2181,15 +2196,16 @@ dependencies = [ [[package]] name = "wasmtime-environ" -version = "41.0.3" +version = "42.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bf9dff572c950258548cbbaf39033f68f8dcd0b43b22e80def9fe12d532d3e5" +checksum = "bb637d5aa960ac391ca5a4cbf3e45807632e56beceeeb530e14dfa67fdfccc62" dependencies = [ "anyhow", "cpp_demangle", "cranelift-bitset", "cranelift-entity", "gimli", + "hashbrown 0.15.5", "indexmap", "log", "object", @@ -2200,23 +2216,24 @@ dependencies = [ "serde_derive", "smallvec", "target-lexicon", - "wasm-encoder 0.243.0", - "wasmparser 0.243.0", + "wasm-encoder 0.244.0", + "wasmparser 0.244.0", "wasmprinter", "wasmtime-internal-component-util", + "wasmtime-internal-core", ] [[package]] name = "wasmtime-internal-cache" -version = "41.0.3" +version = "42.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f52a985f5b5dae53147fc596f3a313c334e2c24fd1ba708634e1382f6ecd727" +checksum = "4ab6c428c610ae3e7acd25ca2681b4d23672c50d8769240d9dda99b751d4deec" dependencies = [ "base64", "directories-next", "log", "postcard", - "rustix 1.1.2", + "rustix 1.1.4", "serde", "serde_derive", "sha2", @@ -2228,9 +2245,9 @@ dependencies = [ [[package]] name = "wasmtime-internal-component-macro" -version = "41.0.3" +version = "42.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7920dc7dcb608352f5fe93c52582e65075b7643efc5dac3fc717c1645a8d29a0" +checksum = "ca768b11d5e7de017e8c3d4d444da6b4ce3906f565bcbc253d76b4ecbb5d2869" dependencies = [ "anyhow", "proc-macro2", @@ -2238,20 +2255,30 @@ dependencies = [ "syn", "wasmtime-internal-component-util", "wasmtime-internal-wit-bindgen", - "wit-parser 0.243.0", + "wit-parser 0.244.0", ] [[package]] name = "wasmtime-internal-component-util" -version = "41.0.3" +version = "42.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "066f5aed35aa60580a2ac0df145c0f0d4b04319862fee1d6036693e1cca43a12" +checksum = "763f504faf96c9b409051e96a1434655eea7f56a90bed9cb1e22e22c941253fd" + +[[package]] +name = "wasmtime-internal-core" +version = "42.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a4a3f055a804a2f3d86e816a9df78a8fa57762212a8506164959224a40cd48" +dependencies = [ + "anyhow", + "libm", +] [[package]] name = "wasmtime-internal-cranelift" -version = "41.0.3" +version = "42.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb8002dc415b7773d7949ee360c05ee8f91627ec25a7a0b01ee03831bdfdda1" +checksum = "55154a91d22ad51f9551124ce7fb49ddddc6a82c4910813db4c790c97c9ccf32" dependencies = [ "cfg-if", "cranelift-codegen", @@ -2266,24 +2293,24 @@ dependencies = [ "pulley-interpreter", "smallvec", "target-lexicon", - "thiserror 2.0.17", - "wasmparser 0.243.0", + "thiserror 2.0.18", + "wasmparser 0.244.0", "wasmtime-environ", - "wasmtime-internal-math", + "wasmtime-internal-core", "wasmtime-internal-unwinder", "wasmtime-internal-versioned-export-macros", ] [[package]] name = "wasmtime-internal-fiber" -version = "41.0.3" +version = "42.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9c562c5a272bc9f615d8f0c085a4360bafa28eef9aa5947e63d204b1129b22" +checksum = "05decfad1021ad2efcca5c1be9855acb54b6ee7158ac4467119b30b7481508e3" dependencies = [ "cc", "cfg-if", "libc", - "rustix 1.1.2", + "rustix 1.1.4", "wasmtime-environ", "wasmtime-internal-versioned-export-macros", "windows-sys 0.61.2", @@ -2291,48 +2318,33 @@ dependencies = [ [[package]] name = "wasmtime-internal-jit-debug" -version = "41.0.3" +version = "42.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db673148f26e1211db3913c12c75594be9e3858a71fa297561e9162b1a49cfb0" +checksum = "924980c50427885fd4feed2049b88380178e567768aaabf29045b02eb262eaa7" dependencies = [ "cc", "object", - "rustix 1.1.2", + "rustix 1.1.4", "wasmtime-internal-versioned-export-macros", ] [[package]] name = "wasmtime-internal-jit-icache-coherence" -version = "41.0.3" +version = "42.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bada5ca1cc47df7d14100e2254e187c2486b426df813cea2dd2553a7469f7674" +checksum = "c57d24e8d1334a0e5a8b600286ffefa1fc4c3e8176b110dff6fbc1f43c4a599b" dependencies = [ - "anyhow", "cfg-if", "libc", + "wasmtime-internal-core", "windows-sys 0.61.2", ] -[[package]] -name = "wasmtime-internal-math" -version = "41.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf6f615d528eda9adc6eefb062135f831b5215c348f4c3ec3e143690c730605b" -dependencies = [ - "libm", -] - -[[package]] -name = "wasmtime-internal-slab" -version = "41.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da169d4f789b586e1b2612ba8399c653ed5763edf3e678884ba785bb151d018f" - [[package]] name = "wasmtime-internal-unwinder" -version = "41.0.3" +version = "42.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4888301f3393e4e8c75c938cce427293fade300fee3fc8fd466fdf3e54ae068e" +checksum = "3a1a144bd4393593a868ba9df09f34a6a360cb5db6e71815f20d3f649c6e6735" dependencies = [ "cfg-if", "cranelift-codegen", @@ -2343,9 +2355,9 @@ dependencies = [ [[package]] name = "wasmtime-internal-versioned-export-macros" -version = "41.0.3" +version = "42.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63ba3124cc2cbcd362672f9f077303ccc4cd61daa908f73447b7fdaece75ff9f" +checksum = "9a6948b56bb00c62dbd205ea18a4f1ceccbe1e4b8479651fdb0bab2553790f20" dependencies = [ "proc-macro2", "quote", @@ -2354,16 +2366,16 @@ dependencies = [ [[package]] name = "wasmtime-internal-winch" -version = "41.0.3" +version = "42.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90a4182515dabba776656de4ebd62efad03399e261cf937ecccb838ce8823534" +checksum = "9130b3ab6fb01be80b27b9a2c84817af29ae8224094f2503d2afa9fea5bf9d00" dependencies = [ "cranelift-codegen", "gimli", "log", "object", "target-lexicon", - "wasmparser 0.243.0", + "wasmparser 0.244.0", "wasmtime-environ", "wasmtime-internal-cranelift", "winch-codegen", @@ -2371,24 +2383,23 @@ dependencies = [ [[package]] name = "wasmtime-internal-wit-bindgen" -version = "41.0.3" +version = "42.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87acbd416227cdd279565ba49e57cf7f08d112657c3b3f39b70250acdfd094fe" +checksum = "102d0d70dbfede00e4cc9c24e86df6d32c03bf6f5ad06b5d6c76b0a4a5004c4a" dependencies = [ "anyhow", "bitflags", "heck", "indexmap", - "wit-parser 0.243.0", + "wit-parser 0.244.0", ] [[package]] name = "wasmtime-wasi" -version = "41.0.3" +version = "42.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9a1bdb4948463ed22559a640e687fed0df50b66353144aa6a9496c041ecd927" +checksum = "ea938f6f4f11e5ffe6d8b6f34c9a994821db9511c3e9c98e535896f27d06bb92" dependencies = [ - "anyhow", "async-trait", "bitflags", "bytes", @@ -2401,9 +2412,9 @@ dependencies = [ "futures", "io-extras", "io-lifetimes", - "rustix 1.1.2", + "rustix 1.1.4", "system-interface", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tracing", "url", @@ -2415,14 +2426,14 @@ dependencies = [ [[package]] name = "wasmtime-wasi-io" -version = "41.0.3" +version = "42.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7873d8b990d3cf1105ef491abf2b3cf1e19ff6722d24d5ca662026ea082cdff" +checksum = "71cb16a88d0443b509d6eca4298617233265179090abf03e0a8042b9b251e9da" dependencies = [ - "anyhow", "async-trait", "bytes", "futures", + "tracing", "wasmtime", ] @@ -2437,59 +2448,59 @@ dependencies = [ [[package]] name = "wast" -version = "245.0.0" +version = "245.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75ffc7471e16a6f3c7a3c3a230314915b5dcd158e5ef13ccda2f43358a9df00c" +checksum = "28cf1149285569120b8ce39db8b465e8a2b55c34cbb586bd977e43e2bc7300bf" dependencies = [ "bumpalo", "leb128fmt", "memchr", "unicode-width", - "wasm-encoder 0.245.0", + "wasm-encoder 0.245.1", ] [[package]] name = "wat" -version = "1.245.0" +version = "1.245.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bcac6f915e2a84a4c0d9df9d41ad7518d99cda13f3bb83e3b8c22bf8726ab6" +checksum = "cd48d1679b6858988cb96b154dda0ec5bbb09275b71db46057be37332d5477be" dependencies = [ - "wast 245.0.0", + "wast 245.0.1", ] [[package]] name = "wiggle" -version = "41.0.3" +version = "42.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f05d2a9932ca235984248dc98471ae83d1985e095682d049af4c296f54f0fb4" +checksum = "2dca2bf96d20f0c70e6741cc6c8c1a9ee4c3c0310c7ad1971242628c083cc9a5" dependencies = [ - "anyhow", "bitflags", - "thiserror 2.0.17", + "thiserror 2.0.18", "tracing", "wasmtime", + "wasmtime-environ", "wiggle-macro", ] [[package]] name = "wiggle-generate" -version = "41.0.3" +version = "42.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57f773d51c1696bd7d028aa35c884d9fc58f48d79a1176dfbad6c908de314235" +checksum = "d0d8c016d6d3ec6dc6b8c80c23cede4ee2386ccf347d01984f7991d7659f73ef" dependencies = [ - "anyhow", "heck", "proc-macro2", "quote", "syn", + "wasmtime-environ", "witx", ] [[package]] name = "wiggle-macro" -version = "41.0.3" +version = "42.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e976fe0cecd60041f66b15ad45ebc997952af13da9bf9d90261c7b025057edc" +checksum = "91a267096e48857096f035fffca29e22f0bbe840af4d74a6725eb695e1782110" dependencies = [ "proc-macro2", "quote", @@ -2530,22 +2541,21 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "winch-codegen" -version = "41.0.3" +version = "42.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4f31dcfdfaf9d6df9e1124d7c8ee6fc29af5b99b89d11ae731c138e0f5bd77b" +checksum = "1977857998e4dd70d26e2bfc0618a9684a2fb65b1eca174dc13f3b3e9c2159ca" dependencies = [ - "anyhow", "cranelift-assembler-x64", "cranelift-codegen", "gimli", "regalloc2", "smallvec", "target-lexicon", - "thiserror 2.0.17", - "wasmparser 0.243.0", + "thiserror 2.0.18", + "wasmparser 0.244.0", "wasmtime-environ", + "wasmtime-internal-core", "wasmtime-internal-cranelift", - "wasmtime-internal-math", ] [[package]] @@ -2765,9 +2775,9 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winnow" -version = "0.7.13" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" [[package]] name = "winx" @@ -2781,9 +2791,12 @@ dependencies = [ [[package]] name = "wit-bindgen" -version = "0.46.0" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro 0.51.0", +] [[package]] name = "wit-bindgen" @@ -2792,7 +2805,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e048f41ef90f0b5dd61f1059c35f5636252e56813bf616d0803aa3739867230" dependencies = [ "bitflags", - "wit-bindgen-rust-macro", + "wit-bindgen-rust-macro 0.52.0", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser 0.244.0", ] [[package]] @@ -2806,6 +2830,33 @@ dependencies = [ "wit-parser 0.244.0", ] +[[package]] +name = "wit-bindgen-core" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3deda4b7e9f522d994906f6e6e0fc67965ea8660306940a776b76732be8f3933" +dependencies = [ + "anyhow", + "heck", + "wit-parser 0.245.1", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn", + "wasm-metadata 0.244.0", + "wit-bindgen-core 0.51.0", + "wit-component 0.244.0", +] + [[package]] name = "wit-bindgen-rust" version = "0.52.0" @@ -2817,9 +2868,24 @@ dependencies = [ "indexmap", "prettyplease", "syn", - "wasm-metadata", - "wit-bindgen-core", - "wit-component", + "wasm-metadata 0.244.0", + "wit-bindgen-core 0.52.0", + "wit-component 0.244.0", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core 0.51.0", + "wit-bindgen-rust 0.51.0", ] [[package]] @@ -2833,8 +2899,8 @@ dependencies = [ "proc-macro2", "quote", "syn", - "wit-bindgen-core", - "wit-bindgen-rust", + "wit-bindgen-core 0.52.0", + "wit-bindgen-rust 0.52.0", ] [[package]] @@ -2851,16 +2917,35 @@ dependencies = [ "serde_derive", "serde_json", "wasm-encoder 0.244.0", - "wasm-metadata", + "wasm-metadata 0.244.0", "wasmparser 0.244.0", "wit-parser 0.244.0", ] +[[package]] +name = "wit-component" +version = "0.245.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4894f10d2d5cbc17c77e91f86a1e48e191a788da4425293b55c98b44ba3fcac9" +dependencies = [ + "anyhow", + "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder 0.245.1", + "wasm-metadata 0.245.1", + "wasmparser 0.245.1", + "wit-parser 0.245.1", +] + [[package]] name = "wit-parser" -version = "0.243.0" +version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df983a8608e513d8997f435bb74207bf0933d0e49ca97aa9d8a6157164b9b7fc" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" dependencies = [ "anyhow", "id-arena", @@ -2871,16 +2956,17 @@ dependencies = [ "serde_derive", "serde_json", "unicode-xid", - "wasmparser 0.243.0", + "wasmparser 0.244.0", ] [[package]] name = "wit-parser" -version = "0.244.0" +version = "0.245.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +checksum = "330698718e82983499419494dd1e3d7811a457a9bf9f69734e8c5f07a2547929" dependencies = [ "anyhow", + "hashbrown 0.16.1", "id-arena", "indexmap", "log", @@ -2889,7 +2975,7 @@ dependencies = [ "serde_derive", "serde_json", "unicode-xid", - "wasmparser 0.244.0", + "wasmparser 0.245.1", ] [[package]] @@ -2935,18 +3021,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.27" +version = "0.8.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" +checksum = "a789c6e490b576db9f7e6b6d661bcc9799f7c0ac8352f56ea20193b2681532e5" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.27" +version = "0.8.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +checksum = "f65c489a7071a749c849713807783f70672b28094011623e200cb86dcb835953" dependencies = [ "proc-macro2", "quote", @@ -3007,6 +3093,12 @@ dependencies = [ "syn", ] +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + [[package]] name = "zstd" version = "0.13.3" diff --git a/Cargo.toml b/Cargo.toml index 4e6b25c..c57f860 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,9 +2,11 @@ members = [ "components/debug", "components/recorder" -] +, "crates/trace"] [workspace.dependencies] wit-bindgen = { version = "0.52.0", default-features = false, features = ["bitflags", "std", "macros"] } +serde = { version = "1.0.226", features = ["derive"] } +serde_json = "1.0.145" [package] name = "proxy-component" @@ -12,23 +14,20 @@ version = "0.1.0" edition = "2024" [dependencies] +trace = { path = "crates/trace" } anyhow = "1.0.98" clap = { version = "4.5.40", features = ["derive"] } heck = "0.5.0" prettyplease = "0.2.37" quote = "1.0.41" proc-macro2 = "1.0.103" -serde = "1.0.226" -serde_json = "1.0.145" syn = { version = "2.0.108", features = ["visit-mut"] } tempfile = "3.20.0" -#wit-bindgen-core = { git = "https://github.com/chenyan2002/wit-bindgen.git", branch = "proxy" } -#wit-bindgen-rust = { git = "https://github.com/chenyan2002/wit-bindgen.git", branch = "proxy" } -wit-bindgen-core = "0.52.0" -wit-component = "0.244.0" +wit-bindgen-core = "0.53.1" +wit-component = "0.245.0" -wasmtime = { version = "41.0.0", features = ["wave"], optional = true } -wasmtime-wasi = { version = "41.0.0", optional = true } +wasmtime = { version = "42.0.0", features = ["wave"], optional = true } +wasmtime-wasi = { version = "42.0.0", optional = true } [features] run = ["wasmtime", "wasmtime-wasi"] diff --git a/Makefile b/Makefile index 793d55a..8fa07f1 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ all: build-components build-cli build-cli: - cargo build --release + cargo build --all-features --release build-components: cargo build -p debug --target wasm32-wasip2 --release cargo build -p recorder --target wasm32-wasip2 --release @@ -31,6 +31,9 @@ run-record: $(MAKE) run-viceroy URL=localhost:7676 target/release/proxy-component instrument -m replay $(WASM) wasmtime --invoke 'start()' composed.wasm < trace.out + # test host replay + target/release/proxy-component instrument -m replay --use-host-recorder $(WASM) + target/release/proxy-component run composed.wasm --invoke 'start()' --trace trace.out run-viceroy: viceroy composed.wasm > trace.out & echo $$! > viceroy.pid diff --git a/assets/debug.wasm b/assets/debug.wasm index adde5e1..d22efa2 100644 Binary files a/assets/debug.wasm and b/assets/debug.wasm differ diff --git a/assets/recorder.wasm b/assets/recorder.wasm index 1c121f2..3a7c079 100644 Binary files a/assets/recorder.wasm and b/assets/recorder.wasm differ diff --git a/components/recorder/Cargo.toml b/components/recorder/Cargo.toml index 0ba2fb8..e64a57a 100644 --- a/components/recorder/Cargo.toml +++ b/components/recorder/Cargo.toml @@ -7,6 +7,6 @@ edition = "2024" crate-type = ["cdylib"] [dependencies] +trace = { path = "../../crates/trace" } +serde_json.workspace = true wit-bindgen.workspace = true -serde = { version = "1.0.226", features = ["derive"] } -serde_json = "1.0.145" diff --git a/components/recorder/src/lib.rs b/components/recorder/src/lib.rs index 1ac37aa..8566a28 100644 --- a/components/recorder/src/lib.rs +++ b/components/recorder/src/lib.rs @@ -4,56 +4,39 @@ mod bindings { world: "guest", }); } -mod trace; -use trace::FuncCall; +use trace::Logger; struct Component; impl bindings::exports::proxy::recorder::record::Guest for Component { fn record_args(method: Option, args: Vec, is_export: bool) { - let call = if is_export { - FuncCall::ExportArgs { - method: method.unwrap(), - args, - } - } else { - FuncCall::ImportArgs { method, args } - }; + let mut logger = Logger::new(); + let call = logger.record_args(method, args, is_export); let json = serde_json::to_string(&call).unwrap(); println!("{json}"); } fn record_ret(method: Option, ret: Option, is_export: bool) { - let call = if is_export { - FuncCall::ExportRet { method, ret } - } else { - FuncCall::ImportRet { method, ret } - }; + let mut logger = Logger::new(); + let call = logger.record_ret(method, ret, is_export); let json = serde_json::to_string(&call).unwrap(); println!("{json}"); } } use std::cell::RefCell; -use std::collections::VecDeque; thread_local! { - static TRACE: RefCell>> = RefCell::new(None); + static TRACE: RefCell> = RefCell::new(None); } fn load_trace() { let load = TRACE.with_borrow(|v| v.is_none()); if load { TRACE.with_borrow_mut(|v| { - use std::io::BufRead; - let mut res = VecDeque::new(); - let f = std::io::stdin(); - let reader = std::io::BufReader::new(f); - for line in reader.lines() { - let line = line.unwrap(); - match serde_json::from_str::(&line) { - Ok(item) => res.push_back(item), - Err(_) => continue, - } - } - *v = Some(res); + use std::io::Read; + let mut input = String::new(); + std::io::stdin().read_to_string(&mut input).unwrap(); + let mut logger = Logger::new(); + logger.load_trace(&input); + *v = Some(logger); }); } } @@ -61,28 +44,13 @@ fn load_trace() { impl bindings::exports::proxy::recorder::replay::Guest for Component { fn replay_export() -> Option<(String, Vec)> { load_trace(); - TRACE.with_borrow_mut(|v| { - let call = v.as_mut().unwrap().pop_front()?; - println!("export call: {}", call.to_string()); - let FuncCall::ExportArgs { method, args } = call else { - panic!() - }; - Some((method, args)) - }) + TRACE.with_borrow_mut(|v| v.as_mut().unwrap().replay_export()) } fn assert_export_ret(assert_method: Option, assert_ret: Option) { TRACE.with_borrow_mut(|v| { - if let Some(FuncCall::ExportRet { .. }) = v.as_mut().unwrap().front() { - let call = v.as_mut().unwrap().pop_front().unwrap(); - println!("export ret: {}", call.to_string()); - let FuncCall::ExportRet { method, ret } = call else { - panic!() - }; - if let (Some(method), Some(assert_method)) = (method, assert_method) { - assert_eq!(method, assert_method); - } - assert_eq!(ret, assert_ret); - } + v.as_mut() + .unwrap() + .assert_export_ret(assert_method, assert_ret) }); } fn replay_import( @@ -90,34 +58,10 @@ impl bindings::exports::proxy::recorder::replay::Guest for Component { assert_args: Option>, ) -> Option { TRACE.with_borrow_mut(|v| { - let mut call = v.as_mut().unwrap().pop_front().unwrap(); - if let FuncCall::ImportArgs { method, args } = &call { - if let (Some(method), Some(assert_method)) = (method, assert_method) { - assert_eq!(method, &assert_method); - } - if let Some(assert_args) = &assert_args { - assert_eq!(args, assert_args); - } - println!("import call: {}", call.to_string()); - if method - .as_ref() - .is_some_and(|m| m.starts_with("wasi:cli/exit")) - { - let code = if assert_args - .is_some_and(|args| args.get(0).is_some_and(|arg| arg.starts_with("err"))) - { - 1 - } else { - 0 - }; - std::process::exit(code); - } - call = v.as_mut().unwrap().pop_front().unwrap(); - } - println!("import ret: {}", call.to_string()); - let FuncCall::ImportRet { ret, .. } = call else { - panic!() - }; + let (_, ret) = v + .as_mut() + .unwrap() + .replay_import(assert_method, assert_args, true); ret }) } diff --git a/components/recorder/src/trace.rs b/components/recorder/src/trace.rs deleted file mode 100644 index 14aeb8e..0000000 --- a/components/recorder/src/trace.rs +++ /dev/null @@ -1,36 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Serialize, Deserialize, Debug)] -pub enum FuncCall { - ExportArgs { - method: String, - args: Vec, - }, - ExportRet { - method: Option, - ret: Option, - }, - ImportArgs { - method: Option, - args: Vec, - }, - ImportRet { - method: Option, - ret: Option, - }, -} -impl FuncCall { - pub fn to_string(&self) -> String { - match self { - FuncCall::ExportArgs { method, args } => format!("{method}({})", args.join(", ")), - FuncCall::ImportArgs { method, args } => format!( - "{}({})", - method.as_deref().unwrap_or(""), - args.join(", ") - ), - FuncCall::ExportRet { ret, .. } | FuncCall::ImportRet { ret, .. } => { - ret.as_deref().unwrap_or("()").to_owned() - } - } - } -} diff --git a/crates/trace/Cargo.toml b/crates/trace/Cargo.toml new file mode 100644 index 0000000..fb4614b --- /dev/null +++ b/crates/trace/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "trace" +version = "0.1.0" +edition = "2024" + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/crates/trace/src/lib.rs b/crates/trace/src/lib.rs new file mode 100644 index 0000000..e263552 --- /dev/null +++ b/crates/trace/src/lib.rs @@ -0,0 +1,158 @@ +use std::collections::VecDeque; + +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub enum FuncCall { + ExportArgs { + method: String, + args: Vec, + }, + ExportRet { + method: Option, + ret: Option, + }, + ImportArgs { + method: Option, + args: Vec, + }, + ImportRet { + method: Option, + ret: Option, + }, +} + +pub struct Logger(pub VecDeque); + +impl Logger { + pub fn new() -> Self { + Self(VecDeque::new()) + } + pub fn load_trace(&mut self, text: &str) { + self.0.clear(); + for line in text.lines() { + match serde_json::from_str::(line) { + Ok(item) => self.0.push_back(item), + // Ignore non-JSON lines. + Err(_) => continue, + } + } + } + pub fn dump_trace(&self) -> String { + self.0 + .iter() + .map(|call| serde_json::to_string(call).unwrap()) + .collect::>() + .join("\n") + } + pub fn record_args( + &mut self, + method: Option, + args: Vec, + is_export: bool, + ) -> FuncCall { + let call = if is_export { + FuncCall::ExportArgs { + method: method.unwrap(), + args, + } + } else { + FuncCall::ImportArgs { method, args } + }; + self.0.push_back(call.clone()); + call + } + pub fn record_ret( + &mut self, + method: Option, + ret: Option, + is_export: bool, + ) -> FuncCall { + let call = if is_export { + FuncCall::ExportRet { method, ret } + } else { + FuncCall::ImportRet { method, ret } + }; + self.0.push_back(call.clone()); + call + } + pub fn replay_export(&mut self) -> Option<(String, Vec)> { + let call = self.0.pop_front()?; + println!("export call: {}", call.to_string()); + let FuncCall::ExportArgs { method, args } = call else { + panic!() + }; + Some((method, args)) + } + pub fn assert_export_ret(&mut self, assert_method: Option, assert_ret: Option) { + if let Some(FuncCall::ExportRet { .. }) = self.0.front() { + let call = self.0.pop_front().unwrap(); + println!("export ret: {}", call.to_string()); + let FuncCall::ExportRet { method, ret } = call else { + panic!() + }; + if let (Some(method), Some(assert_method)) = (method, assert_method) { + assert_eq!(method, assert_method); + } + assert_eq!(ret, assert_ret); + } + } + pub fn replay_import( + &mut self, + assert_method: Option, + assert_args: Option>, + from_guest: bool, + ) -> (bool, Option) { + let mut exit_called = false; + let mut call = self.0.pop_front().unwrap(); + if let FuncCall::ImportArgs { method, args } = &call { + if let (Some(method), Some(assert_method)) = (method, assert_method) { + assert_eq!(method, &assert_method); + } + if let Some(assert_args) = &assert_args { + assert_eq!(args, assert_args); + } + println!("import call: {}", call.to_string()); + if method + .as_ref() + .is_some_and(|m| m.starts_with("wasi:cli/exit")) + { + if from_guest { + let code = if assert_args + .is_some_and(|args| args.get(0).is_some_and(|arg| arg.starts_with("err"))) + { + 1 + } else { + 0 + }; + std::process::exit(code); + } else { + exit_called = true; + return (exit_called, Some("Something that can crash".to_string())); + } + } + call = self.0.pop_front().unwrap(); + } + println!("import ret: {}", call.to_string()); + let FuncCall::ImportRet { ret, .. } = call else { + panic!() + }; + (exit_called, ret) + } +} + +impl FuncCall { + pub fn to_string(&self) -> String { + match self { + FuncCall::ExportArgs { method, args } => format!("{method}({})", args.join(", ")), + FuncCall::ImportArgs { method, args } => format!( + "{}({})", + method.as_deref().unwrap_or(""), + args.join(", ") + ), + FuncCall::ExportRet { ret, .. } | FuncCall::ImportRet { ret, .. } => { + ret.as_deref().unwrap_or("()").to_owned() + } + } + } +} diff --git a/src/codegen.rs b/src/codegen.rs deleted file mode 100644 index 129788c..0000000 --- a/src/codegen.rs +++ /dev/null @@ -1,530 +0,0 @@ -use crate::util::{ - FullTypePath, ResourceFuncKind, extract_arg_info, get_owned_type, get_resource_from_trait_name, - get_return_type, make_path, wit_func_name, -}; -use anyhow::Result; -use quote::quote; -use std::collections::{BTreeMap, BTreeSet}; -use std::path::PathBuf; -use syn::{ - File, Ident, Item, ItemEnum, ItemStruct, ItemTrait, Signature, TraitItem, parse_quote, - visit_mut::VisitMut, -}; - -#[derive(clap::Parser)] -pub struct GenerateArgs { - /// The path to the binding file generated by wit-bindgen. - pub bindings: PathBuf, - /// Specifies the type of the WIT component. - pub mode: GenerateMode, - /// The path to the output file. - #[arg(short, long, default_value("lib.rs"))] - pub output_file: PathBuf, -} -#[derive(clap::ValueEnum, clap::Parser, Clone)] -pub enum GenerateMode { - /// An arbitrary component, we can only generate an empty stub. - Stubs, - /// An instrument component which imports and exports the same interface. - /// The generated code will redirect the export interface to call the corresponding import interface. - Instrument, - /// An instrument component which records all import calls. - Record, - /// A virtualized component with no imports, with implementation for replay. - Replay, - /// A virtualized component with no imports, with implementation for fuzzing. - Fuzz, -} -impl GenerateMode { - pub fn is_instrument(&self) -> bool { - matches!(self, GenerateMode::Instrument | GenerateMode::Record) - } -} - -pub struct State { - pub mode: GenerateMode, - pub traits: BTreeMap, Vec>, - pub types: BTreeMap, Vec>, - pub funcs: BTreeMap, BTreeMap, Vec>>, - pub module_paths: BTreeSet>, - pub output: Vec, -} -pub enum TypeInfo { - Struct(ItemStruct), - Enum(ItemEnum), - Resource(ItemStruct), - Flag(ItemFlag), -} -pub struct ItemFlag { - pub name: Ident, - pub flags: Vec, -} - -impl GenerateArgs { - pub fn generate(&self) -> Result<()> { - let file = std::fs::read_to_string(&self.bindings)?; - let ast = syn::parse_file(&file)?; - - let mut state = State { - mode: self.mode.clone(), - traits: BTreeMap::new(), - types: BTreeMap::new(), - funcs: BTreeMap::new(), - module_paths: BTreeSet::new(), - output: Vec::new(), - }; - state.generate_preamble(); - state.find_all_items(&ast.items, vec![]); - state.generate_stubs(); - let trait_generator = crate::traits::TraitGenerator::new(&state); - let traits = trait_generator.generate(); - drop(trait_generator); - state.output.extend(traits); - let file = state.into_output_file(); - let output = prettyplease::unparse(&file); - std::fs::write(&self.output_file, output)?; - Ok(()) - } -} -impl State { - fn generate_stubs(&mut self) { - for (module_path, traits) in &self.traits { - for trait_item in traits { - let impl_item = self.generate_impl_with_methods(trait_item, module_path); - self.output.push(impl_item); - } - } - } - fn generate_preamble(&mut self) { - let file: File = parse_quote! { - mod bindings; - use bindings::*; - struct Stub; - bindings::export!(Stub with_types_in bindings); - }; - self.output = file.items; - } - fn generate_impl_with_methods(&self, trait_item: &ItemTrait, module_path: &[String]) -> Item { - let trait_name = &trait_item.ident.to_string(); - let trait_path = make_path(module_path, trait_name); - let resource = get_resource_from_trait_name(trait_name); - let stub: syn::Path = match (&self.mode.is_instrument(), &resource) { - (true, Some(resource)) => { - let import_path = get_proxy_path(module_path); - make_path(&import_path, resource) - } - (false, Some(_)) => parse_quote! { MockedResource }, - (_, _) => parse_quote! { Stub }, - }; - // Collect all method signatures from the trait - let mut methods = Vec::new(); - for item in &trait_item.items { - match item { - TraitItem::Type(assoc_type) => { - let type_name = &assoc_type.ident; - let stub: syn::Path = if self.mode.is_instrument() { - let import_path = get_proxy_path(module_path); - make_path(&import_path, &type_name.to_string()) - } else { - parse_quote! { MockedResource } - }; - let impl_item = parse_quote! { - type #type_name = #stub; - }; - methods.push(syn::ImplItem::Type(impl_item)); - } - TraitItem::Fn(method) => { - if method.sig.ident.to_string().starts_with("_resource_") { - continue; - } - let mut sig = method.sig.clone(); - let mut transformer = FullTypePath { module_path }; - transformer.visit_signature_mut(&mut sig); - let stub_impl = match self.mode { - GenerateMode::Stubs => parse_quote! { - #[allow(unused_variables)] - #sig { - unimplemented!() - } - }, - GenerateMode::Instrument | GenerateMode::Record => { - if module_path.join("::") == "exports::proxy::conversion::conversion" { - self.generate_conversion_func(&sig) - } else { - self.generate_instrument_func(module_path, &sig, &resource) - } - } - GenerateMode::Replay => { - if module_path.join("::") == "exports::proxy::conversion::conversion" { - self.generate_conversion_func(&sig) - } else { - self.generate_replay_func(module_path, &sig, &resource) - } - } - GenerateMode::Fuzz => { - if module_path.join("::") == "exports::proxy::conversion::conversion" { - self.generate_conversion_func(&sig) - } else { - self.generate_fuzz_func(module_path, &sig, &resource) - } - } - }; - methods.push(syn::ImplItem::Fn(stub_impl)); - } - _ => (), - } - } - parse_quote! { - impl #trait_path for #stub { - #(#methods)* - } - } - } - fn generate_fuzz_func( - &self, - module_path: &[String], - sig: &Signature, - resource: &Option, - ) -> syn::ImplItemFn { - let func_name = &sig.ident; - let is_export = module_path.join("::") == "exports::proxy::recorder::start_replay"; - if !is_export { - let (kind, args) = extract_arg_info(sig); - let arg_names = args.iter().map(|arg| &arg.ident); - let display_name = wit_func_name(module_path, resource, func_name, &kind); - let ret_ty = get_return_type(&sig.output); - if ret_ty.is_some() { - parse_quote! { - #sig { - let mut __params: Vec = Vec::new(); - #( - __params.push(wasm_wave::to_string(&ToValue::to_value(&#arg_names)).unwrap()); - )* - let mut __buf = __params.join(","); - proxy::util::debug::print(&format!("import: {}({})", #display_name, __buf)); - __buf += #display_name; - let mut u = Unstructured::new(&__buf.as_bytes()); - let res = u.arbitrary().unwrap(); - let res_str = wasm_wave::to_string(&ToValue::to_value(&res)).unwrap(); - proxy::util::debug::print(&format!("ret: {}", res_str)); - res - } - } - } else { - parse_quote! { - #sig {} - } - } - } else { - assert!(func_name == "start"); - let arms: Vec<_> = self - .funcs - .iter() - .filter(|(path, _)| path[0] != "exports" && path[0] != "proxy") - .flat_map(|(path, resources)| { - resources.iter().flat_map(move |(resource, sigs)| { - sigs.iter().filter_map(move |sig| { - let (kind, args) = extract_arg_info(sig); - if matches!(kind, Some(ResourceFuncKind::Method)) { - return None; - } - let arg_name: Vec<_> = args.iter().map(|arg| &arg.ident).collect(); - let call_param = args.iter().map(|arg| arg.call_param()); - let ty = args.iter().map(|arg| { - let mut ty = arg.ty.clone(); - FullTypePath { module_path: path }.visit_type_mut(&mut ty); - if let Some(owned) = get_owned_type(&ty) { - owned - } else { - ty - } - }); - let func_name = if let Some(resource) = resource { - format!("{}::{}", resource, sig.ident) - } else { - sig.ident.to_string() - }; - let func = make_path(path, &func_name); - let display_name = wit_func_name(path, resource, &sig.ident, &kind); - Some(quote! { - { - let mut __params: Vec = Vec::new(); - #( - let #arg_name: #ty = u.arbitrary().unwrap(); - __params.push(wasm_wave::to_string(&ToValue::to_value(&#arg_name)).unwrap()); - )* - proxy::util::debug::print(&format!("export: {}({})", #display_name, __params.join(", "))); - let _ = #func(#(#call_param),*); - } - }) - }) - }) - }) - .collect(); - let func_len = arms.iter().len(); - let idxs = 1..=func_len; - parse_quote! { - #sig { - let __buf = proxy::util::debug::get_random(); - let mut u = Unstructured::new(&__buf); - for _ in 0..10 { - let idx = u.int_in_range(1..=#func_len).unwrap(); - match idx { - #(#idxs => #arms)* - _ => unreachable!(), - } - // clean up borrowed resources from input args - SCOPED_ALLOC.with(|alloc| { - alloc.borrow_mut().clear(); - }); - } - } - } - } - } - fn generate_replay_func( - &self, - module_path: &[String], - sig: &Signature, - resource: &Option, - ) -> syn::ImplItemFn { - let func_name = &sig.ident; - let is_export = module_path.join("::") == "exports::proxy::recorder::start_replay"; - if !is_export { - let (kind, args) = extract_arg_info(sig); - let arg_names = args.iter().map(|arg| &arg.ident); - let display_name = wit_func_name(module_path, resource, func_name, &kind); - let ret_ty = get_return_type(&sig.output); - let replay_import = if let Some(ret_ty) = ret_ty { - quote! { - let wave = proxy::recorder::replay::replay_import(Some(#display_name), Some(&args)).unwrap(); - let ret: Value = wasm_wave::from_str(&<#ret_ty as ValueTyped>::value_type(), &wave).unwrap(); - ret.to_rust() - } - } else { - quote! { - let wave = proxy::recorder::replay::replay_import(Some(#display_name), Some(&args)); - assert!(wave.is_none()); - } - }; - let self_value = if matches!(kind, Some(ResourceFuncKind::Method)) { - // Use ToValue::to_value to avoid the auto-deref from self.to_value() - quote! { wasm_wave::to_string(&ToValue::to_value(&self)).unwrap(), } - } else { - quote! {} - }; - parse_quote! { - #sig { - let args = vec![#self_value #( wasm_wave::to_string(&#arg_names.to_value()).unwrap() ),*]; - #replay_import - } - } - } else { - assert!(func_name == "start"); - let arms = self - .funcs - .iter() - .filter(|(path, _)| path[0] != "exports" && path[0] != "proxy") - .flat_map(|(path, resources)| { - resources.iter().flat_map(move |(resource, sigs)| { - sigs.iter().filter_map(move |sig| { - let (kind, args) = extract_arg_info(sig); - if matches!(kind, Some(ResourceFuncKind::Method)) { - return None; - } - let arg_name: Vec<_> = args.iter().map(|arg| &arg.ident).collect(); - let arg_idx = args.iter().enumerate().map(|(idx, _)| quote! { args[#idx] }); - let call_param = args.iter().map(|arg| arg.call_param()); - let ty = args.iter().map(|arg| { - let mut ty = arg.ty.clone(); - FullTypePath { - module_path: path, - }.visit_type_mut(&mut ty); - if let Some(owned) = get_owned_type(&ty) { - owned - } else { - ty - } - }); - let func_name = if let Some(resource) = resource { - format!("{}::{}", resource, sig.ident) - } else { - sig.ident.to_string() - }; - let func = make_path(path, &func_name); - let display_name = wit_func_name(path, resource, &sig.ident, &kind); - let assert_ret = if get_return_type(&sig.output).is_none() { - quote! { - assert!(res == ()); - proxy::recorder::replay::assert_export_ret(Some(#display_name), None); - } - } else { - quote! { - let wave_res = wasm_wave::to_string(&res.to_value()).unwrap(); - proxy::recorder::replay::assert_export_ret(Some(#display_name), Some(&wave_res)); - } - }; - Some(quote! { - #display_name => { - #( - let arg_value: Value = wasm_wave::from_str(&<#ty as ValueTyped>::value_type(), &#arg_idx).unwrap(); - let #arg_name: #ty = arg_value.to_rust(); - )* - let res = #func(#(#call_param),*); - #assert_ret - } - }) - }) - }) - }); - parse_quote! { - #sig { - while let Some((method, args)) = proxy::recorder::replay::replay_export() { - match method.as_str() { - #(#arms)* - _ => unreachable!(), - } - // clean up borrowed resources from input args - SCOPED_ALLOC.with(|alloc| { - alloc.borrow_mut().clear(); - }); - } - } - } - } - } - fn generate_instrument_func( - &self, - module_path: &[String], - sig: &Signature, - resource: &Option, - ) -> syn::ImplItemFn { - let func_name = &sig.ident; - let (kind, args) = extract_arg_info(sig); - let import_path = get_proxy_path(module_path); - let import_sig = self - .find_function(&import_path, resource, func_name) - .unwrap(); - let (_, import_args) = extract_arg_info(import_sig); - let arg_names = args.iter().map(|arg| &arg.ident); - let call_args = args - .iter() - .zip(import_args.iter()) - .map(|(arg, import_arg)| -> syn::Expr { - let ident = &arg.ident; - if import_arg.is_borrowed { - parse_quote! { &#ident } - } else { - parse_quote! { #ident } - } - }); - let (func, res): (syn::Expr, _) = match (resource.is_some(), &kind) { - (true, Some(ResourceFuncKind::Method)) => { - (parse_quote! { self.#func_name }, quote! { res.to_proxy() }) - } - (true, Some(ResourceFuncKind::Constructor)) => { - (parse_quote! { Self::#func_name }, quote! { res }) - } - (true, None) => (parse_quote! { Self::#func_name }, quote! { res.to_proxy() }), - (false, _) => ( - syn::parse_str(&format!("{}::{}", import_path.join("::"), func_name)).unwrap(), - quote! { res.to_proxy() }, - ), - }; - match &self.mode { - GenerateMode::Instrument => parse_quote! { - #sig { - let res = #func(#(#call_args.to_proxy()),*); - #res - } - }, - GenerateMode::Record => { - let init_vec = if matches!(kind, Some(ResourceFuncKind::Method)) { - quote! { vec![wasm_wave::to_string(&ToValue::to_value(&self)).unwrap()] } - } else { - quote! { Vec::new() } - }; - let is_mut = if args.is_empty() { - quote! {} - } else { - quote! { mut } - }; - let display_name = wit_func_name(module_path, resource, func_name, &kind); - let is_export = !module_path[1].starts_with("wrapped_"); - let record_ret = if get_return_type(&sig.output).is_none() { - quote! { - #func(#(#call_args),*); - proxy::recorder::record::record_ret(Some(#display_name), None, #is_export); - } - } else { - quote! { - let res = #func(#(#call_args),*); - let wave_res = wasm_wave::to_string(&res.to_value()).unwrap(); - proxy::recorder::record::record_ret(Some(#display_name), Some(&wave_res), #is_export); - #res - } - }; - parse_quote! { - #sig { - let #is_mut params: Vec = #init_vec; - #( - let #arg_names = #arg_names.to_proxy(); - params.push(wasm_wave::to_string(&ToValue::to_value(&#arg_names)).unwrap()); - )* - proxy::recorder::record::record_args(Some(#display_name), ¶ms, #is_export); - #record_ret - } - } - } - _ => unreachable!(), - } - } - fn generate_conversion_func(&self, sig: &Signature) -> syn::ImplItemFn { - let func_name = &sig.ident.to_string(); - let body = if func_name.starts_with("get_wrapped_") { - quote! { x.to_proxy() } - } else if func_name.starts_with("get_host_") { - quote! { x.to_proxy() } - } else if func_name.starts_with("get_mock_") { - let resource = get_return_type(&sig.output).unwrap(); - let name = func_name - .rfind("_magic42_") - .map(|idx| &func_name[idx + 9..]) - .unwrap(); - quote! { - #resource::new(MockedResource { handle, name: #name.to_string() }) - } - } else { - unreachable!() - }; - parse_quote! { - #sig { - #body - } - } - } - fn into_output_file(self) -> File { - File { - items: self.output, - shebang: None, - attrs: Vec::new(), - } - } -} - -pub fn get_proxy_path(src_path: &[String]) -> Vec { - assert!(src_path.len() >= 3); - let mut res = src_path.to_vec(); - let mut wrapped_idx = 0; - if res[0] == "exports" { - res.remove(0); - } else { - res.insert(0, "exports".to_string()); - wrapped_idx = 1; - } - match res[wrapped_idx].strip_prefix("wrapped_") { - Some(name) => res[wrapped_idx] = name.to_string(), - None => res[wrapped_idx] = "wrapped_".to_string() + &res[wrapped_idx], - } - res -} diff --git a/src/codegen/fuzz.rs b/src/codegen/fuzz.rs new file mode 100644 index 0000000..d5bda0b --- /dev/null +++ b/src/codegen/fuzz.rs @@ -0,0 +1,112 @@ +use super::State; +use crate::util::{ + FullTypePath, ResourceFuncKind, extract_arg_info, get_owned_type, get_return_type, make_path, + wit_func_name, +}; +use quote::quote; +use syn::{Signature, parse_quote, visit_mut::VisitMut}; + +impl State { + pub fn generate_fuzz_func( + &self, + module_path: &[String], + sig: &Signature, + resource: &Option, + ) -> syn::ImplItemFn { + let func_name = &sig.ident; + let is_export = module_path.join("::") == "exports::proxy::recorder::start_replay"; + if !is_export { + let (kind, args) = extract_arg_info(sig); + let arg_names = args.iter().map(|arg| &arg.ident); + let display_name = wit_func_name(module_path, resource, func_name, &kind); + let ret_ty = get_return_type(&sig.output); + if ret_ty.is_some() { + parse_quote! { + #sig { + let mut __params: Vec = Vec::new(); + #( + __params.push(wasm_wave::to_string(&ToValue::to_value(&#arg_names)).unwrap()); + )* + let mut __buf = __params.join(","); + proxy::util::debug::print(&format!("import: {}({})", #display_name, __buf)); + __buf += #display_name; + let mut u = Unstructured::new(&__buf.as_bytes()); + let res = u.arbitrary().unwrap(); + let res_str = wasm_wave::to_string(&ToValue::to_value(&res)).unwrap(); + proxy::util::debug::print(&format!("ret: {}", res_str)); + res + } + } + } else { + parse_quote! { + #sig {} + } + } + } else { + assert!(func_name == "start"); + let arms: Vec<_> = self + .funcs + .iter() + .filter(|(path, _)| path[0] != "exports" && path[0] != "proxy") + .flat_map(|(path, resources)| { + resources.iter().flat_map(move |(resource, sigs)| { + sigs.iter().filter_map(move |sig| { + let (kind, args) = extract_arg_info(sig); + if matches!(kind, Some(ResourceFuncKind::Method)) { + return None; + } + let arg_name: Vec<_> = args.iter().map(|arg| &arg.ident).collect(); + let call_param = args.iter().map(|arg| arg.call_param()); + let ty = args.iter().map(|arg| { + let mut ty = arg.ty.clone(); + FullTypePath { module_path: path }.visit_type_mut(&mut ty); + if let Some(owned) = get_owned_type(&ty) { + owned + } else { + ty + } + }); + let func_name = if let Some(resource) = resource { + format!("{}::{}", resource, sig.ident) + } else { + sig.ident.to_string() + }; + let func = make_path(path, &func_name); + let display_name = wit_func_name(path, resource, &sig.ident, &kind); + Some(quote! { + { + let mut __params: Vec = Vec::new(); + #( + let #arg_name: #ty = u.arbitrary().unwrap(); + __params.push(wasm_wave::to_string(&ToValue::to_value(&#arg_name)).unwrap()); + )* + proxy::util::debug::print(&format!("export: {}({})", #display_name, __params.join(", "))); + let _ = #func(#(#call_param),*); + } + }) + }) + }) + }) + .collect(); + let func_len = arms.iter().len(); + let idxs = 1..=func_len; + parse_quote! { + #sig { + let __buf = proxy::util::debug::get_random(); + let mut u = Unstructured::new(&__buf); + for _ in 0..10 { + let idx = u.int_in_range(1..=#func_len).unwrap(); + match idx { + #(#idxs => #arms)* + _ => unreachable!(), + } + // clean up borrowed resources from input args + SCOPED_ALLOC.with(|alloc| { + alloc.borrow_mut().clear(); + }); + } + } + } + } + } +} diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs new file mode 100644 index 0000000..8fe8a20 --- /dev/null +++ b/src/codegen/mod.rs @@ -0,0 +1,225 @@ +use crate::util::{FullTypePath, get_resource_from_trait_name, get_return_type, make_path}; +use anyhow::Result; +use quote::quote; +use std::collections::{BTreeMap, BTreeSet}; +use std::path::PathBuf; +use syn::{ + File, Ident, Item, ItemEnum, ItemStruct, ItemTrait, Signature, TraitItem, parse_quote, + visit_mut::VisitMut, +}; + +mod fuzz; +mod record; +mod replay; + +#[derive(clap::Parser)] +pub struct GenerateArgs { + /// The path to the binding file generated by wit-bindgen. + pub bindings: PathBuf, + /// Specifies the type of the WIT component. + pub mode: GenerateMode, + /// The path to the output file. + #[arg(short, long, default_value("lib.rs"))] + pub output_file: PathBuf, +} +#[derive(clap::ValueEnum, clap::Parser, Clone)] +pub enum GenerateMode { + /// An arbitrary component, we can only generate an empty stub. + Stubs, + /// An instrument component which imports and exports the same interface. + /// The generated code will redirect the export interface to call the corresponding import interface. + Instrument, + /// An instrument component which records all import calls. + Record, + /// A virtualized component with no imports, with implementation for replay. + Replay, + /// A virtualized component with no imports, with implementation for fuzzing. + Fuzz, +} +impl GenerateMode { + pub fn is_instrument(&self) -> bool { + matches!(self, GenerateMode::Instrument | GenerateMode::Record) + } +} + +pub struct State { + pub mode: GenerateMode, + pub traits: BTreeMap, Vec>, + pub types: BTreeMap, Vec>, + pub funcs: BTreeMap, BTreeMap, Vec>>, + pub module_paths: BTreeSet>, + pub output: Vec, +} +pub enum TypeInfo { + Struct(ItemStruct), + Enum(ItemEnum), + Resource(ItemStruct), + Flag(ItemFlag), +} +pub struct ItemFlag { + pub name: Ident, + pub flags: Vec, +} + +impl GenerateArgs { + pub fn generate(&self) -> Result<()> { + let file = std::fs::read_to_string(&self.bindings)?; + let ast = syn::parse_file(&file)?; + + let mut state = State { + mode: self.mode.clone(), + traits: BTreeMap::new(), + types: BTreeMap::new(), + funcs: BTreeMap::new(), + module_paths: BTreeSet::new(), + output: Vec::new(), + }; + state.generate_preamble(); + state.find_all_items(&ast.items, vec![]); + state.generate_stubs(); + let trait_generator = crate::traits::TraitGenerator::new(&state); + let traits = trait_generator.generate(); + drop(trait_generator); + state.output.extend(traits); + let file = state.into_output_file(); + let output = prettyplease::unparse(&file); + std::fs::write(&self.output_file, output)?; + Ok(()) + } +} +impl State { + fn generate_stubs(&mut self) { + for (module_path, traits) in &self.traits { + for trait_item in traits { + let impl_item = self.generate_impl_with_methods(trait_item, module_path); + self.output.push(impl_item); + } + } + } + fn generate_preamble(&mut self) { + let file: File = parse_quote! { + mod bindings; + use bindings::*; + struct Stub; + bindings::export!(Stub with_types_in bindings); + }; + self.output = file.items; + } + fn generate_impl_with_methods(&self, trait_item: &ItemTrait, module_path: &[String]) -> Item { + let trait_name = &trait_item.ident.to_string(); + let trait_path = make_path(module_path, trait_name); + let resource = get_resource_from_trait_name(trait_name); + let stub: syn::Path = match (&self.mode.is_instrument(), &resource) { + (true, Some(resource)) => { + let import_path = get_proxy_path(module_path); + make_path(&import_path, resource) + } + (false, Some(_)) => parse_quote! { MockedResource }, + (_, _) => parse_quote! { Stub }, + }; + // Collect all method signatures from the trait + let mut methods = Vec::new(); + for item in &trait_item.items { + match item { + TraitItem::Type(assoc_type) => { + let type_name = &assoc_type.ident; + let stub: syn::Path = if self.mode.is_instrument() { + let import_path = get_proxy_path(module_path); + make_path(&import_path, &type_name.to_string()) + } else { + parse_quote! { MockedResource } + }; + let impl_item = parse_quote! { + type #type_name = #stub; + }; + methods.push(syn::ImplItem::Type(impl_item)); + } + TraitItem::Fn(method) => { + if method.sig.ident.to_string().starts_with("_resource_") { + continue; + } + let mut sig = method.sig.clone(); + let mut transformer = FullTypePath { module_path }; + transformer.visit_signature_mut(&mut sig); + let module_full_name = module_path.join("::"); + if module_full_name == "exports::proxy::conversion::conversion" { + let stub_impl = self.generate_conversion_func(&sig); + methods.push(syn::ImplItem::Fn(stub_impl)); + continue; + } + let stub_impl = match self.mode { + GenerateMode::Stubs => parse_quote! { + #[allow(unused_variables)] + #sig { + unimplemented!() + } + }, + GenerateMode::Instrument | GenerateMode::Record => { + self.generate_instrument_func(module_path, &sig, &resource) + } + GenerateMode::Replay => { + self.generate_replay_func(module_path, &sig, &resource) + } + GenerateMode::Fuzz => self.generate_fuzz_func(module_path, &sig, &resource), + }; + methods.push(syn::ImplItem::Fn(stub_impl)); + } + _ => (), + } + } + parse_quote! { + impl #trait_path for #stub { + #(#methods)* + } + } + } + + fn generate_conversion_func(&self, sig: &Signature) -> syn::ImplItemFn { + let func_name = &sig.ident.to_string(); + let body = if func_name.starts_with("get_wrapped_") { + quote! { x.to_proxy() } + } else if func_name.starts_with("get_host_") { + quote! { x.to_proxy() } + } else if func_name.starts_with("get_mock_") { + let resource = get_return_type(&sig.output).unwrap(); + let name = func_name + .rfind("_magic42_") + .map(|idx| &func_name[idx + 9..]) + .unwrap(); + quote! { + #resource::new(MockedResource { handle, name: #name.to_string() }) + } + } else { + unreachable!() + }; + parse_quote! { + #sig { + #body + } + } + } + fn into_output_file(self) -> File { + File { + items: self.output, + shebang: None, + attrs: Vec::new(), + } + } +} + +pub fn get_proxy_path(src_path: &[String]) -> Vec { + assert!(src_path.len() >= 3); + let mut res = src_path.to_vec(); + let mut wrapped_idx = 0; + if res[0] == "exports" { + res.remove(0); + } else { + res.insert(0, "exports".to_string()); + wrapped_idx = 1; + } + match res[wrapped_idx].strip_prefix("wrapped_") { + Some(name) => res[wrapped_idx] = name.to_string(), + None => res[wrapped_idx] = "wrapped_".to_string() + &res[wrapped_idx], + } + res +} diff --git a/src/codegen/record.rs b/src/codegen/record.rs new file mode 100644 index 0000000..2671b3f --- /dev/null +++ b/src/codegen/record.rs @@ -0,0 +1,93 @@ +use super::{GenerateMode, State, get_proxy_path}; +use crate::util::{ResourceFuncKind, extract_arg_info, get_return_type, wit_func_name}; +use quote::quote; +use syn::{Signature, parse_quote}; + +impl State { + pub fn generate_instrument_func( + &self, + module_path: &[String], + sig: &Signature, + resource: &Option, + ) -> syn::ImplItemFn { + let func_name = &sig.ident; + let (kind, args) = extract_arg_info(sig); + let import_path = get_proxy_path(module_path); + let import_sig = self + .find_function(&import_path, resource, func_name) + .unwrap(); + let (_, import_args) = extract_arg_info(import_sig); + let arg_names = args.iter().map(|arg| &arg.ident); + let call_args = args + .iter() + .zip(import_args.iter()) + .map(|(arg, import_arg)| -> syn::Expr { + let ident = &arg.ident; + if import_arg.is_borrowed { + parse_quote! { &#ident } + } else { + parse_quote! { #ident } + } + }); + let (func, res): (syn::Expr, _) = match (resource.is_some(), &kind) { + (true, Some(ResourceFuncKind::Method)) => { + (parse_quote! { self.#func_name }, quote! { res.to_proxy() }) + } + (true, Some(ResourceFuncKind::Constructor)) => { + (parse_quote! { Self::#func_name }, quote! { res }) + } + (true, None) => (parse_quote! { Self::#func_name }, quote! { res.to_proxy() }), + (false, _) => ( + syn::parse_str(&format!("{}::{}", import_path.join("::"), func_name)).unwrap(), + quote! { res.to_proxy() }, + ), + }; + match &self.mode { + GenerateMode::Instrument => parse_quote! { + #sig { + let res = #func(#(#call_args.to_proxy()),*); + #res + } + }, + GenerateMode::Record => { + let init_vec = if matches!(kind, Some(ResourceFuncKind::Method)) { + quote! { vec![wasm_wave::to_string(&ToValue::to_value(&self)).unwrap()] } + } else { + quote! { Vec::new() } + }; + let is_mut = if args.is_empty() { + quote! {} + } else { + quote! { mut } + }; + let display_name = wit_func_name(module_path, resource, func_name, &kind); + let is_export = !module_path[1].starts_with("wrapped_"); + let record_ret = if get_return_type(&sig.output).is_none() { + quote! { + #func(#(#call_args),*); + proxy::recorder::record::record_ret(Some(#display_name), None, #is_export); + } + } else { + quote! { + let res = #func(#(#call_args),*); + let wave_res = wasm_wave::to_string(&res.to_value()).unwrap(); + proxy::recorder::record::record_ret(Some(#display_name), Some(&wave_res), #is_export); + #res + } + }; + parse_quote! { + #sig { + let #is_mut params: Vec = #init_vec; + #( + let #arg_names = #arg_names.to_proxy(); + params.push(wasm_wave::to_string(&ToValue::to_value(&#arg_names)).unwrap()); + )* + proxy::recorder::record::record_args(Some(#display_name), ¶ms, #is_export); + #record_ret + } + } + } + _ => unreachable!(), + } + } +} diff --git a/src/codegen/replay.rs b/src/codegen/replay.rs new file mode 100644 index 0000000..552b297 --- /dev/null +++ b/src/codegen/replay.rs @@ -0,0 +1,121 @@ +use super::State; +use crate::util::{ + FullTypePath, ResourceFuncKind, extract_arg_info, get_owned_type, get_return_type, make_path, + wit_func_name, +}; +use quote::quote; +use syn::{Signature, parse_quote, visit_mut::VisitMut}; + +impl State { + pub fn generate_replay_func( + &self, + module_path: &[String], + sig: &Signature, + resource: &Option, + ) -> syn::ImplItemFn { + let func_name = &sig.ident; + let is_export = module_path.join("::") == "exports::proxy::recorder::start_replay"; + if !is_export { + let (kind, args) = extract_arg_info(sig); + let arg_names = args.iter().map(|arg| &arg.ident); + let display_name = wit_func_name(module_path, resource, func_name, &kind); + let ret_ty = get_return_type(&sig.output); + let replay_import = if let Some(ret_ty) = ret_ty { + quote! { + let wave = proxy::recorder::replay::replay_import(Some(#display_name), Some(&args)).unwrap(); + let ret: Value = wasm_wave::from_str(&<#ret_ty as ValueTyped>::value_type(), &wave).unwrap(); + ret.to_rust() + } + } else { + quote! { + let wave = proxy::recorder::replay::replay_import(Some(#display_name), Some(&args)); + assert!(wave.is_none()); + } + }; + let self_value = if matches!(kind, Some(ResourceFuncKind::Method)) { + // Use ToValue::to_value to avoid the auto-deref from self.to_value() + quote! { wasm_wave::to_string(&ToValue::to_value(&self)).unwrap(), } + } else { + quote! {} + }; + parse_quote! { + #sig { + let args = vec![#self_value #( wasm_wave::to_string(&#arg_names.to_value()).unwrap() ),*]; + #replay_import + } + } + } else { + assert!(func_name == "start"); + let arms = self + .funcs + .iter() + .filter(|(path, _)| path[0] != "exports" && path[0] != "proxy") + .flat_map(|(path, resources)| { + resources.iter().flat_map(move |(resource, sigs)| { + sigs.iter().filter_map(move |sig| { + let (kind, args) = extract_arg_info(sig); + if matches!(kind, Some(ResourceFuncKind::Method)) { + return None; + } + let arg_name: Vec<_> = args.iter().map(|arg| &arg.ident).collect(); + let arg_idx = args.iter().enumerate().map(|(idx, _)| quote! { args[#idx] }); + let call_param = args.iter().map(|arg| arg.call_param()); + let ty = args.iter().map(|arg| { + let mut ty = arg.ty.clone(); + FullTypePath { + module_path: path, + }.visit_type_mut(&mut ty); + if let Some(owned) = get_owned_type(&ty) { + owned + } else { + ty + } + }); + let func_name = if let Some(resource) = resource { + format!("{}::{}", resource, sig.ident) + } else { + sig.ident.to_string() + }; + let func = make_path(path, &func_name); + let display_name = wit_func_name(path, resource, &sig.ident, &kind); + let assert_ret = if get_return_type(&sig.output).is_none() { + quote! { + assert!(res == ()); + proxy::recorder::replay::assert_export_ret(Some(#display_name), None); + } + } else { + quote! { + let wave_res = wasm_wave::to_string(&res.to_value()).unwrap(); + proxy::recorder::replay::assert_export_ret(Some(#display_name), Some(&wave_res)); + } + }; + Some(quote! { + #display_name => { + #( + let arg_value: Value = wasm_wave::from_str(&<#ty as ValueTyped>::value_type(), &#arg_idx).unwrap(); + let #arg_name: #ty = arg_value.to_rust(); + )* + let res = #func(#(#call_param),*); + #assert_ret + } + }) + }) + }) + }); + parse_quote! { + #sig { + while let Some((method, args)) = proxy::recorder::replay::replay_export() { + match method.as_str() { + #(#arms)* + _ => unreachable!(), + } + // clean up borrowed resources from input args + SCOPED_ALLOC.with(|alloc| { + alloc.borrow_mut().clear(); + }); + } + } + } + } + } +} diff --git a/src/run.rs b/src/run.rs index e60e780..123cdc0 100644 --- a/src/run.rs +++ b/src/run.rs @@ -1,7 +1,6 @@ use clap::Parser; -use serde::{Deserialize, Serialize}; -use std::collections::VecDeque; use std::path::PathBuf; +use trace::Logger; use wasmtime::component::types::{ComponentFunc, ComponentItem as CItem}; use wasmtime::component::wasm_wave::{untyped::UntypedFuncCall, wasm::WasmFunc}; use wasmtime::component::{Component, HasSelf, Linker, ResourceTable, Val}; @@ -27,119 +26,39 @@ mod bindings { }); } -#[derive(Serialize, Deserialize, Debug)] -enum FuncCall { - ExportArgs { - method: String, - args: Vec, - }, - ExportRet { - method: Option, - ret: Option, - }, - ImportArgs { - method: Option, - args: Vec, - }, - ImportRet { - method: Option, - ret: Option, - }, -} -impl FuncCall { - fn to_string(&self) -> String { - match self { - FuncCall::ExportArgs { method, args } => format!("{method}({})", args.join(", ")), - FuncCall::ImportArgs { method, args } => format!( - "{}({})", - method.as_deref().unwrap_or(""), - args.join(", ") - ), - FuncCall::ExportRet { ret, .. } | FuncCall::ImportRet { ret, .. } => { - ret.as_deref().unwrap_or("()").to_owned() - } - } - } -} - -struct Logger { +struct State { wasi_ctx: WasiCtx, resource_table: ResourceTable, - logger: VecDeque, + logger: Logger, exit_called: bool, } -impl bindings::proxy::recorder::record::Host for Logger { +impl bindings::proxy::recorder::record::Host for State { fn record_args(&mut self, method: Option, args: Vec, is_export: bool) { - let call = if is_export { - FuncCall::ExportArgs { - method: method.unwrap(), - args, - } - } else { - FuncCall::ImportArgs { method, args } - }; + let call = self.logger.record_args(method, args, is_export); println!("call: {}", call.to_string()); - self.logger.push_back(call); } fn record_ret(&mut self, method: Option, ret: Option, is_export: bool) { - let call = if is_export { - FuncCall::ExportRet { method, ret } - } else { - FuncCall::ImportRet { method, ret } - }; + let call = self.logger.record_ret(method, ret, is_export); println!("ret: {}", call.to_string()); - self.logger.push_back(call); } } -impl bindings::proxy::recorder::replay::Host for Logger { +impl bindings::proxy::recorder::replay::Host for State { fn replay_export(&mut self) -> Option<(String, Vec)> { - let call = self.logger.pop_front()?; - println!("export call: {}", call.to_string()); - let FuncCall::ExportArgs { method, args } = call else { - panic!() - }; - Some((method, args)) + self.logger.replay_export() } fn assert_export_ret(&mut self, assert_method: Option, assert_ret: Option) { - if let Some(FuncCall::ExportRet { .. }) = self.logger.front() { - let call = self.logger.pop_front().unwrap(); - println!("export ret: {}", call.to_string()); - let FuncCall::ExportRet { method, ret } = call else { - panic!() - }; - if let (Some(method), Some(assert_method)) = (method, assert_method) { - assert_eq!(method, assert_method); - } - assert_eq!(ret, assert_ret); - } + self.logger.assert_export_ret(assert_method, assert_ret); } fn replay_import( &mut self, assert_method: Option, assert_args: Option>, ) -> Option { - let mut call = self.logger.pop_front().unwrap(); - if let FuncCall::ImportArgs { method, args } = &call { - if let (Some(method), Some(assert_method)) = (method, assert_method) { - assert_eq!(method, &assert_method); - } - if let Some(assert_args) = &assert_args { - assert_eq!(args, assert_args); - } - println!("import call: {}", call.to_string()); - if method - .as_ref() - .is_some_and(|m| m.starts_with("wasi:cli/exit")) - { - self.exit_called = true; - return Some("Something that can crash".to_string()); - } - call = self.logger.pop_front().unwrap(); + let (exit_called, ret) = self.logger.replay_import(assert_method, assert_args, false); + if exit_called { + self.exit_called = exit_called; + return Some("Something that can crash".to_string()); } - println!("import ret: {}", call.to_string()); - let FuncCall::ImportRet { ret, .. } = call else { - panic!() - }; ret } } @@ -154,25 +73,25 @@ pub fn run(args: RunArgs) -> anyhow::Result<()> { .wasm_backtrace_details(WasmBacktraceDetails::Enable); let engine = Engine::new(&config)?; - let mut linker = Linker::::new(&engine); + let mut linker = Linker::::new(&engine); add_to_linker_sync(&mut linker)?; let wasi = WasiCtxBuilder::new().inherit_stdio().inherit_args().build(); - let mut state = Logger { + let mut state = State { wasi_ctx: wasi, resource_table: ResourceTable::new(), - logger: VecDeque::new(), + logger: Logger::new(), exit_called: false, }; if let Some(path) = &args.trace { - bindings::proxy::recorder::replay::add_to_linker::<_, HasSelf<_>>(&mut linker, |logger| { - logger + bindings::proxy::recorder::replay::add_to_linker::<_, HasSelf<_>>(&mut linker, |state| { + state })?; let trace = std::fs::read_to_string(path)?; - state.logger = serde_json::from_str(&trace)?; + state.logger.load_trace(&trace); } else { - bindings::proxy::recorder::record::add_to_linker::>( + bindings::proxy::recorder::record::add_to_linker::>( &mut linker, - |logger| logger, + |state| state, )?; } @@ -211,7 +130,7 @@ pub fn run(args: RunArgs) -> anyhow::Result<()> { } }?; if args.trace.is_none() { - let trace = serde_json::to_string(&store.data().logger)?; + let trace = store.data().logger.dump_trace(); std::fs::write("trace.out", &trace)?; } } @@ -264,7 +183,7 @@ fn collect_export_funcs( .collect() } -impl WasiView for Logger { +impl WasiView for State { fn ctx(&mut self) -> WasiCtxView<'_> { WasiCtxView { ctx: &mut self.wasi_ctx,