mirror of
https://github.com/sharkdp/hexyl.git
synced 2026-10-28 08:05:52 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a9234c182 | ||
|
|
45fa72ec3b | ||
|
|
711627bfe8 | ||
|
|
ba89e88dfd | ||
|
|
1792090799 | ||
|
|
33d5b4dbda | ||
|
|
921327f2ae | ||
|
|
4bf875095c | ||
|
|
a78c00b10d | ||
|
|
2bab0c769e | ||
|
|
1310b1d19e | ||
|
|
a56b3b0c46 | ||
|
|
7ca00279ed | ||
|
|
dfb5d57ee7 | ||
|
|
a0a7d6761f | ||
|
|
7ef8e5aae4 | ||
|
|
8d5b355b76 | ||
|
|
19f325a691 | ||
|
|
10ddbbad7d | ||
|
|
58c8c06317 | ||
|
|
78477a90c9 | ||
|
|
9362c2313a | ||
|
|
e363f2fdc4 | ||
|
|
29e3350e69 | ||
|
|
0c192e979b | ||
|
|
c4f91959ef | ||
|
|
4e66357618 | ||
|
|
6a230d34a4 | ||
|
|
663e4c19ff | ||
|
|
894ca71b40 | ||
|
|
e85953eeb5 | ||
|
|
f5ce9946f6 | ||
|
|
668054fe50 | ||
|
|
d6cb7af643 | ||
|
|
7b59a3f374 | ||
|
|
3c69797f23 | ||
|
|
7e9bc5138d | ||
|
|
ce70246f80 | ||
|
|
a306c82024 | ||
|
|
e1e53335d3 | ||
|
|
c9f113c8c4 | ||
|
|
59557bd433 | ||
|
|
39a94379c6 |
No files matched your search
Generated
+62
-70
@@ -4,9 +4,9 @@ version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.0.2"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41"
|
||||
checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
@@ -52,9 +52,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "1.0.1"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188"
|
||||
checksum = "c677ab05e09154296dd37acecd46420c17b9713e8366facafa8fc0885167cf4c"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"windows-sys",
|
||||
@@ -62,9 +62,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.72"
|
||||
version = "1.0.75"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854"
|
||||
checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
|
||||
|
||||
[[package]]
|
||||
name = "assert_cmd"
|
||||
@@ -75,7 +75,7 @@ dependencies = [
|
||||
"anstyle",
|
||||
"bstr",
|
||||
"doc-comment",
|
||||
"predicates 3.0.3",
|
||||
"predicates",
|
||||
"predicates-core",
|
||||
"predicates-tree",
|
||||
"wait-timeout",
|
||||
@@ -95,9 +95,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.3.3"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42"
|
||||
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
@@ -112,24 +112,27 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.79"
|
||||
version = "1.0.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
|
||||
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.3.19"
|
||||
version = "4.3.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fd304a20bff958a57f04c4e96a2e7594cc4490a0e809cbd48bb6437edaa452d"
|
||||
checksum = "03aef18ddf7d879c15ce20f04826ef8418101c7e528014c3eeea13321047dca3"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.3.19"
|
||||
version = "4.3.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01c6a3f08f1fe5662a35cfe393aec09c4df95f60ee93b7556505260f75eee9e1"
|
||||
checksum = "f8ce6fffb678c9b80a70b6b6de0aad31df727623a70fd9a842c30cd573e2fa98"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@@ -197,9 +200,9 @@ checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.1"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
|
||||
checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f"
|
||||
dependencies = [
|
||||
"errno-dragonfly",
|
||||
"libc",
|
||||
@@ -233,7 +236,7 @@ checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
|
||||
|
||||
[[package]]
|
||||
name = "hexyl"
|
||||
version = "0.13.1"
|
||||
version = "0.14.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"assert_cmd",
|
||||
@@ -241,7 +244,7 @@ dependencies = [
|
||||
"const_format",
|
||||
"libc",
|
||||
"owo-colors",
|
||||
"predicates 2.1.5",
|
||||
"predicates",
|
||||
"pretty_assertions",
|
||||
"supports-color",
|
||||
"terminal_size",
|
||||
@@ -266,7 +269,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"rustix 0.38.4",
|
||||
"rustix 0.38.8",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
@@ -299,9 +302,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.3"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0"
|
||||
checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
@@ -336,20 +339,6 @@ version = "3.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
|
||||
|
||||
[[package]]
|
||||
name = "predicates"
|
||||
version = "2.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59230a63c37f3e18569bdb90e4a89cbf5bf8b06fea0b84e65ea10cc4df47addd"
|
||||
dependencies = [
|
||||
"difflib",
|
||||
"float-cmp",
|
||||
"itertools",
|
||||
"normalize-line-endings",
|
||||
"predicates-core",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "predicates"
|
||||
version = "3.0.3"
|
||||
@@ -358,8 +347,11 @@ checksum = "09963355b9f467184c04017ced4a2ba2d75cbcb4e7462690d388233253d4b1a9"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"difflib",
|
||||
"float-cmp",
|
||||
"itertools",
|
||||
"normalize-line-endings",
|
||||
"predicates-core",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -399,18 +391,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.32"
|
||||
version = "1.0.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965"
|
||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.9.1"
|
||||
version = "1.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575"
|
||||
checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
@@ -420,9 +412,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.3.3"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310"
|
||||
checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
@@ -451,22 +443,22 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.4"
|
||||
version = "0.38.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5"
|
||||
checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f"
|
||||
dependencies = [
|
||||
"bitflags 2.3.3",
|
||||
"bitflags 2.4.0",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.4.3",
|
||||
"linux-raw-sys 0.4.5",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.175"
|
||||
version = "1.0.185"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d25439cd7397d044e2748a6fe2432b5e85db703d6d097bd014b3c0ad1ebff0b"
|
||||
checksum = "be9b6f69f1dfd54c3b568ffa45c310d6973a5e5148fd40cf515acaf38cf5bc31"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
@@ -486,9 +478,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.27"
|
||||
version = "2.0.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b60f673f44a8255b9c8c657daf66a596d435f2da81a555b06dc644d080ba45e0"
|
||||
checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -513,18 +505,18 @@ checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76"
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.44"
|
||||
version = "1.0.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90"
|
||||
checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.44"
|
||||
version = "1.0.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96"
|
||||
checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -569,9 +561,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.1"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
@@ -584,45 +576,45 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.0"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.0"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.0"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.0"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.0"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.0"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.0"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
||||
[[package]]
|
||||
name = "yansi"
|
||||
|
||||
+2
-2
@@ -7,7 +7,7 @@ license = "MIT/Apache-2.0"
|
||||
name = "hexyl"
|
||||
readme = "README.md"
|
||||
repository = "https://github.com/sharkdp/hexyl"
|
||||
version = "0.13.1"
|
||||
version = "0.14.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.66"
|
||||
|
||||
@@ -27,7 +27,7 @@ features = ["std", "suggestions", "color", "wrap_help", "cargo", "help", "usage"
|
||||
|
||||
[dev-dependencies]
|
||||
assert_cmd = "2.0"
|
||||
predicates = "2.0"
|
||||
predicates = "3.0"
|
||||
pretty_assertions = "1.3.0"
|
||||
|
||||
[profile.release]
|
||||
|
||||
@@ -68,7 +68,7 @@ sudo dnf install hexyl
|
||||
|
||||
### On Arch Linux
|
||||
|
||||
You can install `hexyl` from [the official package repository](https://www.archlinux.org/packages/community/x86_64/hexyl/):
|
||||
You can install `hexyl` from [the official package repository](https://archlinux.org/packages/extra/x86_64/hexyl/):
|
||||
|
||||
```
|
||||
pacman -S hexyl
|
||||
@@ -110,6 +110,18 @@ sudo port install hexyl
|
||||
pkg install hexyl
|
||||
```
|
||||
|
||||
### On NetBSD
|
||||
|
||||
```
|
||||
pkgin install hexyl
|
||||
```
|
||||
|
||||
### On OpenBSD
|
||||
|
||||
```
|
||||
doas pkg_add hexyl
|
||||
```
|
||||
|
||||
### on Termux
|
||||
```
|
||||
pkg install hexyl
|
||||
|
||||
@@ -2,11 +2,6 @@
|
||||
%
|
||||
% 2022-12-05
|
||||
|
||||
<!--
|
||||
This man page is written in Pandoc's Markdown.
|
||||
See: https://pandoc.org/MANUAL.html#pandocs-markdown
|
||||
-->
|
||||
|
||||
# NAME
|
||||
|
||||
hexyl - a command-line hex viewer
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
use owo_colors::{colors, Color};
|
||||
|
||||
pub const COLOR_NULL: &[u8] = colors::BrightBlack::ANSI_FG.as_bytes();
|
||||
pub const COLOR_OFFSET: &[u8] = colors::BrightBlack::ANSI_FG.as_bytes();
|
||||
pub const COLOR_ASCII_PRINTABLE: &[u8] = colors::Cyan::ANSI_FG.as_bytes();
|
||||
pub const COLOR_ASCII_WHITESPACE: &[u8] = colors::Green::ANSI_FG.as_bytes();
|
||||
pub const COLOR_ASCII_OTHER: &[u8] = colors::Green::ANSI_FG.as_bytes();
|
||||
pub const COLOR_NONASCII: &[u8] = colors::Yellow::ANSI_FG.as_bytes();
|
||||
pub const COLOR_RESET: &[u8] = colors::Default::ANSI_FG.as_bytes();
|
||||
|
||||
#[rustfmt::skip]
|
||||
pub const CP437: [char; 256] = [
|
||||
// Copyright (c) 2016, Delan Azabani <delan@azabani.com>
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// modified to use the ⋄ character instead of ␀
|
||||
|
||||
// use https://en.wikipedia.org/w/index.php?title=Code_page_437&oldid=978947122
|
||||
// not ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/PC/CP437.TXT
|
||||
// because we want the graphic versions of 01h–1Fh + 7Fh
|
||||
'⋄','☺','☻','♥','♦','♣','♠','•','◘','○','◙','♂','♀','♪','♫','☼',
|
||||
'►','◄','↕','‼','¶','§','▬','↨','↑','↓','→','←','∟','↔','▲','▼',
|
||||
' ','!','"','#','$','%','&','\'','(',')','*','+',',','-','.','/',
|
||||
'0','1','2','3','4','5','6','7','8','9',':',';','<','=','>','?',
|
||||
'@','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O',
|
||||
'P','Q','R','S','T','U','V','W','X','Y','Z','[','\\',']','^','_',
|
||||
'`','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o',
|
||||
'p','q','r','s','t','u','v','w','x','y','z','{','|','}','~','⌂',
|
||||
'Ç','ü','é','â','ä','à','å','ç','ê','ë','è','ï','î','ì','Ä','Å',
|
||||
'É','æ','Æ','ô','ö','ò','û','ù','ÿ','Ö','Ü','¢','£','¥','₧','ƒ',
|
||||
'á','í','ó','ú','ñ','Ñ','ª','º','¿','⌐','¬','½','¼','¡','«','»',
|
||||
'░','▒','▓','│','┤','╡','╢','╖','╕','╣','║','╗','╝','╜','╛','┐',
|
||||
'└','┴','┬','├','─','┼','╞','╟','╚','╔','╩','╦','╠','═','╬','╧',
|
||||
'╨','╤','╥','╙','╘','╒','╓','╫','╪','┘','┌','█','▄','▌','▐','▀',
|
||||
'α','ß','Γ','π','Σ','σ','µ','τ','Φ','Θ','Ω','δ','∞','φ','ε','∩',
|
||||
'≡','±','≥','≤','⌠','⌡','÷','≈','°','∙','·','√','ⁿ','²','■','ff',
|
||||
];
|
||||
+49
-24
@@ -1,11 +1,11 @@
|
||||
pub(crate) mod colors;
|
||||
pub(crate) mod input;
|
||||
|
||||
pub use colors::*;
|
||||
pub use input::*;
|
||||
|
||||
use std::io::{self, BufReader, Read, Write};
|
||||
|
||||
use owo_colors::{colors, Color};
|
||||
|
||||
pub enum Base {
|
||||
Binary,
|
||||
Octal,
|
||||
@@ -13,14 +13,6 @@ pub enum Base {
|
||||
Hexadecimal,
|
||||
}
|
||||
|
||||
const COLOR_NULL: &[u8] = colors::BrightBlack::ANSI_FG.as_bytes();
|
||||
const COLOR_OFFSET: &[u8] = colors::BrightBlack::ANSI_FG.as_bytes();
|
||||
const COLOR_ASCII_PRINTABLE: &[u8] = colors::Cyan::ANSI_FG.as_bytes();
|
||||
const COLOR_ASCII_WHITESPACE: &[u8] = colors::Green::ANSI_FG.as_bytes();
|
||||
const COLOR_ASCII_OTHER: &[u8] = colors::Green::ANSI_FG.as_bytes();
|
||||
const COLOR_NONASCII: &[u8] = colors::Yellow::ANSI_FG.as_bytes();
|
||||
const COLOR_RESET: &[u8] = colors::Default::ANSI_FG.as_bytes();
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum ByteCategory {
|
||||
Null,
|
||||
@@ -30,6 +22,14 @@ pub enum ByteCategory {
|
||||
NonAscii,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[non_exhaustive]
|
||||
pub enum CharacterTable {
|
||||
Default,
|
||||
Ascii,
|
||||
CP437,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Endianness {
|
||||
Little,
|
||||
@@ -64,7 +64,6 @@ impl Byte {
|
||||
|
||||
fn color(self) -> &'static [u8] {
|
||||
use crate::ByteCategory::*;
|
||||
|
||||
match self.category() {
|
||||
Null => COLOR_NULL,
|
||||
AsciiPrintable => COLOR_ASCII_PRINTABLE,
|
||||
@@ -74,16 +73,26 @@ impl Byte {
|
||||
}
|
||||
}
|
||||
|
||||
fn as_char(self) -> char {
|
||||
fn as_char(self, character_table: CharacterTable) -> char {
|
||||
use crate::ByteCategory::*;
|
||||
|
||||
match self.category() {
|
||||
Null => '⋄',
|
||||
AsciiPrintable => self.0 as char,
|
||||
AsciiWhitespace if self.0 == 0x20 => ' ',
|
||||
AsciiWhitespace => '_',
|
||||
AsciiOther => '•',
|
||||
NonAscii => '×',
|
||||
match character_table {
|
||||
CharacterTable::Default => match self.category() {
|
||||
Null => '⋄',
|
||||
AsciiPrintable => self.0 as char,
|
||||
AsciiWhitespace if self.0 == 0x20 => ' ',
|
||||
AsciiWhitespace => '_',
|
||||
AsciiOther => '•',
|
||||
NonAscii => '×',
|
||||
},
|
||||
CharacterTable::Ascii => match self.category() {
|
||||
Null => '.',
|
||||
AsciiPrintable => self.0 as char,
|
||||
AsciiWhitespace if self.0 == 0x20 => ' ',
|
||||
AsciiWhitespace => '.',
|
||||
AsciiOther => '.',
|
||||
NonAscii => '.',
|
||||
},
|
||||
CharacterTable::CP437 => CP437[self.0 as usize],
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,6 +176,7 @@ pub struct PrinterBuilder<'a, Writer: Write> {
|
||||
group_size: u8,
|
||||
base: Base,
|
||||
endianness: Endianness,
|
||||
character_table: CharacterTable,
|
||||
}
|
||||
|
||||
impl<'a, Writer: Write> PrinterBuilder<'a, Writer> {
|
||||
@@ -182,6 +192,7 @@ impl<'a, Writer: Write> PrinterBuilder<'a, Writer> {
|
||||
group_size: 1,
|
||||
base: Base::Hexadecimal,
|
||||
endianness: Endianness::Big,
|
||||
character_table: CharacterTable::Default,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,6 +241,11 @@ impl<'a, Writer: Write> PrinterBuilder<'a, Writer> {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn character_table(mut self, character_table: CharacterTable) -> Self {
|
||||
self.character_table = character_table;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> Printer<'a, Writer> {
|
||||
Printer::new(
|
||||
self.writer,
|
||||
@@ -242,6 +258,7 @@ impl<'a, Writer: Write> PrinterBuilder<'a, Writer> {
|
||||
self.group_size,
|
||||
self.base,
|
||||
self.endianness,
|
||||
self.character_table,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -285,6 +302,7 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
|
||||
group_size: u8,
|
||||
base: Base,
|
||||
endianness: Endianness,
|
||||
character_table: CharacterTable,
|
||||
) -> Printer<'a, Writer> {
|
||||
Printer {
|
||||
idx: 0,
|
||||
@@ -304,7 +322,7 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
|
||||
})
|
||||
.collect(),
|
||||
byte_char_panel: (0u8..=u8::MAX)
|
||||
.map(|i| format!("{}", Byte(i).as_char()))
|
||||
.map(|i| format!("{}", Byte(i).as_char(character_table)))
|
||||
.collect(),
|
||||
byte_hex_panel_g: (0u8..=u8::MAX).map(|i| format!("{i:02x}")).collect(),
|
||||
squeezer: if use_squeeze {
|
||||
@@ -401,8 +419,7 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
|
||||
if self.show_position_panel {
|
||||
match self.squeezer {
|
||||
Squeezer::Print => {
|
||||
self.writer
|
||||
.write_all(self.byte_char_panel[b'*' as usize].as_bytes())?;
|
||||
self.writer.write_all(&[b'*'])?;
|
||||
if self.show_color {
|
||||
self.writer.write_all(COLOR_RESET)?;
|
||||
}
|
||||
@@ -613,7 +630,6 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
|
||||
}
|
||||
if is_empty {
|
||||
self.print_header()?;
|
||||
is_empty = false;
|
||||
}
|
||||
|
||||
// squeeze is active, check if the line is the same
|
||||
@@ -641,6 +657,11 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
|
||||
}
|
||||
self.writer.write_all(b"\n")?;
|
||||
|
||||
if is_empty {
|
||||
self.writer.flush()?;
|
||||
is_empty = false;
|
||||
}
|
||||
|
||||
// increment index to next line
|
||||
self.idx += 8 * self.panels;
|
||||
|
||||
@@ -732,6 +753,7 @@ mod tests {
|
||||
1,
|
||||
Base::Hexadecimal,
|
||||
Endianness::Big,
|
||||
CharacterTable::Default,
|
||||
);
|
||||
|
||||
printer.print_all(input).unwrap();
|
||||
@@ -787,6 +809,7 @@ mod tests {
|
||||
1,
|
||||
Base::Hexadecimal,
|
||||
Endianness::Big,
|
||||
CharacterTable::Default,
|
||||
);
|
||||
printer.display_offset(0xdeadbeef);
|
||||
|
||||
@@ -821,6 +844,7 @@ mod tests {
|
||||
1,
|
||||
Base::Hexadecimal,
|
||||
Endianness::Big,
|
||||
CharacterTable::Default,
|
||||
);
|
||||
|
||||
printer.print_all(input).unwrap();
|
||||
@@ -881,6 +905,7 @@ mod tests {
|
||||
1,
|
||||
Base::Hexadecimal,
|
||||
Endianness::Big,
|
||||
CharacterTable::Default,
|
||||
);
|
||||
|
||||
printer.print_all(input).unwrap();
|
||||
|
||||
+48
-163
@@ -17,7 +17,10 @@ use thiserror::Error as ThisError;
|
||||
|
||||
use terminal_size::terminal_size;
|
||||
|
||||
use hexyl::{Base, BorderStyle, Endianness, Input, PrinterBuilder};
|
||||
use hexyl::{Base, BorderStyle, CharacterTable, Endianness, Input, PrinterBuilder};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
const DEFAULT_BLOCK_SIZE: i64 = 512;
|
||||
|
||||
@@ -102,12 +105,13 @@ fn run() -> Result<()> {
|
||||
.long("color")
|
||||
.num_args(1)
|
||||
.value_name("WHEN")
|
||||
.value_parser(["always", "auto", "never"])
|
||||
.value_parser(["always", "auto", "never", "force"])
|
||||
.default_value_if("plain", ArgPredicate::IsPresent, Some("never"))
|
||||
.default_value("always")
|
||||
.help(
|
||||
"When to use colors. The auto-mode only displays colors if the output \
|
||||
goes to an interactive terminal",
|
||||
"When to use colors. The 'auto' mode only displays colors if the output \
|
||||
goes to an interactive terminal. 'force' can be used to override the \
|
||||
NO_COLOR environment variable.",
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
@@ -140,6 +144,21 @@ fn run() -> Result<()> {
|
||||
.action(ArgAction::SetTrue)
|
||||
.help("Show the character panel on the right. This is the default, unless --no-characters has been specified."),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("character-table")
|
||||
.long("character-table")
|
||||
.value_name("FORMAT")
|
||||
.value_parser(["default", "ascii", "codepage-437"])
|
||||
.default_value("default")
|
||||
.help(
|
||||
"Defines how bytes are mapped to characters:\n \
|
||||
\"default\": show printable ASCII characters as-is, '⋄' for NULL bytes, \
|
||||
' ' for space, '_' for other ASCII whitespace, \
|
||||
'•' for other ASCII characters, and '×' for non-ASCII bytes.\n \
|
||||
\"ascii\": show printable ASCII as-is, ' ' for space, '.' for everything else.\n \
|
||||
\"codepage-437\": uses code page 437 (for non-ASCII bytes).\n"
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("no_position")
|
||||
.short('P')
|
||||
@@ -323,12 +342,20 @@ fn run() -> Result<()> {
|
||||
reader.into_inner()
|
||||
};
|
||||
|
||||
let no_color = std::env::var_os("NO_COLOR").is_some();
|
||||
let show_color = match matches.get_one::<String>("color").map(String::as_ref) {
|
||||
Some("never") => false,
|
||||
Some("always") => true,
|
||||
_ => supports_color::on(supports_color::Stream::Stdout)
|
||||
.map(|level| level.has_basic)
|
||||
.unwrap_or(false),
|
||||
Some("always") => !no_color,
|
||||
Some("force") => true,
|
||||
_ => {
|
||||
if no_color {
|
||||
false
|
||||
} else {
|
||||
supports_color::on(supports_color::Stream::Stdout)
|
||||
.map(|level| level.has_basic)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let border_style = match matches.get_one::<String>("border").map(String::as_ref) {
|
||||
@@ -466,6 +493,18 @@ fn run() -> Result<()> {
|
||||
("big", _) => Endianness::Big,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let character_table = match matches
|
||||
.get_one::<String>("character-table")
|
||||
.unwrap()
|
||||
.as_ref()
|
||||
{
|
||||
"default" => CharacterTable::Default,
|
||||
"ascii" => CharacterTable::Ascii,
|
||||
"codepage-437" => CharacterTable::CP437,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let stdout = io::stdout();
|
||||
let mut stdout_lock = BufWriter::new(stdout.lock());
|
||||
|
||||
@@ -479,6 +518,7 @@ fn run() -> Result<()> {
|
||||
.group_size(group_size)
|
||||
.with_base(base)
|
||||
.endianness(endianness)
|
||||
.character_table(character_table)
|
||||
.build();
|
||||
printer.display_offset(skip_offset + display_offset);
|
||||
printer.print_all(&mut reader).map_err(|e| anyhow!(e))?;
|
||||
@@ -765,158 +805,3 @@ fn try_parse_as_hex_number(n: &str) -> Option<Result<i64, ByteOffsetParseError>>
|
||||
i64::from_str_radix(num, 16).map_err(ParseNum)
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unit_multipliers() {
|
||||
use Unit::*;
|
||||
assert_eq!(Kilobyte.get_multiplier(), 1000 * Byte.get_multiplier());
|
||||
assert_eq!(Megabyte.get_multiplier(), 1000 * Kilobyte.get_multiplier());
|
||||
assert_eq!(Gigabyte.get_multiplier(), 1000 * Megabyte.get_multiplier());
|
||||
assert_eq!(Terabyte.get_multiplier(), 1000 * Gigabyte.get_multiplier());
|
||||
|
||||
assert_eq!(Kibibyte.get_multiplier(), 1024 * Byte.get_multiplier());
|
||||
assert_eq!(Mebibyte.get_multiplier(), 1024 * Kibibyte.get_multiplier());
|
||||
assert_eq!(Gibibyte.get_multiplier(), 1024 * Mebibyte.get_multiplier());
|
||||
assert_eq!(Tebibyte.get_multiplier(), 1024 * Gibibyte.get_multiplier());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_process_sign() {
|
||||
use ByteOffsetKind::*;
|
||||
use ByteOffsetParseError::*;
|
||||
assert_eq!(process_sign_of("123"), Ok(("123", ForwardFromBeginning)));
|
||||
assert_eq!(process_sign_of("+123"), Ok(("123", ForwardFromLastOffset)));
|
||||
assert_eq!(process_sign_of("-123"), Ok(("123", BackwardFromEnd)));
|
||||
assert_eq!(process_sign_of("-"), Err(EmptyAfterSign));
|
||||
assert_eq!(process_sign_of("+"), Err(EmptyAfterSign));
|
||||
assert_eq!(process_sign_of(""), Err(Empty));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_as_hex() {
|
||||
assert_eq!(try_parse_as_hex_number("73"), None);
|
||||
assert_eq!(try_parse_as_hex_number("0x1337"), Some(Ok(0x1337)));
|
||||
assert!(matches!(try_parse_as_hex_number("0xnope"), Some(Err(_))));
|
||||
assert!(matches!(try_parse_as_hex_number("0x-1"), Some(Err(_))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extract_num_and_unit() {
|
||||
use ByteOffsetParseError::*;
|
||||
use Unit::*;
|
||||
// byte is default unit
|
||||
assert_eq!(extract_num_and_unit_from("4"), Ok((4, Byte)));
|
||||
// blocks are returned without customization
|
||||
assert_eq!(
|
||||
extract_num_and_unit_from("2blocks"),
|
||||
Ok((2, Block { custom_size: None }))
|
||||
);
|
||||
// no normalization is performed
|
||||
assert_eq!(extract_num_and_unit_from("1024kb"), Ok((1024, Kilobyte)));
|
||||
|
||||
// unit without number results in error
|
||||
assert_eq!(
|
||||
extract_num_and_unit_from("gib"),
|
||||
Err(EmptyWithUnit("gib".to_string()))
|
||||
);
|
||||
// empty string results in error
|
||||
assert_eq!(extract_num_and_unit_from(""), Err(Empty));
|
||||
// an invalid unit results in an error
|
||||
assert_eq!(
|
||||
extract_num_and_unit_from("25litres"),
|
||||
Err(InvalidUnit("litres".to_string()))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_byte_offset() {
|
||||
use ByteOffsetParseError::*;
|
||||
|
||||
macro_rules! success {
|
||||
($input: expr, $expected_kind: ident $expected_value: expr) => {
|
||||
success!($input, $expected_kind $expected_value; block_size: DEFAULT_BLOCK_SIZE)
|
||||
};
|
||||
($input: expr, $expected_kind: ident $expected_value: expr; block_size: $block_size: expr) => {
|
||||
assert_eq!(
|
||||
parse_byte_offset($input, PositiveI64::new($block_size).unwrap()),
|
||||
Ok(
|
||||
ByteOffset {
|
||||
value: NonNegativeI64::new($expected_value).unwrap(),
|
||||
kind: ByteOffsetKind::$expected_kind,
|
||||
}
|
||||
),
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! error {
|
||||
($input: expr, $expected_err: expr) => {
|
||||
assert_eq!(
|
||||
parse_byte_offset($input, PositiveI64::new(DEFAULT_BLOCK_SIZE).unwrap()),
|
||||
Err($expected_err),
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
success!("0", ForwardFromBeginning 0);
|
||||
success!("1", ForwardFromBeginning 1);
|
||||
success!("1", ForwardFromBeginning 1);
|
||||
success!("100", ForwardFromBeginning 100);
|
||||
success!("+100", ForwardFromLastOffset 100);
|
||||
|
||||
success!("0x0", ForwardFromBeginning 0);
|
||||
success!("0xf", ForwardFromBeginning 15);
|
||||
success!("0xdeadbeef", ForwardFromBeginning 3_735_928_559);
|
||||
|
||||
success!("1KB", ForwardFromBeginning 1000);
|
||||
success!("2MB", ForwardFromBeginning 2000000);
|
||||
success!("3GB", ForwardFromBeginning 3000000000);
|
||||
success!("4TB", ForwardFromBeginning 4000000000000);
|
||||
success!("+4TB", ForwardFromLastOffset 4000000000000);
|
||||
|
||||
success!("1GiB", ForwardFromBeginning 1073741824);
|
||||
success!("2TiB", ForwardFromBeginning 2199023255552);
|
||||
success!("+2TiB", ForwardFromLastOffset 2199023255552);
|
||||
|
||||
success!("0xff", ForwardFromBeginning 255);
|
||||
success!("0xEE", ForwardFromBeginning 238);
|
||||
success!("+0xFF", ForwardFromLastOffset 255);
|
||||
|
||||
success!("1block", ForwardFromBeginning 512; block_size: 512);
|
||||
success!("2block", ForwardFromBeginning 1024; block_size: 512);
|
||||
success!("1block", ForwardFromBeginning 4; block_size: 4);
|
||||
success!("2block", ForwardFromBeginning 8; block_size: 4);
|
||||
|
||||
// empty string is invalid
|
||||
error!("", Empty);
|
||||
// These are also bad.
|
||||
error!("+", EmptyAfterSign);
|
||||
error!("-", EmptyAfterSign);
|
||||
error!("K", InvalidNumAndUnit("K".to_owned()));
|
||||
error!("k", InvalidNumAndUnit("k".to_owned()));
|
||||
error!("m", InvalidNumAndUnit("m".to_owned()));
|
||||
error!("block", EmptyWithUnit("block".to_owned()));
|
||||
// leading/trailing space is invalid
|
||||
error!(" 0", InvalidNumAndUnit(" 0".to_owned()));
|
||||
error!("0 ", InvalidUnit(" ".to_owned()));
|
||||
// Signs after the hex prefix make no sense
|
||||
error!("0x-12", SignFoundAfterHexPrefix('-'));
|
||||
// This was previously accepted but shouldn't be.
|
||||
error!("0x+12", SignFoundAfterHexPrefix('+'));
|
||||
// invalid suffix
|
||||
error!("1234asdf", InvalidUnit("asdf".to_owned()));
|
||||
// bad numbers
|
||||
error!("asdf1234", InvalidNumAndUnit("asdf1234".to_owned()));
|
||||
error!("a1s2d3f4", InvalidNumAndUnit("a1s2d3f4".to_owned()));
|
||||
// multiplication overflows u64
|
||||
error!("20000000TiB", UnitMultiplicationOverflow);
|
||||
|
||||
assert!(
|
||||
match parse_byte_offset("99999999999999999999", PositiveI64::new(512).unwrap()) {
|
||||
// We can't check against the kind of the `ParseIntError`, so we'll just make sure it's the
|
||||
// same as trying to do the parse directly.
|
||||
Err(ParseNum(e)) => e == "99999999999999999999".parse::<i64>().unwrap_err(),
|
||||
_ => false,
|
||||
}
|
||||
);
|
||||
}
|
||||
+156
@@ -0,0 +1,156 @@
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn unit_multipliers() {
|
||||
use Unit::*;
|
||||
assert_eq!(Kilobyte.get_multiplier(), 1000 * Byte.get_multiplier());
|
||||
assert_eq!(Megabyte.get_multiplier(), 1000 * Kilobyte.get_multiplier());
|
||||
assert_eq!(Gigabyte.get_multiplier(), 1000 * Megabyte.get_multiplier());
|
||||
assert_eq!(Terabyte.get_multiplier(), 1000 * Gigabyte.get_multiplier());
|
||||
|
||||
assert_eq!(Kibibyte.get_multiplier(), 1024 * Byte.get_multiplier());
|
||||
assert_eq!(Mebibyte.get_multiplier(), 1024 * Kibibyte.get_multiplier());
|
||||
assert_eq!(Gibibyte.get_multiplier(), 1024 * Mebibyte.get_multiplier());
|
||||
assert_eq!(Tebibyte.get_multiplier(), 1024 * Gibibyte.get_multiplier());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_process_sign() {
|
||||
use ByteOffsetKind::*;
|
||||
use ByteOffsetParseError::*;
|
||||
assert_eq!(process_sign_of("123"), Ok(("123", ForwardFromBeginning)));
|
||||
assert_eq!(process_sign_of("+123"), Ok(("123", ForwardFromLastOffset)));
|
||||
assert_eq!(process_sign_of("-123"), Ok(("123", BackwardFromEnd)));
|
||||
assert_eq!(process_sign_of("-"), Err(EmptyAfterSign));
|
||||
assert_eq!(process_sign_of("+"), Err(EmptyAfterSign));
|
||||
assert_eq!(process_sign_of(""), Err(Empty));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_as_hex() {
|
||||
assert_eq!(try_parse_as_hex_number("73"), None);
|
||||
assert_eq!(try_parse_as_hex_number("0x1337"), Some(Ok(0x1337)));
|
||||
assert!(matches!(try_parse_as_hex_number("0xnope"), Some(Err(_))));
|
||||
assert!(matches!(try_parse_as_hex_number("0x-1"), Some(Err(_))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extract_num_and_unit() {
|
||||
use ByteOffsetParseError::*;
|
||||
use Unit::*;
|
||||
// byte is default unit
|
||||
assert_eq!(extract_num_and_unit_from("4"), Ok((4, Byte)));
|
||||
// blocks are returned without customization
|
||||
assert_eq!(
|
||||
extract_num_and_unit_from("2blocks"),
|
||||
Ok((2, Block { custom_size: None }))
|
||||
);
|
||||
// no normalization is performed
|
||||
assert_eq!(extract_num_and_unit_from("1024kb"), Ok((1024, Kilobyte)));
|
||||
|
||||
// unit without number results in error
|
||||
assert_eq!(
|
||||
extract_num_and_unit_from("gib"),
|
||||
Err(EmptyWithUnit("gib".to_string()))
|
||||
);
|
||||
// empty string results in error
|
||||
assert_eq!(extract_num_and_unit_from(""), Err(Empty));
|
||||
// an invalid unit results in an error
|
||||
assert_eq!(
|
||||
extract_num_and_unit_from("25litres"),
|
||||
Err(InvalidUnit("litres".to_string()))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_byte_offset() {
|
||||
use ByteOffsetParseError::*;
|
||||
|
||||
macro_rules! success {
|
||||
($input: expr, $expected_kind: ident $expected_value: expr) => {
|
||||
success!($input, $expected_kind $expected_value; block_size: DEFAULT_BLOCK_SIZE)
|
||||
};
|
||||
($input: expr, $expected_kind: ident $expected_value: expr; block_size: $block_size: expr) => {
|
||||
assert_eq!(
|
||||
parse_byte_offset($input, PositiveI64::new($block_size).unwrap()),
|
||||
Ok(
|
||||
ByteOffset {
|
||||
value: NonNegativeI64::new($expected_value).unwrap(),
|
||||
kind: ByteOffsetKind::$expected_kind,
|
||||
}
|
||||
),
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! error {
|
||||
($input: expr, $expected_err: expr) => {
|
||||
assert_eq!(
|
||||
parse_byte_offset($input, PositiveI64::new(DEFAULT_BLOCK_SIZE).unwrap()),
|
||||
Err($expected_err),
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
success!("0", ForwardFromBeginning 0);
|
||||
success!("1", ForwardFromBeginning 1);
|
||||
success!("1", ForwardFromBeginning 1);
|
||||
success!("100", ForwardFromBeginning 100);
|
||||
success!("+100", ForwardFromLastOffset 100);
|
||||
|
||||
success!("0x0", ForwardFromBeginning 0);
|
||||
success!("0xf", ForwardFromBeginning 15);
|
||||
success!("0xdeadbeef", ForwardFromBeginning 3_735_928_559);
|
||||
|
||||
success!("1KB", ForwardFromBeginning 1000);
|
||||
success!("2MB", ForwardFromBeginning 2000000);
|
||||
success!("3GB", ForwardFromBeginning 3000000000);
|
||||
success!("4TB", ForwardFromBeginning 4000000000000);
|
||||
success!("+4TB", ForwardFromLastOffset 4000000000000);
|
||||
|
||||
success!("1GiB", ForwardFromBeginning 1073741824);
|
||||
success!("2TiB", ForwardFromBeginning 2199023255552);
|
||||
success!("+2TiB", ForwardFromLastOffset 2199023255552);
|
||||
|
||||
success!("0xff", ForwardFromBeginning 255);
|
||||
success!("0xEE", ForwardFromBeginning 238);
|
||||
success!("+0xFF", ForwardFromLastOffset 255);
|
||||
|
||||
success!("1block", ForwardFromBeginning 512; block_size: 512);
|
||||
success!("2block", ForwardFromBeginning 1024; block_size: 512);
|
||||
success!("1block", ForwardFromBeginning 4; block_size: 4);
|
||||
success!("2block", ForwardFromBeginning 8; block_size: 4);
|
||||
|
||||
// empty string is invalid
|
||||
error!("", Empty);
|
||||
// These are also bad.
|
||||
error!("+", EmptyAfterSign);
|
||||
error!("-", EmptyAfterSign);
|
||||
error!("K", InvalidNumAndUnit("K".to_owned()));
|
||||
error!("k", InvalidNumAndUnit("k".to_owned()));
|
||||
error!("m", InvalidNumAndUnit("m".to_owned()));
|
||||
error!("block", EmptyWithUnit("block".to_owned()));
|
||||
// leading/trailing space is invalid
|
||||
error!(" 0", InvalidNumAndUnit(" 0".to_owned()));
|
||||
error!("0 ", InvalidUnit(" ".to_owned()));
|
||||
// Signs after the hex prefix make no sense
|
||||
error!("0x-12", SignFoundAfterHexPrefix('-'));
|
||||
// This was previously accepted but shouldn't be.
|
||||
error!("0x+12", SignFoundAfterHexPrefix('+'));
|
||||
// invalid suffix
|
||||
error!("1234asdf", InvalidUnit("asdf".to_owned()));
|
||||
// bad numbers
|
||||
error!("asdf1234", InvalidNumAndUnit("asdf1234".to_owned()));
|
||||
error!("a1s2d3f4", InvalidNumAndUnit("a1s2d3f4".to_owned()));
|
||||
// multiplication overflows u64
|
||||
error!("20000000TiB", UnitMultiplicationOverflow);
|
||||
|
||||
assert!(
|
||||
match parse_byte_offset("99999999999999999999", PositiveI64::new(512).unwrap()) {
|
||||
// We can't check against the kind of the `ParseIntError`, so we'll just make sure it's the
|
||||
// same as trying to do the parse directly.
|
||||
Err(ParseNum(e)) => e == "99999999999999999999".parse::<i64>().unwrap_err(),
|
||||
_ => false,
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -618,3 +618,116 @@ mod base {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
mod character_table {
|
||||
use super::hexyl;
|
||||
use super::PrettyAssert;
|
||||
|
||||
#[test]
|
||||
fn ascii() {
|
||||
hexyl()
|
||||
.arg("hello_world_elf64")
|
||||
.arg("--color=never")
|
||||
.arg("--character-table=ascii")
|
||||
.assert()
|
||||
.success()
|
||||
.pretty_stdout(
|
||||
"┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐
|
||||
│00000000│ 7f 45 4c 46 02 01 01 00 ┊ 00 00 00 00 00 00 00 00 │.ELF....┊........│
|
||||
│00000010│ 02 00 3e 00 01 00 00 00 ┊ 00 10 40 00 00 00 00 00 │..>.....┊..@.....│
|
||||
│00000020│ 40 00 00 00 00 00 00 00 ┊ 28 20 00 00 00 00 00 00 │@.......┊( ......│
|
||||
│00000030│ 00 00 00 00 40 00 38 00 ┊ 03 00 40 00 04 00 03 00 │....@.8.┊..@.....│
|
||||
│00000040│ 01 00 00 00 04 00 00 00 ┊ 00 00 00 00 00 00 00 00 │........┊........│
|
||||
│00000050│ 00 00 40 00 00 00 00 00 ┊ 00 00 40 00 00 00 00 00 │..@.....┊..@.....│
|
||||
│00000060│ e8 00 00 00 00 00 00 00 ┊ e8 00 00 00 00 00 00 00 │........┊........│
|
||||
│00000070│ 00 10 00 00 00 00 00 00 ┊ 01 00 00 00 05 00 00 00 │........┊........│
|
||||
│00000080│ 00 10 00 00 00 00 00 00 ┊ 00 10 40 00 00 00 00 00 │........┊..@.....│
|
||||
│00000090│ 00 10 40 00 00 00 00 00 ┊ 1d 00 00 00 00 00 00 00 │..@.....┊........│
|
||||
│000000a0│ 1d 00 00 00 00 00 00 00 ┊ 00 10 00 00 00 00 00 00 │........┊........│
|
||||
│000000b0│ 01 00 00 00 06 00 00 00 ┊ 00 20 00 00 00 00 00 00 │........┊. ......│
|
||||
│000000c0│ 00 20 40 00 00 00 00 00 ┊ 00 20 40 00 00 00 00 00 │. @.....┊. @.....│
|
||||
│000000d0│ 0e 00 00 00 00 00 00 00 ┊ 0e 00 00 00 00 00 00 00 │........┊........│
|
||||
│000000e0│ 00 10 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │........┊........│
|
||||
│000000f0│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │........┊........│
|
||||
│* │ ┊ │ ┊ │
|
||||
│00001000│ ba 0e 00 00 00 b9 00 20 ┊ 40 00 bb 01 00 00 00 b8 │....... ┊@.......│
|
||||
│00001010│ 04 00 00 00 cd 80 b8 01 ┊ 00 00 00 cd 80 00 00 00 │........┊........│
|
||||
│00001020│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │........┊........│
|
||||
│* │ ┊ │ ┊ │
|
||||
│00002000│ 48 65 6c 6c 6f 2c 20 77 ┊ 6f 72 6c 64 21 0a 00 2e │Hello, w┊orld!...│
|
||||
│00002010│ 73 68 73 74 72 74 61 62 ┊ 00 2e 74 65 78 74 00 2e │shstrtab┊..text..│
|
||||
│00002020│ 64 61 74 61 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │data....┊........│
|
||||
│00002030│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │........┊........│
|
||||
│* │ ┊ │ ┊ │
|
||||
│00002060│ 00 00 00 00 00 00 00 00 ┊ 0b 00 00 00 01 00 00 00 │........┊........│
|
||||
│00002070│ 06 00 00 00 00 00 00 00 ┊ 00 10 40 00 00 00 00 00 │........┊..@.....│
|
||||
│00002080│ 00 10 00 00 00 00 00 00 ┊ 1d 00 00 00 00 00 00 00 │........┊........│
|
||||
│00002090│ 00 00 00 00 00 00 00 00 ┊ 10 00 00 00 00 00 00 00 │........┊........│
|
||||
│000020a0│ 00 00 00 00 00 00 00 00 ┊ 11 00 00 00 01 00 00 00 │........┊........│
|
||||
│000020b0│ 03 00 00 00 00 00 00 00 ┊ 00 20 40 00 00 00 00 00 │........┊. @.....│
|
||||
│000020c0│ 00 20 00 00 00 00 00 00 ┊ 0e 00 00 00 00 00 00 00 │. ......┊........│
|
||||
│000020d0│ 00 00 00 00 00 00 00 00 ┊ 04 00 00 00 00 00 00 00 │........┊........│
|
||||
│000020e0│ 00 00 00 00 00 00 00 00 ┊ 01 00 00 00 03 00 00 00 │........┊........│
|
||||
│000020f0│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │........┊........│
|
||||
│00002100│ 0e 20 00 00 00 00 00 00 ┊ 17 00 00 00 00 00 00 00 │. ......┊........│
|
||||
│00002110│ 00 00 00 00 00 00 00 00 ┊ 01 00 00 00 00 00 00 00 │........┊........│
|
||||
│00002120│ 00 00 00 00 00 00 00 00 ┊ │........┊ │
|
||||
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘
|
||||
",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn codepage_437() {
|
||||
hexyl()
|
||||
.arg("hello_world_elf64")
|
||||
.arg("--color=never")
|
||||
.arg("--character-table=codepage-437")
|
||||
.assert()
|
||||
.success()
|
||||
.pretty_stdout(
|
||||
"┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐
|
||||
│00000000│ 7f 45 4c 46 02 01 01 00 ┊ 00 00 00 00 00 00 00 00 │⌂ELF☻☺☺⋄┊⋄⋄⋄⋄⋄⋄⋄⋄│
|
||||
│00000010│ 02 00 3e 00 01 00 00 00 ┊ 00 10 40 00 00 00 00 00 │☻⋄>⋄☺⋄⋄⋄┊⋄►@⋄⋄⋄⋄⋄│
|
||||
│00000020│ 40 00 00 00 00 00 00 00 ┊ 28 20 00 00 00 00 00 00 │@⋄⋄⋄⋄⋄⋄⋄┊( ⋄⋄⋄⋄⋄⋄│
|
||||
│00000030│ 00 00 00 00 40 00 38 00 ┊ 03 00 40 00 04 00 03 00 │⋄⋄⋄⋄@⋄8⋄┊♥⋄@⋄♦⋄♥⋄│
|
||||
│00000040│ 01 00 00 00 04 00 00 00 ┊ 00 00 00 00 00 00 00 00 │☺⋄⋄⋄♦⋄⋄⋄┊⋄⋄⋄⋄⋄⋄⋄⋄│
|
||||
│00000050│ 00 00 40 00 00 00 00 00 ┊ 00 00 40 00 00 00 00 00 │⋄⋄@⋄⋄⋄⋄⋄┊⋄⋄@⋄⋄⋄⋄⋄│
|
||||
│00000060│ e8 00 00 00 00 00 00 00 ┊ e8 00 00 00 00 00 00 00 │Φ⋄⋄⋄⋄⋄⋄⋄┊Φ⋄⋄⋄⋄⋄⋄⋄│
|
||||
│00000070│ 00 10 00 00 00 00 00 00 ┊ 01 00 00 00 05 00 00 00 │⋄►⋄⋄⋄⋄⋄⋄┊☺⋄⋄⋄♣⋄⋄⋄│
|
||||
│00000080│ 00 10 00 00 00 00 00 00 ┊ 00 10 40 00 00 00 00 00 │⋄►⋄⋄⋄⋄⋄⋄┊⋄►@⋄⋄⋄⋄⋄│
|
||||
│00000090│ 00 10 40 00 00 00 00 00 ┊ 1d 00 00 00 00 00 00 00 │⋄►@⋄⋄⋄⋄⋄┊↔⋄⋄⋄⋄⋄⋄⋄│
|
||||
│000000a0│ 1d 00 00 00 00 00 00 00 ┊ 00 10 00 00 00 00 00 00 │↔⋄⋄⋄⋄⋄⋄⋄┊⋄►⋄⋄⋄⋄⋄⋄│
|
||||
│000000b0│ 01 00 00 00 06 00 00 00 ┊ 00 20 00 00 00 00 00 00 │☺⋄⋄⋄♠⋄⋄⋄┊⋄ ⋄⋄⋄⋄⋄⋄│
|
||||
│000000c0│ 00 20 40 00 00 00 00 00 ┊ 00 20 40 00 00 00 00 00 │⋄ @⋄⋄⋄⋄⋄┊⋄ @⋄⋄⋄⋄⋄│
|
||||
│000000d0│ 0e 00 00 00 00 00 00 00 ┊ 0e 00 00 00 00 00 00 00 │♫⋄⋄⋄⋄⋄⋄⋄┊♫⋄⋄⋄⋄⋄⋄⋄│
|
||||
│000000e0│ 00 10 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │⋄►⋄⋄⋄⋄⋄⋄┊⋄⋄⋄⋄⋄⋄⋄⋄│
|
||||
│000000f0│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │⋄⋄⋄⋄⋄⋄⋄⋄┊⋄⋄⋄⋄⋄⋄⋄⋄│
|
||||
│* │ ┊ │ ┊ │
|
||||
│00001000│ ba 0e 00 00 00 b9 00 20 ┊ 40 00 bb 01 00 00 00 b8 │║♫⋄⋄⋄╣⋄ ┊@⋄╗☺⋄⋄⋄╕│
|
||||
│00001010│ 04 00 00 00 cd 80 b8 01 ┊ 00 00 00 cd 80 00 00 00 │♦⋄⋄⋄═Ç╕☺┊⋄⋄⋄═Ç⋄⋄⋄│
|
||||
│00001020│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │⋄⋄⋄⋄⋄⋄⋄⋄┊⋄⋄⋄⋄⋄⋄⋄⋄│
|
||||
│* │ ┊ │ ┊ │
|
||||
│00002000│ 48 65 6c 6c 6f 2c 20 77 ┊ 6f 72 6c 64 21 0a 00 2e │Hello, w┊orld!◙⋄.│
|
||||
│00002010│ 73 68 73 74 72 74 61 62 ┊ 00 2e 74 65 78 74 00 2e │shstrtab┊⋄.text⋄.│
|
||||
│00002020│ 64 61 74 61 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │data⋄⋄⋄⋄┊⋄⋄⋄⋄⋄⋄⋄⋄│
|
||||
│00002030│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │⋄⋄⋄⋄⋄⋄⋄⋄┊⋄⋄⋄⋄⋄⋄⋄⋄│
|
||||
│* │ ┊ │ ┊ │
|
||||
│00002060│ 00 00 00 00 00 00 00 00 ┊ 0b 00 00 00 01 00 00 00 │⋄⋄⋄⋄⋄⋄⋄⋄┊♂⋄⋄⋄☺⋄⋄⋄│
|
||||
│00002070│ 06 00 00 00 00 00 00 00 ┊ 00 10 40 00 00 00 00 00 │♠⋄⋄⋄⋄⋄⋄⋄┊⋄►@⋄⋄⋄⋄⋄│
|
||||
│00002080│ 00 10 00 00 00 00 00 00 ┊ 1d 00 00 00 00 00 00 00 │⋄►⋄⋄⋄⋄⋄⋄┊↔⋄⋄⋄⋄⋄⋄⋄│
|
||||
│00002090│ 00 00 00 00 00 00 00 00 ┊ 10 00 00 00 00 00 00 00 │⋄⋄⋄⋄⋄⋄⋄⋄┊►⋄⋄⋄⋄⋄⋄⋄│
|
||||
│000020a0│ 00 00 00 00 00 00 00 00 ┊ 11 00 00 00 01 00 00 00 │⋄⋄⋄⋄⋄⋄⋄⋄┊◄⋄⋄⋄☺⋄⋄⋄│
|
||||
│000020b0│ 03 00 00 00 00 00 00 00 ┊ 00 20 40 00 00 00 00 00 │♥⋄⋄⋄⋄⋄⋄⋄┊⋄ @⋄⋄⋄⋄⋄│
|
||||
│000020c0│ 00 20 00 00 00 00 00 00 ┊ 0e 00 00 00 00 00 00 00 │⋄ ⋄⋄⋄⋄⋄⋄┊♫⋄⋄⋄⋄⋄⋄⋄│
|
||||
│000020d0│ 00 00 00 00 00 00 00 00 ┊ 04 00 00 00 00 00 00 00 │⋄⋄⋄⋄⋄⋄⋄⋄┊♦⋄⋄⋄⋄⋄⋄⋄│
|
||||
│000020e0│ 00 00 00 00 00 00 00 00 ┊ 01 00 00 00 03 00 00 00 │⋄⋄⋄⋄⋄⋄⋄⋄┊☺⋄⋄⋄♥⋄⋄⋄│
|
||||
│000020f0│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │⋄⋄⋄⋄⋄⋄⋄⋄┊⋄⋄⋄⋄⋄⋄⋄⋄│
|
||||
│00002100│ 0e 20 00 00 00 00 00 00 ┊ 17 00 00 00 00 00 00 00 │♫ ⋄⋄⋄⋄⋄⋄┊↨⋄⋄⋄⋄⋄⋄⋄│
|
||||
│00002110│ 00 00 00 00 00 00 00 00 ┊ 01 00 00 00 00 00 00 00 │⋄⋄⋄⋄⋄⋄⋄⋄┊☺⋄⋄⋄⋄⋄⋄⋄│
|
||||
│00002120│ 00 00 00 00 00 00 00 00 ┊ │⋄⋄⋄⋄⋄⋄⋄⋄┊ │
|
||||
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘
|
||||
",
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user