From 564cf64b1b9c7616d4d5857093d64aca9db4e53c Mon Sep 17 00:00:00 2001 From: RinHizakura Date: Tue, 18 Apr 2023 19:01:18 +0800 Subject: [PATCH] Support both little and big endian dump --- src/bin/hexyl.rs | 11 ++++++++ src/lib.rs | 37 ++++++++++++++++++++++++- tests/integration_tests.rs | 56 +++++++++++++++++++++++++++++++++++--- 3 files changed, 99 insertions(+), 5 deletions(-) diff --git a/src/bin/hexyl.rs b/src/bin/hexyl.rs index 872df04..32986a4 100644 --- a/src/bin/hexyl.rs +++ b/src/bin/hexyl.rs @@ -203,6 +203,15 @@ fn run() -> Result<()> { width but still leave some space to the right.\nCannot be used with other \ width-setting options.", ), + ) + .arg( + Arg::new("little_endian_dump") + .short('e') + .action(ArgAction::SetTrue) + .help( + "Print out the data in little endian format. Otherwise the data will be showed \ + in big endian format by default.", + ), ); let matches = command.get_matches(); @@ -425,6 +434,7 @@ fn run() -> Result<()> { ) }; + let little_endian_dump = *matches.get_one::("little_endian_dump").unwrap_or(&false); let stdout = io::stdout(); let mut stdout_lock = BufWriter::new(stdout.lock()); @@ -437,6 +447,7 @@ fn run() -> Result<()> { .num_panels(panels) .group_size(group_size) .with_base(base) + .little_endian_dump(little_endian_dump) .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 62d01ce..dcb10bf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -159,6 +159,7 @@ pub struct PrinterBuilder<'a, Writer: Write> { panels: u64, group_size: u8, base: Base, + little_endian_dump: bool, } impl<'a, Writer: Write> PrinterBuilder<'a, Writer> { @@ -173,6 +174,7 @@ impl<'a, Writer: Write> PrinterBuilder<'a, Writer> { panels: 2, group_size: 1, base: Base::Hexadecimal, + little_endian_dump: false, } } @@ -216,6 +218,11 @@ impl<'a, Writer: Write> PrinterBuilder<'a, Writer> { self } + pub fn little_endian_dump(mut self, little_endian_dump: bool) -> Self { + self.little_endian_dump = little_endian_dump; + self + } + pub fn build(self) -> Printer<'a, Writer> { Printer::new( self.writer, @@ -227,6 +234,7 @@ impl<'a, Writer: Write> PrinterBuilder<'a, Writer> { self.panels, self.group_size, self.base, + self.little_endian_dump, ) } } @@ -254,6 +262,8 @@ pub struct Printer<'a, Writer: Write> { group_size: u8, /// The number of digits used to write the base. base_digits: u8, + /// Whether to print the bytes in little endian + little_endian_dump: bool, } impl<'a, Writer: Write> Printer<'a, Writer> { @@ -267,6 +277,7 @@ impl<'a, Writer: Write> Printer<'a, Writer> { panels: u64, group_size: u8, base: Base, + little_endian_dump: bool, ) -> Printer<'a, Writer> { Printer { idx: 0, @@ -304,6 +315,7 @@ impl<'a, Writer: Write> Printer<'a, Writer> { Base::Decimal => 3, Base::Hexadecimal => 2, }, + little_endian_dump, } } @@ -523,8 +535,27 @@ impl<'a, Writer: Write> Printer<'a, Writer> { Ok(()) } + fn reorder_buf_to_le(&self, buf: &mut Vec) { + let n = buf.len(); + let group_sz = self.group_size as usize; + + for idx in (0..n).step_by(group_sz) { + let remaining = n - idx; + let total = remaining.min(group_sz); + + buf[idx..idx+total].reverse(); + } + } + pub fn print_bytes(&mut self) -> io::Result<()> { - for (i, &b) in self.line_buf.clone().iter().enumerate() { + let mut buf = self.line_buf.clone(); + + if self.little_endian_dump { + // reorder the buffer to the little endian format + self.reorder_buf_to_le(&mut buf); + }; + + for (i, &b) in buf.iter().enumerate() { self.print_byte(i, b)?; } Ok(()) @@ -682,6 +713,7 @@ mod tests { 2, 1, Base::Hexadecimal, + false, ); printer.print_all(input).unwrap(); @@ -736,6 +768,7 @@ mod tests { 2, 1, Base::Hexadecimal, + false, ); printer.display_offset(0xdeadbeef); @@ -769,6 +802,7 @@ mod tests { 4, 1, Base::Hexadecimal, + false, ); printer.print_all(input).unwrap(); @@ -828,6 +862,7 @@ mod tests { 3, 1, Base::Hexadecimal, + false, ); printer.print_all(input).unwrap(); diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index fda9daf..b8a95c9 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -292,12 +292,12 @@ mod display_settings { } } -mod group { +mod group_and_endian { use super::hexyl; use super::PrettyAssert; #[test] - fn group_2_bytes() { + fn group_2_bytes_be() { hexyl() .arg("ascii") .arg("--color=never") @@ -312,7 +312,23 @@ mod group { } #[test] - fn group_4_bytes() { + fn group_2_bytes_le() { + hexyl() + .arg("ascii") + .arg("--color=never") + .arg("--group-size=2") + .arg("-e") + .assert() + .success() + .stdout( + "┌────────┬─────────────────────┬─────────────────────┬────────┬────────┐\n\ + │00000000│ 3130 3332 3534 3736 ┊ 3938 6261 6463 0a65 │01234567┊89abcde_│\n\ + └────────┴─────────────────────┴─────────────────────┴────────┴────────┘\n", + ); + } + + #[test] + fn group_4_bytes_be() { hexyl() .arg("ascii") .arg("--color=never") @@ -327,7 +343,23 @@ mod group { } #[test] - fn group_8_bytes() { + fn group_4_bytes_le() { + hexyl() + .arg("ascii") + .arg("--color=never") + .arg("--group-size=4") + .arg("-e") + .assert() + .success() + .stdout( + "┌────────┬───────────────────┬───────────────────┬────────┬────────┐\n\ + │00000000│ 33323130 37363534 ┊ 62613938 0a656463 │01234567┊89abcde_│\n\ + └────────┴───────────────────┴───────────────────┴────────┴────────┘\n", + ); + } + + #[test] + fn group_8_bytes_be() { hexyl() .arg("ascii") .arg("--color=never") @@ -341,6 +373,22 @@ mod group { ); } + #[test] + fn group_8_bytes_le() { + hexyl() + .arg("ascii") + .arg("--color=never") + .arg("--group-size=8") + .arg("-e") + .assert() + .success() + .stdout( + "┌────────┬──────────────────┬──────────────────┬────────┬────────┐\n\ + │00000000│ 3736353433323130 ┊ 0a65646362613938 │01234567┊89abcde_│\n\ + └────────┴──────────────────┴──────────────────┴────────┴────────┘\n", + ); + } + #[test] fn group_size_plain() { hexyl()