blob: b2f403fd7771e5f71044e02c69bc2ab77b9bb311 [file] [log] [blame]
// Copyright (c) 2017,2021 Linaro LTD
//
// SPDX-License-Identifier: Apache-2.0
// Printable hexdump.
pub trait HexDump {
// Output the data value in hex.
fn dump(&self);
}
struct Dumper {
hex: String,
ascii: String,
count: usize,
total_count: usize,
}
impl Dumper {
fn new() -> Dumper {
Dumper {
hex: String::with_capacity(49),
ascii: String::with_capacity(16),
count: 0,
total_count: 0,
}
}
fn add_byte(&mut self, ch: u8) {
if self.count == 16 {
self.ship();
}
if self.count == 8 {
self.hex.push(' ');
}
self.hex.push_str(&format!(" {:02x}", ch)[..]);
self.ascii.push(if (b' '..=b'~').contains(&ch) {
ch as char
} else {
'.'
});
self.count += 1;
}
fn ship(&mut self) {
if self.count == 0 {
return;
}
println!("{:06x} {:-49} |{}|", self.total_count, self.hex, self.ascii);
self.hex.clear();
self.ascii.clear();
self.total_count += 16;
self.count = 0;
}
}
impl<'a> HexDump for &'a [u8] {
fn dump(&self) {
let mut dump = Dumper::new();
for ch in self.iter() {
dump.add_byte(*ch);
}
dump.ship();
}
}
impl HexDump for Vec<u8> {
fn dump(&self) {
(&self[..]).dump()
}
}
#[test]
fn samples() {
"Hello".as_bytes().dump();
"This is a much longer string".as_bytes().dump();
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f".as_bytes().dump();
}