1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
use alloc::{string::String, vec::Vec};
use core::fmt;
use core::result::Result;
pub fn simple_hex<T: AsRef<[u8]>>(source: &T) -> String {
let mut writer = String::new();
simple_hex_write(&mut writer, source).unwrap_or(());
writer
}
pub fn pretty_hex<T: AsRef<[u8]>>(source: &T) -> String {
let mut writer = String::new();
pretty_hex_write(&mut writer, source).unwrap_or(());
writer
}
const COLS: usize = 16;
const CHNK: usize = 4;
const NASCI: char = '.';
pub fn simple_hex_write<T, W>(writer: &mut W, source: &T) -> Result<(), fmt::Error>
where T: AsRef<[u8]>
, W: fmt::Write
{
for (i,x) in source.as_ref().iter().enumerate() {
write!(writer, "{:02x}{}", x,
match i+1 {
n if n == source.as_ref().len() => "",
n if n % CHNK == 0 => " ",
_ => " ",
}
)?;
}
Ok(())
}
pub fn pretty_hex_write<T, W>(writer: &mut W, source: &T) -> Result<(), fmt::Error>
where T: AsRef<[u8]>
, W: fmt::Write
{
writeln!(writer, "Length: {0} (0x{0:x}) bytes", source.as_ref().len())?;
let chunks = source.as_ref().chunks(COLS);
let lines = chunks.len();
for (i, row) in chunks.enumerate() {
write!(writer, "{:04x}: ", i * COLS)?;
simple_hex_write(writer, &row)?;
let pad = COLS - row.len();
let pad = pad * 3 + pad / CHNK;
for _ in 0..pad {
writer.write_char(' ')?;
}
write!(writer, " ")?;
for x in row {
writer.write_char(
if x.is_ascii() && !x.is_ascii_control() { (*x).into() }
else { NASCI }
)?;
}
if i+1 < lines {
writeln!(writer, "")?;
}
}
Ok(())
}
pub struct Hex<'a, T: 'a>(&'a T);
impl<'a, T:'a + AsRef<[u8]>> fmt::Display for Hex<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
simple_hex_write(f, self.0)
}
}
impl<'a, T:'a + AsRef<[u8]>> fmt::Debug for Hex<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
pretty_hex_write(f, self.0)
}
}
pub trait PrettyHex: Sized {
fn hex_dump<'a>(&'a self) -> Hex<'a, Self>;
}
impl PrettyHex for Vec<u8> {
fn hex_dump<'a>(&'a self) -> Hex<'a, Self> { Hex(self) }
}
impl<'a> PrettyHex for &'a [u8] {
fn hex_dump<'b>(&'b self) -> Hex<'b, Self> { Hex(self) }
}
impl<'a> PrettyHex for &'a mut [u8] {
fn hex_dump<'b>(&'b self) -> Hex<'b, Self> { Hex(self) }
}