| // 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(); |
| } |