From 179c8f40a2765eaf6c9cf12a4c6ed4f88e24cc1a Mon Sep 17 00:00:00 2001 From: RinHizakura Date: Mon, 3 Oct 2022 20:52:57 +0800 Subject: [PATCH 1/7] Support byte grouping --- examples/simple.rs | 1 + src/bin/hexyl.rs | 33 ++++++++++++++++++++++++- src/lib.rs | 49 +++++++++++++++++++++++++++++++------- tests/integration_tests.rs | 4 ++-- 4 files changed, 75 insertions(+), 12 deletions(-) diff --git a/examples/simple.rs b/examples/simple.rs index a7996c1..4f4b671 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -18,6 +18,7 @@ fn main() { .with_border_style(BorderStyle::Unicode) .enable_squeezing(false) .num_panels(2) + .num_group_bytes(1) .build(); printer.print_all(&input[..]).unwrap(); } diff --git a/src/bin/hexyl.rs b/src/bin/hexyl.rs index 03d3579..2c17dee 100644 --- a/src/bin/hexyl.rs +++ b/src/bin/hexyl.rs @@ -4,7 +4,7 @@ extern crate clap; use std::convert::TryFrom; use std::fs::File; use std::io::{self, prelude::*, BufWriter, SeekFrom}; -use std::num::{NonZeroI64, NonZeroU64}; +use std::num::{NonZeroI64, NonZeroU64, NonZeroU8}; use clap::builder::ArgPredicate; use clap::{crate_name, crate_version, Arg, ArgAction, ColorChoice, Command}; @@ -166,6 +166,17 @@ fn run() -> Result<(), AnyhowError> { based on the current terminal width", ), ) + .arg( + Arg::new("group_bytes") + .short('g') + .takes_value(true) + .value_name("N") + .help( + "Sets the number of octets per group to be displayed. \ + The possible option will be 1, 2, 4, 8, otherwise it will be set \ + to 1 by default.", + ), + ) .arg( Arg::new("terminal_width") .long("terminal-width") @@ -337,6 +348,25 @@ fn run() -> Result<(), AnyhowError> { 2 }; + let group_bytes = if let Some(group_bytes) = matches + .value_of("group_bytes") + .map(|s| { + s.parse::().map(u8::from).context(anyhow!( + "failed to parse `-g` arg {:?} as unsigned nonzero integer", + s + )) + }) + .transpose()? + { + if (group_bytes <= 8) && ((group_bytes & (group_bytes - 1)) == 0) { + group_bytes + } else { + 1 + } + } else { + 1 + }; + let stdout = io::stdout(); let mut stdout_lock = BufWriter::new(stdout.lock()); @@ -347,6 +377,7 @@ fn run() -> Result<(), AnyhowError> { .with_border_style(border_style) .enable_squeezing(squeeze) .num_panels(panels) + .num_group_bytes(group_bytes) .build(); printer.display_offset(skip_offset + display_offset); printer.print_all(&mut reader).map_err(|e| anyhow!(e))?; diff --git a/src/lib.rs b/src/lib.rs index 1b4738e..dfaaa9c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -150,6 +150,7 @@ pub struct PrinterBuilder<'a, Writer: Write> { border_style: BorderStyle, use_squeeze: bool, panels: u64, + group_bytes: u8, } impl<'a, Writer: Write> PrinterBuilder<'a, Writer> { @@ -162,6 +163,7 @@ impl<'a, Writer: Write> PrinterBuilder<'a, Writer> { border_style: BorderStyle::Unicode, use_squeeze: true, panels: 2, + group_bytes: 1, } } @@ -195,6 +197,11 @@ impl<'a, Writer: Write> PrinterBuilder<'a, Writer> { self } + pub fn num_group_bytes(mut self, num: u8) -> Self { + self.group_bytes = num; + self + } + pub fn build(self) -> Printer<'a, Writer> { Printer::new( self.writer, @@ -204,6 +211,7 @@ impl<'a, Writer: Write> PrinterBuilder<'a, Writer> { self.border_style, self.use_squeeze, self.panels, + self.group_bytes, ) } } @@ -226,6 +234,8 @@ pub struct Printer<'a, Writer: Write> { /// The number of panels to draw. panels: u64, squeeze_byte: usize, + /// The number of octets per group. + group_bytes: u8, } impl<'a, Writer: Write> Printer<'a, Writer> { @@ -237,6 +247,7 @@ impl<'a, Writer: Write> Printer<'a, Writer> { border_style: BorderStyle, use_squeeze: bool, panels: u64, + group_bytes: u8, ) -> Printer<'a, Writer> { Printer { idx: 0, @@ -295,6 +306,7 @@ impl<'a, Writer: Write> Printer<'a, Writer> { display_offset: 0, panels, squeeze_byte: 0x00, + group_bytes, } } @@ -303,13 +315,21 @@ impl<'a, Writer: Write> Printer<'a, Writer> { self } + fn panel_sz(&self) -> usize { + // add one to include the trailing space of a group + let group_sz = 2 * self.group_bytes as usize + 1; + let group_per_panel = 8 / self.group_bytes as usize; + // add one to include the leading space + 1 + group_sz * group_per_panel + } + fn write_border(&mut self, border_elements: BorderElements) -> io::Result<()> { let h = border_elements.horizontal_line; let c = border_elements.column_separator; let l = border_elements.left_corner; let r = border_elements.right_corner; let h8 = h.to_string().repeat(8); - let h25 = h.to_string().repeat(25); + let h_repeat = h.to_string().repeat(self.panel_sz()); if self.show_position_panel { write!(self.writer, "{l}{h8}{c}", l = l, c = c, h8 = h8).ok(); @@ -318,12 +338,12 @@ impl<'a, Writer: Write> Printer<'a, Writer> { } for _ in 0..self.panels - 1 { - write!(self.writer, "{h25}{c}", h25 = h25, c = c).ok(); + write!(self.writer, "{h_repeat}{c}", h_repeat = h_repeat, c = c).ok(); } if self.show_char_panel { - write!(self.writer, "{h25}{c}", h25 = h25, c = c).ok(); + write!(self.writer, "{h_repeat}{c}", h_repeat = h_repeat, c = c).ok(); } else { - write!(self.writer, "{h25}", h25 = h25).ok(); + write!(self.writer, "{h_repeat}", h_repeat = h_repeat).ok(); } if self.show_char_panel { @@ -433,13 +453,17 @@ impl<'a, Writer: Write> Printer<'a, Writer> { self.writer .write_all(self.byte_char_panel_g[b'*' as usize].as_bytes())?; } else { - self.writer.write_all(b" ")?; + if i % (self.group_bytes as usize) == 0 { + self.writer.write_all(b" ")?; + } } self.writer.write_all(b" ")?; } Squeezer::Delete => self.writer.write_all(b" ")?, Squeezer::Ignore | Squeezer::Disabled => { - self.writer.write_all(b" ")?; + if i % (self.group_bytes as usize) == 0 { + self.writer.write_all(b" ")?; + } self.writer .write_all(self.byte_hex_panel[b as usize].as_bytes())?; } @@ -562,8 +586,11 @@ impl<'a, Writer: Write> Printer<'a, Writer> { } write!( self.writer, - "{0:2}{1:24}{0}{0:>26}", - "│", "No content to print" + "{0:2}{1:2$}{0}{0:>3$}", + "│", + "No content", + self.panel_sz() - 1, + self.panel_sz() + 1, )?; if self.show_char_panel { write!(self.writer, "{0:>9}{0:>9}", "│")?; @@ -614,6 +641,7 @@ mod tests { BorderStyle::Unicode, true, 2, + 1, ); printer.print_all(input).unwrap(); @@ -627,7 +655,7 @@ mod tests { let input = io::empty(); let expected_string = "\ ┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐ -│ │ No content to print │ │ │ │ +│ │ No content │ │ │ │ └────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘ " .to_owned(); @@ -666,6 +694,7 @@ mod tests { BorderStyle::Unicode, true, 2, + 1, ); printer.display_offset(0xdeadbeef); @@ -697,6 +726,7 @@ mod tests { BorderStyle::Unicode, true, 4, + 1, ); printer.print_all(input).unwrap(); @@ -754,6 +784,7 @@ mod tests { BorderStyle::Unicode, true, 3, + 1, ); printer.print_all(input).unwrap(); diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index df076e5..dd7c437 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -51,7 +51,7 @@ mod basic { .success() .stdout( "┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐\n\ - │ │ No content to print │ │ │ │\n\ + │ │ No content │ │ │ │\n\ └────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘\n", ); } @@ -140,7 +140,7 @@ mod skip { .success() .stdout( "┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐\n\ - │ │ No content to print │ │ │ │\n\ + │ │ No content │ │ │ │\n\ └────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘\n", ); } From aeee0a10338cdc30005aa80a00dc0c59b94ccd94 Mon Sep 17 00:00:00 2001 From: RinHizakura Date: Mon, 21 Nov 2022 10:32:52 +0800 Subject: [PATCH 2/7] Add new integration tests for group bytes feature --- tests/integration_tests.rs | 76 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index dd7c437..a2befaf 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -271,3 +271,79 @@ mod display_settings { ); } } + +mod group { + use super::hexyl; + + #[test] + fn group_2_bytes() { + hexyl() + .arg("ascii") + .arg("--color=never") + .arg("-g=2") + .assert() + .success() + .stdout( + "┌────────┬─────────────────────┬─────────────────────┬────────┬────────┐\n\ + │00000000│ 3031 3233 3435 3637 ┊ 3839 6162 6364 650a │01234567┊89abcde_│\n\ + └────────┴─────────────────────┴─────────────────────┴────────┴────────┘\n", + ); + } + + #[test] + fn group_4_bytes() { + hexyl() + .arg("ascii") + .arg("--color=never") + .arg("-g=4") + .assert() + .success() + .stdout( + "┌────────┬───────────────────┬───────────────────┬────────┬────────┐\n\ + │00000000│ 30313233 34353637 ┊ 38396162 6364650a │01234567┊89abcde_│\n\ + └────────┴───────────────────┴───────────────────┴────────┴────────┘\n", + ); + } + + #[test] + fn group_8_bytes() { + hexyl() + .arg("ascii") + .arg("--color=never") + .arg("-g=8") + .assert() + .success() + .stdout( + "┌────────┬──────────────────┬──────────────────┬────────┬────────┐\n\ + │00000000│ 3031323334353637 ┊ 383961626364650a │01234567┊89abcde_│\n\ + └────────┴──────────────────┴──────────────────┴────────┴────────┘\n", + ); + } + + #[test] + fn group_bytes_plain() { + hexyl() + .arg("ascii") + .arg("--color=never") + .arg("--plain") + .arg("-g=2") + .assert() + .success() + .stdout(" 3031 3233 3435 3637 3839 6162 6364 650a \n"); + } + + #[test] + fn group_bytes_fill_space() { + hexyl() + .arg("--color=never") + .arg("-g=2") + .write_stdin("abc") + .assert() + .success() + .stdout( + "┌────────┬─────────────────────┬─────────────────────┬────────┬────────┐\n\ + │00000000│ 6162 63 ┊ │abc ┊ │\n\ + └────────┴─────────────────────┴─────────────────────┴────────┴────────┘\n", + ); + } +} From 55fed5e3c0b41c572f2ef36ff9678a5bf743d36b Mon Sep 17 00:00:00 2001 From: RinHizakura Date: Mon, 21 Nov 2022 10:46:26 +0800 Subject: [PATCH 3/7] Fix for clap4 --- src/bin/hexyl.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bin/hexyl.rs b/src/bin/hexyl.rs index 2c17dee..bd49994 100644 --- a/src/bin/hexyl.rs +++ b/src/bin/hexyl.rs @@ -169,7 +169,7 @@ fn run() -> Result<(), AnyhowError> { .arg( Arg::new("group_bytes") .short('g') - .takes_value(true) + .num_args(1) .value_name("N") .help( "Sets the number of octets per group to be displayed. \ @@ -349,7 +349,7 @@ fn run() -> Result<(), AnyhowError> { }; let group_bytes = if let Some(group_bytes) = matches - .value_of("group_bytes") + .get_one::("group_bytes") .map(|s| { s.parse::().map(u8::from).context(anyhow!( "failed to parse `-g` arg {:?} as unsigned nonzero integer", From c0f94ad6aa084c3c6be133a87c1c009d66ec9c56 Mon Sep 17 00:00:00 2001 From: RinHizakura Date: Mon, 3 Oct 2022 20:52:57 +0800 Subject: [PATCH 4/7] Refine the support of byte grouping --- src/bin/hexyl.rs | 10 ++++++---- tests/integration_tests.rs | 37 ++++++++++++++++++++++++------------- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/src/bin/hexyl.rs b/src/bin/hexyl.rs index bd49994..45df101 100644 --- a/src/bin/hexyl.rs +++ b/src/bin/hexyl.rs @@ -169,12 +169,12 @@ fn run() -> Result<(), AnyhowError> { .arg( Arg::new("group_bytes") .short('g') + .long("group-bytes") .num_args(1) .value_name("N") .help( "Sets the number of octets per group to be displayed. \ - The possible option will be 1, 2, 4, 8, otherwise it will be set \ - to 1 by default.", + The possible options are 1, 2, 4, 8. The default is 1", ), ) .arg( @@ -352,7 +352,7 @@ fn run() -> Result<(), AnyhowError> { .get_one::("group_bytes") .map(|s| { s.parse::().map(u8::from).context(anyhow!( - "failed to parse `-g` arg {:?} as unsigned nonzero integer", + "failed to parse `--group-bytes` arg {:?} as unsigned nonzero integer", s )) }) @@ -361,7 +361,9 @@ fn run() -> Result<(), AnyhowError> { if (group_bytes <= 8) && ((group_bytes & (group_bytes - 1)) == 0) { group_bytes } else { - 1 + return Err(anyhow!( + "the possible options of group_bytes could only be 1, 2, 4 or 8. " + )); } } else { 1 diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index a2befaf..dce506b 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -280,13 +280,13 @@ mod group { hexyl() .arg("ascii") .arg("--color=never") - .arg("-g=2") + .arg("--group-bytes=2") .assert() .success() .stdout( "┌────────┬─────────────────────┬─────────────────────┬────────┬────────┐\n\ - │00000000│ 3031 3233 3435 3637 ┊ 3839 6162 6364 650a │01234567┊89abcde_│\n\ - └────────┴─────────────────────┴─────────────────────┴────────┴────────┘\n", + │00000000│ 3031 3233 3435 3637 ┊ 3839 6162 6364 650a │01234567┊89abcde_│\n\ + └────────┴─────────────────────┴─────────────────────┴────────┴────────┘\n", ); } @@ -295,13 +295,13 @@ mod group { hexyl() .arg("ascii") .arg("--color=never") - .arg("-g=4") + .arg("--group-bytes=4") .assert() .success() .stdout( "┌────────┬───────────────────┬───────────────────┬────────┬────────┐\n\ - │00000000│ 30313233 34353637 ┊ 38396162 6364650a │01234567┊89abcde_│\n\ - └────────┴───────────────────┴───────────────────┴────────┴────────┘\n", + │00000000│ 30313233 34353637 ┊ 38396162 6364650a │01234567┊89abcde_│\n\ + └────────┴───────────────────┴───────────────────┴────────┴────────┘\n", ); } @@ -310,13 +310,13 @@ mod group { hexyl() .arg("ascii") .arg("--color=never") - .arg("-g=8") + .arg("--group-bytes=8") .assert() .success() .stdout( "┌────────┬──────────────────┬──────────────────┬────────┬────────┐\n\ - │00000000│ 3031323334353637 ┊ 383961626364650a │01234567┊89abcde_│\n\ - └────────┴──────────────────┴──────────────────┴────────┴────────┘\n", + │00000000│ 3031323334353637 ┊ 383961626364650a │01234567┊89abcde_│\n\ + └────────┴──────────────────┴──────────────────┴────────┴────────┘\n", ); } @@ -326,7 +326,7 @@ mod group { .arg("ascii") .arg("--color=never") .arg("--plain") - .arg("-g=2") + .arg("--group-bytes=2") .assert() .success() .stdout(" 3031 3233 3435 3637 3839 6162 6364 650a \n"); @@ -336,14 +336,25 @@ mod group { fn group_bytes_fill_space() { hexyl() .arg("--color=never") - .arg("-g=2") + .arg("--group-bytes=2") .write_stdin("abc") .assert() .success() .stdout( "┌────────┬─────────────────────┬─────────────────────┬────────┬────────┐\n\ - │00000000│ 6162 63 ┊ │abc ┊ │\n\ - └────────┴─────────────────────┴─────────────────────┴────────┴────────┘\n", + │00000000│ 6162 63 ┊ │abc ┊ │\n\ + └────────┴─────────────────────┴─────────────────────┴────────┴────────┘\n", ); } + + #[test] + fn group_bytes_invalid() { + hexyl() + .arg("ascii") + .arg("--color=never") + .arg("--plain") + .arg("--group-bytes=3") + .assert() + .failure(); + } } From 31c0bcfeae2ad371b50a0ce42b7f30fa71378cb1 Mon Sep 17 00:00:00 2001 From: David Peter Date: Sat, 26 Nov 2022 13:05:37 +0100 Subject: [PATCH 5/7] Improve error messages --- src/bin/hexyl.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bin/hexyl.rs b/src/bin/hexyl.rs index 45df101..92fadf8 100644 --- a/src/bin/hexyl.rs +++ b/src/bin/hexyl.rs @@ -352,7 +352,7 @@ fn run() -> Result<(), AnyhowError> { .get_one::("group_bytes") .map(|s| { s.parse::().map(u8::from).context(anyhow!( - "failed to parse `--group-bytes` arg {:?} as unsigned nonzero integer", + "failed to parse `--group-bytes`/`-g` arg {:?} as unsigned nonzero integer", s )) }) @@ -362,7 +362,7 @@ fn run() -> Result<(), AnyhowError> { group_bytes } else { return Err(anyhow!( - "the possible options of group_bytes could only be 1, 2, 4 or 8. " + "Possible options for the `--group-bytes`/`-g` option are 1, 2, 4 or 8. " )); } } else { From fe65792b9619e471c7b39789eb751457a0436350 Mon Sep 17 00:00:00 2001 From: David Peter Date: Sat, 26 Nov 2022 13:06:28 +0100 Subject: [PATCH 6/7] Add CHANGELOG entry --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15ce1fb..79c8852 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ - Added variable panels through the `--panels` and `--terminal-width` flags, see [#13](https://github.com/sharkdp/hexyl/issues/13) and [#164](https://github.com/sharkdp/hexyl/pull/164) (@sharifhsn) +- Added new `--group-bytes`/`-g` option, see #104 and #170 (@RinHizakura) + ## Bugfixes From b1ff8b6ce401457ebadd98f7fcc442340eeaa03f Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Sat, 26 Nov 2022 12:54:04 -0500 Subject: [PATCH 7/7] added squeeze tests --- Cargo.lock | 58 +++++++++-- Cargo.toml | 1 + tests/integration_tests.rs | 193 +++++++++++++++++++++++++++++++++++++ 3 files changed, 245 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 49eb795..2931b7c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -124,6 +124,22 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "ctor" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + [[package]] name = "difflib" version = "0.4.0" @@ -193,6 +209,7 @@ dependencies = [ "const_format", "libc", "predicates", + "pretty_assertions", "terminal_size", "thiserror", ] @@ -263,6 +280,15 @@ version = "6.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "029d8d0b2f198229de29dca79676f2738ff952edf3fde542eb8bf94d8c21b435" +[[package]] +name = "output_vt100" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66" +dependencies = [ + "winapi", +] + [[package]] name = "predicates" version = "2.1.1" @@ -294,19 +320,31 @@ dependencies = [ ] [[package]] -name = "proc-macro2" -version = "1.0.39" +name = "pretty_assertions" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" +checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755" +dependencies = [ + "ctor", + "diff", + "output_vt100", + "yansi", +] + +[[package]] +name = "proc-macro2" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.18" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] @@ -356,9 +394,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "1.0.95" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942" +checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" dependencies = [ "proc-macro2", "quote", @@ -504,3 +542,9 @@ name = "windows_x86_64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + +[[package]] +name = "yansi" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" diff --git a/Cargo.toml b/Cargo.toml index d5be575..0b1370d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ features = ["std", "suggestions", "color", "wrap_help", "cargo", "help", "usage" [dev-dependencies] assert_cmd = "2.0" predicates = "2.0" +pretty_assertions = "1.3.0" [profile.release] lto = true diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index dce506b..e7a5716 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -5,6 +5,26 @@ fn hexyl() -> Command { cmd.current_dir("tests/examples"); cmd } +trait PrettyAssert +where + S: AsRef, +{ + fn pretty_stdout(self, other: S); +} + +// https://github.com/assert-rs/assert_cmd/issues/121#issuecomment-849937376 +// +impl PrettyAssert for assert_cmd::assert::Assert +where + S: AsRef, +{ + fn pretty_stdout(self, other: S) { + println!("{}", other.as_ref().len()); + let self_str = String::from_utf8(self.get_output().stdout.clone()).unwrap(); + println!("{}", self_str.len()); + pretty_assertions::assert_eq!(self_str, other.as_ref()); + } +} mod basic { use super::hexyl; @@ -274,6 +294,7 @@ mod display_settings { mod group { use super::hexyl; + use super::PrettyAssert; #[test] fn group_2_bytes() { @@ -357,4 +378,176 @@ mod group { .assert() .failure(); } + #[test] + fn squeeze_no_chars() { + hexyl() + .arg("hello_world_elf64") + .arg("--color=never") + .arg("--skip=1024") + .arg("--length=4096") + .arg("--no-characters") + .assert() + .success() + .pretty_stdout( + "\ +┌────────┬─────────────────────────┬─────────────────────────┐ +│00000400│ 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 │ +│* │ ┊ │ +│00001400│ ┊ │ +└────────┴─────────────────────────┴─────────────────────────┘ +", + ); + } + #[test] + fn squeeze_no_chars_one_panel() { + hexyl() + .arg("hello_world_elf64") + .arg("--color=never") + .arg("--skip=1024") + .arg("--length=4096") + .arg("--no-characters") + .arg("--panels=1") + .assert() + .success() + .pretty_stdout( + "\ +┌────────┬─────────────────────────┐ +│00000400│ 00 00 00 00 00 00 00 00 │ +│* │ │ +│00001000│ ba 0e 00 00 00 b9 00 20 │ +│00001008│ 40 00 bb 01 00 00 00 b8 │ +│00001010│ 04 00 00 00 cd 80 b8 01 │ +│00001018│ 00 00 00 cd 80 00 00 00 │ +│00001020│ 00 00 00 00 00 00 00 00 │ +│* │ │ +│00001400│ │ +└────────┴─────────────────────────┘ +", + ); + } + #[test] + fn squeeze_no_position() { + hexyl() + .arg("hello_world_elf64") + .arg("--color=never") + .arg("--skip=1024") + .arg("--length=4096") + .arg("--no-position") + .assert() + .success() + .pretty_stdout( + "\ +┌─────────────────────────┬─────────────────────────┬────────┬────────┐ +│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │00000000┊00000000│ +│* ┊ │ ┊ │ +│ ba 0e 00 00 00 b9 00 20 ┊ 40 00 bb 01 00 00 00 b8 │ו000×0 ┊@0ו000×│ +│ 04 00 00 00 cd 80 b8 01 ┊ 00 00 00 cd 80 00 00 00 │•000××ו┊000××000│ +│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │00000000┊00000000│ +│* ┊ │ ┊ │ +│* ┊ │ ┊ │ +└─────────────────────────┴─────────────────────────┴────────┴────────┘ +", + ); + } + #[test] + fn squeeze_no_position_one_panel() { + hexyl() + .arg("hello_world_elf64") + .arg("--color=never") + .arg("--skip=1024") + .arg("--length=4096") + .arg("--no-position") + .arg("--panels=1") + .assert() + .success() + .pretty_stdout( + "\ +┌─────────────────────────┬────────┐ +│ 00 00 00 00 00 00 00 00 │00000000│ +│* │ │ +│ ba 0e 00 00 00 b9 00 20 │ו000×0 │ +│ 40 00 bb 01 00 00 00 b8 │@0ו000×│ +│ 04 00 00 00 cd 80 b8 01 │•000××ו│ +│ 00 00 00 cd 80 00 00 00 │000××000│ +│ 00 00 00 00 00 00 00 00 │00000000│ +│* │ │ +│* │ │ +└─────────────────────────┴────────┘ +", + ); + } + #[test] + fn squeeze_odd_panels_remainder_bytes() { + hexyl() + .arg("hello_world_elf64") + .arg("--color=never") + .arg("--skip=1024") + .arg("--length=4092") // 4 byte remainder + .arg("--panels=3") + .assert() + .success() + .pretty_stdout( + "\ +┌────────┬─────────────────────────┬─────────────────────────┬─────────────────────────┬────────┬────────┬────────┐ +│00000400│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │00000000┊00000000┊00000000│ +│* │ ┊ ┊ │ ┊ ┊ │ +│00001000│ ba 0e 00 00 00 b9 00 20 ┊ 40 00 bb 01 00 00 00 b8 ┊ 04 00 00 00 cd 80 b8 01 │ו000×0 ┊@0ו000×┊•000××ו│ +│00001018│ 00 00 00 cd 80 00 00 00 ┊ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │000××000┊00000000┊00000000│ +│00001030│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │00000000┊00000000┊00000000│ +│* │ ┊ ┊ │ ┊ ┊ │ +│000013f0│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 ┊ │00000000┊0000 ┊ │ +└────────┴─────────────────────────┴─────────────────────────┴─────────────────────────┴────────┴────────┴────────┘ +", + ); + } + + #[test] + fn squeeze_plain() { + hexyl() + .arg("hello_world_elf64") + .arg("--color=never") + .arg("--skip=1024") + .arg("--length=4096") + .arg("--plain") + .assert() + .success() + .pretty_stdout( + " \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * + ba 0e 00 00 00 b9 00 20 40 00 bb 01 00 00 00 b8 + 04 00 00 00 cd 80 b8 01 00 00 00 cd 80 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * + * +", + ); + } + + #[test] + fn squeeze_plain_remainder() { + hexyl() + .arg("hello_world_elf64") + .arg("--color=never") + .arg("--skip=1024") + .arg("--length=4092") // 4 byte remainder + .arg("--plain") + .assert() + .success() + .pretty_stdout( + " \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * + ba 0e 00 00 00 b9 00 20 40 00 bb 01 00 00 00 b8 + 04 00 00 00 cd 80 b8 01 00 00 00 cd 80 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * + 00 00 00 00 00 00 00 00 00 00 00 00 +", + ); + } }