sem_reg/data_conversion/
hex_bytes.rs1use std::fmt::{self};
2
3pub struct HexBytes<'a> {
4 bytes: &'a [u8],
5 old_bytes: Option<&'a [u8]>,
6}
7
8impl<'a> HexBytes<'a> {
9 pub fn new(bytes: &'a [u8]) -> Self {
10 Self {
11 bytes,
12 old_bytes: None,
13 }
14 }
15
16 pub fn diff_against(mut self, old_bytes: &'a [u8]) -> Self {
17 self.old_bytes = Some(old_bytes);
20 self
21 }
22}
23
24impl fmt::Display for HexBytes<'_> {
25 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26 let write_byte = |f: &mut fmt::Formatter<'_>, first: bool, byte| -> fmt::Result {
27 if !first {
28 write!(f, " ")?;
29 }
30 write!(f, "{byte:02x}")?;
31 Ok(())
32 };
33
34 let mut first = true;
35 if let Some(other_bytes) = self.old_bytes {
36 let mut current_color = Color::Default;
37 write!(f, "{current_color}")?;
38
39 for fragment in diff::slice(other_bytes, self.bytes) {
40 let (byte, byte_color) = match fragment {
41 diff::Result::Left(byte) => (byte, Color::BrightRed),
42 diff::Result::Right(byte) => (byte, Color::BrightGreen),
43 diff::Result::Both(byte, _) => (byte, Color::Default),
44 };
45
46 if byte_color != current_color {
47 write!(f, "{byte_color}")?;
48 current_color = byte_color;
49 }
50
51 write_byte(f, first, byte)?;
52
53 first = false;
54 }
55
56 if current_color != Color::Default {
57 write!(f, "{}", Color::Default)?;
58 }
59 } else {
60 for byte in self.bytes {
61 write_byte(f, first, byte)?;
62 first = false;
63 }
64 }
65
66 Ok(())
67 }
68}
69
70#[derive(Clone, Copy, PartialEq)]
71enum Color {
72 Default,
73 BrightRed,
74 BrightGreen,
75}
76
77impl fmt::Display for Color {
78 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 write!(
80 f,
81 "{}",
82 match self {
83 Color::Default => "\x1b[0m",
85 Color::BrightRed => "\x1b[91m",
86 Color::BrightGreen => "\x1b[92m",
87 }
88 )?;
89
90 Ok(())
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use crate::data_conversion::hex_bytes::HexBytes;
97
98 #[test]
99 fn diff_output() {
100 assert_eq!(
101 HexBytes::new(&[0x10, 0xf1, 0xf2, 0x13])
102 .diff_against(&[0x10, 0x11, 0x12, 0x13])
103 .to_string(),
104 String::new()
105 + "\x1b[0m"
106 + "10"
107 + "\x1b[91m"
108 + " 11 12"
109 + "\x1b[92m"
110 + " f1 f2"
111 + "\x1b[0m"
112 + " 13"
113 );
114 }
115}