Initial vendor packages
Signed-off-by: Valentin Popov <valentin@popov.link>
This commit is contained in:
parent
5ecd8cf2cb
commit
1b6a04ca55
5
.cargo/config.toml
Normal file
5
.cargo/config.toml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
[source.crates-io]
|
||||||
|
replace-with = "vendored-sources"
|
||||||
|
|
||||||
|
[source.vendored-sources]
|
||||||
|
directory = "vendor"
|
1
vendor/addr2line/.cargo-checksum.json
vendored
Normal file
1
vendor/addr2line/.cargo-checksum.json
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"files":{"CHANGELOG.md":"ef9fa958318e442f1da7d204494cefec75c144aa6d5d5c93b0a5d6fcdf4ef6c6","Cargo.lock":"20b23c454fc3127f08a1bcd2864bbf029793759e6411fba24d44d8f4b7831ad0","Cargo.toml":"d0f15fde73d42bdf00e93f960dff908447225bede9364cb1659e44740a536c04","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"e99d88d232bf57d70f0fb87f6b496d44b6653f99f8a63d250a54c61ea4bcde40","README.md":"76d28502bd2e83f6a9e3576bd45e9a7fe5308448c4b5384b0d249515b5f67a5c","bench.plot.r":"6a5d7a4d36ed6b3d9919be703a479bef47698bf947818b483ff03951df2d4e01","benchmark.sh":"b35f89b1ca2c1dc0476cdd07f0284b72d41920d1c7b6054072f50ffba296d78d","coverage.sh":"4677e81922d08a82e83068a911717a247c66af12e559f37b78b6be3337ac9f07","examples/addr2line.rs":"3c5eb5a6726634df6cf53e4d67ee9f90c9ac09838303947f45c3bea1e84548b5","rustfmt.toml":"01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b","src/builtin_split_dwarf_loader.rs":"dc6979de81b35f82e97275e6be27ec61f3c4225ea10574a9e031813e00185174","src/function.rs":"68f047e0c78afe18ad165db255c8254ee74c35cd6df0cc07e400252981f661ed","src/lazy.rs":"0bf23f7098f1902f181e43c2ffa82a3f86df2c0dbcb9bc0ebce6a0168dd8b060","src/lib.rs":"9d6531f71fd138d31cc7596db9ab234198d0895a21ea9cb116434c19ec78b660","tests/correctness.rs":"4081f8019535305e3aa254c6a4e1436272dd873f9717c687ca0e66ea8d5871ed","tests/output_equivalence.rs":"b2cd7c59fa55808a2e66e9fe7f160d846867e3ecefe22c22a818f822c3c41f23","tests/parse.rs":"c2f7362e4679c1b4803b12ec6e8dca6da96aed7273fd210a857524a4182c30e7"},"package":"8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"}
|
336
vendor/addr2line/CHANGELOG.md
vendored
Normal file
336
vendor/addr2line/CHANGELOG.md
vendored
Normal file
@ -0,0 +1,336 @@
|
|||||||
|
# `addr2line` Change Log
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## 0.21.0 (2023/08/12)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
* Updated `gimli`, `object`, and `fallible-iterator` dependencies.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* The minimum supported rust version is 1.65.0.
|
||||||
|
|
||||||
|
* Store boxed slices instead of `Vec` objects in `Context`.
|
||||||
|
[#278](https://github.com/gimli-rs/addr2line/pull/278)
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## 0.20.0 (2023/04/15)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
* The minimum supported rust version is 1.58.0.
|
||||||
|
|
||||||
|
* Changed `Context::find_frames` to return `LookupResult`.
|
||||||
|
Use `LookupResult::skip_all_loads` to obtain the result without loading split DWARF.
|
||||||
|
[#260](https://github.com/gimli-rs/addr2line/pull/260)
|
||||||
|
|
||||||
|
* Replaced `Context::find_dwarf_unit` with `Context::find_dwarf_and_unit`.
|
||||||
|
[#260](https://github.com/gimli-rs/addr2line/pull/260)
|
||||||
|
|
||||||
|
* Updated `object` dependency.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* Fix handling of file index 0 for DWARF 5.
|
||||||
|
[#264](https://github.com/gimli-rs/addr2line/pull/264)
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* Added types and methods to support loading split DWARF:
|
||||||
|
`LookupResult`, `SplitDwarfLoad`, `SplitDwarfLoader`, `Context::preload_units`.
|
||||||
|
[#260](https://github.com/gimli-rs/addr2line/pull/260)
|
||||||
|
[#262](https://github.com/gimli-rs/addr2line/pull/262)
|
||||||
|
[#263](https://github.com/gimli-rs/addr2line/pull/263)
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## 0.19.0 (2022/11/24)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
* Updated `gimli` and `object` dependencies.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## 0.18.0 (2022/07/16)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
* Updated `object` dependency.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* Fixed handling of relative path for `DW_AT_comp_dir`.
|
||||||
|
[#239](https://github.com/gimli-rs/addr2line/pull/239)
|
||||||
|
|
||||||
|
* Fixed handling of `DW_FORM_addrx` for DWARF 5 support.
|
||||||
|
[#243](https://github.com/gimli-rs/addr2line/pull/243)
|
||||||
|
|
||||||
|
* Fixed handling of units that are missing range information.
|
||||||
|
[#249](https://github.com/gimli-rs/addr2line/pull/249)
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## 0.17.0 (2021/10/24)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
* Updated `gimli` and `object` dependencies.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* Use `skip_attributes` to improve performance.
|
||||||
|
[#236](https://github.com/gimli-rs/addr2line/pull/236)
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## 0.16.0 (2021/07/26)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
* Updated `gimli` and `object` dependencies.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## 0.15.2 (2021/06/04)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Allow `Context` to be `Send`.
|
||||||
|
[#219](https://github.com/gimli-rs/addr2line/pull/219)
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## 0.15.1 (2021/05/02)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Don't ignore aranges with address 0.
|
||||||
|
[#217](https://github.com/gimli-rs/addr2line/pull/217)
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## 0.15.0 (2021/05/02)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
* Updated `gimli` and `object` dependencies.
|
||||||
|
[#215](https://github.com/gimli-rs/addr2line/pull/215)
|
||||||
|
|
||||||
|
* Added `debug_aranges` parameter to `Context::from_sections`.
|
||||||
|
[#200](https://github.com/gimli-rs/addr2line/pull/200)
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* Added `.debug_aranges` support.
|
||||||
|
[#200](https://github.com/gimli-rs/addr2line/pull/200)
|
||||||
|
|
||||||
|
* Added supplementary object file support.
|
||||||
|
[#208](https://github.com/gimli-rs/addr2line/pull/208)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Fixed handling of Windows paths in locations.
|
||||||
|
[#209](https://github.com/gimli-rs/addr2line/pull/209)
|
||||||
|
|
||||||
|
* examples/addr2line: Flush stdout after each response.
|
||||||
|
[#210](https://github.com/gimli-rs/addr2line/pull/210)
|
||||||
|
|
||||||
|
* examples/addr2line: Avoid copying every section.
|
||||||
|
[#213](https://github.com/gimli-rs/addr2line/pull/213)
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## 0.14.1 (2020/12/31)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Fix location lookup for skeleton units.
|
||||||
|
[#201](https://github.com/gimli-rs/addr2line/pull/201)
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* Added `Context::find_location_range`.
|
||||||
|
[#196](https://github.com/gimli-rs/addr2line/pull/196)
|
||||||
|
[#199](https://github.com/gimli-rs/addr2line/pull/199)
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## 0.14.0 (2020/10/27)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
* Updated `gimli` and `object` dependencies.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Handle units that only have line information.
|
||||||
|
[#188](https://github.com/gimli-rs/addr2line/pull/188)
|
||||||
|
|
||||||
|
* Handle DWARF units with version <= 4 and no `DW_AT_name`.
|
||||||
|
[#191](https://github.com/gimli-rs/addr2line/pull/191)
|
||||||
|
|
||||||
|
* Fix handling of `DW_FORM_ref_addr`.
|
||||||
|
[#193](https://github.com/gimli-rs/addr2line/pull/193)
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## 0.13.0 (2020/07/07)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
* Updated `gimli` and `object` dependencies.
|
||||||
|
|
||||||
|
* Added `rustc-dep-of-std` feature.
|
||||||
|
[#166](https://github.com/gimli-rs/addr2line/pull/166)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* Improve performance by parsing function contents lazily.
|
||||||
|
[#178](https://github.com/gimli-rs/addr2line/pull/178)
|
||||||
|
|
||||||
|
* Don't skip `.debug_info` and `.debug_line` entries with a zero address.
|
||||||
|
[#182](https://github.com/gimli-rs/addr2line/pull/182)
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## 0.12.2 (2020/06/21)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Avoid linear search for `DW_FORM_ref_addr`.
|
||||||
|
[#175](https://github.com/gimli-rs/addr2line/pull/175)
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## 0.12.1 (2020/05/19)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Handle units with overlapping address ranges.
|
||||||
|
[#163](https://github.com/gimli-rs/addr2line/pull/163)
|
||||||
|
|
||||||
|
* Don't assert for functions with overlapping address ranges.
|
||||||
|
[#168](https://github.com/gimli-rs/addr2line/pull/168)
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## 0.12.0 (2020/05/12)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
* Updated `gimli` and `object` dependencies.
|
||||||
|
|
||||||
|
* Added more optional features: `smallvec` and `fallible-iterator`.
|
||||||
|
[#160](https://github.com/gimli-rs/addr2line/pull/160)
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* Added `Context::dwarf` and `Context::find_dwarf_unit`.
|
||||||
|
[#159](https://github.com/gimli-rs/addr2line/pull/159)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* Removed `lazycell` dependency.
|
||||||
|
[#160](https://github.com/gimli-rs/addr2line/pull/160)
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## 0.11.0 (2020/01/11)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
* Updated `gimli` and `object` dependencies.
|
||||||
|
|
||||||
|
* [#130](https://github.com/gimli-rs/addr2line/pull/130)
|
||||||
|
Changed `Location::file` from `Option<String>` to `Option<&str>`.
|
||||||
|
This required adding lifetime parameters to `Location` and other structs that
|
||||||
|
contain it.
|
||||||
|
|
||||||
|
* [#152](https://github.com/gimli-rs/addr2line/pull/152)
|
||||||
|
Changed `Location::line` and `Location::column` from `Option<u64>`to `Option<u32>`.
|
||||||
|
|
||||||
|
* [#156](https://github.com/gimli-rs/addr2line/pull/156)
|
||||||
|
Deleted `alloc` feature, and fixed `no-std` builds with stable rust.
|
||||||
|
Removed default `Reader` parameter for `Context`, and added `ObjectContext` instead.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* [#134](https://github.com/gimli-rs/addr2line/pull/134)
|
||||||
|
Added `Context::from_dwarf`.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* [#133](https://github.com/gimli-rs/addr2line/pull/133)
|
||||||
|
Fixed handling of units that can't be parsed.
|
||||||
|
|
||||||
|
* [#155](https://github.com/gimli-rs/addr2line/pull/155)
|
||||||
|
Fixed `addr2line` output to match binutils.
|
||||||
|
|
||||||
|
* [#130](https://github.com/gimli-rs/addr2line/pull/130)
|
||||||
|
Improved `.debug_line` parsing performance.
|
||||||
|
|
||||||
|
* [#148](https://github.com/gimli-rs/addr2line/pull/148)
|
||||||
|
[#150](https://github.com/gimli-rs/addr2line/pull/150)
|
||||||
|
[#151](https://github.com/gimli-rs/addr2line/pull/151)
|
||||||
|
[#152](https://github.com/gimli-rs/addr2line/pull/152)
|
||||||
|
Improved `.debug_info` parsing performance.
|
||||||
|
|
||||||
|
* [#137](https://github.com/gimli-rs/addr2line/pull/137)
|
||||||
|
[#138](https://github.com/gimli-rs/addr2line/pull/138)
|
||||||
|
[#139](https://github.com/gimli-rs/addr2line/pull/139)
|
||||||
|
[#140](https://github.com/gimli-rs/addr2line/pull/140)
|
||||||
|
[#146](https://github.com/gimli-rs/addr2line/pull/146)
|
||||||
|
Improved benchmarks.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## 0.10.0 (2019/07/07)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
* [#127](https://github.com/gimli-rs/addr2line/pull/127)
|
||||||
|
Update `gimli`.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## 0.9.0 (2019/05/02)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
* [#121](https://github.com/gimli-rs/addr2line/pull/121)
|
||||||
|
Update `gimli`, `object`, and `fallible-iterator` dependencies.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* [#121](https://github.com/gimli-rs/addr2line/pull/121)
|
||||||
|
Reexport `gimli`, `object`, and `fallible-iterator`.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## 0.8.0 (2019/02/06)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
* [#107](https://github.com/gimli-rs/addr2line/pull/107)
|
||||||
|
Update `object` dependency to 0.11. This is part of the public API.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* [#101](https://github.com/gimli-rs/addr2line/pull/101)
|
||||||
|
Add `object` feature (enabled by default). Disable this feature to remove
|
||||||
|
the `object` dependency and `Context::new` API.
|
||||||
|
|
||||||
|
* [#102](https://github.com/gimli-rs/addr2line/pull/102)
|
||||||
|
Add `std` (enabled by default) and `alloc` features.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* [#108](https://github.com/gimli-rs/addr2line/issues/108)
|
||||||
|
`demangle` no longer outputs the hash for rust symbols.
|
||||||
|
|
||||||
|
* [#109](https://github.com/gimli-rs/addr2line/issues/109)
|
||||||
|
Set default `R` for `Context<R>`.
|
704
vendor/addr2line/Cargo.lock
generated
vendored
Normal file
704
vendor/addr2line/Cargo.lock
generated
vendored
Normal file
@ -0,0 +1,704 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "addr2line"
|
||||||
|
version = "0.19.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
|
||||||
|
dependencies = [
|
||||||
|
"gimli 0.27.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "addr2line"
|
||||||
|
version = "0.21.0"
|
||||||
|
dependencies = [
|
||||||
|
"backtrace",
|
||||||
|
"clap",
|
||||||
|
"compiler_builtins",
|
||||||
|
"cpp_demangle",
|
||||||
|
"fallible-iterator",
|
||||||
|
"findshlibs",
|
||||||
|
"gimli 0.28.0",
|
||||||
|
"libtest-mimic",
|
||||||
|
"memmap2",
|
||||||
|
"object 0.32.0",
|
||||||
|
"rustc-demangle",
|
||||||
|
"rustc-std-workspace-alloc",
|
||||||
|
"rustc-std-workspace-core",
|
||||||
|
"smallvec",
|
||||||
|
"typed-arena",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "adler"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstream"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"anstyle-parse",
|
||||||
|
"anstyle-query",
|
||||||
|
"anstyle-wincon",
|
||||||
|
"colorchoice",
|
||||||
|
"is-terminal",
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-parse"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333"
|
||||||
|
dependencies = [
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-query"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-wincon"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c677ab05e09154296dd37acecd46420c17b9713e8366facafa8fc0885167cf4c"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "backtrace"
|
||||||
|
version = "0.3.67"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca"
|
||||||
|
dependencies = [
|
||||||
|
"addr2line 0.19.0",
|
||||||
|
"cc",
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"miniz_oxide",
|
||||||
|
"object 0.30.3",
|
||||||
|
"rustc-demangle",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.0.79"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
|
||||||
|
|
||||||
|
[[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.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c27cdf28c0f604ba3f512b0c9a409f8de8513e4816705deb0498b627e7c3a3fd"
|
||||||
|
dependencies = [
|
||||||
|
"clap_builder",
|
||||||
|
"clap_derive",
|
||||||
|
"once_cell",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_builder"
|
||||||
|
version = "4.3.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "08a9f1ab5e9f01a9b81f202e8562eb9a10de70abf9eaeac1be465c28b75aa4aa"
|
||||||
|
dependencies = [
|
||||||
|
"anstream",
|
||||||
|
"anstyle",
|
||||||
|
"clap_lex",
|
||||||
|
"strsim",
|
||||||
|
"terminal_size",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_derive"
|
||||||
|
version = "4.3.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.15",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "compiler_builtins"
|
||||||
|
version = "0.1.91"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "571298a3cce7e2afbd3d61abb91a18667d5ab25993ec577a88ee8ac45f00cc3a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cpp_demangle"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2c76f98bdfc7f66172e6c7065f981ebb576ffc903fe4c0561d9f0c2509226dc6"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crc32fast"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "errno"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f"
|
||||||
|
dependencies = [
|
||||||
|
"errno-dragonfly",
|
||||||
|
"libc",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "errno-dragonfly"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fallible-iterator"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "findshlibs"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "40b9e59cd0f7e0806cca4be089683ecb6434e602038df21fe6bf6711b2f07f64"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"lazy_static",
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "flate2"
|
||||||
|
version = "1.0.25"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
|
||||||
|
dependencies = [
|
||||||
|
"crc32fast",
|
||||||
|
"miniz_oxide",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gimli"
|
||||||
|
version = "0.27.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gimli"
|
||||||
|
version = "0.28.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"
|
||||||
|
dependencies = [
|
||||||
|
"compiler_builtins",
|
||||||
|
"fallible-iterator",
|
||||||
|
"rustc-std-workspace-alloc",
|
||||||
|
"rustc-std-workspace-core",
|
||||||
|
"stable_deref_trait",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.2.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
|
||||||
|
|
||||||
|
[[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.2",
|
||||||
|
"libc",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "is-terminal"
|
||||||
|
version = "0.4.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi 0.3.2",
|
||||||
|
"rustix 0.38.8",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.147"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libtest-mimic"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6d8de370f98a6cb8a4606618e53e802f93b094ddec0f96988eaec2c27e6e9ce7"
|
||||||
|
dependencies = [
|
||||||
|
"clap",
|
||||||
|
"termcolor",
|
||||||
|
"threadpool",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memmap2"
|
||||||
|
version = "0.5.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miniz_oxide"
|
||||||
|
version = "0.6.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
|
||||||
|
dependencies = [
|
||||||
|
"adler",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num_cpus"
|
||||||
|
version = "1.15.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi 0.2.6",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "object"
|
||||||
|
version = "0.30.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "object"
|
||||||
|
version = "0.32.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe"
|
||||||
|
dependencies = [
|
||||||
|
"flate2",
|
||||||
|
"memchr",
|
||||||
|
"ruzstd",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.17.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.56"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-demangle"
|
||||||
|
version = "0.1.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d4a36c42d1873f9a77c53bde094f9664d9891bc604a45b4798fd2c389ed12e5b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-std-workspace-alloc"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ff66d57013a5686e1917ed6a025d54dd591fcda71a41fe07edf4d16726aefa86"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-std-workspace-core"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1956f5517128a2b6f23ab2dadf1a976f4f5b27962e7724c2bf3d45e539ec098c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustix"
|
||||||
|
version = "0.37.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"errno",
|
||||||
|
"io-lifetimes",
|
||||||
|
"libc",
|
||||||
|
"linux-raw-sys 0.3.8",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustix"
|
||||||
|
version = "0.38.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.4.0",
|
||||||
|
"errno",
|
||||||
|
"libc",
|
||||||
|
"linux-raw-sys 0.4.5",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ruzstd"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3ffab8f9715a0d455df4bbb9d21e91135aab3cd3ca187af0cd0c3c3f868fdc"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"thiserror-core",
|
||||||
|
"twox-hash",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smallvec"
|
||||||
|
version = "1.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "stable_deref_trait"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "static_assertions"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.109"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "termcolor"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "terminal_size"
|
||||||
|
version = "0.2.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e6bf6f19e9f8ed8d4048dc22981458ebcf406d67e94cd422e5ecd73d63b3237"
|
||||||
|
dependencies = [
|
||||||
|
"rustix 0.37.23",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-core"
|
||||||
|
version = "1.0.38"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0d97345f6437bb2004cd58819d8a9ef8e36cdd7661c2abc4bbde0a7c40d9f497"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-core-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-core-impl"
|
||||||
|
version = "1.0.38"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "10ac1c5050e43014d16b2f94d0d2ce79e65ffdd8b38d8048f9c8f6a8a6da62ac"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "threadpool"
|
||||||
|
version = "1.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"
|
||||||
|
dependencies = [
|
||||||
|
"num_cpus",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "twox-hash"
|
||||||
|
version = "1.6.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"static_assertions",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typed-arena"
|
||||||
|
version = "2.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf8parse"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu",
|
||||||
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-util"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.48.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm",
|
||||||
|
"windows_aarch64_msvc",
|
||||||
|
"windows_i686_gnu",
|
||||||
|
"windows_i686_msvc",
|
||||||
|
"windows_x86_64_gnu",
|
||||||
|
"windows_x86_64_gnullvm",
|
||||||
|
"windows_x86_64_msvc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
|
147
vendor/addr2line/Cargo.toml
vendored
Normal file
147
vendor/addr2line/Cargo.toml
vendored
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
# 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 = "2018"
|
||||||
|
rust-version = "1.65"
|
||||||
|
name = "addr2line"
|
||||||
|
version = "0.21.0"
|
||||||
|
exclude = [
|
||||||
|
"/benches/*",
|
||||||
|
"/fixtures/*",
|
||||||
|
".github",
|
||||||
|
]
|
||||||
|
description = "A cross-platform symbolication library written in Rust, using `gimli`"
|
||||||
|
documentation = "https://docs.rs/addr2line"
|
||||||
|
readme = "./README.md"
|
||||||
|
keywords = [
|
||||||
|
"DWARF",
|
||||||
|
"debug",
|
||||||
|
"elf",
|
||||||
|
"symbolicate",
|
||||||
|
"atos",
|
||||||
|
]
|
||||||
|
categories = ["development-tools::debugging"]
|
||||||
|
license = "Apache-2.0 OR MIT"
|
||||||
|
repository = "https://github.com/gimli-rs/addr2line"
|
||||||
|
|
||||||
|
[profile.bench]
|
||||||
|
codegen-units = 1
|
||||||
|
debug = true
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
debug = true
|
||||||
|
|
||||||
|
[[example]]
|
||||||
|
name = "addr2line"
|
||||||
|
required-features = ["default"]
|
||||||
|
|
||||||
|
[[test]]
|
||||||
|
name = "output_equivalence"
|
||||||
|
harness = false
|
||||||
|
required-features = ["default"]
|
||||||
|
|
||||||
|
[[test]]
|
||||||
|
name = "correctness"
|
||||||
|
required-features = ["default"]
|
||||||
|
|
||||||
|
[[test]]
|
||||||
|
name = "parse"
|
||||||
|
required-features = ["std-object"]
|
||||||
|
|
||||||
|
[dependencies.alloc]
|
||||||
|
version = "1.0.0"
|
||||||
|
optional = true
|
||||||
|
package = "rustc-std-workspace-alloc"
|
||||||
|
|
||||||
|
[dependencies.compiler_builtins]
|
||||||
|
version = "0.1.2"
|
||||||
|
optional = true
|
||||||
|
|
||||||
|
[dependencies.core]
|
||||||
|
version = "1.0.0"
|
||||||
|
optional = true
|
||||||
|
package = "rustc-std-workspace-core"
|
||||||
|
|
||||||
|
[dependencies.cpp_demangle]
|
||||||
|
version = "0.4"
|
||||||
|
features = ["alloc"]
|
||||||
|
optional = true
|
||||||
|
default-features = false
|
||||||
|
|
||||||
|
[dependencies.fallible-iterator]
|
||||||
|
version = "0.3.0"
|
||||||
|
optional = true
|
||||||
|
default-features = false
|
||||||
|
|
||||||
|
[dependencies.gimli]
|
||||||
|
version = "0.28.0"
|
||||||
|
features = ["read"]
|
||||||
|
default-features = false
|
||||||
|
|
||||||
|
[dependencies.memmap2]
|
||||||
|
version = "0.5.5"
|
||||||
|
optional = true
|
||||||
|
|
||||||
|
[dependencies.object]
|
||||||
|
version = "0.32.0"
|
||||||
|
features = ["read"]
|
||||||
|
optional = true
|
||||||
|
default-features = false
|
||||||
|
|
||||||
|
[dependencies.rustc-demangle]
|
||||||
|
version = "0.1"
|
||||||
|
optional = true
|
||||||
|
|
||||||
|
[dependencies.smallvec]
|
||||||
|
version = "1"
|
||||||
|
optional = true
|
||||||
|
default-features = false
|
||||||
|
|
||||||
|
[dev-dependencies.backtrace]
|
||||||
|
version = "0.3.13"
|
||||||
|
|
||||||
|
[dev-dependencies.clap]
|
||||||
|
version = "4.3.21"
|
||||||
|
features = ["wrap_help"]
|
||||||
|
|
||||||
|
[dev-dependencies.findshlibs]
|
||||||
|
version = "0.10"
|
||||||
|
|
||||||
|
[dev-dependencies.libtest-mimic]
|
||||||
|
version = "0.6.1"
|
||||||
|
|
||||||
|
[dev-dependencies.typed-arena]
|
||||||
|
version = "2"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = [
|
||||||
|
"rustc-demangle",
|
||||||
|
"cpp_demangle",
|
||||||
|
"std-object",
|
||||||
|
"fallible-iterator",
|
||||||
|
"smallvec",
|
||||||
|
"memmap2",
|
||||||
|
]
|
||||||
|
rustc-dep-of-std = [
|
||||||
|
"core",
|
||||||
|
"alloc",
|
||||||
|
"compiler_builtins",
|
||||||
|
"gimli/rustc-dep-of-std",
|
||||||
|
]
|
||||||
|
std = ["gimli/std"]
|
||||||
|
std-object = [
|
||||||
|
"std",
|
||||||
|
"object",
|
||||||
|
"object/std",
|
||||||
|
"object/compression",
|
||||||
|
"gimli/endian-reader",
|
||||||
|
]
|
201
vendor/addr2line/LICENSE-APACHE
vendored
Normal file
201
vendor/addr2line/LICENSE-APACHE
vendored
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
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.
|
25
vendor/addr2line/LICENSE-MIT
vendored
Normal file
25
vendor/addr2line/LICENSE-MIT
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
Copyright (c) 2016-2018 The gimli Developers
|
||||||
|
|
||||||
|
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.
|
48
vendor/addr2line/README.md
vendored
Normal file
48
vendor/addr2line/README.md
vendored
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# addr2line
|
||||||
|
|
||||||
|
[![](https://img.shields.io/crates/v/addr2line.svg)](https://crates.io/crates/addr2line)
|
||||||
|
[![](https://img.shields.io/docsrs/addr2line.svg)](https://docs.rs/addr2line)
|
||||||
|
[![Coverage Status](https://coveralls.io/repos/github/gimli-rs/addr2line/badge.svg?branch=master)](https://coveralls.io/github/gimli-rs/addr2line?branch=master)
|
||||||
|
|
||||||
|
A cross-platform library for retrieving per-address debug information
|
||||||
|
from files with DWARF debug information.
|
||||||
|
|
||||||
|
`addr2line` uses [`gimli`](https://github.com/gimli-rs/gimli) to parse
|
||||||
|
the debug information, and exposes an interface for finding
|
||||||
|
the source file, line number, and wrapping function for instruction
|
||||||
|
addresses within the target program. These lookups can either be
|
||||||
|
performed programmatically through `Context::find_location` and
|
||||||
|
`Context::find_frames`, or via the included example binary,
|
||||||
|
`addr2line` (named and modelled after the equivalent utility from
|
||||||
|
[GNU binutils](https://sourceware.org/binutils/docs/binutils/addr2line.html)).
|
||||||
|
|
||||||
|
# Quickstart
|
||||||
|
- Add the [`addr2line` crate](https://crates.io/crates/addr2line) to your `Cargo.toml`
|
||||||
|
- Load the file and parse it with [`addr2line::object::read::File::parse`](https://docs.rs/object/*/object/read/struct.File.html#method.parse)
|
||||||
|
- Pass the parsed file to [`addr2line::Context::new` ](https://docs.rs/addr2line/*/addr2line/struct.Context.html#method.new)
|
||||||
|
- Use [`addr2line::Context::find_location`](https://docs.rs/addr2line/*/addr2line/struct.Context.html#method.find_location)
|
||||||
|
or [`addr2line::Context::find_frames`](https://docs.rs/addr2line/*/addr2line/struct.Context.html#method.find_frames)
|
||||||
|
to look up debug information for an address
|
||||||
|
|
||||||
|
# Performance
|
||||||
|
|
||||||
|
`addr2line` optimizes for speed over memory by caching parsed information.
|
||||||
|
The DWARF information is parsed lazily where possible.
|
||||||
|
|
||||||
|
The library aims to perform similarly to equivalent existing tools such
|
||||||
|
as `addr2line` from binutils, `eu-addr2line` from elfutils, and
|
||||||
|
`llvm-symbolize` from the llvm project, and in the past some benchmarking
|
||||||
|
was done that indicates a comparable performance.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Licensed under either of
|
||||||
|
|
||||||
|
* Apache License, Version 2.0 ([`LICENSE-APACHE`](./LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
* MIT license ([`LICENSE-MIT`](./LICENSE-MIT) or https://opensource.org/licenses/MIT)
|
||||||
|
|
||||||
|
at your option.
|
||||||
|
|
||||||
|
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.
|
23
vendor/addr2line/bench.plot.r
vendored
Normal file
23
vendor/addr2line/bench.plot.r
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
v <- read.table(file("stdin"))
|
||||||
|
t <- data.frame(prog=v[,1], funcs=(v[,2]=="func"), time=v[,3], mem=v[,4], stringsAsFactors=FALSE)
|
||||||
|
|
||||||
|
t$prog <- as.character(t$prog)
|
||||||
|
t$prog[t$prog == "master"] <- "gimli-rs/addr2line"
|
||||||
|
t$funcs[t$funcs == TRUE] <- "With functions"
|
||||||
|
t$funcs[t$funcs == FALSE] <- "File/line only"
|
||||||
|
t$mem = t$mem / 1024.0
|
||||||
|
|
||||||
|
library(ggplot2)
|
||||||
|
p <- ggplot(data=t, aes(x=prog, y=time, fill=prog))
|
||||||
|
p <- p + geom_bar(stat = "identity")
|
||||||
|
p <- p + facet_wrap(~ funcs)
|
||||||
|
p <- p + theme(axis.title.x=element_blank(), axis.text.x=element_blank(), axis.ticks.x=element_blank())
|
||||||
|
p <- p + ylab("time (s)") + ggtitle("addr2line runtime")
|
||||||
|
ggsave('time.png',plot=p,width=10,height=6)
|
||||||
|
|
||||||
|
p <- ggplot(data=t, aes(x=prog, y=mem, fill=prog))
|
||||||
|
p <- p + geom_bar(stat = "identity")
|
||||||
|
p <- p + facet_wrap(~ funcs)
|
||||||
|
p <- p + theme(axis.title.x=element_blank(), axis.text.x=element_blank(), axis.ticks.x=element_blank())
|
||||||
|
p <- p + ylab("memory (kB)") + ggtitle("addr2line memory usage")
|
||||||
|
ggsave('memory.png',plot=p,width=10,height=6)
|
112
vendor/addr2line/benchmark.sh
vendored
Executable file
112
vendor/addr2line/benchmark.sh
vendored
Executable file
@ -0,0 +1,112 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
if [[ $# -le 1 ]]; then
|
||||||
|
echo "Usage: $0 <executable> [<addresses>] REFS..."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
target="$1"
|
||||||
|
shift
|
||||||
|
|
||||||
|
addresses=""
|
||||||
|
if [[ -e "$1" ]]; then
|
||||||
|
addresses="$1"
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
# path to "us"
|
||||||
|
# readlink -f, but more portable:
|
||||||
|
dirname=$(perl -e 'use Cwd "abs_path";print abs_path(shift)' "$(dirname "$0")")
|
||||||
|
|
||||||
|
# https://stackoverflow.com/a/2358432/472927
|
||||||
|
{
|
||||||
|
# compile all refs
|
||||||
|
pushd "$dirname" > /dev/null
|
||||||
|
# if the user has some local changes, preserve them
|
||||||
|
nstashed=$(git stash list | wc -l)
|
||||||
|
echo "==> Stashing any local modifications"
|
||||||
|
git stash --keep-index > /dev/null
|
||||||
|
popstash() {
|
||||||
|
# https://stackoverflow.com/q/24520791/472927
|
||||||
|
if [[ "$(git stash list | wc -l)" -ne "$nstashed" ]]; then
|
||||||
|
echo "==> Restoring stashed state"
|
||||||
|
git stash pop > /dev/null
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
# if the user has added stuff to the index, abort
|
||||||
|
if ! git diff-index --quiet HEAD --; then
|
||||||
|
echo "Refusing to overwrite outstanding git changes"
|
||||||
|
popstash
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
current=$(git symbolic-ref --short HEAD)
|
||||||
|
for ref in "$@"; do
|
||||||
|
echo "==> Compiling $ref"
|
||||||
|
git checkout -q "$ref"
|
||||||
|
commit=$(git rev-parse HEAD)
|
||||||
|
fn="target/release/addr2line-$commit"
|
||||||
|
if [[ ! -e "$fn" ]]; then
|
||||||
|
cargo build --release --example addr2line
|
||||||
|
cp target/release/examples/addr2line "$fn"
|
||||||
|
fi
|
||||||
|
if [[ "$ref" != "$commit" ]]; then
|
||||||
|
ln -sfn "addr2line-$commit" target/release/addr2line-"$ref"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
git checkout -q "$current"
|
||||||
|
popstash
|
||||||
|
popd > /dev/null
|
||||||
|
|
||||||
|
# get us some addresses to look up
|
||||||
|
if [[ -z "$addresses" ]]; then
|
||||||
|
echo "==> Looking for benchmarking addresses (this may take a while)"
|
||||||
|
addresses=$(mktemp tmp.XXXXXXXXXX)
|
||||||
|
objdump -C -x --disassemble -l "$target" \
|
||||||
|
| grep -P '0[048]:' \
|
||||||
|
| awk '{print $1}' \
|
||||||
|
| sed 's/:$//' \
|
||||||
|
> "$addresses"
|
||||||
|
echo " -> Addresses stored in $addresses; you should re-use it next time"
|
||||||
|
fi
|
||||||
|
|
||||||
|
run() {
|
||||||
|
func="$1"
|
||||||
|
name="$2"
|
||||||
|
cmd="$3"
|
||||||
|
args="$4"
|
||||||
|
printf "%s\t%s\t" "$name" "$func"
|
||||||
|
if [[ "$cmd" =~ llvm-symbolizer ]]; then
|
||||||
|
/usr/bin/time -f '%e\t%M' "$cmd" $args -obj="$target" < "$addresses" 2>&1 >/dev/null
|
||||||
|
else
|
||||||
|
/usr/bin/time -f '%e\t%M' "$cmd" $args -e "$target" < "$addresses" 2>&1 >/dev/null
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# run without functions
|
||||||
|
log1=$(mktemp tmp.XXXXXXXXXX)
|
||||||
|
echo "==> Benchmarking"
|
||||||
|
run nofunc binutils addr2line >> "$log1"
|
||||||
|
#run nofunc elfutils eu-addr2line >> "$log1"
|
||||||
|
run nofunc llvm-sym llvm-symbolizer -functions=none >> "$log1"
|
||||||
|
for ref in "$@"; do
|
||||||
|
run nofunc "$ref" "$dirname/target/release/addr2line-$ref" >> "$log1"
|
||||||
|
done
|
||||||
|
cat "$log1" | column -t
|
||||||
|
|
||||||
|
# run with functions
|
||||||
|
log2=$(mktemp tmp.XXXXXXXXXX)
|
||||||
|
echo "==> Benchmarking with -f"
|
||||||
|
run func binutils addr2line "-f -i" >> "$log2"
|
||||||
|
#run func elfutils eu-addr2line "-f -i" >> "$log2"
|
||||||
|
run func llvm-sym llvm-symbolizer "-functions=linkage -demangle=0" >> "$log2"
|
||||||
|
for ref in "$@"; do
|
||||||
|
run func "$ref" "$dirname/target/release/addr2line-$ref" "-f -i" >> "$log2"
|
||||||
|
done
|
||||||
|
cat "$log2" | column -t
|
||||||
|
cat "$log2" >> "$log1"; rm "$log2"
|
||||||
|
|
||||||
|
echo "==> Plotting"
|
||||||
|
Rscript --no-readline --no-restore --no-save "$dirname/bench.plot.r" < "$log1"
|
||||||
|
|
||||||
|
echo "==> Cleaning up"
|
||||||
|
rm "$log1"
|
||||||
|
exit 0
|
||||||
|
}
|
5
vendor/addr2line/coverage.sh
vendored
Normal file
5
vendor/addr2line/coverage.sh
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Run tarpaulin and pycobertura to generate coverage.html.
|
||||||
|
|
||||||
|
cargo tarpaulin --skip-clean --out Xml
|
||||||
|
pycobertura show --format html --output coverage.html cobertura.xml
|
317
vendor/addr2line/examples/addr2line.rs
vendored
Normal file
317
vendor/addr2line/examples/addr2line.rs
vendored
Normal file
@ -0,0 +1,317 @@
|
|||||||
|
use std::borrow::Cow;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{BufRead, Lines, StdinLock, Write};
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
use clap::{Arg, ArgAction, Command};
|
||||||
|
use fallible_iterator::FallibleIterator;
|
||||||
|
use object::{Object, ObjectSection, SymbolMap, SymbolMapName};
|
||||||
|
use typed_arena::Arena;
|
||||||
|
|
||||||
|
use addr2line::{Context, Location};
|
||||||
|
|
||||||
|
fn parse_uint_from_hex_string(string: &str) -> Option<u64> {
|
||||||
|
if string.len() > 2 && string.starts_with("0x") {
|
||||||
|
u64::from_str_radix(&string[2..], 16).ok()
|
||||||
|
} else {
|
||||||
|
u64::from_str_radix(string, 16).ok()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Addrs<'a> {
|
||||||
|
Args(clap::parser::ValuesRef<'a, String>),
|
||||||
|
Stdin(Lines<StdinLock<'a>>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for Addrs<'a> {
|
||||||
|
type Item = Option<u64>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Option<u64>> {
|
||||||
|
let text = match *self {
|
||||||
|
Addrs::Args(ref mut vals) => vals.next().map(Cow::from),
|
||||||
|
Addrs::Stdin(ref mut lines) => lines.next().map(Result::unwrap).map(Cow::from),
|
||||||
|
};
|
||||||
|
text.as_ref()
|
||||||
|
.map(Cow::as_ref)
|
||||||
|
.map(parse_uint_from_hex_string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_loc(loc: Option<&Location<'_>>, basenames: bool, llvm: bool) {
|
||||||
|
if let Some(loc) = loc {
|
||||||
|
if let Some(ref file) = loc.file.as_ref() {
|
||||||
|
let path = if basenames {
|
||||||
|
Path::new(Path::new(file).file_name().unwrap())
|
||||||
|
} else {
|
||||||
|
Path::new(file)
|
||||||
|
};
|
||||||
|
print!("{}:", path.display());
|
||||||
|
} else {
|
||||||
|
print!("??:");
|
||||||
|
}
|
||||||
|
if llvm {
|
||||||
|
print!("{}:{}", loc.line.unwrap_or(0), loc.column.unwrap_or(0));
|
||||||
|
} else if let Some(line) = loc.line {
|
||||||
|
print!("{}", line);
|
||||||
|
} else {
|
||||||
|
print!("?");
|
||||||
|
}
|
||||||
|
println!();
|
||||||
|
} else if llvm {
|
||||||
|
println!("??:0:0");
|
||||||
|
} else {
|
||||||
|
println!("??:0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_function(name: Option<&str>, language: Option<gimli::DwLang>, demangle: bool) {
|
||||||
|
if let Some(name) = name {
|
||||||
|
if demangle {
|
||||||
|
print!("{}", addr2line::demangle_auto(Cow::from(name), language));
|
||||||
|
} else {
|
||||||
|
print!("{}", name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print!("??");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_file_section<'input, 'arena, Endian: gimli::Endianity>(
|
||||||
|
id: gimli::SectionId,
|
||||||
|
file: &object::File<'input>,
|
||||||
|
endian: Endian,
|
||||||
|
arena_data: &'arena Arena<Cow<'input, [u8]>>,
|
||||||
|
) -> Result<gimli::EndianSlice<'arena, Endian>, ()> {
|
||||||
|
// TODO: Unify with dwarfdump.rs in gimli.
|
||||||
|
let name = id.name();
|
||||||
|
match file.section_by_name(name) {
|
||||||
|
Some(section) => match section.uncompressed_data().unwrap() {
|
||||||
|
Cow::Borrowed(b) => Ok(gimli::EndianSlice::new(b, endian)),
|
||||||
|
Cow::Owned(b) => Ok(gimli::EndianSlice::new(arena_data.alloc(b.into()), endian)),
|
||||||
|
},
|
||||||
|
None => Ok(gimli::EndianSlice::new(&[][..], endian)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_name_from_symbols<'a>(
|
||||||
|
symbols: &'a SymbolMap<SymbolMapName<'_>>,
|
||||||
|
probe: u64,
|
||||||
|
) -> Option<&'a str> {
|
||||||
|
symbols.get(probe).map(|x| x.name())
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Options<'a> {
|
||||||
|
do_functions: bool,
|
||||||
|
do_inlines: bool,
|
||||||
|
pretty: bool,
|
||||||
|
print_addrs: bool,
|
||||||
|
basenames: bool,
|
||||||
|
demangle: bool,
|
||||||
|
llvm: bool,
|
||||||
|
exe: &'a PathBuf,
|
||||||
|
sup: Option<&'a PathBuf>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let matches = Command::new("addr2line")
|
||||||
|
.version(env!("CARGO_PKG_VERSION"))
|
||||||
|
.about("A fast addr2line Rust port")
|
||||||
|
.max_term_width(100)
|
||||||
|
.args(&[
|
||||||
|
Arg::new("exe")
|
||||||
|
.short('e')
|
||||||
|
.long("exe")
|
||||||
|
.value_name("filename")
|
||||||
|
.value_parser(clap::value_parser!(PathBuf))
|
||||||
|
.help(
|
||||||
|
"Specify the name of the executable for which addresses should be translated.",
|
||||||
|
)
|
||||||
|
.required(true),
|
||||||
|
Arg::new("sup")
|
||||||
|
.long("sup")
|
||||||
|
.value_name("filename")
|
||||||
|
.value_parser(clap::value_parser!(PathBuf))
|
||||||
|
.help("Path to supplementary object file."),
|
||||||
|
Arg::new("functions")
|
||||||
|
.short('f')
|
||||||
|
.long("functions")
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
|
.help("Display function names as well as file and line number information."),
|
||||||
|
Arg::new("pretty").short('p').long("pretty-print")
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
|
.help(
|
||||||
|
"Make the output more human friendly: each location are printed on one line.",
|
||||||
|
),
|
||||||
|
Arg::new("inlines").short('i').long("inlines")
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
|
.help(
|
||||||
|
"If the address belongs to a function that was inlined, the source information for \
|
||||||
|
all enclosing scopes back to the first non-inlined function will also be printed.",
|
||||||
|
),
|
||||||
|
Arg::new("addresses").short('a').long("addresses")
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
|
.help(
|
||||||
|
"Display the address before the function name, file and line number information.",
|
||||||
|
),
|
||||||
|
Arg::new("basenames")
|
||||||
|
.short('s')
|
||||||
|
.long("basenames")
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
|
.help("Display only the base of each file name."),
|
||||||
|
Arg::new("demangle").short('C').long("demangle")
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
|
.help(
|
||||||
|
"Demangle function names. \
|
||||||
|
Specifying a specific demangling style (like GNU addr2line) is not supported. \
|
||||||
|
(TODO)"
|
||||||
|
),
|
||||||
|
Arg::new("llvm")
|
||||||
|
.long("llvm")
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
|
.help("Display output in the same format as llvm-symbolizer."),
|
||||||
|
Arg::new("addrs")
|
||||||
|
.action(ArgAction::Append)
|
||||||
|
.help("Addresses to use instead of reading from stdin."),
|
||||||
|
])
|
||||||
|
.get_matches();
|
||||||
|
|
||||||
|
let arena_data = Arena::new();
|
||||||
|
|
||||||
|
let opts = Options {
|
||||||
|
do_functions: matches.get_flag("functions"),
|
||||||
|
do_inlines: matches.get_flag("inlines"),
|
||||||
|
pretty: matches.get_flag("pretty"),
|
||||||
|
print_addrs: matches.get_flag("addresses"),
|
||||||
|
basenames: matches.get_flag("basenames"),
|
||||||
|
demangle: matches.get_flag("demangle"),
|
||||||
|
llvm: matches.get_flag("llvm"),
|
||||||
|
exe: matches.get_one::<PathBuf>("exe").unwrap(),
|
||||||
|
sup: matches.get_one::<PathBuf>("sup"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let file = File::open(opts.exe).unwrap();
|
||||||
|
let map = unsafe { memmap2::Mmap::map(&file).unwrap() };
|
||||||
|
let object = &object::File::parse(&*map).unwrap();
|
||||||
|
|
||||||
|
let endian = if object.is_little_endian() {
|
||||||
|
gimli::RunTimeEndian::Little
|
||||||
|
} else {
|
||||||
|
gimli::RunTimeEndian::Big
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut load_section = |id: gimli::SectionId| -> Result<_, _> {
|
||||||
|
load_file_section(id, object, endian, &arena_data)
|
||||||
|
};
|
||||||
|
|
||||||
|
let sup_map;
|
||||||
|
let sup_object = if let Some(sup_path) = opts.sup {
|
||||||
|
let sup_file = File::open(sup_path).unwrap();
|
||||||
|
sup_map = unsafe { memmap2::Mmap::map(&sup_file).unwrap() };
|
||||||
|
Some(object::File::parse(&*sup_map).unwrap())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let symbols = object.symbol_map();
|
||||||
|
let mut dwarf = gimli::Dwarf::load(&mut load_section).unwrap();
|
||||||
|
if let Some(ref sup_object) = sup_object {
|
||||||
|
let mut load_sup_section = |id: gimli::SectionId| -> Result<_, _> {
|
||||||
|
load_file_section(id, sup_object, endian, &arena_data)
|
||||||
|
};
|
||||||
|
dwarf.load_sup(&mut load_sup_section).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut split_dwarf_loader = addr2line::builtin_split_dwarf_loader::SplitDwarfLoader::new(
|
||||||
|
|data, endian| {
|
||||||
|
gimli::EndianSlice::new(arena_data.alloc(Cow::Owned(data.into_owned())), endian)
|
||||||
|
},
|
||||||
|
Some(opts.exe.clone()),
|
||||||
|
);
|
||||||
|
let ctx = Context::from_dwarf(dwarf).unwrap();
|
||||||
|
|
||||||
|
let stdin = std::io::stdin();
|
||||||
|
let addrs = matches
|
||||||
|
.get_many::<String>("addrs")
|
||||||
|
.map(Addrs::Args)
|
||||||
|
.unwrap_or_else(|| Addrs::Stdin(stdin.lock().lines()));
|
||||||
|
|
||||||
|
for probe in addrs {
|
||||||
|
if opts.print_addrs {
|
||||||
|
let addr = probe.unwrap_or(0);
|
||||||
|
if opts.llvm {
|
||||||
|
print!("0x{:x}", addr);
|
||||||
|
} else {
|
||||||
|
print!("0x{:016x}", addr);
|
||||||
|
}
|
||||||
|
if opts.pretty {
|
||||||
|
print!(": ");
|
||||||
|
} else {
|
||||||
|
println!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.do_functions || opts.do_inlines {
|
||||||
|
let mut printed_anything = false;
|
||||||
|
if let Some(probe) = probe {
|
||||||
|
let frames = ctx.find_frames(probe);
|
||||||
|
let frames = split_dwarf_loader.run(frames).unwrap();
|
||||||
|
let mut frames = frames.enumerate();
|
||||||
|
while let Some((i, frame)) = frames.next().unwrap() {
|
||||||
|
if opts.pretty && i != 0 {
|
||||||
|
print!(" (inlined by) ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.do_functions {
|
||||||
|
if let Some(func) = frame.function {
|
||||||
|
print_function(
|
||||||
|
func.raw_name().ok().as_ref().map(AsRef::as_ref),
|
||||||
|
func.language,
|
||||||
|
opts.demangle,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
let name = find_name_from_symbols(&symbols, probe);
|
||||||
|
print_function(name, None, opts.demangle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.pretty {
|
||||||
|
print!(" at ");
|
||||||
|
} else {
|
||||||
|
println!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
print_loc(frame.location.as_ref(), opts.basenames, opts.llvm);
|
||||||
|
|
||||||
|
printed_anything = true;
|
||||||
|
|
||||||
|
if !opts.do_inlines {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !printed_anything {
|
||||||
|
if opts.do_functions {
|
||||||
|
let name = probe.and_then(|probe| find_name_from_symbols(&symbols, probe));
|
||||||
|
print_function(name, None, opts.demangle);
|
||||||
|
|
||||||
|
if opts.pretty {
|
||||||
|
print!(" at ");
|
||||||
|
} else {
|
||||||
|
println!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
print_loc(None, opts.basenames, opts.llvm);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let loc = probe.and_then(|probe| ctx.find_location(probe).unwrap());
|
||||||
|
print_loc(loc.as_ref(), opts.basenames, opts.llvm);
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.llvm {
|
||||||
|
println!();
|
||||||
|
}
|
||||||
|
std::io::stdout().flush().unwrap();
|
||||||
|
}
|
||||||
|
}
|
1
vendor/addr2line/rustfmt.toml
vendored
Normal file
1
vendor/addr2line/rustfmt.toml
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
|
164
vendor/addr2line/src/builtin_split_dwarf_loader.rs
vendored
Normal file
164
vendor/addr2line/src/builtin_split_dwarf_loader.rs
vendored
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
use alloc::borrow::Cow;
|
||||||
|
use alloc::sync::Arc;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use object::Object;
|
||||||
|
|
||||||
|
use crate::{LookupContinuation, LookupResult};
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
fn convert_path<R: gimli::Reader<Endian = gimli::RunTimeEndian>>(
|
||||||
|
r: &R,
|
||||||
|
) -> Result<PathBuf, gimli::Error> {
|
||||||
|
use std::ffi::OsStr;
|
||||||
|
use std::os::unix::ffi::OsStrExt;
|
||||||
|
let bytes = r.to_slice()?;
|
||||||
|
let s = OsStr::from_bytes(&bytes);
|
||||||
|
Ok(PathBuf::from(s))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(unix))]
|
||||||
|
fn convert_path<R: gimli::Reader<Endian = gimli::RunTimeEndian>>(
|
||||||
|
r: &R,
|
||||||
|
) -> Result<PathBuf, gimli::Error> {
|
||||||
|
let bytes = r.to_slice()?;
|
||||||
|
let s = std::str::from_utf8(&bytes).map_err(|_| gimli::Error::BadUtf8)?;
|
||||||
|
Ok(PathBuf::from(s))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_section<'data: 'file, 'file, O, R, F>(
|
||||||
|
id: gimli::SectionId,
|
||||||
|
file: &'file O,
|
||||||
|
endian: R::Endian,
|
||||||
|
loader: &mut F,
|
||||||
|
) -> Result<R, gimli::Error>
|
||||||
|
where
|
||||||
|
O: object::Object<'data, 'file>,
|
||||||
|
R: gimli::Reader<Endian = gimli::RunTimeEndian>,
|
||||||
|
F: FnMut(Cow<'data, [u8]>, R::Endian) -> R,
|
||||||
|
{
|
||||||
|
use object::ObjectSection;
|
||||||
|
|
||||||
|
let data = id
|
||||||
|
.dwo_name()
|
||||||
|
.and_then(|dwo_name| {
|
||||||
|
file.section_by_name(dwo_name)
|
||||||
|
.and_then(|section| section.uncompressed_data().ok())
|
||||||
|
})
|
||||||
|
.unwrap_or(Cow::Borrowed(&[]));
|
||||||
|
Ok(loader(data, endian))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A simple builtin split DWARF loader.
|
||||||
|
pub struct SplitDwarfLoader<R, F>
|
||||||
|
where
|
||||||
|
R: gimli::Reader<Endian = gimli::RunTimeEndian>,
|
||||||
|
F: FnMut(Cow<'_, [u8]>, R::Endian) -> R,
|
||||||
|
{
|
||||||
|
loader: F,
|
||||||
|
dwarf_package: Option<gimli::DwarfPackage<R>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R, F> SplitDwarfLoader<R, F>
|
||||||
|
where
|
||||||
|
R: gimli::Reader<Endian = gimli::RunTimeEndian>,
|
||||||
|
F: FnMut(Cow<'_, [u8]>, R::Endian) -> R,
|
||||||
|
{
|
||||||
|
fn load_dwarf_package(loader: &mut F, path: Option<PathBuf>) -> Option<gimli::DwarfPackage<R>> {
|
||||||
|
let mut path = path.map(Ok).unwrap_or_else(std::env::current_exe).ok()?;
|
||||||
|
let dwp_extension = path
|
||||||
|
.extension()
|
||||||
|
.map(|previous_extension| {
|
||||||
|
let mut previous_extension = previous_extension.to_os_string();
|
||||||
|
previous_extension.push(".dwp");
|
||||||
|
previous_extension
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|| "dwp".into());
|
||||||
|
path.set_extension(dwp_extension);
|
||||||
|
let file = File::open(&path).ok()?;
|
||||||
|
let map = unsafe { memmap2::Mmap::map(&file).ok()? };
|
||||||
|
let dwp = object::File::parse(&*map).ok()?;
|
||||||
|
|
||||||
|
let endian = if dwp.is_little_endian() {
|
||||||
|
gimli::RunTimeEndian::Little
|
||||||
|
} else {
|
||||||
|
gimli::RunTimeEndian::Big
|
||||||
|
};
|
||||||
|
|
||||||
|
let empty = loader(Cow::Borrowed(&[]), endian);
|
||||||
|
gimli::DwarfPackage::load(
|
||||||
|
|section_id| load_section(section_id, &dwp, endian, loader),
|
||||||
|
empty,
|
||||||
|
)
|
||||||
|
.ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new split DWARF loader.
|
||||||
|
pub fn new(mut loader: F, path: Option<PathBuf>) -> SplitDwarfLoader<R, F> {
|
||||||
|
let dwarf_package = SplitDwarfLoader::load_dwarf_package(&mut loader, path);
|
||||||
|
SplitDwarfLoader {
|
||||||
|
loader,
|
||||||
|
dwarf_package,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Run the provided `LookupResult` to completion, loading any necessary
|
||||||
|
/// split DWARF along the way.
|
||||||
|
pub fn run<L>(&mut self, mut l: LookupResult<L>) -> L::Output
|
||||||
|
where
|
||||||
|
L: LookupContinuation<Buf = R>,
|
||||||
|
{
|
||||||
|
loop {
|
||||||
|
let (load, continuation) = match l {
|
||||||
|
LookupResult::Output(output) => break output,
|
||||||
|
LookupResult::Load { load, continuation } => (load, continuation),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut r: Option<Arc<gimli::Dwarf<_>>> = None;
|
||||||
|
if let Some(dwp) = self.dwarf_package.as_ref() {
|
||||||
|
if let Ok(Some(cu)) = dwp.find_cu(load.dwo_id, &load.parent) {
|
||||||
|
r = Some(Arc::new(cu));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.is_none() {
|
||||||
|
let mut path = PathBuf::new();
|
||||||
|
if let Some(p) = load.comp_dir.as_ref() {
|
||||||
|
if let Ok(p) = convert_path(p) {
|
||||||
|
path.push(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(p) = load.path.as_ref() {
|
||||||
|
if let Ok(p) = convert_path(p) {
|
||||||
|
path.push(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Ok(file) = File::open(&path) {
|
||||||
|
if let Ok(map) = unsafe { memmap2::Mmap::map(&file) } {
|
||||||
|
if let Ok(file) = object::File::parse(&*map) {
|
||||||
|
let endian = if file.is_little_endian() {
|
||||||
|
gimli::RunTimeEndian::Little
|
||||||
|
} else {
|
||||||
|
gimli::RunTimeEndian::Big
|
||||||
|
};
|
||||||
|
|
||||||
|
r = gimli::Dwarf::load(|id| {
|
||||||
|
load_section(id, &file, endian, &mut self.loader)
|
||||||
|
})
|
||||||
|
.ok()
|
||||||
|
.map(|mut dwo_dwarf| {
|
||||||
|
dwo_dwarf.make_dwo(&load.parent);
|
||||||
|
Arc::new(dwo_dwarf)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
l = continuation.resume(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
555
vendor/addr2line/src/function.rs
vendored
Normal file
555
vendor/addr2line/src/function.rs
vendored
Normal file
@ -0,0 +1,555 @@
|
|||||||
|
use alloc::boxed::Box;
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
use core::cmp::Ordering;
|
||||||
|
use core::iter;
|
||||||
|
|
||||||
|
use crate::lazy::LazyCell;
|
||||||
|
use crate::maybe_small;
|
||||||
|
use crate::{Context, DebugFile, Error, RangeAttributes};
|
||||||
|
|
||||||
|
pub(crate) struct Functions<R: gimli::Reader> {
|
||||||
|
/// List of all `DW_TAG_subprogram` details in the unit.
|
||||||
|
pub(crate) functions: Box<
|
||||||
|
[(
|
||||||
|
gimli::UnitOffset<R::Offset>,
|
||||||
|
LazyCell<Result<Function<R>, Error>>,
|
||||||
|
)],
|
||||||
|
>,
|
||||||
|
/// List of `DW_TAG_subprogram` address ranges in the unit.
|
||||||
|
pub(crate) addresses: Box<[FunctionAddress]>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A single address range for a function.
|
||||||
|
///
|
||||||
|
/// It is possible for a function to have multiple address ranges; this
|
||||||
|
/// is handled by having multiple `FunctionAddress` entries with the same
|
||||||
|
/// `function` field.
|
||||||
|
pub(crate) struct FunctionAddress {
|
||||||
|
range: gimli::Range,
|
||||||
|
/// An index into `Functions::functions`.
|
||||||
|
pub(crate) function: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) struct Function<R: gimli::Reader> {
|
||||||
|
pub(crate) dw_die_offset: gimli::UnitOffset<R::Offset>,
|
||||||
|
pub(crate) name: Option<R>,
|
||||||
|
/// List of all `DW_TAG_inlined_subroutine` details in this function.
|
||||||
|
inlined_functions: Box<[InlinedFunction<R>]>,
|
||||||
|
/// List of `DW_TAG_inlined_subroutine` address ranges in this function.
|
||||||
|
inlined_addresses: Box<[InlinedFunctionAddress]>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) struct InlinedFunctionAddress {
|
||||||
|
range: gimli::Range,
|
||||||
|
call_depth: usize,
|
||||||
|
/// An index into `Function::inlined_functions`.
|
||||||
|
function: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) struct InlinedFunction<R: gimli::Reader> {
|
||||||
|
pub(crate) dw_die_offset: gimli::UnitOffset<R::Offset>,
|
||||||
|
pub(crate) name: Option<R>,
|
||||||
|
pub(crate) call_file: Option<u64>,
|
||||||
|
pub(crate) call_line: u32,
|
||||||
|
pub(crate) call_column: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R: gimli::Reader> Functions<R> {
|
||||||
|
pub(crate) fn parse(
|
||||||
|
unit: &gimli::Unit<R>,
|
||||||
|
sections: &gimli::Dwarf<R>,
|
||||||
|
) -> Result<Functions<R>, Error> {
|
||||||
|
let mut functions = Vec::new();
|
||||||
|
let mut addresses = Vec::new();
|
||||||
|
let mut entries = unit.entries_raw(None)?;
|
||||||
|
while !entries.is_empty() {
|
||||||
|
let dw_die_offset = entries.next_offset();
|
||||||
|
if let Some(abbrev) = entries.read_abbreviation()? {
|
||||||
|
if abbrev.tag() == gimli::DW_TAG_subprogram {
|
||||||
|
let mut ranges = RangeAttributes::default();
|
||||||
|
for spec in abbrev.attributes() {
|
||||||
|
match entries.read_attribute(*spec) {
|
||||||
|
Ok(ref attr) => {
|
||||||
|
match attr.name() {
|
||||||
|
gimli::DW_AT_low_pc => match attr.value() {
|
||||||
|
gimli::AttributeValue::Addr(val) => {
|
||||||
|
ranges.low_pc = Some(val)
|
||||||
|
}
|
||||||
|
gimli::AttributeValue::DebugAddrIndex(index) => {
|
||||||
|
ranges.low_pc = Some(sections.address(unit, index)?);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
gimli::DW_AT_high_pc => match attr.value() {
|
||||||
|
gimli::AttributeValue::Addr(val) => {
|
||||||
|
ranges.high_pc = Some(val)
|
||||||
|
}
|
||||||
|
gimli::AttributeValue::DebugAddrIndex(index) => {
|
||||||
|
ranges.high_pc = Some(sections.address(unit, index)?);
|
||||||
|
}
|
||||||
|
gimli::AttributeValue::Udata(val) => {
|
||||||
|
ranges.size = Some(val)
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
gimli::DW_AT_ranges => {
|
||||||
|
ranges.ranges_offset =
|
||||||
|
sections.attr_ranges_offset(unit, attr.value())?;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let function_index = functions.len();
|
||||||
|
if ranges.for_each_range(sections, unit, |range| {
|
||||||
|
addresses.push(FunctionAddress {
|
||||||
|
range,
|
||||||
|
function: function_index,
|
||||||
|
});
|
||||||
|
})? {
|
||||||
|
functions.push((dw_die_offset, LazyCell::new()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
entries.skip_attributes(abbrev.attributes())?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The binary search requires the addresses to be sorted.
|
||||||
|
//
|
||||||
|
// It also requires them to be non-overlapping. In practice, overlapping
|
||||||
|
// function ranges are unlikely, so we don't try to handle that yet.
|
||||||
|
//
|
||||||
|
// It's possible for multiple functions to have the same address range if the
|
||||||
|
// compiler can detect and remove functions with identical code. In that case
|
||||||
|
// we'll nondeterministically return one of them.
|
||||||
|
addresses.sort_by_key(|x| x.range.begin);
|
||||||
|
|
||||||
|
Ok(Functions {
|
||||||
|
functions: functions.into_boxed_slice(),
|
||||||
|
addresses: addresses.into_boxed_slice(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn find_address(&self, probe: u64) -> Option<usize> {
|
||||||
|
self.addresses
|
||||||
|
.binary_search_by(|address| {
|
||||||
|
if probe < address.range.begin {
|
||||||
|
Ordering::Greater
|
||||||
|
} else if probe >= address.range.end {
|
||||||
|
Ordering::Less
|
||||||
|
} else {
|
||||||
|
Ordering::Equal
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn parse_inlined_functions(
|
||||||
|
&self,
|
||||||
|
file: DebugFile,
|
||||||
|
unit: &gimli::Unit<R>,
|
||||||
|
ctx: &Context<R>,
|
||||||
|
sections: &gimli::Dwarf<R>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
for function in &*self.functions {
|
||||||
|
function
|
||||||
|
.1
|
||||||
|
.borrow_with(|| Function::parse(function.0, file, unit, ctx, sections))
|
||||||
|
.as_ref()
|
||||||
|
.map_err(Error::clone)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R: gimli::Reader> Function<R> {
|
||||||
|
pub(crate) fn parse(
|
||||||
|
dw_die_offset: gimli::UnitOffset<R::Offset>,
|
||||||
|
file: DebugFile,
|
||||||
|
unit: &gimli::Unit<R>,
|
||||||
|
ctx: &Context<R>,
|
||||||
|
sections: &gimli::Dwarf<R>,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
let mut entries = unit.entries_raw(Some(dw_die_offset))?;
|
||||||
|
let depth = entries.next_depth();
|
||||||
|
let abbrev = entries.read_abbreviation()?.unwrap();
|
||||||
|
debug_assert_eq!(abbrev.tag(), gimli::DW_TAG_subprogram);
|
||||||
|
|
||||||
|
let mut name = None;
|
||||||
|
for spec in abbrev.attributes() {
|
||||||
|
match entries.read_attribute(*spec) {
|
||||||
|
Ok(ref attr) => {
|
||||||
|
match attr.name() {
|
||||||
|
gimli::DW_AT_linkage_name | gimli::DW_AT_MIPS_linkage_name => {
|
||||||
|
if let Ok(val) = sections.attr_string(unit, attr.value()) {
|
||||||
|
name = Some(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gimli::DW_AT_name => {
|
||||||
|
if name.is_none() {
|
||||||
|
name = sections.attr_string(unit, attr.value()).ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gimli::DW_AT_abstract_origin | gimli::DW_AT_specification => {
|
||||||
|
if name.is_none() {
|
||||||
|
name = name_attr(attr.value(), file, unit, ctx, sections, 16)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut inlined_functions = Vec::new();
|
||||||
|
let mut inlined_addresses = Vec::new();
|
||||||
|
Function::parse_children(
|
||||||
|
&mut entries,
|
||||||
|
depth,
|
||||||
|
file,
|
||||||
|
unit,
|
||||||
|
ctx,
|
||||||
|
sections,
|
||||||
|
&mut inlined_functions,
|
||||||
|
&mut inlined_addresses,
|
||||||
|
0,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// Sort ranges in "breadth-first traversal order", i.e. first by call_depth
|
||||||
|
// and then by range.begin. This allows finding the range containing an
|
||||||
|
// address at a certain depth using binary search.
|
||||||
|
// Note: Using DFS order, i.e. ordering by range.begin first and then by
|
||||||
|
// call_depth, would not work! Consider the two examples
|
||||||
|
// "[0..10 at depth 0], [0..2 at depth 1], [6..8 at depth 1]" and
|
||||||
|
// "[0..5 at depth 0], [0..2 at depth 1], [5..10 at depth 0], [6..8 at depth 1]".
|
||||||
|
// In this example, if you want to look up address 7 at depth 0, and you
|
||||||
|
// encounter [0..2 at depth 1], are you before or after the target range?
|
||||||
|
// You don't know.
|
||||||
|
inlined_addresses.sort_by(|r1, r2| {
|
||||||
|
if r1.call_depth < r2.call_depth {
|
||||||
|
Ordering::Less
|
||||||
|
} else if r1.call_depth > r2.call_depth {
|
||||||
|
Ordering::Greater
|
||||||
|
} else if r1.range.begin < r2.range.begin {
|
||||||
|
Ordering::Less
|
||||||
|
} else if r1.range.begin > r2.range.begin {
|
||||||
|
Ordering::Greater
|
||||||
|
} else {
|
||||||
|
Ordering::Equal
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(Function {
|
||||||
|
dw_die_offset,
|
||||||
|
name,
|
||||||
|
inlined_functions: inlined_functions.into_boxed_slice(),
|
||||||
|
inlined_addresses: inlined_addresses.into_boxed_slice(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_children(
|
||||||
|
entries: &mut gimli::EntriesRaw<'_, '_, R>,
|
||||||
|
depth: isize,
|
||||||
|
file: DebugFile,
|
||||||
|
unit: &gimli::Unit<R>,
|
||||||
|
ctx: &Context<R>,
|
||||||
|
sections: &gimli::Dwarf<R>,
|
||||||
|
inlined_functions: &mut Vec<InlinedFunction<R>>,
|
||||||
|
inlined_addresses: &mut Vec<InlinedFunctionAddress>,
|
||||||
|
inlined_depth: usize,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
loop {
|
||||||
|
let dw_die_offset = entries.next_offset();
|
||||||
|
let next_depth = entries.next_depth();
|
||||||
|
if next_depth <= depth {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
if let Some(abbrev) = entries.read_abbreviation()? {
|
||||||
|
match abbrev.tag() {
|
||||||
|
gimli::DW_TAG_subprogram => {
|
||||||
|
Function::skip(entries, abbrev, next_depth)?;
|
||||||
|
}
|
||||||
|
gimli::DW_TAG_inlined_subroutine => {
|
||||||
|
InlinedFunction::parse(
|
||||||
|
dw_die_offset,
|
||||||
|
entries,
|
||||||
|
abbrev,
|
||||||
|
next_depth,
|
||||||
|
file,
|
||||||
|
unit,
|
||||||
|
ctx,
|
||||||
|
sections,
|
||||||
|
inlined_functions,
|
||||||
|
inlined_addresses,
|
||||||
|
inlined_depth,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
entries.skip_attributes(abbrev.attributes())?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn skip(
|
||||||
|
entries: &mut gimli::EntriesRaw<'_, '_, R>,
|
||||||
|
abbrev: &gimli::Abbreviation,
|
||||||
|
depth: isize,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
// TODO: use DW_AT_sibling
|
||||||
|
entries.skip_attributes(abbrev.attributes())?;
|
||||||
|
while entries.next_depth() > depth {
|
||||||
|
if let Some(abbrev) = entries.read_abbreviation()? {
|
||||||
|
entries.skip_attributes(abbrev.attributes())?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Build the list of inlined functions that contain `probe`.
|
||||||
|
pub(crate) fn find_inlined_functions(
|
||||||
|
&self,
|
||||||
|
probe: u64,
|
||||||
|
) -> iter::Rev<maybe_small::IntoIter<&InlinedFunction<R>>> {
|
||||||
|
// `inlined_functions` is ordered from outside to inside.
|
||||||
|
let mut inlined_functions = maybe_small::Vec::new();
|
||||||
|
let mut inlined_addresses = &self.inlined_addresses[..];
|
||||||
|
loop {
|
||||||
|
let current_depth = inlined_functions.len();
|
||||||
|
// Look up (probe, current_depth) in inline_ranges.
|
||||||
|
// `inlined_addresses` is sorted in "breadth-first traversal order", i.e.
|
||||||
|
// by `call_depth` first, and then by `range.begin`. See the comment at
|
||||||
|
// the sort call for more information about why.
|
||||||
|
let search = inlined_addresses.binary_search_by(|range| {
|
||||||
|
if range.call_depth > current_depth {
|
||||||
|
Ordering::Greater
|
||||||
|
} else if range.call_depth < current_depth {
|
||||||
|
Ordering::Less
|
||||||
|
} else if range.range.begin > probe {
|
||||||
|
Ordering::Greater
|
||||||
|
} else if range.range.end <= probe {
|
||||||
|
Ordering::Less
|
||||||
|
} else {
|
||||||
|
Ordering::Equal
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if let Ok(index) = search {
|
||||||
|
let function_index = inlined_addresses[index].function;
|
||||||
|
inlined_functions.push(&self.inlined_functions[function_index]);
|
||||||
|
inlined_addresses = &inlined_addresses[index + 1..];
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inlined_functions.into_iter().rev()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R: gimli::Reader> InlinedFunction<R> {
|
||||||
|
fn parse(
|
||||||
|
dw_die_offset: gimli::UnitOffset<R::Offset>,
|
||||||
|
entries: &mut gimli::EntriesRaw<'_, '_, R>,
|
||||||
|
abbrev: &gimli::Abbreviation,
|
||||||
|
depth: isize,
|
||||||
|
file: DebugFile,
|
||||||
|
unit: &gimli::Unit<R>,
|
||||||
|
ctx: &Context<R>,
|
||||||
|
sections: &gimli::Dwarf<R>,
|
||||||
|
inlined_functions: &mut Vec<InlinedFunction<R>>,
|
||||||
|
inlined_addresses: &mut Vec<InlinedFunctionAddress>,
|
||||||
|
inlined_depth: usize,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let mut ranges = RangeAttributes::default();
|
||||||
|
let mut name = None;
|
||||||
|
let mut call_file = None;
|
||||||
|
let mut call_line = 0;
|
||||||
|
let mut call_column = 0;
|
||||||
|
for spec in abbrev.attributes() {
|
||||||
|
match entries.read_attribute(*spec) {
|
||||||
|
Ok(ref attr) => match attr.name() {
|
||||||
|
gimli::DW_AT_low_pc => match attr.value() {
|
||||||
|
gimli::AttributeValue::Addr(val) => ranges.low_pc = Some(val),
|
||||||
|
gimli::AttributeValue::DebugAddrIndex(index) => {
|
||||||
|
ranges.low_pc = Some(sections.address(unit, index)?);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
gimli::DW_AT_high_pc => match attr.value() {
|
||||||
|
gimli::AttributeValue::Addr(val) => ranges.high_pc = Some(val),
|
||||||
|
gimli::AttributeValue::DebugAddrIndex(index) => {
|
||||||
|
ranges.high_pc = Some(sections.address(unit, index)?);
|
||||||
|
}
|
||||||
|
gimli::AttributeValue::Udata(val) => ranges.size = Some(val),
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
gimli::DW_AT_ranges => {
|
||||||
|
ranges.ranges_offset = sections.attr_ranges_offset(unit, attr.value())?;
|
||||||
|
}
|
||||||
|
gimli::DW_AT_linkage_name | gimli::DW_AT_MIPS_linkage_name => {
|
||||||
|
if let Ok(val) = sections.attr_string(unit, attr.value()) {
|
||||||
|
name = Some(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gimli::DW_AT_name => {
|
||||||
|
if name.is_none() {
|
||||||
|
name = sections.attr_string(unit, attr.value()).ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gimli::DW_AT_abstract_origin | gimli::DW_AT_specification => {
|
||||||
|
if name.is_none() {
|
||||||
|
name = name_attr(attr.value(), file, unit, ctx, sections, 16)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gimli::DW_AT_call_file => {
|
||||||
|
// There is a spec issue [1] with how DW_AT_call_file is specified in DWARF 5.
|
||||||
|
// Before, a file index of 0 would indicate no source file, however in
|
||||||
|
// DWARF 5 this could be a valid index into the file table.
|
||||||
|
//
|
||||||
|
// Implementations such as LLVM generates a file index of 0 when DWARF 5 is
|
||||||
|
// used.
|
||||||
|
//
|
||||||
|
// Thus, if we see a version of 5 or later, treat a file index of 0 as such.
|
||||||
|
// [1]: http://wiki.dwarfstd.org/index.php?title=DWARF5_Line_Table_File_Numbers
|
||||||
|
if let gimli::AttributeValue::FileIndex(fi) = attr.value() {
|
||||||
|
if fi > 0 || unit.header.version() >= 5 {
|
||||||
|
call_file = Some(fi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gimli::DW_AT_call_line => {
|
||||||
|
call_line = attr.udata_value().unwrap_or(0) as u32;
|
||||||
|
}
|
||||||
|
gimli::DW_AT_call_column => {
|
||||||
|
call_column = attr.udata_value().unwrap_or(0) as u32;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let function_index = inlined_functions.len();
|
||||||
|
inlined_functions.push(InlinedFunction {
|
||||||
|
dw_die_offset,
|
||||||
|
name,
|
||||||
|
call_file,
|
||||||
|
call_line,
|
||||||
|
call_column,
|
||||||
|
});
|
||||||
|
|
||||||
|
ranges.for_each_range(sections, unit, |range| {
|
||||||
|
inlined_addresses.push(InlinedFunctionAddress {
|
||||||
|
range,
|
||||||
|
call_depth: inlined_depth,
|
||||||
|
function: function_index,
|
||||||
|
});
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Function::parse_children(
|
||||||
|
entries,
|
||||||
|
depth,
|
||||||
|
file,
|
||||||
|
unit,
|
||||||
|
ctx,
|
||||||
|
sections,
|
||||||
|
inlined_functions,
|
||||||
|
inlined_addresses,
|
||||||
|
inlined_depth + 1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn name_attr<R>(
|
||||||
|
attr: gimli::AttributeValue<R>,
|
||||||
|
mut file: DebugFile,
|
||||||
|
unit: &gimli::Unit<R>,
|
||||||
|
ctx: &Context<R>,
|
||||||
|
sections: &gimli::Dwarf<R>,
|
||||||
|
recursion_limit: usize,
|
||||||
|
) -> Result<Option<R>, Error>
|
||||||
|
where
|
||||||
|
R: gimli::Reader,
|
||||||
|
{
|
||||||
|
if recursion_limit == 0 {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
match attr {
|
||||||
|
gimli::AttributeValue::UnitRef(offset) => {
|
||||||
|
name_entry(file, unit, offset, ctx, sections, recursion_limit)
|
||||||
|
}
|
||||||
|
gimli::AttributeValue::DebugInfoRef(dr) => {
|
||||||
|
let (unit, offset) = ctx.find_unit(dr, file)?;
|
||||||
|
name_entry(file, unit, offset, ctx, sections, recursion_limit)
|
||||||
|
}
|
||||||
|
gimli::AttributeValue::DebugInfoRefSup(dr) => {
|
||||||
|
if let Some(sup_sections) = sections.sup.as_ref() {
|
||||||
|
file = DebugFile::Supplementary;
|
||||||
|
let (unit, offset) = ctx.find_unit(dr, file)?;
|
||||||
|
name_entry(file, unit, offset, ctx, sup_sections, recursion_limit)
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => Ok(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn name_entry<R>(
|
||||||
|
file: DebugFile,
|
||||||
|
unit: &gimli::Unit<R>,
|
||||||
|
offset: gimli::UnitOffset<R::Offset>,
|
||||||
|
ctx: &Context<R>,
|
||||||
|
sections: &gimli::Dwarf<R>,
|
||||||
|
recursion_limit: usize,
|
||||||
|
) -> Result<Option<R>, Error>
|
||||||
|
where
|
||||||
|
R: gimli::Reader,
|
||||||
|
{
|
||||||
|
let mut entries = unit.entries_raw(Some(offset))?;
|
||||||
|
let abbrev = if let Some(abbrev) = entries.read_abbreviation()? {
|
||||||
|
abbrev
|
||||||
|
} else {
|
||||||
|
return Err(gimli::Error::NoEntryAtGivenOffset);
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut name = None;
|
||||||
|
let mut next = None;
|
||||||
|
for spec in abbrev.attributes() {
|
||||||
|
match entries.read_attribute(*spec) {
|
||||||
|
Ok(ref attr) => match attr.name() {
|
||||||
|
gimli::DW_AT_linkage_name | gimli::DW_AT_MIPS_linkage_name => {
|
||||||
|
if let Ok(val) = sections.attr_string(unit, attr.value()) {
|
||||||
|
return Ok(Some(val));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gimli::DW_AT_name => {
|
||||||
|
if let Ok(val) = sections.attr_string(unit, attr.value()) {
|
||||||
|
name = Some(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gimli::DW_AT_abstract_origin | gimli::DW_AT_specification => {
|
||||||
|
next = Some(attr.value());
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if name.is_some() {
|
||||||
|
return Ok(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(next) = next {
|
||||||
|
return name_attr(next, file, unit, ctx, sections, recursion_limit - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
}
|
31
vendor/addr2line/src/lazy.rs
vendored
Normal file
31
vendor/addr2line/src/lazy.rs
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
use core::cell::UnsafeCell;
|
||||||
|
|
||||||
|
pub struct LazyCell<T> {
|
||||||
|
contents: UnsafeCell<Option<T>>,
|
||||||
|
}
|
||||||
|
impl<T> LazyCell<T> {
|
||||||
|
pub fn new() -> LazyCell<T> {
|
||||||
|
LazyCell {
|
||||||
|
contents: UnsafeCell::new(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn borrow(&self) -> Option<&T> {
|
||||||
|
unsafe { &*self.contents.get() }.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn borrow_with(&self, closure: impl FnOnce() -> T) -> &T {
|
||||||
|
// First check if we're already initialized...
|
||||||
|
let ptr = self.contents.get();
|
||||||
|
if let Some(val) = unsafe { &*ptr } {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
// Note that while we're executing `closure` our `borrow_with` may
|
||||||
|
// be called recursively. This means we need to check again after
|
||||||
|
// the closure has executed. For that we use the `get_or_insert`
|
||||||
|
// method which will only perform mutation if we aren't already
|
||||||
|
// `Some`.
|
||||||
|
let val = closure();
|
||||||
|
unsafe { (*ptr).get_or_insert(val) }
|
||||||
|
}
|
||||||
|
}
|
1729
vendor/addr2line/src/lib.rs
vendored
Normal file
1729
vendor/addr2line/src/lib.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
126
vendor/addr2line/tests/correctness.rs
vendored
Normal file
126
vendor/addr2line/tests/correctness.rs
vendored
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
use addr2line::Context;
|
||||||
|
use fallible_iterator::FallibleIterator;
|
||||||
|
use findshlibs::{IterationControl, SharedLibrary, TargetSharedLibrary};
|
||||||
|
use object::Object;
|
||||||
|
use std::borrow::Cow;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
fn find_debuginfo() -> memmap2::Mmap {
|
||||||
|
let path = std::env::current_exe().unwrap();
|
||||||
|
let file = File::open(&path).unwrap();
|
||||||
|
let map = unsafe { memmap2::Mmap::map(&file).unwrap() };
|
||||||
|
let file = &object::File::parse(&*map).unwrap();
|
||||||
|
if let Ok(uuid) = file.mach_uuid() {
|
||||||
|
for candidate in path.parent().unwrap().read_dir().unwrap() {
|
||||||
|
let path = candidate.unwrap().path();
|
||||||
|
if !path.to_str().unwrap().ends_with(".dSYM") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for candidate in path.join("Contents/Resources/DWARF").read_dir().unwrap() {
|
||||||
|
let path = candidate.unwrap().path();
|
||||||
|
let file = File::open(&path).unwrap();
|
||||||
|
let map = unsafe { memmap2::Mmap::map(&file).unwrap() };
|
||||||
|
let file = &object::File::parse(&*map).unwrap();
|
||||||
|
if file.mach_uuid().unwrap() == uuid {
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn correctness() {
|
||||||
|
let map = find_debuginfo();
|
||||||
|
let file = &object::File::parse(&*map).unwrap();
|
||||||
|
let module_base = file.relative_address_base();
|
||||||
|
|
||||||
|
let endian = if file.is_little_endian() {
|
||||||
|
gimli::RunTimeEndian::Little
|
||||||
|
} else {
|
||||||
|
gimli::RunTimeEndian::Big
|
||||||
|
};
|
||||||
|
|
||||||
|
fn load_section<'data: 'file, 'file, O, Endian>(
|
||||||
|
id: gimli::SectionId,
|
||||||
|
file: &'file O,
|
||||||
|
endian: Endian,
|
||||||
|
) -> Result<gimli::EndianArcSlice<Endian>, gimli::Error>
|
||||||
|
where
|
||||||
|
O: object::Object<'data, 'file>,
|
||||||
|
Endian: gimli::Endianity,
|
||||||
|
{
|
||||||
|
use object::ObjectSection;
|
||||||
|
|
||||||
|
let data = file
|
||||||
|
.section_by_name(id.name())
|
||||||
|
.and_then(|section| section.uncompressed_data().ok())
|
||||||
|
.unwrap_or(Cow::Borrowed(&[]));
|
||||||
|
Ok(gimli::EndianArcSlice::new(Arc::from(&*data), endian))
|
||||||
|
}
|
||||||
|
|
||||||
|
let dwarf = gimli::Dwarf::load(|id| load_section(id, file, endian)).unwrap();
|
||||||
|
let ctx = Context::from_dwarf(dwarf).unwrap();
|
||||||
|
let mut split_dwarf_loader = addr2line::builtin_split_dwarf_loader::SplitDwarfLoader::new(
|
||||||
|
|data, endian| gimli::EndianArcSlice::new(Arc::from(&*data), endian),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut bias = None;
|
||||||
|
TargetSharedLibrary::each(|lib| {
|
||||||
|
bias = Some((lib.virtual_memory_bias().0 as u64).wrapping_sub(module_base));
|
||||||
|
IterationControl::Break
|
||||||
|
});
|
||||||
|
|
||||||
|
#[allow(unused_mut)]
|
||||||
|
let mut test = |sym: u64, expected_prefix: &str| {
|
||||||
|
let ip = sym.wrapping_sub(bias.unwrap());
|
||||||
|
|
||||||
|
let frames = ctx.find_frames(ip);
|
||||||
|
let frames = split_dwarf_loader.run(frames).unwrap();
|
||||||
|
let frame = frames.last().unwrap().unwrap();
|
||||||
|
let name = frame.function.as_ref().unwrap().demangle().unwrap();
|
||||||
|
// Old rust versions generate DWARF with wrong linkage name,
|
||||||
|
// so only check the start.
|
||||||
|
if !name.starts_with(expected_prefix) {
|
||||||
|
panic!("incorrect name '{}', expected {:?}", name, expected_prefix);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
test(test_function as u64, "correctness::test_function");
|
||||||
|
test(
|
||||||
|
small::test_function as u64,
|
||||||
|
"correctness::small::test_function",
|
||||||
|
);
|
||||||
|
test(auxiliary::foo as u64, "auxiliary::foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
mod small {
|
||||||
|
pub fn test_function() {
|
||||||
|
println!("y");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_function() {
|
||||||
|
println!("x");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn zero_function() {
|
||||||
|
let map = find_debuginfo();
|
||||||
|
let file = &object::File::parse(&*map).unwrap();
|
||||||
|
let ctx = Context::new(file).unwrap();
|
||||||
|
for probe in 0..10 {
|
||||||
|
assert!(
|
||||||
|
ctx.find_frames(probe)
|
||||||
|
.skip_all_loads()
|
||||||
|
.unwrap()
|
||||||
|
.count()
|
||||||
|
.unwrap()
|
||||||
|
< 10
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
135
vendor/addr2line/tests/output_equivalence.rs
vendored
Normal file
135
vendor/addr2line/tests/output_equivalence.rs
vendored
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
use std::env;
|
||||||
|
use std::ffi::OsStr;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
use backtrace::Backtrace;
|
||||||
|
use findshlibs::{IterationControl, SharedLibrary, TargetSharedLibrary};
|
||||||
|
use libtest_mimic::{Arguments, Failed, Trial};
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
fn make_trace() -> Vec<String> {
|
||||||
|
fn foo() -> Backtrace {
|
||||||
|
bar()
|
||||||
|
}
|
||||||
|
#[inline(never)]
|
||||||
|
fn bar() -> Backtrace {
|
||||||
|
baz()
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn baz() -> Backtrace {
|
||||||
|
Backtrace::new_unresolved()
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut base_addr = None;
|
||||||
|
TargetSharedLibrary::each(|lib| {
|
||||||
|
base_addr = Some(lib.virtual_memory_bias().0 as isize);
|
||||||
|
IterationControl::Break
|
||||||
|
});
|
||||||
|
let addrfix = -base_addr.unwrap();
|
||||||
|
|
||||||
|
let trace = foo();
|
||||||
|
trace
|
||||||
|
.frames()
|
||||||
|
.iter()
|
||||||
|
.take(5)
|
||||||
|
.map(|x| format!("{:p}", (x.ip() as *const u8).wrapping_offset(addrfix)))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_cmd<P: AsRef<OsStr>>(exe: P, me: &Path, flags: Option<&str>, trace: &str) -> String {
|
||||||
|
let mut cmd = Command::new(exe);
|
||||||
|
cmd.env("LC_ALL", "C"); // GNU addr2line is localized, we aren't
|
||||||
|
cmd.env("RUST_BACKTRACE", "1"); // if a child crashes, we want to know why
|
||||||
|
|
||||||
|
if let Some(flags) = flags {
|
||||||
|
cmd.arg(flags);
|
||||||
|
}
|
||||||
|
cmd.arg("--exe").arg(me).arg(trace);
|
||||||
|
|
||||||
|
let output = cmd.output().unwrap();
|
||||||
|
|
||||||
|
assert!(output.status.success());
|
||||||
|
String::from_utf8(output.stdout).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_test(flags: Option<&str>) -> Result<(), Failed> {
|
||||||
|
let me = env::current_exe().unwrap();
|
||||||
|
let mut exe = me.clone();
|
||||||
|
assert!(exe.pop());
|
||||||
|
if exe.file_name().unwrap().to_str().unwrap() == "deps" {
|
||||||
|
assert!(exe.pop());
|
||||||
|
}
|
||||||
|
exe.push("examples");
|
||||||
|
exe.push("addr2line");
|
||||||
|
|
||||||
|
assert!(exe.is_file());
|
||||||
|
|
||||||
|
let trace = make_trace();
|
||||||
|
|
||||||
|
// HACK: GNU addr2line has a bug where looking up multiple addresses can cause the second
|
||||||
|
// lookup to fail. Workaround by doing one address at a time.
|
||||||
|
for addr in &trace {
|
||||||
|
let theirs = run_cmd("addr2line", &me, flags, addr);
|
||||||
|
let ours = run_cmd(&exe, &me, flags, addr);
|
||||||
|
|
||||||
|
// HACK: GNU addr2line does not tidy up paths properly, causing double slashes to be printed.
|
||||||
|
// We consider our behavior to be correct, so we fix their output to match ours.
|
||||||
|
let theirs = theirs.replace("//", "/");
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
theirs == ours,
|
||||||
|
"Output not equivalent:
|
||||||
|
|
||||||
|
$ addr2line {0} --exe {1} {2}
|
||||||
|
{4}
|
||||||
|
$ {3} {0} --exe {1} {2}
|
||||||
|
{5}
|
||||||
|
|
||||||
|
|
||||||
|
",
|
||||||
|
flags.unwrap_or(""),
|
||||||
|
me.display(),
|
||||||
|
trace.join(" "),
|
||||||
|
exe.display(),
|
||||||
|
theirs,
|
||||||
|
ours
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
static FLAGS: &str = "aipsf";
|
||||||
|
|
||||||
|
fn make_tests() -> Vec<Trial> {
|
||||||
|
(0..(1 << FLAGS.len()))
|
||||||
|
.map(|bits| {
|
||||||
|
if bits == 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let mut param = String::new();
|
||||||
|
param.push('-');
|
||||||
|
for (i, flag) in FLAGS.chars().enumerate() {
|
||||||
|
if (bits & (1 << i)) != 0 {
|
||||||
|
param.push(flag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(param)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.map(|param| {
|
||||||
|
Trial::test(
|
||||||
|
format!("addr2line {}", param.as_ref().map_or("", String::as_str)),
|
||||||
|
move || run_test(param.as_ref().map(String::as_str)),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
if !cfg!(target_os = "linux") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let args = Arguments::from_args();
|
||||||
|
libtest_mimic::run(&args, make_tests()).exit();
|
||||||
|
}
|
114
vendor/addr2line/tests/parse.rs
vendored
Normal file
114
vendor/addr2line/tests/parse.rs
vendored
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
use std::borrow::Cow;
|
||||||
|
use std::env;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::path::{self, PathBuf};
|
||||||
|
|
||||||
|
use object::Object;
|
||||||
|
|
||||||
|
fn release_fixture_path() -> PathBuf {
|
||||||
|
if let Ok(p) = env::var("ADDR2LINE_FIXTURE_PATH") {
|
||||||
|
return p.into();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut path = PathBuf::new();
|
||||||
|
if let Ok(dir) = env::var("CARGO_MANIFEST_DIR") {
|
||||||
|
path.push(dir);
|
||||||
|
}
|
||||||
|
path.push("fixtures");
|
||||||
|
path.push("addr2line-release");
|
||||||
|
path
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_file<F: FnOnce(&object::File<'_>)>(target: &path::Path, f: F) {
|
||||||
|
let file = File::open(target).unwrap();
|
||||||
|
let map = unsafe { memmap2::Mmap::map(&file).unwrap() };
|
||||||
|
let file = object::File::parse(&*map).unwrap();
|
||||||
|
f(&file)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dwarf_load<'a>(object: &object::File<'a>) -> gimli::Dwarf<Cow<'a, [u8]>> {
|
||||||
|
let load_section = |id: gimli::SectionId| -> Result<Cow<'a, [u8]>, gimli::Error> {
|
||||||
|
use object::ObjectSection;
|
||||||
|
|
||||||
|
let data = object
|
||||||
|
.section_by_name(id.name())
|
||||||
|
.and_then(|section| section.data().ok())
|
||||||
|
.unwrap_or(&[][..]);
|
||||||
|
Ok(Cow::Borrowed(data))
|
||||||
|
};
|
||||||
|
gimli::Dwarf::load(&load_section).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dwarf_borrow<'a>(
|
||||||
|
dwarf: &'a gimli::Dwarf<Cow<'_, [u8]>>,
|
||||||
|
) -> gimli::Dwarf<gimli::EndianSlice<'a, gimli::LittleEndian>> {
|
||||||
|
let borrow_section: &dyn for<'b> Fn(
|
||||||
|
&'b Cow<'_, [u8]>,
|
||||||
|
) -> gimli::EndianSlice<'b, gimli::LittleEndian> =
|
||||||
|
&|section| gimli::EndianSlice::new(section, gimli::LittleEndian);
|
||||||
|
dwarf.borrow(&borrow_section)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_base_rc() {
|
||||||
|
let target = release_fixture_path();
|
||||||
|
|
||||||
|
with_file(&target, |file| {
|
||||||
|
addr2line::ObjectContext::new(file).unwrap();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_base_slice() {
|
||||||
|
let target = release_fixture_path();
|
||||||
|
|
||||||
|
with_file(&target, |file| {
|
||||||
|
let dwarf = dwarf_load(file);
|
||||||
|
let dwarf = dwarf_borrow(&dwarf);
|
||||||
|
addr2line::Context::from_dwarf(dwarf).unwrap();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_lines_rc() {
|
||||||
|
let target = release_fixture_path();
|
||||||
|
|
||||||
|
with_file(&target, |file| {
|
||||||
|
let context = addr2line::ObjectContext::new(file).unwrap();
|
||||||
|
context.parse_lines().unwrap();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_lines_slice() {
|
||||||
|
let target = release_fixture_path();
|
||||||
|
|
||||||
|
with_file(&target, |file| {
|
||||||
|
let dwarf = dwarf_load(file);
|
||||||
|
let dwarf = dwarf_borrow(&dwarf);
|
||||||
|
let context = addr2line::Context::from_dwarf(dwarf).unwrap();
|
||||||
|
context.parse_lines().unwrap();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_functions_rc() {
|
||||||
|
let target = release_fixture_path();
|
||||||
|
|
||||||
|
with_file(&target, |file| {
|
||||||
|
let context = addr2line::ObjectContext::new(file).unwrap();
|
||||||
|
context.parse_functions().unwrap();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_functions_slice() {
|
||||||
|
let target = release_fixture_path();
|
||||||
|
|
||||||
|
with_file(&target, |file| {
|
||||||
|
let dwarf = dwarf_load(file);
|
||||||
|
let dwarf = dwarf_borrow(&dwarf);
|
||||||
|
let context = addr2line::Context::from_dwarf(dwarf).unwrap();
|
||||||
|
context.parse_functions().unwrap();
|
||||||
|
});
|
||||||
|
}
|
1
vendor/adler/.cargo-checksum.json
vendored
Normal file
1
vendor/adler/.cargo-checksum.json
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"files":{"CHANGELOG.md":"737088e45fdf27fe2cfedce163332d8ce08c58fd86ca287de2de34c0fbaf63e7","Cargo.toml":"f410869f0f1a5697f65a8a77be03da7aeecc0be26e7cf3a1feb1acaa4f518770","LICENSE-0BSD":"861399f8c21c042b110517e76dc6b63a2b334276c8cf17412fc3c8908ca8dc17","LICENSE-APACHE":"8ada45cd9f843acf64e4722ae262c622a2b3b3007c7310ef36ac1061a30f6adb","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"308c50cdb42b9573743068158339570b45ca3f895015ca3b87ba983edb0a21e6","RELEASE_PROCESS.md":"a86cd10fc70f167f8d00e9e4ce0c6b4ebdfa1865058390dffd1e0ad4d3e68d9d","benches/bench.rs":"c07ce370e3680c602e415f8d1ec4e543ea2163ab22a09b6b82d93e8a30adca82","src/algo.rs":"b664b131f724a809591394a10b9023f40ab5963e32a83fa3163c2668e59c8b66","src/lib.rs":"b55ba9c629b30360d08168b2ca0c96275432856a539737a105a6d6ae6bf7e88f"},"package":"f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"}
|
63
vendor/adler/CHANGELOG.md
vendored
Normal file
63
vendor/adler/CHANGELOG.md
vendored
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
No changes.
|
||||||
|
|
||||||
|
## [1.0.2 - 2021-02-26](https://github.com/jonas-schievink/adler/releases/tag/v1.0.2)
|
||||||
|
|
||||||
|
- Fix doctest on big-endian systems ([#9]).
|
||||||
|
|
||||||
|
[#9]: https://github.com/jonas-schievink/adler/pull/9
|
||||||
|
|
||||||
|
## [1.0.1 - 2020-11-08](https://github.com/jonas-schievink/adler/releases/tag/v1.0.1)
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
- Fix documentation on docs.rs.
|
||||||
|
|
||||||
|
## [1.0.0 - 2020-11-08](https://github.com/jonas-schievink/adler/releases/tag/v1.0.0)
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
- Fix `cargo test --no-default-features` ([#5]).
|
||||||
|
|
||||||
|
### Improvements
|
||||||
|
|
||||||
|
- Extended and clarified documentation.
|
||||||
|
- Added more rustdoc examples.
|
||||||
|
- Extended CI to test the crate with `--no-default-features`.
|
||||||
|
|
||||||
|
### Breaking Changes
|
||||||
|
|
||||||
|
- `adler32_reader` now takes its generic argument by value instead of as a `&mut`.
|
||||||
|
- Renamed `adler32_reader` to `adler32`.
|
||||||
|
|
||||||
|
## [0.2.3 - 2020-07-11](https://github.com/jonas-schievink/adler/releases/tag/v0.2.3)
|
||||||
|
|
||||||
|
- Process 4 Bytes at a time, improving performance by up to 50% ([#2]).
|
||||||
|
|
||||||
|
## [0.2.2 - 2020-06-27](https://github.com/jonas-schievink/adler/releases/tag/v0.2.2)
|
||||||
|
|
||||||
|
- Bump MSRV to 1.31.0.
|
||||||
|
|
||||||
|
## [0.2.1 - 2020-06-27](https://github.com/jonas-schievink/adler/releases/tag/v0.2.1)
|
||||||
|
|
||||||
|
- Add a few `#[inline]` annotations to small functions.
|
||||||
|
- Fix CI badge.
|
||||||
|
- Allow integration into libstd.
|
||||||
|
|
||||||
|
## [0.2.0 - 2020-06-27](https://github.com/jonas-schievink/adler/releases/tag/v0.2.0)
|
||||||
|
|
||||||
|
- Support `#![no_std]` when using `default-features = false`.
|
||||||
|
- Improve performance by around 7x.
|
||||||
|
- Support Rust 1.8.0.
|
||||||
|
- Improve API naming.
|
||||||
|
|
||||||
|
## [0.1.0 - 2020-06-26](https://github.com/jonas-schievink/adler/releases/tag/v0.1.0)
|
||||||
|
|
||||||
|
Initial release.
|
||||||
|
|
||||||
|
|
||||||
|
[#2]: https://github.com/jonas-schievink/adler/pull/2
|
||||||
|
[#5]: https://github.com/jonas-schievink/adler/pull/5
|
64
vendor/adler/Cargo.toml
vendored
Normal file
64
vendor/adler/Cargo.toml
vendored
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
# 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 believe there's an error in this file please file an
|
||||||
|
# issue against the rust-lang/cargo repository. If you're
|
||||||
|
# editing this file be aware that the upstream Cargo.toml
|
||||||
|
# will likely look very different (and much more reasonable)
|
||||||
|
|
||||||
|
[package]
|
||||||
|
name = "adler"
|
||||||
|
version = "1.0.2"
|
||||||
|
authors = ["Jonas Schievink <jonasschievink@gmail.com>"]
|
||||||
|
description = "A simple clean-room implementation of the Adler-32 checksum"
|
||||||
|
documentation = "https://docs.rs/adler/"
|
||||||
|
readme = "README.md"
|
||||||
|
keywords = ["checksum", "integrity", "hash", "adler32", "zlib"]
|
||||||
|
categories = ["algorithms"]
|
||||||
|
license = "0BSD OR MIT OR Apache-2.0"
|
||||||
|
repository = "https://github.com/jonas-schievink/adler.git"
|
||||||
|
[package.metadata.docs.rs]
|
||||||
|
rustdoc-args = ["--cfg=docsrs"]
|
||||||
|
|
||||||
|
[package.metadata.release]
|
||||||
|
no-dev-version = true
|
||||||
|
pre-release-commit-message = "Release {{version}}"
|
||||||
|
tag-message = "{{version}}"
|
||||||
|
|
||||||
|
[[package.metadata.release.pre-release-replacements]]
|
||||||
|
file = "CHANGELOG.md"
|
||||||
|
replace = "## Unreleased\n\nNo changes.\n\n## [{{version}} - {{date}}](https://github.com/jonas-schievink/adler/releases/tag/v{{version}})\n"
|
||||||
|
search = "## Unreleased\n"
|
||||||
|
|
||||||
|
[[package.metadata.release.pre-release-replacements]]
|
||||||
|
file = "README.md"
|
||||||
|
replace = "adler = \"{{version}}\""
|
||||||
|
search = "adler = \"[a-z0-9\\\\.-]+\""
|
||||||
|
|
||||||
|
[[package.metadata.release.pre-release-replacements]]
|
||||||
|
file = "src/lib.rs"
|
||||||
|
replace = "https://docs.rs/adler/{{version}}"
|
||||||
|
search = "https://docs.rs/adler/[a-z0-9\\.-]+"
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "bench"
|
||||||
|
harness = false
|
||||||
|
[dependencies.compiler_builtins]
|
||||||
|
version = "0.1.2"
|
||||||
|
optional = true
|
||||||
|
|
||||||
|
[dependencies.core]
|
||||||
|
version = "1.0.0"
|
||||||
|
optional = true
|
||||||
|
package = "rustc-std-workspace-core"
|
||||||
|
[dev-dependencies.criterion]
|
||||||
|
version = "0.3.2"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["std"]
|
||||||
|
rustc-dep-of-std = ["core", "compiler_builtins"]
|
||||||
|
std = []
|
12
vendor/adler/LICENSE-0BSD
vendored
Normal file
12
vendor/adler/LICENSE-0BSD
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
Copyright (C) Jonas Schievink <jonasschievink@gmail.com>
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
any purpose with or without fee is hereby granted.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||||
|
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||||
|
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
201
vendor/adler/LICENSE-APACHE
vendored
Normal file
201
vendor/adler/LICENSE-APACHE
vendored
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
https://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.
|
23
vendor/adler/LICENSE-MIT
vendored
Normal file
23
vendor/adler/LICENSE-MIT
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
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.
|
39
vendor/adler/README.md
vendored
Normal file
39
vendor/adler/README.md
vendored
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# Adler-32 checksums for Rust
|
||||||
|
|
||||||
|
[![crates.io](https://img.shields.io/crates/v/adler.svg)](https://crates.io/crates/adler)
|
||||||
|
[![docs.rs](https://docs.rs/adler/badge.svg)](https://docs.rs/adler/)
|
||||||
|
![CI](https://github.com/jonas-schievink/adler/workflows/CI/badge.svg)
|
||||||
|
|
||||||
|
This crate provides a simple implementation of the Adler-32 checksum, used in
|
||||||
|
the zlib compression format.
|
||||||
|
|
||||||
|
Please refer to the [changelog](CHANGELOG.md) to see what changed in the last
|
||||||
|
releases.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Permissively licensed (0BSD) clean-room implementation.
|
||||||
|
- Zero dependencies.
|
||||||
|
- Zero `unsafe`.
|
||||||
|
- Decent performance (3-4 GB/s).
|
||||||
|
- Supports `#![no_std]` (with `default-features = false`).
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Add an entry to your `Cargo.toml`:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[dependencies]
|
||||||
|
adler = "1.0.2"
|
||||||
|
```
|
||||||
|
|
||||||
|
Check the [API Documentation](https://docs.rs/adler/) for how to use the
|
||||||
|
crate's functionality.
|
||||||
|
|
||||||
|
## Rust version support
|
||||||
|
|
||||||
|
Currently, this crate supports all Rust versions starting at Rust 1.31.0.
|
||||||
|
|
||||||
|
Bumping the Minimum Supported Rust Version (MSRV) is *not* considered a breaking
|
||||||
|
change, but will not be done without good reasons. The latest 3 stable Rust
|
||||||
|
versions will always be supported no matter what.
|
13
vendor/adler/RELEASE_PROCESS.md
vendored
Normal file
13
vendor/adler/RELEASE_PROCESS.md
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# What to do to publish a new release
|
||||||
|
|
||||||
|
1. Ensure all notable changes are in the changelog under "Unreleased".
|
||||||
|
|
||||||
|
2. Execute `cargo release <level>` to bump version(s), tag and publish
|
||||||
|
everything. External subcommand, must be installed with `cargo install
|
||||||
|
cargo-release`.
|
||||||
|
|
||||||
|
`<level>` can be one of `major|minor|patch`. If this is the first release
|
||||||
|
(`0.1.0`), use `minor`, since the version starts out as `0.0.0`.
|
||||||
|
|
||||||
|
3. Go to the GitHub releases, edit the just-pushed tag. Copy the release notes
|
||||||
|
from the changelog.
|
109
vendor/adler/benches/bench.rs
vendored
Normal file
109
vendor/adler/benches/bench.rs
vendored
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
extern crate adler;
|
||||||
|
extern crate criterion;
|
||||||
|
|
||||||
|
use adler::{adler32_slice, Adler32};
|
||||||
|
use criterion::{criterion_group, criterion_main, Criterion, Throughput};
|
||||||
|
|
||||||
|
fn simple(c: &mut Criterion) {
|
||||||
|
{
|
||||||
|
const SIZE: usize = 100;
|
||||||
|
|
||||||
|
let mut group = c.benchmark_group("simple-100b");
|
||||||
|
group.throughput(Throughput::Bytes(SIZE as u64));
|
||||||
|
group.bench_function("zeroes-100", |bencher| {
|
||||||
|
bencher.iter(|| {
|
||||||
|
adler32_slice(&[0; SIZE]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
group.bench_function("ones-100", |bencher| {
|
||||||
|
bencher.iter(|| {
|
||||||
|
adler32_slice(&[0xff; SIZE]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const SIZE: usize = 1024;
|
||||||
|
|
||||||
|
let mut group = c.benchmark_group("simple-1k");
|
||||||
|
group.throughput(Throughput::Bytes(SIZE as u64));
|
||||||
|
|
||||||
|
group.bench_function("zeroes-1k", |bencher| {
|
||||||
|
bencher.iter(|| {
|
||||||
|
adler32_slice(&[0; SIZE]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group.bench_function("ones-1k", |bencher| {
|
||||||
|
bencher.iter(|| {
|
||||||
|
adler32_slice(&[0xff; SIZE]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const SIZE: usize = 1024 * 1024;
|
||||||
|
|
||||||
|
let mut group = c.benchmark_group("simple-1m");
|
||||||
|
group.throughput(Throughput::Bytes(SIZE as u64));
|
||||||
|
group.bench_function("zeroes-1m", |bencher| {
|
||||||
|
bencher.iter(|| {
|
||||||
|
adler32_slice(&[0; SIZE]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group.bench_function("ones-1m", |bencher| {
|
||||||
|
bencher.iter(|| {
|
||||||
|
adler32_slice(&[0xff; SIZE]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn chunked(c: &mut Criterion) {
|
||||||
|
const SIZE: usize = 16 * 1024 * 1024;
|
||||||
|
|
||||||
|
let data = vec![0xAB; SIZE];
|
||||||
|
|
||||||
|
let mut group = c.benchmark_group("chunked-16m");
|
||||||
|
group.throughput(Throughput::Bytes(SIZE as u64));
|
||||||
|
group.bench_function("5552", |bencher| {
|
||||||
|
bencher.iter(|| {
|
||||||
|
let mut h = Adler32::new();
|
||||||
|
for chunk in data.chunks(5552) {
|
||||||
|
h.write_slice(chunk);
|
||||||
|
}
|
||||||
|
h.checksum()
|
||||||
|
});
|
||||||
|
});
|
||||||
|
group.bench_function("8k", |bencher| {
|
||||||
|
bencher.iter(|| {
|
||||||
|
let mut h = Adler32::new();
|
||||||
|
for chunk in data.chunks(8 * 1024) {
|
||||||
|
h.write_slice(chunk);
|
||||||
|
}
|
||||||
|
h.checksum()
|
||||||
|
});
|
||||||
|
});
|
||||||
|
group.bench_function("64k", |bencher| {
|
||||||
|
bencher.iter(|| {
|
||||||
|
let mut h = Adler32::new();
|
||||||
|
for chunk in data.chunks(64 * 1024) {
|
||||||
|
h.write_slice(chunk);
|
||||||
|
}
|
||||||
|
h.checksum()
|
||||||
|
});
|
||||||
|
});
|
||||||
|
group.bench_function("1m", |bencher| {
|
||||||
|
bencher.iter(|| {
|
||||||
|
let mut h = Adler32::new();
|
||||||
|
for chunk in data.chunks(1024 * 1024) {
|
||||||
|
h.write_slice(chunk);
|
||||||
|
}
|
||||||
|
h.checksum()
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
criterion_group!(benches, simple, chunked);
|
||||||
|
criterion_main!(benches);
|
146
vendor/adler/src/algo.rs
vendored
Normal file
146
vendor/adler/src/algo.rs
vendored
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
use crate::Adler32;
|
||||||
|
use std::ops::{AddAssign, MulAssign, RemAssign};
|
||||||
|
|
||||||
|
impl Adler32 {
|
||||||
|
pub(crate) fn compute(&mut self, bytes: &[u8]) {
|
||||||
|
// The basic algorithm is, for every byte:
|
||||||
|
// a = (a + byte) % MOD
|
||||||
|
// b = (b + a) % MOD
|
||||||
|
// where MOD = 65521.
|
||||||
|
//
|
||||||
|
// For efficiency, we can defer the `% MOD` operations as long as neither a nor b overflows:
|
||||||
|
// - Between calls to `write`, we ensure that a and b are always in range 0..MOD.
|
||||||
|
// - We use 32-bit arithmetic in this function.
|
||||||
|
// - Therefore, a and b must not increase by more than 2^32-MOD without performing a `% MOD`
|
||||||
|
// operation.
|
||||||
|
//
|
||||||
|
// According to Wikipedia, b is calculated as follows for non-incremental checksumming:
|
||||||
|
// b = n×D1 + (n−1)×D2 + (n−2)×D3 + ... + Dn + n*1 (mod 65521)
|
||||||
|
// Where n is the number of bytes and Di is the i-th Byte. We need to change this to account
|
||||||
|
// for the previous values of a and b, as well as treat every input Byte as being 255:
|
||||||
|
// b_inc = n×255 + (n-1)×255 + ... + 255 + n*65520
|
||||||
|
// Or in other words:
|
||||||
|
// b_inc = n*65520 + n(n+1)/2*255
|
||||||
|
// The max chunk size is thus the largest value of n so that b_inc <= 2^32-65521.
|
||||||
|
// 2^32-65521 = n*65520 + n(n+1)/2*255
|
||||||
|
// Plugging this into an equation solver since I can't math gives n = 5552.18..., so 5552.
|
||||||
|
//
|
||||||
|
// On top of the optimization outlined above, the algorithm can also be parallelized with a
|
||||||
|
// bit more work:
|
||||||
|
//
|
||||||
|
// Note that b is a linear combination of a vector of input bytes (D1, ..., Dn).
|
||||||
|
//
|
||||||
|
// If we fix some value k<N and rewrite indices 1, ..., N as
|
||||||
|
//
|
||||||
|
// 1_1, 1_2, ..., 1_k, 2_1, ..., 2_k, ..., (N/k)_k,
|
||||||
|
//
|
||||||
|
// then we can express a and b in terms of sums of smaller sequences kb and ka:
|
||||||
|
//
|
||||||
|
// ka(j) := D1_j + D2_j + ... + D(N/k)_j where j <= k
|
||||||
|
// kb(j) := (N/k)*D1_j + (N/k-1)*D2_j + ... + D(N/k)_j where j <= k
|
||||||
|
//
|
||||||
|
// a = ka(1) + ka(2) + ... + ka(k) + 1
|
||||||
|
// b = k*(kb(1) + kb(2) + ... + kb(k)) - 1*ka(2) - ... - (k-1)*ka(k) + N
|
||||||
|
//
|
||||||
|
// We use this insight to unroll the main loop and process k=4 bytes at a time.
|
||||||
|
// The resulting code is highly amenable to SIMD acceleration, although the immediate speedups
|
||||||
|
// stem from increased pipeline parallelism rather than auto-vectorization.
|
||||||
|
//
|
||||||
|
// This technique is described in-depth (here:)[https://software.intel.com/content/www/us/\
|
||||||
|
// en/develop/articles/fast-computation-of-fletcher-checksums.html]
|
||||||
|
|
||||||
|
const MOD: u32 = 65521;
|
||||||
|
const CHUNK_SIZE: usize = 5552 * 4;
|
||||||
|
|
||||||
|
let mut a = u32::from(self.a);
|
||||||
|
let mut b = u32::from(self.b);
|
||||||
|
let mut a_vec = U32X4([0; 4]);
|
||||||
|
let mut b_vec = a_vec;
|
||||||
|
|
||||||
|
let (bytes, remainder) = bytes.split_at(bytes.len() - bytes.len() % 4);
|
||||||
|
|
||||||
|
// iterate over 4 bytes at a time
|
||||||
|
let chunk_iter = bytes.chunks_exact(CHUNK_SIZE);
|
||||||
|
let remainder_chunk = chunk_iter.remainder();
|
||||||
|
for chunk in chunk_iter {
|
||||||
|
for byte_vec in chunk.chunks_exact(4) {
|
||||||
|
let val = U32X4::from(byte_vec);
|
||||||
|
a_vec += val;
|
||||||
|
b_vec += a_vec;
|
||||||
|
}
|
||||||
|
b += CHUNK_SIZE as u32 * a;
|
||||||
|
a_vec %= MOD;
|
||||||
|
b_vec %= MOD;
|
||||||
|
b %= MOD;
|
||||||
|
}
|
||||||
|
// special-case the final chunk because it may be shorter than the rest
|
||||||
|
for byte_vec in remainder_chunk.chunks_exact(4) {
|
||||||
|
let val = U32X4::from(byte_vec);
|
||||||
|
a_vec += val;
|
||||||
|
b_vec += a_vec;
|
||||||
|
}
|
||||||
|
b += remainder_chunk.len() as u32 * a;
|
||||||
|
a_vec %= MOD;
|
||||||
|
b_vec %= MOD;
|
||||||
|
b %= MOD;
|
||||||
|
|
||||||
|
// combine the sub-sum results into the main sum
|
||||||
|
b_vec *= 4;
|
||||||
|
b_vec.0[1] += MOD - a_vec.0[1];
|
||||||
|
b_vec.0[2] += (MOD - a_vec.0[2]) * 2;
|
||||||
|
b_vec.0[3] += (MOD - a_vec.0[3]) * 3;
|
||||||
|
for &av in a_vec.0.iter() {
|
||||||
|
a += av;
|
||||||
|
}
|
||||||
|
for &bv in b_vec.0.iter() {
|
||||||
|
b += bv;
|
||||||
|
}
|
||||||
|
|
||||||
|
// iterate over the remaining few bytes in serial
|
||||||
|
for &byte in remainder.iter() {
|
||||||
|
a += u32::from(byte);
|
||||||
|
b += a;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.a = (a % MOD) as u16;
|
||||||
|
self.b = (b % MOD) as u16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
struct U32X4([u32; 4]);
|
||||||
|
|
||||||
|
impl U32X4 {
|
||||||
|
fn from(bytes: &[u8]) -> Self {
|
||||||
|
U32X4([
|
||||||
|
u32::from(bytes[0]),
|
||||||
|
u32::from(bytes[1]),
|
||||||
|
u32::from(bytes[2]),
|
||||||
|
u32::from(bytes[3]),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AddAssign<Self> for U32X4 {
|
||||||
|
fn add_assign(&mut self, other: Self) {
|
||||||
|
for (s, o) in self.0.iter_mut().zip(other.0.iter()) {
|
||||||
|
*s += o;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RemAssign<u32> for U32X4 {
|
||||||
|
fn rem_assign(&mut self, quotient: u32) {
|
||||||
|
for s in self.0.iter_mut() {
|
||||||
|
*s %= quotient;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MulAssign<u32> for U32X4 {
|
||||||
|
fn mul_assign(&mut self, rhs: u32) {
|
||||||
|
for s in self.0.iter_mut() {
|
||||||
|
*s *= rhs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
287
vendor/adler/src/lib.rs
vendored
Normal file
287
vendor/adler/src/lib.rs
vendored
Normal file
@ -0,0 +1,287 @@
|
|||||||
|
//! Adler-32 checksum implementation.
|
||||||
|
//!
|
||||||
|
//! This implementation features:
|
||||||
|
//!
|
||||||
|
//! - Permissively licensed (0BSD) clean-room implementation.
|
||||||
|
//! - Zero dependencies.
|
||||||
|
//! - Zero `unsafe`.
|
||||||
|
//! - Decent performance (3-4 GB/s).
|
||||||
|
//! - `#![no_std]` support (with `default-features = false`).
|
||||||
|
|
||||||
|
#![doc(html_root_url = "https://docs.rs/adler/1.0.2")]
|
||||||
|
// Deny a few warnings in doctests, since rustdoc `allow`s many warnings by default
|
||||||
|
#![doc(test(attr(deny(unused_imports, unused_must_use))))]
|
||||||
|
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||||
|
#![warn(missing_debug_implementations)]
|
||||||
|
#![forbid(unsafe_code)]
|
||||||
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
|
extern crate core as std;
|
||||||
|
|
||||||
|
mod algo;
|
||||||
|
|
||||||
|
use std::hash::Hasher;
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
use std::io::{self, BufRead};
|
||||||
|
|
||||||
|
/// Adler-32 checksum calculator.
|
||||||
|
///
|
||||||
|
/// An instance of this type is equivalent to an Adler-32 checksum: It can be created in the default
|
||||||
|
/// state via [`new`] (or the provided `Default` impl), or from a precalculated checksum via
|
||||||
|
/// [`from_checksum`], and the currently stored checksum can be fetched via [`checksum`].
|
||||||
|
///
|
||||||
|
/// This type also implements `Hasher`, which makes it easy to calculate Adler-32 checksums of any
|
||||||
|
/// type that implements or derives `Hash`. This also allows using Adler-32 in a `HashMap`, although
|
||||||
|
/// that is not recommended (while every checksum is a hash function, they are not necessarily a
|
||||||
|
/// good one).
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Basic, piecewise checksum calculation:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use adler::Adler32;
|
||||||
|
///
|
||||||
|
/// let mut adler = Adler32::new();
|
||||||
|
///
|
||||||
|
/// adler.write_slice(&[0, 1, 2]);
|
||||||
|
/// adler.write_slice(&[3, 4, 5]);
|
||||||
|
///
|
||||||
|
/// assert_eq!(adler.checksum(), 0x00290010);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Using `Hash` to process structures:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::hash::Hash;
|
||||||
|
/// use adler::Adler32;
|
||||||
|
///
|
||||||
|
/// #[derive(Hash)]
|
||||||
|
/// struct Data {
|
||||||
|
/// byte: u8,
|
||||||
|
/// word: u16,
|
||||||
|
/// big: u64,
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// let mut adler = Adler32::new();
|
||||||
|
///
|
||||||
|
/// let data = Data { byte: 0x1F, word: 0xABCD, big: !0 };
|
||||||
|
/// data.hash(&mut adler);
|
||||||
|
///
|
||||||
|
/// // hash value depends on architecture endianness
|
||||||
|
/// if cfg!(target_endian = "little") {
|
||||||
|
/// assert_eq!(adler.checksum(), 0x33410990);
|
||||||
|
/// }
|
||||||
|
/// if cfg!(target_endian = "big") {
|
||||||
|
/// assert_eq!(adler.checksum(), 0x331F0990);
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [`new`]: #method.new
|
||||||
|
/// [`from_checksum`]: #method.from_checksum
|
||||||
|
/// [`checksum`]: #method.checksum
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct Adler32 {
|
||||||
|
a: u16,
|
||||||
|
b: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Adler32 {
|
||||||
|
/// Creates a new Adler-32 instance with default state.
|
||||||
|
#[inline]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates an `Adler32` instance from a precomputed Adler-32 checksum.
|
||||||
|
///
|
||||||
|
/// This allows resuming checksum calculation without having to keep the `Adler32` instance
|
||||||
|
/// around.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use adler::Adler32;
|
||||||
|
/// let parts = [
|
||||||
|
/// "rust",
|
||||||
|
/// "acean",
|
||||||
|
/// ];
|
||||||
|
/// let whole = adler::adler32_slice(b"rustacean");
|
||||||
|
///
|
||||||
|
/// let mut sum = Adler32::new();
|
||||||
|
/// sum.write_slice(parts[0].as_bytes());
|
||||||
|
/// let partial = sum.checksum();
|
||||||
|
///
|
||||||
|
/// // ...later
|
||||||
|
///
|
||||||
|
/// let mut sum = Adler32::from_checksum(partial);
|
||||||
|
/// sum.write_slice(parts[1].as_bytes());
|
||||||
|
/// assert_eq!(sum.checksum(), whole);
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn from_checksum(sum: u32) -> Self {
|
||||||
|
Adler32 {
|
||||||
|
a: sum as u16,
|
||||||
|
b: (sum >> 16) as u16,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the calculated checksum at this point in time.
|
||||||
|
#[inline]
|
||||||
|
pub fn checksum(&self) -> u32 {
|
||||||
|
(u32::from(self.b) << 16) | u32::from(self.a)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds `bytes` to the checksum calculation.
|
||||||
|
///
|
||||||
|
/// If efficiency matters, this should be called with Byte slices that contain at least a few
|
||||||
|
/// thousand Bytes.
|
||||||
|
pub fn write_slice(&mut self, bytes: &[u8]) {
|
||||||
|
self.compute(bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Adler32 {
|
||||||
|
#[inline]
|
||||||
|
fn default() -> Self {
|
||||||
|
Adler32 { a: 1, b: 0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hasher for Adler32 {
|
||||||
|
#[inline]
|
||||||
|
fn finish(&self) -> u64 {
|
||||||
|
u64::from(self.checksum())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&mut self, bytes: &[u8]) {
|
||||||
|
self.write_slice(bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Calculates the Adler-32 checksum of a byte slice.
|
||||||
|
///
|
||||||
|
/// This is a convenience function around the [`Adler32`] type.
|
||||||
|
///
|
||||||
|
/// [`Adler32`]: struct.Adler32.html
|
||||||
|
pub fn adler32_slice(data: &[u8]) -> u32 {
|
||||||
|
let mut h = Adler32::new();
|
||||||
|
h.write_slice(data);
|
||||||
|
h.checksum()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Calculates the Adler-32 checksum of a `BufRead`'s contents.
|
||||||
|
///
|
||||||
|
/// The passed `BufRead` implementor will be read until it reaches EOF (or until it reports an
|
||||||
|
/// error).
|
||||||
|
///
|
||||||
|
/// If you only have a `Read` implementor, you can wrap it in `std::io::BufReader` before calling
|
||||||
|
/// this function.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Any error returned by the reader are bubbled up by this function.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// # fn run() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
/// use adler::adler32;
|
||||||
|
///
|
||||||
|
/// use std::fs::File;
|
||||||
|
/// use std::io::BufReader;
|
||||||
|
///
|
||||||
|
/// let file = File::open("input.txt")?;
|
||||||
|
/// let mut file = BufReader::new(file);
|
||||||
|
///
|
||||||
|
/// adler32(&mut file)?;
|
||||||
|
/// # Ok(()) }
|
||||||
|
/// # fn main() { run().unwrap() }
|
||||||
|
/// ```
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||||
|
pub fn adler32<R: BufRead>(mut reader: R) -> io::Result<u32> {
|
||||||
|
let mut h = Adler32::new();
|
||||||
|
loop {
|
||||||
|
let len = {
|
||||||
|
let buf = reader.fill_buf()?;
|
||||||
|
if buf.is_empty() {
|
||||||
|
return Ok(h.checksum());
|
||||||
|
}
|
||||||
|
|
||||||
|
h.write_slice(buf);
|
||||||
|
buf.len()
|
||||||
|
};
|
||||||
|
reader.consume(len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn zeroes() {
|
||||||
|
assert_eq!(adler32_slice(&[]), 1);
|
||||||
|
assert_eq!(adler32_slice(&[0]), 1 | 1 << 16);
|
||||||
|
assert_eq!(adler32_slice(&[0, 0]), 1 | 2 << 16);
|
||||||
|
assert_eq!(adler32_slice(&[0; 100]), 0x00640001);
|
||||||
|
assert_eq!(adler32_slice(&[0; 1024]), 0x04000001);
|
||||||
|
assert_eq!(adler32_slice(&[0; 1024 * 1024]), 0x00f00001);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ones() {
|
||||||
|
assert_eq!(adler32_slice(&[0xff; 1024]), 0x79a6fc2e);
|
||||||
|
assert_eq!(adler32_slice(&[0xff; 1024 * 1024]), 0x8e88ef11);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn mixed() {
|
||||||
|
assert_eq!(adler32_slice(&[1]), 2 | 2 << 16);
|
||||||
|
assert_eq!(adler32_slice(&[40]), 41 | 41 << 16);
|
||||||
|
|
||||||
|
assert_eq!(adler32_slice(&[0xA5; 1024 * 1024]), 0xd5009ab1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Example calculation from https://en.wikipedia.org/wiki/Adler-32.
|
||||||
|
#[test]
|
||||||
|
fn wiki() {
|
||||||
|
assert_eq!(adler32_slice(b"Wikipedia"), 0x11E60398);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn resume() {
|
||||||
|
let mut adler = Adler32::new();
|
||||||
|
adler.write_slice(&[0xff; 1024]);
|
||||||
|
let partial = adler.checksum();
|
||||||
|
assert_eq!(partial, 0x79a6fc2e); // from above
|
||||||
|
adler.write_slice(&[0xff; 1024 * 1024 - 1024]);
|
||||||
|
assert_eq!(adler.checksum(), 0x8e88ef11); // from above
|
||||||
|
|
||||||
|
// Make sure that we can resume computing from the partial checksum via `from_checksum`.
|
||||||
|
let mut adler = Adler32::from_checksum(partial);
|
||||||
|
adler.write_slice(&[0xff; 1024 * 1024 - 1024]);
|
||||||
|
assert_eq!(adler.checksum(), 0x8e88ef11); // from above
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
#[test]
|
||||||
|
fn bufread() {
|
||||||
|
use std::io::BufReader;
|
||||||
|
fn test(data: &[u8], checksum: u32) {
|
||||||
|
// `BufReader` uses an 8 KB buffer, so this will test buffer refilling.
|
||||||
|
let mut buf = BufReader::new(data);
|
||||||
|
let real_sum = adler32(&mut buf).unwrap();
|
||||||
|
assert_eq!(checksum, real_sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
test(&[], 1);
|
||||||
|
test(&[0; 1024], 0x04000001);
|
||||||
|
test(&[0; 1024 * 1024], 0x00f00001);
|
||||||
|
test(&[0xA5; 1024 * 1024], 0xd5009ab1);
|
||||||
|
}
|
||||||
|
}
|
1
vendor/anstream/.cargo-checksum.json
vendored
Normal file
1
vendor/anstream/.cargo-checksum.json
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"files":{"Cargo.lock":"e89078a9d7e89f125bea210c74fd30ef1167c208b9b240baa3fe76ec1170f6ec","Cargo.toml":"38deb1bfcca1eaef87c409274c63f9b25df94f6faaebc74061fa7ef1e4f078f1","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"6efb0476a1cc085077ed49357026d8c173bf33017278ef440f222fb9cbcb66e6","README.md":"b230c2257d0c7a49b9bd97f2fa73abedcdc055757b5cedd2b0eb1a7a448ff461","benches/stream.rs":"7e666c4f4b79ddb5237361ed25264a966ee241192fbb2c1baea3006e3e0326b4","benches/strip.rs":"9603bd5ca1ae4661c2ccab50315dbfdec0c661ac2624262172bbd8f5d0bd87c9","benches/wincon.rs":"680e86933c008b242a3286c5149c33d3c086426eb99fe134b6e79f7578f96663","examples/dump-stream.rs":"54b2bce2409fc1a1f00dbdcab7abbbb6cde447fa20b5c829d1b17ce2e15eefd1","examples/query-stream.rs":"16f38843083174fbefa974a5aa38a5f3ffa51bd6e6db3dc1d91164462219399e","src/adapter/mod.rs":"baf4237ea0b18df63609e49d93572ca27c2202a4cbec0220adb5a7e815c7d8ed","src/adapter/strip.rs":"010972f96708c56da9bced98287f134ce43a4f6459c22c1697abdc4fd6f82d00","src/adapter/wincon.rs":"07d75878ca9edcef4f473a5ff6113b40aab681dcbcd1ae9de1ec895332f7cc2a","src/auto.rs":"71c249ab6b0af64c3946817ea9f1719d4b789128c244611a05075b1e13413007","src/buffer.rs":"83e7088b50dd3e2941c06a417d9eef75fda45311a2912ba94f480ec98d6f0183","src/fmt.rs":"cc11b005c4559843bd908a57958a13c8d0922fae6aff5261f3583c90e60da73c","src/lib.rs":"649b86b187835e0e33baaaf2242c5f331b7dff133fae8fc419c52b7add797c57","src/macros.rs":"a26ababe32a39732d0aade9674f6e5e267bd26c6ea06603ff9e61e80681195e0","src/stream.rs":"cbe8f61fba4c3c60934339c8bda5d1ff43320f57cdc4ed409aa173945a941b3d","src/strip.rs":"56e6516283b6c0dfa72a8e0e6679da8424295f50a3e56c44281e76de6aa0344b","src/wincon.rs":"fe5aff7bfd80b14c9a6b07143079d59b81831293ad766b845e46fad2e1459c9a"},"package":"d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6"}
|
1094
vendor/anstream/Cargo.lock
generated
vendored
Normal file
1094
vendor/anstream/Cargo.lock
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
144
vendor/anstream/Cargo.toml
vendored
Normal file
144
vendor/anstream/Cargo.toml
vendored
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
# 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.70.0"
|
||||||
|
name = "anstream"
|
||||||
|
version = "0.6.5"
|
||||||
|
include = [
|
||||||
|
"build.rs",
|
||||||
|
"src/**/*",
|
||||||
|
"Cargo.toml",
|
||||||
|
"Cargo.lock",
|
||||||
|
"LICENSE*",
|
||||||
|
"README.md",
|
||||||
|
"benches/**/*",
|
||||||
|
"examples/**/*",
|
||||||
|
]
|
||||||
|
description = "A simple cross platform library for writing colored text to a terminal."
|
||||||
|
homepage = "https://github.com/rust-cli/anstyle"
|
||||||
|
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]
|
||||||
|
cargo-args = [
|
||||||
|
"-Zunstable-options",
|
||||||
|
"-Zrustdoc-scrape-examples",
|
||||||
|
]
|
||||||
|
rustdoc-args = [
|
||||||
|
"--cfg",
|
||||||
|
"docsrs",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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 -->"
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "strip"
|
||||||
|
harness = false
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "wincon"
|
||||||
|
harness = false
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "stream"
|
||||||
|
harness = false
|
||||||
|
|
||||||
|
[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"
|
||||||
|
optional = true
|
||||||
|
|
||||||
|
[dependencies.utf8parse]
|
||||||
|
version = "0.2.1"
|
||||||
|
|
||||||
|
[dev-dependencies.criterion]
|
||||||
|
version = "0.5.1"
|
||||||
|
|
||||||
|
[dev-dependencies.lexopt]
|
||||||
|
version = "0.3.0"
|
||||||
|
|
||||||
|
[dev-dependencies.owo-colors]
|
||||||
|
version = "3.5.0"
|
||||||
|
|
||||||
|
[dev-dependencies.proptest]
|
||||||
|
version = "1.4.0"
|
||||||
|
|
||||||
|
[dev-dependencies.strip-ansi-escapes]
|
||||||
|
version = "0.2.0"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
auto = [
|
||||||
|
"dep:anstyle-query",
|
||||||
|
"dep:colorchoice",
|
||||||
|
]
|
||||||
|
default = [
|
||||||
|
"auto",
|
||||||
|
"wincon",
|
||||||
|
]
|
||||||
|
test = []
|
||||||
|
wincon = ["dep:anstyle-wincon"]
|
||||||
|
|
||||||
|
[target."cfg(windows)".dependencies.anstyle-wincon]
|
||||||
|
version = "3.0.1"
|
||||||
|
optional = true
|
202
vendor/anstream/LICENSE-APACHE
vendored
Normal file
202
vendor/anstream/LICENSE-APACHE
vendored
Normal file
@ -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.
|
||||||
|
|
19
vendor/anstream/LICENSE-MIT
vendored
Normal file
19
vendor/anstream/LICENSE-MIT
vendored
Normal file
@ -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.
|
34
vendor/anstream/README.md
vendored
Normal file
34
vendor/anstream/README.md
vendored
Normal file
@ -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.
|
||||||
|
|
||||||
|
### Contribution
|
||||||
|
|
||||||
|
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
|
81
vendor/anstream/benches/stream.rs
vendored
Normal file
81
vendor/anstream/benches/stream.rs
vendored
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
use std::io::Write as _;
|
||||||
|
|
||||||
|
use criterion::{black_box, Criterion};
|
||||||
|
|
||||||
|
fn stream(c: &mut Criterion) {
|
||||||
|
for (name, content) in [
|
||||||
|
("demo.vte", &include_bytes!("../tests/demo.vte")[..]),
|
||||||
|
("rg_help.vte", &include_bytes!("../tests/rg_help.vte")[..]),
|
||||||
|
("rg_linus.vte", &include_bytes!("../tests/rg_linus.vte")[..]),
|
||||||
|
(
|
||||||
|
"state_changes",
|
||||||
|
&b"\x1b]2;X\x1b\\ \x1b[0m \x1bP0@\x1b\\"[..],
|
||||||
|
),
|
||||||
|
] {
|
||||||
|
let mut group = c.benchmark_group(name);
|
||||||
|
group.bench_function("nop", |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
let buffer = Vec::with_capacity(content.len());
|
||||||
|
let mut stream = buffer;
|
||||||
|
|
||||||
|
stream.write_all(content).unwrap();
|
||||||
|
|
||||||
|
black_box(stream)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
group.bench_function("StripStream", |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
let buffer = Vec::with_capacity(content.len());
|
||||||
|
let mut stream = anstream::StripStream::new(buffer);
|
||||||
|
|
||||||
|
stream.write_all(content).unwrap();
|
||||||
|
|
||||||
|
black_box(stream)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
#[cfg(all(windows, feature = "wincon"))]
|
||||||
|
group.bench_function("WinconStream", |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
let buffer = Vec::with_capacity(content.len());
|
||||||
|
let mut stream = anstream::WinconStream::new(buffer);
|
||||||
|
|
||||||
|
stream.write_all(content).unwrap();
|
||||||
|
|
||||||
|
black_box(stream)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
group.bench_function("AutoStream::always_ansi", |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
let buffer = Vec::with_capacity(content.len());
|
||||||
|
let mut stream = anstream::AutoStream::always_ansi(buffer);
|
||||||
|
|
||||||
|
stream.write_all(content).unwrap();
|
||||||
|
|
||||||
|
black_box(stream)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
group.bench_function("AutoStream::always", |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
let buffer = Vec::with_capacity(content.len());
|
||||||
|
let mut stream = anstream::AutoStream::always(buffer);
|
||||||
|
|
||||||
|
stream.write_all(content).unwrap();
|
||||||
|
|
||||||
|
black_box(stream)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
group.bench_function("AutoStream::never", |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
let buffer = Vec::with_capacity(content.len());
|
||||||
|
let mut stream = anstream::AutoStream::never(buffer);
|
||||||
|
|
||||||
|
stream.write_all(content).unwrap();
|
||||||
|
|
||||||
|
black_box(stream)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
criterion::criterion_group!(benches, stream);
|
||||||
|
criterion::criterion_main!(benches);
|
102
vendor/anstream/benches/strip.rs
vendored
Normal file
102
vendor/anstream/benches/strip.rs
vendored
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
use criterion::{black_box, Criterion};
|
||||||
|
|
||||||
|
#[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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn strip(c: &mut Criterion) {
|
||||||
|
for (name, content) in [
|
||||||
|
("demo.vte", &include_bytes!("../tests/demo.vte")[..]),
|
||||||
|
("rg_help.vte", &include_bytes!("../tests/rg_help.vte")[..]),
|
||||||
|
("rg_linus.vte", &include_bytes!("../tests/rg_linus.vte")[..]),
|
||||||
|
(
|
||||||
|
"state_changes",
|
||||||
|
&b"\x1b]2;X\x1b\\ \x1b[0m \x1bP0@\x1b\\"[..],
|
||||||
|
),
|
||||||
|
] {
|
||||||
|
// Make sure the comparison is fair
|
||||||
|
if let Ok(content) = std::str::from_utf8(content) {
|
||||||
|
let mut stripped = Strip::with_capacity(content.len());
|
||||||
|
let mut parser = anstyle_parse::Parser::<anstyle_parse::DefaultCharAccumulator>::new();
|
||||||
|
for byte in content.as_bytes() {
|
||||||
|
parser.advance(&mut stripped, *byte);
|
||||||
|
}
|
||||||
|
assert_eq!(
|
||||||
|
stripped.0,
|
||||||
|
anstream::adapter::strip_str(content).to_string()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
stripped.0,
|
||||||
|
String::from_utf8(anstream::adapter::strip_bytes(content.as_bytes()).into_vec())
|
||||||
|
.unwrap()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut group = c.benchmark_group(name);
|
||||||
|
group.bench_function("advance_strip", |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
let mut stripped = Strip::with_capacity(content.len());
|
||||||
|
let mut parser =
|
||||||
|
anstyle_parse::Parser::<anstyle_parse::DefaultCharAccumulator>::new();
|
||||||
|
|
||||||
|
for byte in content {
|
||||||
|
parser.advance(&mut stripped, *byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
black_box(stripped.0)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
group.bench_function("strip_ansi_escapes", |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
let stripped = strip_ansi_escapes::strip(content);
|
||||||
|
|
||||||
|
black_box(stripped)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
if let Ok(content) = std::str::from_utf8(content) {
|
||||||
|
group.bench_function("strip_str", |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
let stripped = anstream::adapter::strip_str(content).to_string();
|
||||||
|
|
||||||
|
black_box(stripped)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
group.bench_function("StripStr", |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
let mut stripped = String::with_capacity(content.len());
|
||||||
|
let mut state = anstream::adapter::StripStr::new();
|
||||||
|
for printable in state.strip_next(content) {
|
||||||
|
stripped.push_str(printable);
|
||||||
|
}
|
||||||
|
|
||||||
|
black_box(stripped)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
group.bench_function("strip_bytes", |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
let stripped = anstream::adapter::strip_bytes(content).into_vec();
|
||||||
|
|
||||||
|
black_box(stripped)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
criterion::criterion_group!(benches, strip);
|
||||||
|
criterion::criterion_main!(benches);
|
26
vendor/anstream/benches/wincon.rs
vendored
Normal file
26
vendor/anstream/benches/wincon.rs
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
use criterion::{black_box, Criterion};
|
||||||
|
|
||||||
|
fn wincon(c: &mut Criterion) {
|
||||||
|
for (name, content) in [
|
||||||
|
("demo.vte", &include_bytes!("../tests/demo.vte")[..]),
|
||||||
|
("rg_help.vte", &include_bytes!("../tests/rg_help.vte")[..]),
|
||||||
|
("rg_linus.vte", &include_bytes!("../tests/rg_linus.vte")[..]),
|
||||||
|
(
|
||||||
|
"state_changes",
|
||||||
|
&b"\x1b]2;X\x1b\\ \x1b[0m \x1bP0@\x1b\\"[..],
|
||||||
|
),
|
||||||
|
] {
|
||||||
|
let mut group = c.benchmark_group(name);
|
||||||
|
group.bench_function("wincon_bytes", |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
let mut state = anstream::adapter::WinconBytes::new();
|
||||||
|
let stripped = state.extract_next(content).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
black_box(stripped)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
criterion::criterion_group!(benches, wincon);
|
||||||
|
criterion::criterion_main!(benches);
|
128
vendor/anstream/examples/dump-stream.rs
vendored
Normal file
128
vendor/anstream/examples/dump-stream.rs
vendored
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
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 style = style(fixed, args.layer, args.effects);
|
||||||
|
let _ = print_number(&mut stdout, fixed, style);
|
||||||
|
if fixed == 7 || fixed == 15 {
|
||||||
|
let _ = writeln!(&mut stdout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for r in 0..6 {
|
||||||
|
let _ = writeln!(stdout);
|
||||||
|
for g in 0..6 {
|
||||||
|
for b in 0..6 {
|
||||||
|
let fixed = r * 36 + g * 6 + b + 16;
|
||||||
|
let style = style(fixed, args.layer, args.effects);
|
||||||
|
let _ = print_number(&mut stdout, fixed, style);
|
||||||
|
}
|
||||||
|
let _ = writeln!(stdout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for c in 0..24 {
|
||||||
|
if 0 == c % 8 {
|
||||||
|
let _ = writeln!(stdout);
|
||||||
|
}
|
||||||
|
let fixed = 232 + c;
|
||||||
|
let style = style(fixed, args.layer, args.effects);
|
||||||
|
let _ = print_number(&mut stdout, fixed, style);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn style(fixed: u8, layer: Layer, effects: anstyle::Effects) -> anstyle::Style {
|
||||||
|
let color = anstyle::Ansi256Color(fixed).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,
|
||||||
|
"{}{:>4}{}",
|
||||||
|
style.render(),
|
||||||
|
fixed,
|
||||||
|
anstyle::Reset.render()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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)
|
||||||
|
}
|
||||||
|
}
|
20
vendor/anstream/examples/query-stream.rs
vendored
Normal file
20
vendor/anstream/examples/query-stream.rs
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
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()
|
||||||
|
);
|
||||||
|
}
|
15
vendor/anstream/src/adapter/mod.rs
vendored
Normal file
15
vendor/anstream/src/adapter/mod.rs
vendored
Normal file
@ -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;
|
513
vendor/anstream/src/adapter/strip.rs
vendored
Normal file
513
vendor/anstream/src/adapter/strip.rs
vendored
Normal file
@ -0,0 +1,513 @@
|
|||||||
|
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<'s> std::fmt::Display for StrippedStr<'s> {
|
||||||
|
/// **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_str(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_str(action, 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 {
|
||||||
|
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_printable_str(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;
|
||||||
|
(action == Action::Print && byte != DEL)
|
||||||
|
|| action == Action::BeginUtf8
|
||||||
|
// since we know the input is valid UTF-8, the only thing we can do with
|
||||||
|
// continuations is to print them
|
||||||
|
|| is_utf8_continuation(byte)
|
||||||
|
|| (action == Action::Execute && byte.is_ascii_whitespace())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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 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<'a> utf8parse::Receiver for VtUtf8Receiver<'a> {
|
||||||
|
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).to_vec()).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).to_vec()).unwrap();
|
||||||
|
assert_eq!(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
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()).to_vec()).unwrap();
|
||||||
|
assert_eq!(expected, actual);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
320
vendor/anstream/src/adapter/wincon.rs
vendored
Normal file
320
vendor/anstream/src/adapter/wincon.rs
vendored
Normal file
@ -0,0 +1,320 @@
|
|||||||
|
/// 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<'s> Iterator for WinconBytesIter<'s> {
|
||||||
|
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 = State::Normal;
|
||||||
|
let mut r = None;
|
||||||
|
let mut g = None;
|
||||||
|
let mut is_bg = false;
|
||||||
|
for param in params {
|
||||||
|
for value in param {
|
||||||
|
match (state, *value) {
|
||||||
|
(State::Normal, 0) => {
|
||||||
|
style = anstyle::Style::default();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
(State::Normal, 1) => {
|
||||||
|
style = style.bold();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
(State::Normal, 4) => {
|
||||||
|
style = style.underline();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
(State::Normal, 30..=37) => {
|
||||||
|
let color = to_ansi_color(value - 30).unwrap();
|
||||||
|
style = style.fg_color(Some(color.into()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
(State::Normal, 38) => {
|
||||||
|
is_bg = false;
|
||||||
|
state = State::PrepareCustomColor;
|
||||||
|
}
|
||||||
|
(State::Normal, 39) => {
|
||||||
|
style = style.fg_color(None);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
(State::Normal, 40..=47) => {
|
||||||
|
let color = to_ansi_color(value - 40).unwrap();
|
||||||
|
style = style.bg_color(Some(color.into()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
(State::Normal, 48) => {
|
||||||
|
is_bg = true;
|
||||||
|
state = State::PrepareCustomColor;
|
||||||
|
}
|
||||||
|
(State::Normal, 49) => {
|
||||||
|
style = style.bg_color(None);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
(State::Normal, 90..=97) => {
|
||||||
|
let color = to_ansi_color(value - 90).unwrap().bright(true);
|
||||||
|
style = style.fg_color(Some(color.into()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
(State::Normal, 100..=107) => {
|
||||||
|
let color = to_ansi_color(value - 100).unwrap().bright(true);
|
||||||
|
style = style.bg_color(Some(color.into()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
(State::PrepareCustomColor, 5) => {
|
||||||
|
state = State::Ansi256;
|
||||||
|
}
|
||||||
|
(State::PrepareCustomColor, 2) => {
|
||||||
|
state = State::Rgb;
|
||||||
|
r = None;
|
||||||
|
g = None;
|
||||||
|
}
|
||||||
|
(State::Ansi256, n) => {
|
||||||
|
let color = anstyle::Ansi256Color(n as u8);
|
||||||
|
if is_bg {
|
||||||
|
style = style.bg_color(Some(color.into()));
|
||||||
|
} else {
|
||||||
|
style = style.fg_color(Some(color.into()));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
(State::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);
|
||||||
|
if is_bg {
|
||||||
|
style = style.bg_color(Some(color.into()));
|
||||||
|
} else {
|
||||||
|
style = style.fg_color(Some(color.into()));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if style != self.style && !self.printable.is_empty() {
|
||||||
|
self.ready = Some(self.style);
|
||||||
|
}
|
||||||
|
self.style = style;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
|
enum State {
|
||||||
|
Normal,
|
||||||
|
PrepareCustomColor,
|
||||||
|
Ansi256,
|
||||||
|
Rgb,
|
||||||
|
}
|
||||||
|
|
||||||
|
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 owo_colors::OwoColorize as _;
|
||||||
|
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 input = format!("{} world!", "Hello".green().on_red());
|
||||||
|
let expected = vec![
|
||||||
|
(
|
||||||
|
anstyle::AnsiColor::Green.on(anstyle::AnsiColor::Red),
|
||||||
|
"Hello",
|
||||||
|
),
|
||||||
|
(anstyle::Style::default(), " world!"),
|
||||||
|
];
|
||||||
|
verify(&input, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn middle() {
|
||||||
|
let input = format!("Hello {}!", "world".green().on_red());
|
||||||
|
let expected = vec![
|
||||||
|
(anstyle::Style::default(), "Hello "),
|
||||||
|
(
|
||||||
|
anstyle::AnsiColor::Green.on(anstyle::AnsiColor::Red),
|
||||||
|
"world",
|
||||||
|
),
|
||||||
|
(anstyle::Style::default(), "!"),
|
||||||
|
];
|
||||||
|
verify(&input, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn end() {
|
||||||
|
let input = format!("Hello {}", "world!".green().on_red());
|
||||||
|
let expected = vec![
|
||||||
|
(anstyle::Style::default(), "Hello "),
|
||||||
|
(
|
||||||
|
anstyle::AnsiColor::Green.on(anstyle::AnsiColor::Red),
|
||||||
|
"world!",
|
||||||
|
),
|
||||||
|
];
|
||||||
|
verify(&input, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ansi256_colors() {
|
||||||
|
// termcolor only supports "brights" via these
|
||||||
|
let input = format!(
|
||||||
|
"Hello {}!",
|
||||||
|
"world".color(owo_colors::XtermColors::UserBrightYellow)
|
||||||
|
);
|
||||||
|
let expected = vec![
|
||||||
|
(anstyle::Style::default(), "Hello "),
|
||||||
|
(anstyle::Ansi256Color(11).on_default(), "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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
263
vendor/anstream/src/auto.rs
vendored
Normal file
263
vendor/anstream/src/auto.rs
vendored
Normal file
@ -0,0 +1,263 @@
|
|||||||
|
use crate::stream::AsLockedWrite;
|
||||||
|
use crate::stream::RawStream;
|
||||||
|
#[cfg(feature = "auto")]
|
||||||
|
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
|
||||||
|
#[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
|
||||||
|
#[cfg(feature = "auto")]
|
||||||
|
#[inline]
|
||||||
|
pub fn new(raw: S, choice: ColorChoice) -> Self {
|
||||||
|
match choice {
|
||||||
|
ColorChoice::Auto => Self::auto(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(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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 raw.is_terminal()
|
||||||
|
&& !anstyle_query::no_color()
|
||||||
|
&& !clicolor_disabled
|
||||||
|
&& (anstyle_query::term_supports_color()
|
||||||
|
|| clicolor_enabled
|
||||||
|
|| anstyle_query::is_ci())
|
||||||
|
|| anstyle_query::clicolor_force()
|
||||||
|
{
|
||||||
|
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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
68
vendor/anstream/src/buffer.rs
vendored
Normal file
68
vendor/anstream/src/buffer.rs
vendored
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#![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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(windows, feature = "wincon"))]
|
||||||
|
impl anstyle_wincon::WinconStream for &'_ mut Buffer {
|
||||||
|
fn write_colored(
|
||||||
|
&mut self,
|
||||||
|
fg: Option<anstyle::AnsiColor>,
|
||||||
|
bg: Option<anstyle::AnsiColor>,
|
||||||
|
data: &[u8],
|
||||||
|
) -> std::io::Result<usize> {
|
||||||
|
(**self).write_colored(fg, bg, data)
|
||||||
|
}
|
||||||
|
}
|
54
vendor/anstream/src/fmt.rs
vendored
Normal file
54
vendor/anstream/src/fmt.rs
vendored
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
79
vendor/anstream/src/lib.rs
vendored
Normal file
79
vendor/anstream/src/lib.rs
vendored
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
//! **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.
|
||||||
|
//!
|
||||||
|
//! 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
|
||||||
|
//! (once it hits 1.0)
|
||||||
|
//! - [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))]
|
||||||
|
|
||||||
|
pub mod adapter;
|
||||||
|
pub mod stream;
|
||||||
|
|
||||||
|
mod buffer;
|
||||||
|
#[macro_use]
|
||||||
|
mod macros;
|
||||||
|
mod auto;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/// 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() -> AutoStream<std::io::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() -> AutoStream<std::io::Stderr> {
|
||||||
|
let stderr = std::io::stderr();
|
||||||
|
AutoStream::auto(stderr)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Selection for overriding color output
|
||||||
|
#[cfg(feature = "auto")]
|
||||||
|
pub use colorchoice::ColorChoice;
|
389
vendor/anstream/src/macros.rs
vendored
Normal file
389
vendor/anstream/src/macros.rs
vendored
Normal file
@ -0,0 +1,389 @@
|
|||||||
|
/// 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!(any(feature = "test", test)) {
|
||||||
|
use std::io::Write as _;
|
||||||
|
|
||||||
|
let stdio = std::io::stdout();
|
||||||
|
let choice = $crate::AutoStream::choice(&stdio);
|
||||||
|
let buffer = Vec::new();
|
||||||
|
let mut stream = $crate::AutoStream::new(buffer, choice);
|
||||||
|
// Ignore errors rather than panic
|
||||||
|
let _ = ::std::write!(&mut stream, $($arg)*);
|
||||||
|
let buffer = stream.into_inner();
|
||||||
|
// Should be UTF-8 but not wanting to panic
|
||||||
|
let buffer = String::from_utf8_lossy(&buffer);
|
||||||
|
::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!(any(feature = "test", test)) {
|
||||||
|
use std::io::Write as _;
|
||||||
|
|
||||||
|
let stdio = std::io::stdout();
|
||||||
|
let choice = $crate::AutoStream::choice(&stdio);
|
||||||
|
let buffer = Vec::new();
|
||||||
|
let mut stream = $crate::AutoStream::new(buffer, choice);
|
||||||
|
// Ignore errors rather than panic
|
||||||
|
let _ = ::std::write!(&mut stream, $($arg)*);
|
||||||
|
let buffer = stream.into_inner();
|
||||||
|
// Should be UTF-8 but not wanting to panic
|
||||||
|
let buffer = String::from_utf8_lossy(&buffer);
|
||||||
|
::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!(any(feature = "test", test)) {
|
||||||
|
use std::io::Write as _;
|
||||||
|
|
||||||
|
let stdio = std::io::stderr();
|
||||||
|
let choice = $crate::AutoStream::choice(&stdio);
|
||||||
|
let buffer = Vec::new();
|
||||||
|
let mut stream = $crate::AutoStream::new(buffer, choice);
|
||||||
|
// Ignore errors rather than panic
|
||||||
|
let _ = ::std::write!(&mut stream, $($arg)*);
|
||||||
|
let buffer = stream.into_inner();
|
||||||
|
// Should be UTF-8 but not wanting to panic
|
||||||
|
let buffer = String::from_utf8_lossy(&buffer);
|
||||||
|
::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 stdout: {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!(any(feature = "test", test)) {
|
||||||
|
use std::io::Write as _;
|
||||||
|
|
||||||
|
let stdio = std::io::stderr();
|
||||||
|
let choice = $crate::AutoStream::choice(&stdio);
|
||||||
|
let buffer = Vec::new();
|
||||||
|
let mut stream = $crate::AutoStream::new(buffer, choice);
|
||||||
|
// Ignore errors rather than panic
|
||||||
|
let _ = ::std::write!(&mut stream, $($arg)*);
|
||||||
|
let buffer = stream.into_inner();
|
||||||
|
// Should be UTF-8 but not wanting to panic
|
||||||
|
let buffer = String::from_utf8_lossy(&buffer);
|
||||||
|
::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 stdout: {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 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
|
||||||
|
/// [`Any`]: crate::any::Any
|
||||||
|
/// [`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)*) => {{
|
||||||
|
use std::io::Write as _;
|
||||||
|
|
||||||
|
let panic_stream = std::io::stderr();
|
||||||
|
let choice = $crate::AutoStream::choice(&panic_stream);
|
||||||
|
let buffer = Vec::new();
|
||||||
|
let mut stream = $crate::AutoStream::new(buffer, choice);
|
||||||
|
// Ignore errors rather than panic
|
||||||
|
let _ = ::std::write!(&mut stream, $($arg)*);
|
||||||
|
let buffer = stream.into_inner();
|
||||||
|
// Should be UTF-8 but not wanting to panic
|
||||||
|
let buffer = String::from_utf8_lossy(&buffer).into_owned();
|
||||||
|
::std::panic!("{}", buffer)
|
||||||
|
}};
|
||||||
|
}
|
261
vendor/anstream/src/stream.rs
vendored
Normal file
261
vendor/anstream/src/stream.rs
vendored
Normal file
@ -0,0 +1,261 @@
|
|||||||
|
//! 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 RawStream for std::io::Stdout {}
|
||||||
|
|
||||||
|
impl RawStream for std::io::StdoutLock<'_> {}
|
||||||
|
|
||||||
|
impl RawStream for &'_ mut std::io::StdoutLock<'_> {}
|
||||||
|
|
||||||
|
impl RawStream for std::io::Stderr {}
|
||||||
|
|
||||||
|
impl RawStream for std::io::StderrLock<'_> {}
|
||||||
|
|
||||||
|
impl RawStream for &'_ mut std::io::StderrLock<'_> {}
|
||||||
|
|
||||||
|
impl RawStream for Box<dyn std::io::Write> {}
|
||||||
|
|
||||||
|
impl RawStream for &'_ mut Box<dyn std::io::Write> {}
|
||||||
|
|
||||||
|
impl RawStream for Vec<u8> {}
|
||||||
|
|
||||||
|
impl RawStream for &'_ mut Vec<u8> {}
|
||||||
|
|
||||||
|
impl RawStream for std::fs::File {}
|
||||||
|
|
||||||
|
impl RawStream for &'_ mut std::fs::File {}
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
|
impl RawStream for crate::Buffer {}
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
|
impl RawStream for &'_ mut crate::Buffer {}
|
||||||
|
|
||||||
|
pub trait IsTerminal: private::Sealed {
|
||||||
|
fn is_terminal(&self) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IsTerminal for std::io::Stdout {
|
||||||
|
#[inline]
|
||||||
|
fn is_terminal(&self) -> bool {
|
||||||
|
std::io::IsTerminal::is_terminal(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IsTerminal for std::io::StdoutLock<'_> {
|
||||||
|
#[inline]
|
||||||
|
fn is_terminal(&self) -> bool {
|
||||||
|
std::io::IsTerminal::is_terminal(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IsTerminal for &'_ mut std::io::StdoutLock<'_> {
|
||||||
|
#[inline]
|
||||||
|
fn is_terminal(&self) -> bool {
|
||||||
|
(**self).is_terminal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IsTerminal for std::io::Stderr {
|
||||||
|
#[inline]
|
||||||
|
fn is_terminal(&self) -> bool {
|
||||||
|
std::io::IsTerminal::is_terminal(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IsTerminal for std::io::StderrLock<'_> {
|
||||||
|
#[inline]
|
||||||
|
fn is_terminal(&self) -> bool {
|
||||||
|
std::io::IsTerminal::is_terminal(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IsTerminal for &'_ mut std::io::StderrLock<'_> {
|
||||||
|
#[inline]
|
||||||
|
fn is_terminal(&self) -> bool {
|
||||||
|
(**self).is_terminal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IsTerminal for Box<dyn std::io::Write> {
|
||||||
|
#[inline]
|
||||||
|
fn is_terminal(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IsTerminal for &'_ mut Box<dyn std::io::Write> {
|
||||||
|
#[inline]
|
||||||
|
fn is_terminal(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IsTerminal for Vec<u8> {
|
||||||
|
#[inline]
|
||||||
|
fn is_terminal(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IsTerminal for &'_ mut Vec<u8> {
|
||||||
|
#[inline]
|
||||||
|
fn is_terminal(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IsTerminal for std::fs::File {
|
||||||
|
#[inline]
|
||||||
|
fn is_terminal(&self) -> bool {
|
||||||
|
std::io::IsTerminal::is_terminal(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IsTerminal for &'_ mut std::fs::File {
|
||||||
|
#[inline]
|
||||||
|
fn is_terminal(&self) -> bool {
|
||||||
|
(**self).is_terminal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
|
impl IsTerminal for crate::Buffer {
|
||||||
|
#[inline]
|
||||||
|
fn is_terminal(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
|
impl IsTerminal for &'_ mut crate::Buffer {
|
||||||
|
#[inline]
|
||||||
|
fn is_terminal(&self) -> bool {
|
||||||
|
(**self).is_terminal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait AsLockedWrite: private::Sealed {
|
||||||
|
type Write<'w>: RawStream + 'w
|
||||||
|
where
|
||||||
|
Self: 'w;
|
||||||
|
|
||||||
|
fn as_locked_write(&mut self) -> Self::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 Box<dyn std::io::Write> {
|
||||||
|
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 {
|
||||||
|
pub trait Sealed {}
|
||||||
|
|
||||||
|
impl Sealed for std::io::Stdout {}
|
||||||
|
|
||||||
|
impl Sealed for std::io::StdoutLock<'_> {}
|
||||||
|
|
||||||
|
impl Sealed for &'_ mut std::io::StdoutLock<'_> {}
|
||||||
|
|
||||||
|
impl Sealed for std::io::Stderr {}
|
||||||
|
|
||||||
|
impl Sealed for std::io::StderrLock<'_> {}
|
||||||
|
|
||||||
|
impl Sealed for &'_ mut std::io::StderrLock<'_> {}
|
||||||
|
|
||||||
|
impl Sealed for Box<dyn std::io::Write> {}
|
||||||
|
|
||||||
|
impl Sealed for &'_ mut Box<dyn std::io::Write> {}
|
||||||
|
|
||||||
|
impl Sealed for Vec<u8> {}
|
||||||
|
|
||||||
|
impl Sealed for &'_ mut Vec<u8> {}
|
||||||
|
|
||||||
|
impl Sealed for std::fs::File {}
|
||||||
|
|
||||||
|
impl Sealed for &'_ mut std::fs::File {}
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
|
impl Sealed for crate::Buffer {}
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
|
impl Sealed for &'_ mut crate::Buffer {}
|
||||||
|
}
|
219
vendor/anstream/src/strip.rs
vendored
Normal file
219
vendor/anstream/src/strip.rs
vendored
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
use crate::adapter::StripBytes;
|
||||||
|
use crate::stream::AsLockedWrite;
|
||||||
|
use crate::stream::RawStream;
|
||||||
|
|
||||||
|
/// Only pass printable data to the inner `Write`
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct StripStream<S>
|
||||||
|
where
|
||||||
|
S: RawStream,
|
||||||
|
{
|
||||||
|
raw: S,
|
||||||
|
state: StripBytes,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S> StripStream<S>
|
||||||
|
where
|
||||||
|
S: RawStream,
|
||||||
|
{
|
||||||
|
/// Only pass printable data to the inner `Write`
|
||||||
|
#[inline]
|
||||||
|
pub fn new(raw: S) -> Self {
|
||||||
|
Self {
|
||||||
|
raw,
|
||||||
|
state: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the wrapped [`RawStream`]
|
||||||
|
#[inline]
|
||||||
|
pub fn into_inner(self) -> S {
|
||||||
|
self.raw
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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: RawStream + 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
210
vendor/anstream/src/wincon.rs
vendored
Normal file
210
vendor/anstream/src/wincon.rs
vendored
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
use crate::adapter::WinconBytes;
|
||||||
|
use crate::stream::AsLockedWrite;
|
||||||
|
use crate::stream::RawStream;
|
||||||
|
|
||||||
|
/// Only pass printable data to the inner `Write`
|
||||||
|
#[cfg(feature = "wincon")] // here mostly for documentation purposes
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct WinconStream<S>
|
||||||
|
where
|
||||||
|
S: RawStream,
|
||||||
|
{
|
||||||
|
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: RawStream,
|
||||||
|
{
|
||||||
|
/// Only pass printable data to the inner `Write`
|
||||||
|
#[inline]
|
||||||
|
pub fn new(raw: S) -> Self {
|
||||||
|
Self {
|
||||||
|
raw,
|
||||||
|
state: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the wrapped [`RawStream`]
|
||||||
|
#[inline]
|
||||||
|
pub fn into_inner(self) -> S {
|
||||||
|
self.raw
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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: RawStream + 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 RawStream, 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 RawStream, 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 RawStream,
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
vendor/anstyle-parse/.cargo-checksum.json
vendored
Normal file
1
vendor/anstyle-parse/.cargo-checksum.json
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"files":{"Cargo.lock":"7f68b5328c460caf1d2198b10fe1761e5f0282262f92d04076b30b25539970b0","Cargo.toml":"2834f39b7169c03b03da1e209f56133783ce00ea64d5f2c14381d93984ca20bf","LICENSE-APACHE":"b40930bbcf80744c86c46a12bc9da056641d722716c378f5659b9e555ef833e1","LICENSE-MIT":"c1d4bc00896473e0109ccb4c3c7d21addb55a4ff1a644be204dcfce26612af2a","README.md":"abc82171d436ee0eb221838e8d21a21a2e392504e87f0c130b5eca6a35671e1e","benches/parse.rs":"336c808d51c90db2497fa87e571df7f71c844a1b09be88839fe4255066c632f4","examples/parselog.rs":"58b7db739deed701aa0ab386d0d0c1772511b8aed1c08d31ec5b35a1c8cd4321","src/lib.rs":"c89f2afa0e982276dc47ca8d8a76d47516aa39aa9d3354254c87fdbf2f8ef4cc","src/params.rs":"8cfef4e2ab1961ca2d9f210da553fc6ac64bb6dbd03321f0ee7d6089ab45389c","src/state/codegen.rs":"8530124c8f998f391e47950f130590376321dcade810990f4312c3b1c0a61968","src/state/definitions.rs":"dc3dbb3244def74430a72b0108f019e22cc02e0ae5f563ee14d38300ff82b814","src/state/mod.rs":"be07c2ea393a971dd54117dc2ce8a3ffb5b803cb557ab468389b74570855fa37","src/state/table.rs":"673b7e9242c5248efc076086cc6923578ec2f059c0c26da21363528e20e4285c"},"package":"c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"}
|
1202
vendor/anstyle-parse/Cargo.lock
generated
vendored
Normal file
1202
vendor/anstyle-parse/Cargo.lock
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
108
vendor/anstyle-parse/Cargo.toml
vendored
Normal file
108
vendor/anstyle-parse/Cargo.toml
vendored
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
# 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.70.0"
|
||||||
|
name = "anstyle-parse"
|
||||||
|
version = "0.2.3"
|
||||||
|
include = [
|
||||||
|
"build.rs",
|
||||||
|
"src/**/*",
|
||||||
|
"Cargo.toml",
|
||||||
|
"Cargo.lock",
|
||||||
|
"LICENSE*",
|
||||||
|
"README.md",
|
||||||
|
"benches/**/*",
|
||||||
|
"examples/**/*",
|
||||||
|
]
|
||||||
|
description = "Parse ANSI Style Escapes"
|
||||||
|
homepage = "https://github.com/rust-cli/anstyle"
|
||||||
|
readme = "README.md"
|
||||||
|
keywords = [
|
||||||
|
"ansi",
|
||||||
|
"terminal",
|
||||||
|
"color",
|
||||||
|
"vte",
|
||||||
|
]
|
||||||
|
categories = ["command-line-interface"]
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
repository = "https://github.com/rust-cli/anstyle.git"
|
||||||
|
|
||||||
|
[[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 -->"
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "parse"
|
||||||
|
harness = false
|
||||||
|
|
||||||
|
[dependencies.arrayvec]
|
||||||
|
version = "0.7.2"
|
||||||
|
optional = true
|
||||||
|
default-features = false
|
||||||
|
|
||||||
|
[dependencies.utf8parse]
|
||||||
|
version = "0.2.1"
|
||||||
|
optional = true
|
||||||
|
|
||||||
|
[dev-dependencies.codegenrs]
|
||||||
|
version = "3.0.1"
|
||||||
|
default-features = false
|
||||||
|
|
||||||
|
[dev-dependencies.criterion]
|
||||||
|
version = "0.5.1"
|
||||||
|
|
||||||
|
[dev-dependencies.proptest]
|
||||||
|
version = "1.4.0"
|
||||||
|
|
||||||
|
[dev-dependencies.snapbox]
|
||||||
|
version = "0.4.14"
|
||||||
|
features = ["path"]
|
||||||
|
|
||||||
|
[dev-dependencies.vte_generate_state_changes]
|
||||||
|
version = "0.1.1"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
core = ["dep:arrayvec"]
|
||||||
|
default = ["utf8"]
|
||||||
|
utf8 = ["dep:utf8parse"]
|
201
vendor/anstyle-parse/LICENSE-APACHE
vendored
Normal file
201
vendor/anstyle-parse/LICENSE-APACHE
vendored
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
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.
|
25
vendor/anstyle-parse/LICENSE-MIT
vendored
Normal file
25
vendor/anstyle-parse/LICENSE-MIT
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
Copyright (c) 2016 Joe Wilm and 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.
|
33
vendor/anstyle-parse/README.md
vendored
Normal file
33
vendor/anstyle-parse/README.md
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# anstyle-parse
|
||||||
|
|
||||||
|
> Parse [Parse ANSI Style Escapes](https://vt100.net/emu/dec_ansi_parser)
|
||||||
|
|
||||||
|
[![Documentation](https://img.shields.io/badge/docs-master-blue.svg)][Documentation]
|
||||||
|
![License](https://img.shields.io/crates/l/anstyle-parse.svg)
|
||||||
|
[![Crates Status](https://img.shields.io/crates/v/anstyle-parse.svg)](https://crates.io/crates/anstyle-parse)
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
|
### Contribution
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
### Special Thanks
|
||||||
|
|
||||||
|
[chrisduerr](https://github.com/alacritty/vte/commits?author=chrisduerr) and the
|
||||||
|
[alacritty project](https://github.com/alacritty/alacritty) for
|
||||||
|
[vte](https://crates.io/crates/vte) which
|
||||||
|
[this was forked from](https://github.com/alacritty/vte/issues/82)
|
||||||
|
|
||||||
|
[Crates.io]: https://crates.io/crates/anstyle-parse
|
||||||
|
[Documentation]: https://docs.rs/anstyle-parse
|
169
vendor/anstyle-parse/benches/parse.rs
vendored
Normal file
169
vendor/anstyle-parse/benches/parse.rs
vendored
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
use criterion::{black_box, Criterion};
|
||||||
|
|
||||||
|
use anstyle_parse::*;
|
||||||
|
|
||||||
|
struct BenchDispatcher;
|
||||||
|
impl Perform for BenchDispatcher {
|
||||||
|
fn print(&mut self, c: char) {
|
||||||
|
black_box(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn execute(&mut self, byte: u8) {
|
||||||
|
black_box(byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hook(&mut self, params: &Params, intermediates: &[u8], ignore: bool, c: u8) {
|
||||||
|
black_box((params, intermediates, ignore, c));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn put(&mut self, byte: u8) {
|
||||||
|
black_box(byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn osc_dispatch(&mut self, params: &[&[u8]], bell_terminated: bool) {
|
||||||
|
black_box((params, bell_terminated));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn csi_dispatch(&mut self, params: &Params, intermediates: &[u8], ignore: bool, c: u8) {
|
||||||
|
black_box((params, intermediates, ignore, c));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn esc_dispatch(&mut self, intermediates: &[u8], ignore: bool, byte: u8) {
|
||||||
|
black_box((intermediates, ignore, byte));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct Strip(String);
|
||||||
|
impl Strip {
|
||||||
|
fn with_capacity(capacity: usize) -> Self {
|
||||||
|
Self(String::with_capacity(capacity))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn strip_str(content: &str) -> String {
|
||||||
|
use anstyle_parse::state::state_change;
|
||||||
|
use anstyle_parse::state::Action;
|
||||||
|
use anstyle_parse::state::State;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn is_utf8_continuation(b: u8) -> bool {
|
||||||
|
matches!(b, 0x80..=0xbf)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn is_printable(action: Action, byte: u8) -> bool {
|
||||||
|
action == Action::Print
|
||||||
|
|| action == Action::BeginUtf8
|
||||||
|
// since we know the input is valid UTF-8, the only thing we can do with
|
||||||
|
// continuations is to print them
|
||||||
|
|| is_utf8_continuation(byte)
|
||||||
|
|| (action == Action::Execute && byte.is_ascii_whitespace())
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut stripped = Vec::with_capacity(content.len());
|
||||||
|
|
||||||
|
let mut bytes = content.as_bytes();
|
||||||
|
while !bytes.is_empty() {
|
||||||
|
let offset = bytes.iter().copied().position(|b| {
|
||||||
|
let (_next_state, action) = state_change(State::Ground, b);
|
||||||
|
!is_printable(action, b)
|
||||||
|
});
|
||||||
|
let (printable, next) = bytes.split_at(offset.unwrap_or(bytes.len()));
|
||||||
|
stripped.extend(printable);
|
||||||
|
bytes = next;
|
||||||
|
|
||||||
|
let mut state = State::Ground;
|
||||||
|
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(action, b)
|
||||||
|
});
|
||||||
|
let (_, next) = bytes.split_at(offset.unwrap_or(bytes.len()));
|
||||||
|
bytes = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
String::from_utf8(stripped).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse(c: &mut Criterion) {
|
||||||
|
for (name, content) in [
|
||||||
|
#[cfg(feature = "utf8")]
|
||||||
|
("demo.vte", &include_bytes!("../tests/demo.vte")[..]),
|
||||||
|
("rg_help.vte", &include_bytes!("../tests/rg_help.vte")[..]),
|
||||||
|
("rg_linus.vte", &include_bytes!("../tests/rg_linus.vte")[..]),
|
||||||
|
(
|
||||||
|
"state_changes",
|
||||||
|
&b"\x1b]2;X\x1b\\ \x1b[0m \x1bP0@\x1b\\"[..],
|
||||||
|
),
|
||||||
|
] {
|
||||||
|
// Make sure the comparison is fair
|
||||||
|
if let Ok(content) = std::str::from_utf8(content) {
|
||||||
|
let mut stripped = Strip::with_capacity(content.len());
|
||||||
|
let mut parser = Parser::<DefaultCharAccumulator>::new();
|
||||||
|
for byte in content.as_bytes() {
|
||||||
|
parser.advance(&mut stripped, *byte);
|
||||||
|
}
|
||||||
|
assert_eq!(stripped.0, strip_str(content));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut group = c.benchmark_group(name);
|
||||||
|
group.bench_function("advance", |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
let mut dispatcher = BenchDispatcher;
|
||||||
|
let mut parser = Parser::<DefaultCharAccumulator>::new();
|
||||||
|
|
||||||
|
for byte in content {
|
||||||
|
parser.advance(&mut dispatcher, *byte);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
group.bench_function("advance_strip", |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
let mut stripped = Strip::with_capacity(content.len());
|
||||||
|
let mut parser = Parser::<DefaultCharAccumulator>::new();
|
||||||
|
|
||||||
|
for byte in content {
|
||||||
|
parser.advance(&mut stripped, *byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
black_box(stripped.0)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
group.bench_function("state_change", |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
let mut state = anstyle_parse::state::State::default();
|
||||||
|
for byte in content {
|
||||||
|
let (next_state, action) = anstyle_parse::state::state_change(state, *byte);
|
||||||
|
state = next_state;
|
||||||
|
black_box(action);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
if let Ok(content) = std::str::from_utf8(content) {
|
||||||
|
group.bench_function("state_change_strip_str", |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
let stripped = strip_str(content);
|
||||||
|
|
||||||
|
black_box(stripped)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
criterion::criterion_group!(benches, parse);
|
||||||
|
criterion::criterion_main!(benches);
|
78
vendor/anstyle-parse/examples/parselog.rs
vendored
Normal file
78
vendor/anstyle-parse/examples/parselog.rs
vendored
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
//! Parse input from stdin and log actions on stdout
|
||||||
|
use std::io::{self, Read};
|
||||||
|
|
||||||
|
use anstyle_parse::{DefaultCharAccumulator, Params, Parser, Perform};
|
||||||
|
|
||||||
|
/// A type implementing Perform that just logs actions
|
||||||
|
struct Log;
|
||||||
|
|
||||||
|
impl Perform for Log {
|
||||||
|
fn print(&mut self, c: char) {
|
||||||
|
println!("[print] {:?}", c);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn execute(&mut self, byte: u8) {
|
||||||
|
println!("[execute] {:02x}", byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hook(&mut self, params: &Params, intermediates: &[u8], ignore: bool, c: u8) {
|
||||||
|
println!(
|
||||||
|
"[hook] params={:?}, intermediates={:?}, ignore={:?}, char={:?}",
|
||||||
|
params, intermediates, ignore, c
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn put(&mut self, byte: u8) {
|
||||||
|
println!("[put] {:02x}", byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unhook(&mut self) {
|
||||||
|
println!("[unhook]");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn osc_dispatch(&mut self, params: &[&[u8]], bell_terminated: bool) {
|
||||||
|
println!(
|
||||||
|
"[osc_dispatch] params={:?} bell_terminated={}",
|
||||||
|
params, bell_terminated
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn csi_dispatch(&mut self, params: &Params, intermediates: &[u8], ignore: bool, c: u8) {
|
||||||
|
println!(
|
||||||
|
"[csi_dispatch] params={:#?}, intermediates={:?}, ignore={:?}, char={:?}",
|
||||||
|
params, intermediates, ignore, c
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn esc_dispatch(&mut self, intermediates: &[u8], ignore: bool, byte: u8) {
|
||||||
|
println!(
|
||||||
|
"[esc_dispatch] intermediates={:?}, ignore={:?}, byte={:02x}",
|
||||||
|
intermediates, ignore, byte
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let input = io::stdin();
|
||||||
|
let mut handle = input.lock();
|
||||||
|
|
||||||
|
let mut statemachine = Parser::<DefaultCharAccumulator>::new();
|
||||||
|
let mut performer = Log;
|
||||||
|
|
||||||
|
let mut buf = [0; 2048];
|
||||||
|
|
||||||
|
loop {
|
||||||
|
match handle.read(&mut buf) {
|
||||||
|
Ok(0) => break,
|
||||||
|
Ok(n) => {
|
||||||
|
for byte in &buf[..n] {
|
||||||
|
statemachine.advance(&mut performer, *byte);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
println!("err: {}", err);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
431
vendor/anstyle-parse/src/lib.rs
vendored
Normal file
431
vendor/anstyle-parse/src/lib.rs
vendored
Normal file
@ -0,0 +1,431 @@
|
|||||||
|
//! Parser for implementing virtual terminal emulators
|
||||||
|
//!
|
||||||
|
//! [`Parser`] is implemented according to [Paul Williams' ANSI parser
|
||||||
|
//! state machine]. The state machine doesn't assign meaning to the parsed data
|
||||||
|
//! and is thus not itself sufficient for writing a terminal emulator. Instead,
|
||||||
|
//! it is expected that an implementation of [`Perform`] is provided which does
|
||||||
|
//! something useful with the parsed data. The [`Parser`] handles the book
|
||||||
|
//! keeping, and the [`Perform`] gets to simply handle actions.
|
||||||
|
//!
|
||||||
|
//! # Examples
|
||||||
|
//!
|
||||||
|
//! For an example of using the [`Parser`] please see the examples folder. The example included
|
||||||
|
//! there simply logs all the actions [`Perform`] does. One quick thing to see it in action is to
|
||||||
|
//! pipe `vim` into it
|
||||||
|
//!
|
||||||
|
//! ```sh
|
||||||
|
//! cargo build --release --example parselog
|
||||||
|
//! vim | target/release/examples/parselog
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! Just type `:q` to exit.
|
||||||
|
//!
|
||||||
|
//! # Differences from original state machine description
|
||||||
|
//!
|
||||||
|
//! * UTF-8 Support for Input
|
||||||
|
//! * OSC Strings can be terminated by 0x07
|
||||||
|
//! * Only supports 7-bit codes. Some 8-bit codes are still supported, but they no longer work in
|
||||||
|
//! all states.
|
||||||
|
//!
|
||||||
|
//! [Paul Williams' ANSI parser state machine]: https://vt100.net/emu/dec_ansi_parser
|
||||||
|
#![cfg_attr(not(test), no_std)]
|
||||||
|
|
||||||
|
#[cfg(not(feature = "core"))]
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
|
use core::mem::MaybeUninit;
|
||||||
|
|
||||||
|
#[cfg(feature = "core")]
|
||||||
|
use arrayvec::ArrayVec;
|
||||||
|
#[cfg(feature = "utf8")]
|
||||||
|
use utf8parse as utf8;
|
||||||
|
|
||||||
|
mod params;
|
||||||
|
pub mod state;
|
||||||
|
|
||||||
|
pub use params::{Params, ParamsIter};
|
||||||
|
|
||||||
|
use state::{state_change, Action, State};
|
||||||
|
|
||||||
|
const MAX_INTERMEDIATES: usize = 2;
|
||||||
|
const MAX_OSC_PARAMS: usize = 16;
|
||||||
|
#[cfg(feature = "core")]
|
||||||
|
const MAX_OSC_RAW: usize = 1024;
|
||||||
|
|
||||||
|
/// Parser for raw _VTE_ protocol which delegates actions to a [`Perform`]
|
||||||
|
#[derive(Default, Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct Parser<C = DefaultCharAccumulator> {
|
||||||
|
state: State,
|
||||||
|
intermediates: [u8; MAX_INTERMEDIATES],
|
||||||
|
intermediate_idx: usize,
|
||||||
|
params: Params,
|
||||||
|
param: u16,
|
||||||
|
#[cfg(feature = "core")]
|
||||||
|
osc_raw: ArrayVec<u8, MAX_OSC_RAW>,
|
||||||
|
#[cfg(not(feature = "core"))]
|
||||||
|
osc_raw: alloc::vec::Vec<u8>,
|
||||||
|
osc_params: [(usize, usize); MAX_OSC_PARAMS],
|
||||||
|
osc_num_params: usize,
|
||||||
|
ignoring: bool,
|
||||||
|
utf8_parser: C,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C> Parser<C>
|
||||||
|
where
|
||||||
|
C: CharAccumulator,
|
||||||
|
{
|
||||||
|
/// Create a new Parser
|
||||||
|
pub fn new() -> Parser {
|
||||||
|
Parser::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn params(&self) -> &Params {
|
||||||
|
&self.params
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn intermediates(&self) -> &[u8] {
|
||||||
|
&self.intermediates[..self.intermediate_idx]
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Advance the parser state
|
||||||
|
///
|
||||||
|
/// Requires a [`Perform`] in case `byte` triggers an action
|
||||||
|
#[inline]
|
||||||
|
pub fn advance<P: Perform>(&mut self, performer: &mut P, byte: u8) {
|
||||||
|
// Utf8 characters are handled out-of-band.
|
||||||
|
if let State::Utf8 = self.state {
|
||||||
|
self.process_utf8(performer, byte);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (state, action) = state_change(self.state, byte);
|
||||||
|
self.perform_state_change(performer, state, action, byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn process_utf8<P>(&mut self, performer: &mut P, byte: u8)
|
||||||
|
where
|
||||||
|
P: Perform,
|
||||||
|
{
|
||||||
|
if let Some(c) = self.utf8_parser.add(byte) {
|
||||||
|
performer.print(c);
|
||||||
|
self.state = State::Ground;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn perform_state_change<P>(&mut self, performer: &mut P, state: State, action: Action, byte: u8)
|
||||||
|
where
|
||||||
|
P: Perform,
|
||||||
|
{
|
||||||
|
match state {
|
||||||
|
State::Anywhere => {
|
||||||
|
// Just run the action
|
||||||
|
self.perform_action(performer, action, byte);
|
||||||
|
}
|
||||||
|
state => {
|
||||||
|
match self.state {
|
||||||
|
State::DcsPassthrough => {
|
||||||
|
self.perform_action(performer, Action::Unhook, byte);
|
||||||
|
}
|
||||||
|
State::OscString => {
|
||||||
|
self.perform_action(performer, Action::OscEnd, byte);
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
|
||||||
|
match action {
|
||||||
|
Action::Nop => (),
|
||||||
|
action => {
|
||||||
|
self.perform_action(performer, action, byte);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match state {
|
||||||
|
State::CsiEntry | State::DcsEntry | State::Escape => {
|
||||||
|
self.perform_action(performer, Action::Clear, byte);
|
||||||
|
}
|
||||||
|
State::DcsPassthrough => {
|
||||||
|
self.perform_action(performer, Action::Hook, byte);
|
||||||
|
}
|
||||||
|
State::OscString => {
|
||||||
|
self.perform_action(performer, Action::OscStart, byte);
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assume the new state
|
||||||
|
self.state = state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Separate method for osc_dispatch that borrows self as read-only
|
||||||
|
///
|
||||||
|
/// The aliasing is needed here for multiple slices into self.osc_raw
|
||||||
|
#[inline]
|
||||||
|
fn osc_dispatch<P: Perform>(&self, performer: &mut P, byte: u8) {
|
||||||
|
let mut slices: [MaybeUninit<&[u8]>; MAX_OSC_PARAMS] =
|
||||||
|
unsafe { MaybeUninit::uninit().assume_init() };
|
||||||
|
|
||||||
|
for (i, slice) in slices.iter_mut().enumerate().take(self.osc_num_params) {
|
||||||
|
let indices = self.osc_params[i];
|
||||||
|
*slice = MaybeUninit::new(&self.osc_raw[indices.0..indices.1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let num_params = self.osc_num_params;
|
||||||
|
let params = &slices[..num_params] as *const [MaybeUninit<&[u8]>] as *const [&[u8]];
|
||||||
|
performer.osc_dispatch(&*params, byte == 0x07);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn perform_action<P: Perform>(&mut self, performer: &mut P, action: Action, byte: u8) {
|
||||||
|
match action {
|
||||||
|
Action::Print => performer.print(byte as char),
|
||||||
|
Action::Execute => performer.execute(byte),
|
||||||
|
Action::Hook => {
|
||||||
|
if self.params.is_full() {
|
||||||
|
self.ignoring = true;
|
||||||
|
} else {
|
||||||
|
self.params.push(self.param);
|
||||||
|
}
|
||||||
|
|
||||||
|
performer.hook(self.params(), self.intermediates(), self.ignoring, byte);
|
||||||
|
}
|
||||||
|
Action::Put => performer.put(byte),
|
||||||
|
Action::OscStart => {
|
||||||
|
self.osc_raw.clear();
|
||||||
|
self.osc_num_params = 0;
|
||||||
|
}
|
||||||
|
Action::OscPut => {
|
||||||
|
#[cfg(feature = "core")]
|
||||||
|
{
|
||||||
|
if self.osc_raw.is_full() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let idx = self.osc_raw.len();
|
||||||
|
|
||||||
|
// Param separator
|
||||||
|
if byte == b';' {
|
||||||
|
let param_idx = self.osc_num_params;
|
||||||
|
match param_idx {
|
||||||
|
// Only process up to MAX_OSC_PARAMS
|
||||||
|
MAX_OSC_PARAMS => return,
|
||||||
|
|
||||||
|
// First param is special - 0 to current byte index
|
||||||
|
0 => {
|
||||||
|
self.osc_params[param_idx] = (0, idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// All other params depend on previous indexing
|
||||||
|
_ => {
|
||||||
|
let prev = self.osc_params[param_idx - 1];
|
||||||
|
let begin = prev.1;
|
||||||
|
self.osc_params[param_idx] = (begin, idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.osc_num_params += 1;
|
||||||
|
} else {
|
||||||
|
self.osc_raw.push(byte);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Action::OscEnd => {
|
||||||
|
let param_idx = self.osc_num_params;
|
||||||
|
let idx = self.osc_raw.len();
|
||||||
|
|
||||||
|
match param_idx {
|
||||||
|
// Finish last parameter if not already maxed
|
||||||
|
MAX_OSC_PARAMS => (),
|
||||||
|
|
||||||
|
// First param is special - 0 to current byte index
|
||||||
|
0 => {
|
||||||
|
self.osc_params[param_idx] = (0, idx);
|
||||||
|
self.osc_num_params += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All other params depend on previous indexing
|
||||||
|
_ => {
|
||||||
|
let prev = self.osc_params[param_idx - 1];
|
||||||
|
let begin = prev.1;
|
||||||
|
self.osc_params[param_idx] = (begin, idx);
|
||||||
|
self.osc_num_params += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.osc_dispatch(performer, byte);
|
||||||
|
}
|
||||||
|
Action::Unhook => performer.unhook(),
|
||||||
|
Action::CsiDispatch => {
|
||||||
|
if self.params.is_full() {
|
||||||
|
self.ignoring = true;
|
||||||
|
} else {
|
||||||
|
self.params.push(self.param);
|
||||||
|
}
|
||||||
|
|
||||||
|
performer.csi_dispatch(self.params(), self.intermediates(), self.ignoring, byte);
|
||||||
|
}
|
||||||
|
Action::EscDispatch => {
|
||||||
|
performer.esc_dispatch(self.intermediates(), self.ignoring, byte);
|
||||||
|
}
|
||||||
|
Action::Collect => {
|
||||||
|
if self.intermediate_idx == MAX_INTERMEDIATES {
|
||||||
|
self.ignoring = true;
|
||||||
|
} else {
|
||||||
|
self.intermediates[self.intermediate_idx] = byte;
|
||||||
|
self.intermediate_idx += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Action::Param => {
|
||||||
|
if self.params.is_full() {
|
||||||
|
self.ignoring = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if byte == b';' {
|
||||||
|
self.params.push(self.param);
|
||||||
|
self.param = 0;
|
||||||
|
} else if byte == b':' {
|
||||||
|
self.params.extend(self.param);
|
||||||
|
self.param = 0;
|
||||||
|
} else {
|
||||||
|
// Continue collecting bytes into param
|
||||||
|
self.param = self.param.saturating_mul(10);
|
||||||
|
self.param = self.param.saturating_add((byte - b'0') as u16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Action::Clear => {
|
||||||
|
// Reset everything on ESC/CSI/DCS entry
|
||||||
|
self.intermediate_idx = 0;
|
||||||
|
self.ignoring = false;
|
||||||
|
self.param = 0;
|
||||||
|
|
||||||
|
self.params.clear();
|
||||||
|
}
|
||||||
|
Action::BeginUtf8 => self.process_utf8(performer, byte),
|
||||||
|
Action::Ignore => (),
|
||||||
|
Action::Nop => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Build a `char` out of bytes
|
||||||
|
pub trait CharAccumulator: Default {
|
||||||
|
/// Build a `char` out of bytes
|
||||||
|
///
|
||||||
|
/// Return `None` when more data is needed
|
||||||
|
fn add(&mut self, byte: u8) -> Option<char>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "utf8")]
|
||||||
|
pub type DefaultCharAccumulator = Utf8Parser;
|
||||||
|
#[cfg(not(feature = "utf8"))]
|
||||||
|
pub type DefaultCharAccumulator = AsciiParser;
|
||||||
|
|
||||||
|
/// Only allow parsing 7-bit ASCII
|
||||||
|
#[derive(Default, Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct AsciiParser;
|
||||||
|
|
||||||
|
impl CharAccumulator for AsciiParser {
|
||||||
|
fn add(&mut self, _byte: u8) -> Option<char> {
|
||||||
|
unreachable!("multi-byte UTF8 characters are unsupported")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Allow parsing UTF-8
|
||||||
|
#[cfg(feature = "utf8")]
|
||||||
|
#[derive(Default, Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct Utf8Parser {
|
||||||
|
utf8_parser: utf8::Parser,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "utf8")]
|
||||||
|
impl CharAccumulator for Utf8Parser {
|
||||||
|
fn add(&mut self, byte: u8) -> Option<char> {
|
||||||
|
let mut c = None;
|
||||||
|
let mut receiver = VtUtf8Receiver(&mut c);
|
||||||
|
self.utf8_parser.advance(&mut receiver, byte);
|
||||||
|
c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "utf8")]
|
||||||
|
struct VtUtf8Receiver<'a>(&'a mut Option<char>);
|
||||||
|
|
||||||
|
#[cfg(feature = "utf8")]
|
||||||
|
impl<'a> utf8::Receiver for VtUtf8Receiver<'a> {
|
||||||
|
fn codepoint(&mut self, c: char) {
|
||||||
|
*self.0 = Some(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn invalid_sequence(&mut self) {
|
||||||
|
*self.0 = Some('<27>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Performs actions requested by the [`Parser`]
|
||||||
|
///
|
||||||
|
/// Actions in this case mean, for example, handling a CSI escape sequence describing cursor
|
||||||
|
/// movement, or simply printing characters to the screen.
|
||||||
|
///
|
||||||
|
/// The methods on this type correspond to actions described in
|
||||||
|
/// <http://vt100.net/emu/dec_ansi_parser>. I've done my best to describe them in
|
||||||
|
/// a useful way in my own words for completeness, but the site should be
|
||||||
|
/// referenced if something isn't clear. If the site disappears at some point in
|
||||||
|
/// the future, consider checking archive.org.
|
||||||
|
pub trait Perform {
|
||||||
|
/// Draw a character to the screen and update states.
|
||||||
|
fn print(&mut self, _c: char) {}
|
||||||
|
|
||||||
|
/// Execute a C0 or C1 control function.
|
||||||
|
fn execute(&mut self, _byte: u8) {}
|
||||||
|
|
||||||
|
/// Invoked when a final character arrives in first part of device control string.
|
||||||
|
///
|
||||||
|
/// The control function should be determined from the private marker, final character, and
|
||||||
|
/// execute with a parameter list. A handler should be selected for remaining characters in the
|
||||||
|
/// string; the handler function should subsequently be called by `put` for every character in
|
||||||
|
/// the control string.
|
||||||
|
///
|
||||||
|
/// The `ignore` flag indicates that more than two intermediates arrived and
|
||||||
|
/// subsequent characters were ignored.
|
||||||
|
fn hook(&mut self, _params: &Params, _intermediates: &[u8], _ignore: bool, _action: u8) {}
|
||||||
|
|
||||||
|
/// Pass bytes as part of a device control string to the handle chosen in `hook`. C0 controls
|
||||||
|
/// will also be passed to the handler.
|
||||||
|
fn put(&mut self, _byte: u8) {}
|
||||||
|
|
||||||
|
/// Called when a device control string is terminated.
|
||||||
|
///
|
||||||
|
/// The previously selected handler should be notified that the DCS has
|
||||||
|
/// terminated.
|
||||||
|
fn unhook(&mut self) {}
|
||||||
|
|
||||||
|
/// Dispatch an operating system command.
|
||||||
|
fn osc_dispatch(&mut self, _params: &[&[u8]], _bell_terminated: bool) {}
|
||||||
|
|
||||||
|
/// A final character has arrived for a CSI sequence
|
||||||
|
///
|
||||||
|
/// The `ignore` flag indicates that either more than two intermediates arrived
|
||||||
|
/// or the number of parameters exceeded the maximum supported length,
|
||||||
|
/// and subsequent characters were ignored.
|
||||||
|
fn csi_dispatch(
|
||||||
|
&mut self,
|
||||||
|
_params: &Params,
|
||||||
|
_intermediates: &[u8],
|
||||||
|
_ignore: bool,
|
||||||
|
_action: u8,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The final character of an escape sequence has arrived.
|
||||||
|
///
|
||||||
|
/// The `ignore` flag indicates that more than two intermediates arrived and
|
||||||
|
/// subsequent characters were ignored.
|
||||||
|
fn esc_dispatch(&mut self, _intermediates: &[u8], _ignore: bool, _byte: u8) {}
|
||||||
|
}
|
143
vendor/anstyle-parse/src/params.rs
vendored
Normal file
143
vendor/anstyle-parse/src/params.rs
vendored
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
//! Fixed size parameters list with optional subparameters.
|
||||||
|
|
||||||
|
use core::fmt::{self, Debug, Formatter};
|
||||||
|
|
||||||
|
pub(crate) const MAX_PARAMS: usize = 32;
|
||||||
|
|
||||||
|
#[derive(Default, Clone, PartialEq, Eq)]
|
||||||
|
pub struct Params {
|
||||||
|
/// Number of subparameters for each parameter.
|
||||||
|
///
|
||||||
|
/// For each entry in the `params` slice, this stores the length of the param as number of
|
||||||
|
/// subparams at the same index as the param in the `params` slice.
|
||||||
|
///
|
||||||
|
/// At the subparam positions the length will always be `0`.
|
||||||
|
subparams: [u8; MAX_PARAMS],
|
||||||
|
|
||||||
|
/// All parameters and subparameters.
|
||||||
|
params: [u16; MAX_PARAMS],
|
||||||
|
|
||||||
|
/// Number of suparameters in the current parameter.
|
||||||
|
current_subparams: u8,
|
||||||
|
|
||||||
|
/// Total number of parameters and subparameters.
|
||||||
|
len: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Params {
|
||||||
|
/// Returns the number of parameters.
|
||||||
|
#[inline]
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.len
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if there are no parameters present.
|
||||||
|
#[inline]
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.len == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns an iterator over all parameters and subparameters.
|
||||||
|
#[inline]
|
||||||
|
pub fn iter(&self) -> ParamsIter<'_> {
|
||||||
|
ParamsIter::new(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if there is no more space for additional parameters.
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn is_full(&self) -> bool {
|
||||||
|
self.len == MAX_PARAMS
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Clear all parameters.
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn clear(&mut self) {
|
||||||
|
self.current_subparams = 0;
|
||||||
|
self.len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add an additional parameter.
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn push(&mut self, item: u16) {
|
||||||
|
self.subparams[self.len - self.current_subparams as usize] = self.current_subparams + 1;
|
||||||
|
self.params[self.len] = item;
|
||||||
|
self.current_subparams = 0;
|
||||||
|
self.len += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add an additional subparameter to the current parameter.
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn extend(&mut self, item: u16) {
|
||||||
|
self.subparams[self.len - self.current_subparams as usize] = self.current_subparams + 1;
|
||||||
|
self.params[self.len] = item;
|
||||||
|
self.current_subparams += 1;
|
||||||
|
self.len += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoIterator for &'a Params {
|
||||||
|
type IntoIter = ParamsIter<'a>;
|
||||||
|
type Item = &'a [u16];
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
self.iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Immutable subparameter iterator.
|
||||||
|
pub struct ParamsIter<'a> {
|
||||||
|
params: &'a Params,
|
||||||
|
index: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ParamsIter<'a> {
|
||||||
|
fn new(params: &'a Params) -> Self {
|
||||||
|
Self { params, index: 0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for ParamsIter<'a> {
|
||||||
|
type Item = &'a [u16];
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
if self.index >= self.params.len() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all subparameters for the current parameter.
|
||||||
|
let num_subparams = self.params.subparams[self.index];
|
||||||
|
let param = &self.params.params[self.index..self.index + num_subparams as usize];
|
||||||
|
|
||||||
|
// Jump to the next parameter.
|
||||||
|
self.index += num_subparams as usize;
|
||||||
|
|
||||||
|
Some(param)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
|
let remaining = self.params.len() - self.index;
|
||||||
|
(remaining, Some(remaining))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for Params {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "[")?;
|
||||||
|
|
||||||
|
for (i, param) in self.iter().enumerate() {
|
||||||
|
if i != 0 {
|
||||||
|
write!(f, ";")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i, subparam) in param.iter().enumerate() {
|
||||||
|
if i != 0 {
|
||||||
|
write!(f, ":")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
subparam.fmt(f)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
write!(f, "]")
|
||||||
|
}
|
||||||
|
}
|
217
vendor/anstyle-parse/src/state/codegen.rs
vendored
Normal file
217
vendor/anstyle-parse/src/state/codegen.rs
vendored
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
use super::{pack, unpack, Action, State};
|
||||||
|
|
||||||
|
use vte_generate_state_changes::generate_state_changes;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn table() {
|
||||||
|
let mut content = vec![];
|
||||||
|
generate_table(&mut content).unwrap();
|
||||||
|
|
||||||
|
let content = String::from_utf8(content).unwrap();
|
||||||
|
let content = codegenrs::rustfmt(&content, None).unwrap();
|
||||||
|
snapbox::assert_eq_path("./src/state/table.rs", content);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::write_literal)]
|
||||||
|
fn generate_table(file: &mut impl std::io::Write) -> std::io::Result<()> {
|
||||||
|
writeln!(
|
||||||
|
file,
|
||||||
|
"// This file is @generated by {}",
|
||||||
|
file!().replace('\\', "/")
|
||||||
|
)?;
|
||||||
|
writeln!(file)?;
|
||||||
|
writeln!(
|
||||||
|
file,
|
||||||
|
"{}",
|
||||||
|
r#"#[rustfmt::skip]
|
||||||
|
pub(crate) const STATE_CHANGES: [[u8; 256]; 16] = ["#
|
||||||
|
)?;
|
||||||
|
|
||||||
|
for (state, entries) in STATE_CHANGES.iter().enumerate() {
|
||||||
|
writeln!(file, " // {:?}", State::try_from(state as u8).unwrap())?;
|
||||||
|
write!(file, " [")?;
|
||||||
|
let mut last_entry = None;
|
||||||
|
for packed in entries {
|
||||||
|
let (next_state, action) = unpack(*packed);
|
||||||
|
if last_entry != Some(packed) {
|
||||||
|
writeln!(file)?;
|
||||||
|
writeln!(file, " // {:?} {:?}", next_state, action)?;
|
||||||
|
write!(file, " ")?;
|
||||||
|
}
|
||||||
|
write!(file, "0x{:0>2x}, ", packed)?;
|
||||||
|
last_entry = Some(packed);
|
||||||
|
}
|
||||||
|
writeln!(file)?;
|
||||||
|
writeln!(file, " ],")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeln!(file, "{}", r#"];"#)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This is the state change table. It's indexed first by current state and then by the next
|
||||||
|
/// character in the pty stream.
|
||||||
|
pub static STATE_CHANGES: [[u8; 256]; 16] = state_changes();
|
||||||
|
generate_state_changes!(state_changes, {
|
||||||
|
Anywhere {
|
||||||
|
0x18 => (Ground, Execute),
|
||||||
|
0x1a => (Ground, Execute),
|
||||||
|
0x1b => (Escape, Nop),
|
||||||
|
},
|
||||||
|
|
||||||
|
Ground {
|
||||||
|
0x00..=0x17 => (Anywhere, Execute),
|
||||||
|
0x19 => (Anywhere, Execute),
|
||||||
|
0x1c..=0x1f => (Anywhere, Execute),
|
||||||
|
0x20..=0x7f => (Anywhere, Print),
|
||||||
|
0x80..=0x8f => (Anywhere, Execute),
|
||||||
|
0x91..=0x9a => (Anywhere, Execute),
|
||||||
|
0x9c => (Anywhere, Execute),
|
||||||
|
// Beginning of UTF-8 2 byte sequence
|
||||||
|
0xc2..=0xdf => (Utf8, BeginUtf8),
|
||||||
|
// Beginning of UTF-8 3 byte sequence
|
||||||
|
0xe0..=0xef => (Utf8, BeginUtf8),
|
||||||
|
// Beginning of UTF-8 4 byte sequence
|
||||||
|
0xf0..=0xf4 => (Utf8, BeginUtf8),
|
||||||
|
},
|
||||||
|
|
||||||
|
Escape {
|
||||||
|
0x00..=0x17 => (Anywhere, Execute),
|
||||||
|
0x19 => (Anywhere, Execute),
|
||||||
|
0x1c..=0x1f => (Anywhere, Execute),
|
||||||
|
0x7f => (Anywhere, Ignore),
|
||||||
|
0x20..=0x2f => (EscapeIntermediate, Collect),
|
||||||
|
0x30..=0x4f => (Ground, EscDispatch),
|
||||||
|
0x51..=0x57 => (Ground, EscDispatch),
|
||||||
|
0x59 => (Ground, EscDispatch),
|
||||||
|
0x5a => (Ground, EscDispatch),
|
||||||
|
0x5c => (Ground, EscDispatch),
|
||||||
|
0x60..=0x7e => (Ground, EscDispatch),
|
||||||
|
0x5b => (CsiEntry, Nop),
|
||||||
|
0x5d => (OscString, Nop),
|
||||||
|
0x50 => (DcsEntry, Nop),
|
||||||
|
0x58 => (SosPmApcString, Nop),
|
||||||
|
0x5e => (SosPmApcString, Nop),
|
||||||
|
0x5f => (SosPmApcString, Nop),
|
||||||
|
},
|
||||||
|
|
||||||
|
EscapeIntermediate {
|
||||||
|
0x00..=0x17 => (Anywhere, Execute),
|
||||||
|
0x19 => (Anywhere, Execute),
|
||||||
|
0x1c..=0x1f => (Anywhere, Execute),
|
||||||
|
0x20..=0x2f => (Anywhere, Collect),
|
||||||
|
0x7f => (Anywhere, Ignore),
|
||||||
|
0x30..=0x7e => (Ground, EscDispatch),
|
||||||
|
},
|
||||||
|
|
||||||
|
CsiEntry {
|
||||||
|
0x00..=0x17 => (Anywhere, Execute),
|
||||||
|
0x19 => (Anywhere, Execute),
|
||||||
|
0x1c..=0x1f => (Anywhere, Execute),
|
||||||
|
0x7f => (Anywhere, Ignore),
|
||||||
|
0x20..=0x2f => (CsiIntermediate, Collect),
|
||||||
|
0x30..=0x39 => (CsiParam, Param),
|
||||||
|
0x3a..=0x3b => (CsiParam, Param),
|
||||||
|
0x3c..=0x3f => (CsiParam, Collect),
|
||||||
|
0x40..=0x7e => (Ground, CsiDispatch),
|
||||||
|
},
|
||||||
|
|
||||||
|
CsiIgnore {
|
||||||
|
0x00..=0x17 => (Anywhere, Execute),
|
||||||
|
0x19 => (Anywhere, Execute),
|
||||||
|
0x1c..=0x1f => (Anywhere, Execute),
|
||||||
|
0x20..=0x3f => (Anywhere, Ignore),
|
||||||
|
0x7f => (Anywhere, Ignore),
|
||||||
|
0x40..=0x7e => (Ground, Nop),
|
||||||
|
},
|
||||||
|
|
||||||
|
CsiParam {
|
||||||
|
0x00..=0x17 => (Anywhere, Execute),
|
||||||
|
0x19 => (Anywhere, Execute),
|
||||||
|
0x1c..=0x1f => (Anywhere, Execute),
|
||||||
|
0x30..=0x39 => (Anywhere, Param),
|
||||||
|
0x3a..=0x3b => (Anywhere, Param),
|
||||||
|
0x7f => (Anywhere, Ignore),
|
||||||
|
0x3c..=0x3f => (CsiIgnore, Nop),
|
||||||
|
0x20..=0x2f => (CsiIntermediate, Collect),
|
||||||
|
0x40..=0x7e => (Ground, CsiDispatch),
|
||||||
|
},
|
||||||
|
|
||||||
|
CsiIntermediate {
|
||||||
|
0x00..=0x17 => (Anywhere, Execute),
|
||||||
|
0x19 => (Anywhere, Execute),
|
||||||
|
0x1c..=0x1f => (Anywhere, Execute),
|
||||||
|
0x20..=0x2f => (Anywhere, Collect),
|
||||||
|
0x7f => (Anywhere, Ignore),
|
||||||
|
0x30..=0x3f => (CsiIgnore, Nop),
|
||||||
|
0x40..=0x7e => (Ground, CsiDispatch),
|
||||||
|
},
|
||||||
|
|
||||||
|
DcsEntry {
|
||||||
|
0x00..=0x17 => (Anywhere, Ignore),
|
||||||
|
0x19 => (Anywhere, Ignore),
|
||||||
|
0x1c..=0x1f => (Anywhere, Ignore),
|
||||||
|
0x7f => (Anywhere, Ignore),
|
||||||
|
0x20..=0x2f => (DcsIntermediate, Collect),
|
||||||
|
0x30..=0x39 => (DcsParam, Param),
|
||||||
|
0x3a..=0x3b => (DcsParam, Param),
|
||||||
|
0x3c..=0x3f => (DcsParam, Collect),
|
||||||
|
0x40..=0x7e => (DcsPassthrough, Nop),
|
||||||
|
},
|
||||||
|
|
||||||
|
DcsIntermediate {
|
||||||
|
0x00..=0x17 => (Anywhere, Ignore),
|
||||||
|
0x19 => (Anywhere, Ignore),
|
||||||
|
0x1c..=0x1f => (Anywhere, Ignore),
|
||||||
|
0x20..=0x2f => (Anywhere, Collect),
|
||||||
|
0x7f => (Anywhere, Ignore),
|
||||||
|
0x30..=0x3f => (DcsIgnore, Nop),
|
||||||
|
0x40..=0x7e => (DcsPassthrough, Nop),
|
||||||
|
},
|
||||||
|
|
||||||
|
DcsIgnore {
|
||||||
|
0x00..=0x17 => (Anywhere, Ignore),
|
||||||
|
0x19 => (Anywhere, Ignore),
|
||||||
|
0x1c..=0x1f => (Anywhere, Ignore),
|
||||||
|
0x20..=0x7f => (Anywhere, Ignore),
|
||||||
|
0x9c => (Ground, Nop),
|
||||||
|
},
|
||||||
|
|
||||||
|
DcsParam {
|
||||||
|
0x00..=0x17 => (Anywhere, Ignore),
|
||||||
|
0x19 => (Anywhere, Ignore),
|
||||||
|
0x1c..=0x1f => (Anywhere, Ignore),
|
||||||
|
0x30..=0x39 => (Anywhere, Param),
|
||||||
|
0x3a..=0x3b => (Anywhere, Param),
|
||||||
|
0x7f => (Anywhere, Ignore),
|
||||||
|
0x3c..=0x3f => (DcsIgnore, Nop),
|
||||||
|
0x20..=0x2f => (DcsIntermediate, Collect),
|
||||||
|
0x40..=0x7e => (DcsPassthrough, Nop),
|
||||||
|
},
|
||||||
|
|
||||||
|
DcsPassthrough {
|
||||||
|
0x00..=0x17 => (Anywhere, Put),
|
||||||
|
0x19 => (Anywhere, Put),
|
||||||
|
0x1c..=0x1f => (Anywhere, Put),
|
||||||
|
0x20..=0x7e => (Anywhere, Put),
|
||||||
|
0x7f => (Anywhere, Ignore),
|
||||||
|
0x9c => (Ground, Nop),
|
||||||
|
},
|
||||||
|
|
||||||
|
SosPmApcString {
|
||||||
|
0x00..=0x17 => (Anywhere, Ignore),
|
||||||
|
0x19 => (Anywhere, Ignore),
|
||||||
|
0x1c..=0x1f => (Anywhere, Ignore),
|
||||||
|
0x20..=0x7f => (Anywhere, Ignore),
|
||||||
|
0x9c => (Ground, Nop),
|
||||||
|
},
|
||||||
|
|
||||||
|
OscString {
|
||||||
|
0x00..=0x06 => (Anywhere, Ignore),
|
||||||
|
0x07 => (Ground, Nop),
|
||||||
|
0x08..=0x17 => (Anywhere, Ignore),
|
||||||
|
0x19 => (Anywhere, Ignore),
|
||||||
|
0x1c..=0x1f => (Anywhere, Ignore),
|
||||||
|
0x20..=0xff => (Anywhere, OscPut),
|
||||||
|
}
|
||||||
|
});
|
169
vendor/anstyle-parse/src/state/definitions.rs
vendored
Normal file
169
vendor/anstyle-parse/src/state/definitions.rs
vendored
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
use core::mem;
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
#[repr(u8)]
|
||||||
|
#[derive(Default)]
|
||||||
|
pub enum State {
|
||||||
|
Anywhere = 0,
|
||||||
|
CsiEntry = 1,
|
||||||
|
CsiIgnore = 2,
|
||||||
|
CsiIntermediate = 3,
|
||||||
|
CsiParam = 4,
|
||||||
|
DcsEntry = 5,
|
||||||
|
DcsIgnore = 6,
|
||||||
|
DcsIntermediate = 7,
|
||||||
|
DcsParam = 8,
|
||||||
|
DcsPassthrough = 9,
|
||||||
|
Escape = 10,
|
||||||
|
EscapeIntermediate = 11,
|
||||||
|
#[default]
|
||||||
|
Ground = 12,
|
||||||
|
OscString = 13,
|
||||||
|
SosPmApcString = 14,
|
||||||
|
Utf8 = 15,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<u8> for State {
|
||||||
|
type Error = u8;
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn try_from(raw: u8) -> Result<Self, Self::Error> {
|
||||||
|
STATES.get(raw as usize).ok_or(raw).copied()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const STATES: [State; 16] = [
|
||||||
|
State::Anywhere,
|
||||||
|
State::CsiEntry,
|
||||||
|
State::CsiIgnore,
|
||||||
|
State::CsiIntermediate,
|
||||||
|
State::CsiParam,
|
||||||
|
State::DcsEntry,
|
||||||
|
State::DcsIgnore,
|
||||||
|
State::DcsIntermediate,
|
||||||
|
State::DcsParam,
|
||||||
|
State::DcsPassthrough,
|
||||||
|
State::Escape,
|
||||||
|
State::EscapeIntermediate,
|
||||||
|
State::Ground,
|
||||||
|
State::OscString,
|
||||||
|
State::SosPmApcString,
|
||||||
|
State::Utf8,
|
||||||
|
];
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
#[repr(u8)]
|
||||||
|
#[derive(Default)]
|
||||||
|
pub enum Action {
|
||||||
|
#[default]
|
||||||
|
Nop = 0,
|
||||||
|
Clear = 1,
|
||||||
|
Collect = 2,
|
||||||
|
CsiDispatch = 3,
|
||||||
|
EscDispatch = 4,
|
||||||
|
Execute = 5,
|
||||||
|
Hook = 6,
|
||||||
|
Ignore = 7,
|
||||||
|
OscEnd = 8,
|
||||||
|
OscPut = 9,
|
||||||
|
OscStart = 10,
|
||||||
|
Param = 11,
|
||||||
|
Print = 12,
|
||||||
|
Put = 13,
|
||||||
|
Unhook = 14,
|
||||||
|
BeginUtf8 = 15,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<u8> for Action {
|
||||||
|
type Error = u8;
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn try_from(raw: u8) -> Result<Self, Self::Error> {
|
||||||
|
ACTIONS.get(raw as usize).ok_or(raw).copied()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ACTIONS: [Action; 16] = [
|
||||||
|
Action::Nop,
|
||||||
|
Action::Clear,
|
||||||
|
Action::Collect,
|
||||||
|
Action::CsiDispatch,
|
||||||
|
Action::EscDispatch,
|
||||||
|
Action::Execute,
|
||||||
|
Action::Hook,
|
||||||
|
Action::Ignore,
|
||||||
|
Action::OscEnd,
|
||||||
|
Action::OscPut,
|
||||||
|
Action::OscStart,
|
||||||
|
Action::Param,
|
||||||
|
Action::Print,
|
||||||
|
Action::Put,
|
||||||
|
Action::Unhook,
|
||||||
|
Action::BeginUtf8,
|
||||||
|
];
|
||||||
|
|
||||||
|
/// Unpack a u8 into a State and Action
|
||||||
|
///
|
||||||
|
/// The implementation of this assumes that there are *precisely* 16 variants for both Action and
|
||||||
|
/// State. Furthermore, it assumes that the enums are tag-only; that is, there is no data in any
|
||||||
|
/// variant.
|
||||||
|
///
|
||||||
|
/// Bad things will happen if those invariants are violated.
|
||||||
|
#[inline(always)]
|
||||||
|
pub const fn unpack(delta: u8) -> (State, Action) {
|
||||||
|
unsafe {
|
||||||
|
(
|
||||||
|
// State is stored in bottom 4 bits
|
||||||
|
mem::transmute(delta & 0x0f),
|
||||||
|
// Action is stored in top 4 bits
|
||||||
|
mem::transmute(delta >> 4),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
#[cfg(test)]
|
||||||
|
pub const fn pack(state: State, action: Action) -> u8 {
|
||||||
|
(action as u8) << 4 | state as u8
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn unpack_state_action() {
|
||||||
|
match unpack(0xee) {
|
||||||
|
(State::SosPmApcString, Action::Unhook) => (),
|
||||||
|
_ => panic!("unpack failed"),
|
||||||
|
}
|
||||||
|
|
||||||
|
match unpack(0x0f) {
|
||||||
|
(State::Utf8, Action::Nop) => (),
|
||||||
|
_ => panic!("unpack failed"),
|
||||||
|
}
|
||||||
|
|
||||||
|
match unpack(0xff) {
|
||||||
|
(State::Utf8, Action::BeginUtf8) => (),
|
||||||
|
_ => panic!("unpack failed"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn pack_state_action() {
|
||||||
|
match unpack(0xee) {
|
||||||
|
(State::SosPmApcString, Action::Unhook) => (),
|
||||||
|
_ => panic!("unpack failed"),
|
||||||
|
}
|
||||||
|
|
||||||
|
match unpack(0x0f) {
|
||||||
|
(State::Utf8, Action::Nop) => (),
|
||||||
|
_ => panic!("unpack failed"),
|
||||||
|
}
|
||||||
|
|
||||||
|
match unpack(0xff) {
|
||||||
|
(State::Utf8, Action::BeginUtf8) => (),
|
||||||
|
_ => panic!("unpack failed"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
41
vendor/anstyle-parse/src/state/mod.rs
vendored
Normal file
41
vendor/anstyle-parse/src/state/mod.rs
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
mod codegen;
|
||||||
|
mod definitions;
|
||||||
|
mod table;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
pub(crate) use definitions::pack;
|
||||||
|
pub(crate) use definitions::unpack;
|
||||||
|
pub use definitions::Action;
|
||||||
|
pub use definitions::State;
|
||||||
|
|
||||||
|
/// Transition to next [`State`]
|
||||||
|
///
|
||||||
|
/// Note: This does not directly support UTF-8.
|
||||||
|
/// - If the data is validated as UTF-8 (e.g. `str`) or single-byte C1 control codes are
|
||||||
|
/// unsupported, then treat [`Action::BeginUtf8`] and [`Action::Execute`] for UTF-8 continuations
|
||||||
|
/// as [`Action::Print`].
|
||||||
|
/// - If the data is not validated, then a UTF-8 state machine will need to be implemented on top,
|
||||||
|
/// starting with [`Action::BeginUtf8`].
|
||||||
|
///
|
||||||
|
/// Note: When [`State::Anywhere`] is returned, revert back to the prior state.
|
||||||
|
#[inline]
|
||||||
|
pub const fn state_change(state: State, byte: u8) -> (State, Action) {
|
||||||
|
// Handle state changes in the anywhere state before evaluating changes
|
||||||
|
// for current state.
|
||||||
|
let mut change = state_change_(State::Anywhere, byte);
|
||||||
|
if change == 0 {
|
||||||
|
change = state_change_(state, byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unpack into a state and action
|
||||||
|
unpack(change)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
const fn state_change_(state: State, byte: u8) -> u8 {
|
||||||
|
let state_idx = state as usize;
|
||||||
|
let byte_idx = byte as usize;
|
||||||
|
|
||||||
|
table::STATE_CHANGES[state_idx][byte_idx]
|
||||||
|
}
|
361
vendor/anstyle-parse/src/state/table.rs
vendored
Normal file
361
vendor/anstyle-parse/src/state/table.rs
vendored
Normal file
@ -0,0 +1,361 @@
|
|||||||
|
// This file is @generated by crates/anstyle-parse/src/state/codegen.rs
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
pub(crate) const STATE_CHANGES: [[u8; 256]; 16] = [
|
||||||
|
// Anywhere
|
||||||
|
[
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Ground Execute
|
||||||
|
0x5c,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00,
|
||||||
|
// Ground Execute
|
||||||
|
0x5c,
|
||||||
|
// Escape Nop
|
||||||
|
0x0a,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
],
|
||||||
|
// CsiEntry
|
||||||
|
[
|
||||||
|
// Anywhere Execute
|
||||||
|
0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00,
|
||||||
|
// Anywhere Execute
|
||||||
|
0x50,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00,
|
||||||
|
// Anywhere Execute
|
||||||
|
0x50, 0x50, 0x50, 0x50,
|
||||||
|
// CsiIntermediate Collect
|
||||||
|
0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23,
|
||||||
|
// CsiParam Param
|
||||||
|
0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
|
||||||
|
// CsiParam Collect
|
||||||
|
0x24, 0x24, 0x24, 0x24,
|
||||||
|
// Ground CsiDispatch
|
||||||
|
0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
|
||||||
|
// Anywhere Ignore
|
||||||
|
0x70,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
],
|
||||||
|
// CsiIgnore
|
||||||
|
[
|
||||||
|
// Anywhere Execute
|
||||||
|
0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00,
|
||||||
|
// Anywhere Execute
|
||||||
|
0x50,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00,
|
||||||
|
// Anywhere Execute
|
||||||
|
0x50, 0x50, 0x50, 0x50,
|
||||||
|
// Anywhere Ignore
|
||||||
|
0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
|
||||||
|
// Ground Nop
|
||||||
|
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
|
||||||
|
// Anywhere Ignore
|
||||||
|
0x70,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
],
|
||||||
|
// CsiIntermediate
|
||||||
|
[
|
||||||
|
// Anywhere Execute
|
||||||
|
0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00,
|
||||||
|
// Anywhere Execute
|
||||||
|
0x50,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00,
|
||||||
|
// Anywhere Execute
|
||||||
|
0x50, 0x50, 0x50, 0x50,
|
||||||
|
// Anywhere Collect
|
||||||
|
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||||
|
// CsiIgnore Nop
|
||||||
|
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||||
|
// Ground CsiDispatch
|
||||||
|
0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
|
||||||
|
// Anywhere Ignore
|
||||||
|
0x70,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
],
|
||||||
|
// CsiParam
|
||||||
|
[
|
||||||
|
// Anywhere Execute
|
||||||
|
0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00,
|
||||||
|
// Anywhere Execute
|
||||||
|
0x50,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00,
|
||||||
|
// Anywhere Execute
|
||||||
|
0x50, 0x50, 0x50, 0x50,
|
||||||
|
// CsiIntermediate Collect
|
||||||
|
0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23,
|
||||||
|
// Anywhere Param
|
||||||
|
0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0,
|
||||||
|
// CsiIgnore Nop
|
||||||
|
0x02, 0x02, 0x02, 0x02,
|
||||||
|
// Ground CsiDispatch
|
||||||
|
0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
|
||||||
|
// Anywhere Ignore
|
||||||
|
0x70,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
],
|
||||||
|
// DcsEntry
|
||||||
|
[
|
||||||
|
// Anywhere Ignore
|
||||||
|
0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00,
|
||||||
|
// Anywhere Ignore
|
||||||
|
0x70,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00,
|
||||||
|
// Anywhere Ignore
|
||||||
|
0x70, 0x70, 0x70, 0x70,
|
||||||
|
// DcsIntermediate Collect
|
||||||
|
0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
|
||||||
|
// DcsParam Param
|
||||||
|
0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8,
|
||||||
|
// DcsParam Collect
|
||||||
|
0x28, 0x28, 0x28, 0x28,
|
||||||
|
// DcsPassthrough Nop
|
||||||
|
0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
|
||||||
|
// Anywhere Ignore
|
||||||
|
0x70,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
],
|
||||||
|
// DcsIgnore
|
||||||
|
[
|
||||||
|
// Anywhere Ignore
|
||||||
|
0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00,
|
||||||
|
// Anywhere Ignore
|
||||||
|
0x70,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00,
|
||||||
|
// Anywhere Ignore
|
||||||
|
0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Ground Nop
|
||||||
|
0x0c,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
],
|
||||||
|
// DcsIntermediate
|
||||||
|
[
|
||||||
|
// Anywhere Ignore
|
||||||
|
0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00,
|
||||||
|
// Anywhere Ignore
|
||||||
|
0x70,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00,
|
||||||
|
// Anywhere Ignore
|
||||||
|
0x70, 0x70, 0x70, 0x70,
|
||||||
|
// Anywhere Collect
|
||||||
|
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||||
|
// DcsIgnore Nop
|
||||||
|
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
|
||||||
|
// DcsPassthrough Nop
|
||||||
|
0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
|
||||||
|
// Anywhere Ignore
|
||||||
|
0x70,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
],
|
||||||
|
// DcsParam
|
||||||
|
[
|
||||||
|
// Anywhere Ignore
|
||||||
|
0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00,
|
||||||
|
// Anywhere Ignore
|
||||||
|
0x70,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00,
|
||||||
|
// Anywhere Ignore
|
||||||
|
0x70, 0x70, 0x70, 0x70,
|
||||||
|
// DcsIntermediate Collect
|
||||||
|
0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
|
||||||
|
// Anywhere Param
|
||||||
|
0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0,
|
||||||
|
// DcsIgnore Nop
|
||||||
|
0x06, 0x06, 0x06, 0x06,
|
||||||
|
// DcsPassthrough Nop
|
||||||
|
0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
|
||||||
|
// Anywhere Ignore
|
||||||
|
0x70,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
],
|
||||||
|
// DcsPassthrough
|
||||||
|
[
|
||||||
|
// Anywhere Put
|
||||||
|
0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00,
|
||||||
|
// Anywhere Put
|
||||||
|
0xd0,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00,
|
||||||
|
// Anywhere Put
|
||||||
|
0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0,
|
||||||
|
// Anywhere Ignore
|
||||||
|
0x70,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Ground Nop
|
||||||
|
0x0c,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
],
|
||||||
|
// Escape
|
||||||
|
[
|
||||||
|
// Anywhere Execute
|
||||||
|
0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00,
|
||||||
|
// Anywhere Execute
|
||||||
|
0x50,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00,
|
||||||
|
// Anywhere Execute
|
||||||
|
0x50, 0x50, 0x50, 0x50,
|
||||||
|
// EscapeIntermediate Collect
|
||||||
|
0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b,
|
||||||
|
// Ground EscDispatch
|
||||||
|
0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
|
||||||
|
// DcsEntry Nop
|
||||||
|
0x05,
|
||||||
|
// Ground EscDispatch
|
||||||
|
0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
|
||||||
|
// SosPmApcString Nop
|
||||||
|
0x0e,
|
||||||
|
// Ground EscDispatch
|
||||||
|
0x4c, 0x4c,
|
||||||
|
// CsiEntry Nop
|
||||||
|
0x01,
|
||||||
|
// Ground EscDispatch
|
||||||
|
0x4c,
|
||||||
|
// OscString Nop
|
||||||
|
0x0d,
|
||||||
|
// SosPmApcString Nop
|
||||||
|
0x0e, 0x0e,
|
||||||
|
// Ground EscDispatch
|
||||||
|
0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
|
||||||
|
// Anywhere Ignore
|
||||||
|
0x70,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
],
|
||||||
|
// EscapeIntermediate
|
||||||
|
[
|
||||||
|
// Anywhere Execute
|
||||||
|
0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00,
|
||||||
|
// Anywhere Execute
|
||||||
|
0x50,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00,
|
||||||
|
// Anywhere Execute
|
||||||
|
0x50, 0x50, 0x50, 0x50,
|
||||||
|
// Anywhere Collect
|
||||||
|
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||||
|
// Ground EscDispatch
|
||||||
|
0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
|
||||||
|
// Anywhere Ignore
|
||||||
|
0x70,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
],
|
||||||
|
// Ground
|
||||||
|
[
|
||||||
|
// Anywhere Execute
|
||||||
|
0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00,
|
||||||
|
// Anywhere Execute
|
||||||
|
0x50,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00,
|
||||||
|
// Anywhere Execute
|
||||||
|
0x50, 0x50, 0x50, 0x50,
|
||||||
|
// Anywhere Print
|
||||||
|
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
|
||||||
|
// Anywhere Execute
|
||||||
|
0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00,
|
||||||
|
// Anywhere Execute
|
||||||
|
0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00,
|
||||||
|
// Anywhere Execute
|
||||||
|
0x50,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Utf8 BeginUtf8
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
],
|
||||||
|
// OscString
|
||||||
|
[
|
||||||
|
// Anywhere Ignore
|
||||||
|
0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
|
||||||
|
// Ground Nop
|
||||||
|
0x0c,
|
||||||
|
// Anywhere Ignore
|
||||||
|
0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00,
|
||||||
|
// Anywhere Ignore
|
||||||
|
0x70,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00,
|
||||||
|
// Anywhere Ignore
|
||||||
|
0x70, 0x70, 0x70, 0x70,
|
||||||
|
// Anywhere OscPut
|
||||||
|
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||||
|
],
|
||||||
|
// SosPmApcString
|
||||||
|
[
|
||||||
|
// Anywhere Ignore
|
||||||
|
0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00,
|
||||||
|
// Anywhere Ignore
|
||||||
|
0x70,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00,
|
||||||
|
// Anywhere Ignore
|
||||||
|
0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Ground Nop
|
||||||
|
0x0c,
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
],
|
||||||
|
// Utf8
|
||||||
|
[
|
||||||
|
// Anywhere Nop
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
],
|
||||||
|
];
|
1
vendor/anstyle-query/.cargo-checksum.json
vendored
Normal file
1
vendor/anstyle-query/.cargo-checksum.json
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"files":{"Cargo.lock":"dbef8401bf3e334d4f3a8230f2506dbc1439dd3aea07cbbc174125eb5fef0eed","Cargo.toml":"4b85a1d05db43bc0aa4ccc814c9e6b922d6a811aa79e02e614f5baccfa803a05","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"6efb0476a1cc085077ed49357026d8c173bf33017278ef440f222fb9cbcb66e6","README.md":"94cda3914d2693b89e0b5855ffff04b971823f6cbae885a1610353254a269ed9","examples/query.rs":"d9f5b94967c7b9579ee399c481148b07fd0fb371f4a5d557017ff86cb5034543","src/lib.rs":"4dd716dbe701acc5644b25d84503d53ea8bc8fb9bf81914b2183526edc63826c","src/windows.rs":"44272f13079fbaed8c16426950c24d9de94d81eba0636138d8e44346eccc0acd"},"package":"e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"}
|
76
vendor/anstyle-query/Cargo.lock
generated
vendored
Normal file
76
vendor/anstyle-query/Cargo.lock
generated
vendored
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-query"
|
||||||
|
version = "1.0.2"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm",
|
||||||
|
"windows_aarch64_msvc",
|
||||||
|
"windows_i686_gnu",
|
||||||
|
"windows_i686_msvc",
|
||||||
|
"windows_x86_64_gnu",
|
||||||
|
"windows_x86_64_gnullvm",
|
||||||
|
"windows_x86_64_msvc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
80
vendor/anstyle-query/Cargo.toml
vendored
Normal file
80
vendor/anstyle-query/Cargo.toml
vendored
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
# 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.70.0"
|
||||||
|
name = "anstyle-query"
|
||||||
|
version = "1.0.2"
|
||||||
|
include = [
|
||||||
|
"build.rs",
|
||||||
|
"src/**/*",
|
||||||
|
"Cargo.toml",
|
||||||
|
"Cargo.lock",
|
||||||
|
"LICENSE*",
|
||||||
|
"README.md",
|
||||||
|
"benches/**/*",
|
||||||
|
"examples/**/*",
|
||||||
|
]
|
||||||
|
description = "Look up colored console capabilities"
|
||||||
|
readme = "README.md"
|
||||||
|
keywords = [
|
||||||
|
"cli",
|
||||||
|
"color",
|
||||||
|
"no-std",
|
||||||
|
"terminal",
|
||||||
|
"ansi",
|
||||||
|
]
|
||||||
|
categories = ["command-line-interface"]
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
repository = "https://github.com/rust-cli/anstyle"
|
||||||
|
|
||||||
|
[[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 -->"
|
||||||
|
|
||||||
|
[target."cfg(windows)".dependencies.windows-sys]
|
||||||
|
version = "0.52.0"
|
||||||
|
features = [
|
||||||
|
"Win32_System_Console",
|
||||||
|
"Win32_Foundation",
|
||||||
|
]
|
202
vendor/anstyle-query/LICENSE-APACHE
vendored
Normal file
202
vendor/anstyle-query/LICENSE-APACHE
vendored
Normal file
@ -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.
|
||||||
|
|
19
vendor/anstyle-query/LICENSE-MIT
vendored
Normal file
19
vendor/anstyle-query/LICENSE-MIT
vendored
Normal file
@ -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.
|
15
vendor/anstyle-query/README.md
vendored
Normal file
15
vendor/anstyle-query/README.md
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# anstyle-query
|
||||||
|
|
||||||
|
> **Low level terminal capability lookups**
|
||||||
|
|
||||||
|
[![Documentation](https://img.shields.io/badge/docs-master-blue.svg)][Documentation]
|
||||||
|
![License](https://img.shields.io/crates/l/anstyle-query.svg)
|
||||||
|
[![Crates Status](https://img.shields.io/crates/v/anstyle-query.svg)](https://crates.io/crates/anstyle-query)
|
||||||
|
|
||||||
|
## [Contribute](../../CONTRIBUTING.md)
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Dual-licensed under [MIT](../../LICENSE-MIT) or [Apache 2.0](../../LICENSE-APACHE)
|
||||||
|
|
||||||
|
[Documentation]: https://docs.rs/anstyle-query
|
24
vendor/anstyle-query/examples/query.rs
vendored
Normal file
24
vendor/anstyle-query/examples/query.rs
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
fn main() {
|
||||||
|
println!("clicolor: {:?}", anstyle_query::clicolor());
|
||||||
|
println!("clicolor_force: {}", anstyle_query::clicolor_force());
|
||||||
|
println!("no_color: {}", anstyle_query::no_color());
|
||||||
|
println!(
|
||||||
|
"term_supports_ansi_color: {}",
|
||||||
|
anstyle_query::term_supports_ansi_color()
|
||||||
|
);
|
||||||
|
println!(
|
||||||
|
"term_supports_color: {}",
|
||||||
|
anstyle_query::term_supports_color()
|
||||||
|
);
|
||||||
|
println!("truecolor: {}", anstyle_query::truecolor());
|
||||||
|
println!(
|
||||||
|
"enable_ansi_colors: {:?}",
|
||||||
|
anstyle_query::windows::enable_ansi_colors()
|
||||||
|
);
|
||||||
|
#[cfg(windows)]
|
||||||
|
println!(
|
||||||
|
" enable_virtual_terminal_processing: {:?}",
|
||||||
|
anstyle_query::windows::enable_virtual_terminal_processing()
|
||||||
|
);
|
||||||
|
println!("is_ci: {:?}", anstyle_query::is_ci());
|
||||||
|
}
|
134
vendor/anstyle-query/src/lib.rs
vendored
Normal file
134
vendor/anstyle-query/src/lib.rs
vendored
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
pub mod windows;
|
||||||
|
|
||||||
|
/// Check [CLICOLOR] status
|
||||||
|
///
|
||||||
|
/// - When `true`, ANSI colors are supported and should be used when the program isn't piped,
|
||||||
|
/// similar to [`term_supports_color`]
|
||||||
|
/// - When `false`, don’t output ANSI color escape codes, similar to [`no_color`]
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
/// - [terminfo](https://crates.io/crates/terminfo) or [term](https://crates.io/crates/term) for
|
||||||
|
/// checking termcaps
|
||||||
|
/// - [termbg](https://crates.io/crates/termbg) for detecting background color
|
||||||
|
///
|
||||||
|
/// [CLICOLOR]: https://bixense.com/clicolors/
|
||||||
|
#[inline]
|
||||||
|
pub fn clicolor() -> Option<bool> {
|
||||||
|
let value = std::env::var_os("CLICOLOR")?;
|
||||||
|
Some(value != "0")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check [CLICOLOR_FORCE] status
|
||||||
|
///
|
||||||
|
/// ANSI colors should be enabled no matter what.
|
||||||
|
///
|
||||||
|
/// [CLICOLOR_FORCE]: https://bixense.com/clicolors/
|
||||||
|
#[inline]
|
||||||
|
pub fn clicolor_force() -> bool {
|
||||||
|
let value = std::env::var_os("CLICOLOR_FORCE");
|
||||||
|
value
|
||||||
|
.as_deref()
|
||||||
|
.unwrap_or_else(|| std::ffi::OsStr::new("0"))
|
||||||
|
!= "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check [NO_COLOR] status
|
||||||
|
///
|
||||||
|
/// When `true`, should prevent the addition of ANSI color.
|
||||||
|
///
|
||||||
|
/// User-level configuration files and per-instance command-line arguments should override
|
||||||
|
/// [NO_COLOR]. A user should be able to export `$NO_COLOR` in their shell configuration file as a
|
||||||
|
/// default, but configure a specific program in its configuration file to specifically enable
|
||||||
|
/// color.
|
||||||
|
///
|
||||||
|
/// [NO_COLOR]: https://no-color.org/
|
||||||
|
#[inline]
|
||||||
|
pub fn no_color() -> bool {
|
||||||
|
let value = std::env::var_os("NO_COLOR");
|
||||||
|
value.as_deref().unwrap_or_else(|| std::ffi::OsStr::new("")) != ""
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check `TERM` for color support
|
||||||
|
#[inline]
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
pub fn term_supports_color() -> bool {
|
||||||
|
match std::env::var_os("TERM") {
|
||||||
|
// If TERM isn't set, then we are in a weird environment that
|
||||||
|
// probably doesn't support colors.
|
||||||
|
None => return false,
|
||||||
|
Some(k) => {
|
||||||
|
if k == "dumb" {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check `TERM` for color support
|
||||||
|
#[inline]
|
||||||
|
#[cfg(windows)]
|
||||||
|
pub fn term_supports_color() -> bool {
|
||||||
|
// On Windows, if TERM isn't set, then we shouldn't automatically
|
||||||
|
// assume that colors aren't allowed. This is unlike Unix environments
|
||||||
|
// where TERM is more rigorously set.
|
||||||
|
if let Some(k) = std::env::var_os("TERM") {
|
||||||
|
if k == "dumb" {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check `TERM` for ANSI color support
|
||||||
|
#[inline]
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
pub fn term_supports_ansi_color() -> bool {
|
||||||
|
term_supports_color()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check `TERM` for ANSI color support
|
||||||
|
#[inline]
|
||||||
|
#[cfg(windows)]
|
||||||
|
pub fn term_supports_ansi_color() -> bool {
|
||||||
|
match std::env::var_os("TERM") {
|
||||||
|
// If TERM isn't set, then we are in a weird environment that
|
||||||
|
// probably doesn't support ansi.
|
||||||
|
None => return false,
|
||||||
|
Some(k) => {
|
||||||
|
// cygwin doesn't seem to support ANSI escape sequences
|
||||||
|
// and instead has its own variety. However, the Windows
|
||||||
|
// console API may be available.
|
||||||
|
if k == "dumb" || k == "cygwin" {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check [COLORTERM] for truecolor support
|
||||||
|
///
|
||||||
|
/// [COLORTERM]: https://github.com/termstandard/colors
|
||||||
|
#[inline]
|
||||||
|
pub fn truecolor() -> bool {
|
||||||
|
let value = std::env::var_os("COLORTERM");
|
||||||
|
let value = value.as_deref().unwrap_or_default();
|
||||||
|
value == "truecolor" || value == "24bit"
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Report whether this is running in CI
|
||||||
|
///
|
||||||
|
/// CI is a common environment where, despite being piped, ansi color codes are supported
|
||||||
|
///
|
||||||
|
/// This is not as exhaustive as you'd find in a crate like `is_ci` but it should work in enough
|
||||||
|
/// cases.
|
||||||
|
#[inline]
|
||||||
|
pub fn is_ci() -> bool {
|
||||||
|
// Assuming its CI based on presence because who would be setting `CI=false`?
|
||||||
|
//
|
||||||
|
// This makes it easier to all of the potential values when considering our known values:
|
||||||
|
// - Gitlab and Github set it to `true`
|
||||||
|
// - Woodpecker sets it to `woodpecker`
|
||||||
|
std::env::var_os("CI").is_some()
|
||||||
|
}
|
78
vendor/anstyle-query/src/windows.rs
vendored
Normal file
78
vendor/anstyle-query/src/windows.rs
vendored
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
//! Windows-specific style queries
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
mod windows_console {
|
||||||
|
use std::os::windows::io::AsRawHandle;
|
||||||
|
use std::os::windows::io::RawHandle;
|
||||||
|
|
||||||
|
use windows_sys::Win32::System::Console::CONSOLE_MODE;
|
||||||
|
use windows_sys::Win32::System::Console::ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||||
|
|
||||||
|
fn enable_vt(handle: RawHandle) -> std::io::Result<()> {
|
||||||
|
unsafe {
|
||||||
|
let handle = std::mem::transmute(handle);
|
||||||
|
if handle == 0 {
|
||||||
|
return Err(std::io::Error::new(
|
||||||
|
std::io::ErrorKind::BrokenPipe,
|
||||||
|
"console is detached",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut dwmode: CONSOLE_MODE = 0;
|
||||||
|
if windows_sys::Win32::System::Console::GetConsoleMode(handle, &mut dwmode) == 0 {
|
||||||
|
return Err(std::io::Error::last_os_error());
|
||||||
|
}
|
||||||
|
|
||||||
|
dwmode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||||
|
if windows_sys::Win32::System::Console::SetConsoleMode(handle, dwmode) == 0 {
|
||||||
|
return Err(std::io::Error::last_os_error());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enable_virtual_terminal_processing() -> std::io::Result<()> {
|
||||||
|
let stdout = std::io::stdout();
|
||||||
|
let stdout_handle = stdout.as_raw_handle();
|
||||||
|
let stderr = std::io::stderr();
|
||||||
|
let stderr_handle = stderr.as_raw_handle();
|
||||||
|
|
||||||
|
enable_vt(stdout_handle)?;
|
||||||
|
if stdout_handle != stderr_handle {
|
||||||
|
enable_vt(stderr_handle)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn enable_ansi_colors() -> Option<bool> {
|
||||||
|
Some(
|
||||||
|
enable_virtual_terminal_processing()
|
||||||
|
.map(|_| true)
|
||||||
|
.unwrap_or(false),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
mod windows_console {
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn enable_ansi_colors() -> Option<bool> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Enable ANSI escape codes (ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
||||||
|
///
|
||||||
|
/// For non-windows systems, returns `None`
|
||||||
|
pub fn enable_ansi_colors() -> Option<bool> {
|
||||||
|
windows_console::enable_ansi_colors()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Raw ENABLE_VIRTUAL_TERMINAL_PROCESSING on stdout/stderr
|
||||||
|
#[cfg(windows)]
|
||||||
|
pub fn enable_virtual_terminal_processing() -> std::io::Result<()> {
|
||||||
|
windows_console::enable_virtual_terminal_processing()
|
||||||
|
}
|
1
vendor/anstyle-wincon/.cargo-checksum.json
vendored
Normal file
1
vendor/anstyle-wincon/.cargo-checksum.json
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"files":{"Cargo.lock":"3cc0f5705ebb0bb446d6f88f71832d2db70bee8c78a545343a755e2a969212a3","Cargo.toml":"5a090b294286cb22bed379e818f8657da219f62fe0e1e8eb21e91aaaf875c139","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"73b0d84e4b954ce904a00043379767ae2a5f8d4f40564639cee230f639fe4dae","README.md":"513a578c6c2ea39a811e2038358e512cbc0c709e3a7c18303871ec2c52ebbeec","examples/dump-wincon.rs":"bd0ffadd14eed711fc74d64caff5ce98bb5c5b3f0b313b54ac759b5a6c6a289b","examples/set-wincon.rs":"b8bc444537449bf334a1e26dd010986c16cb260567f87ae9597fc869c936fe6a","src/ansi.rs":"1b0166d064fe261bc012acca2f3ff442703a774e5fa4b8e96f63dce87b7e73d1","src/lib.rs":"4b4415a0684901bab712dbe94aec960792760aa1db5505adacfdc43db2cd93a7","src/stream.rs":"afdbd6e314127bd412e81894a857cb95fe3140e2b994e17e4e5580ef113a4159","src/windows.rs":"e4aeae1b32f6348b6b9c54e0cd54d9a3c08c6f250c7313fcaa59e3d8a8f51c97"},"package":"1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"}
|
90
vendor/anstyle-wincon/Cargo.lock
generated
vendored
Normal file
90
vendor/anstyle-wincon/Cargo.lock
generated
vendored
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-wincon"
|
||||||
|
version = "3.0.2"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"lexopt",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lexopt"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baff4b617f7df3d896f97fe922b64817f6cd9a756bb81d40f8883f2f66dcb401"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm",
|
||||||
|
"windows_aarch64_msvc",
|
||||||
|
"windows_i686_gnu",
|
||||||
|
"windows_i686_msvc",
|
||||||
|
"windows_x86_64_gnu",
|
||||||
|
"windows_x86_64_gnullvm",
|
||||||
|
"windows_x86_64_msvc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
94
vendor/anstyle-wincon/Cargo.toml
vendored
Normal file
94
vendor/anstyle-wincon/Cargo.toml
vendored
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
# 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.70.0"
|
||||||
|
name = "anstyle-wincon"
|
||||||
|
version = "3.0.2"
|
||||||
|
include = [
|
||||||
|
"build.rs",
|
||||||
|
"src/**/*",
|
||||||
|
"Cargo.toml",
|
||||||
|
"Cargo.lock",
|
||||||
|
"LICENSE*",
|
||||||
|
"README.md",
|
||||||
|
"benches/**/*",
|
||||||
|
"examples/**/*",
|
||||||
|
]
|
||||||
|
description = "Styling legacy Windows terminals"
|
||||||
|
homepage = "https://github.com/rust-cli/anstyle"
|
||||||
|
readme = "README.md"
|
||||||
|
keywords = [
|
||||||
|
"ansi",
|
||||||
|
"terminal",
|
||||||
|
"color",
|
||||||
|
"windows",
|
||||||
|
]
|
||||||
|
categories = ["command-line-interface"]
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
repository = "https://github.com/rust-cli/anstyle.git"
|
||||||
|
|
||||||
|
[package.metadata.docs.rs]
|
||||||
|
features = []
|
||||||
|
rustdoc-args = [
|
||||||
|
"--cfg",
|
||||||
|
"docsrs",
|
||||||
|
]
|
||||||
|
targets = ["x86_64-pc-windows-msvc"]
|
||||||
|
|
||||||
|
[[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 -->"
|
||||||
|
|
||||||
|
[dependencies.anstyle]
|
||||||
|
version = "1.0.0"
|
||||||
|
|
||||||
|
[dev-dependencies.lexopt]
|
||||||
|
version = "0.3.0"
|
||||||
|
|
||||||
|
[target."cfg(windows)".dependencies.windows-sys]
|
||||||
|
version = "0.52.0"
|
||||||
|
features = [
|
||||||
|
"Win32_System_Console",
|
||||||
|
"Win32_Foundation",
|
||||||
|
]
|
202
vendor/anstyle-wincon/LICENSE-APACHE
vendored
Normal file
202
vendor/anstyle-wincon/LICENSE-APACHE
vendored
Normal file
@ -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.
|
||||||
|
|
19
vendor/anstyle-wincon/LICENSE-MIT
vendored
Normal file
19
vendor/anstyle-wincon/LICENSE-MIT
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
Copyright (c) 2015 Josh Triplett, 2022 The rust-cli Developers
|
||||||
|
|
||||||
|
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.
|
30
vendor/anstyle-wincon/README.md
vendored
Normal file
30
vendor/anstyle-wincon/README.md
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# anstyle-wincon
|
||||||
|
|
||||||
|
> Styling legacy Windows terminals
|
||||||
|
|
||||||
|
[![Documentation](https://img.shields.io/badge/docs-master-blue.svg)][Documentation]
|
||||||
|
![License](https://img.shields.io/crates/l/anstyle-wincon.svg)
|
||||||
|
[![Crates Status](https://img.shields.io/crates/v/anstyle-wincon.svg)](https://crates.io/crates/anstyle-wincon)
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
|
### Contribution
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
### Special Thanks
|
||||||
|
|
||||||
|
[burntsushi](https://github.com/burntsushi) for [termcolor](https://github.com/burntsushi/termcolor) as I don't know Windows either :)
|
||||||
|
|
||||||
|
[Crates.io]: https://crates.io/crates/anstyle-wincon
|
||||||
|
[Documentation]: https://docs.rs/anstyle-wincon
|
139
vendor/anstyle-wincon/examples/dump-wincon.rs
vendored
Normal file
139
vendor/anstyle-wincon/examples/dump-wincon.rs
vendored
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
use anstyle_wincon::WinconStream as _;
|
||||||
|
|
||||||
|
fn main() -> Result<(), lexopt::Error> {
|
||||||
|
let args = Args::parse()?;
|
||||||
|
let stdout = std::io::stdout();
|
||||||
|
let mut stdout = stdout.lock();
|
||||||
|
|
||||||
|
for fixed in 0..16 {
|
||||||
|
let style = style(fixed, args.layer, args.effects);
|
||||||
|
let _ = print_number(&mut stdout, fixed, style);
|
||||||
|
if fixed == 7 || fixed == 15 {
|
||||||
|
let _ = stdout.write_colored(None, None, &b"\n"[..]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for r in 0..6 {
|
||||||
|
let _ = stdout.write_colored(None, None, &b"\n"[..]);
|
||||||
|
for g in 0..6 {
|
||||||
|
for b in 0..6 {
|
||||||
|
let fixed = r * 36 + g * 6 + b + 16;
|
||||||
|
let style = style(fixed, args.layer, args.effects);
|
||||||
|
let _ = print_number(&mut stdout, fixed, style);
|
||||||
|
}
|
||||||
|
let _ = stdout.write_colored(None, None, &b"\n"[..]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for c in 0..24 {
|
||||||
|
if 0 == c % 8 {
|
||||||
|
let _ = stdout.write_colored(None, None, &b"\n"[..]);
|
||||||
|
}
|
||||||
|
let fixed = 232 + c;
|
||||||
|
let style = style(fixed, args.layer, args.effects);
|
||||||
|
let _ = print_number(&mut stdout, fixed, style);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn style(fixed: u8, layer: Layer, effects: anstyle::Effects) -> anstyle::Style {
|
||||||
|
let color = anstyle::Ansi256Color(fixed).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 std::io::StdoutLock<'static>,
|
||||||
|
fixed: u8,
|
||||||
|
style: anstyle::Style,
|
||||||
|
) -> std::io::Result<()> {
|
||||||
|
let fg = style.get_fg_color().and_then(|c| match c {
|
||||||
|
anstyle::Color::Ansi(c) => Some(c),
|
||||||
|
anstyle::Color::Ansi256(c) => c.into_ansi(),
|
||||||
|
anstyle::Color::Rgb(_) => None,
|
||||||
|
});
|
||||||
|
let bg = style.get_bg_color().and_then(|c| match c {
|
||||||
|
anstyle::Color::Ansi(c) => Some(c),
|
||||||
|
anstyle::Color::Ansi256(c) => c.into_ansi(),
|
||||||
|
anstyle::Color::Rgb(_) => None,
|
||||||
|
});
|
||||||
|
|
||||||
|
stdout
|
||||||
|
.write_colored(fg, bg, format!("{:>4}", fixed).as_bytes())
|
||||||
|
.map(|_| ())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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::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)
|
||||||
|
}
|
||||||
|
}
|
58
vendor/anstyle-wincon/examples/set-wincon.rs
vendored
Normal file
58
vendor/anstyle-wincon/examples/set-wincon.rs
vendored
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#![cfg_attr(not(windows), allow(dead_code))]
|
||||||
|
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
fn main() {
|
||||||
|
panic!("unsupported");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
fn main() -> Result<(), lexopt::Error> {
|
||||||
|
use anstyle_wincon::WinconStream as _;
|
||||||
|
|
||||||
|
let args = Args::parse()?;
|
||||||
|
let stdout = std::io::stdout();
|
||||||
|
let mut stdout = stdout.lock();
|
||||||
|
|
||||||
|
let fg = args.fg.and_then(|c| c.into_ansi());
|
||||||
|
let bg = args.bg.and_then(|c| c.into_ansi());
|
||||||
|
|
||||||
|
let _ = stdout.write_colored(fg, bg, "".as_bytes());
|
||||||
|
|
||||||
|
std::mem::forget(stdout);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct Args {
|
||||||
|
fg: Option<anstyle::Ansi256Color>,
|
||||||
|
bg: Option<anstyle::Ansi256Color>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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("fg") => {
|
||||||
|
res.fg = Some(
|
||||||
|
args.value()?
|
||||||
|
.parse_with(|s| s.parse::<u8>().map(anstyle::Ansi256Color))?,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Long("bg") => {
|
||||||
|
res.fg = Some(
|
||||||
|
args.value()?
|
||||||
|
.parse_with(|s| s.parse::<u8>().map(anstyle::Ansi256Color))?,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => return Err(arg.unexpected()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
}
|
25
vendor/anstyle-wincon/src/ansi.rs
vendored
Normal file
25
vendor/anstyle-wincon/src/ansi.rs
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
//! Low-level ANSI-styling
|
||||||
|
|
||||||
|
/// Write ANSI colored text to the stream
|
||||||
|
pub fn write_colored<S: std::io::Write>(
|
||||||
|
stream: &mut S,
|
||||||
|
fg: Option<anstyle::AnsiColor>,
|
||||||
|
bg: Option<anstyle::AnsiColor>,
|
||||||
|
data: &[u8],
|
||||||
|
) -> std::io::Result<usize> {
|
||||||
|
let non_default = fg.is_some() || bg.is_some();
|
||||||
|
|
||||||
|
if non_default {
|
||||||
|
if let Some(fg) = fg {
|
||||||
|
write!(stream, "{}", fg.render_fg())?;
|
||||||
|
}
|
||||||
|
if let Some(bg) = bg {
|
||||||
|
write!(stream, "{}", bg.render_bg())?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let written = stream.write(data)?;
|
||||||
|
if non_default {
|
||||||
|
write!(stream, "{}", anstyle::Reset.render())?;
|
||||||
|
}
|
||||||
|
Ok(written)
|
||||||
|
}
|
18
vendor/anstyle-wincon/src/lib.rs
vendored
Normal file
18
vendor/anstyle-wincon/src/lib.rs
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
//! Styling legacy Windows terminals
|
||||||
|
//!
|
||||||
|
//! See [`WinconStream`]
|
||||||
|
//!
|
||||||
|
//! This fills a similar role as [`winapi-util`](https://crates.io/crates/winapi-util) does for
|
||||||
|
//! [`termcolor`](https://crates.io/crates/termcolor) with the differences
|
||||||
|
//! - Uses `windows-sys` rather than `winapi`
|
||||||
|
//! - Uses [`anstyle`](https://crates.io/crates/termcolor) rather than defining its own types
|
||||||
|
//! - More focused, smaller
|
||||||
|
|
||||||
|
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||||
|
|
||||||
|
pub mod ansi;
|
||||||
|
mod stream;
|
||||||
|
#[cfg(windows)]
|
||||||
|
pub mod windows;
|
||||||
|
|
||||||
|
pub use stream::WinconStream;
|
178
vendor/anstyle-wincon/src/stream.rs
vendored
Normal file
178
vendor/anstyle-wincon/src/stream.rs
vendored
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
/// Extend `std::io::Write` with wincon styling
|
||||||
|
pub trait WinconStream {
|
||||||
|
/// Write colored text to the stream
|
||||||
|
fn write_colored(
|
||||||
|
&mut self,
|
||||||
|
fg: Option<anstyle::AnsiColor>,
|
||||||
|
bg: Option<anstyle::AnsiColor>,
|
||||||
|
data: &[u8],
|
||||||
|
) -> std::io::Result<usize>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WinconStream for Box<dyn std::io::Write> {
|
||||||
|
fn write_colored(
|
||||||
|
&mut self,
|
||||||
|
fg: Option<anstyle::AnsiColor>,
|
||||||
|
bg: Option<anstyle::AnsiColor>,
|
||||||
|
data: &[u8],
|
||||||
|
) -> std::io::Result<usize> {
|
||||||
|
crate::ansi::write_colored(self, fg, bg, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WinconStream for &'_ mut Box<dyn std::io::Write> {
|
||||||
|
fn write_colored(
|
||||||
|
&mut self,
|
||||||
|
fg: Option<anstyle::AnsiColor>,
|
||||||
|
bg: Option<anstyle::AnsiColor>,
|
||||||
|
data: &[u8],
|
||||||
|
) -> std::io::Result<usize> {
|
||||||
|
(**self).write_colored(fg, bg, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WinconStream for std::fs::File {
|
||||||
|
fn write_colored(
|
||||||
|
&mut self,
|
||||||
|
fg: Option<anstyle::AnsiColor>,
|
||||||
|
bg: Option<anstyle::AnsiColor>,
|
||||||
|
data: &[u8],
|
||||||
|
) -> std::io::Result<usize> {
|
||||||
|
crate::ansi::write_colored(self, fg, bg, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WinconStream for &'_ mut std::fs::File {
|
||||||
|
fn write_colored(
|
||||||
|
&mut self,
|
||||||
|
fg: Option<anstyle::AnsiColor>,
|
||||||
|
bg: Option<anstyle::AnsiColor>,
|
||||||
|
data: &[u8],
|
||||||
|
) -> std::io::Result<usize> {
|
||||||
|
(**self).write_colored(fg, bg, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WinconStream for Vec<u8> {
|
||||||
|
fn write_colored(
|
||||||
|
&mut self,
|
||||||
|
fg: Option<anstyle::AnsiColor>,
|
||||||
|
bg: Option<anstyle::AnsiColor>,
|
||||||
|
data: &[u8],
|
||||||
|
) -> std::io::Result<usize> {
|
||||||
|
crate::ansi::write_colored(self, fg, bg, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WinconStream for &'_ mut Vec<u8> {
|
||||||
|
fn write_colored(
|
||||||
|
&mut self,
|
||||||
|
fg: Option<anstyle::AnsiColor>,
|
||||||
|
bg: Option<anstyle::AnsiColor>,
|
||||||
|
data: &[u8],
|
||||||
|
) -> std::io::Result<usize> {
|
||||||
|
(**self).write_colored(fg, bg, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WinconStream for std::io::Stdout {
|
||||||
|
fn write_colored(
|
||||||
|
&mut self,
|
||||||
|
fg: Option<anstyle::AnsiColor>,
|
||||||
|
bg: Option<anstyle::AnsiColor>,
|
||||||
|
data: &[u8],
|
||||||
|
) -> std::io::Result<usize> {
|
||||||
|
// Ensure exclusive access
|
||||||
|
self.lock().write_colored(fg, bg, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WinconStream for std::io::Stderr {
|
||||||
|
fn write_colored(
|
||||||
|
&mut self,
|
||||||
|
fg: Option<anstyle::AnsiColor>,
|
||||||
|
bg: Option<anstyle::AnsiColor>,
|
||||||
|
data: &[u8],
|
||||||
|
) -> std::io::Result<usize> {
|
||||||
|
// Ensure exclusive access
|
||||||
|
self.lock().write_colored(fg, bg, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
mod platform {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
impl WinconStream for std::io::StdoutLock<'_> {
|
||||||
|
fn write_colored(
|
||||||
|
&mut self,
|
||||||
|
fg: Option<anstyle::AnsiColor>,
|
||||||
|
bg: Option<anstyle::AnsiColor>,
|
||||||
|
data: &[u8],
|
||||||
|
) -> std::io::Result<usize> {
|
||||||
|
crate::ansi::write_colored(self, fg, bg, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WinconStream for std::io::StderrLock<'_> {
|
||||||
|
fn write_colored(
|
||||||
|
&mut self,
|
||||||
|
fg: Option<anstyle::AnsiColor>,
|
||||||
|
bg: Option<anstyle::AnsiColor>,
|
||||||
|
data: &[u8],
|
||||||
|
) -> std::io::Result<usize> {
|
||||||
|
crate::ansi::write_colored(self, fg, bg, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
mod platform {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
impl WinconStream for std::io::StdoutLock<'_> {
|
||||||
|
fn write_colored(
|
||||||
|
&mut self,
|
||||||
|
fg: Option<anstyle::AnsiColor>,
|
||||||
|
bg: Option<anstyle::AnsiColor>,
|
||||||
|
data: &[u8],
|
||||||
|
) -> std::io::Result<usize> {
|
||||||
|
let initial = crate::windows::stdout_initial_colors();
|
||||||
|
crate::windows::write_colored(self, fg, bg, data, initial)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WinconStream for std::io::StderrLock<'_> {
|
||||||
|
fn write_colored(
|
||||||
|
&mut self,
|
||||||
|
fg: Option<anstyle::AnsiColor>,
|
||||||
|
bg: Option<anstyle::AnsiColor>,
|
||||||
|
data: &[u8],
|
||||||
|
) -> std::io::Result<usize> {
|
||||||
|
let initial = crate::windows::stderr_initial_colors();
|
||||||
|
crate::windows::write_colored(self, fg, bg, data, initial)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WinconStream for &'_ mut std::io::StdoutLock<'_> {
|
||||||
|
fn write_colored(
|
||||||
|
&mut self,
|
||||||
|
fg: Option<anstyle::AnsiColor>,
|
||||||
|
bg: Option<anstyle::AnsiColor>,
|
||||||
|
data: &[u8],
|
||||||
|
) -> std::io::Result<usize> {
|
||||||
|
(**self).write_colored(fg, bg, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WinconStream for &'_ mut std::io::StderrLock<'_> {
|
||||||
|
fn write_colored(
|
||||||
|
&mut self,
|
||||||
|
fg: Option<anstyle::AnsiColor>,
|
||||||
|
bg: Option<anstyle::AnsiColor>,
|
||||||
|
data: &[u8],
|
||||||
|
) -> std::io::Result<usize> {
|
||||||
|
(**self).write_colored(fg, bg, data)
|
||||||
|
}
|
||||||
|
}
|
263
vendor/anstyle-wincon/src/windows.rs
vendored
Normal file
263
vendor/anstyle-wincon/src/windows.rs
vendored
Normal file
@ -0,0 +1,263 @@
|
|||||||
|
//! Low-level wincon-styling
|
||||||
|
|
||||||
|
use std::os::windows::io::AsHandle;
|
||||||
|
use std::os::windows::io::AsRawHandle;
|
||||||
|
|
||||||
|
type StdioColorResult = std::io::Result<(anstyle::AnsiColor, anstyle::AnsiColor)>;
|
||||||
|
type StdioColorInnerResult = Result<(anstyle::AnsiColor, anstyle::AnsiColor), inner::IoError>;
|
||||||
|
|
||||||
|
/// Cached [`get_colors`] call for [`std::io::stdout`]
|
||||||
|
pub fn stdout_initial_colors() -> StdioColorResult {
|
||||||
|
static INITIAL: std::sync::OnceLock<StdioColorInnerResult> = std::sync::OnceLock::new();
|
||||||
|
INITIAL
|
||||||
|
.get_or_init(|| get_colors_(&std::io::stdout()))
|
||||||
|
.clone()
|
||||||
|
.map_err(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Cached [`get_colors`] call for [`std::io::stderr`]
|
||||||
|
pub fn stderr_initial_colors() -> StdioColorResult {
|
||||||
|
static INITIAL: std::sync::OnceLock<StdioColorInnerResult> = std::sync::OnceLock::new();
|
||||||
|
INITIAL
|
||||||
|
.get_or_init(|| get_colors_(&std::io::stderr()))
|
||||||
|
.clone()
|
||||||
|
.map_err(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Apply colors to future writes
|
||||||
|
///
|
||||||
|
/// **Note:** Make sure any buffers are first flushed or else these colors will apply
|
||||||
|
pub fn set_colors<S: AsHandle>(
|
||||||
|
stream: &mut S,
|
||||||
|
fg: anstyle::AnsiColor,
|
||||||
|
bg: anstyle::AnsiColor,
|
||||||
|
) -> std::io::Result<()> {
|
||||||
|
set_colors_(stream, fg, bg).map_err(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_colors_<S: AsHandle>(
|
||||||
|
stream: &mut S,
|
||||||
|
fg: anstyle::AnsiColor,
|
||||||
|
bg: anstyle::AnsiColor,
|
||||||
|
) -> Result<(), inner::IoError> {
|
||||||
|
let handle = stream.as_handle();
|
||||||
|
let handle = handle.as_raw_handle();
|
||||||
|
let attributes = inner::set_colors(fg, bg);
|
||||||
|
inner::set_console_text_attributes(handle, attributes)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the colors currently active on the console
|
||||||
|
pub fn get_colors<S: AsHandle>(stream: &S) -> StdioColorResult {
|
||||||
|
get_colors_(stream).map_err(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_colors_<S: AsHandle>(stream: &S) -> StdioColorInnerResult {
|
||||||
|
let handle = stream.as_handle();
|
||||||
|
let handle = handle.as_raw_handle();
|
||||||
|
let info = inner::get_screen_buffer_info(handle)?;
|
||||||
|
let (fg, bg) = inner::get_colors(&info);
|
||||||
|
Ok((fg, bg))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn write_colored<S: AsHandle + std::io::Write>(
|
||||||
|
stream: &mut S,
|
||||||
|
fg: Option<anstyle::AnsiColor>,
|
||||||
|
bg: Option<anstyle::AnsiColor>,
|
||||||
|
data: &[u8],
|
||||||
|
initial: StdioColorResult,
|
||||||
|
) -> std::io::Result<usize> {
|
||||||
|
let (initial_fg, initial_bg) = initial?;
|
||||||
|
let non_default = fg.is_some() || bg.is_some();
|
||||||
|
|
||||||
|
if non_default {
|
||||||
|
let fg = fg.unwrap_or(initial_fg);
|
||||||
|
let bg = bg.unwrap_or(initial_bg);
|
||||||
|
// Ensure everything is written with the last set of colors before applying the next set
|
||||||
|
stream.flush()?;
|
||||||
|
set_colors(stream, fg, bg)?;
|
||||||
|
}
|
||||||
|
let written = stream.write(data)?;
|
||||||
|
if non_default {
|
||||||
|
// Ensure everything is written with the last set of colors before applying the next set
|
||||||
|
stream.flush()?;
|
||||||
|
set_colors(stream, initial_fg, initial_bg)?;
|
||||||
|
}
|
||||||
|
Ok(written)
|
||||||
|
}
|
||||||
|
|
||||||
|
mod inner {
|
||||||
|
use windows_sys::Win32::System::Console::CONSOLE_CHARACTER_ATTRIBUTES;
|
||||||
|
use windows_sys::Win32::System::Console::CONSOLE_SCREEN_BUFFER_INFO;
|
||||||
|
use windows_sys::Win32::System::Console::FOREGROUND_BLUE;
|
||||||
|
use windows_sys::Win32::System::Console::FOREGROUND_GREEN;
|
||||||
|
use windows_sys::Win32::System::Console::FOREGROUND_INTENSITY;
|
||||||
|
use windows_sys::Win32::System::Console::FOREGROUND_RED;
|
||||||
|
|
||||||
|
use std::os::windows::io::RawHandle;
|
||||||
|
|
||||||
|
const FOREGROUND_CYAN: CONSOLE_CHARACTER_ATTRIBUTES = FOREGROUND_BLUE | FOREGROUND_GREEN;
|
||||||
|
const FOREGROUND_MAGENTA: CONSOLE_CHARACTER_ATTRIBUTES = FOREGROUND_BLUE | FOREGROUND_RED;
|
||||||
|
const FOREGROUND_YELLOW: CONSOLE_CHARACTER_ATTRIBUTES = FOREGROUND_GREEN | FOREGROUND_RED;
|
||||||
|
const FOREGROUND_WHITE: CONSOLE_CHARACTER_ATTRIBUTES =
|
||||||
|
FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub(crate) enum IoError {
|
||||||
|
BrokenPipe,
|
||||||
|
RawOs(i32),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<IoError> for std::io::Error {
|
||||||
|
fn from(io: IoError) -> Self {
|
||||||
|
match io {
|
||||||
|
IoError::BrokenPipe => {
|
||||||
|
std::io::Error::new(std::io::ErrorKind::BrokenPipe, "console is detached")
|
||||||
|
}
|
||||||
|
IoError::RawOs(code) => std::io::Error::from_raw_os_error(code),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IoError {
|
||||||
|
fn last_os_error() -> Self {
|
||||||
|
Self::RawOs(std::io::Error::last_os_error().raw_os_error().unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_screen_buffer_info(
|
||||||
|
handle: RawHandle,
|
||||||
|
) -> Result<CONSOLE_SCREEN_BUFFER_INFO, IoError> {
|
||||||
|
unsafe {
|
||||||
|
let handle = std::mem::transmute(handle);
|
||||||
|
if handle == 0 {
|
||||||
|
return Err(IoError::BrokenPipe);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut info: CONSOLE_SCREEN_BUFFER_INFO = std::mem::zeroed();
|
||||||
|
if windows_sys::Win32::System::Console::GetConsoleScreenBufferInfo(handle, &mut info)
|
||||||
|
!= 0
|
||||||
|
{
|
||||||
|
Ok(info)
|
||||||
|
} else {
|
||||||
|
Err(IoError::last_os_error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn set_console_text_attributes(
|
||||||
|
handle: RawHandle,
|
||||||
|
attributes: CONSOLE_CHARACTER_ATTRIBUTES,
|
||||||
|
) -> Result<(), IoError> {
|
||||||
|
unsafe {
|
||||||
|
let handle = std::mem::transmute(handle);
|
||||||
|
if handle == 0 {
|
||||||
|
return Err(IoError::BrokenPipe);
|
||||||
|
}
|
||||||
|
|
||||||
|
if windows_sys::Win32::System::Console::SetConsoleTextAttribute(handle, attributes) != 0
|
||||||
|
{
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(IoError::last_os_error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_colors(
|
||||||
|
info: &CONSOLE_SCREEN_BUFFER_INFO,
|
||||||
|
) -> (anstyle::AnsiColor, anstyle::AnsiColor) {
|
||||||
|
let attributes = info.wAttributes;
|
||||||
|
let bg = from_nibble(attributes >> 4);
|
||||||
|
let fg = from_nibble(attributes);
|
||||||
|
(fg, bg)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn set_colors(
|
||||||
|
fg: anstyle::AnsiColor,
|
||||||
|
bg: anstyle::AnsiColor,
|
||||||
|
) -> CONSOLE_CHARACTER_ATTRIBUTES {
|
||||||
|
to_nibble(bg) << 4 | to_nibble(fg)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_nibble(color: CONSOLE_CHARACTER_ATTRIBUTES) -> anstyle::AnsiColor {
|
||||||
|
if color & FOREGROUND_WHITE == FOREGROUND_WHITE {
|
||||||
|
// 3 bits high
|
||||||
|
anstyle::AnsiColor::White
|
||||||
|
} else if color & FOREGROUND_CYAN == FOREGROUND_CYAN {
|
||||||
|
// 2 bits high
|
||||||
|
anstyle::AnsiColor::Cyan
|
||||||
|
} else if color & FOREGROUND_YELLOW == FOREGROUND_YELLOW {
|
||||||
|
// 2 bits high
|
||||||
|
anstyle::AnsiColor::Yellow
|
||||||
|
} else if color & FOREGROUND_MAGENTA == FOREGROUND_MAGENTA {
|
||||||
|
// 2 bits high
|
||||||
|
anstyle::AnsiColor::Magenta
|
||||||
|
} else if color & FOREGROUND_RED == FOREGROUND_RED {
|
||||||
|
// 1 bit high
|
||||||
|
anstyle::AnsiColor::Red
|
||||||
|
} else if color & FOREGROUND_GREEN == FOREGROUND_GREEN {
|
||||||
|
// 1 bit high
|
||||||
|
anstyle::AnsiColor::Green
|
||||||
|
} else if color & FOREGROUND_BLUE == FOREGROUND_BLUE {
|
||||||
|
// 1 bit high
|
||||||
|
anstyle::AnsiColor::Blue
|
||||||
|
} else {
|
||||||
|
// 0 bits high
|
||||||
|
anstyle::AnsiColor::Black
|
||||||
|
}
|
||||||
|
.bright(color & FOREGROUND_INTENSITY == FOREGROUND_INTENSITY)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_nibble(color: anstyle::AnsiColor) -> CONSOLE_CHARACTER_ATTRIBUTES {
|
||||||
|
let mut attributes = 0;
|
||||||
|
attributes |= match color.bright(false) {
|
||||||
|
anstyle::AnsiColor::Black => 0,
|
||||||
|
anstyle::AnsiColor::Red => FOREGROUND_RED,
|
||||||
|
anstyle::AnsiColor::Green => FOREGROUND_GREEN,
|
||||||
|
anstyle::AnsiColor::Yellow => FOREGROUND_YELLOW,
|
||||||
|
anstyle::AnsiColor::Blue => FOREGROUND_BLUE,
|
||||||
|
anstyle::AnsiColor::Magenta => FOREGROUND_MAGENTA,
|
||||||
|
anstyle::AnsiColor::Cyan => FOREGROUND_CYAN,
|
||||||
|
anstyle::AnsiColor::White => FOREGROUND_WHITE,
|
||||||
|
anstyle::AnsiColor::BrightBlack
|
||||||
|
| anstyle::AnsiColor::BrightRed
|
||||||
|
| anstyle::AnsiColor::BrightGreen
|
||||||
|
| anstyle::AnsiColor::BrightYellow
|
||||||
|
| anstyle::AnsiColor::BrightBlue
|
||||||
|
| anstyle::AnsiColor::BrightMagenta
|
||||||
|
| anstyle::AnsiColor::BrightCyan
|
||||||
|
| anstyle::AnsiColor::BrightWhite => unreachable!("brights were toggled off"),
|
||||||
|
};
|
||||||
|
if color.is_bright() {
|
||||||
|
attributes |= FOREGROUND_INTENSITY;
|
||||||
|
}
|
||||||
|
attributes
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn to_from_nibble() {
|
||||||
|
const COLORS: [anstyle::AnsiColor; 16] = [
|
||||||
|
anstyle::AnsiColor::Black,
|
||||||
|
anstyle::AnsiColor::Red,
|
||||||
|
anstyle::AnsiColor::Green,
|
||||||
|
anstyle::AnsiColor::Yellow,
|
||||||
|
anstyle::AnsiColor::Blue,
|
||||||
|
anstyle::AnsiColor::Magenta,
|
||||||
|
anstyle::AnsiColor::Cyan,
|
||||||
|
anstyle::AnsiColor::White,
|
||||||
|
anstyle::AnsiColor::BrightBlack,
|
||||||
|
anstyle::AnsiColor::BrightRed,
|
||||||
|
anstyle::AnsiColor::BrightGreen,
|
||||||
|
anstyle::AnsiColor::BrightYellow,
|
||||||
|
anstyle::AnsiColor::BrightBlue,
|
||||||
|
anstyle::AnsiColor::BrightMagenta,
|
||||||
|
anstyle::AnsiColor::BrightCyan,
|
||||||
|
anstyle::AnsiColor::BrightWhite,
|
||||||
|
];
|
||||||
|
for expected in COLORS {
|
||||||
|
let nibble = to_nibble(expected);
|
||||||
|
let actual = from_nibble(nibble);
|
||||||
|
assert_eq!(expected, actual, "Intermediate: {}", nibble);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
vendor/anstyle/.cargo-checksum.json
vendored
Normal file
1
vendor/anstyle/.cargo-checksum.json
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"files":{"Cargo.lock":"ccf805a1b70ac0205b4a5f39db4c21ff2b6c2420d58120f5b74ebd574de3beed","Cargo.toml":"cecc5e02aafb4fa8bcbbcd64eb0c91fada8bcb6ca2514504540e01227295b7b1","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"3dad3b7606dec7ce40f54546e0dd485aeb52a45d4fcdfdaf830fd8349bbe43a5","README.md":"dcb157ba695dd8f1572944cc5bf84b8f67f8bb73925a5b725a9e274c755ce1a6","examples/dump.rs":"236dd2a3dce7512d1faeda5caec8d272299441b5d204696957940c687a021be8","src/color.rs":"8ac17093415630424ab61ca7a674aa98c39438bee51ae9d294072b1d2b17e743","src/effect.rs":"64573c03643af32ed5efe941ccdecb3f4c89685db1b4fbf35a0803e0347f06ee","src/lib.rs":"0106395ba7263dbee67458e5ff4038cab493a3d34f3dcf0cb75504b1531a58e1","src/macros.rs":"0c90b45626fe8331d5b3326abb831f4ba6e04bcc975b1b9c01e465715050caa2","src/reset.rs":"8f8c2f996e5f446d2bbcfb9926494fb2ad76701260225ab6b627960c53dfcb59","src/style.rs":"fecf7c3fcdd00a26727c62861f4ce532ff80df0e0c6a9b4e288d3d2a3d1e4d65"},"package":"7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"}
|
16
vendor/anstyle/Cargo.lock
generated
vendored
Normal file
16
vendor/anstyle/Cargo.lock
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle"
|
||||||
|
version = "1.0.4"
|
||||||
|
dependencies = [
|
||||||
|
"lexopt",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lexopt"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baff4b617f7df3d896f97fe922b64817f6cd9a756bb81d40f8883f2f66dcb401"
|
85
vendor/anstyle/Cargo.toml
vendored
Normal file
85
vendor/anstyle/Cargo.toml
vendored
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
# 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.70.0"
|
||||||
|
name = "anstyle"
|
||||||
|
version = "1.0.4"
|
||||||
|
include = [
|
||||||
|
"build.rs",
|
||||||
|
"src/**/*",
|
||||||
|
"Cargo.toml",
|
||||||
|
"Cargo.lock",
|
||||||
|
"LICENSE*",
|
||||||
|
"README.md",
|
||||||
|
"benches/**/*",
|
||||||
|
"examples/**/*",
|
||||||
|
]
|
||||||
|
description = "ANSI text styling"
|
||||||
|
homepage = "https://github.com/rust-cli/anstyle"
|
||||||
|
readme = "README.md"
|
||||||
|
keywords = [
|
||||||
|
"ansi",
|
||||||
|
"terminal",
|
||||||
|
"color",
|
||||||
|
"no_std",
|
||||||
|
]
|
||||||
|
categories = ["command-line-interface"]
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
repository = "https://github.com/rust-cli/anstyle.git"
|
||||||
|
|
||||||
|
[package.metadata.release]
|
||||||
|
tag-prefix = ""
|
||||||
|
|
||||||
|
[[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 -->"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
|
||||||
|
[dev-dependencies.lexopt]
|
||||||
|
version = "0.3.0"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["std"]
|
||||||
|
std = []
|
202
vendor/anstyle/LICENSE-APACHE
vendored
Normal file
202
vendor/anstyle/LICENSE-APACHE
vendored
Normal file
@ -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.
|
||||||
|
|
19
vendor/anstyle/LICENSE-MIT
vendored
Normal file
19
vendor/anstyle/LICENSE-MIT
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
Copyright (c) 2022 The rust-cli Developers
|
||||||
|
|
||||||
|
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.
|
42
vendor/anstyle/README.md
vendored
Normal file
42
vendor/anstyle/README.md
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# anstyle
|
||||||
|
|
||||||
|
> ANSI text styling
|
||||||
|
|
||||||
|
*A portmanteau of "ansi style"*
|
||||||
|
|
||||||
|
[![Documentation](https://img.shields.io/badge/docs-master-blue.svg)][Documentation]
|
||||||
|
![License](https://img.shields.io/crates/l/anstyle.svg)
|
||||||
|
[![Crates Status](https://img.shields.io/crates/v/anstyle.svg)](https://crates.io/crates/anstyle)
|
||||||
|
|
||||||
|
`anstyle` provides core types describing [ANSI styling escape
|
||||||
|
codes](https://en.wikipedia.org/wiki/ANSI_escape_code) for interoperability
|
||||||
|
between crates. For example, this would allow a crate to provide an API for
|
||||||
|
customizing the colors used without putting the underlying text styling crate
|
||||||
|
in the API.
|
||||||
|
|
||||||
|
For integration with your text styling crate, see:
|
||||||
|
- [anstyle-termcolor](crates/termcolor)
|
||||||
|
- [anstyle-owo-colors](crates/owo)
|
||||||
|
- [anstyle-yansi](crates/yansi)
|
||||||
|
|
||||||
|
General utilities:
|
||||||
|
- [anstyle-git](crates/git): Parse Git style descriptions
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
|
### Contribution
|
||||||
|
|
||||||
|
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/anstyle
|
||||||
|
[Documentation]: https://docs.rs/anstyle
|
132
vendor/anstyle/examples/dump.rs
vendored
Normal file
132
vendor/anstyle/examples/dump.rs
vendored
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
fn main() -> Result<(), lexopt::Error> {
|
||||||
|
let args = Args::parse()?;
|
||||||
|
let stdout = std::io::stdout();
|
||||||
|
let mut stdout = stdout.lock();
|
||||||
|
|
||||||
|
for fixed in 0..16 {
|
||||||
|
let style = style(fixed, args.layer, args.effects);
|
||||||
|
let _ = print_number(&mut stdout, fixed, style);
|
||||||
|
if fixed == 7 || fixed == 15 {
|
||||||
|
let _ = writeln!(&mut stdout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for r in 0..6 {
|
||||||
|
let _ = writeln!(stdout);
|
||||||
|
for g in 0..6 {
|
||||||
|
for b in 0..6 {
|
||||||
|
let fixed = r * 36 + g * 6 + b + 16;
|
||||||
|
let style = style(fixed, args.layer, args.effects);
|
||||||
|
let _ = print_number(&mut stdout, fixed, style);
|
||||||
|
}
|
||||||
|
let _ = writeln!(stdout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for c in 0..24 {
|
||||||
|
if 0 == c % 8 {
|
||||||
|
let _ = writeln!(stdout);
|
||||||
|
}
|
||||||
|
let fixed = 232 + c;
|
||||||
|
let style = style(fixed, args.layer, args.effects);
|
||||||
|
let _ = print_number(&mut stdout, fixed, style);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn style(fixed: u8, layer: Layer, effects: anstyle::Effects) -> anstyle::Style {
|
||||||
|
let color = anstyle::Ansi256Color(fixed).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 std::io::StdoutLock<'_>,
|
||||||
|
fixed: u8,
|
||||||
|
style: anstyle::Style,
|
||||||
|
) -> std::io::Result<()> {
|
||||||
|
write!(
|
||||||
|
stdout,
|
||||||
|
"{}{:>4}{}",
|
||||||
|
style.render(),
|
||||||
|
fixed,
|
||||||
|
anstyle::Reset.render()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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)
|
||||||
|
}
|
||||||
|
}
|
611
vendor/anstyle/src/color.rs
vendored
Normal file
611
vendor/anstyle/src/color.rs
vendored
Normal file
@ -0,0 +1,611 @@
|
|||||||
|
/// Any ANSI color code scheme
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub enum Color {
|
||||||
|
Ansi(AnsiColor),
|
||||||
|
Ansi256(Ansi256Color),
|
||||||
|
Rgb(RgbColor),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Color {
|
||||||
|
/// Create a [`Style`][crate::Style] with this as the foreground
|
||||||
|
#[inline]
|
||||||
|
pub fn on(self, background: impl Into<Color>) -> crate::Style {
|
||||||
|
crate::Style::new()
|
||||||
|
.fg_color(Some(self))
|
||||||
|
.bg_color(Some(background.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a [`Style`][crate::Style] with this as the foreground
|
||||||
|
#[inline]
|
||||||
|
pub const fn on_default(self) -> crate::Style {
|
||||||
|
crate::Style::new().fg_color(Some(self))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Render the ANSI code for a foreground color
|
||||||
|
#[inline]
|
||||||
|
pub fn render_fg(self) -> impl core::fmt::Display + Copy + Clone {
|
||||||
|
match self {
|
||||||
|
Self::Ansi(color) => DisplayBuffer::default().write_str(color.as_fg_str()),
|
||||||
|
Self::Ansi256(color) => color.as_fg_buffer(),
|
||||||
|
Self::Rgb(color) => color.as_fg_buffer(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub(crate) fn write_fg_to(self, write: &mut dyn std::io::Write) -> std::io::Result<()> {
|
||||||
|
let buffer = match self {
|
||||||
|
Self::Ansi(color) => DisplayBuffer::default().write_str(color.as_fg_str()),
|
||||||
|
Self::Ansi256(color) => color.as_fg_buffer(),
|
||||||
|
Self::Rgb(color) => color.as_fg_buffer(),
|
||||||
|
};
|
||||||
|
buffer.write_to(write)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Render the ANSI code for a background color
|
||||||
|
#[inline]
|
||||||
|
pub fn render_bg(self) -> impl core::fmt::Display + Copy + Clone {
|
||||||
|
match self {
|
||||||
|
Self::Ansi(color) => DisplayBuffer::default().write_str(color.as_bg_str()),
|
||||||
|
Self::Ansi256(color) => color.as_bg_buffer(),
|
||||||
|
Self::Rgb(color) => color.as_bg_buffer(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub(crate) fn write_bg_to(self, write: &mut dyn std::io::Write) -> std::io::Result<()> {
|
||||||
|
let buffer = match self {
|
||||||
|
Self::Ansi(color) => DisplayBuffer::default().write_str(color.as_bg_str()),
|
||||||
|
Self::Ansi256(color) => color.as_bg_buffer(),
|
||||||
|
Self::Rgb(color) => color.as_bg_buffer(),
|
||||||
|
};
|
||||||
|
buffer.write_to(write)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn render_underline(self) -> impl core::fmt::Display + Copy + Clone {
|
||||||
|
match self {
|
||||||
|
Self::Ansi(color) => color.as_underline_buffer(),
|
||||||
|
Self::Ansi256(color) => color.as_underline_buffer(),
|
||||||
|
Self::Rgb(color) => color.as_underline_buffer(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub(crate) fn write_underline_to(self, write: &mut dyn std::io::Write) -> std::io::Result<()> {
|
||||||
|
let buffer = match self {
|
||||||
|
Self::Ansi(color) => color.as_underline_buffer(),
|
||||||
|
Self::Ansi256(color) => color.as_underline_buffer(),
|
||||||
|
Self::Rgb(color) => color.as_underline_buffer(),
|
||||||
|
};
|
||||||
|
buffer.write_to(write)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<AnsiColor> for Color {
|
||||||
|
#[inline]
|
||||||
|
fn from(inner: AnsiColor) -> Self {
|
||||||
|
Self::Ansi(inner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Ansi256Color> for Color {
|
||||||
|
#[inline]
|
||||||
|
fn from(inner: Ansi256Color) -> Self {
|
||||||
|
Self::Ansi256(inner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<RgbColor> for Color {
|
||||||
|
#[inline]
|
||||||
|
fn from(inner: RgbColor) -> Self {
|
||||||
|
Self::Rgb(inner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u8> for Color {
|
||||||
|
#[inline]
|
||||||
|
fn from(inner: u8) -> Self {
|
||||||
|
Self::Ansi256(inner.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<(u8, u8, u8)> for Color {
|
||||||
|
#[inline]
|
||||||
|
fn from(inner: (u8, u8, u8)) -> Self {
|
||||||
|
Self::Rgb(inner.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Available 4-bit ANSI color palette codes
|
||||||
|
///
|
||||||
|
/// The user's terminal defines the meaning of the each palette code.
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum AnsiColor {
|
||||||
|
/// Black: #0 (foreground code `30`, background code `40`).
|
||||||
|
Black,
|
||||||
|
|
||||||
|
/// Red: #1 (foreground code `31`, background code `41`).
|
||||||
|
Red,
|
||||||
|
|
||||||
|
/// Green: #2 (foreground code `32`, background code `42`).
|
||||||
|
Green,
|
||||||
|
|
||||||
|
/// Yellow: #3 (foreground code `33`, background code `43`).
|
||||||
|
Yellow,
|
||||||
|
|
||||||
|
/// Blue: #4 (foreground code `34`, background code `44`).
|
||||||
|
Blue,
|
||||||
|
|
||||||
|
/// Magenta: #5 (foreground code `35`, background code `45`).
|
||||||
|
Magenta,
|
||||||
|
|
||||||
|
/// Cyan: #6 (foreground code `36`, background code `46`).
|
||||||
|
Cyan,
|
||||||
|
|
||||||
|
/// White: #7 (foreground code `37`, background code `47`).
|
||||||
|
White,
|
||||||
|
|
||||||
|
/// Bright black: #0 (foreground code `90`, background code `100`).
|
||||||
|
BrightBlack,
|
||||||
|
|
||||||
|
/// Bright red: #1 (foreground code `91`, background code `101`).
|
||||||
|
BrightRed,
|
||||||
|
|
||||||
|
/// Bright green: #2 (foreground code `92`, background code `102`).
|
||||||
|
BrightGreen,
|
||||||
|
|
||||||
|
/// Bright yellow: #3 (foreground code `93`, background code `103`).
|
||||||
|
BrightYellow,
|
||||||
|
|
||||||
|
/// Bright blue: #4 (foreground code `94`, background code `104`).
|
||||||
|
BrightBlue,
|
||||||
|
|
||||||
|
/// Bright magenta: #5 (foreground code `95`, background code `105`).
|
||||||
|
BrightMagenta,
|
||||||
|
|
||||||
|
/// Bright cyan: #6 (foreground code `96`, background code `106`).
|
||||||
|
BrightCyan,
|
||||||
|
|
||||||
|
/// Bright white: #7 (foreground code `97`, background code `107`).
|
||||||
|
BrightWhite,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AnsiColor {
|
||||||
|
/// Create a [`Style`][crate::Style] with this as the foreground
|
||||||
|
#[inline]
|
||||||
|
pub fn on(self, background: impl Into<Color>) -> crate::Style {
|
||||||
|
crate::Style::new()
|
||||||
|
.fg_color(Some(self.into()))
|
||||||
|
.bg_color(Some(background.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a [`Style`][crate::Style] with this as the foreground
|
||||||
|
#[inline]
|
||||||
|
pub const fn on_default(self) -> crate::Style {
|
||||||
|
crate::Style::new().fg_color(Some(Color::Ansi(self)))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Render the ANSI code for a foreground color
|
||||||
|
#[inline]
|
||||||
|
pub fn render_fg(self) -> impl core::fmt::Display + Copy + Clone {
|
||||||
|
self.as_fg_str()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn as_fg_str(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::Black => escape!("3", "0"),
|
||||||
|
Self::Red => escape!("3", "1"),
|
||||||
|
Self::Green => escape!("3", "2"),
|
||||||
|
Self::Yellow => escape!("3", "3"),
|
||||||
|
Self::Blue => escape!("3", "4"),
|
||||||
|
Self::Magenta => escape!("3", "5"),
|
||||||
|
Self::Cyan => escape!("3", "6"),
|
||||||
|
Self::White => escape!("3", "7"),
|
||||||
|
Self::BrightBlack => escape!("9", "0"),
|
||||||
|
Self::BrightRed => escape!("9", "1"),
|
||||||
|
Self::BrightGreen => escape!("9", "2"),
|
||||||
|
Self::BrightYellow => escape!("9", "3"),
|
||||||
|
Self::BrightBlue => escape!("9", "4"),
|
||||||
|
Self::BrightMagenta => escape!("9", "5"),
|
||||||
|
Self::BrightCyan => escape!("9", "6"),
|
||||||
|
Self::BrightWhite => escape!("9", "7"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Render the ANSI code for a background color
|
||||||
|
#[inline]
|
||||||
|
pub fn render_bg(self) -> impl core::fmt::Display + Copy + Clone {
|
||||||
|
self.as_bg_str()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn as_bg_str(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::Black => escape!("4", "0"),
|
||||||
|
Self::Red => escape!("4", "1"),
|
||||||
|
Self::Green => escape!("4", "2"),
|
||||||
|
Self::Yellow => escape!("4", "3"),
|
||||||
|
Self::Blue => escape!("4", "4"),
|
||||||
|
Self::Magenta => escape!("4", "5"),
|
||||||
|
Self::Cyan => escape!("4", "6"),
|
||||||
|
Self::White => escape!("4", "7"),
|
||||||
|
Self::BrightBlack => escape!("10", "0"),
|
||||||
|
Self::BrightRed => escape!("10", "1"),
|
||||||
|
Self::BrightGreen => escape!("10", "2"),
|
||||||
|
Self::BrightYellow => escape!("10", "3"),
|
||||||
|
Self::BrightBlue => escape!("10", "4"),
|
||||||
|
Self::BrightMagenta => escape!("10", "5"),
|
||||||
|
Self::BrightCyan => escape!("10", "6"),
|
||||||
|
Self::BrightWhite => escape!("10", "7"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn as_underline_buffer(&self) -> DisplayBuffer {
|
||||||
|
// No per-color codes; must delegate to `Ansi256Color`
|
||||||
|
Ansi256Color::from(*self).as_underline_buffer()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Change the color to/from bright
|
||||||
|
#[must_use]
|
||||||
|
#[inline]
|
||||||
|
pub fn bright(self, yes: bool) -> Self {
|
||||||
|
if yes {
|
||||||
|
match self {
|
||||||
|
Self::Black => Self::BrightBlack,
|
||||||
|
Self::Red => Self::BrightRed,
|
||||||
|
Self::Green => Self::BrightGreen,
|
||||||
|
Self::Yellow => Self::BrightYellow,
|
||||||
|
Self::Blue => Self::BrightBlue,
|
||||||
|
Self::Magenta => Self::BrightMagenta,
|
||||||
|
Self::Cyan => Self::BrightCyan,
|
||||||
|
Self::White => Self::BrightWhite,
|
||||||
|
Self::BrightBlack => self,
|
||||||
|
Self::BrightRed => self,
|
||||||
|
Self::BrightGreen => self,
|
||||||
|
Self::BrightYellow => self,
|
||||||
|
Self::BrightBlue => self,
|
||||||
|
Self::BrightMagenta => self,
|
||||||
|
Self::BrightCyan => self,
|
||||||
|
Self::BrightWhite => self,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
match self {
|
||||||
|
Self::Black => self,
|
||||||
|
Self::Red => self,
|
||||||
|
Self::Green => self,
|
||||||
|
Self::Yellow => self,
|
||||||
|
Self::Blue => self,
|
||||||
|
Self::Magenta => self,
|
||||||
|
Self::Cyan => self,
|
||||||
|
Self::White => self,
|
||||||
|
Self::BrightBlack => Self::Black,
|
||||||
|
Self::BrightRed => Self::Red,
|
||||||
|
Self::BrightGreen => Self::Green,
|
||||||
|
Self::BrightYellow => Self::Yellow,
|
||||||
|
Self::BrightBlue => Self::Blue,
|
||||||
|
Self::BrightMagenta => Self::Magenta,
|
||||||
|
Self::BrightCyan => Self::Cyan,
|
||||||
|
Self::BrightWhite => Self::White,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Report whether the color is bright
|
||||||
|
#[inline]
|
||||||
|
pub fn is_bright(self) -> bool {
|
||||||
|
match self {
|
||||||
|
Self::Black => false,
|
||||||
|
Self::Red => false,
|
||||||
|
Self::Green => false,
|
||||||
|
Self::Yellow => false,
|
||||||
|
Self::Blue => false,
|
||||||
|
Self::Magenta => false,
|
||||||
|
Self::Cyan => false,
|
||||||
|
Self::White => false,
|
||||||
|
Self::BrightBlack => true,
|
||||||
|
Self::BrightRed => true,
|
||||||
|
Self::BrightGreen => true,
|
||||||
|
Self::BrightYellow => true,
|
||||||
|
Self::BrightBlue => true,
|
||||||
|
Self::BrightMagenta => true,
|
||||||
|
Self::BrightCyan => true,
|
||||||
|
Self::BrightWhite => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 256 (8-bit) color support
|
||||||
|
///
|
||||||
|
/// - `0..16` are [`AnsiColor`] palette codes
|
||||||
|
/// - `0..232` map to [`RgbColor`] color values
|
||||||
|
/// - `232..` map to [`RgbColor`] gray-scale values
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct Ansi256Color(pub u8);
|
||||||
|
|
||||||
|
impl Ansi256Color {
|
||||||
|
/// Create a [`Style`][crate::Style] with this as the foreground
|
||||||
|
#[inline]
|
||||||
|
pub fn on(self, background: impl Into<Color>) -> crate::Style {
|
||||||
|
crate::Style::new()
|
||||||
|
.fg_color(Some(self.into()))
|
||||||
|
.bg_color(Some(background.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a [`Style`][crate::Style] with this as the foreground
|
||||||
|
#[inline]
|
||||||
|
pub const fn on_default(self) -> crate::Style {
|
||||||
|
crate::Style::new().fg_color(Some(Color::Ansi256(self)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub const fn index(self) -> u8 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub const fn into_ansi(self) -> Option<AnsiColor> {
|
||||||
|
match self.index() {
|
||||||
|
0 => Some(AnsiColor::Black),
|
||||||
|
1 => Some(AnsiColor::Red),
|
||||||
|
2 => Some(AnsiColor::Green),
|
||||||
|
3 => Some(AnsiColor::Yellow),
|
||||||
|
4 => Some(AnsiColor::Blue),
|
||||||
|
5 => Some(AnsiColor::Magenta),
|
||||||
|
6 => Some(AnsiColor::Cyan),
|
||||||
|
7 => Some(AnsiColor::White),
|
||||||
|
8 => Some(AnsiColor::BrightBlack),
|
||||||
|
9 => Some(AnsiColor::BrightRed),
|
||||||
|
10 => Some(AnsiColor::BrightGreen),
|
||||||
|
11 => Some(AnsiColor::BrightYellow),
|
||||||
|
12 => Some(AnsiColor::BrightBlue),
|
||||||
|
13 => Some(AnsiColor::BrightMagenta),
|
||||||
|
14 => Some(AnsiColor::BrightCyan),
|
||||||
|
15 => Some(AnsiColor::BrightWhite),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub const fn from_ansi(color: AnsiColor) -> Self {
|
||||||
|
match color {
|
||||||
|
AnsiColor::Black => Self(0),
|
||||||
|
AnsiColor::Red => Self(1),
|
||||||
|
AnsiColor::Green => Self(2),
|
||||||
|
AnsiColor::Yellow => Self(3),
|
||||||
|
AnsiColor::Blue => Self(4),
|
||||||
|
AnsiColor::Magenta => Self(5),
|
||||||
|
AnsiColor::Cyan => Self(6),
|
||||||
|
AnsiColor::White => Self(7),
|
||||||
|
AnsiColor::BrightBlack => Self(8),
|
||||||
|
AnsiColor::BrightRed => Self(9),
|
||||||
|
AnsiColor::BrightGreen => Self(10),
|
||||||
|
AnsiColor::BrightYellow => Self(11),
|
||||||
|
AnsiColor::BrightBlue => Self(12),
|
||||||
|
AnsiColor::BrightMagenta => Self(13),
|
||||||
|
AnsiColor::BrightCyan => Self(14),
|
||||||
|
AnsiColor::BrightWhite => Self(15),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Render the ANSI code for a foreground color
|
||||||
|
#[inline]
|
||||||
|
pub fn render_fg(self) -> impl core::fmt::Display + Copy + Clone {
|
||||||
|
self.as_fg_buffer()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn as_fg_buffer(&self) -> DisplayBuffer {
|
||||||
|
DisplayBuffer::default()
|
||||||
|
.write_str("\x1B[38;5;")
|
||||||
|
.write_code(self.index())
|
||||||
|
.write_str("m")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Render the ANSI code for a background color
|
||||||
|
#[inline]
|
||||||
|
pub fn render_bg(self) -> impl core::fmt::Display + Copy + Clone {
|
||||||
|
self.as_bg_buffer()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn as_bg_buffer(&self) -> DisplayBuffer {
|
||||||
|
DisplayBuffer::default()
|
||||||
|
.write_str("\x1B[48;5;")
|
||||||
|
.write_code(self.index())
|
||||||
|
.write_str("m")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn as_underline_buffer(&self) -> DisplayBuffer {
|
||||||
|
DisplayBuffer::default()
|
||||||
|
.write_str("\x1B[58;5;")
|
||||||
|
.write_code(self.index())
|
||||||
|
.write_str("m")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u8> for Ansi256Color {
|
||||||
|
#[inline]
|
||||||
|
fn from(inner: u8) -> Self {
|
||||||
|
Self(inner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<AnsiColor> for Ansi256Color {
|
||||||
|
#[inline]
|
||||||
|
fn from(inner: AnsiColor) -> Self {
|
||||||
|
Self::from_ansi(inner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 24-bit ANSI RGB color codes
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub struct RgbColor(pub u8, pub u8, pub u8);
|
||||||
|
|
||||||
|
impl RgbColor {
|
||||||
|
/// Create a [`Style`][crate::Style] with this as the foreground
|
||||||
|
#[inline]
|
||||||
|
pub fn on(self, background: impl Into<Color>) -> crate::Style {
|
||||||
|
crate::Style::new()
|
||||||
|
.fg_color(Some(self.into()))
|
||||||
|
.bg_color(Some(background.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a [`Style`][crate::Style] with this as the foreground
|
||||||
|
#[inline]
|
||||||
|
pub const fn on_default(self) -> crate::Style {
|
||||||
|
crate::Style::new().fg_color(Some(Color::Rgb(self)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub const fn r(self) -> u8 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub const fn g(self) -> u8 {
|
||||||
|
self.1
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub const fn b(self) -> u8 {
|
||||||
|
self.2
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Render the ANSI code for a foreground color
|
||||||
|
#[inline]
|
||||||
|
pub fn render_fg(self) -> impl core::fmt::Display + Copy + Clone {
|
||||||
|
self.as_fg_buffer()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn as_fg_buffer(&self) -> DisplayBuffer {
|
||||||
|
DisplayBuffer::default()
|
||||||
|
.write_str("\x1B[38;2;")
|
||||||
|
.write_code(self.r())
|
||||||
|
.write_str(";")
|
||||||
|
.write_code(self.g())
|
||||||
|
.write_str(";")
|
||||||
|
.write_code(self.b())
|
||||||
|
.write_str("m")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Render the ANSI code for a background color
|
||||||
|
#[inline]
|
||||||
|
pub fn render_bg(self) -> impl core::fmt::Display + Copy + Clone {
|
||||||
|
self.as_bg_buffer()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn as_bg_buffer(&self) -> DisplayBuffer {
|
||||||
|
DisplayBuffer::default()
|
||||||
|
.write_str("\x1B[48;2;")
|
||||||
|
.write_code(self.r())
|
||||||
|
.write_str(";")
|
||||||
|
.write_code(self.g())
|
||||||
|
.write_str(";")
|
||||||
|
.write_code(self.b())
|
||||||
|
.write_str("m")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn as_underline_buffer(&self) -> DisplayBuffer {
|
||||||
|
DisplayBuffer::default()
|
||||||
|
.write_str("\x1B[58;2;")
|
||||||
|
.write_code(self.r())
|
||||||
|
.write_str(";")
|
||||||
|
.write_code(self.g())
|
||||||
|
.write_str(";")
|
||||||
|
.write_code(self.b())
|
||||||
|
.write_str("m")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<(u8, u8, u8)> for RgbColor {
|
||||||
|
#[inline]
|
||||||
|
fn from(inner: (u8, u8, u8)) -> Self {
|
||||||
|
let (r, g, b) = inner;
|
||||||
|
Self(r, g, b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Default, Debug)]
|
||||||
|
struct DisplayBuffer {
|
||||||
|
buffer: [u8; 19],
|
||||||
|
len: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DisplayBuffer {
|
||||||
|
#[must_use]
|
||||||
|
#[inline(never)]
|
||||||
|
fn write_str(mut self, part: &'static str) -> Self {
|
||||||
|
for (i, b) in part.as_bytes().iter().enumerate() {
|
||||||
|
self.buffer[self.len + i] = *b;
|
||||||
|
}
|
||||||
|
self.len += part.len();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
#[inline(never)]
|
||||||
|
fn write_code(mut self, code: u8) -> Self {
|
||||||
|
let c1: u8 = (code / 100) % 10;
|
||||||
|
let c2: u8 = (code / 10) % 10;
|
||||||
|
let c3: u8 = code % 10;
|
||||||
|
|
||||||
|
let mut printed = true;
|
||||||
|
if c1 != 0 {
|
||||||
|
printed = true;
|
||||||
|
self.buffer[self.len] = b'0' + c1;
|
||||||
|
self.len += 1;
|
||||||
|
}
|
||||||
|
if c2 != 0 || printed {
|
||||||
|
self.buffer[self.len] = b'0' + c2;
|
||||||
|
self.len += 1;
|
||||||
|
}
|
||||||
|
// If we received a zero value we must still print a value.
|
||||||
|
self.buffer[self.len] = b'0' + c3;
|
||||||
|
self.len += 1;
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn as_str(&self) -> &str {
|
||||||
|
// SAFETY: Only `&str` can be written to the buffer
|
||||||
|
unsafe { core::str::from_utf8_unchecked(&self.buffer[0..self.len]) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
fn write_to(self, write: &mut dyn std::io::Write) -> std::io::Result<()> {
|
||||||
|
write.write_all(self.as_str().as_bytes())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl core::fmt::Display for DisplayBuffer {
|
||||||
|
#[inline]
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
self.as_str().fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn max_display_buffer() {
|
||||||
|
let c = RgbColor(255, 255, 255);
|
||||||
|
let actual = c.render_fg().to_string();
|
||||||
|
assert_eq!(actual, "\u{1b}[38;2;255;255;255m");
|
||||||
|
}
|
||||||
|
}
|
369
vendor/anstyle/src/effect.rs
vendored
Normal file
369
vendor/anstyle/src/effect.rs
vendored
Normal file
@ -0,0 +1,369 @@
|
|||||||
|
/// A set of text effects
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// let effects = anstyle::Effects::BOLD | anstyle::Effects::UNDERLINE;
|
||||||
|
/// ```
|
||||||
|
#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub struct Effects(u16);
|
||||||
|
|
||||||
|
impl Effects {
|
||||||
|
const PLAIN: Self = Effects(0);
|
||||||
|
|
||||||
|
pub const BOLD: Self = Effects(1 << 0);
|
||||||
|
pub const DIMMED: Self = Effects(1 << 1);
|
||||||
|
/// Not widely supported. Sometimes treated as inverse or blink
|
||||||
|
pub const ITALIC: Self = Effects(1 << 2);
|
||||||
|
/// Style extensions exist for Kitty, VTE, mintty and iTerm2.
|
||||||
|
pub const UNDERLINE: Self = Effects(1 << 3);
|
||||||
|
pub const DOUBLE_UNDERLINE: Self = Effects(1 << 4);
|
||||||
|
pub const CURLY_UNDERLINE: Self = Effects(1 << 5);
|
||||||
|
pub const DOTTED_UNDERLINE: Self = Effects(1 << 6);
|
||||||
|
pub const DASHED_UNDERLINE: Self = Effects(1 << 7);
|
||||||
|
pub const BLINK: Self = Effects(1 << 8);
|
||||||
|
/// Swap foreground and background colors; inconsistent emulation
|
||||||
|
pub const INVERT: Self = Effects(1 << 9);
|
||||||
|
pub const HIDDEN: Self = Effects(1 << 10);
|
||||||
|
/// Characters legible but marked as if for deletion. Not supported in Terminal.app
|
||||||
|
pub const STRIKETHROUGH: Self = Effects(1 << 11);
|
||||||
|
|
||||||
|
/// No effects enabled
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// let effects = anstyle::Effects::new();
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
Self::PLAIN
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if no effects are enabled
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// let effects = anstyle::Effects::new();
|
||||||
|
/// assert!(effects.is_plain());
|
||||||
|
///
|
||||||
|
/// let effects = anstyle::Effects::BOLD | anstyle::Effects::UNDERLINE;
|
||||||
|
/// assert!(!effects.is_plain());
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub const fn is_plain(self) -> bool {
|
||||||
|
self.0 == Self::PLAIN.0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if all of the effects in `other` are contained within `self`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// let effects = anstyle::Effects::BOLD | anstyle::Effects::UNDERLINE;
|
||||||
|
/// assert!(effects.contains(anstyle::Effects::BOLD));
|
||||||
|
///
|
||||||
|
/// let effects = anstyle::Effects::new();
|
||||||
|
/// assert!(!effects.contains(anstyle::Effects::BOLD));
|
||||||
|
/// ```
|
||||||
|
#[inline(always)]
|
||||||
|
pub const fn contains(self, other: Effects) -> bool {
|
||||||
|
(other.0 & self.0) == other.0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Inserts the specified effects in-place.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// let effects = anstyle::Effects::new().insert(anstyle::Effects::new());
|
||||||
|
/// assert!(effects.is_plain());
|
||||||
|
///
|
||||||
|
/// let effects = anstyle::Effects::new().insert(anstyle::Effects::BOLD);
|
||||||
|
/// assert!(effects.contains(anstyle::Effects::BOLD));
|
||||||
|
/// ```
|
||||||
|
#[inline(always)]
|
||||||
|
#[must_use]
|
||||||
|
pub const fn insert(mut self, other: Effects) -> Self {
|
||||||
|
self.0 |= other.0;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Removes the specified effects in-place.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// let effects = (anstyle::Effects::BOLD | anstyle::Effects::UNDERLINE).remove(anstyle::Effects::BOLD);
|
||||||
|
/// assert!(!effects.contains(anstyle::Effects::BOLD));
|
||||||
|
/// assert!(effects.contains(anstyle::Effects::UNDERLINE));
|
||||||
|
/// ```
|
||||||
|
#[inline(always)]
|
||||||
|
#[must_use]
|
||||||
|
pub const fn remove(mut self, other: Effects) -> Self {
|
||||||
|
self.0 &= !other.0;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reset all effects in-place
|
||||||
|
/// ```rust
|
||||||
|
/// let effects = (anstyle::Effects::BOLD | anstyle::Effects::UNDERLINE).clear();
|
||||||
|
/// assert!(!effects.contains(anstyle::Effects::BOLD));
|
||||||
|
/// assert!(!effects.contains(anstyle::Effects::UNDERLINE));
|
||||||
|
/// ```
|
||||||
|
#[inline(always)]
|
||||||
|
#[must_use]
|
||||||
|
pub const fn clear(self) -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Enable or disable the specified effects depending on the passed value.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// let effects = anstyle::Effects::new().set(anstyle::Effects::BOLD, true);
|
||||||
|
/// assert!(effects.contains(anstyle::Effects::BOLD));
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
|
pub const fn set(self, other: Self, enable: bool) -> Self {
|
||||||
|
if enable {
|
||||||
|
self.insert(other)
|
||||||
|
} else {
|
||||||
|
self.remove(other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Iterate over enabled effects
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn iter(self) -> EffectIter {
|
||||||
|
EffectIter {
|
||||||
|
index: 0,
|
||||||
|
effects: self,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Iterate over enabled effect indices
|
||||||
|
#[inline(always)]
|
||||||
|
pub(crate) fn index_iter(self) -> EffectIndexIter {
|
||||||
|
EffectIndexIter {
|
||||||
|
index: 0,
|
||||||
|
effects: self,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Render the ANSI code
|
||||||
|
#[inline]
|
||||||
|
pub fn render(self) -> impl core::fmt::Display + Copy + Clone {
|
||||||
|
EffectsDisplay(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub(crate) fn write_to(self, write: &mut dyn std::io::Write) -> std::io::Result<()> {
|
||||||
|
for index in self.index_iter() {
|
||||||
|
write.write_all(METADATA[index].escape.as_bytes())?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// let effects = anstyle::Effects::new();
|
||||||
|
/// assert_eq!(format!("{:?}", effects), "Effects()");
|
||||||
|
///
|
||||||
|
/// let effects = anstyle::Effects::BOLD | anstyle::Effects::UNDERLINE;
|
||||||
|
/// assert_eq!(format!("{:?}", effects), "Effects(BOLD | UNDERLINE)");
|
||||||
|
/// ```
|
||||||
|
impl core::fmt::Debug for Effects {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
write!(f, "Effects(")?;
|
||||||
|
for (i, index) in self.index_iter().enumerate() {
|
||||||
|
if i != 0 {
|
||||||
|
write!(f, " | ")?;
|
||||||
|
}
|
||||||
|
write!(f, "{}", METADATA[index].name)?;
|
||||||
|
}
|
||||||
|
write!(f, ")")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// let effects = anstyle::Effects::BOLD | anstyle::Effects::UNDERLINE;
|
||||||
|
/// assert_eq!(format!("{:?}", effects), "Effects(BOLD | UNDERLINE)");
|
||||||
|
/// ```
|
||||||
|
impl core::ops::BitOr for Effects {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn bitor(self, rhs: Self) -> Self {
|
||||||
|
self.insert(rhs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// let mut effects = anstyle::Effects::BOLD;
|
||||||
|
/// effects |= anstyle::Effects::UNDERLINE;
|
||||||
|
/// assert_eq!(format!("{:?}", effects), "Effects(BOLD | UNDERLINE)");
|
||||||
|
/// ```
|
||||||
|
impl core::ops::BitOrAssign for Effects {
|
||||||
|
#[inline]
|
||||||
|
fn bitor_assign(&mut self, other: Self) {
|
||||||
|
*self = self.insert(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// let effects = (anstyle::Effects::BOLD | anstyle::Effects::UNDERLINE) - anstyle::Effects::BOLD;
|
||||||
|
/// assert_eq!(format!("{:?}", effects), "Effects(UNDERLINE)");
|
||||||
|
/// ```
|
||||||
|
impl core::ops::Sub for Effects {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn sub(self, other: Self) -> Self {
|
||||||
|
self.remove(other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// let mut effects = anstyle::Effects::BOLD | anstyle::Effects::UNDERLINE;
|
||||||
|
/// effects -= anstyle::Effects::BOLD;
|
||||||
|
/// assert_eq!(format!("{:?}", effects), "Effects(UNDERLINE)");
|
||||||
|
/// ```
|
||||||
|
impl core::ops::SubAssign for Effects {
|
||||||
|
#[inline]
|
||||||
|
fn sub_assign(&mut self, other: Self) {
|
||||||
|
*self = self.remove(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) struct Metadata {
|
||||||
|
pub(crate) name: &'static str,
|
||||||
|
pub(crate) escape: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) const METADATA: [Metadata; 12] = [
|
||||||
|
Metadata {
|
||||||
|
name: "BOLD",
|
||||||
|
escape: escape!("1"),
|
||||||
|
},
|
||||||
|
Metadata {
|
||||||
|
name: "DIMMED",
|
||||||
|
escape: escape!("2"),
|
||||||
|
},
|
||||||
|
Metadata {
|
||||||
|
name: "ITALIC",
|
||||||
|
escape: escape!("3"),
|
||||||
|
},
|
||||||
|
Metadata {
|
||||||
|
name: "UNDERLINE",
|
||||||
|
escape: escape!("4"),
|
||||||
|
},
|
||||||
|
Metadata {
|
||||||
|
name: "DOUBLE_UNDERLINE",
|
||||||
|
escape: escape!("21"),
|
||||||
|
},
|
||||||
|
Metadata {
|
||||||
|
name: "CURLY_UNDERLINE",
|
||||||
|
escape: escape!("4:3"),
|
||||||
|
},
|
||||||
|
Metadata {
|
||||||
|
name: "DOTTED_UNDERLINE",
|
||||||
|
escape: escape!("4:4"),
|
||||||
|
},
|
||||||
|
Metadata {
|
||||||
|
name: "DASHED_UNDERLINE",
|
||||||
|
escape: escape!("4:5"),
|
||||||
|
},
|
||||||
|
Metadata {
|
||||||
|
name: "BLINK",
|
||||||
|
escape: escape!("5"),
|
||||||
|
},
|
||||||
|
Metadata {
|
||||||
|
name: "INVERT",
|
||||||
|
escape: escape!("7"),
|
||||||
|
},
|
||||||
|
Metadata {
|
||||||
|
name: "HIDDEN",
|
||||||
|
escape: escape!("8"),
|
||||||
|
},
|
||||||
|
Metadata {
|
||||||
|
name: "STRIKETHROUGH",
|
||||||
|
escape: escape!("9"),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Default, Debug)]
|
||||||
|
struct EffectsDisplay(Effects);
|
||||||
|
|
||||||
|
impl core::fmt::Display for EffectsDisplay {
|
||||||
|
#[inline]
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
for index in self.0.index_iter() {
|
||||||
|
METADATA[index].escape.fmt(f)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct EffectIter {
|
||||||
|
index: usize,
|
||||||
|
effects: Effects,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for EffectIter {
|
||||||
|
type Item = Effects;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
while self.index < METADATA.len() {
|
||||||
|
let index = self.index;
|
||||||
|
self.index += 1;
|
||||||
|
|
||||||
|
let effect = Effects(1 << index);
|
||||||
|
if self.effects.contains(effect) {
|
||||||
|
return Some(effect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub(crate) struct EffectIndexIter {
|
||||||
|
index: usize,
|
||||||
|
effects: Effects,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for EffectIndexIter {
|
||||||
|
type Item = usize;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
while self.index < METADATA.len() {
|
||||||
|
let index = self.index;
|
||||||
|
self.index += 1;
|
||||||
|
|
||||||
|
let effect = Effects(1 << index);
|
||||||
|
if self.effects.contains(effect) {
|
||||||
|
return Some(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
59
vendor/anstyle/src/lib.rs
vendored
Normal file
59
vendor/anstyle/src/lib.rs
vendored
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
//! ANSI Text Styling
|
||||||
|
//!
|
||||||
|
//! *A portmanteau of "ansi style"*
|
||||||
|
//!
|
||||||
|
//! `anstyle` provides core types describing [ANSI styling escape
|
||||||
|
//! codes](https://en.wikipedia.org/wiki/ANSI_escape_code) for interoperability
|
||||||
|
//! between crates.
|
||||||
|
//!
|
||||||
|
//! Example use cases:
|
||||||
|
//! - An argument parser allowing callers to define the colors used in the help-output without
|
||||||
|
//! putting the text formatting crate in the public API
|
||||||
|
//! - A style description parser that can work with any text formatting crate
|
||||||
|
//!
|
||||||
|
//! Priorities:
|
||||||
|
//! 1. API stability
|
||||||
|
//! 2. Low compile-time and binary-size overhead
|
||||||
|
//! 3. `const` friendly API for callers to statically define their stylesheet
|
||||||
|
//!
|
||||||
|
//! For integration with text styling crate, see:
|
||||||
|
//! - [anstyle-ansi-term](https://docs.rs/anstyle-ansi-term)
|
||||||
|
//! - [anstyle-crossterm](https://docs.rs/anstyle-crossterm)
|
||||||
|
//! - [anstyle-owo-colors](https://docs.rs/anstyle-owo-colors)
|
||||||
|
//! - [anstyle-termcolor](https://docs.rs/anstyle-termcolor)
|
||||||
|
//! - [anstyle-yansi](https://docs.rs/anstyle-yansi)
|
||||||
|
//!
|
||||||
|
//! User-styling parsers:
|
||||||
|
//! - [anstyle-git](https://docs.rs/anstyle-git): Parse Git style descriptions
|
||||||
|
//! - [anstyle-ls](https://docs.rs/anstyle-ls): Parse LS_COLORS style descriptions
|
||||||
|
//!
|
||||||
|
//! Convert to other formats
|
||||||
|
//! - [anstream](https://docs.rs/anstream): A simple cross platform library for writing colored text to a terminal
|
||||||
|
//! - [anstyle-roff](https://docs.rs/anstyle-roff): For converting to ROFF
|
||||||
|
//!
|
||||||
|
//! Utilities
|
||||||
|
//! - [anstyle-lossy](https://docs.rs/anstyle-lossy): Convert between `anstyle::Color` types
|
||||||
|
//! - [anstyle-parse](https://docs.rs/anstyle-parse): Parsing ANSI Style Escapes
|
||||||
|
//! - [anstyle-wincon](https://docs.rs/anstyle-wincon): Styling legacy Microsoft terminals
|
||||||
|
//!
|
||||||
|
//! # Examples
|
||||||
|
//!
|
||||||
|
//! The core type is [`Style`]:
|
||||||
|
//! ```rust
|
||||||
|
//! let style = anstyle::Style::new().bold();
|
||||||
|
//! ```
|
||||||
|
|
||||||
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
mod macros;
|
||||||
|
|
||||||
|
mod color;
|
||||||
|
mod effect;
|
||||||
|
mod reset;
|
||||||
|
mod style;
|
||||||
|
|
||||||
|
pub use color::*;
|
||||||
|
pub use effect::*;
|
||||||
|
pub use reset::*;
|
||||||
|
pub use style::*;
|
5
vendor/anstyle/src/macros.rs
vendored
Normal file
5
vendor/anstyle/src/macros.rs
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
macro_rules! escape {
|
||||||
|
($($inner:expr),*) => {
|
||||||
|
concat!("\x1B[", $($inner),*, "m")
|
||||||
|
};
|
||||||
|
}
|
22
vendor/anstyle/src/reset.rs
vendored
Normal file
22
vendor/anstyle/src/reset.rs
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/// Reset terminal formatting
|
||||||
|
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub struct Reset;
|
||||||
|
|
||||||
|
impl Reset {
|
||||||
|
/// Render the ANSI code
|
||||||
|
#[inline]
|
||||||
|
pub fn render(self) -> impl core::fmt::Display + Copy + Clone {
|
||||||
|
ResetDisplay
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Default, Debug)]
|
||||||
|
struct ResetDisplay;
|
||||||
|
|
||||||
|
impl core::fmt::Display for ResetDisplay {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
RESET.fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) const RESET: &str = "\x1B[0m";
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user