summaryrefslogtreecommitdiff
path: root/vendor/anstream
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-07-10 13:11:11 -0600
committermo khan <mo@mokhan.ca>2025-07-10 13:11:11 -0600
commit01959b16a21b22b5df5f16569c2a8e8f92beecef (patch)
tree32afa5d747c5466345c59ec52161a7cba3d6d755 /vendor/anstream
parentff30574117a996df332e23d1fb6f65259b316b5b (diff)
chore: vendor dependencies
Diffstat (limited to 'vendor/anstream')
-rw-r--r--vendor/anstream/.cargo-checksum.json1
-rw-r--r--vendor/anstream/Cargo.lock705
-rw-r--r--vendor/anstream/Cargo.toml220
-rw-r--r--vendor/anstream/LICENSE-APACHE202
-rw-r--r--vendor/anstream/LICENSE-MIT19
-rw-r--r--vendor/anstream/README.md34
-rw-r--r--vendor/anstream/examples/dump-stream.rs130
-rw-r--r--vendor/anstream/examples/query-stream.rs22
-rw-r--r--vendor/anstream/src/_macros.rs364
-rw-r--r--vendor/anstream/src/adapter/mod.rs15
-rw-r--r--vendor/anstream/src/adapter/strip.rs511
-rw-r--r--vendor/anstream/src/adapter/wincon.rs378
-rw-r--r--vendor/anstream/src/auto.rs302
-rw-r--r--vendor/anstream/src/buffer.rs56
-rw-r--r--vendor/anstream/src/fmt.rs54
-rw-r--r--vendor/anstream/src/lib.rs90
-rw-r--r--vendor/anstream/src/stream.rs316
-rw-r--r--vendor/anstream/src/strip.rs227
-rw-r--r--vendor/anstream/src/wincon.rs226
19 files changed, 3872 insertions, 0 deletions
diff --git a/vendor/anstream/.cargo-checksum.json b/vendor/anstream/.cargo-checksum.json
new file mode 100644
index 00000000..cdcd1885
--- /dev/null
+++ b/vendor/anstream/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.lock":"b024d6d428ff4fddba14421c31f79d675c3acbcd1f80d602908c77002b8c4a82","Cargo.toml":"1771559805c603fa2dd152b75b6cf45abaa293a37ac1491c908e70b1f125ec11","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"6efb0476a1cc085077ed49357026d8c173bf33017278ef440f222fb9cbcb66e6","README.md":"7b22f0ac46116cae53ea847f9bc008d172276765e9955924cdbf5ff82cae5fca","examples/dump-stream.rs":"6dbd8fca846ac8addd43ae941fa1220a7c31862896ac2ae4971afe792480523d","examples/query-stream.rs":"3796dec1ffe79cc49d088086eb27214764e8e0cff0370d60150aeecdadd47d30","src/_macros.rs":"04590ef86f86bb67fb11580ab101caffde4d36da84652537da20424b72c8729a","src/adapter/mod.rs":"baf4237ea0b18df63609e49d93572ca27c2202a4cbec0220adb5a7e815c7d8ed","src/adapter/strip.rs":"642375f9dc5836eb5aa6eba7be849a84786d22764d470672bf1f646061254c1c","src/adapter/wincon.rs":"88607742fb7bbfb85e122a8dcc3188ef7c15ef332063af3a8939701dad05b90a","src/auto.rs":"e513fd903153df148fe1718471db3363fb3ec6a3d7bc167426033ed37dd307ba","src/buffer.rs":"597cc2a109a49f0a48888c7d882058d0ec4b771da34348d4da384ba056c6ea1c","src/fmt.rs":"cc11b005c4559843bd908a57958a13c8d0922fae6aff5261f3583c90e60da73c","src/lib.rs":"41885c714cd46e11b7c717ade9039a736a4bedae4f148f4a0efebe54708f3685","src/stream.rs":"680ef529d62377365cd543ebcd51076c909fffc06d1f52231fb69c68bbd05218","src/strip.rs":"155fa7bb0bc333b7648236df44d14ff742139c28659332bf03ed00b2943b8fac","src/wincon.rs":"018b824680576e5279830b2ca1ede0e36a97044d4d30cfd50199e1df7a5fb0f4"},"package":"301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933"} \ No newline at end of file
diff --git a/vendor/anstream/Cargo.lock b/vendor/anstream/Cargo.lock
new file mode 100644
index 00000000..30984393
--- /dev/null
+++ b/vendor/anstream/Cargo.lock
@@ -0,0 +1,705 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "anstream"
+version = "0.6.19"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "divan",
+ "is_terminal_polyfill",
+ "lexopt",
+ "owo-colors",
+ "proptest",
+ "strip-ansi-escapes",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
+dependencies = [
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
+dependencies = [
+ "anstyle",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
+
+[[package]]
+name = "bit-set"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"
+dependencies = [
+ "bit-vec",
+]
+
+[[package]]
+name = "bit-vec"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bitflags"
+version = "2.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
+
+[[package]]
+name = "byteorder"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "clap"
+version = "4.3.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb690e81c7840c0d7aade59f242ea3b41b9bc27bcd5997890e7702ae4b32e487"
+dependencies = [
+ "clap_builder",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.3.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5ed2e96bc16d8d740f6f48d663eddf4b8a0983e79210fd55479b7bcd0a69860e"
+dependencies = [
+ "anstyle",
+ "clap_lex",
+ "terminal_size",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b"
+
+[[package]]
+name = "colorchoice"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
+
+[[package]]
+name = "condtype"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf0a07a401f374238ab8e2f11a104d2851bf9ce711ec69804834de8af45c7af"
+
+[[package]]
+name = "divan"
+version = "0.1.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e05d17bd4ff1c1e7998ed4623d2efd91f72f1e24141ac33aac9377974270e1f"
+dependencies = [
+ "cfg-if",
+ "clap",
+ "condtype",
+ "divan-macros",
+ "libc",
+ "regex-lite",
+]
+
+[[package]]
+name = "divan-macros"
+version = "0.1.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b4464d46ce68bfc7cb76389248c7c254def7baca8bece0693b02b83842c4c88"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "errno"
+version = "0.3.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e"
+dependencies = [
+ "libc",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "fastrand"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6"
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "getrandom"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
+
+[[package]]
+name = "hermit-abi"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
+
+[[package]]
+name = "io-lifetimes"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
+dependencies = [
+ "hermit-abi 0.3.9",
+ "libc",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "is-terminal"
+version = "0.4.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b"
+dependencies = [
+ "hermit-abi 0.4.0",
+ "libc",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "is_terminal_polyfill"
+version = "1.48.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2736dd548daf35f50d261bbad35a83890bb9b461797f15de528485fbf206ab15"
+dependencies = [
+ "is-terminal",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
+
+[[package]]
+name = "lexopt"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baff4b617f7df3d896f97fe922b64817f6cd9a756bb81d40f8883f2f66dcb401"
+
+[[package]]
+name = "libc"
+version = "0.2.172"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
+
+[[package]]
+name = "libm"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
+
+[[package]]
+name = "num-traits"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
+dependencies = [
+ "autocfg",
+ "libm",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.20.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
+
+[[package]]
+name = "owo-colors"
+version = "4.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "caff54706df99d2a78a5a4e3455ff45448d81ef1bb63c22cd14052ca0e993a3f"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
+dependencies = [
+ "zerocopy",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.89"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "proptest"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d"
+dependencies = [
+ "bit-set",
+ "bit-vec",
+ "bitflags 2.9.0",
+ "lazy_static",
+ "num-traits",
+ "rand",
+ "rand_chacha",
+ "rand_xorshift",
+ "regex-syntax",
+ "rusty-fork",
+ "tempfile",
+ "unarray",
+]
+
+[[package]]
+name = "quick-error"
+version = "1.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
+
+[[package]]
+name = "quote"
+version = "1.0.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "rand_xorshift"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "regex-lite"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a"
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
+
+[[package]]
+name = "rustix"
+version = "0.37.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2"
+dependencies = [
+ "bitflags 1.3.2",
+ "errno",
+ "io-lifetimes",
+ "libc",
+ "linux-raw-sys 0.3.8",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "rustix"
+version = "0.38.38"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a"
+dependencies = [
+ "bitflags 2.9.0",
+ "errno",
+ "libc",
+ "linux-raw-sys 0.4.14",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "rusty-fork"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f"
+dependencies = [
+ "fnv",
+ "quick-error",
+ "tempfile",
+ "wait-timeout",
+]
+
+[[package]]
+name = "strip-ansi-escapes"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55ff8ef943b384c414f54aefa961dd2bd853add74ec75e7ac74cf91dba62bcfa"
+dependencies = [
+ "vte",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.86"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e89275301d38033efb81a6e60e3497e734dfcc62571f2854bf4b16690398824c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "tempfile"
+version = "3.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b"
+dependencies = [
+ "cfg-if",
+ "fastrand",
+ "once_cell",
+ "rustix 0.38.38",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "terminal_size"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e6bf6f19e9f8ed8d4048dc22981458ebcf406d67e94cd422e5ecd73d63b3237"
+dependencies = [
+ "rustix 0.37.27",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "unarray"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
+
+[[package]]
+name = "utf8parse"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
+
+[[package]]
+name = "vte"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f5022b5fbf9407086c180e9557be968742d839e68346af7792b8592489732197"
+dependencies = [
+ "utf8parse",
+ "vte_generate_state_changes",
+]
+
+[[package]]
+name = "vte_generate_state_changes"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e369bee1b05d510a7b4ed645f5faa90619e05437111783ea5848f28d97d3c2e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+]
+
+[[package]]
+name = "wait-timeout"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "windows-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+dependencies = [
+ "windows-targets 0.48.5",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.59.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
+dependencies = [
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
+dependencies = [
+ "windows_aarch64_gnullvm 0.48.5",
+ "windows_aarch64_msvc 0.48.5",
+ "windows_i686_gnu 0.48.5",
+ "windows_i686_msvc 0.48.5",
+ "windows_x86_64_gnu 0.48.5",
+ "windows_x86_64_gnullvm 0.48.5",
+ "windows_x86_64_msvc 0.48.5",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+dependencies = [
+ "windows_aarch64_gnullvm 0.52.6",
+ "windows_aarch64_msvc 0.52.6",
+ "windows_i686_gnu 0.52.6",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc 0.52.6",
+ "windows_x86_64_gnu 0.52.6",
+ "windows_x86_64_gnullvm 0.52.6",
+ "windows_x86_64_msvc 0.52.6",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+
+[[package]]
+name = "zerocopy"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
+dependencies = [
+ "byteorder",
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
diff --git a/vendor/anstream/Cargo.toml b/vendor/anstream/Cargo.toml
new file mode 100644
index 00000000..4dc0828b
--- /dev/null
+++ b/vendor/anstream/Cargo.toml
@@ -0,0 +1,220 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2021"
+rust-version = "1.66.0"
+name = "anstream"
+version = "0.6.19"
+build = false
+include = [
+ "build.rs",
+ "src/**/*",
+ "Cargo.toml",
+ "Cargo.lock",
+ "LICENSE*",
+ "README.md",
+ "examples/**/*",
+]
+autolib = false
+autobins = false
+autoexamples = false
+autotests = false
+autobenches = false
+description = "A simple cross platform library for writing colored text to a terminal."
+readme = "README.md"
+keywords = [
+ "ansi",
+ "terminal",
+ "color",
+ "strip",
+ "wincon",
+]
+categories = ["command-line-interface"]
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/rust-cli/anstyle.git"
+
+[package.metadata.docs.rs]
+all-features = true
+rustdoc-args = [
+ "--cfg",
+ "docsrs",
+ "--generate-link-to-definition",
+]
+
+[[package.metadata.release.pre-release-replacements]]
+file = "CHANGELOG.md"
+min = 1
+replace = "{{version}}"
+search = "Unreleased"
+
+[[package.metadata.release.pre-release-replacements]]
+exactly = 1
+file = "CHANGELOG.md"
+replace = "...{{tag_name}}"
+search = '\.\.\.HEAD'
+
+[[package.metadata.release.pre-release-replacements]]
+file = "CHANGELOG.md"
+min = 1
+replace = "{{date}}"
+search = "ReleaseDate"
+
+[[package.metadata.release.pre-release-replacements]]
+exactly = 1
+file = "CHANGELOG.md"
+replace = """
+<!-- next-header -->
+## [Unreleased] - ReleaseDate
+"""
+search = "<!-- next-header -->"
+
+[[package.metadata.release.pre-release-replacements]]
+exactly = 1
+file = "CHANGELOG.md"
+replace = """
+<!-- next-url -->
+[Unreleased]: https://github.com/rust-cli/anstyle/compare/{{tag_name}}...HEAD"""
+search = "<!-- next-url -->"
+
+[features]
+auto = ["dep:anstyle-query"]
+default = [
+ "auto",
+ "wincon",
+]
+test = []
+wincon = ["dep:anstyle-wincon"]
+
+[lib]
+name = "anstream"
+path = "src/lib.rs"
+
+[[example]]
+name = "dump-stream"
+path = "examples/dump-stream.rs"
+required-features = ["auto"]
+
+[[example]]
+name = "query-stream"
+path = "examples/query-stream.rs"
+required-features = ["auto"]
+
+[dependencies.anstyle]
+version = "1.0.0"
+
+[dependencies.anstyle-parse]
+version = "0.2.0"
+
+[dependencies.anstyle-query]
+version = "1.0.0"
+optional = true
+
+[dependencies.colorchoice]
+version = "1.0.0"
+
+[dependencies.is_terminal_polyfill]
+version = "1.48"
+
+[dependencies.utf8parse]
+version = "0.2.1"
+
+[dev-dependencies.divan]
+version = "0.1.11"
+
+[dev-dependencies.lexopt]
+version = "0.3.0"
+
+[dev-dependencies.owo-colors]
+version = "4.0.0"
+
+[dev-dependencies.proptest]
+version = "1.4.0"
+
+[dev-dependencies.strip-ansi-escapes]
+version = "0.2.0"
+
+[target."cfg(windows)".dependencies.anstyle-wincon]
+version = "3.0.5"
+optional = true
+
+[lints.clippy]
+bool_assert_comparison = "allow"
+branches_sharing_code = "allow"
+checked_conversions = "warn"
+collapsible_else_if = "allow"
+create_dir = "warn"
+dbg_macro = "warn"
+debug_assert_with_mut_call = "warn"
+doc_markdown = "warn"
+empty_enum = "warn"
+enum_glob_use = "warn"
+expl_impl_clone_on_copy = "warn"
+explicit_deref_methods = "warn"
+explicit_into_iter_loop = "warn"
+fallible_impl_from = "warn"
+filter_map_next = "warn"
+flat_map_option = "warn"
+float_cmp_const = "warn"
+fn_params_excessive_bools = "warn"
+from_iter_instead_of_collect = "warn"
+if_same_then_else = "allow"
+implicit_clone = "warn"
+imprecise_flops = "warn"
+inconsistent_struct_constructor = "warn"
+inefficient_to_string = "warn"
+infinite_loop = "warn"
+invalid_upcast_comparisons = "warn"
+large_digit_groups = "warn"
+large_stack_arrays = "warn"
+large_types_passed_by_value = "warn"
+let_and_return = "allow"
+linkedlist = "warn"
+lossy_float_literal = "warn"
+macro_use_imports = "warn"
+mem_forget = "warn"
+mutex_integer = "warn"
+needless_continue = "allow"
+needless_for_each = "warn"
+negative_feature_names = "warn"
+path_buf_push_overwrite = "warn"
+ptr_as_ptr = "warn"
+rc_mutex = "warn"
+redundant_feature_names = "warn"
+ref_option_ref = "warn"
+rest_pat_in_fully_bound_structs = "warn"
+result_large_err = "allow"
+same_functions_in_if_condition = "warn"
+self_named_module_files = "warn"
+semicolon_if_nothing_returned = "warn"
+str_to_string = "warn"
+string_add = "warn"
+string_add_assign = "warn"
+string_lit_as_bytes = "warn"
+string_to_string = "warn"
+todo = "warn"
+trait_duplication_in_bounds = "warn"
+uninlined_format_args = "warn"
+verbose_file_reads = "warn"
+wildcard_imports = "warn"
+zero_sized_map_values = "warn"
+
+[lints.rust]
+unnameable_types = "warn"
+unreachable_pub = "warn"
+unsafe_op_in_unsafe_fn = "warn"
+unused_lifetimes = "warn"
+unused_macro_rules = "warn"
+unused_qualifications = "warn"
+
+[lints.rust.rust_2018_idioms]
+level = "warn"
+priority = -1
diff --git a/vendor/anstream/LICENSE-APACHE b/vendor/anstream/LICENSE-APACHE
new file mode 100644
index 00000000..8f71f43f
--- /dev/null
+++ b/vendor/anstream/LICENSE-APACHE
@@ -0,0 +1,202 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
diff --git a/vendor/anstream/LICENSE-MIT b/vendor/anstream/LICENSE-MIT
new file mode 100644
index 00000000..a2d01088
--- /dev/null
+++ b/vendor/anstream/LICENSE-MIT
@@ -0,0 +1,19 @@
+Copyright (c) Individual contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/anstream/README.md b/vendor/anstream/README.md
new file mode 100644
index 00000000..7e751d65
--- /dev/null
+++ b/vendor/anstream/README.md
@@ -0,0 +1,34 @@
+# anstream
+
+> A simple cross platform library for writing colored text to a terminal.
+
+*A portmanteau of "ansi stream"*
+
+[![Documentation](https://img.shields.io/badge/docs-master-blue.svg)][Documentation]
+![License](https://img.shields.io/crates/l/anstream.svg)
+[![Crates Status](https://img.shields.io/crates/v/anstream.svg)](https://crates.io/crates/anstream)
+
+Specialized `stdout` and `stderr` that accept ANSI escape codes and adapt them
+based on the terminal's capabilities.
+
+`anstream::adapter::strip_str` may also be of interest on its own for low
+overhead stripping of ANSI escape codes.
+
+## License
+
+Licensed under either of
+
+* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or <http://www.apache.org/licenses/LICENSE-2.0>)
+* MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
+
+at your option.
+
+## [Contribute](../../CONTRIBUTING.md)
+
+Unless you explicitly state otherwise, any contribution intentionally
+submitted for inclusion in the work by you, as defined in the Apache-2.0
+license, shall be dual-licensed as above, without any additional terms or
+conditions.
+
+[Crates.io]: https://crates.io/crates/anstream
+[Documentation]: https://docs.rs/anstream
diff --git a/vendor/anstream/examples/dump-stream.rs b/vendor/anstream/examples/dump-stream.rs
new file mode 100644
index 00000000..18bd2eb2
--- /dev/null
+++ b/vendor/anstream/examples/dump-stream.rs
@@ -0,0 +1,130 @@
+//! Write colored text, adapting to the terminals capabilities
+
+use std::io::Write;
+
+fn main() -> Result<(), lexopt::Error> {
+ let args = Args::parse()?;
+ let stdout = anstream::stdout();
+ let mut stdout = stdout.lock();
+
+ for fixed in 0..16 {
+ let color = anstyle::Ansi256Color(fixed)
+ .into_ansi()
+ .expect("within 4-bit color range");
+ let style = style(color, args.layer, args.effects);
+ let _ = print_number(&mut stdout, fixed, style);
+ if fixed == 7 || fixed == 15 {
+ let _ = writeln!(&mut stdout);
+ }
+ }
+
+ for fixed in 16..232 {
+ let col = (fixed - 16) % 36;
+ if col == 0 {
+ let _ = writeln!(stdout);
+ }
+ let color = anstyle::Ansi256Color(fixed);
+ let style = style(color, args.layer, args.effects);
+ let _ = print_number(&mut stdout, fixed, style);
+ }
+
+ let _ = writeln!(stdout);
+ let _ = writeln!(stdout);
+ for fixed in 232..=255 {
+ let color = anstyle::Ansi256Color(fixed);
+ let style = style(color, args.layer, args.effects);
+ let _ = print_number(&mut stdout, fixed, style);
+ }
+
+ let _ = writeln!(stdout);
+
+ Ok(())
+}
+
+fn style(
+ color: impl Into<anstyle::Color>,
+ layer: Layer,
+ effects: anstyle::Effects,
+) -> anstyle::Style {
+ let color = color.into();
+ (match layer {
+ Layer::Fg => anstyle::Style::new().fg_color(Some(color)),
+ Layer::Bg => anstyle::Style::new().bg_color(Some(color)),
+ Layer::Underline => anstyle::Style::new().underline_color(Some(color)),
+ }) | effects
+}
+
+fn print_number(stdout: &mut impl Write, fixed: u8, style: anstyle::Style) -> std::io::Result<()> {
+ write!(stdout, "{style}{fixed:>3X}{style:#}",)
+}
+
+#[derive(Default)]
+struct Args {
+ effects: anstyle::Effects,
+ layer: Layer,
+}
+
+#[derive(Copy, Clone, Default)]
+enum Layer {
+ #[default]
+ Fg,
+ Bg,
+ Underline,
+}
+
+impl Args {
+ fn parse() -> Result<Self, lexopt::Error> {
+ use lexopt::prelude::*;
+
+ let mut res = Args::default();
+
+ let mut args = lexopt::Parser::from_env();
+ while let Some(arg) = args.next()? {
+ match arg {
+ Long("layer") => {
+ res.layer = args.value()?.parse_with(|s| match s {
+ "fg" => Ok(Layer::Fg),
+ "bg" => Ok(Layer::Bg),
+ "underline" => Ok(Layer::Underline),
+ _ => Err("expected values fg, bg, underline"),
+ })?;
+ }
+ Long("effect") => {
+ const EFFECTS: [(&str, anstyle::Effects); 12] = [
+ ("bold", anstyle::Effects::BOLD),
+ ("dimmed", anstyle::Effects::DIMMED),
+ ("italic", anstyle::Effects::ITALIC),
+ ("underline", anstyle::Effects::UNDERLINE),
+ ("double_underline", anstyle::Effects::DOUBLE_UNDERLINE),
+ ("curly_underline", anstyle::Effects::CURLY_UNDERLINE),
+ ("dotted_underline", anstyle::Effects::DOTTED_UNDERLINE),
+ ("dashed_underline", anstyle::Effects::DASHED_UNDERLINE),
+ ("blink", anstyle::Effects::BLINK),
+ ("invert", anstyle::Effects::INVERT),
+ ("hidden", anstyle::Effects::HIDDEN),
+ ("strikethrough", anstyle::Effects::STRIKETHROUGH),
+ ];
+ let effect = args.value()?.parse_with(|s| {
+ EFFECTS
+ .into_iter()
+ .find(|(name, _)| *name == s)
+ .map(|(_, effect)| effect)
+ .ok_or_else(|| {
+ format!(
+ "expected one of {}",
+ EFFECTS
+ .into_iter()
+ .map(|(n, _)| n)
+ .collect::<Vec<_>>()
+ .join(", ")
+ )
+ })
+ })?;
+ res.effects = res.effects.insert(effect);
+ }
+ _ => return Err(arg.unexpected()),
+ }
+ }
+ Ok(res)
+ }
+}
diff --git a/vendor/anstream/examples/query-stream.rs b/vendor/anstream/examples/query-stream.rs
new file mode 100644
index 00000000..1c8670ec
--- /dev/null
+++ b/vendor/anstream/examples/query-stream.rs
@@ -0,0 +1,22 @@
+//! Report a terminal's capabilities
+
+fn main() {
+ println!("stdout:");
+ println!(
+ " choice: {:?}",
+ anstream::AutoStream::choice(&std::io::stdout())
+ );
+ println!(
+ " choice: {:?}",
+ anstream::AutoStream::auto(std::io::stdout()).current_choice()
+ );
+ println!("stderr:");
+ println!(
+ " choice: {:?}",
+ anstream::AutoStream::choice(&std::io::stderr())
+ );
+ println!(
+ " choice: {:?}",
+ anstream::AutoStream::auto(std::io::stderr()).current_choice()
+ );
+}
diff --git a/vendor/anstream/src/_macros.rs b/vendor/anstream/src/_macros.rs
new file mode 100644
index 00000000..a1fa97d3
--- /dev/null
+++ b/vendor/anstream/src/_macros.rs
@@ -0,0 +1,364 @@
+/// Prints to [`stdout`][crate::stdout].
+///
+/// Equivalent to the [`println!`] macro except that a newline is not printed at
+/// the end of the message.
+///
+/// Note that stdout is frequently line-buffered by default so it may be
+/// necessary to use [`std::io::Write::flush()`] to ensure the output is emitted
+/// immediately.
+///
+/// **NOTE:** The `print!` macro will lock the standard output on each call. If you call
+/// `print!` within a hot loop, this behavior may be the bottleneck of the loop.
+/// To avoid this, lock stdout with [`AutoStream::lock`][crate::AutoStream::lock]:
+/// ```
+/// # #[cfg(feature = "auto")] {
+/// use std::io::Write as _;
+///
+/// let mut lock = anstream::stdout().lock();
+/// write!(lock, "hello world").unwrap();
+/// # }
+/// ```
+///
+/// Use `print!` only for the primary output of your program. Use
+/// [`eprint!`] instead to print error and progress messages.
+///
+/// **NOTE:** Not all `print!` calls will be captured in tests like [`std::print!`]
+/// - Capturing will automatically be activated in test binaries
+/// - Otherwise, only when the `test` feature is enabled
+///
+/// # Panics
+///
+/// Panics if writing to `stdout` fails for any reason **except** broken pipe.
+///
+/// Writing to non-blocking stdout can cause an error, which will lead
+/// this macro to panic.
+///
+/// # Examples
+///
+/// ```
+/// # #[cfg(feature = "auto")] {
+/// use std::io::Write as _;
+/// use anstream::print;
+/// use anstream::stdout;
+///
+/// print!("this ");
+/// print!("will ");
+/// print!("be ");
+/// print!("on ");
+/// print!("the ");
+/// print!("same ");
+/// print!("line ");
+///
+/// stdout().flush().unwrap();
+///
+/// print!("this string has a newline, why not choose println! instead?\n");
+///
+/// stdout().flush().unwrap();
+/// # }
+/// ```
+#[cfg(feature = "auto")]
+#[macro_export]
+macro_rules! print {
+ ($($arg:tt)*) => {{
+ if cfg!(test) || $crate::_macros::FEATURE_TEST_ACTIVATED {
+ let target_stream = std::io::stdout();
+ let buffer = $crate::_macros::to_adapted_string(&format_args!($($arg)*), &target_stream);
+ ::std::print!("{}", buffer)
+ } else {
+ use std::io::Write as _;
+
+ let mut stream = $crate::stdout();
+ match ::std::write!(&mut stream, $($arg)*) {
+ Err(e) if e.kind() != ::std::io::ErrorKind::BrokenPipe => {
+ ::std::panic!("failed printing to stdout: {e}");
+ }
+ Err(_) | Ok(_) => {}
+ }
+ }
+ }};
+}
+
+/// Prints to [`stdout`][crate::stdout], with a newline.
+///
+/// On all platforms, the newline is the LINE FEED character (`\n`/`U+000A`) alone
+/// (no additional CARRIAGE RETURN (`\r`/`U+000D`)).
+///
+/// This macro uses the same syntax as [`format!`], but writes to the standard output instead.
+/// See [`std::fmt`] for more information.
+///
+/// **NOTE:** The `println!` macro will lock the standard output on each call. If you call
+/// `println!` within a hot loop, this behavior may be the bottleneck of the loop.
+/// To avoid this, lock stdout with [`AutoStream::lock`][crate::AutoStream::lock]:
+/// ```
+/// # #[cfg(feature = "auto")] {
+/// use std::io::Write as _;
+///
+/// let mut lock = anstream::stdout().lock();
+/// writeln!(lock, "hello world").unwrap();
+/// # }
+/// ```
+///
+/// Use `println!` only for the primary output of your program. Use
+/// [`eprintln!`] instead to print error and progress messages.
+///
+/// **NOTE:** Not all `println!` calls will be captured in tests like [`std::println!`]
+/// - Capturing will automatically be activated in test binaries
+/// - Otherwise, only when the `test` feature is enabled
+///
+/// # Panics
+///
+/// Panics if writing to `stdout` fails for any reason **except** broken pipe.
+///
+/// Writing to non-blocking stdout can cause an error, which will lead
+/// this macro to panic.
+///
+/// # Examples
+///
+/// ```
+/// # #[cfg(feature = "auto")] {
+/// use anstream::println;
+///
+/// println!(); // prints just a newline
+/// println!("hello there!");
+/// println!("format {} arguments", "some");
+/// let local_variable = "some";
+/// println!("format {local_variable} arguments");
+/// # }
+/// ```
+#[cfg(feature = "auto")]
+#[macro_export]
+macro_rules! println {
+ () => {
+ $crate::print!("\n")
+ };
+ ($($arg:tt)*) => {{
+ if cfg!(test) || $crate::_macros::FEATURE_TEST_ACTIVATED {
+ let target_stream = std::io::stdout();
+ let buffer = $crate::_macros::to_adapted_string(&format_args!($($arg)*), &target_stream);
+ ::std::println!("{}", buffer)
+ } else {
+ use std::io::Write as _;
+
+ let mut stream = $crate::stdout();
+ match ::std::writeln!(&mut stream, $($arg)*) {
+ Err(e) if e.kind() != ::std::io::ErrorKind::BrokenPipe => {
+ ::std::panic!("failed printing to stdout: {e}");
+ }
+ Err(_) | Ok(_) => {}
+ }
+ }
+ }};
+}
+
+/// Prints to [`stderr`][crate::stderr].
+///
+/// Equivalent to the [`print!`] macro, except that output goes to
+/// `stderr` instead of `stdout`. See [`print!`] for
+/// example usage.
+///
+/// Use `eprint!` only for error and progress messages. Use `print!`
+/// instead for the primary output of your program.
+///
+/// **NOTE:** Not all `eprint!` calls will be captured in tests like [`std::eprint!`]
+/// - Capturing will automatically be activated in test binaries
+/// - Otherwise, only when the `test` feature is enabled
+///
+/// # Panics
+///
+/// Panics if writing to `stderr` fails for any reason **except** broken pipe.
+///
+/// Writing to non-blocking stdout can cause an error, which will lead
+/// this macro to panic.
+///
+/// # Examples
+///
+/// ```
+/// # #[cfg(feature = "auto")] {
+/// use anstream::eprint;
+///
+/// eprint!("Error: Could not complete task");
+/// # }
+/// ```
+#[cfg(feature = "auto")]
+#[macro_export]
+macro_rules! eprint {
+ ($($arg:tt)*) => {{
+ if cfg!(test) || $crate::_macros::FEATURE_TEST_ACTIVATED {
+ let target_stream = std::io::stderr();
+ let buffer = $crate::_macros::to_adapted_string(&format_args!($($arg)*), &target_stream);
+ ::std::eprint!("{}", buffer)
+ } else {
+ use std::io::Write as _;
+
+ let mut stream = $crate::stderr();
+ match ::std::write!(&mut stream, $($arg)*) {
+ Err(e) if e.kind() != ::std::io::ErrorKind::BrokenPipe => {
+ ::std::panic!("failed printing to stderr: {e}");
+ }
+ Err(_) | Ok(_) => {}
+ }
+ }
+ }};
+}
+
+/// Prints to [`stderr`][crate::stderr], with a newline.
+///
+/// Equivalent to the [`println!`] macro, except that output goes to
+/// `stderr` instead of `stdout`. See [`println!`] for
+/// example usage.
+///
+/// Use `eprintln!` only for error and progress messages. Use `println!`
+/// instead for the primary output of your program.
+///
+/// **NOTE:** Not all `eprintln!` calls will be captured in tests like [`std::eprintln!`]
+/// - Capturing will automatically be activated in test binaries
+/// - Otherwise, only when the `test` feature is enabled
+///
+/// # Panics
+///
+/// Panics if writing to `stderr` fails for any reason **except** broken pipe.
+///
+/// Writing to non-blocking stdout can cause an error, which will lead
+/// this macro to panic.
+///
+/// # Examples
+///
+/// ```
+/// # #[cfg(feature = "auto")] {
+/// use anstream::eprintln;
+///
+/// eprintln!("Error: Could not complete task");
+/// # }
+/// ```
+#[cfg(feature = "auto")]
+#[macro_export]
+macro_rules! eprintln {
+ () => {
+ $crate::eprint!("\n")
+ };
+ ($($arg:tt)*) => {{
+ if cfg!(test) || $crate::_macros::FEATURE_TEST_ACTIVATED {
+ let target_stream = std::io::stderr();
+ let buffer = $crate::_macros::to_adapted_string(&format_args!($($arg)*), &target_stream);
+ ::std::eprintln!("{}", buffer)
+ } else {
+ use std::io::Write as _;
+
+ let mut stream = $crate::stderr();
+ match ::std::writeln!(&mut stream, $($arg)*) {
+ Err(e) if e.kind() != ::std::io::ErrorKind::BrokenPipe => {
+ ::std::panic!("failed printing to stderr: {e}");
+ }
+ Err(_) | Ok(_) => {}
+ }
+ }
+ }};
+}
+
+/// Panics the current thread.
+///
+/// This allows a program to terminate immediately and provide feedback
+/// to the caller of the program.
+///
+/// This macro is the perfect way to assert conditions in example code and in
+/// tests. `panic!` is closely tied with the `unwrap` method of both
+/// [`Option`][ounwrap] and [`Result`][runwrap] enums. Both implementations call
+/// `panic!` when they are set to [`None`] or [`Err`] variants.
+///
+/// When using `panic!()` you can specify a string payload, that is built using
+/// the [`format!`] syntax. That payload is used when injecting the panic into
+/// the calling Rust thread, causing the thread to panic entirely.
+///
+/// The behavior of the default `std` hook, i.e. the code that runs directly
+/// after the panic is invoked, is to print the message payload to
+/// `stderr` along with the file/line/column information of the `panic!()`
+/// call. You can override the panic hook using [`std::panic::set_hook()`].
+/// Inside the hook a panic can be accessed as a `&dyn Any + Send`,
+/// which contains either a `&str` or `String` for regular `panic!()` invocations.
+/// To panic with a value of another other type, [`panic_any`] can be used.
+///
+/// See also the macro [`compile_error!`], for raising errors during compilation.
+///
+/// # When to use `panic!` vs `Result`
+///
+/// The Rust language provides two complementary systems for constructing /
+/// representing, reporting, propagating, reacting to, and discarding errors. These
+/// responsibilities are collectively known as "error handling." `panic!` and
+/// `Result` are similar in that they are each the primary interface of their
+/// respective error handling systems; however, the meaning these interfaces attach
+/// to their errors and the responsibilities they fulfill within their respective
+/// error handling systems differ.
+///
+/// The `panic!` macro is used to construct errors that represent a bug that has
+/// been detected in your program. With `panic!` you provide a message that
+/// describes the bug and the language then constructs an error with that message,
+/// reports it, and propagates it for you.
+///
+/// `Result` on the other hand is used to wrap other types that represent either
+/// the successful result of some computation, `Ok(T)`, or error types that
+/// represent an anticipated runtime failure mode of that computation, `Err(E)`.
+/// `Result` is used alongside user defined types which represent the various
+/// anticipated runtime failure modes that the associated computation could
+/// encounter. `Result` must be propagated manually, often with the help of the
+/// `?` operator and `Try` trait, and they must be reported manually, often with
+/// the help of the `Error` trait.
+///
+/// For more detailed information about error handling check out the [book] or the
+/// [`std::result`] module docs.
+///
+/// [ounwrap]: Option::unwrap
+/// [runwrap]: Result::unwrap
+/// [`std::panic::set_hook()`]: ../std/panic/fn.set_hook.html
+/// [`panic_any`]: ../std/panic/fn.panic_any.html
+/// [`Box`]: ../std/boxed/struct.Box.html
+/// [`format!`]: ../std/macro.format.html
+/// [book]: ../book/ch09-00-error-handling.html
+/// [`std::result`]: ../std/result/index.html
+///
+/// # Current implementation
+///
+/// If the main thread panics it will terminate all your threads and end your
+/// program with code `101`.
+///
+/// # Examples
+///
+/// ```should_panic
+/// # #![allow(unreachable_code)]
+/// use anstream::panic;
+/// panic!();
+/// panic!("this is a terrible mistake!");
+/// panic!("this is a {} {message}", "fancy", message = "message");
+/// ```
+#[cfg(feature = "auto")]
+#[macro_export]
+macro_rules! panic {
+ () => {
+ ::std::panic!()
+ };
+ ($($arg:tt)*) => {{
+ let target_stream = std::io::stderr();
+ let buffer = $crate::_macros::to_adapted_string(&format_args!($($arg)*), &target_stream);
+ ::std::panic!("{}", buffer)
+ }};
+}
+
+#[cfg(feature = "auto")]
+pub const FEATURE_TEST_ACTIVATED: bool = cfg!(feature = "test");
+
+#[cfg(feature = "auto")]
+pub fn to_adapted_string(
+ display: &dyn std::fmt::Display,
+ stream: &impl crate::stream::RawStream,
+) -> String {
+ use std::io::Write as _;
+
+ let choice = crate::AutoStream::choice(stream);
+ let buffer = Vec::new();
+ let mut stream = crate::AutoStream::new(buffer, choice);
+ // Ignore errors rather than panic
+ let _ = ::std::write!(&mut stream, "{display}");
+ let buffer = stream.into_inner();
+ // Should be UTF-8 but not wanting to panic
+ let buffer = String::from_utf8_lossy(&buffer).into_owned();
+ buffer
+}
diff --git a/vendor/anstream/src/adapter/mod.rs b/vendor/anstream/src/adapter/mod.rs
new file mode 100644
index 00000000..f266b680
--- /dev/null
+++ b/vendor/anstream/src/adapter/mod.rs
@@ -0,0 +1,15 @@
+//! Gracefully degrade styled output
+
+mod strip;
+mod wincon;
+
+pub use strip::strip_bytes;
+pub use strip::strip_str;
+pub use strip::StripBytes;
+pub use strip::StripBytesIter;
+pub use strip::StripStr;
+pub use strip::StripStrIter;
+pub use strip::StrippedBytes;
+pub use strip::StrippedStr;
+pub use wincon::WinconBytes;
+pub use wincon::WinconBytesIter;
diff --git a/vendor/anstream/src/adapter/strip.rs b/vendor/anstream/src/adapter/strip.rs
new file mode 100644
index 00000000..dca414bb
--- /dev/null
+++ b/vendor/anstream/src/adapter/strip.rs
@@ -0,0 +1,511 @@
+use anstyle_parse::state::state_change;
+use anstyle_parse::state::Action;
+use anstyle_parse::state::State;
+
+/// Strip ANSI escapes from a `&str`, returning the printable content
+///
+/// This can be used to take output from a program that includes escape sequences and write it
+/// somewhere that does not easily support them, such as a log file.
+///
+/// For non-contiguous data, see [`StripStr`].
+///
+/// # Example
+///
+/// ```rust
+/// use std::io::Write as _;
+///
+/// let styled_text = "\x1b[32mfoo\x1b[m bar";
+/// let plain_str = anstream::adapter::strip_str(&styled_text).to_string();
+/// assert_eq!(plain_str, "foo bar");
+/// ```
+#[inline]
+pub fn strip_str(data: &str) -> StrippedStr<'_> {
+ StrippedStr::new(data)
+}
+
+/// See [`strip_str`]
+#[derive(Default, Clone, Debug, PartialEq, Eq)]
+pub struct StrippedStr<'s> {
+ bytes: &'s [u8],
+ state: State,
+}
+
+impl<'s> StrippedStr<'s> {
+ #[inline]
+ fn new(data: &'s str) -> Self {
+ Self {
+ bytes: data.as_bytes(),
+ state: State::Ground,
+ }
+ }
+
+ /// Create a [`String`] of the printable content
+ #[inline]
+ #[allow(clippy::inherent_to_string_shadow_display)] // Single-allocation implementation
+ pub fn to_string(&self) -> String {
+ use std::fmt::Write as _;
+ let mut stripped = String::with_capacity(self.bytes.len());
+ let _ = write!(&mut stripped, "{self}");
+ stripped
+ }
+}
+
+impl std::fmt::Display for StrippedStr<'_> {
+ /// **Note:** this does *not* exhaust the [`Iterator`]
+ #[inline]
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ let iter = Self {
+ bytes: self.bytes,
+ state: self.state,
+ };
+ for printable in iter {
+ printable.fmt(f)?;
+ }
+ Ok(())
+ }
+}
+
+impl<'s> Iterator for StrippedStr<'s> {
+ type Item = &'s str;
+
+ #[inline]
+ fn next(&mut self) -> Option<Self::Item> {
+ next_str(&mut self.bytes, &mut self.state)
+ }
+}
+
+/// Incrementally strip non-contiguous data
+#[derive(Default, Clone, Debug, PartialEq, Eq)]
+pub struct StripStr {
+ state: State,
+}
+
+impl StripStr {
+ /// Initial state
+ pub fn new() -> Self {
+ Default::default()
+ }
+
+ /// Strip the next segment of data
+ pub fn strip_next<'s>(&'s mut self, data: &'s str) -> StripStrIter<'s> {
+ StripStrIter {
+ bytes: data.as_bytes(),
+ state: &mut self.state,
+ }
+ }
+}
+
+/// See [`StripStr`]
+#[derive(Debug, PartialEq, Eq)]
+pub struct StripStrIter<'s> {
+ bytes: &'s [u8],
+ state: &'s mut State,
+}
+
+impl<'s> Iterator for StripStrIter<'s> {
+ type Item = &'s str;
+
+ #[inline]
+ fn next(&mut self) -> Option<Self::Item> {
+ next_str(&mut self.bytes, self.state)
+ }
+}
+
+#[inline]
+fn next_str<'s>(bytes: &mut &'s [u8], state: &mut State) -> Option<&'s str> {
+ let offset = bytes.iter().copied().position(|b| {
+ let (next_state, action) = state_change(*state, b);
+ if next_state != State::Anywhere {
+ *state = next_state;
+ }
+ is_printable_bytes(action, b)
+ });
+ let (_, next) = bytes.split_at(offset.unwrap_or(bytes.len()));
+ *bytes = next;
+ *state = State::Ground;
+
+ let offset = bytes.iter().copied().position(|b| {
+ let (_next_state, action) = state_change(State::Ground, b);
+ !(is_printable_bytes(action, b) || is_utf8_continuation(b))
+ });
+ let (printable, next) = bytes.split_at(offset.unwrap_or(bytes.len()));
+ *bytes = next;
+ if printable.is_empty() {
+ None
+ } else {
+ let printable = unsafe {
+ from_utf8_unchecked(
+ printable,
+ "`bytes` was validated as UTF-8, the parser preserves UTF-8 continuations",
+ )
+ };
+ Some(printable)
+ }
+}
+
+#[inline]
+unsafe fn from_utf8_unchecked<'b>(bytes: &'b [u8], safety_justification: &'static str) -> &'b str {
+ unsafe {
+ if cfg!(debug_assertions) {
+ // Catch problems more quickly when testing
+ std::str::from_utf8(bytes).expect(safety_justification)
+ } else {
+ std::str::from_utf8_unchecked(bytes)
+ }
+ }
+}
+
+#[inline]
+fn is_utf8_continuation(b: u8) -> bool {
+ matches!(b, 0x80..=0xbf)
+}
+
+/// Strip ANSI escapes from bytes, returning the printable content
+///
+/// This can be used to take output from a program that includes escape sequences and write it
+/// somewhere that does not easily support them, such as a log file.
+///
+/// # Example
+///
+/// ```rust
+/// use std::io::Write as _;
+///
+/// let styled_text = "\x1b[32mfoo\x1b[m bar";
+/// let plain_str = anstream::adapter::strip_bytes(styled_text.as_bytes()).into_vec();
+/// assert_eq!(plain_str.as_slice(), &b"foo bar"[..]);
+/// ```
+#[inline]
+pub fn strip_bytes(data: &[u8]) -> StrippedBytes<'_> {
+ StrippedBytes::new(data)
+}
+
+/// See [`strip_bytes`]
+#[derive(Default, Clone, Debug, PartialEq, Eq)]
+pub struct StrippedBytes<'s> {
+ bytes: &'s [u8],
+ state: State,
+ utf8parser: Utf8Parser,
+}
+
+impl<'s> StrippedBytes<'s> {
+ /// See [`strip_bytes`]
+ #[inline]
+ pub fn new(bytes: &'s [u8]) -> Self {
+ Self {
+ bytes,
+ state: State::Ground,
+ utf8parser: Default::default(),
+ }
+ }
+
+ /// Strip the next slice of bytes
+ ///
+ /// Used when the content is in several non-contiguous slices
+ ///
+ /// # Panic
+ ///
+ /// May panic if it is not exhausted / empty
+ #[inline]
+ pub fn extend(&mut self, bytes: &'s [u8]) {
+ debug_assert!(
+ self.is_empty(),
+ "current bytes must be processed to ensure we end at the right state"
+ );
+ self.bytes = bytes;
+ }
+
+ /// Report the bytes has been exhausted
+ #[inline]
+ pub fn is_empty(&self) -> bool {
+ self.bytes.is_empty()
+ }
+
+ /// Create a [`Vec`] of the printable content
+ #[inline]
+ pub fn into_vec(self) -> Vec<u8> {
+ let mut stripped = Vec::with_capacity(self.bytes.len());
+ for printable in self {
+ stripped.extend(printable);
+ }
+ stripped
+ }
+}
+
+impl<'s> Iterator for StrippedBytes<'s> {
+ type Item = &'s [u8];
+
+ #[inline]
+ fn next(&mut self) -> Option<Self::Item> {
+ next_bytes(&mut self.bytes, &mut self.state, &mut self.utf8parser)
+ }
+}
+
+/// Incrementally strip non-contiguous data
+#[derive(Default, Clone, Debug, PartialEq, Eq)]
+pub struct StripBytes {
+ state: State,
+ utf8parser: Utf8Parser,
+}
+
+impl StripBytes {
+ /// Initial state
+ pub fn new() -> Self {
+ Default::default()
+ }
+
+ /// Strip the next segment of data
+ pub fn strip_next<'s>(&'s mut self, bytes: &'s [u8]) -> StripBytesIter<'s> {
+ StripBytesIter {
+ bytes,
+ state: &mut self.state,
+ utf8parser: &mut self.utf8parser,
+ }
+ }
+}
+
+/// See [`StripBytes`]
+#[derive(Debug, PartialEq, Eq)]
+pub struct StripBytesIter<'s> {
+ bytes: &'s [u8],
+ state: &'s mut State,
+ utf8parser: &'s mut Utf8Parser,
+}
+
+impl<'s> Iterator for StripBytesIter<'s> {
+ type Item = &'s [u8];
+
+ #[inline]
+ fn next(&mut self) -> Option<Self::Item> {
+ next_bytes(&mut self.bytes, self.state, self.utf8parser)
+ }
+}
+
+#[inline]
+fn next_bytes<'s>(
+ bytes: &mut &'s [u8],
+ state: &mut State,
+ utf8parser: &mut Utf8Parser,
+) -> Option<&'s [u8]> {
+ let offset = bytes.iter().copied().position(|b| {
+ if *state == State::Utf8 {
+ true
+ } else {
+ let (next_state, action) = state_change(*state, b);
+ if next_state != State::Anywhere {
+ *state = next_state;
+ }
+ is_printable_bytes(action, b)
+ }
+ });
+ let (_, next) = bytes.split_at(offset.unwrap_or(bytes.len()));
+ *bytes = next;
+
+ let offset = bytes.iter().copied().position(|b| {
+ if *state == State::Utf8 {
+ if utf8parser.add(b) {
+ *state = State::Ground;
+ }
+ false
+ } else {
+ let (next_state, action) = state_change(State::Ground, b);
+ if next_state != State::Anywhere {
+ *state = next_state;
+ }
+ if *state == State::Utf8 {
+ utf8parser.add(b);
+ false
+ } else {
+ !is_printable_bytes(action, b)
+ }
+ }
+ });
+ let (printable, next) = bytes.split_at(offset.unwrap_or(bytes.len()));
+ *bytes = next;
+ if printable.is_empty() {
+ None
+ } else {
+ Some(printable)
+ }
+}
+
+#[derive(Default, Clone, Debug, PartialEq, Eq)]
+pub(crate) struct Utf8Parser {
+ utf8_parser: utf8parse::Parser,
+}
+
+impl Utf8Parser {
+ fn add(&mut self, byte: u8) -> bool {
+ let mut b = false;
+ let mut receiver = VtUtf8Receiver(&mut b);
+ self.utf8_parser.advance(&mut receiver, byte);
+ b
+ }
+}
+
+struct VtUtf8Receiver<'a>(&'a mut bool);
+
+impl utf8parse::Receiver for VtUtf8Receiver<'_> {
+ fn codepoint(&mut self, _: char) {
+ *self.0 = true;
+ }
+
+ fn invalid_sequence(&mut self) {
+ *self.0 = true;
+ }
+}
+
+#[inline]
+fn is_printable_bytes(action: Action, byte: u8) -> bool {
+ // VT320 considered 0x7f to be `Print`able but we expect to be working in UTF-8 systems and not
+ // ISO Latin-1, making it DEL and non-printable
+ const DEL: u8 = 0x7f;
+
+ // Continuations aren't included as they may also be control codes, requiring more context
+ (action == Action::Print && byte != DEL)
+ || action == Action::BeginUtf8
+ || (action == Action::Execute && byte.is_ascii_whitespace())
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+ use proptest::prelude::*;
+
+ /// Model based off full parser
+ fn parser_strip(bytes: &[u8]) -> String {
+ #[derive(Default)]
+ struct Strip(String);
+ impl Strip {
+ fn with_capacity(capacity: usize) -> Self {
+ Self(String::with_capacity(capacity))
+ }
+ }
+ impl anstyle_parse::Perform for Strip {
+ fn print(&mut self, c: char) {
+ self.0.push(c);
+ }
+
+ fn execute(&mut self, byte: u8) {
+ if byte.is_ascii_whitespace() {
+ self.0.push(byte as char);
+ }
+ }
+ }
+
+ let mut stripped = Strip::with_capacity(bytes.len());
+ let mut parser = anstyle_parse::Parser::<anstyle_parse::DefaultCharAccumulator>::new();
+ for byte in bytes {
+ parser.advance(&mut stripped, *byte);
+ }
+ stripped.0
+ }
+
+ /// Model verifying incremental parsing
+ fn strip_char(mut s: &str) -> String {
+ let mut result = String::new();
+ let mut state = StripStr::new();
+ while !s.is_empty() {
+ let mut indices = s.char_indices();
+ indices.next(); // current
+ let offset = indices.next().map(|(i, _)| i).unwrap_or_else(|| s.len());
+ let (current, remainder) = s.split_at(offset);
+ for printable in state.strip_next(current) {
+ result.push_str(printable);
+ }
+ s = remainder;
+ }
+ result
+ }
+
+ /// Model verifying incremental parsing
+ fn strip_byte(s: &[u8]) -> Vec<u8> {
+ let mut result = Vec::new();
+ let mut state = StripBytes::default();
+ for start in 0..s.len() {
+ let current = &s[start..=start];
+ for printable in state.strip_next(current) {
+ result.extend(printable);
+ }
+ }
+ result
+ }
+
+ #[test]
+ fn test_strip_bytes_multibyte() {
+ let bytes = [240, 145, 141, 139];
+ let expected = parser_strip(&bytes);
+ let actual = String::from_utf8(strip_bytes(&bytes).into_vec()).unwrap();
+ assert_eq!(expected, actual);
+ }
+
+ #[test]
+ fn test_strip_byte_multibyte() {
+ let bytes = [240, 145, 141, 139];
+ let expected = parser_strip(&bytes);
+ let actual = String::from_utf8(strip_byte(&bytes).clone()).unwrap();
+ assert_eq!(expected, actual);
+ }
+
+ #[test]
+ fn test_strip_str_del() {
+ let input = std::str::from_utf8(&[0x7f]).unwrap();
+ let expected = "";
+ let actual = strip_str(input).to_string();
+ assert_eq!(expected, actual);
+ }
+
+ #[test]
+ fn test_strip_byte_del() {
+ let bytes = [0x7f];
+ let expected = "";
+ let actual = String::from_utf8(strip_byte(&bytes).clone()).unwrap();
+ assert_eq!(expected, actual);
+ }
+
+ #[test]
+ fn test_strip_str_handles_broken_sequence() {
+ // valid utf8: \xc3\xb6 then \x1b then \xf0\x9f\x98\x80
+ let s = "ö\x1b😀hello😀goodbye";
+ let mut it = strip_str(s);
+ assert_eq!("ö", it.next().unwrap());
+ assert_eq!("ello😀goodbye", it.next().unwrap());
+ }
+
+ proptest! {
+ #[test]
+ #[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253
+ fn strip_str_no_escapes(s in "\\PC*") {
+ let expected = parser_strip(s.as_bytes());
+ let actual = strip_str(&s).to_string();
+ assert_eq!(expected, actual);
+ }
+
+ #[test]
+ #[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253
+ fn strip_char_no_escapes(s in "\\PC*") {
+ let expected = parser_strip(s.as_bytes());
+ let actual = strip_char(&s);
+ assert_eq!(expected, actual);
+ }
+
+ #[test]
+ #[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253
+ fn strip_bytes_no_escapes(s in "\\PC*") {
+ dbg!(&s);
+ dbg!(s.as_bytes());
+ let expected = parser_strip(s.as_bytes());
+ let actual = String::from_utf8(strip_bytes(s.as_bytes()).into_vec()).unwrap();
+ assert_eq!(expected, actual);
+ }
+
+ #[test]
+ #[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253
+ fn strip_byte_no_escapes(s in "\\PC*") {
+ dbg!(&s);
+ dbg!(s.as_bytes());
+ let expected = parser_strip(s.as_bytes());
+ let actual = String::from_utf8(strip_byte(s.as_bytes()).clone()).unwrap();
+ assert_eq!(expected, actual);
+ }
+ }
+}
diff --git a/vendor/anstream/src/adapter/wincon.rs b/vendor/anstream/src/adapter/wincon.rs
new file mode 100644
index 00000000..c2114919
--- /dev/null
+++ b/vendor/anstream/src/adapter/wincon.rs
@@ -0,0 +1,378 @@
+/// Incrementally convert to wincon calls for non-contiguous data
+#[derive(Default, Clone, Debug, PartialEq, Eq)]
+pub struct WinconBytes {
+ parser: anstyle_parse::Parser,
+ capture: WinconCapture,
+}
+
+impl WinconBytes {
+ /// Initial state
+ pub fn new() -> Self {
+ Default::default()
+ }
+
+ /// Strip the next segment of data
+ pub fn extract_next<'s>(&'s mut self, bytes: &'s [u8]) -> WinconBytesIter<'s> {
+ self.capture.reset();
+ self.capture.printable.reserve(bytes.len());
+ WinconBytesIter {
+ bytes,
+ parser: &mut self.parser,
+ capture: &mut self.capture,
+ }
+ }
+}
+
+/// See [`WinconBytes`]
+#[derive(Debug, PartialEq, Eq)]
+pub struct WinconBytesIter<'s> {
+ bytes: &'s [u8],
+ parser: &'s mut anstyle_parse::Parser,
+ capture: &'s mut WinconCapture,
+}
+
+impl Iterator for WinconBytesIter<'_> {
+ type Item = (anstyle::Style, String);
+
+ #[inline]
+ fn next(&mut self) -> Option<Self::Item> {
+ next_bytes(&mut self.bytes, self.parser, self.capture)
+ }
+}
+
+#[inline]
+fn next_bytes(
+ bytes: &mut &[u8],
+ parser: &mut anstyle_parse::Parser,
+ capture: &mut WinconCapture,
+) -> Option<(anstyle::Style, String)> {
+ capture.reset();
+ while capture.ready.is_none() {
+ let byte = if let Some((byte, remainder)) = (*bytes).split_first() {
+ *bytes = remainder;
+ *byte
+ } else {
+ break;
+ };
+ parser.advance(capture, byte);
+ }
+ if capture.printable.is_empty() {
+ return None;
+ }
+
+ let style = capture.ready.unwrap_or(capture.style);
+ Some((style, std::mem::take(&mut capture.printable)))
+}
+
+#[derive(Default, Clone, Debug, PartialEq, Eq)]
+struct WinconCapture {
+ style: anstyle::Style,
+ printable: String,
+ ready: Option<anstyle::Style>,
+}
+
+impl WinconCapture {
+ fn reset(&mut self) {
+ self.ready = None;
+ }
+}
+
+impl anstyle_parse::Perform for WinconCapture {
+ /// Draw a character to the screen and update states.
+ fn print(&mut self, c: char) {
+ self.printable.push(c);
+ }
+
+ /// Execute a C0 or C1 control function.
+ fn execute(&mut self, byte: u8) {
+ if byte.is_ascii_whitespace() {
+ self.printable.push(byte as char);
+ }
+ }
+
+ fn csi_dispatch(
+ &mut self,
+ params: &anstyle_parse::Params,
+ _intermediates: &[u8],
+ ignore: bool,
+ action: u8,
+ ) {
+ if ignore {
+ return;
+ }
+ if action != b'm' {
+ return;
+ }
+
+ let mut style = self.style;
+ // param/value differences are dependent on the escape code
+ let mut state = CsiState::Normal;
+ let mut r = None;
+ let mut g = None;
+ let mut color_target = ColorTarget::Fg;
+ for param in params {
+ for value in param {
+ match (state, *value) {
+ (CsiState::Normal, 0) => {
+ style = anstyle::Style::default();
+ break;
+ }
+ (CsiState::Normal, 1) => {
+ style = style.bold();
+ break;
+ }
+ (CsiState::Normal, 2) => {
+ style = style.dimmed();
+ break;
+ }
+ (CsiState::Normal, 3) => {
+ style = style.italic();
+ break;
+ }
+ (CsiState::Normal, 4) => {
+ style = style.underline();
+ state = CsiState::Underline;
+ }
+ (CsiState::Normal, 21) => {
+ style |= anstyle::Effects::DOUBLE_UNDERLINE;
+ break;
+ }
+ (CsiState::Normal, 7) => {
+ style = style.invert();
+ break;
+ }
+ (CsiState::Normal, 8) => {
+ style = style.hidden();
+ break;
+ }
+ (CsiState::Normal, 9) => {
+ style = style.strikethrough();
+ break;
+ }
+ (CsiState::Normal, 30..=37) => {
+ let color = to_ansi_color(value - 30).expect("within 4-bit range");
+ style = style.fg_color(Some(color.into()));
+ break;
+ }
+ (CsiState::Normal, 38) => {
+ color_target = ColorTarget::Fg;
+ state = CsiState::PrepareCustomColor;
+ }
+ (CsiState::Normal, 39) => {
+ style = style.fg_color(None);
+ break;
+ }
+ (CsiState::Normal, 40..=47) => {
+ let color = to_ansi_color(value - 40).expect("within 4-bit range");
+ style = style.bg_color(Some(color.into()));
+ break;
+ }
+ (CsiState::Normal, 48) => {
+ color_target = ColorTarget::Bg;
+ state = CsiState::PrepareCustomColor;
+ }
+ (CsiState::Normal, 49) => {
+ style = style.bg_color(None);
+ break;
+ }
+ (CsiState::Normal, 58) => {
+ color_target = ColorTarget::Underline;
+ state = CsiState::PrepareCustomColor;
+ }
+ (CsiState::Normal, 90..=97) => {
+ let color = to_ansi_color(value - 90)
+ .expect("within 4-bit range")
+ .bright(true);
+ style = style.fg_color(Some(color.into()));
+ break;
+ }
+ (CsiState::Normal, 100..=107) => {
+ let color = to_ansi_color(value - 100)
+ .expect("within 4-bit range")
+ .bright(true);
+ style = style.bg_color(Some(color.into()));
+ break;
+ }
+ (CsiState::PrepareCustomColor, 5) => {
+ state = CsiState::Ansi256;
+ }
+ (CsiState::PrepareCustomColor, 2) => {
+ state = CsiState::Rgb;
+ r = None;
+ g = None;
+ }
+ (CsiState::Ansi256, n) => {
+ let color = anstyle::Ansi256Color(n as u8);
+ style = match color_target {
+ ColorTarget::Fg => style.fg_color(Some(color.into())),
+ ColorTarget::Bg => style.bg_color(Some(color.into())),
+ ColorTarget::Underline => style.underline_color(Some(color.into())),
+ };
+ break;
+ }
+ (CsiState::Rgb, b) => match (r, g) {
+ (None, _) => {
+ r = Some(b);
+ }
+ (Some(_), None) => {
+ g = Some(b);
+ }
+ (Some(r), Some(g)) => {
+ let color = anstyle::RgbColor(r as u8, g as u8, b as u8);
+ style = match color_target {
+ ColorTarget::Fg => style.fg_color(Some(color.into())),
+ ColorTarget::Bg => style.bg_color(Some(color.into())),
+ ColorTarget::Underline => style.underline_color(Some(color.into())),
+ };
+ break;
+ }
+ },
+ (CsiState::Underline, 0) => {
+ style =
+ style.effects(style.get_effects().remove(anstyle::Effects::UNDERLINE));
+ }
+ (CsiState::Underline, 1) => {
+ // underline already set
+ }
+ (CsiState::Underline, 2) => {
+ style = style
+ .effects(style.get_effects().remove(anstyle::Effects::UNDERLINE))
+ | anstyle::Effects::DOUBLE_UNDERLINE;
+ }
+ (CsiState::Underline, 3) => {
+ style = style
+ .effects(style.get_effects().remove(anstyle::Effects::UNDERLINE))
+ | anstyle::Effects::CURLY_UNDERLINE;
+ }
+ (CsiState::Underline, 4) => {
+ style = style
+ .effects(style.get_effects().remove(anstyle::Effects::UNDERLINE))
+ | anstyle::Effects::DOTTED_UNDERLINE;
+ }
+ (CsiState::Underline, 5) => {
+ style = style
+ .effects(style.get_effects().remove(anstyle::Effects::UNDERLINE))
+ | anstyle::Effects::DASHED_UNDERLINE;
+ }
+ _ => {
+ break;
+ }
+ }
+ }
+ }
+
+ if style != self.style && !self.printable.is_empty() {
+ self.ready = Some(self.style);
+ }
+ self.style = style;
+ }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+enum CsiState {
+ Normal,
+ PrepareCustomColor,
+ Ansi256,
+ Rgb,
+ Underline,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+enum ColorTarget {
+ Fg,
+ Bg,
+ Underline,
+}
+
+fn to_ansi_color(digit: u16) -> Option<anstyle::AnsiColor> {
+ match digit {
+ 0 => Some(anstyle::AnsiColor::Black),
+ 1 => Some(anstyle::AnsiColor::Red),
+ 2 => Some(anstyle::AnsiColor::Green),
+ 3 => Some(anstyle::AnsiColor::Yellow),
+ 4 => Some(anstyle::AnsiColor::Blue),
+ 5 => Some(anstyle::AnsiColor::Magenta),
+ 6 => Some(anstyle::AnsiColor::Cyan),
+ 7 => Some(anstyle::AnsiColor::White),
+ _ => None,
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+ use proptest::prelude::*;
+
+ #[track_caller]
+ fn verify(input: &str, expected: Vec<(anstyle::Style, &str)>) {
+ let expected = expected
+ .into_iter()
+ .map(|(style, value)| (style, value.to_owned()))
+ .collect::<Vec<_>>();
+ let mut state = WinconBytes::new();
+ let actual = state.extract_next(input.as_bytes()).collect::<Vec<_>>();
+ assert_eq!(expected, actual, "{input:?}");
+ }
+
+ #[test]
+ fn start() {
+ let green_on_red = anstyle::AnsiColor::Green.on(anstyle::AnsiColor::Red);
+ let input = format!("{green_on_red}Hello{green_on_red:#} world!");
+ let expected = vec![
+ (green_on_red, "Hello"),
+ (anstyle::Style::default(), " world!"),
+ ];
+ verify(&input, expected);
+ }
+
+ #[test]
+ fn middle() {
+ let green_on_red = anstyle::AnsiColor::Green.on(anstyle::AnsiColor::Red);
+ let input = format!("Hello {green_on_red}world{green_on_red:#}!");
+ let expected = vec![
+ (anstyle::Style::default(), "Hello "),
+ (green_on_red, "world"),
+ (anstyle::Style::default(), "!"),
+ ];
+ verify(&input, expected);
+ }
+
+ #[test]
+ fn end() {
+ let green_on_red = anstyle::AnsiColor::Green.on(anstyle::AnsiColor::Red);
+ let input = format!("Hello {green_on_red}world!{green_on_red:#}");
+ let expected = vec![
+ (anstyle::Style::default(), "Hello "),
+ (green_on_red, "world!"),
+ ];
+ verify(&input, expected);
+ }
+
+ #[test]
+ fn ansi256_colors() {
+ let ansi_11 = anstyle::Ansi256Color(11).on_default();
+ // termcolor only supports "brights" via these
+ let input = format!("Hello {ansi_11}world{ansi_11:#}!");
+ let expected = vec![
+ (anstyle::Style::default(), "Hello "),
+ (ansi_11, "world"),
+ (anstyle::Style::default(), "!"),
+ ];
+ verify(&input, expected);
+ }
+
+ proptest! {
+ #[test]
+ #[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253
+ fn wincon_no_escapes(s in "\\PC*") {
+ let expected = if s.is_empty() {
+ vec![]
+ } else {
+ vec![(anstyle::Style::default(), s.clone())]
+ };
+ let mut state = WinconBytes::new();
+ let actual = state.extract_next(s.as_bytes()).collect::<Vec<_>>();
+ assert_eq!(expected, actual);
+ }
+ }
+}
diff --git a/vendor/anstream/src/auto.rs b/vendor/anstream/src/auto.rs
new file mode 100644
index 00000000..743640f8
--- /dev/null
+++ b/vendor/anstream/src/auto.rs
@@ -0,0 +1,302 @@
+use crate::stream::AsLockedWrite;
+use crate::stream::RawStream;
+use crate::ColorChoice;
+use crate::StripStream;
+#[cfg(all(windows, feature = "wincon"))]
+use crate::WinconStream;
+
+/// [`std::io::Write`] that adapts ANSI escape codes to the underlying `Write`s capabilities
+///
+/// This includes
+/// - Stripping colors for non-terminals
+/// - Respecting env variables like [NO_COLOR](https://no-color.org/) or [CLICOLOR](https://bixense.com/clicolors/)
+/// - *(windows)* Falling back to the wincon API where [ENABLE_VIRTUAL_TERMINAL_PROCESSING](https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences#output-sequences) is unsupported
+///
+/// You can customize auto-detection by calling into
+/// [anstyle_query](https://docs.rs/anstyle-query/latest/anstyle_query/)
+/// to get a [`ColorChoice`] and then calling [`AutoStream::new(stream, choice)`].
+#[derive(Debug)]
+pub struct AutoStream<S: RawStream> {
+ inner: StreamInner<S>,
+}
+
+#[derive(Debug)]
+enum StreamInner<S: RawStream> {
+ PassThrough(S),
+ Strip(StripStream<S>),
+ #[cfg(all(windows, feature = "wincon"))]
+ Wincon(WinconStream<S>),
+}
+
+impl<S> AutoStream<S>
+where
+ S: RawStream,
+{
+ /// Runtime control over styling behavior
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// # #[cfg(feature = "auto")] {
+ /// # use std::io::IsTerminal as _;
+ /// // Like `AutoStream::choice` but without `NO_COLOR`, `CLICOLOR_FORCE`, `CI`
+ /// fn choice(raw: &dyn anstream::stream::RawStream) -> anstream::ColorChoice {
+ /// let choice = anstream::ColorChoice::global();
+ /// if choice == anstream::ColorChoice::Auto {
+ /// if raw.is_terminal() && anstyle_query::term_supports_color() {
+ /// anstream::ColorChoice::Always
+ /// } else {
+ /// anstream::ColorChoice::Never
+ /// }
+ /// } else {
+ /// choice
+ /// }
+ /// }
+ ///
+ /// let stream = std::io::stdout();
+ /// let choice = choice(&stream);
+ /// let auto = anstream::AutoStream::new(stream, choice);
+ /// # }
+ /// ```
+ #[inline]
+ pub fn new(raw: S, choice: ColorChoice) -> Self {
+ match choice {
+ #[cfg(feature = "auto")]
+ ColorChoice::Auto => Self::auto(raw),
+ #[cfg(not(feature = "auto"))]
+ ColorChoice::Auto => Self::never(raw),
+ ColorChoice::AlwaysAnsi => Self::always_ansi(raw),
+ ColorChoice::Always => Self::always(raw),
+ ColorChoice::Never => Self::never(raw),
+ }
+ }
+
+ /// Auto-adapt for the stream's capabilities
+ #[cfg(feature = "auto")]
+ #[inline]
+ pub fn auto(raw: S) -> Self {
+ let choice = Self::choice(&raw);
+ debug_assert_ne!(choice, ColorChoice::Auto);
+ Self::new(raw, choice)
+ }
+
+ /// Report the desired choice for the given stream
+ #[cfg(feature = "auto")]
+ pub fn choice(raw: &S) -> ColorChoice {
+ choice(raw)
+ }
+
+ /// Force ANSI escape codes to be passed through as-is, no matter what the inner `Write`
+ /// supports.
+ #[inline]
+ pub fn always_ansi(raw: S) -> Self {
+ #[cfg(feature = "auto")]
+ {
+ if raw.is_terminal() {
+ let _ = anstyle_query::windows::enable_ansi_colors();
+ }
+ }
+ Self::always_ansi_(raw)
+ }
+
+ #[inline]
+ fn always_ansi_(raw: S) -> Self {
+ let inner = StreamInner::PassThrough(raw);
+ AutoStream { inner }
+ }
+
+ /// Force color, no matter what the inner `Write` supports.
+ #[inline]
+ pub fn always(raw: S) -> Self {
+ if cfg!(windows) {
+ #[cfg(feature = "auto")]
+ let use_wincon = raw.is_terminal()
+ && !anstyle_query::windows::enable_ansi_colors().unwrap_or(true)
+ && !anstyle_query::term_supports_ansi_color();
+ #[cfg(not(feature = "auto"))]
+ let use_wincon = true;
+ if use_wincon {
+ Self::wincon(raw).unwrap_or_else(|raw| Self::always_ansi_(raw))
+ } else {
+ Self::always_ansi_(raw)
+ }
+ } else {
+ Self::always_ansi(raw)
+ }
+ }
+
+ /// Only pass printable data to the inner `Write`.
+ #[inline]
+ pub fn never(raw: S) -> Self {
+ let inner = StreamInner::Strip(StripStream::new(raw));
+ AutoStream { inner }
+ }
+
+ #[inline]
+ fn wincon(raw: S) -> Result<Self, S> {
+ #[cfg(all(windows, feature = "wincon"))]
+ {
+ Ok(Self {
+ inner: StreamInner::Wincon(WinconStream::new(raw)),
+ })
+ }
+ #[cfg(not(all(windows, feature = "wincon")))]
+ {
+ Err(raw)
+ }
+ }
+
+ /// Get the wrapped [`RawStream`]
+ #[inline]
+ pub fn into_inner(self) -> S {
+ match self.inner {
+ StreamInner::PassThrough(w) => w,
+ StreamInner::Strip(w) => w.into_inner(),
+ #[cfg(all(windows, feature = "wincon"))]
+ StreamInner::Wincon(w) => w.into_inner(),
+ }
+ }
+
+ /// Returns `true` if the descriptor/handle refers to a terminal/tty.
+ #[inline]
+ pub fn is_terminal(&self) -> bool {
+ match &self.inner {
+ StreamInner::PassThrough(w) => w.is_terminal(),
+ StreamInner::Strip(w) => w.is_terminal(),
+ #[cfg(all(windows, feature = "wincon"))]
+ StreamInner::Wincon(_) => true, // its only ever a terminal
+ }
+ }
+
+ /// Prefer [`AutoStream::choice`]
+ ///
+ /// This doesn't report what is requested but what is currently active.
+ #[inline]
+ #[cfg(feature = "auto")]
+ pub fn current_choice(&self) -> ColorChoice {
+ match &self.inner {
+ StreamInner::PassThrough(_) => ColorChoice::AlwaysAnsi,
+ StreamInner::Strip(_) => ColorChoice::Never,
+ #[cfg(all(windows, feature = "wincon"))]
+ StreamInner::Wincon(_) => ColorChoice::Always,
+ }
+ }
+}
+
+#[cfg(feature = "auto")]
+fn choice(raw: &dyn RawStream) -> ColorChoice {
+ let choice = ColorChoice::global();
+ match choice {
+ ColorChoice::Auto => {
+ let clicolor = anstyle_query::clicolor();
+ let clicolor_enabled = clicolor.unwrap_or(false);
+ let clicolor_disabled = !clicolor.unwrap_or(true);
+ if anstyle_query::no_color() {
+ ColorChoice::Never
+ } else if anstyle_query::clicolor_force() {
+ ColorChoice::Always
+ } else if clicolor_disabled {
+ ColorChoice::Never
+ } else if raw.is_terminal()
+ && (anstyle_query::term_supports_color()
+ || clicolor_enabled
+ || anstyle_query::is_ci())
+ {
+ ColorChoice::Always
+ } else {
+ ColorChoice::Never
+ }
+ }
+ ColorChoice::AlwaysAnsi | ColorChoice::Always | ColorChoice::Never => choice,
+ }
+}
+
+impl AutoStream<std::io::Stdout> {
+ /// Get exclusive access to the `AutoStream`
+ ///
+ /// Why?
+ /// - Faster performance when writing in a loop
+ /// - Avoid other threads interleaving output with the current thread
+ #[inline]
+ pub fn lock(self) -> AutoStream<std::io::StdoutLock<'static>> {
+ let inner = match self.inner {
+ StreamInner::PassThrough(w) => StreamInner::PassThrough(w.lock()),
+ StreamInner::Strip(w) => StreamInner::Strip(w.lock()),
+ #[cfg(all(windows, feature = "wincon"))]
+ StreamInner::Wincon(w) => StreamInner::Wincon(w.lock()),
+ };
+ AutoStream { inner }
+ }
+}
+
+impl AutoStream<std::io::Stderr> {
+ /// Get exclusive access to the `AutoStream`
+ ///
+ /// Why?
+ /// - Faster performance when writing in a loop
+ /// - Avoid other threads interleaving output with the current thread
+ #[inline]
+ pub fn lock(self) -> AutoStream<std::io::StderrLock<'static>> {
+ let inner = match self.inner {
+ StreamInner::PassThrough(w) => StreamInner::PassThrough(w.lock()),
+ StreamInner::Strip(w) => StreamInner::Strip(w.lock()),
+ #[cfg(all(windows, feature = "wincon"))]
+ StreamInner::Wincon(w) => StreamInner::Wincon(w.lock()),
+ };
+ AutoStream { inner }
+ }
+}
+
+impl<S> std::io::Write for AutoStream<S>
+where
+ S: RawStream + AsLockedWrite,
+{
+ // Must forward all calls to ensure locking happens appropriately
+ #[inline]
+ fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
+ match &mut self.inner {
+ StreamInner::PassThrough(w) => w.as_locked_write().write(buf),
+ StreamInner::Strip(w) => w.write(buf),
+ #[cfg(all(windows, feature = "wincon"))]
+ StreamInner::Wincon(w) => w.write(buf),
+ }
+ }
+ #[inline]
+ fn write_vectored(&mut self, bufs: &[std::io::IoSlice<'_>]) -> std::io::Result<usize> {
+ match &mut self.inner {
+ StreamInner::PassThrough(w) => w.as_locked_write().write_vectored(bufs),
+ StreamInner::Strip(w) => w.write_vectored(bufs),
+ #[cfg(all(windows, feature = "wincon"))]
+ StreamInner::Wincon(w) => w.write_vectored(bufs),
+ }
+ }
+ // is_write_vectored: nightly only
+ #[inline]
+ fn flush(&mut self) -> std::io::Result<()> {
+ match &mut self.inner {
+ StreamInner::PassThrough(w) => w.as_locked_write().flush(),
+ StreamInner::Strip(w) => w.flush(),
+ #[cfg(all(windows, feature = "wincon"))]
+ StreamInner::Wincon(w) => w.flush(),
+ }
+ }
+ #[inline]
+ fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> {
+ match &mut self.inner {
+ StreamInner::PassThrough(w) => w.as_locked_write().write_all(buf),
+ StreamInner::Strip(w) => w.write_all(buf),
+ #[cfg(all(windows, feature = "wincon"))]
+ StreamInner::Wincon(w) => w.write_all(buf),
+ }
+ }
+ // write_all_vectored: nightly only
+ #[inline]
+ fn write_fmt(&mut self, args: std::fmt::Arguments<'_>) -> std::io::Result<()> {
+ match &mut self.inner {
+ StreamInner::PassThrough(w) => w.as_locked_write().write_fmt(args),
+ StreamInner::Strip(w) => w.write_fmt(args),
+ #[cfg(all(windows, feature = "wincon"))]
+ StreamInner::Wincon(w) => w.write_fmt(args),
+ }
+ }
+}
diff --git a/vendor/anstream/src/buffer.rs b/vendor/anstream/src/buffer.rs
new file mode 100644
index 00000000..92e5aafe
--- /dev/null
+++ b/vendor/anstream/src/buffer.rs
@@ -0,0 +1,56 @@
+#![allow(deprecated)]
+
+/// In-memory [`RawStream`][crate::stream::RawStream]
+#[derive(Clone, Default, Debug, PartialEq, Eq)]
+#[deprecated(since = "0.6.2", note = "Use Vec")]
+#[doc(hidden)]
+pub struct Buffer(Vec<u8>);
+
+impl Buffer {
+ #[inline]
+ pub fn new() -> Self {
+ Default::default()
+ }
+
+ #[inline]
+ pub fn with_capacity(capacity: usize) -> Self {
+ Self(Vec::with_capacity(capacity))
+ }
+
+ #[inline]
+ pub fn as_bytes(&self) -> &[u8] {
+ &self.0
+ }
+}
+
+impl AsRef<[u8]> for Buffer {
+ #[inline]
+ fn as_ref(&self) -> &[u8] {
+ self.as_bytes()
+ }
+}
+
+impl std::io::Write for Buffer {
+ #[inline]
+ fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
+ self.0.extend(buf);
+ Ok(buf.len())
+ }
+
+ #[inline]
+ fn flush(&mut self) -> std::io::Result<()> {
+ Ok(())
+ }
+}
+
+#[cfg(all(windows, feature = "wincon"))]
+impl anstyle_wincon::WinconStream for Buffer {
+ fn write_colored(
+ &mut self,
+ fg: Option<anstyle::AnsiColor>,
+ bg: Option<anstyle::AnsiColor>,
+ data: &[u8],
+ ) -> std::io::Result<usize> {
+ self.0.write_colored(fg, bg, data)
+ }
+}
diff --git a/vendor/anstream/src/fmt.rs b/vendor/anstream/src/fmt.rs
new file mode 100644
index 00000000..e673c26d
--- /dev/null
+++ b/vendor/anstream/src/fmt.rs
@@ -0,0 +1,54 @@
+/// A shim which allows a [`std::io::Write`] to be implemented in terms of a [`std::fmt::Write`]
+///
+/// This saves off I/O errors. instead of discarding them
+pub(crate) struct Adapter<W>
+where
+ W: FnMut(&[u8]) -> std::io::Result<()>,
+{
+ writer: W,
+ error: std::io::Result<()>,
+}
+
+impl<W> Adapter<W>
+where
+ W: FnMut(&[u8]) -> std::io::Result<()>,
+{
+ pub(crate) fn new(writer: W) -> Self {
+ Adapter {
+ writer,
+ error: Ok(()),
+ }
+ }
+
+ pub(crate) fn write_fmt(mut self, fmt: std::fmt::Arguments<'_>) -> std::io::Result<()> {
+ match std::fmt::write(&mut self, fmt) {
+ Ok(()) => Ok(()),
+ Err(..) => {
+ // check if the error came from the underlying `Write` or not
+ if self.error.is_err() {
+ self.error
+ } else {
+ Err(std::io::Error::new(
+ std::io::ErrorKind::Other,
+ "formatter error",
+ ))
+ }
+ }
+ }
+ }
+}
+
+impl<W> std::fmt::Write for Adapter<W>
+where
+ W: FnMut(&[u8]) -> std::io::Result<()>,
+{
+ fn write_str(&mut self, s: &str) -> std::fmt::Result {
+ match (self.writer)(s.as_bytes()) {
+ Ok(()) => Ok(()),
+ Err(e) => {
+ self.error = Err(e);
+ Err(std::fmt::Error)
+ }
+ }
+ }
+}
diff --git a/vendor/anstream/src/lib.rs b/vendor/anstream/src/lib.rs
new file mode 100644
index 00000000..9233df7c
--- /dev/null
+++ b/vendor/anstream/src/lib.rs
@@ -0,0 +1,90 @@
+//! **Auto-adapting [`stdout`] / [`stderr`] streams**
+//!
+//! *A portmanteau of "ansi stream"*
+//!
+//! [`AutoStream`] always accepts [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code),
+//! [adapting to the user's terminal's capabilities][AutoStream].
+//!
+//! Benefits
+//! - Allows the caller to not be concerned with the terminal's capabilities
+//! - Semver safe way of passing styled text between crates as ANSI escape codes offer more
+//! compatibility than most crate APIs.
+//!
+//! Available styling crates:
+//! - [anstyle](https://docs.rs/anstyle) for minimal runtime styling, designed to go in public APIs
+//! - [owo-colors](https://docs.rs/owo-colors) for feature-rich runtime styling
+//! - [color-print](https://docs.rs/color-print) for feature-rich compile-time styling
+//!
+//! # Example
+//!
+//! ```
+//! # #[cfg(feature = "auto")] {
+//! use anstream::println;
+//! use owo_colors::OwoColorize as _;
+//!
+//! // Foreground colors
+//! println!("My number is {:#x}!", 10.green());
+//! // Background colors
+//! println!("My number is not {}!", 4.on_red());
+//! # }
+//! ```
+//!
+//! And this will correctly handle piping to a file, etc
+
+#![cfg_attr(docsrs, feature(doc_auto_cfg))]
+#![warn(missing_docs)]
+#![warn(clippy::print_stderr)]
+#![warn(clippy::print_stdout)]
+
+pub mod adapter;
+pub mod stream;
+#[doc(hidden)]
+#[macro_use]
+pub mod _macros;
+
+mod auto;
+mod buffer;
+mod fmt;
+mod strip;
+#[cfg(all(windows, feature = "wincon"))]
+mod wincon;
+
+pub use auto::AutoStream;
+pub use strip::StripStream;
+#[cfg(all(windows, feature = "wincon"))]
+pub use wincon::WinconStream;
+
+#[allow(deprecated)]
+pub use buffer::Buffer;
+
+/// An adaptive wrapper around the global standard output stream of the current process
+pub type Stdout = AutoStream<std::io::Stdout>;
+/// An adaptive wrapper around the global standard error stream of the current process
+pub type Stderr = AutoStream<std::io::Stderr>;
+
+/// Create an ANSI escape code compatible stdout
+///
+/// **Note:** Call [`AutoStream::lock`] in loops to avoid the performance hit of acquiring/releasing
+/// from the implicit locking in each [`std::io::Write`] call
+#[cfg(feature = "auto")]
+pub fn stdout() -> Stdout {
+ let stdout = std::io::stdout();
+ AutoStream::auto(stdout)
+}
+
+/// Create an ANSI escape code compatible stderr
+///
+/// **Note:** Call [`AutoStream::lock`] in loops to avoid the performance hit of acquiring/releasing
+/// from the implicit locking in each [`std::io::Write`] call
+#[cfg(feature = "auto")]
+pub fn stderr() -> Stderr {
+ let stderr = std::io::stderr();
+ AutoStream::auto(stderr)
+}
+
+/// Selection for overriding color output
+pub use colorchoice::ColorChoice;
+
+#[doc = include_str!("../README.md")]
+#[cfg(doctest)]
+pub struct ReadmeDoctests;
diff --git a/vendor/anstream/src/stream.rs b/vendor/anstream/src/stream.rs
new file mode 100644
index 00000000..875455e2
--- /dev/null
+++ b/vendor/anstream/src/stream.rs
@@ -0,0 +1,316 @@
+//! Higher-level traits to describe writeable streams
+
+/// Required functionality for underlying [`std::io::Write`] for adaptation
+#[cfg(not(all(windows, feature = "wincon")))]
+pub trait RawStream: std::io::Write + IsTerminal + private::Sealed {}
+
+/// Required functionality for underlying [`std::io::Write`] for adaptation
+#[cfg(all(windows, feature = "wincon"))]
+pub trait RawStream:
+ std::io::Write + IsTerminal + anstyle_wincon::WinconStream + private::Sealed
+{
+}
+
+impl<T: RawStream + ?Sized> RawStream for &mut T {}
+impl<T: RawStream + ?Sized> RawStream for Box<T> {}
+
+impl RawStream for std::io::Stdout {}
+
+impl RawStream for std::io::StdoutLock<'_> {}
+
+impl RawStream for std::io::Stderr {}
+
+impl RawStream for std::io::StderrLock<'_> {}
+
+impl RawStream for dyn std::io::Write {}
+impl RawStream for dyn std::io::Write + Send {}
+impl RawStream for dyn std::io::Write + Send + Sync {}
+
+impl RawStream for Vec<u8> {}
+
+impl RawStream for std::fs::File {}
+
+#[allow(deprecated)]
+impl RawStream for crate::Buffer {}
+
+/// Trait to determine if a descriptor/handle refers to a terminal/tty.
+pub trait IsTerminal: private::Sealed {
+ /// Returns `true` if the descriptor/handle refers to a terminal/tty.
+ fn is_terminal(&self) -> bool;
+}
+
+impl<T: IsTerminal + ?Sized> IsTerminal for &T {
+ #[inline]
+ fn is_terminal(&self) -> bool {
+ (**self).is_terminal()
+ }
+}
+
+impl<T: IsTerminal + ?Sized> IsTerminal for &mut T {
+ #[inline]
+ fn is_terminal(&self) -> bool {
+ (**self).is_terminal()
+ }
+}
+
+impl<T: IsTerminal + ?Sized> IsTerminal for Box<T> {
+ #[inline]
+ fn is_terminal(&self) -> bool {
+ (**self).is_terminal()
+ }
+}
+
+impl IsTerminal for std::io::Stdout {
+ #[inline]
+ fn is_terminal(&self) -> bool {
+ is_terminal_polyfill::IsTerminal::is_terminal(self)
+ }
+}
+
+impl IsTerminal for std::io::StdoutLock<'_> {
+ #[inline]
+ fn is_terminal(&self) -> bool {
+ is_terminal_polyfill::IsTerminal::is_terminal(self)
+ }
+}
+
+impl IsTerminal for std::io::Stderr {
+ #[inline]
+ fn is_terminal(&self) -> bool {
+ is_terminal_polyfill::IsTerminal::is_terminal(self)
+ }
+}
+
+impl IsTerminal for std::io::StderrLock<'_> {
+ #[inline]
+ fn is_terminal(&self) -> bool {
+ is_terminal_polyfill::IsTerminal::is_terminal(self)
+ }
+}
+
+impl IsTerminal for dyn std::io::Write {
+ #[inline]
+ fn is_terminal(&self) -> bool {
+ false
+ }
+}
+
+impl IsTerminal for dyn std::io::Write + Send {
+ #[inline]
+ fn is_terminal(&self) -> bool {
+ false
+ }
+}
+
+impl IsTerminal for dyn std::io::Write + Send + Sync {
+ #[inline]
+ fn is_terminal(&self) -> bool {
+ false
+ }
+}
+
+impl IsTerminal for Vec<u8> {
+ #[inline]
+ fn is_terminal(&self) -> bool {
+ false
+ }
+}
+
+impl IsTerminal for std::fs::File {
+ #[inline]
+ fn is_terminal(&self) -> bool {
+ is_terminal_polyfill::IsTerminal::is_terminal(self)
+ }
+}
+
+#[allow(deprecated)]
+impl IsTerminal for crate::Buffer {
+ #[inline]
+ fn is_terminal(&self) -> bool {
+ false
+ }
+}
+
+/// Lock a stream
+pub trait AsLockedWrite: private::Sealed {
+ /// Locked writer type
+ type Write<'w>: RawStream + 'w
+ where
+ Self: 'w;
+
+ /// Lock a stream
+ fn as_locked_write(&mut self) -> Self::Write<'_>;
+}
+
+impl<T: AsLockedWrite + ?Sized> AsLockedWrite for &mut T {
+ type Write<'w>
+ = T::Write<'w>
+ where
+ Self: 'w;
+
+ #[inline]
+ fn as_locked_write(&mut self) -> Self::Write<'_> {
+ (**self).as_locked_write()
+ }
+}
+
+impl<T: AsLockedWrite + ?Sized> AsLockedWrite for Box<T> {
+ type Write<'w>
+ = T::Write<'w>
+ where
+ Self: 'w;
+
+ #[inline]
+ fn as_locked_write(&mut self) -> Self::Write<'_> {
+ (**self).as_locked_write()
+ }
+}
+
+impl AsLockedWrite for std::io::Stdout {
+ type Write<'w> = std::io::StdoutLock<'w>;
+
+ #[inline]
+ fn as_locked_write(&mut self) -> Self::Write<'_> {
+ self.lock()
+ }
+}
+
+impl AsLockedWrite for std::io::StdoutLock<'static> {
+ type Write<'w> = &'w mut Self;
+
+ #[inline]
+ fn as_locked_write(&mut self) -> Self::Write<'_> {
+ self
+ }
+}
+
+impl AsLockedWrite for std::io::Stderr {
+ type Write<'w> = std::io::StderrLock<'w>;
+
+ #[inline]
+ fn as_locked_write(&mut self) -> Self::Write<'_> {
+ self.lock()
+ }
+}
+
+impl AsLockedWrite for std::io::StderrLock<'static> {
+ type Write<'w> = &'w mut Self;
+
+ #[inline]
+ fn as_locked_write(&mut self) -> Self::Write<'_> {
+ self
+ }
+}
+
+impl AsLockedWrite for dyn std::io::Write {
+ type Write<'w> = &'w mut Self;
+
+ #[inline]
+ fn as_locked_write(&mut self) -> Self::Write<'_> {
+ self
+ }
+}
+
+impl AsLockedWrite for dyn std::io::Write + Send {
+ type Write<'w> = &'w mut Self;
+
+ #[inline]
+ fn as_locked_write(&mut self) -> Self::Write<'_> {
+ self
+ }
+}
+
+impl AsLockedWrite for dyn std::io::Write + Send + Sync {
+ type Write<'w> = &'w mut Self;
+
+ #[inline]
+ fn as_locked_write(&mut self) -> Self::Write<'_> {
+ self
+ }
+}
+
+impl AsLockedWrite for Vec<u8> {
+ type Write<'w> = &'w mut Self;
+
+ #[inline]
+ fn as_locked_write(&mut self) -> Self::Write<'_> {
+ self
+ }
+}
+
+impl AsLockedWrite for std::fs::File {
+ type Write<'w> = &'w mut Self;
+
+ #[inline]
+ fn as_locked_write(&mut self) -> Self::Write<'_> {
+ self
+ }
+}
+
+#[allow(deprecated)]
+impl AsLockedWrite for crate::Buffer {
+ type Write<'w> = &'w mut Self;
+
+ #[inline]
+ fn as_locked_write(&mut self) -> Self::Write<'_> {
+ self
+ }
+}
+
+mod private {
+ #[allow(unnameable_types)]
+ pub trait Sealed {}
+
+ impl<T: Sealed + ?Sized> Sealed for &T {}
+ impl<T: Sealed + ?Sized> Sealed for &mut T {}
+ impl<T: Sealed + ?Sized> Sealed for Box<T> {}
+
+ impl Sealed for std::io::Stdout {}
+
+ impl Sealed for std::io::StdoutLock<'_> {}
+
+ impl Sealed for std::io::Stderr {}
+
+ impl Sealed for std::io::StderrLock<'_> {}
+
+ impl Sealed for dyn std::io::Write {}
+ impl Sealed for dyn std::io::Write + Send {}
+ impl Sealed for dyn std::io::Write + Send + Sync {}
+
+ impl Sealed for Vec<u8> {}
+
+ impl Sealed for std::fs::File {}
+
+ #[allow(deprecated)]
+ impl Sealed for crate::Buffer {}
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ fn assert_raw_stream<T: RawStream>()
+ where
+ crate::AutoStream<T>: std::io::Write,
+ {
+ }
+
+ #[test]
+ fn test() {
+ assert_raw_stream::<Box<dyn std::io::Write>>();
+ assert_raw_stream::<Box<dyn std::io::Write + 'static>>();
+ assert_raw_stream::<Box<dyn std::io::Write + Send>>();
+ assert_raw_stream::<Box<dyn std::io::Write + Send + Sync>>();
+
+ assert_raw_stream::<&mut (dyn std::io::Write)>();
+ assert_raw_stream::<&mut (dyn std::io::Write + 'static)>();
+ assert_raw_stream::<&mut (dyn std::io::Write + Send)>();
+ assert_raw_stream::<&mut (dyn std::io::Write + Send + Sync)>();
+
+ assert_raw_stream::<Vec<u8>>();
+ assert_raw_stream::<&mut Vec<u8>>();
+
+ assert_raw_stream::<std::fs::File>();
+ assert_raw_stream::<&mut std::fs::File>();
+ }
+}
diff --git a/vendor/anstream/src/strip.rs b/vendor/anstream/src/strip.rs
new file mode 100644
index 00000000..9f0d28bd
--- /dev/null
+++ b/vendor/anstream/src/strip.rs
@@ -0,0 +1,227 @@
+use crate::adapter::StripBytes;
+use crate::stream::AsLockedWrite;
+use crate::stream::IsTerminal;
+
+/// Only pass printable data to the inner `Write`
+#[derive(Debug)]
+pub struct StripStream<S>
+where
+ S: std::io::Write,
+{
+ raw: S,
+ state: StripBytes,
+}
+
+impl<S> StripStream<S>
+where
+ S: std::io::Write,
+{
+ /// Only pass printable data to the inner `Write`
+ #[inline]
+ pub fn new(raw: S) -> Self {
+ Self {
+ raw,
+ state: Default::default(),
+ }
+ }
+
+ /// Get the wrapped [`std::io::Write`]
+ #[inline]
+ pub fn into_inner(self) -> S {
+ self.raw
+ }
+}
+
+impl<S> StripStream<S>
+where
+ S: std::io::Write,
+ S: IsTerminal,
+{
+ /// Returns `true` if the descriptor/handle refers to a terminal/tty.
+ #[inline]
+ pub fn is_terminal(&self) -> bool {
+ self.raw.is_terminal()
+ }
+}
+
+impl StripStream<std::io::Stdout> {
+ /// Get exclusive access to the `StripStream`
+ ///
+ /// Why?
+ /// - Faster performance when writing in a loop
+ /// - Avoid other threads interleaving output with the current thread
+ #[inline]
+ pub fn lock(self) -> StripStream<std::io::StdoutLock<'static>> {
+ StripStream {
+ raw: self.raw.lock(),
+ state: self.state,
+ }
+ }
+}
+
+impl StripStream<std::io::Stderr> {
+ /// Get exclusive access to the `StripStream`
+ ///
+ /// Why?
+ /// - Faster performance when writing in a loop
+ /// - Avoid other threads interleaving output with the current thread
+ #[inline]
+ pub fn lock(self) -> StripStream<std::io::StderrLock<'static>> {
+ StripStream {
+ raw: self.raw.lock(),
+ state: self.state,
+ }
+ }
+}
+
+impl<S> std::io::Write for StripStream<S>
+where
+ S: std::io::Write,
+ S: AsLockedWrite,
+{
+ // Must forward all calls to ensure locking happens appropriately
+ #[inline]
+ fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
+ write(&mut self.raw.as_locked_write(), &mut self.state, buf)
+ }
+ #[inline]
+ fn write_vectored(&mut self, bufs: &[std::io::IoSlice<'_>]) -> std::io::Result<usize> {
+ let buf = bufs
+ .iter()
+ .find(|b| !b.is_empty())
+ .map(|b| &**b)
+ .unwrap_or(&[][..]);
+ self.write(buf)
+ }
+ // is_write_vectored: nightly only
+ #[inline]
+ fn flush(&mut self) -> std::io::Result<()> {
+ self.raw.as_locked_write().flush()
+ }
+ #[inline]
+ fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> {
+ write_all(&mut self.raw.as_locked_write(), &mut self.state, buf)
+ }
+ // write_all_vectored: nightly only
+ #[inline]
+ fn write_fmt(&mut self, args: std::fmt::Arguments<'_>) -> std::io::Result<()> {
+ write_fmt(&mut self.raw.as_locked_write(), &mut self.state, args)
+ }
+}
+
+fn write(
+ raw: &mut dyn std::io::Write,
+ state: &mut StripBytes,
+ buf: &[u8],
+) -> std::io::Result<usize> {
+ let initial_state = state.clone();
+
+ for printable in state.strip_next(buf) {
+ let possible = printable.len();
+ let written = raw.write(printable)?;
+ if possible != written {
+ let divergence = &printable[written..];
+ let offset = offset_to(buf, divergence);
+ let consumed = &buf[offset..];
+ *state = initial_state;
+ state.strip_next(consumed).last();
+ return Ok(offset);
+ }
+ }
+ Ok(buf.len())
+}
+
+fn write_all(
+ raw: &mut dyn std::io::Write,
+ state: &mut StripBytes,
+ buf: &[u8],
+) -> std::io::Result<()> {
+ for printable in state.strip_next(buf) {
+ raw.write_all(printable)?;
+ }
+ Ok(())
+}
+
+fn write_fmt(
+ raw: &mut dyn std::io::Write,
+ state: &mut StripBytes,
+ args: std::fmt::Arguments<'_>,
+) -> std::io::Result<()> {
+ let write_all = |buf: &[u8]| write_all(raw, state, buf);
+ crate::fmt::Adapter::new(write_all).write_fmt(args)
+}
+
+#[inline]
+fn offset_to(total: &[u8], subslice: &[u8]) -> usize {
+ let total = total.as_ptr();
+ let subslice = subslice.as_ptr();
+
+ debug_assert!(
+ total <= subslice,
+ "`Offset::offset_to` only accepts slices of `self`"
+ );
+ subslice as usize - total as usize
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+ use proptest::prelude::*;
+ use std::io::Write as _;
+
+ proptest! {
+ #[test]
+ #[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253
+ fn write_all_no_escapes(s in "\\PC*") {
+ let buffer = Vec::new();
+ let mut stream = StripStream::new(buffer);
+ stream.write_all(s.as_bytes()).unwrap();
+ let buffer = stream.into_inner();
+ let actual = std::str::from_utf8(buffer.as_ref()).unwrap();
+ assert_eq!(s, actual);
+ }
+
+ #[test]
+ #[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253
+ fn write_byte_no_escapes(s in "\\PC*") {
+ let buffer = Vec::new();
+ let mut stream = StripStream::new(buffer);
+ for byte in s.as_bytes() {
+ stream.write_all(&[*byte]).unwrap();
+ }
+ let buffer = stream.into_inner();
+ let actual = std::str::from_utf8(buffer.as_ref()).unwrap();
+ assert_eq!(s, actual);
+ }
+
+ #[test]
+ #[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253
+ fn write_all_random(s in any::<Vec<u8>>()) {
+ let buffer = Vec::new();
+ let mut stream = StripStream::new(buffer);
+ stream.write_all(s.as_slice()).unwrap();
+ let buffer = stream.into_inner();
+ if let Ok(actual) = std::str::from_utf8(buffer.as_ref()) {
+ for char in actual.chars() {
+ assert!(!char.is_ascii() || !char.is_control() || char.is_ascii_whitespace(), "{:?} -> {:?}: {:?}", String::from_utf8_lossy(&s), actual, char);
+ }
+ }
+ }
+
+ #[test]
+ #[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253
+ fn write_byte_random(s in any::<Vec<u8>>()) {
+ let buffer = Vec::new();
+ let mut stream = StripStream::new(buffer);
+ for byte in s.as_slice() {
+ stream.write_all(&[*byte]).unwrap();
+ }
+ let buffer = stream.into_inner();
+ if let Ok(actual) = std::str::from_utf8(buffer.as_ref()) {
+ for char in actual.chars() {
+ assert!(!char.is_ascii() || !char.is_control() || char.is_ascii_whitespace(), "{:?} -> {:?}: {:?}", String::from_utf8_lossy(&s), actual, char);
+ }
+ }
+ }
+ }
+}
diff --git a/vendor/anstream/src/wincon.rs b/vendor/anstream/src/wincon.rs
new file mode 100644
index 00000000..570511dd
--- /dev/null
+++ b/vendor/anstream/src/wincon.rs
@@ -0,0 +1,226 @@
+use crate::adapter::WinconBytes;
+use crate::stream::AsLockedWrite;
+use crate::stream::IsTerminal;
+
+/// Only pass printable data to the inner `Write`
+#[cfg(feature = "wincon")] // here mostly for documentation purposes
+#[derive(Debug)]
+pub struct WinconStream<S>
+where
+ S: anstyle_wincon::WinconStream,
+{
+ raw: S,
+ // `WinconBytes` is especially large compared to other variants of `AutoStream`, so boxing it
+ // here so `AutoStream` doesn't have to discard one allocation and create another one when
+ // calling `AutoStream::lock`
+ state: Box<WinconBytes>,
+}
+
+impl<S> WinconStream<S>
+where
+ S: anstyle_wincon::WinconStream,
+{
+ /// Only pass printable data to the inner `Write`
+ #[inline]
+ pub fn new(raw: S) -> Self {
+ Self {
+ raw,
+ state: Default::default(),
+ }
+ }
+
+ /// Get the wrapped [`anstyle_wincon::WinconStream`]
+ #[inline]
+ pub fn into_inner(self) -> S {
+ self.raw
+ }
+}
+
+impl<S> WinconStream<S>
+where
+ S: anstyle_wincon::WinconStream,
+ S: IsTerminal,
+{
+ /// Returns `true` if the descriptor/handle refers to a terminal/tty.
+ #[inline]
+ pub fn is_terminal(&self) -> bool {
+ self.raw.is_terminal()
+ }
+}
+
+impl WinconStream<std::io::Stdout> {
+ /// Get exclusive access to the `WinconStream`
+ ///
+ /// Why?
+ /// - Faster performance when writing in a loop
+ /// - Avoid other threads interleaving output with the current thread
+ #[inline]
+ pub fn lock(self) -> WinconStream<std::io::StdoutLock<'static>> {
+ WinconStream {
+ raw: self.raw.lock(),
+ state: self.state,
+ }
+ }
+}
+
+impl WinconStream<std::io::Stderr> {
+ /// Get exclusive access to the `WinconStream`
+ ///
+ /// Why?
+ /// - Faster performance when writing in a loop
+ /// - Avoid other threads interleaving output with the current thread
+ #[inline]
+ pub fn lock(self) -> WinconStream<std::io::StderrLock<'static>> {
+ WinconStream {
+ raw: self.raw.lock(),
+ state: self.state,
+ }
+ }
+}
+
+impl<S> std::io::Write for WinconStream<S>
+where
+ S: anstyle_wincon::WinconStream,
+ S: AsLockedWrite,
+{
+ // Must forward all calls to ensure locking happens appropriately
+ #[inline]
+ fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
+ write(&mut self.raw.as_locked_write(), &mut self.state, buf)
+ }
+ #[inline]
+ fn write_vectored(&mut self, bufs: &[std::io::IoSlice<'_>]) -> std::io::Result<usize> {
+ let buf = bufs
+ .iter()
+ .find(|b| !b.is_empty())
+ .map(|b| &**b)
+ .unwrap_or(&[][..]);
+ self.write(buf)
+ }
+ // is_write_vectored: nightly only
+ #[inline]
+ fn flush(&mut self) -> std::io::Result<()> {
+ self.raw.as_locked_write().flush()
+ }
+ #[inline]
+ fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> {
+ write_all(&mut self.raw.as_locked_write(), &mut self.state, buf)
+ }
+ // write_all_vectored: nightly only
+ #[inline]
+ fn write_fmt(&mut self, args: std::fmt::Arguments<'_>) -> std::io::Result<()> {
+ write_fmt(&mut self.raw.as_locked_write(), &mut self.state, args)
+ }
+}
+
+fn write(
+ raw: &mut dyn anstyle_wincon::WinconStream,
+ state: &mut WinconBytes,
+ buf: &[u8],
+) -> std::io::Result<usize> {
+ for (style, printable) in state.extract_next(buf) {
+ let fg = style.get_fg_color().and_then(cap_wincon_color);
+ let bg = style.get_bg_color().and_then(cap_wincon_color);
+ let written = raw.write_colored(fg, bg, printable.as_bytes())?;
+ let possible = printable.len();
+ if possible != written {
+ // HACK: Unsupported atm
+ break;
+ }
+ }
+ Ok(buf.len())
+}
+
+fn write_all(
+ raw: &mut dyn anstyle_wincon::WinconStream,
+ state: &mut WinconBytes,
+ buf: &[u8],
+) -> std::io::Result<()> {
+ for (style, printable) in state.extract_next(buf) {
+ let mut buf = printable.as_bytes();
+ let fg = style.get_fg_color().and_then(cap_wincon_color);
+ let bg = style.get_bg_color().and_then(cap_wincon_color);
+ while !buf.is_empty() {
+ match raw.write_colored(fg, bg, buf) {
+ Ok(0) => {
+ return Err(std::io::Error::new(
+ std::io::ErrorKind::WriteZero,
+ "failed to write whole buffer",
+ ));
+ }
+ Ok(n) => buf = &buf[n..],
+ Err(ref e) if e.kind() == std::io::ErrorKind::Interrupted => {}
+ Err(e) => return Err(e),
+ }
+ }
+ }
+ Ok(())
+}
+
+fn write_fmt(
+ raw: &mut dyn anstyle_wincon::WinconStream,
+ state: &mut WinconBytes,
+ args: std::fmt::Arguments<'_>,
+) -> std::io::Result<()> {
+ let write_all = |buf: &[u8]| write_all(raw, state, buf);
+ crate::fmt::Adapter::new(write_all).write_fmt(args)
+}
+
+fn cap_wincon_color(color: anstyle::Color) -> Option<anstyle::AnsiColor> {
+ match color {
+ anstyle::Color::Ansi(c) => Some(c),
+ anstyle::Color::Ansi256(c) => c.into_ansi(),
+ anstyle::Color::Rgb(_) => None,
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+ use proptest::prelude::*;
+ use std::io::Write as _;
+
+ proptest! {
+ #[test]
+ #[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253
+ fn write_all_no_escapes(s in "\\PC*") {
+ let buffer = Vec::new();
+ let mut stream = WinconStream::new(buffer);
+ stream.write_all(s.as_bytes()).unwrap();
+ let buffer = stream.into_inner();
+ let actual = std::str::from_utf8(buffer.as_ref()).unwrap();
+ assert_eq!(s, actual);
+ }
+
+ #[test]
+ #[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253
+ fn write_byte_no_escapes(s in "\\PC*") {
+ let buffer = Vec::new();
+ let mut stream = WinconStream::new(buffer);
+ for byte in s.as_bytes() {
+ stream.write_all(&[*byte]).unwrap();
+ }
+ let buffer = stream.into_inner();
+ let actual = std::str::from_utf8(buffer.as_ref()).unwrap();
+ assert_eq!(s, actual);
+ }
+
+ #[test]
+ #[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253
+ fn write_all_random(s in any::<Vec<u8>>()) {
+ let buffer = Vec::new();
+ let mut stream = WinconStream::new(buffer);
+ stream.write_all(s.as_slice()).unwrap();
+ }
+
+ #[test]
+ #[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253
+ fn write_byte_random(s in any::<Vec<u8>>()) {
+ let buffer = Vec::new();
+ let mut stream = WinconStream::new(buffer);
+ for byte in s.as_slice() {
+ stream.write_all(&[*byte]).unwrap();
+ }
+ }
+ }
+}