1const BITS_IN_BYTE: u8 = 8;
2
3pub struct QwordTable<'a> {
4 data: &'a Vec<u8>,
5}
6
7impl<'a> QwordTable<'a> {
8 pub fn from_bytes(data: &Vec<u8>) -> QwordTable {
9 QwordTable { data }
10 }
11
12 pub fn format(self: &QwordTable<'a>) -> String {
18 let mut result = self.format_qword_table_header();
19 let num_qwords = self.data.len().div_euclid(BITS_IN_BYTE as usize);
20 for i in 0..num_qwords {
22 let from_byte_ix = i * BITS_IN_BYTE as usize;
23 let to_byte_ix = from_byte_ix + BITS_IN_BYTE as usize;
24 let qword_number: usize = i + 1;
25 result.push_str(&self.format_qword_row(
26 qword_number,
27 &self.data[from_byte_ix..to_byte_ix],
28 BITS_IN_BYTE as usize,
29 ));
30 }
31 let remaining_bytes = self.data.len().rem_euclid(BITS_IN_BYTE as usize);
33 let from_byte_ix: usize = num_qwords * BITS_IN_BYTE as usize;
34 let to_byte_ix: usize = from_byte_ix + remaining_bytes as usize;
35 let qword_number: usize = num_qwords + 1;
36 result.push_str(&self.format_qword_row(
37 qword_number,
38 &self.data[from_byte_ix..to_byte_ix],
39 remaining_bytes,
40 ));
41 result
42 }
43
44 fn format_qword_table_header(self: &QwordTable<'a>) -> String {
46 let mut result = String::from(" +");
48 result.push_str(&(0..BITS_IN_BYTE).map(|_| "--------+").collect::<String>());
49 result.push_str("\n Bytes |");
51 result.push_str(
53 &(0..BITS_IN_BYTE)
54 .map(|i| format!(" Byte {} |", i))
55 .collect::<String>(),
56 );
57 result.push_str("\n+------+");
59 result.push_str(&(0..BITS_IN_BYTE).map(|_| "--------+").collect::<String>());
60 result.push_str("\n");
61 result
62 }
63
64 fn format_qword_row(
72 self: &QwordTable<'a>,
73 qword_number: usize,
74 data: &[u8],
75 num_bytes: usize,
76 ) -> String {
77 if data.len() != num_bytes {
78 return format!(
79 "ERROR: Data must contain exactly {} bytes. QWORD: {}\n",
80 num_bytes, qword_number
81 );
82 }
83
84 let mut result = String::from("|QWORD |");
86 result.push_str(
88 &(0..num_bytes)
89 .map(|i| format!("{:0>8b}|", data[i]))
90 .collect::<String>(),
91 );
92 result.push_str(&format!("\n|{:^6}|", qword_number));
94 result.push_str(
96 &(0..num_bytes)
97 .map(|i| format!("{:>8}|", format!("({})", data[i])))
98 .collect::<String>(),
99 );
100 result.push_str("\n+------+");
102 result.push_str(&(0..num_bytes).map(|_| "--------+").collect::<String>());
103 result.push_str("\n");
104 result
105 }
106}
107
108#[cfg(test)]
109mod tests {
110 use super::*;
111
112 #[test]
113 fn test_one_byte() {
114 let data = vec![129];
115 let table: QwordTable = QwordTable::from_bytes(&data);
116
117 let expected = " +--------+--------+--------+--------+--------+--------+--------+--------+\n Bytes | Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 |\n+------+--------+--------+--------+--------+--------+--------+--------+--------+\n|QWORD |10000001|\n| 1 | (129)|\n+------+--------+\n";
118
119 assert_eq!(expected, table.format());
120 }
121}