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) }
}