From 5396669e46f1306d930e5d92748eeb302fccaa9a Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Thu, 24 Feb 2022 05:32:52 -0500 Subject: move to tokio --- CHANGELOG.md | 6 + Cargo.lock | 627 +++++++++++++--------------------------------- Cargo.toml | 20 +- src/bin/ttyplay/event.rs | 46 ++-- src/bin/ttyplay/frames.rs | 39 ++- src/bin/ttyplay/input.rs | 17 +- src/bin/ttyplay/main.rs | 19 +- src/bin/ttyplay/timer.rs | 199 ++++++++------- src/bin/ttyrec/main.rs | 91 +++---- 9 files changed, 384 insertions(+), 680 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b735851..6e68504 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [Unreleased] + +### Changed + +* Move to tokio + ## [0.1.3] - 2021-12-15 ### Changed diff --git a/Cargo.lock b/Cargo.lock index e2aebfc..2a57c2f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,9 +13,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.51" +version = "1.0.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203" +checksum = "159bb86af3a200e19a068f4224eae4c8bb2d0fa054c7e5d1cacd5cef95e684cd" [[package]] name = "arrayvec" @@ -23,141 +23,6 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" -[[package]] -name = "async-channel" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319" -dependencies = [ - "concurrent-queue", - "event-listener", - "futures-core", -] - -[[package]] -name = "async-executor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" -dependencies = [ - "async-task", - "concurrent-queue", - "fastrand", - "futures-lite", - "once_cell", - "slab", -] - -[[package]] -name = "async-global-executor" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9586ec52317f36de58453159d48351bc244bc24ced3effc1fce22f3d48664af6" -dependencies = [ - "async-channel", - "async-executor", - "async-io", - "async-mutex", - "blocking", - "futures-lite", - "num_cpus", - "once_cell", -] - -[[package]] -name = "async-io" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a811e6a479f2439f0c04038796b5cfb3d2ad56c230e0f2d3f7b04d68cfee607b" -dependencies = [ - "concurrent-queue", - "futures-lite", - "libc", - "log", - "once_cell", - "parking", - "polling", - "slab", - "socket2", - "waker-fn", - "winapi", -] - -[[package]] -name = "async-lock" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6a8ea61bf9947a1007c5cada31e647dbc77b103c679858150003ba697ea798b" -dependencies = [ - "event-listener", -] - -[[package]] -name = "async-mutex" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e" -dependencies = [ - "event-listener", -] - -[[package]] -name = "async-process" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83137067e3a2a6a06d67168e49e68a0957d215410473a740cea95a2425c0b7c6" -dependencies = [ - "async-io", - "blocking", - "cfg-if", - "event-listener", - "futures-lite", - "libc", - "once_cell", - "signal-hook", - "winapi", -] - -[[package]] -name = "async-std" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8056f1455169ab86dd47b47391e4ab0cbd25410a70e9fe675544f49bafaf952" -dependencies = [ - "async-channel", - "async-global-executor", - "async-io", - "async-lock", - "async-process", - "crossbeam-utils", - "futures-channel", - "futures-core", - "futures-io", - "futures-lite", - "gloo-timers", - "kv-log-macro", - "log", - "memchr", - "num_cpus", - "once_cell", - "pin-project-lite", - "pin-utils", - "slab", - "wasm-bindgen-futures", -] - -[[package]] -name = "async-task" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0" - -[[package]] -name = "atomic-waker" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" - [[package]] name = "atty" version = "0.2.14" @@ -171,9 +36,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "bitflags" @@ -182,36 +47,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] -name = "blocking" +name = "bytes" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046e47d4b2d391b1f6f8b407b1deb8dee56c1852ccd868becf2710f601b5f427" -dependencies = [ - "async-channel", - "async-task", - "atomic-waker", - "fastrand", - "futures-lite", - "once_cell", -] - -[[package]] -name = "bumpalo" -version = "3.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c" - -[[package]] -name = "cache-padded" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba" - -[[package]] -name = "cc" -version = "1.0.72" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" [[package]] name = "cfg-if" @@ -235,99 +74,6 @@ dependencies = [ "vec_map", ] -[[package]] -name = "concurrent-queue" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" -dependencies = [ - "cache-padded", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" -dependencies = [ - "cfg-if", - "lazy_static", -] - -[[package]] -name = "ctor" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "event-listener" -version = "2.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59" - -[[package]] -name = "fastrand" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b394ed3d285a429378d3b384b9eb1285267e7df4b166df24b7a6939a04dc392e" -dependencies = [ - "instant", -] - -[[package]] -name = "futures-channel" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888" -dependencies = [ - "futures-core", -] - -[[package]] -name = "futures-core" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d" - -[[package]] -name = "futures-io" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377" - -[[package]] -name = "futures-lite" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] - -[[package]] -name = "gloo-timers" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f16c88aa13d2656ef20d1c042086b8767bbe2bdb62526894275a1b062161b2e" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "heck" version = "0.3.3" @@ -346,39 +92,12 @@ dependencies = [ "libc", ] -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - [[package]] name = "itoa" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" -[[package]] -name = "js-sys" -version = "0.3.55" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "kv-log-macro" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" -dependencies = [ - "log", -] - [[package]] name = "lazy_static" version = "1.4.0" @@ -387,9 +106,18 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.112" +version = "0.2.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4" + +[[package]] +name = "lock_api" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" +checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" +dependencies = [ + "scopeguard", +] [[package]] name = "log" @@ -398,7 +126,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ "cfg-if", - "value-bag", ] [[package]] @@ -417,23 +144,51 @@ dependencies = [ ] [[package]] -name = "nix" -version = "0.23.0" +name = "mio" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f305c2c2e4c39a82f7bf0bf65fb557f9070ce06781d4f2454295cc34b1c43188" +checksum = "ba272f85fa0b41fc91872be579b3bbe0f56b792aa361a380eb669469f68dafb2" +dependencies = [ + "libc", + "log", + "miow", + "ntapi", + "winapi", +] + +[[package]] +name = "miow" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" +dependencies = [ + "winapi", +] + +[[package]] +name = "nix" +version = "0.23.1" dependencies = [ "bitflags", - "cc", "cfg-if", "libc", "memoffset", ] +[[package]] +name = "ntapi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" +dependencies = [ + "winapi", +] + [[package]] name = "num_cpus" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" dependencies = [ "hermit-abi", "libc", @@ -446,10 +201,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" [[package]] -name = "parking" -version = "2.0.0" +name = "parking_lot" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" +checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] [[package]] name = "paw" @@ -480,28 +252,9 @@ checksum = "7f0b59668fe80c5afe998f0c0bf93322bf2cd66cafeeb80581f291716f3467f2" [[package]] name = "pin-project-lite" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "polling" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259" -dependencies = [ - "cfg-if", - "libc", - "log", - "wepoll-ffi", - "winapi", -] +checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" [[package]] name = "proc-macro-error" @@ -529,9 +282,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.34" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f84e92c0f7c9d58328b85a78557813e4bd845130db68d7184635344399423b1" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" dependencies = [ "unicode-xid", ] @@ -539,45 +292,35 @@ dependencies = [ [[package]] name = "pty-process" version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5c0159357669a990d96531d7095fd9d5eaa9f59d3d7d522f65b438dc8d1c109" dependencies = [ - "async-io", - "async-process", "libc", "nix", + "tokio", ] [[package]] name = "quote" -version = "1.0.10" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" dependencies = [ "proc-macro2", ] [[package]] -name = "signal-hook" -version = "0.3.12" +name = "redox_syscall" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c35dfd12afb7828318348b8c408383cf5071a086c1d4ab1c0f9840ec92dbb922" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" dependencies = [ - "libc", - "signal-hook-registry", + "bitflags", ] [[package]] -name = "signal-hook-async-std" -version = "0.2.1" +name = "scopeguard" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90526e74631c69a79b38212e3d4fda4b00de9d6be56b3cead133bf67ad371af1" -dependencies = [ - "async-io", - "futures-lite", - "libc", - "signal-hook", -] +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "signal-hook-registry" @@ -589,16 +332,16 @@ dependencies = [ ] [[package]] -name = "slab" -version = "0.4.5" +name = "smallvec" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" [[package]] name = "socket2" -version = "0.4.2" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" dependencies = [ "libc", "winapi", @@ -612,9 +355,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "structopt" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40b9788f4202aa75c240ecc9c15c65185e6a39ccdeb0fd5d008b98825464c87c" +checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" dependencies = [ "clap", "lazy_static", @@ -637,9 +380,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.82" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" +checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" dependencies = [ "proc-macro2", "quote", @@ -669,14 +412,11 @@ dependencies = [ [[package]] name = "textmode" version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf9ecdb23aae465624a900ae8c795e17f46e081b8454f8ea5b3b5c27a9e7884" dependencies = [ - "blocking", - "futures-lite", "itoa", "nix", "terminal_size", + "tokio", "vt100", ] @@ -690,13 +430,42 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "tokio" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" +dependencies = [ + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "once_cell", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "winapi", +] + +[[package]] +name = "tokio-macros" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "ttyrec" version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55485cfff84edb41e40461911533252cbf57fd0cb0de294b7b5d6b780f1fa755" dependencies = [ - "futures-lite", + "tokio", ] [[package]] @@ -704,24 +473,22 @@ name = "ttyrec-bin" version = "0.1.3" dependencies = [ "anyhow", - "async-std", "libc", "paw", "pty-process", - "signal-hook", - "signal-hook-async-std", "structopt", "terminal_size", "textmode", + "tokio", "ttyrec", "vt100", ] [[package]] name = "unicode-segmentation" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" +checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" [[package]] name = "unicode-width" @@ -741,16 +508,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "936e4b492acfd135421d8dca4b1aa80a7bfc26e702ef3af710e0752684df5372" -[[package]] -name = "value-bag" -version = "1.0.0-alpha.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79923f7731dc61ebfba3633098bf3ac533bbd35ccd8c57e7088d9a5eebe0263f" -dependencies = [ - "ctor", - "version_check", -] - [[package]] name = "vec_map" version = "0.8.2" @@ -759,15 +516,15 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "vt100" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24591a10ef6682b21a3fea7a31629109e6d37bf46b4bf994ee8534f64b89dffb" +checksum = "7541312ce0411d878458abf25175d878e8edc38f9f12ee8eed1d65870cacf540" dependencies = [ "itoa", "log", @@ -797,114 +554,66 @@ dependencies = [ ] [[package]] -name = "waker-fn" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" - -[[package]] -name = "wasm-bindgen" -version = "0.2.78" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.78" +name = "winapi" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ - "bumpalo", - "lazy_static", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", ] [[package]] -name = "wasm-bindgen-futures" -version = "0.4.28" +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8d7523cb1f2a4c96c1317ca690031b714a51cc14e05f712446691f413f5d39" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] -name = "wasm-bindgen-macro" -version = "0.2.78" +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.78" +name = "windows-sys" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" +checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6" dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", ] [[package]] -name = "wasm-bindgen-shared" -version = "0.2.78" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" - -[[package]] -name = "web-sys" -version = "0.3.55" +name = "windows_aarch64_msvc" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] +checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5" [[package]] -name = "wepoll-ffi" -version = "0.1.2" +name = "windows_i686_gnu" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" -dependencies = [ - "cc", -] +checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615" [[package]] -name = "winapi" -version = "0.3.9" +name = "windows_i686_msvc" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] +checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172" [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "windows_x86_64_gnu" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc" [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "windows_x86_64_msvc" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316" diff --git a/Cargo.toml b/Cargo.toml index 6cc8f90..7df863a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,15 +13,19 @@ license = "MIT" include = ["src/**/*", "LICENSE", "README.md", "CHANGELOG.md"] [dependencies] -anyhow = "1.0.51" -async-std = { version = "1.10.0", features = ["unstable"] } -libc = "0.2.112" +anyhow = "1.0.55" +libc = "0.2.119" paw = "1.0.0" -pty-process = { version = "0.2.0", features = ["backend-async-std"] } -signal-hook = "0.3.12" -signal-hook-async-std = "0.2.1" -structopt = { version = "0.3.25", features = ["paw", "wrap_help"] } +pty-process = { version = "0.2.0", features = ["async"] } +structopt = { version = "0.3.26", features = ["paw", "wrap_help"] } terminal_size = "0.1.17" textmode = { version = "0.3.0", features = ["async"] } +tokio = { version = "1.17.0", features = ["full"] } ttyrec = { version = "0.3.3", features = ["async"] } -vt100 = "0.15.0" +vt100 = "0.15.1" + +[patch.crates-io] +nix = { path = "../src/nix" } +pty-process = { path = "../pty-process" } +textmode = { path = "../textmode" } +ttyrec = { path = "../ttyrec" } diff --git a/src/bin/ttyplay/event.rs b/src/bin/ttyplay/event.rs index 534b761..0be477e 100644 --- a/src/bin/ttyplay/event.rs +++ b/src/bin/ttyplay/event.rs @@ -1,3 +1,4 @@ +#[derive(Debug)] pub enum Event { FrameTransition((usize, Box)), FrameLoaded(Option), @@ -13,6 +14,7 @@ pub enum Event { Quit, } +#[derive(Debug)] pub enum TimerAction { Pause, FirstFrame, @@ -27,23 +29,26 @@ pub enum TimerAction { } struct Reader { - pending: async_std::sync::Mutex, - cvar: async_std::sync::Condvar, + pending: tokio::sync::Mutex, + // XXX not quite a condvar, but i think close enough as long as there is + // only ever one consumer? see + // https://github.com/tokio-rs/tokio/issues/3892 + cvar: tokio::sync::Notify, } impl Reader { fn new( - input: async_std::channel::Receiver, - ) -> async_std::sync::Arc { + mut input: tokio::sync::mpsc::UnboundedReceiver, + ) -> std::sync::Arc { let this = Self { - pending: async_std::sync::Mutex::new(Pending::new()), - cvar: async_std::sync::Condvar::new(), + pending: tokio::sync::Mutex::new(Pending::new()), + cvar: tokio::sync::Notify::new(), }; - let this = async_std::sync::Arc::new(this); + let this = std::sync::Arc::new(this); { let this = this.clone(); - async_std::task::spawn(async move { - while let Ok(event) = input.recv().await { + tokio::task::spawn(async move { + while let Some(event) = input.recv().await { this.event(event).await; } this.event(Event::Quit).await; @@ -53,13 +58,14 @@ impl Reader { } async fn read(&self) -> Option { - let mut pending = self - .cvar - .wait_until(self.pending.lock().await, |pending| { - pending.has_event() - }) - .await; - pending.get_event() + loop { + let mut pending = self.pending.lock().await; + if pending.has_event() { + return pending.get_event(); + } + drop(pending); + self.cvar.notified().await; + } } async fn event(&self, event: Event) { @@ -197,8 +203,8 @@ impl Pending { } pub async fn handle_events( - event_r: async_std::channel::Receiver, - timer_w: async_std::channel::Sender, + event_r: tokio::sync::mpsc::UnboundedReceiver, + timer_w: tokio::sync::mpsc::UnboundedSender, mut output: textmode::Output, ) -> anyhow::Result<()> { let mut display = crate::display::Display::new(); @@ -206,7 +212,7 @@ pub async fn handle_events( while let Some(event) = events.read().await { match event { Event::TimerAction(action) => { - timer_w.send(action).await?; + timer_w.send(action)?; continue; } Event::FrameTransition((idx, screen)) => { @@ -240,7 +246,7 @@ pub async fn handle_events( } Event::RunSearch(s, backwards) => { display.clear_search(); - timer_w.send(TimerAction::Search(s, backwards)).await?; + timer_w.send(TimerAction::Search(s, backwards))?; } Event::Error(e) => { return Err(e); diff --git a/src/bin/ttyplay/frames.rs b/src/bin/ttyplay/frames.rs index d6073dc..1cf2d01 100644 --- a/src/bin/ttyplay/frames.rs +++ b/src/bin/ttyplay/frames.rs @@ -21,13 +21,13 @@ impl Frame { pub struct FrameData { frames: Vec, done_reading: bool, - new_frame_w: async_std::channel::Sender>, - new_frame_r: async_std::channel::Receiver>, + new_frame_w: tokio::sync::watch::Sender>, + new_frame_r: tokio::sync::watch::Receiver>, } impl FrameData { pub fn new() -> Self { - let (new_frame_w, new_frame_r) = async_std::channel::unbounded(); + let (new_frame_w, new_frame_r) = tokio::sync::watch::channel(Some(0)); Self { frames: vec![], done_reading: false, @@ -72,7 +72,6 @@ impl FrameData { self.frames.push(frame); self.new_frame_w .send(Some(self.frames.len())) - .await // new_frame_w is never closed, so this can never fail .unwrap(); } @@ -81,7 +80,6 @@ impl FrameData { self.done_reading = true; self.new_frame_w .send(None) - .await // new_frame_w is never closed, so this can never fail .unwrap(); } @@ -98,16 +96,15 @@ impl FrameData { if self.done_reading { return Box::pin(std::future::ready(false)); } - let new_frame_r = self.new_frame_r.clone(); + let mut new_frame_r = self.new_frame_r.clone(); Box::pin(async move { - while let Some(new_len) = new_frame_r - .recv() - .await - // new_frame_r is never closed, so this can never fail - .unwrap() - { - if i < new_len { - return true; + while new_frame_r.changed().await.is_ok() { + if let Some(new_len) = *new_frame_r.borrow() { + if i < new_len { + return true; + } + } else { + break; } } false @@ -116,13 +113,13 @@ impl FrameData { } pub fn load_from_file( - frames: async_std::sync::Arc>, - fh: async_std::fs::File, - event_w: async_std::channel::Sender, + frames: std::sync::Arc>, + fh: tokio::fs::File, + event_w: tokio::sync::mpsc::UnboundedSender, clamp: Option, ) { let clamp = clamp.map(std::time::Duration::from_millis); - async_std::task::spawn(async move { + tokio::task::spawn(async move { let mut reader = ttyrec::Reader::new(fh); let size = terminal_size::terminal_size().map_or( (24, 80), @@ -144,21 +141,19 @@ pub fn load_from_file( } } parser.process(&frame.data); - let mut frames = frames.lock_arc().await; + let mut frames = frames.clone().lock_owned().await; frames .add_frame(Frame::new(parser.screen().clone(), delay)) .await; event_w .send(crate::event::Event::FrameLoaded(Some(frames.count()))) - .await // event_w is never closed, so this can never fail .unwrap(); prev_delay = delay; } - frames.lock_arc().await.done_reading().await; + frames.lock_owned().await.done_reading().await; event_w .send(crate::event::Event::FrameLoaded(None)) - .await // event_w is never closed, so this can never fail .unwrap(); }); diff --git a/src/bin/ttyplay/input.rs b/src/bin/ttyplay/input.rs index 81a2fef..fe7dc30 100644 --- a/src/bin/ttyplay/input.rs +++ b/src/bin/ttyplay/input.rs @@ -1,18 +1,17 @@ -pub fn spawn_task( - event_w: async_std::channel::Sender, - mut input: textmode::Input, +pub fn spawn_thread( + event_w: tokio::sync::mpsc::UnboundedSender, + mut input: textmode::blocking::Input, ) { - async_std::task::spawn(async move { + std::thread::spawn(move || { let mut search: Option = None; let mut prev_search = None; loop { - let key = match input.read_key().await { + let key = match input.read_key() { Ok(Some(key)) => key, Ok(None) => break, Err(e) => { event_w .send(crate::event::Event::Error(anyhow::anyhow!(e))) - .await // event_w is never closed, so this can never fail .unwrap(); break; @@ -26,7 +25,6 @@ pub fn spawn_task( .send(crate::event::Event::ActiveSearch( search_contents.clone(), )) - .await // event_w is never closed, so this can never fail .unwrap(); } @@ -36,7 +34,6 @@ pub fn spawn_task( .send(crate::event::Event::ActiveSearch( search_contents.clone(), )) - .await // event_w is never closed, so this can never fail .unwrap(); } @@ -46,7 +43,6 @@ pub fn spawn_task( search_contents.clone(), false, )) - .await // event_w is never closed, so this can never fail .unwrap(); prev_search = search; @@ -55,7 +51,6 @@ pub fn spawn_task( textmode::Key::Escape => { event_w .send(crate::event::Event::CancelSearch) - .await // event_w is never closed, so this can never fail .unwrap(); search = None; @@ -138,7 +133,7 @@ pub fn spawn_task( _ => continue, }; // event_w is never closed, so this can never fail - event_w.send(event).await.unwrap(); + event_w.send(event).unwrap(); } } }); diff --git a/src/bin/ttyplay/main.rs b/src/bin/ttyplay/main.rs index 499c7b9..832b870 100644 --- a/src/bin/ttyplay/main.rs +++ b/src/bin/ttyplay/main.rs @@ -56,6 +56,7 @@ struct Opt { speed: u32, } +#[tokio::main] async fn async_main(opt: Opt) -> anyhow::Result<()> { let Opt { file, @@ -66,19 +67,19 @@ async fn async_main(opt: Opt) -> anyhow::Result<()> { let speed = speed.clamp(0, 8); - let fh = async_std::fs::File::open(file).await?; + let fh = tokio::fs::File::open(file).await?; - let mut input = textmode::Input::new().await?; + let mut input = textmode::blocking::Input::new()?; let mut output = textmode::Output::new().await?; let _input_guard = input.take_raw_guard(); let _output_guard = output.take_screen_guard(); - let (event_w, event_r) = async_std::channel::unbounded(); - let (timer_w, timer_r) = async_std::channel::unbounded(); + let (event_w, event_r) = tokio::sync::mpsc::unbounded_channel(); + let (timer_w, timer_r) = tokio::sync::mpsc::unbounded_channel(); - input::spawn_task(event_w.clone(), input); + input::spawn_thread(event_w.clone(), input); - let frame_data = async_std::sync::Arc::new(async_std::sync::Mutex::new( + let frame_data = std::sync::Arc::new(tokio::sync::Mutex::new( frames::FrameData::new(), )); frames::load_from_file(frame_data.clone(), fh, event_w.clone(), clamp); @@ -93,15 +94,15 @@ async fn async_main(opt: Opt) -> anyhow::Result<()> { event::handle_events(event_r, timer_w.clone(), output).await?; - timer_w.send(event::TimerAction::Quit).await?; - timer_task.await; + timer_w.send(event::TimerAction::Quit)?; + timer_task.await?; Ok(()) } #[paw::main] fn main(opt: Opt) { - match async_std::task::block_on(async_main(opt)) { + match async_main(opt) { Ok(_) => (), Err(e) => { eprintln!("ttyplay: {}", e); diff --git a/src/bin/ttyplay/timer.rs b/src/bin/ttyplay/timer.rs index 12ff17c..0b918aa 100644 --- a/src/bin/ttyplay/timer.rs +++ b/src/bin/ttyplay/timer.rs @@ -1,21 +1,18 @@ -use async_std::prelude::FutureExt as _; - pub fn spawn_task( - event_w: async_std::channel::Sender, - frames: async_std::sync::Arc< - async_std::sync::Mutex, + event_w: tokio::sync::mpsc::UnboundedSender, + frames: std::sync::Arc>, + mut timer_r: tokio::sync::mpsc::UnboundedReceiver< + crate::event::TimerAction, >, - timer_r: async_std::channel::Receiver, pause_at_start: bool, speed: u32, -) -> async_std::task::JoinHandle<()> { - async_std::task::spawn(async move { +) -> tokio::task::JoinHandle<()> { + tokio::task::spawn(async move { let mut idx = 0; let mut start_time = std::time::Instant::now(); let mut paused_time = if pause_at_start { event_w .send(crate::event::Event::Paused(true)) - .await // event_w is never closed, so this can never fail .unwrap(); Some(start_time) @@ -25,20 +22,17 @@ pub fn spawn_task( let mut force_update_time = false; let mut playback_ratio = 2_u32.pow(speed); loop { - enum Res { - Wait(Option>), - TimerAction( - Result< - crate::event::TimerAction, - async_std::channel::RecvError, - >, - ), - } let wait = async { - let wait_read = frames.lock_arc().await.wait_for_frame(idx); + let wait_read = + frames.clone().lock_owned().await.wait_for_frame(idx); if wait_read.await { - let frame = - frames.lock_arc().await.get(idx).unwrap().clone(); + let frame = frames + .clone() + .lock_owned() + .await + .get(idx) + .unwrap() + .clone(); if force_update_time { let now = std::time::Instant::now(); start_time = now - frame.delay() * playback_ratio / 16 @@ -54,7 +48,7 @@ pub fn spawn_task( } else if paused_time.is_some() { std::future::pending::<()>().await; } else { - async_std::task::sleep( + tokio::time::sleep( (start_time + frame.delay() * playback_ratio / 16) .saturating_duration_since( @@ -63,117 +57,120 @@ pub fn spawn_task( ) .await; } - Res::Wait(Some(Box::new(frame.into_screen()))) + Some(Box::new(frame.into_screen())) } else { - Res::Wait(None) + None } }; - let action = async { Res::TimerAction(timer_r.recv().await) }; - match wait.race(action).await { - Res::Wait(Some(screen)) => { + tokio::select! { + screen = wait => if let Some(screen) = screen { event_w .send(crate::event::Event::FrameTransition(( idx, screen, ))) - .await // event_w is never closed, so this can never fail .unwrap(); idx += 1; } - Res::Wait(None) => { - idx = frames.lock_arc().await.count() - 1; + else { + idx = frames.clone().lock_owned().await.count() - 1; paused_time = Some(std::time::Instant::now()); event_w .send(crate::event::Event::Paused(true)) - .await // event_w is never closed, so this can never fail .unwrap(); - } - Res::TimerAction(Ok(action)) => match action { - crate::event::TimerAction::Pause => { - let now = std::time::Instant::now(); - if let Some(time) = paused_time.take() { - start_time += now - time; - } else { - paused_time = Some(now); - } - event_w - .send(crate::event::Event::Paused( - paused_time.is_some(), - )) - .await - // event_w is never closed, so this can never fail - .unwrap(); - } - crate::event::TimerAction::FirstFrame => { - idx = 0; - force_update_time = true; - } - crate::event::TimerAction::LastFrame => { - idx = frames.lock_arc().await.count() - 1; - force_update_time = true; - } - // force_update_time will immediately transition to the - // next frame and do idx += 1 on its own - crate::event::TimerAction::NextFrame => { - force_update_time = true; - } - crate::event::TimerAction::PreviousFrame => { - idx = idx.saturating_sub(2); - force_update_time = true; - } - crate::event::TimerAction::SpeedUp => { - if playback_ratio > 1 { - playback_ratio /= 2; + }, + action = timer_r.recv() => match action { + Some(action) => match action { + crate::event::TimerAction::Pause => { let now = std::time::Instant::now(); - start_time = now - (now - start_time) / 2; + if let Some(time) = paused_time.take() { + start_time += now - time; + } else { + paused_time = Some(now); + } event_w - .send(crate::event::Event::Speed( - playback_ratio, + .send(crate::event::Event::Paused( + paused_time.is_some(), )) - .await // event_w is never closed, so this can never // fail .unwrap(); } - } - crate::event::TimerAction::SlowDown => { - if playback_ratio < 256 { - playback_ratio *= 2; + crate::event::TimerAction::FirstFrame => { + idx = 0; + force_update_time = true; + } + crate::event::TimerAction::LastFrame => { + idx = + frames.clone().lock_owned().await.count() - 1; + force_update_time = true; + } + // force_update_time will immediately transition to the + // next frame and do idx += 1 on its own + crate::event::TimerAction::NextFrame => { + force_update_time = true; + } + crate::event::TimerAction::PreviousFrame => { + idx = idx.saturating_sub(2); + force_update_time = true; + } + crate::event::TimerAction::SpeedUp => { + if playback_ratio > 1 { + playback_ratio /= 2; + let now = std::time::Instant::now(); + start_time = now - (now - start_time) / 2; + event_w + .send(crate::event::Event::Speed( + playback_ratio, + )) + // event_w is never closed, so this can + // never fail + .unwrap(); + } + } + crate::event::TimerAction::SlowDown => { + if playback_ratio < 256 { + playback_ratio *= 2; + let now = std::time::Instant::now(); + start_time = now - (now - start_time) * 2; + event_w + .send(crate::event::Event::Speed( + playback_ratio, + )) + // event_w is never closed, so this can + // never fail + .unwrap(); + } + } + crate::event::TimerAction::DefaultSpeed => { let now = std::time::Instant::now(); - start_time = now - (now - start_time) * 2; + start_time = now + - (((now - start_time) * 16) / playback_ratio); + playback_ratio = 16; event_w - .send(crate::event::Event::Speed( - playback_ratio, - )) - .await + .send( + crate::event::Event::Speed(playback_ratio) + ) // event_w is never closed, so this can never // fail .unwrap(); } - } - crate::event::TimerAction::DefaultSpeed => { - let now = std::time::Instant::now(); - start_time = now - - (((now - start_time) * 16) / playback_ratio); - playback_ratio = 16; - event_w - .send(crate::event::Event::Speed(playback_ratio)) - .await - // event_w is never closed, so this can never fail - .unwrap(); - } - crate::event::TimerAction::Search(s, backwards) => { - if let Some(new_idx) = - frames.lock_arc().await.search(idx, &s, backwards) - { - idx = new_idx; - force_update_time = true; + crate::event::TimerAction::Search(s, backwards) => { + if let Some(new_idx) = + frames.clone() + .lock_owned() + .await + .search(idx, &s, backwards) + { + idx = new_idx; + force_update_time = true; + } } + crate::event::TimerAction::Quit => break, } - crate::event::TimerAction::Quit => break, + None => unreachable!(), }, - Res::TimerAction(Err(e)) => panic!("{}", e), } } }) diff --git a/src/bin/ttyrec/main.rs b/src/bin/ttyrec/main.rs index 8278998..1dbba54 100644 --- a/src/bin/ttyrec/main.rs +++ b/src/bin/ttyrec/main.rs @@ -11,10 +11,7 @@ #![allow(clippy::too_many_lines)] #![allow(clippy::type_complexity)] -use async_std::io::{ReadExt as _, WriteExt as _}; -use async_std::prelude::FutureExt as _; -use async_std::stream::StreamExt as _; -use pty_process::Command as _; +use tokio::io::{AsyncReadExt as _, AsyncWriteExt as _}; #[derive(Debug, structopt::StructOpt)] #[structopt( @@ -55,42 +52,46 @@ fn get_cmd( ) } +#[derive(Debug)] enum Event { Key(textmode::Result>), Stdout(std::io::Result>), Resize((u16, u16)), Error(anyhow::Error), + Quit, } +#[tokio::main] async fn async_main(opt: Opt) -> anyhow::Result<()> { let Opt { cmd, file } = opt; let (cmd, args) = get_cmd(cmd); - let fh = async_std::fs::File::create(file).await?; + let fh = tokio::fs::File::create(file).await?; - let mut input = textmode::Input::new().await?; + let mut input = textmode::blocking::Input::new()?; let _input_guard = input.take_raw_guard(); - let mut stdout = async_std::io::stdout(); + let mut stdout = tokio::io::stdout(); let size = terminal_size::terminal_size().map_or( (24, 80), |(terminal_size::Width(w), terminal_size::Height(h))| (h, w), ); - let child = async_std::process::Command::new(cmd) - .args(args) - .spawn_pty(Some(&pty_process::Size::new(size.0, size.1)))?; + let mut pty = pty_process::Pty::new()?; + pty.resize(pty_process::Size::new(size.0, size.1))?; + let pts = pty.pts()?; + let mut child = pty_process::Command::new(cmd).args(args).spawn(&pts)?; - let (event_w, event_r) = async_std::channel::unbounded(); - let (input_w, input_r) = async_std::channel::unbounded(); - let (resize_w, resize_r) = async_std::channel::unbounded(); + let (event_w, mut event_r) = tokio::sync::mpsc::unbounded_channel(); + let (input_w, mut input_r) = tokio::sync::mpsc::unbounded_channel(); + let (resize_w, mut resize_r) = tokio::sync::mpsc::unbounded_channel(); { - let mut signals = signal_hook_async_std::Signals::new(&[ - signal_hook::consts::signal::SIGWINCH, - ])?; + let mut signals = tokio::signal::unix::signal( + tokio::signal::unix::SignalKind::window_change(), + )?; let event_w = event_w.clone(); - async_std::task::spawn(async move { - while signals.next().await.is_some() { + tokio::task::spawn(async move { + while signals.recv().await.is_some() { event_w .send(Event::Resize( terminal_size::terminal_size().map_or( @@ -101,7 +102,6 @@ async fn async_main(opt: Opt) -> anyhow::Result<()> { )| { (h, w) }, ), )) - .await // event_w is never closed, so this can never fail .unwrap(); } @@ -110,11 +110,10 @@ async fn async_main(opt: Opt) -> anyhow::Result<()> { { let event_w = event_w.clone(); - async_std::task::spawn(async move { + std::thread::spawn(move || { loop { event_w - .send(Event::Key(input.read_key().await)) - .await + .send(Event::Key(input.read_key())) // event_w is never closed, so this can never fail .unwrap(); } @@ -123,57 +122,50 @@ async fn async_main(opt: Opt) -> anyhow::Result<()> { { let event_w = event_w.clone(); - async_std::task::spawn(async move { + tokio::task::spawn(async move { loop { - enum Res { - Read(Result), - Write(Result, async_std::channel::RecvError>), - Resize(Result<(u16, u16), async_std::channel::RecvError>), - } let mut buf = [0_u8; 4096]; - let mut pty = child.pty(); - let read = async { Res::Read(pty.read(&mut buf).await) }; - let write = async { Res::Write(input_r.recv().await) }; - let resize = async { Res::Resize(resize_r.recv().await) }; - match read.race(write).race(resize).await { - Res::Read(res) => { + tokio::select! { + res = pty.read(&mut buf) => { let res = res.map(|n| buf[..n].to_vec()); let err = res.is_err(); event_w .send(Event::Stdout(res)) - .await // event_w is never closed, so this can never fail .unwrap(); if err { + eprintln!("pty read failed: {}", err); break; } } - Res::Write(res) => { + res = input_r.recv() => { // input_r is never closed, so this can never fail - let bytes = res.unwrap(); + let bytes: Vec = res.unwrap(); if let Err(e) = pty.write(&bytes).await { event_w .send(Event::Error(anyhow::anyhow!(e))) - .await // event_w is never closed, so this can never // fail .unwrap(); } } - Res::Resize(res) => { + res = resize_r.recv() => { // resize_r is never closed, so this can never fail - let size = res.unwrap(); - if let Err(e) = child.resize_pty( - &pty_process::Size::new(size.0, size.1), + let size: (u16, u16) = res.unwrap(); + if let Err(e) = pty.resize( + pty_process::Size::new(size.0, size.1), ) { event_w .send(Event::Error(anyhow::anyhow!(e))) - .await // event_w is never closed, so this can never // fail .unwrap(); } } + _ = child.wait() => { + event_w.send(Event::Quit).unwrap(); + break; + } } } }); @@ -181,11 +173,12 @@ async fn async_main(opt: Opt) -> anyhow::Result<()> { let mut writer = ttyrec::Writer::new(fh); loop { - match event_r.recv().await? { + // XXX unwrap + match event_r.recv().await.unwrap() { Event::Key(key) => { let key = key?; if let Some(key) = key { - input_w.send(key.into_bytes()).await?; + input_w.send(key.into_bytes()).unwrap(); } else { break; } @@ -197,18 +190,16 @@ async fn async_main(opt: Opt) -> anyhow::Result<()> { stdout.flush().await?; } Err(e) => { - if e.raw_os_error() == Some(libc::EIO) { - break; - } anyhow::bail!("failed to read from child process: {}", e); } }, Event::Resize((h, w)) => { - resize_w.send((h, w)).await?; + resize_w.send((h, w)).unwrap(); } Event::Error(e) => { return Err(e); } + Event::Quit => break, } } @@ -217,7 +208,7 @@ async fn async_main(opt: Opt) -> anyhow::Result<()> { #[paw::main] fn main(opt: Opt) { - match async_std::task::block_on(async_main(opt)) { + match async_main(opt) { Ok(_) => (), Err(e) => { eprintln!("ttyrec: {}", e); -- cgit v1.2.3-54-g00ecf