aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2022-02-24 05:32:52 -0500
committerJesse Luehrs <doy@tozt.net>2022-02-24 05:32:52 -0500
commit5396669e46f1306d930e5d92748eeb302fccaa9a (patch)
tree975866bf9e4f84cf8c84941384178c016c68fa59
parent60ca1162956273921f9d1265bd4ec9ad30d33205 (diff)
downloadttyrec-bin-5396669e46f1306d930e5d92748eeb302fccaa9a.tar.gz
ttyrec-bin-5396669e46f1306d930e5d92748eeb302fccaa9a.zip
move to tokio
-rw-r--r--CHANGELOG.md6
-rw-r--r--Cargo.lock627
-rw-r--r--Cargo.toml20
-rw-r--r--src/bin/ttyplay/event.rs46
-rw-r--r--src/bin/ttyplay/frames.rs39
-rw-r--r--src/bin/ttyplay/input.rs17
-rw-r--r--src/bin/ttyplay/main.rs19
-rw-r--r--src/bin/ttyplay/timer.rs199
-rw-r--r--src/bin/ttyrec/main.rs91
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"
@@ -24,141 +24,6 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -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"
@@ -236,99 +75,6 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -347,39 +93,12 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -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",
]
@@ -691,12 +431,41 @@ dependencies = [
]
[[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"
@@ -742,16 +509,6 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -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<vt100::Screen>)),
FrameLoaded(Option<usize>),
@@ -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<Pending>,
- cvar: async_std::sync::Condvar,
+ pending: tokio::sync::Mutex<Pending>,
+ // 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<Event>,
- ) -> async_std::sync::Arc<Self> {
+ mut input: tokio::sync::mpsc::UnboundedReceiver<Event>,
+ ) -> std::sync::Arc<Self> {
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<Event> {
- 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<Event>,
- timer_w: async_std::channel::Sender<TimerAction>,
+ event_r: tokio::sync::mpsc::UnboundedReceiver<Event>,
+ timer_w: tokio::sync::mpsc::UnboundedSender<TimerAction>,
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<Frame>,
done_reading: bool,
- new_frame_w: async_std::channel::Sender<Option<usize>>,
- new_frame_r: async_std::channel::Receiver<Option<usize>>,
+ new_frame_w: tokio::sync::watch::Sender<Option<usize>>,
+ new_frame_r: tokio::sync::watch::Receiver<Option<usize>>,
}
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<async_std::sync::Mutex<FrameData>>,
- fh: async_std::fs::File,
- event_w: async_std::channel::Sender<crate::event::Event>,
+ frames: std::sync::Arc<tokio::sync::Mutex<FrameData>>,
+ fh: tokio::fs::File,
+ event_w: tokio::sync::mpsc::UnboundedSender<crate::event::Event>,
clamp: Option<u64>,
) {
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<crate::event::Event>,
- mut input: textmode::Input,
+pub fn spawn_thread(
+ event_w: tokio::sync::mpsc::UnboundedSender<crate::event::Event>,
+ mut input: textmode::blocking::Input,
) {
- async_std::task::spawn(async move {
+ std::thread::spawn(move || {
let mut search: Option<String> = 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<crate::event::Event>,
- frames: async_std::sync::Arc<
- async_std::sync::Mutex<crate::frames::FrameData>,
+ event_w: tokio::sync::mpsc::UnboundedSender<crate::event::Event>,
+ frames: std::sync::Arc<tokio::sync::Mutex<crate::frames::FrameData>>,
+ mut timer_r: tokio::sync::mpsc::UnboundedReceiver<
+ crate::event::TimerAction,
>,
- timer_r: async_std::channel::Receiver<crate::event::TimerAction>,
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<Box<vt100::Screen>>),
- 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<Option<textmode::Key>>),
Stdout(std::io::Result<Vec<u8>>),
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<usize, std::io::Error>),
- Write(Result<Vec<u8>, 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<u8> = 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);