From 883d56143fcd60da6e3cce9a40a5a83450ee8445 Mon Sep 17 00:00:00 2001 From: Lawrence Bethlenfalvy Date: Fri, 24 Apr 2026 22:32:41 +0000 Subject: [PATCH] Hello World works --- Cargo.lock | 389 +++++++++++-------------- async-fn-stream/Cargo.toml | 4 +- async-fn-stream/src/lib.rs | 2 +- examples/hello-world/main.orc | 6 +- orchid-api-derive/Cargo.toml | 6 +- orchid-api-traits/Cargo.toml | 6 +- orchid-api/Cargo.toml | 6 +- orchid-api/src/proto.rs | 2 +- orchid-async-utils/Cargo.toml | 8 +- orchid-async-utils/src/localset.rs | 86 +++--- orchid-base/Cargo.toml | 20 +- orchid-base/src/comm.rs | 74 +++-- orchid-base/src/tl_cache.rs | 18 +- orchid-extension/Cargo.toml | 20 +- orchid-extension/src/binary.rs | 2 +- orchid-host/Cargo.toml | 13 +- orchid-host/src/cmd_system.rs | 190 ++++++------ orchid-std/Cargo.toml | 20 +- orchid-std/src/std/string/str_lexer.rs | 4 +- orcx/Cargo.toml | 10 +- unsync-pipe/Cargo.toml | 5 +- unsync-pipe/src/lib.rs | 41 ++- xtask/Cargo.toml | 2 +- 23 files changed, 447 insertions(+), 487 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a3243e1..cfb62ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -39,9 +39,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.18" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", "anstyle-parse", @@ -54,15 +54,15 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anstyle-parse" -version = "0.2.6" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" dependencies = [ "utf8parse", ] @@ -122,7 +122,7 @@ name = "async-fn-stream" version = "0.1.0" dependencies = [ "futures", - "test_executors", + "orchid-async-utils", ] [[package]] @@ -137,9 +137,9 @@ version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ - "proc-macro2 1.0.104", - "quote 1.0.42", - "syn 2.0.112", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] [[package]] @@ -208,9 +208,9 @@ checksum = "c2593a3b8b938bd68373196c9832f516be11fa487ef4ae745eb282e6a56a7244" dependencies = [ "once_cell", "proc-macro-crate", - "proc-macro2 1.0.104", - "quote 1.0.42", - "syn 2.0.112", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] [[package]] @@ -242,8 +242,8 @@ version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" dependencies = [ - "proc-macro2 1.0.104", - "quote 1.0.42", + "proc-macro2 1.0.106", + "quote 1.0.45", "syn 1.0.109", ] @@ -319,9 +319,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.54" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ "clap_builder", "clap_derive", @@ -329,9 +329,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.54" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ "anstream", "anstyle", @@ -341,21 +341,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.49" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" dependencies = [ "heck", - "proc-macro2 1.0.104", - "quote 1.0.42", - "syn 2.0.112", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] [[package]] name = "clap_lex" -version = "0.7.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "colorchoice" @@ -420,9 +420,9 @@ dependencies = [ [[package]] name = "ctrlc" -version = "3.5.1" +version = "3.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73736a89c4aff73035ba2ed2e565061954da00d4970fc9ac25dcc85a2a20d790" +checksum = "e0b1fab2ae45819af2d0731d60f2afe17227ebb1a1538a236da84c93e9a60162" dependencies = [ "dispatch2", "nix", @@ -506,9 +506,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[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", @@ -521,9 +521,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", @@ -531,15 +531,15 @@ 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-executor" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" dependencies = [ "futures-core", "futures-task", @@ -548,9 +548,9 @@ dependencies = [ [[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-locks" @@ -565,32 +565,32 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ - "proc-macro2 1.0.104", - "quote 1.0.42", - "syn 2.0.112", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] [[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", @@ -600,7 +600,6 @@ dependencies = [ "futures-task", "memchr", "pin-project-lite", - "pin-utils", "slab", ] @@ -638,18 +637,6 @@ dependencies = [ "wasi", ] -[[package]] -name = "getrandom" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" -dependencies = [ - "cfg-if", - "libc", - "r-efi 5.3.0", - "wasip2", -] - [[package]] name = "getrandom" version = "0.4.2" @@ -658,7 +645,7 @@ checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if", "libc", - "r-efi 6.0.0", + "r-efi", "rand_core 0.10.0", "wasip2", "wasip3", @@ -687,6 +674,12 @@ name = "hashbrown" version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + +[[package]] +name = "hashbrown" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" dependencies = [ "allocator-api2", "equivalent", @@ -744,8 +737,8 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cab85a7ed0bd5f0e76d93846e0147172bed2e2d3f859bcc33a8d9699cad1a75" dependencies = [ - "proc-macro2 1.0.104", - "quote 1.0.42", + "proc-macro2 1.0.106", + "quote 1.0.45", ] [[package]] @@ -822,9 +815,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.175" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libloading" @@ -942,13 +935,13 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" dependencies = [ "libc", "wasi", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -959,9 +952,9 @@ checksum = "c96aba5aa877601bb3f6dd6a63a969e1f82e60646e81e71b14496995e9853c91" [[package]] name = "nix" -version = "0.30.1" +version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3" dependencies = [ "bitflags", "cfg-if", @@ -1014,9 +1007,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oorandom" @@ -1032,8 +1025,8 @@ dependencies = [ "itertools", "orchid-api-derive", "orchid-api-traits", + "orchid-async-utils", "ordered-float", - "test_executors", "unsync-pipe", ] @@ -1043,9 +1036,9 @@ version = "0.1.0" dependencies = [ "itertools", "orchid-api-traits", - "proc-macro2 1.0.104", - "quote 1.0.42", - "syn 2.0.112", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] [[package]] @@ -1078,7 +1071,7 @@ dependencies = [ "derive_destructure", "dyn-clone", "futures", - "hashbrown 0.16.1", + "hashbrown 0.17.0", "itertools", "lazy_static", "never", @@ -1088,7 +1081,7 @@ dependencies = [ "orchid-api-traits", "orchid-async-utils", "ordered-float", - "rand 0.10.0", + "rand 0.10.1", "rand_chacha 0.10.0", "regex", "rust-embed", @@ -1110,7 +1103,7 @@ dependencies = [ "dyn-clone", "futures", "futures-locks", - "hashbrown 0.16.1", + "hashbrown 0.17.0", "include_dir", "itertools", "konst", @@ -1145,7 +1138,7 @@ dependencies = [ "derive_destructure", "futures", "futures-locks", - "hashbrown 0.16.1", + "hashbrown 0.17.0", "itertools", "lazy_static", "libloading", @@ -1154,6 +1147,7 @@ dependencies = [ "num-traits", "orchid-api", "orchid-api-traits", + "orchid-async-utils", "orchid-base", "orchid-extension", "ordered-float", @@ -1175,7 +1169,7 @@ dependencies = [ "async-once-cell", "chrono", "futures", - "hashbrown 0.16.1", + "hashbrown 0.17.0", "itertools", "never", "once_cell", @@ -1217,9 +1211,9 @@ dependencies = [ [[package]] name = "ordered-float" -version = "5.1.0" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4779c6901a562440c3786d08192c6fbda7c1c2060edd10006b05ee35d10f2d" +checksum = "b7d950ca161dc355eaf28f82b11345ed76c6e1f6eb1f4f4479e0323b9e2fbd0e" dependencies = [ "num-traits", ] @@ -1249,9 +1243,9 @@ dependencies = [ [[package]] name = "pastey" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b867cad97c0791bbd3aaa6472142568c6c9e8f71937e98379f584cfb0cf35bec" +checksum = "c5a797f0e07bdf071d15742978fc3128ec6c22891c31a3a931513263904c982a" [[package]] name = "pin-project-lite" @@ -1259,12 +1253,6 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - [[package]] name = "ppv-lite86" version = "0.2.20" @@ -1280,8 +1268,8 @@ version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ - "proc-macro2 1.0.104", - "syn 2.0.112", + "proc-macro2 1.0.106", + "syn 2.0.117", ] [[package]] @@ -1310,9 +1298,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.104" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9695f8df41bb4f3d222c95a67532365f569318332d03d5f3f67f37b20e6ebdf0" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] @@ -1342,8 +1330,8 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" dependencies = [ - "proc-macro2 1.0.104", - "quote 1.0.42", + "proc-macro2 1.0.106", + "quote 1.0.45", "syn 1.0.109", ] @@ -1358,19 +1346,13 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.42" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ - "proc-macro2 1.0.104", + "proc-macro2 1.0.106", ] -[[package]] -name = "r-efi" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" - [[package]] name = "r-efi" version = "6.0.0" @@ -1396,19 +1378,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.2" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" -dependencies = [ - "rand_chacha 0.9.0", - "rand_core 0.9.3", -] - -[[package]] -name = "rand" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" dependencies = [ "chacha20", "getrandom 0.4.2", @@ -1425,16 +1397,6 @@ dependencies = [ "rand_core 0.6.4", ] -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core 0.9.3", -] - [[package]] name = "rand_chacha" version = "0.10.0" @@ -1454,15 +1416,6 @@ dependencies = [ "getrandom 0.2.15", ] -[[package]] -name = "rand_core" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" -dependencies = [ - "getrandom 0.3.4", -] - [[package]] name = "rand_core" version = "0.10.0" @@ -1480,9 +1433,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.12.2" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", @@ -1518,9 +1471,9 @@ dependencies = [ [[package]] name = "rkyv" -version = "0.7.45" +version = "0.7.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b" +checksum = "2297bf9c81a3f0dc96bc9521370b88f054168c29826a75e89c55ff196e7ed6a1" dependencies = [ "bitvec", "bytecheck", @@ -1536,20 +1489,20 @@ dependencies = [ [[package]] name = "rkyv_derive" -version = "0.7.45" +version = "0.7.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0" +checksum = "84d7b42d4b8d06048d3ac8db0eb31bcb942cbeb709f0b5f2b2ebde398d3038f5" dependencies = [ - "proc-macro2 1.0.104", - "quote 1.0.42", + "proc-macro2 1.0.106", + "quote 1.0.45", "syn 1.0.109", ] [[package]] name = "rust-embed" -version = "8.9.0" +version = "8.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "947d7f3fad52b283d261c4c99a084937e2fe492248cb9a68a8435a861b8798ca" +checksum = "04113cb9355a377d83f06ef1f0a45b8ab8cd7d8b1288160717d66df5c7988d27" dependencies = [ "rust-embed-impl", "rust-embed-utils", @@ -1562,10 +1515,10 @@ version = "8.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fa2c8c9e8711e10f9c4fd2d64317ef13feaab820a4c51541f1a8c8e2e851ab2" dependencies = [ - "proc-macro2 1.0.104", - "quote 1.0.42", + "proc-macro2 1.0.106", + "quote 1.0.45", "rust-embed-utils", - "syn 2.0.112", + "syn 2.0.117", "walkdir", ] @@ -1581,9 +1534,9 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.39.0" +version = "1.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35affe401787a9bd846712274d97654355d21b2a2c092a3139aabe31e9022282" +checksum = "2ce901f9a19d251159075a4c37af514c3b8ef99c22e02dd8c19161cf397ee94a" dependencies = [ "arrayvec", "borsh", @@ -1593,6 +1546,7 @@ dependencies = [ "rkyv", "serde", "serde_json", + "wasm-bindgen", ] [[package]] @@ -1665,9 +1619,9 @@ version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ - "proc-macro2 1.0.104", - "quote 1.0.42", - "syn 2.0.112", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] [[package]] @@ -1740,12 +1694,12 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.6.0" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1767,15 +1721,15 @@ dependencies = [ [[package]] name = "stacker" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d74a23609d509411d10e2176dc2a4346e3b4aea2e7b1869f19fdedbc71c013" +checksum = "640c8cdd92b6b12f5bcb1803ca3bbf5ab96e5e6b6b96b9ab77dabe9e880b3190" dependencies = [ "cc", "cfg-if", "libc", "psm", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1817,19 +1771,19 @@ version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2 1.0.104", - "quote 1.0.42", + "proc-macro2 1.0.106", + "quote 1.0.45", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.112" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21f182278bf2d2bcb3c88b1b08a37df029d71ce3d3ae26168e3c653b213b99d4" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ - "proc-macro2 1.0.104", - "quote 1.0.42", + "proc-macro2 1.0.106", + "quote 1.0.45", "unicode-ident", ] @@ -1841,9 +1795,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "task-local" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2c821daee0efdf6414970c8185a1c22e259a7ed87b2fd9f7d3c5f5503fd2863" +checksum = "2972044a9e5e448a506a7ff6f0d03b566d8ef4cd6918a58fc59835a0f8666626" dependencies = [ "pin-project-lite", ] @@ -1869,8 +1823,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b68fbf53af4a8dfdf0bd9192ab2f6fd42e5b59454bcde58fe1382a8677087732" dependencies = [ "proc-macro-crate", - "quote 1.0.42", - "syn 2.0.112", + "quote 1.0.45", + "syn 2.0.117", "wasm-bindgen-test", ] @@ -1889,9 +1843,9 @@ version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" dependencies = [ - "proc-macro2 1.0.104", - "quote 1.0.42", - "syn 2.0.112", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] [[package]] @@ -1920,9 +1874,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.49.0" +version = "1.52.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" +checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6" dependencies = [ "bytes", "libc", @@ -1937,13 +1891,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ - "proc-macro2 1.0.104", - "quote 1.0.42", - "syn 2.0.112", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] [[package]] @@ -2007,9 +1961,9 @@ version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ - "proc-macro2 1.0.104", - "quote 1.0.42", - "syn 2.0.112", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] [[package]] @@ -2057,8 +2011,8 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b79e2e9c9ab44c6d7c20d5976961b47e8f49ac199154daa514b77cd1ab536625" dependencies = [ - "proc-macro2 1.0.104", - "quote 1.0.42", + "proc-macro2 1.0.106", + "quote 1.0.45", "syn 1.0.109", ] @@ -2082,9 +2036,9 @@ checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-segmentation" -version = "1.12.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" [[package]] name = "unicode-xid" @@ -2105,8 +2059,9 @@ dependencies = [ "futures", "futures-io", "itertools", - "rand 0.9.2", - "rand_chacha 0.9.0", + "orchid-async-utils", + "rand 0.10.1", + "rand_chacha 0.10.0", "test_executors", ] @@ -2177,6 +2132,7 @@ dependencies = [ "cfg-if", "once_cell", "rustversion", + "serde", "wasm-bindgen-macro", "wasm-bindgen-shared", ] @@ -2200,7 +2156,7 @@ version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" dependencies = [ - "quote 1.0.42", + "quote 1.0.45", "wasm-bindgen-macro-support", ] @@ -2211,9 +2167,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" dependencies = [ "bumpalo", - "proc-macro2 1.0.104", - "quote 1.0.42", - "syn 2.0.112", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", "wasm-bindgen-shared", ] @@ -2253,9 +2209,9 @@ version = "0.3.56" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7150335716dce6028bead2b848e72f47b45e7b9422f64cccdc23bedca89affc1" dependencies = [ - "proc-macro2 1.0.104", - "quote 1.0.42", - "syn 2.0.112", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] [[package]] @@ -2373,9 +2329,9 @@ version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ - "proc-macro2 1.0.104", - "quote 1.0.42", - "syn 2.0.112", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] [[package]] @@ -2384,9 +2340,9 @@ version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ - "proc-macro2 1.0.104", - "quote 1.0.42", - "syn 2.0.112", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] [[package]] @@ -2413,15 +2369,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.6", -] - [[package]] name = "windows-sys" version = "0.59.0" @@ -2606,7 +2553,7 @@ dependencies = [ "heck", "indexmap", "prettyplease", - "syn 2.0.112", + "syn 2.0.117", "wasm-metadata", "wit-bindgen-core", "wit-component", @@ -2620,9 +2567,9 @@ checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" dependencies = [ "anyhow", "prettyplease", - "proc-macro2 1.0.104", - "quote 1.0.42", - "syn 2.0.112", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", "wit-bindgen-core", "wit-bindgen-rust", ] @@ -2696,7 +2643,7 @@ version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ - "proc-macro2 1.0.104", - "quote 1.0.42", - "syn 2.0.112", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] diff --git a/async-fn-stream/Cargo.toml b/async-fn-stream/Cargo.toml index c7ac8cf..d1c01aa 100644 --- a/async-fn-stream/Cargo.toml +++ b/async-fn-stream/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2024" [dependencies] -futures = { version = "0.3.31", features = ["std"], default-features = false } +futures = { version = "0.3.32", features = ["std"], default-features = false } [dev-dependencies] -test_executors = "0.4.1" +orchid-async-utils = { path = "../orchid-async-utils" } diff --git a/async-fn-stream/src/lib.rs b/async-fn-stream/src/lib.rs index 808c70e..82250e5 100644 --- a/async-fn-stream/src/lib.rs +++ b/async-fn-stream/src/lib.rs @@ -48,7 +48,7 @@ mod test { use futures::channel::mpsc::channel; use futures::{Stream, StreamExt, TryStreamExt}; - use test_executors::spin_on; + use orchid_async_utils::debug::spin_on; use crate::{stream, try_stream}; diff --git a/examples/hello-world/main.orc b/examples/hello-world/main.orc index 0806b48..f072580 100644 --- a/examples/hello-world/main.orc +++ b/examples/hello-world/main.orc @@ -5,9 +5,9 @@ let main = "foo" + string::slice "hello" 1 3 + "bar" let io_main = ( stdio::get_stdout \stdout - std::stream::write_str stdout "Hello, World!" - (std::stream::flush - (std::stream::close + std::stream::write_str stdout "Hello, World!\n" + (std::stream::flush stdout + (std::stream::close stdout orchid::cmd::exit \e e) \e e) diff --git a/orchid-api-derive/Cargo.toml b/orchid-api-derive/Cargo.toml index 50c80b8..6f9b542 100644 --- a/orchid-api-derive/Cargo.toml +++ b/orchid-api-derive/Cargo.toml @@ -9,8 +9,8 @@ proc-macro = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -quote = "1.0.42" -syn = { version = "2.0.112" } +quote = "1.0.45" +syn = { version = "2.0.117" } orchid-api-traits = { version = "0.1.0", path = "../orchid-api-traits" } -proc-macro2 = "1.0.104" +proc-macro2 = "1.0.106" itertools = "0.14.0" diff --git a/orchid-api-traits/Cargo.toml b/orchid-api-traits/Cargo.toml index ac4050f..eae06f6 100644 --- a/orchid-api-traits/Cargo.toml +++ b/orchid-api-traits/Cargo.toml @@ -6,8 +6,8 @@ edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -chrono = "0.4.43" -futures = { version = "0.3.31", features = ["std"], default-features = false } +chrono = "0.4.44" +futures = { version = "0.3.32", features = ["std"], default-features = false } itertools = "0.14.0" never = "0.1.0" -ordered-float = "5.1.0" +ordered-float = "5.3.0" diff --git a/orchid-api/Cargo.toml b/orchid-api/Cargo.toml index 843e38a..a72a24e 100644 --- a/orchid-api/Cargo.toml +++ b/orchid-api/Cargo.toml @@ -6,12 +6,12 @@ edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -ordered-float = "5.1.0" +ordered-float = "5.3.0" orchid-api-traits = { version = "0.1.0", path = "../orchid-api-traits" } orchid-api-derive = { version = "0.1.0", path = "../orchid-api-derive" } -futures = { version = "0.3.31", features = ["std"], default-features = false } +futures = { version = "0.3.32", features = ["std"], default-features = false } itertools = "0.14.0" unsync-pipe = { version = "0.2.0", path = "../unsync-pipe" } [dev-dependencies] -test_executors = "0.4.1" +orchid-async-utils = { path = "../orchid-async-utils" } diff --git a/orchid-api/src/proto.rs b/orchid-api/src/proto.rs index b7d186d..40949c7 100644 --- a/orchid-api/src/proto.rs +++ b/orchid-api/src/proto.rs @@ -157,8 +157,8 @@ mod tests { use std::collections::HashMap; use orchid_api_traits::enc_vec; + use orchid_async_utils::debug::spin_on; use ordered_float::NotNan; - use test_executors::spin_on; use super::*; use crate::Logger; diff --git a/orchid-async-utils/Cargo.toml b/orchid-async-utils/Cargo.toml index 60851df..82ac3f6 100644 --- a/orchid-async-utils/Cargo.toml +++ b/orchid-async-utils/Cargo.toml @@ -4,9 +4,9 @@ version = "0.1.0" edition = "2024" [dependencies] -futures = { version = "0.3.31", default-features = false, features = [ - "std", - "async-await", +futures = { version = "0.3.32", default-features = false, features = [ + "std", + "async-await", ] } itertools = "0.14.0" -task-local = "0.1.0" +task-local = "0.1.1" diff --git a/orchid-async-utils/src/localset.rs b/orchid-async-utils/src/localset.rs index 807ffbb..de1306b 100644 --- a/orchid-async-utils/src/localset.rs +++ b/orchid-async-utils/src/localset.rs @@ -1,61 +1,67 @@ +use std::cell::RefCell; +use std::fmt; use std::pin::Pin; -use std::task::Poll; +use std::rc::Rc; +use std::task::{Poll, Waker}; -use futures::channel::mpsc::{SendError, UnboundedReceiver, UnboundedSender, unbounded}; +use futures::StreamExt; use futures::future::LocalBoxFuture; use futures::stream::FuturesUnordered; -use futures::{SinkExt, StreamExt}; -pub struct LocalSetController<'a, E> { - sender: UnboundedSender>>, +pub struct SpawnError(T); +impl fmt::Debug for SpawnError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("SpawnError") } } + +pub struct LocalSetState<'a, E> { + waker: Waker, + futures: FuturesUnordered>>, +} + +pub struct LocalSetController<'a, E>(Rc>>); impl<'a, E> LocalSetController<'a, E> { - pub async fn spawn> + 'a>( - &mut self, + pub fn is_empty(&self) -> bool { self.len() == 0 } + pub fn len(&self) -> usize { self.0.borrow().futures.len() } + pub fn spawn> + 'a>(&self, fut: F) { + self.try_spawn(fut).unwrap() + } + pub fn try_spawn> + 'a>( + &self, fut: F, - ) -> Result<(), SendError> { - self.sender.send(Box::pin(fut)).await + ) -> Result<(), SpawnError> { + if Rc::strong_count(&self.0) == 1 { + return Err(SpawnError(fut)); + } + let g = self.0.borrow_mut(); + g.futures.push(Box::pin(fut)); + g.waker.wake_by_ref(); + Ok(()) } } -pub fn local_set<'a, E: 'a>() --> (LocalSetController<'a, E>, impl Future> + 'a) { - let (sender, receiver) = unbounded(); - let controller = LocalSetController { sender }; - let set = LocalSet { receiver, pending: FuturesUnordered::new() }; +pub fn local_set<'a, E: 'a>() -> (LocalSetController<'a, E>, LocalSet<'a, E>) { + let state = Rc::new(RefCell::new(LocalSetState { + waker: Waker::noop().clone(), + futures: FuturesUnordered::new(), + })); + let controller = LocalSetController(state.clone()); + let set = LocalSet(state); (controller, set) } -struct LocalSet<'a, E> { - receiver: UnboundedReceiver>>, - pending: FuturesUnordered>>, -} +pub struct LocalSet<'a, E>(Rc>>); impl Future for LocalSet<'_, E> { type Output = Result<(), E>; fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll { - let this = self.get_mut(); - let mut any_pending = false; - loop { - match this.receiver.poll_next_unpin(cx) { - Poll::Ready(Some(fut)) => this.pending.push(fut), - Poll::Ready(None) => break, - Poll::Pending => { - any_pending = true; - break; - }, - } + let ctl_dropped = 1 == Rc::strong_count(&self.0); + let mut this = self.0.borrow_mut(); + if !ctl_dropped { + this.waker.clone_from(cx.waker()); } - loop { - match this.pending.poll_next_unpin(cx) { - Poll::Ready(Some(Err(e))) => return Poll::Ready(Err(e)), - Poll::Ready(Some(Ok(()))) => continue, - Poll::Ready(None) => break, - Poll::Pending => { - any_pending = true; - break; - }, - } + match this.futures.poll_next_unpin(cx) { + Poll::Ready(Some(Err(e))) => Poll::Ready(Err(e)), + Poll::Ready(None) if ctl_dropped => Poll::Ready(Ok(())), + _ => Poll::Pending, } - if any_pending { Poll::Pending } else { Poll::Ready(Ok(())) } } } diff --git a/orchid-base/Cargo.toml b/orchid-base/Cargo.toml index 99b8b48..8280a0a 100644 --- a/orchid-base/Cargo.toml +++ b/orchid-base/Cargo.toml @@ -13,11 +13,11 @@ async-once-cell = "0.5.4" bound = "0.6.0" derive_destructure = "1.0.0" dyn-clone = "1.0.20" -futures = { version = "0.3.31", default-features = false, features = [ - "std", - "async-await", +futures = { version = "0.3.32", default-features = false, features = [ + "std", + "async-await", ] } -hashbrown = "0.16.1" +hashbrown = "0.17.0" itertools = "0.14.0" lazy_static = "1.5.0" never = "0.1.0" @@ -25,14 +25,14 @@ num-traits = "0.2.19" orchid-api = { version = "0.1.0", path = "../orchid-api" } orchid-api-derive = { version = "0.1.0", path = "../orchid-api-derive" } orchid-api-traits = { version = "0.1.0", path = "../orchid-api-traits" } -ordered-float = "5.1.0" -regex = "1.12.2" -rust-embed = "8.9.0" +ordered-float = "5.3.0" +regex = "1.12.3" +rust-embed = "8.11.0" substack = "1.1.1" trait-set = "0.3.0" -task-local = "0.1.0" +task-local = "0.1.1" [dev-dependencies] -futures = "0.3.31" -rand = "0.10.0" +futures = "0.3.32" +rand = "0.10.1" rand_chacha = "0.10.0" diff --git a/orchid-base/src/comm.rs b/orchid-base/src/comm.rs index abcdb70..5d6b0f7 100644 --- a/orchid-base/src/comm.rs +++ b/orchid-base/src/comm.rs @@ -17,7 +17,7 @@ use futures::{ use hashbrown::HashMap; use orchid_api_traits::{Decode, Encode, Request, UnderRoot}; use orchid_async_utils::debug::{PanicOnDrop, assert_no_drop}; -use orchid_async_utils::{cancel_cleanup, local_set, to_task}; +use orchid_async_utils::{Handle, cancel_cleanup, local_set, to_task}; use crate::{clone, finish_or_stash, stash, with_stash}; @@ -293,29 +293,35 @@ type IoGuard = Bound>>, IoLock>; /// An incoming request. This holds a lock on the ingress channel. pub struct IoReqReader { - prefix: u64, + id: u64, read: IoGuard, o: Rc>>, + requests: Rc>>>>, } impl ReqReader for IoReqReader { fn reader(&mut self) -> Pin<&mut dyn AsyncRead> { self.read.as_mut() } fn finish(self: Box) -> LocalBoxFuture<'static, Box> { Box::pin(async { - Box::new(IoReqHandle { prefix: self.prefix, write: self.o }) as Box + Box::new(IoReqHandle { id: self.id, write: self.o, requests: self.requests }) + as Box }) } } pub struct IoReqHandle { - prefix: u64, + id: u64, write: IoLock, + requests: Rc>>>>, } impl ReqHandle for IoReqHandle { fn start_reply(self: Box) -> LocalBoxFuture<'static, io::Result>> { let write = self.write.clone(); Box::pin(async move { let mut write = Bound::async_new(write, |l| l.lock()).await; - self.prefix.encode(write.as_mut()).await?; + self.requests.borrow_mut().remove(&self.id); + let mut prefix = self.id.to_be_bytes(); + prefix[0] = 0x01; + write.write_all(&prefix).await?; Ok(Box::new(IoRepWriter { write }) as Box) }) } @@ -552,8 +558,8 @@ impl IoCommServer { } }); - let running_requests = RefCell::new(HashMap::new()); - let (mut task_pool, fork_future) = local_set(); + let running_requests = Rc::new(RefCell::new(HashMap::new())); + let (task_pool, fork_future) = local_set(); let mut fork_stream = pin!(fork_future.into_stream()); let mut pending_replies = HashMap::new(); 'body: { @@ -577,7 +583,7 @@ impl IoCommServer { // ID 0 is reserved for single-fire notifications Ok(Event::Input(0, read)) => { let notif = ¬if; - task_pool.spawn(notif(Box::new(IoMsgReader { _pd: PhantomData, read }))).await.unwrap(); + task_pool.spawn(notif(Box::new(IoMsgReader { _pd: PhantomData, read }))) }, // non-zero IDs are associated with requests Ok(Event::Input(id, read)) => { @@ -588,21 +594,16 @@ impl IoCommServer { match discr { // request 0x00 => { - let (o, req, reqs) = (o.clone(), &req, &running_requests); - task_pool - .spawn(async move { - id_bytes[0] = 0x01; - let prefix = u64::from_be_bytes(id_bytes); - let reader = Box::new(IoReqReader { prefix, read, o }); - let (fut, handle) = to_task(async { req(reader).await.map(|Receipt| ()) }); - reqs.borrow_mut().insert(id, handle); - with_stash(fut).await; - // during this await the read guard is released and thus we may receive a - // cancel notification from below - Ok(()) - }) - .await - .unwrap(); + let (o, req, reqs) = (o.clone(), &req, running_requests.clone()); + task_pool.spawn(async move { + let reader = Box::new(IoReqReader { id, read, o, requests: reqs.clone() }); + let (fut, handle) = to_task(async { req(reader).await.map(|Receipt| ()) }); + reqs.borrow_mut().insert(id, handle); + with_stash(fut).await; + // during this await the read guard is released and thus we may receive a + // cancel notification from below + Ok(()) + }); }, // response 0x01 => { @@ -619,21 +620,18 @@ impl IoCommServer { None => continue, }; let (o, running_reqs) = (o.clone(), &running_requests); - task_pool - .spawn(async move { - // if the request starts writing back before our abort arrives, we only - // get this mutex once it's done - let mut write = o.lock().await; - // if the request is still in the store, the write didn't begin - let Some(_) = running_reqs.borrow_mut().remove(&id) else { return Ok(()) }; - id_bytes[0] = 0x03; - let cancel_code = u64::from_be_bytes(id_bytes); - cancel_code.encode(write.as_mut()).await?; - write.flush().await?; - Ok(()) - }) - .await - .unwrap(); + task_pool.spawn(async move { + // if the request starts writing back before our abort arrives, we only + // get this mutex once it's done + let mut write = o.lock().await; + // if the request is still in the store, the write didn't begin + let Some(_) = running_reqs.borrow_mut().remove(&id) else { return Ok(()) }; + id_bytes[0] = 0x03; + let cancel_code = u64::from_be_bytes(id_bytes); + cancel_code.encode(write.as_mut()).await?; + write.flush().await?; + Ok(()) + }); }, // stub reply for cancelled request 0x03 => { diff --git a/orchid-base/src/tl_cache.rs b/orchid-base/src/tl_cache.rs index 1bb4556..2af2bb6 100644 --- a/orchid-base/src/tl_cache.rs +++ b/orchid-base/src/tl_cache.rs @@ -1,17 +1,23 @@ /// Cache a value in a [thread_local!]. Supports synchronous and asynchronous /// initializers /// +/// Synchronous use-case: +/// ``` +/// use std::rc::Rc; +/// #[macro_use] +/// use orchid_base::tl_cache; +/// let foo = tl_cache!(Rc>: Rc::new(vec![0; 1024])); +/// ``` +/// +/// Asynchronous use-case: /// ``` /// #[macro_use] /// use orchid_base::tl_cache; /// -/// // simple synchronous case -/// let foo = tl_cache!(Rc>: vec![0; 1024]); +/// async fn complex_operation(x: usize) -> usize { x + 1 } /// async { -/// async fn complex_operation(x: usize) -> usize { x + 1 } -/// // async case -/// let bar = tl_cache!(async usize: complex_operation(0).await) -/// } +/// let bar = tl_cache!(async usize: complex_operation(0).await); +/// }; /// ``` #[macro_export] macro_rules! tl_cache { diff --git a/orchid-extension/Cargo.toml b/orchid-extension/Cargo.toml index 1d3766d..406e35e 100644 --- a/orchid-extension/Cargo.toml +++ b/orchid-extension/Cargo.toml @@ -12,30 +12,30 @@ async-once-cell = "0.5.4" chrono = "0.4.44" derive_destructure = "1.0.0" dyn-clone = "1.0.20" -futures = { version = "0.3.31", default-features = false, features = [ - "std", - "async-await", +futures = { version = "0.3.32", default-features = false, features = [ + "std", + "async-await", ] } futures-locks = "0.7.1" -hashbrown = "0.16.1" +hashbrown = "0.17.0" include_dir = { version = "0.7.4", optional = true } itertools = "0.14.0" konst = "0.4.3" lazy_static = "1.5.0" memo-map = "0.3.3" never = "0.1.0" -once_cell = "1.21.3" +once_cell = "1.21.4" orchid-api = { version = "0.1.0", path = "../orchid-api" } orchid-api-derive = { version = "0.1.0", path = "../orchid-api-derive" } orchid-api-traits = { version = "0.1.0", path = "../orchid-api-traits" } orchid-async-utils = { version = "0.1.0", path = "../orchid-async-utils" } orchid-base = { version = "0.1.0", path = "../orchid-base" } -ordered-float = "5.1.0" -pastey = "0.2.1" +ordered-float = "5.3.0" +pastey = "0.2.2" substack = "1.1.1" -task-local = "0.1.0" -tokio = { version = "1.49.0", optional = true, features = [] } -tokio-util = { version = "0.7.17", optional = true, features = ["compat"] } +task-local = "0.1.1" +tokio = { version = "1.52.1", optional = true, features = ["io-std", "time"] } +tokio-util = { version = "0.7.18", optional = true, features = ["compat"] } trait-set = "0.3.0" unsync-pipe = { version = "0.2.0", path = "../unsync-pipe" } diff --git a/orchid-extension/src/binary.rs b/orchid-extension/src/binary.rs index 35c894a..0129419 100644 --- a/orchid-extension/src/binary.rs +++ b/orchid-extension/src/binary.rs @@ -39,7 +39,7 @@ pub fn orchid_extension_main_body(cx: ExtCx, builder: ExtensionBuilder) { /// ``` /// #[macro_use] /// use orchid_extension::dylib_main; -/// use orchid_extension::entrypoint::ExtensionBuilder; +/// use orchid_extension::ExtensionBuilder; /// /// dylib_main! { /// ExtensionBuilder::new("orchid-std::main") diff --git a/orchid-host/Cargo.toml b/orchid-host/Cargo.toml index 800319b..ab8b22f 100644 --- a/orchid-host/Cargo.toml +++ b/orchid-host/Cargo.toml @@ -12,9 +12,9 @@ async-once-cell = "0.5.4" bound = "0.6.0" chrono = "0.4.44" derive_destructure = "1.0.0" -futures = { version = "0.3.31", features = ["std"], default-features = false } +futures = { version = "0.3.32", features = ["std"], default-features = false } futures-locks = "0.7.1" -hashbrown = "0.16.1" +hashbrown = "0.17.0" itertools = "0.14.0" lazy_static = "1.5.0" libloading = { version = "0.9.0", optional = true } @@ -23,13 +23,14 @@ never = "0.1.0" num-traits = "0.2.19" orchid-api = { version = "0.1.0", path = "../orchid-api" } orchid-api-traits = { version = "0.1.0", path = "../orchid-api-traits" } +orchid-async-utils = { version = "0.1.0", path = "../orchid-async-utils" } orchid-base = { version = "0.1.0", path = "../orchid-base" } orchid-extension = { version = "0.1.0", path = "../orchid-extension", optional = true } -ordered-float = "5.1.0" -pastey = "0.2.1" +ordered-float = "5.3.0" +pastey = "0.2.2" substack = "1.1.1" -task-local = "0.1.0" -tokio = { version = "1.49.0", features = ["process"], optional = true } +task-local = "0.1.1" +tokio = { version = "1.52.1", features = ["process"], optional = true } tokio-util = { version = "0.7.18", features = ["compat"], optional = true } trait-set = "0.3.0" unsync-pipe = { version = "0.2.0", path = "../unsync-pipe" } diff --git a/orchid-host/src/cmd_system.rs b/orchid-host/src/cmd_system.rs index b3bcdcf..123a99f 100644 --- a/orchid-host/src/cmd_system.rs +++ b/orchid-host/src/cmd_system.rs @@ -1,7 +1,7 @@ use std::borrow::Cow; use std::cell::RefCell; use std::collections::VecDeque; -use std::fmt::Debug; +use std::fmt::{self, Debug}; use std::pin::pin; use std::rc::Rc; @@ -9,10 +9,10 @@ use async_event::Event; use async_fn_stream::stream; use chrono::{DateTime, Utc}; use futures::channel::mpsc; -use futures::future::LocalBoxFuture; -use futures::stream::FuturesUnordered; -use futures::{SinkExt, StreamExt, select}; +use futures::stream::select; +use futures::{FutureExt, SinkExt, StreamExt}; use never::Never; +use orchid_async_utils::{LocalSet, LocalSetController, local_set}; use orchid_base::{OrcErrv, Receipt, ReqHandle, Sym, fmt, is, log, mk_errv, sym}; use orchid_extension::{self as ox, AtomicFeatures as _, get_arg}; @@ -25,6 +25,7 @@ use crate::system::System; use crate::tree::Root; /// Events internally recognized by this system sent through [CommandQueue] +#[derive(Debug)] enum Task { RunCommand(Expr), Sleep(DateTime, Expr), @@ -72,7 +73,7 @@ impl CommandQueue { } } impl Debug for CommandQueue { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("CommandQueue").finish_non_exhaustive() } } @@ -99,12 +100,24 @@ pub enum CmdEvent { Err(OrcErrv), } +#[derive(Debug)] +enum TaskOutcome { + /// We need this so that we get an opportunity to exit when the last tasks + /// exited + None, + Next(Expr), + NonCommand(Expr), +} + pub struct CmdRunner { queue: CommandQueue, gas: Option, interrupted: Option, system: System, - futures: FuturesUnordered>>, + recv: mpsc::Receiver, + send: mpsc::Sender, + ctl: LocalSetController<'static, Never>, + local_set: LocalSet<'static, Never>, } impl CmdRunner { pub async fn new(root: &mut Root, ctx: Ctx, init: impl IntoIterator) -> Self { @@ -116,7 +129,9 @@ impl CmdRunner { .expect("Missing command system ctor"); let (cmd_root, system) = system_ctor.run(vec![]).await; *root = root.merge(&cmd_root).await.expect("Could not merge command system into tree"); - Self { futures: FuturesUnordered::new(), gas: None, interrupted: None, queue, system } + let (send, recv) = mpsc::channel(0); + let (ctl, local_set) = local_set(); + Self { send, recv, ctl, local_set, gas: None, interrupted: None, queue, system } } pub fn push(&self, expr: Expr) { self.queue.push(Task::RunCommand(expr)); } #[must_use] @@ -126,110 +141,79 @@ impl CmdRunner { pub fn set_gas(&mut self, gas: u64) { self.gas = Some(gas) } pub fn disable_gas(&mut self) { self.gas = None } pub async fn execute(&mut self, root: &Root) -> CmdEvent { - let waiting_on_queue = RefCell::new(false); - let (mut spawn, mut on_spawn) = mpsc::channel::>>(1); - let mut normalize_stream = pin!( - stream(async |mut h| { - loop { - waiting_on_queue.replace(false); - let mut xctx = match self.interrupted.take() { - None => match self.queue.get_new().await { - Task::RunCommand(expr) => ExecCtx::new(root.clone(), expr).await, - Task::Sleep(until, expr) => { - let queue = self.queue.clone(); - let ctx = queue.0.borrow_mut().ctx.clone(); - spawn - .send(Box::pin(async move { - let delta = until - Utc::now(); - match delta.to_std() { - Err(_) => - writeln!( - log("debug"), - "Negative sleep found ({delta}), requeuing as instant" - ) - .await, - Ok(delay) => ctx.sleep(delay).await, - }; - queue.push(Task::RunCommand(expr)); - None - })) - .await - .expect("Receiver stored in parent future"); - continue; - }, - Task::Exit => { - h.emit(CmdEvent::Exit).await; - break; - }, - }, - Some(xctx) => xctx, - }; - waiting_on_queue.replace(true); + #[derive(Debug)] + enum Event { + Finished(TaskOutcome), + Request(Task), + } + let queue_stream = pin!(stream(async |mut h| loop { + h.emit(self.queue.get_new().await).await + })); + let mut event_stream = pin!(select( + select(queue_stream.map(Event::Request), self.recv.by_ref().map(Event::Finished)), + ((&mut self.local_set).into_stream()) + .map(|_| panic!("self has the ctl so this should never exit cleanly")) + )); + while let Some(ev) = event_stream.next().await { + match ev { + Event::Finished(TaskOutcome::None) if self.ctl.is_empty() => return CmdEvent::Settled, + Event::Finished(TaskOutcome::None) => continue, + Event::Finished(TaskOutcome::Next(expr)) => self.queue.push(Task::RunCommand(expr)), + Event::Finished(TaskOutcome::NonCommand(val)) => return CmdEvent::NonCommand(val), + Event::Request(Task::Exit) => return CmdEvent::Exit, + Event::Request(Task::Sleep(until, expr)) => { + let queue = self.queue.clone(); + let ctx = queue.0.borrow_mut().ctx.clone(); + self.ctl.spawn(async move { + let delta = until - Utc::now(); + match delta.to_std() { + Err(_) => + writeln!(log("debug"), "Negative sleep found ({delta}), requeuing as instant").await, + Ok(delay) => ctx.sleep(delay).await, + }; + queue.push(Task::RunCommand(expr)); + Ok(()) + }) + }, + Event::Request(Task::RunCommand(expr)) => { + let mut xctx = ExecCtx::new(root.clone(), expr).await; xctx.set_gas(self.gas); - let res = xctx.execute().await; - match res { - ExecResult::Err(e, gas) => { + let norm = match xctx.execute().await { + ExecResult::Err(err, gas) => { self.gas = gas; - h.emit(CmdEvent::Err(e)).await; - }, - ExecResult::Gas(exec) => { - self.interrupted = Some(exec); - h.emit(CmdEvent::Gas).await; + return CmdEvent::Err(err); }, ExecResult::Value(val, gas) => { self.gas = gas; - let Some(atom) = val.as_atom().await else { - h.emit(CmdEvent::NonCommand(val)).await; - continue; - }; - let queue = self.queue.clone(); - let ctx = queue.0.borrow_mut().ctx.clone(); - spawn - .send(Box::pin(async move { - match atom.ipc(ox::std_reqs::StartCommand).await { - None => Some(CmdEvent::NonCommand(val)), - Some(None) => None, - Some(Some(expr)) => { - let from_api_cx = ExprFromApiCtx { ctx, sys: atom.api_ref().owner }; - queue.push(Task::RunCommand( - Expr::from_api(expr, PathSetBuilder::new(), from_api_cx).await, - )); - None - }, - } - })) - .await - .expect("Receiver is owned by the layer that polls this"); + val }, - } - } - }) - .fuse() - ); - loop { - let task = select!( - r_opt = self.futures.by_ref().next() => match r_opt { - Some(Some(r)) => { - eprintln!("Exiting because "); - break r - }, - None if *waiting_on_queue.borrow() => { - eprintln!("Exiting because settled"); - break CmdEvent::Settled - }, - None | Some(None) => continue, + ExecResult::Gas(xctx) => { + self.interrupted = Some(xctx); + return CmdEvent::Gas; + }, + }; + let Some(atom) = norm.as_atom().await else { + return CmdEvent::NonCommand(norm); + }; + let queue = self.queue.clone(); + let ctx = queue.0.borrow_mut().ctx.clone(); + let mut send = self.send.clone(); + self.ctl.spawn(async move { + match atom.ipc(ox::std_reqs::StartCommand).await { + None => send.send(TaskOutcome::NonCommand(norm)).await.unwrap(), + Some(None) => send.send(TaskOutcome::None).await.unwrap(), + Some(Some(expr)) => { + let from_api_cx = ExprFromApiCtx { ctx, sys: atom.api_ref().owner }; + let expr = Expr::from_api(expr, PathSetBuilder::new(), from_api_cx).await; + send.send(TaskOutcome::Next(expr)).await.unwrap(); + }, + }; + Ok(()) + }); }, - r = normalize_stream.by_ref().next() => match r { - None => break CmdEvent::Exit, - Some(r) => break r, - }, - task = on_spawn.by_ref().next() => match task { - None => continue, - Some(r) => r, - }, - ); - self.futures.push(task) + } } + unreachable!("Since the localset cannot exit, the function cannot exit either") } } diff --git a/orchid-std/Cargo.toml b/orchid-std/Cargo.toml index 790d8c2..6ea8ead 100644 --- a/orchid-std/Cargo.toml +++ b/orchid-std/Cargo.toml @@ -16,26 +16,26 @@ path = "src/lib.rs" async-event = "0.2.1" async-fn-stream = { version = "0.1.0", path = "../async-fn-stream" } async-once-cell = "0.5.4" -chrono = "0.4.43" -futures = { version = "0.3.31", features = ["std"], default-features = false } -hashbrown = "0.16.1" +chrono = "0.4.44" +futures = { version = "0.3.32", features = ["std"], default-features = false } +hashbrown = "0.17.0" itertools = "0.14.0" never = "0.1.0" -once_cell = "1.21.3" +once_cell = "1.21.4" orchid-api = { version = "0.1.0", path = "../orchid-api" } orchid-api-derive = { version = "0.1.0", path = "../orchid-api-derive" } orchid-api-traits = { version = "0.1.0", path = "../orchid-api-traits" } orchid-base = { version = "0.1.0", path = "../orchid-base" } orchid-extension = { version = "0.1.0", path = "../orchid-extension", features = [ - "tokio", + "tokio", ] } -ordered-float = "5.1.0" -pastey = "0.2.1" -rust_decimal = "1.39.0" +ordered-float = "5.3.0" +pastey = "0.2.2" +rust_decimal = "1.41.0" subslice-offset = "0.1.1" substack = "1.1.1" -tokio = { version = "1.49.0", features = ["full"] } -unicode-segmentation = "1.12.0" +tokio = { version = "1.52.1", features = ["full"] } +unicode-segmentation = "1.13.2" [dev-dependencies] test_executors = "0.4.1" diff --git a/orchid-std/src/std/string/str_lexer.rs b/orchid-std/src/std/string/str_lexer.rs index 5440e94..4608815 100644 --- a/orchid-std/src/std/string/str_lexer.rs +++ b/orchid-std/src/std/string/str_lexer.rs @@ -137,7 +137,9 @@ impl Lexer for StringLexer { ret = Some(add_frag(ret, to_str_call).await); } else if tail.starts_with('\\') { // parse_string will deal with it, we just have to skip the next char - tail = &tail[2..]; + let mut ch = tail.chars(); + cur.extend(ch.by_ref().take(2)); + tail = ch.as_str(); } else { let mut ch = tail.chars(); if let Some(c) = ch.next() { diff --git a/orcx/Cargo.toml b/orcx/Cargo.toml index e7341da..7d7cacf 100644 --- a/orcx/Cargo.toml +++ b/orcx/Cargo.toml @@ -9,9 +9,9 @@ authors = ["Lawrence Bethlenfalvy "] [dependencies] async-fn-stream = { version = "0.1.0", path = "../async-fn-stream" } camino = "1.2.2" -clap = { version = "4.5.54", features = ["derive", "env", "cargo"] } -ctrlc = "3.5.1" -futures = "0.3.31" +clap = { version = "4.6.1", features = ["derive", "env", "cargo"] } +ctrlc = "3.5.2" +futures = "0.3.32" itertools = "0.14.0" never = "0.1.0" orchid-api = { version = "0.1.0", path = "../orchid-api" } @@ -21,7 +21,7 @@ orchid-host = { version = "0.1.0", path = "../orchid-host", features = [ "tokio", "orchid-extension", ] } -stacker = "0.1.23" +stacker = "0.1.24" substack = "1.1.1" -tokio = { version = "1.49.0", features = ["full"] } +tokio = { version = "1.52.1", features = ["full"] } tokio-util = { version = "0.7.18", features = ["compat"] } diff --git a/unsync-pipe/Cargo.toml b/unsync-pipe/Cargo.toml index 217edf8..5e74bd3 100644 --- a/unsync-pipe/Cargo.toml +++ b/unsync-pipe/Cargo.toml @@ -10,9 +10,10 @@ homepage = "https://git.lbfalvy.com/Orchid/orchid" [dev-dependencies] futures = "0.3.31" itertools = "0.14.0" -rand = "0.9.2" -rand_chacha = "0.9.0" +rand = "0.10.1" +rand_chacha = "0.10.0" test_executors = "0.4.1" +orchid-async-utils = { version = "0.1.0", path = "../orchid-async-utils" } [dependencies] futures-io = "0.3.31" diff --git a/unsync-pipe/src/lib.rs b/unsync-pipe/src/lib.rs index a739f8d..762adca 100644 --- a/unsync-pipe/src/lib.rs +++ b/unsync-pipe/src/lib.rs @@ -145,16 +145,9 @@ impl AsyncRingbuffer { self.write_waker = Trigger::new(waker.clone()); Poll::Pending } - fn reader_wait(&mut self, waker: &Waker) -> Poll> { - if self.writer_dropped { - return Poll::Ready(Err(io::Error::new( - io::ErrorKind::BrokenPipe, - "Pipe already closed from writer end.", - ))); - } + fn reader_wait(&mut self, waker: &Waker) { self.read_waker.drop(); self.read_waker = Trigger::new(waker.clone()); - Poll::Pending } unsafe fn non_wrapping_write_unchecked(&mut self, buf: &[u8]) { let write_ptr = unsafe { self.start.add(self.write_idx) }; @@ -326,12 +319,22 @@ impl AsyncRead for Reader { buf: &mut [u8], ) -> Poll> { let data = unsafe { self.0.as_mut().expect("Cannot be null") }; - if !buf.is_empty() && data.is_full() { + if buf.is_empty() { + return Poll::Ready(Ok(0)); + } + if data.is_full() { + // may be blocked so wake data.wake_writer(); } - let poll = if !buf.is_empty() && data.is_empty() { + let poll = if data.is_empty() { // Nothing to read, waiting... - data.reader_wait(cx.waker()) + data.wake_writer(); + if !data.writer_dropped { + data.reader_wait(cx.waker()); + Poll::Pending + } else { + Poll::Ready(Ok(0)) + } } else { Poll::Ready(Ok(data.wrapping_read(buf))) }; @@ -358,9 +361,9 @@ mod tests { use futures::future::join; use futures::{AsyncReadExt, AsyncWriteExt}; use itertools::Itertools; - use rand::{Rng, SeedableRng}; + use orchid_async_utils::debug::spin_on; + use rand::{RngExt, SeedableRng}; use rand_chacha::ChaCha8Rng; - use test_executors::spin_on; use super::*; @@ -410,4 +413,16 @@ mod tests { join(write_fut, read_fut).await; }) } + + #[test] + fn read_to_end() { + let (mut write, mut read) = pipe(1024); + spin_on(async { + write.write_all(&[0, 1, 2, 3, 4]).await.unwrap(); + std::mem::drop(write); + let mut dest = Vec::new(); + read.read_to_end(&mut dest).await.unwrap(); + assert_eq!(dest, [0, 1, 2, 3, 4]); + }) + } } diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 38ee12d..53fbc0a 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -4,4 +4,4 @@ version = "0.1.0" edition = "2024" [dependencies] -clap = { version = "4.5.54", features = ["derive"] } +clap = { version = "4.6.1", features = ["derive"] }