1pub fn is_set(field: bool) -> char {
7 match field {
8 true => '+',
9 false => '-',
10 }
11}
12
13pub fn format_bytes(size: u64) -> String {
15 let mut s = size;
16 let mut divs: u8 = 0;
17 while s / 1024 >= 1 {
18 s /= 1024;
19 divs += 1;
20 }
21
22 format!(
23 "{}{}",
24 s,
25 match divs {
26 0 => "B",
27 1 => "K",
28 2 => "M",
29 3 => "G",
30 4 => "T",
31 _ => return size.to_string(),
32 }
33 )
34}
35
36const SLICE_SIZE: usize = 16;
37pub struct Hexdumper<'a> {
38 pub bytes: &'a [u8],
39 pub show_header: bool,
40 pub show_ascii: bool,
41 pub offset: Option<u64>,
42}
43
44impl std::fmt::Display for Hexdumper<'_> {
45 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46 let size = std::cmp::min(self.bytes.len(), SLICE_SIZE);
47 if self.show_header {
49 write!(f, " ")?;
50 for col in 0..size {
51 write!(f, " {:1x} ", col)?;
52 if col == 7 {
53 write!(f, " ")?;
54 }
55 }
56 writeln!(f)?;
57 }
58
59 let start_addr = self.offset.unwrap_or(0) as usize;
60 for (addr, slice) in self.bytes.chunks(SLICE_SIZE).enumerate() {
61 write!(f, " {:04x}: ", start_addr + (addr * SLICE_SIZE))?;
62 for (i, byte) in slice.iter().enumerate() {
63 write!(f, "{:02x} ", byte)?;
64 if i == 7 {
65 write!(f, " ")?;
66 }
67 }
68 if self.show_ascii {
69 write!(f, " ")?;
70 for byte in slice {
71 if byte.is_ascii_graphic() {
72 write!(f, "{}", *byte as char)?;
73 } else {
74 write!(f, ".")?;
75 }
76 }
77 }
78 writeln!(f)?;
79 }
80 Ok(())
81 }
82}