Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Squeeze identical lines #213

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 75 additions & 17 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,8 @@ pub struct Printer<'a, Writer: Write> {
display_offset: u64,
/// The number of panels to draw.
panels: u64,
squeeze_byte: usize,
squeeze_byte: Option<usize>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing this (as well as some other code below) from usize to u64 fixes the tests on 32-bit platforms.

squeeze_line: Vec<u8>,
/// The number of octets per group.
group_size: u8,
/// The number of digits used to write the base.
Expand Down Expand Up @@ -332,7 +333,8 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
},
display_offset: 0,
panels,
squeeze_byte: 0x00,
squeeze_byte: None,
squeeze_line: vec![0; 8 * panels as usize],
group_size,
base_digits: match base {
Base::Binary => 8,
Expand Down Expand Up @@ -635,11 +637,21 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
// squeeze is active, check if the line is the same
// skip print if still squeezed, otherwise print and deactivate squeeze
if matches!(self.squeezer, Squeezer::Print | Squeezer::Delete) {
if self
.line_buf
.chunks_exact(std::mem::size_of::<usize>())
.all(|w| usize::from_ne_bytes(w.try_into().unwrap()) == self.squeeze_byte)
{
if let Some(byte) = self.squeeze_byte {
if self
.line_buf
.chunks_exact(std::mem::size_of::<usize>())
.all(|w| usize::from_ne_bytes(w.try_into().unwrap()) == byte)
{
if self.squeezer == Squeezer::Delete {
self.idx += 8 * self.panels;
continue;
}
} else {
self.squeeze_byte = None;
self.squeezer = Squeezer::Ignore;
}
} else if self.line_buf == self.squeeze_line {
if self.squeezer == Squeezer::Delete {
self.idx += 8 * self.panels;
continue;
Expand Down Expand Up @@ -670,18 +682,27 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
self.squeezer = Squeezer::Delete;
}

// repeat the first byte in the line until it's a usize
// compare that usize with each usize chunk in the line
// if they are all the same, change squeezer to print
let repeat_byte = (self.line_buf[0] as usize) * (usize::MAX / 255);
if !matches!(self.squeezer, Squeezer::Disabled | Squeezer::Delete)
&& self
let repeat_byte = usize::from_ne_bytes(
self.line_buf[0..std::mem::size_of::<usize>()]
.try_into()
.unwrap(),
);
if !matches!(self.squeezer, Squeezer::Disabled | Squeezer::Delete) {
if self
.line_buf
.chunks_exact(std::mem::size_of::<usize>())
.all(|w| usize::from_ne_bytes(w.try_into().unwrap()) == repeat_byte)
{
self.squeezer = Squeezer::Print;
self.squeeze_byte = repeat_byte;
{
// fast calculation for when repeat fits in usize
self.squeezer = Squeezer::Print;
self.squeeze_byte = Some(repeat_byte);
} else if self.line_buf == self.squeeze_line {
// slow check if entire line is identical
self.squeezer = Squeezer::Print;
self.squeeze_byte = None;
} else {
self.squeeze_line = self.line_buf.clone();
}
};
};

Expand All @@ -707,8 +728,8 @@ impl<'a, Writer: Write> Printer<'a, Writer> {
writeln!(self.writer)?;
} else if let Some(n) = leftover {
// last line is incomplete
self.print_position_panel()?;
self.squeezer = Squeezer::Ignore;
self.print_position_panel()?;
self.print_bytes()?;
self.squeezer = Squeezer::Print;
for i in n..8 * self.panels as usize {
Expand Down Expand Up @@ -913,4 +934,41 @@ mod tests {
let actual_string: &str = str::from_utf8(&output).unwrap();
assert_eq!(actual_string, expected_string)
}

#[test]
fn identical_lines() {
let input = io::Cursor::new(
"abcdefg\ngfedcba\nhijklmn\nhijklmn\nhijklmn\nhijklmn\nopqrstu\nvwxyzab\n",
);
let expected_string = "\
┌────────┬─────────────────────────┬────────┐
│00000000│ 61 62 63 64 65 66 67 0a │abcdefg_│
│00000008│ 67 66 65 64 63 62 61 0a │gfedcba_│
│00000010│ 68 69 6a 6b 6c 6d 6e 0a │hijklmn_│
│* │ │ │
│00000030│ 6f 70 71 72 73 74 75 0a │opqrstu_│
│00000038│ 76 77 78 79 7a 61 62 0a │vwxyzab_│
└────────┴─────────────────────────┴────────┘
"
.to_owned();
let mut output = vec![];
let mut printer: Printer<Vec<u8>> = Printer::new(
&mut output,
false,
true,
true,
BorderStyle::Unicode,
true,
1,
1,
Base::Hexadecimal,
Endianness::Big,
CharacterTable::Default,
);

printer.print_all(input).unwrap();

let actual_string: &str = str::from_utf8(&output).unwrap();
assert_eq!(actual_string, expected_string)
}
}
Loading