binocular/preview/binary/
hex_dump.rs1use crate::preview::doc::PreviewDoc;
4use ratatui::style::{Color, Style};
5use ratatui::text::{Line, Span};
6
7pub fn append_hex_dump(header: &[u8], doc: &mut PreviewDoc) {
8 doc.push_section(super::SECTION_HEX_DUMP);
9 for line in create_hex_dump(header, super::HEX_DUMP_BYTES) {
10 doc.push_line(line);
11 }
12 doc.push_blank_line();
13}
14
15pub fn create_hex_dump(data: &[u8], max_bytes: usize) -> Vec<Line<'static>> {
16 let mut lines = Vec::new();
17 let bytes_to_show = data.len().min(max_bytes);
18
19 for (i, chunk) in data[..bytes_to_show].chunks(16).enumerate() {
20 let offset = format!(" {:08x} ", i * 16);
21
22 let hex: String = chunk
23 .iter()
24 .enumerate()
25 .map(|(j, b)| {
26 if j == 8 {
27 format!(" {:02x}", b)
28 } else {
29 format!("{:02x} ", b)
30 }
31 })
32 .collect();
33
34 let padding = " ".repeat(16 - chunk.len()) + if chunk.len() <= 8 { " " } else { "" };
35
36 let ascii: String = chunk
37 .iter()
38 .map(|&b| {
39 if b.is_ascii_graphic() || b == b' ' {
40 b as char
41 } else {
42 '.'
43 }
44 })
45 .collect();
46
47 lines.push(Line::from(vec![
48 Span::styled(offset, Style::default().fg(Color::DarkGray)),
49 Span::styled(hex, Style::default().fg(Color::Cyan)),
50 Span::styled(padding, Style::default()),
51 Span::styled(" │", Style::default().fg(Color::DarkGray)),
52 Span::styled(ascii, Style::default().fg(Color::Green)),
53 Span::styled("│", Style::default().fg(Color::DarkGray)),
54 ]));
55 }
56
57 lines
58}