initial
This commit is contained in:
commit
b3766beb74
7 changed files with 982 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/target
|
625
Cargo.lock
generated
Normal file
625
Cargo.lock
generated
Normal file
|
@ -0,0 +1,625 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9a60d744a80c30fcb657dfe2c1b22bcb3e814c1a1e3674f32bf5820b570fbff"
|
||||
|
||||
[[package]]
|
||||
name = "arc-swap"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d663a8e9a99154b5fb793032533f6328da35e23aac63d5c152279aa8ba356825"
|
||||
|
||||
[[package]]
|
||||
name = "asciinema"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"futures",
|
||||
"libc",
|
||||
"nix",
|
||||
"parking_lot",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"signal-hook",
|
||||
"termios",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
||||
[[package]]
|
||||
name = "cloudabi"
|
||||
version = "0.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
|
||||
|
||||
[[package]]
|
||||
name = "fuchsia-zircon"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"fuchsia-zircon-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fuchsia-zircon-sys"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c329ae8753502fb44ae4fc2b622fa2a94652c41e795143765ba0927f92ab780"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-executor",
|
||||
"futures-io",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0c77d04ce8edd9cb903932b608268b3fffec4163dc053b3b402bf47eac1f1a8"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f25592f769825e89b92358db00d26f965761e094951ac44d3663ef25b7ac464a"
|
||||
|
||||
[[package]]
|
||||
name = "futures-executor"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f674f3e1bcb15b37284a90cedf55afdba482ab061c407a9c0ebbd0f3109741ba"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a638959aa96152c7a4cddf50fcb1e3fede0583b27157c26e67d6f99904090dc6"
|
||||
|
||||
[[package]]
|
||||
name = "futures-macro"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a5081aa3de1f7542a794a397cde100ed903b0630152d0973479018fd85423a7"
|
||||
dependencies = [
|
||||
"proc-macro-hack",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3466821b4bc114d95b087b850a724c6f83115e929bc88f1fa98a3304a944c8a6"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b0a34e53cf6cdcd0178aa573aed466b646eb3db769570841fda0c7ede375a27"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22766cf25d64306bedf0384da004d05c9974ab104fcc4528f1236181c18004c5"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"futures-macro",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"memchr",
|
||||
"pin-utils",
|
||||
"proc-macro-hack",
|
||||
"proc-macro-nested",
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "725cf19794cf90aa94e65050cb4191ff5d8fa87a498383774c47b332e3af952e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iovec"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e"
|
||||
|
||||
[[package]]
|
||||
name = "kernel32-sys"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
dependencies = [
|
||||
"winapi 0.2.8",
|
||||
"winapi-build",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.68"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75"
|
||||
dependencies = [
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.6.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"fuchsia-zircon",
|
||||
"fuchsia-zircon-sys",
|
||||
"iovec",
|
||||
"kernel32-sys",
|
||||
"libc",
|
||||
"log",
|
||||
"miow 0.2.1",
|
||||
"net2",
|
||||
"slab",
|
||||
"winapi 0.2.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio-named-pipes"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f5e374eff525ce1c5b7687c4cef63943e7686524a387933ad27ca7ec43779cb3"
|
||||
dependencies = [
|
||||
"log",
|
||||
"mio",
|
||||
"miow 0.3.3",
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio-uds"
|
||||
version = "0.6.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125"
|
||||
dependencies = [
|
||||
"iovec",
|
||||
"libc",
|
||||
"mio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miow"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
|
||||
dependencies = [
|
||||
"kernel32-sys",
|
||||
"net2",
|
||||
"winapi 0.2.8",
|
||||
"ws2_32-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miow"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "396aa0f2003d7df8395cb93e09871561ccc3e785f0acb369170e8cc74ddf9226"
|
||||
dependencies = [
|
||||
"socket2",
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "net2"
|
||||
version = "0.2.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"void",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e136c1904604defe99ce5fd71a28d473fa60a12255d511aa78a9ddf11237aeb"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cloudabi",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "237844750cfbb86f67afe27eee600dfbbcb6188d734139b534cbfbf4f96792ae"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
version = "0.1.0-alpha.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-hack"
|
||||
version = "0.5.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d659fe7c6d27f25e9d80a1a094c223f5246f6a6596453e09d7229bf42750b63"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-nested"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e946095f9d3ed29ec38de908c22f95d9ac008e424c7bcae54c75a79c527c694"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.1.56"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36df6ac6412072f67cf767ebbde4133a5b2e88e76dc6187fa7104cd16f783399"
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e549e3abf4fb8621bd1609f11dfc9f5e50320802273b12f3811a67e6716ea6c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da07b57ee2623368351e9a0488bb0b261322a15a6e0ae53e243cbdc0f4208da9"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook"
|
||||
version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10b9f3a1686a29f53cfd91ee5e3db3c12313ec02d33765f02c1a9645a1811e2c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"signal-hook-registry",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41"
|
||||
dependencies = [
|
||||
"arc-swap",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05720e22615919e4734f6a99ceae50d00226c3c5aca406e102ebc33298214e0a"
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.3.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termios"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f0fcee7b24a25675de40d5bb4de6e41b0df07bc9856295e7e2b3a3600c400c2"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39fb9142eb6e9cc37f4f29144e62618440b149a138eee01a7bbe9b9226aaf17c"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
"futures-core",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"memchr",
|
||||
"mio",
|
||||
"mio-named-pipes",
|
||||
"mio-uds",
|
||||
"num_cpus",
|
||||
"pin-project-lite",
|
||||
"signal-hook-registry",
|
||||
"slab",
|
||||
"tokio-macros",
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"log",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
||||
|
||||
[[package]]
|
||||
name = "void"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-build"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "ws2_32-sys"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
|
||||
dependencies = [
|
||||
"winapi 0.2.8",
|
||||
"winapi-build",
|
||||
]
|
19
Cargo.toml
Normal file
19
Cargo.toml
Normal file
|
@ -0,0 +1,19 @@
|
|||
[package]
|
||||
name = "asciinema"
|
||||
version = "0.1.0"
|
||||
authors = ["Michael Zhang <iptq@protonmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.28"
|
||||
futures = "0.3.4"
|
||||
libc = "0.2.68"
|
||||
nix = "0.17.0"
|
||||
parking_lot = "0.10.1"
|
||||
serde = "1.0.106"
|
||||
serde_derive = "1.0.106"
|
||||
serde_json = "1.0.51"
|
||||
signal-hook = "0.1.13"
|
||||
termios = "0.3.2"
|
||||
tokio = { version = "0.2.16", features = ["fs", "io-std", "macros", "process", "rt-core", "rt-threaded", "rt-util", "sync", "time"] }
|
||||
tokio-util = { version = "0.3.1", features = ["codec"] }
|
65
src/asciicast.rs
Normal file
65
src/asciicast.rs
Normal file
|
@ -0,0 +1,65 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use serde::ser::{Serialize, SerializeSeq, Serializer};
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct Header {
|
||||
version: u32,
|
||||
width: u32,
|
||||
height: u32,
|
||||
|
||||
timestamp: Option<u32>,
|
||||
duration: Option<f64>,
|
||||
idle_time_limit: Option<f64>,
|
||||
command: Option<String>,
|
||||
title: Option<String>,
|
||||
env: Option<HashMap<String, String>>,
|
||||
theme: Option<Theme>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct Theme {
|
||||
fg: String,
|
||||
bg: String,
|
||||
palette: String,
|
||||
}
|
||||
|
||||
pub struct Event<'a>(pub f64, pub EventKind<'a>);
|
||||
|
||||
pub enum EventKind<'a> {
|
||||
Output(&'a [u8]),
|
||||
Input(&'a [u8]),
|
||||
}
|
||||
|
||||
impl<'a> Serialize for Event<'a> {
|
||||
fn serialize<S: Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
|
||||
let mut seq = s.serialize_seq(Some(3))?;
|
||||
seq.serialize_element(&self.0)?;
|
||||
match &self.1 {
|
||||
EventKind::Output(s) => {
|
||||
seq.serialize_element("o")?;
|
||||
seq.serialize_element(std::str::from_utf8(s).unwrap())?;
|
||||
}
|
||||
EventKind::Input(s) => {
|
||||
seq.serialize_element("i")?;
|
||||
seq.serialize_element(std::str::from_utf8(s).unwrap())?;
|
||||
}
|
||||
}
|
||||
seq.end()
|
||||
}
|
||||
}
|
||||
|
||||
fn build_header(width: u32, height: u32) -> Header {
|
||||
Header {
|
||||
version: 2,
|
||||
width, height,
|
||||
|
||||
timestamp: None,
|
||||
duration: None,
|
||||
idle_time_limit: None,
|
||||
command: None,
|
||||
title: None,
|
||||
env: None,
|
||||
theme: None,
|
||||
}
|
||||
}
|
26
src/main.rs
Normal file
26
src/main.rs
Normal file
|
@ -0,0 +1,26 @@
|
|||
#![recursion_limit = "256"]
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
mod asciicast;
|
||||
mod pty;
|
||||
mod writer;
|
||||
|
||||
use std::fs::File;
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
use crate::writer::FileWriter;
|
||||
|
||||
async fn record() -> Result<()> {
|
||||
let file = File::create("output.cast")?;
|
||||
pty::record(&["sh", "-c", "/usr/bin/zsh"], FileWriter::new(file))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
record().await?;
|
||||
Ok(())
|
||||
}
|
200
src/pty.rs
Normal file
200
src/pty.rs
Normal file
|
@ -0,0 +1,200 @@
|
|||
use std::env;
|
||||
use std::ffi::CString;
|
||||
use std::io;
|
||||
use std::os::unix::io::RawFd;
|
||||
use std::time::{Instant};
|
||||
|
||||
use anyhow::Error;
|
||||
use nix::{
|
||||
fcntl::{fcntl, FcntlArg, OFlag},
|
||||
ioctl_write_buf,
|
||||
pty::{forkpty, Winsize},
|
||||
sys::{
|
||||
select::{select, FdSet},
|
||||
termios::{tcsetattr, SetArg, Termios},
|
||||
wait::waitpid,
|
||||
},
|
||||
unistd::{execvpe, isatty, pipe, read, write, ForkResult},
|
||||
};
|
||||
use signal_hook::SigId;
|
||||
|
||||
use crate::writer::Writer;
|
||||
|
||||
const STDIN_FILENO: RawFd = 0;
|
||||
const STDOUT_FILENO: RawFd = 1;
|
||||
|
||||
pub fn record(args: &[&str], writer: impl Writer + Send) -> Result<(), Error> {
|
||||
let forkpty_result = forkpty(None, None)?;
|
||||
let master_fd = forkpty_result.master;
|
||||
let start_time = Instant::now();
|
||||
|
||||
let set_pty_size = || -> Result<(), Error> {
|
||||
ioctl_write_buf!(helper_write, libc::TIOCGWINSZ, 104, Winsize);
|
||||
let winsize = Winsize {
|
||||
ws_row: 24,
|
||||
ws_col: 80,
|
||||
ws_xpixel: 0,
|
||||
ws_ypixel: 0,
|
||||
};
|
||||
if isatty(STDOUT_FILENO)? {}
|
||||
unsafe { helper_write(master_fd, &[winsize]) }?;
|
||||
Ok(())
|
||||
};
|
||||
|
||||
let write_stdout = |data: &[u8]| -> Result<(), Error> {
|
||||
write(STDOUT_FILENO, &data)?;
|
||||
Ok(())
|
||||
};
|
||||
|
||||
let mut master_writer = writer.clone();
|
||||
let mut handle_master_read = move |data: &[u8]| -> Result<(), Error> {
|
||||
let elapsed = (Instant::now() - start_time).as_secs_f64();
|
||||
master_writer.write_stdout(elapsed, data)?;
|
||||
write_stdout(data)?;
|
||||
Ok(())
|
||||
};
|
||||
|
||||
let write_master = |data: &[u8]| -> Result<(), Error> {
|
||||
let mut offset = 0;
|
||||
while offset < data.len() {
|
||||
let len = write(master_fd, data)?;
|
||||
offset += len;
|
||||
}
|
||||
Ok(())
|
||||
};
|
||||
|
||||
let mut stdin_writer = writer.clone();
|
||||
let mut handle_stdin_read = |data: &[u8]| -> Result<(), Error> {
|
||||
write_master(data)?;
|
||||
let elapsed = (Instant::now() - start_time).as_secs_f64();
|
||||
stdin_writer.write_stdin(elapsed, data)?;
|
||||
Ok(())
|
||||
};
|
||||
|
||||
let mut copy = |signal_fd: RawFd| -> Result<(), Error> {
|
||||
let mut fdset = FdSet::new();
|
||||
let mut buf = [0; 1024];
|
||||
|
||||
loop {
|
||||
fdset.clear();
|
||||
fdset.insert(master_fd);
|
||||
fdset.insert(STDIN_FILENO);
|
||||
fdset.insert(signal_fd);
|
||||
|
||||
select(None, &mut fdset, None, None, None)?;
|
||||
|
||||
if fdset.contains(master_fd) {
|
||||
let len = read(master_fd, &mut buf)?;
|
||||
if len == 0 {
|
||||
fdset.remove(master_fd);
|
||||
} else {
|
||||
handle_master_read(&buf[..len])?;
|
||||
}
|
||||
} else if fdset.contains(STDIN_FILENO) {
|
||||
let len = read(STDIN_FILENO, &mut buf)?;
|
||||
if len == 0 {
|
||||
fdset.remove(STDIN_FILENO);
|
||||
} else {
|
||||
handle_stdin_read(&buf[..len])?;
|
||||
}
|
||||
} else if fdset.contains(signal_fd) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let child_pid = match forkpty_result.fork_result {
|
||||
ForkResult::Parent { child } => child,
|
||||
ForkResult::Child => {
|
||||
let cstr_args: Vec<_> = args
|
||||
.into_iter()
|
||||
.map(|s| CString::new(*s).unwrap())
|
||||
.collect();
|
||||
let args: Vec<_> = cstr_args.iter().map(|s| s.as_ref()).collect();
|
||||
let cstr_env: Vec<_> = env::vars()
|
||||
.map(|(k, v)| CString::new(format!("{}={}", k, v)).unwrap())
|
||||
.collect();
|
||||
let env: Vec<_> = cstr_env.iter().map(|s| s.as_ref()).collect();
|
||||
execvpe(&args[0], &args, &env)?;
|
||||
unreachable!();
|
||||
}
|
||||
};
|
||||
|
||||
let (pipe_r, pipe_w) = pipe()?;
|
||||
let mut flags = fcntl(pipe_w, FcntlArg::F_GETFL)?;
|
||||
flags |= libc::O_NONBLOCK;
|
||||
fcntl(pipe_w, FcntlArg::F_SETFL(OFlag::from_bits(flags).unwrap()))?;
|
||||
|
||||
let old_handlers = set_signals(
|
||||
[
|
||||
signal_hook::SIGWINCH,
|
||||
signal_hook::SIGCHLD,
|
||||
signal_hook::SIGHUP,
|
||||
signal_hook::SIGTERM,
|
||||
signal_hook::SIGQUIT,
|
||||
]
|
||||
.iter()
|
||||
.map(|sig| (*sig, move || eprintln!("HIT SIGNAL {:?}", *sig))),
|
||||
)?;
|
||||
|
||||
// set_pty_size()?;
|
||||
|
||||
{
|
||||
let _term = RawTerm::init(STDIN_FILENO)?;
|
||||
copy(pipe_r)?;
|
||||
}
|
||||
unset_signals(old_handlers)?;
|
||||
|
||||
waitpid(child_pid, None)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_signals<I, F>(signals_list: I) -> Result<Vec<SigId>, io::Error>
|
||||
where
|
||||
I: Iterator<Item = (i32, F)>,
|
||||
F: Fn() + Sync + Send + 'static,
|
||||
{
|
||||
let mut old_handlers = Vec::new();
|
||||
for (sig, handler) in signals_list {
|
||||
old_handlers.push(unsafe { signal_hook::register(sig, handler) }?);
|
||||
}
|
||||
Ok(old_handlers)
|
||||
}
|
||||
|
||||
fn unset_signals(handlers_list: Vec<SigId>) -> Result<(), io::Error> {
|
||||
for handler in handlers_list {
|
||||
signal_hook::unregister(handler);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
struct RawTerm(RawFd, Termios);
|
||||
|
||||
impl RawTerm {
|
||||
pub fn init(fd: RawFd) -> Result<Self, Error> {
|
||||
use nix::sys::termios::*;
|
||||
let saved_mode = tcgetattr(fd)?;
|
||||
let mut mode = saved_mode.clone();
|
||||
mode.input_flags &= !(InputFlags::BRKINT
|
||||
| InputFlags::ICRNL
|
||||
| InputFlags::INPCK
|
||||
| InputFlags::ISTRIP
|
||||
| InputFlags::IXON);
|
||||
mode.output_flags &= !OutputFlags::OPOST;
|
||||
mode.control_flags &= !(ControlFlags::CSIZE | ControlFlags::PARENB);
|
||||
mode.control_flags |= ControlFlags::CS8;
|
||||
mode.local_flags &=
|
||||
!(LocalFlags::ECHO | LocalFlags::ICANON | LocalFlags::IEXTEN | LocalFlags::ISIG);
|
||||
mode.control_chars[libc::VMIN] = 1;
|
||||
mode.control_chars[libc::VTIME] = 0;
|
||||
tcsetattr(fd, SetArg::TCSAFLUSH, &mode)?;
|
||||
Ok(RawTerm(fd, saved_mode))
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for RawTerm {
|
||||
fn drop(&mut self) {
|
||||
tcsetattr(self.0, SetArg::TCSAFLUSH, &self.1).unwrap();
|
||||
}
|
||||
}
|
46
src/writer.rs
Normal file
46
src/writer.rs
Normal file
|
@ -0,0 +1,46 @@
|
|||
use std::fs::File;
|
||||
use std::io::{self, Write};
|
||||
use std::sync::Arc;
|
||||
|
||||
use parking_lot::Mutex;
|
||||
|
||||
// use tokio::{fs::File, io::AsyncWriteExt};
|
||||
|
||||
use crate::asciicast::{Event, EventKind};
|
||||
|
||||
pub trait Writer: Clone {
|
||||
fn write_line(&mut self, line: String) -> Result<(), io::Error>;
|
||||
|
||||
fn write_stdin(&mut self, time: f64, data: &[u8]) -> Result<(), anyhow::Error> {
|
||||
let output = EventKind::Input(data);
|
||||
let event = Event(time, output);
|
||||
self.write_line(serde_json::to_string(&event)?)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_stdout(&mut self, time: f64, data: &[u8]) -> Result<(), anyhow::Error> {
|
||||
let output = EventKind::Output(data);
|
||||
let event = Event(time, output);
|
||||
self.write_line(serde_json::to_string(&event)?)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct FileWriter(Arc<Mutex<File>>);
|
||||
|
||||
impl FileWriter {
|
||||
pub fn new(file: File) -> Self {
|
||||
FileWriter(Arc::new(Mutex::new(file)))
|
||||
}
|
||||
}
|
||||
|
||||
impl Writer for FileWriter {
|
||||
fn write_line(&mut self, line: String) -> Result<(), io::Error> {
|
||||
let mut writer = self.0.lock();
|
||||
writer.write_all(line.as_bytes())?;
|
||||
writer.write(b"\n")?;
|
||||
writer.flush()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue