1 // Copyright (c) 2017,2021 Linaro LTD
2 //
3 // SPDX-License-Identifier: Apache-2.0
4 
5 // Printable hexdump.
6 
7 pub trait HexDump {
8     // Output the data value in hex.
dump(&self)9     fn dump(&self);
10 }
11 
12 struct Dumper {
13     hex: String,
14     ascii: String,
15     count: usize,
16     total_count: usize,
17 }
18 
19 impl Dumper {
new() -> Dumper20     fn new() -> Dumper {
21         Dumper {
22             hex: String::with_capacity(49),
23             ascii: String::with_capacity(16),
24             count: 0,
25             total_count: 0,
26         }
27     }
28 
add_byte(&mut self, ch: u8)29     fn add_byte(&mut self, ch: u8) {
30         if self.count == 16 {
31             self.ship();
32         }
33         if self.count == 8 {
34             self.hex.push(' ');
35         }
36         self.hex.push_str(&format!(" {:02x}", ch)[..]);
37         self.ascii.push(if (b' '..=b'~').contains(&ch) {
38             ch as char
39         } else {
40             '.'
41         });
42         self.count += 1;
43     }
44 
ship(&mut self)45     fn ship(&mut self) {
46         if self.count == 0 {
47             return;
48         }
49 
50         println!("{:06x} {:-49} |{}|", self.total_count, self.hex, self.ascii);
51 
52         self.hex.clear();
53         self.ascii.clear();
54         self.total_count += 16;
55         self.count = 0;
56     }
57 }
58 
59 impl<'a> HexDump for &'a [u8] {
dump(&self)60     fn dump(&self) {
61         let mut dump = Dumper::new();
62         for ch in self.iter() {
63             dump.add_byte(*ch);
64         }
65         dump.ship();
66     }
67 }
68 
69 impl HexDump for Vec<u8> {
dump(&self)70     fn dump(&self) {
71         (&self[..]).dump()
72     }
73 }
74 
75 #[test]
samples()76 fn samples() {
77     "Hello".as_bytes().dump();
78     "This is a much longer string".as_bytes().dump();
79     "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f".as_bytes().dump();
80 }
81