1pub fn format_offset(offset: u64) -> String {
3 format!("{} (0x{:x})", offset, offset)
4}
5
6pub fn format_hex32(value: u32) -> String {
8 format!("0x{:08x}", value)
9}
10
11pub fn format_hex64(value: u64) -> String {
13 format!("0x{:016x}", value)
14}
15
16pub fn format_bytes(data: &[u8]) -> String {
18 data.iter().map(|b| format!("{:02x}", b)).collect()
19}
20
21pub fn hex_dump(data: &[u8], base_offset: u64) -> String {
28 let mut lines = Vec::new();
29
30 for (i, chunk) in data.chunks(16).enumerate() {
31 let offset = base_offset + (i * 16) as u64;
32
33 let mut line = format!("{:08x} ", offset);
35
36 for (j, byte) in chunk.iter().enumerate() {
38 if j == 8 {
39 line.push(' ');
40 }
41 line.push_str(&format!("{:02x} ", byte));
42 }
43
44 if chunk.len() < 16 {
46 let missing = 16 - chunk.len();
47 for j in 0..missing {
48 if chunk.len() + j == 8 {
49 line.push(' ');
50 }
51 line.push_str(" ");
52 }
53 }
54
55 line.push(' ');
57 line.push('|');
58 for byte in chunk {
59 if byte.is_ascii_graphic() || *byte == b' ' {
60 line.push(*byte as char);
61 } else {
62 line.push('.');
63 }
64 }
65 for _ in chunk.len()..16 {
67 line.push(' ');
68 }
69 line.push('|');
70
71 lines.push(line);
72 }
73
74 lines.join("\n")
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80
81 #[test]
82 fn test_format_bytes() {
83 assert_eq!(format_bytes(&[0x4a, 0x2f, 0x00, 0xff]), "4a2f00ff");
84 assert_eq!(format_bytes(&[]), "");
85 assert_eq!(format_bytes(&[0x00]), "00");
86 }
87
88 #[test]
89 fn test_hex_dump_full_line() {
90 let data: Vec<u8> = (0..16).collect();
91 let output = hex_dump(&data, 0);
92 assert!(output.starts_with("00000000 "));
93 assert!(output.contains("00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f"));
94 assert!(output.contains('|'));
95 }
96
97 #[test]
98 fn test_hex_dump_partial_line() {
99 let data = vec![0x48, 0x65, 0x6c, 0x6c, 0x6f]; let output = hex_dump(&data, 0x100);
101 assert!(output.starts_with("00000100 "));
102 assert!(output.contains("48 65 6c 6c 6f"));
103 assert!(output.contains("|Hello"));
104 }
105
106 #[test]
107 fn test_hex_dump_nonprintable() {
108 let data = vec![0x00, 0x01, 0x7f, 0x80, 0xff];
109 let output = hex_dump(&data, 0);
110 assert!(output.contains("|....."));
111 }
112}