1fn is_printable(c: u8) -> bool {
2 (c > 0x21 && c < 0x7e) || (c > 0xa0)
3}
4fn map_2_printable(c: u8) -> char {
5 if is_printable(c) {
6 char::from(c)
7 } else {
8 '.'
9 }
10}
11pub fn to_hex_line(bytes: &[u8]) -> String {
12 to_hex_pretty(bytes).replace('\n', " ").replace(" ", "")
14}
15pub fn to_hex_pretty(bytes: &[u8]) -> String {
16 struct HexAscii {
17 hex: String,
18 asc: String,
19 }
20 let hex: Vec<HexAscii> = bytes
21 .iter()
22 .map(|v| HexAscii {
23 hex: format!("{:02x}", v),
24 asc: format!("{}", map_2_printable(*v)),
25 })
26 .collect();
27 let mut result = String::new();
28
29 for (idx, chunk16) in hex.chunks(16).enumerate() {
30 let mut hex_view = String::new();
31 let mut asc_view = String::new();
32 for chunk4 in chunk16.chunks(4) {
33 for ha in chunk4 {
34 hex_view.push_str(&format!("{} ", ha.hex));
35 asc_view.push_str(&format!("{} ", ha.asc));
36 }
37 hex_view.push(' ');
38 asc_view.push(' ');
39 }
40 let asc_view = asc_view.trim_end();
41 result.push_str(&format!("{idx:<04}: {hex_view:<52}| {asc_view}\n"));
42 }
43 result
44}
45
46#[cfg(test)]
47mod tests {
48
49 use super::*;
50 use crate::unittest;
51 use text_diff::{diff, print_diff};
52
53 #[test]
54 fn hex() {
55 unittest::setup::log::configure();
56 let mut v: Vec<u8> = Vec::new();
57 for i in 0..=255 {
58 v.push(i);
59 }
60 for i in 0..10 {
61 v.push(i);
62 }
63
64 let expected = r#"0000: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | . . . . . . . . . . . . . . . .
650001: 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f | . . . . . . . . . . . . . . . .
660002: 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f | . . " # $ % & ' ( ) * + , - . /
670003: 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f | 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
680004: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f | @ A B C D E F G H I J K L M N O
690005: 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f | P Q R S T U V W X Y Z [ \ ] ^ _
700006: 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f | ` a b c d e f g h i j k l m n o
710007: 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f | p q r s t u v w x y z { | } . .
720008: 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f | . . . . . . . . . . . . . . . .
730009: 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f | . . . . . . . . . . . . . . . .
740010: a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af | . ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ® ¯
750011: b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf | ° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿
760012: c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf | À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï
770013: d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df | Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß
780014: e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef | à á â ã ä å æ ç è é ê ë ì í î ï
790015: f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff | ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý þ ÿ
800016: 00 01 02 03 04 05 06 07 08 09 | . . . . . . . . . ."#;
81 let actual = to_hex_pretty(&v);
82 let diff_res = diff(expected, actual.as_str(), "\n");
83 print_diff(expected, actual.as_str(), "\n");
84 assert_eq!(diff_res.0, 1);
85 }
86
87 #[test]
88 fn hex_line() {
89 unittest::setup::log::configure();
90 let mut v: Vec<u8> = Vec::new();
91 for i in 0..=18 {
92 v.push(i);
93 }
94 let expected = "0000: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | . . . . . . . . . . . . . . . . 0001: 10 11 12 | . . . ";
95 let actual = to_hex_line(&v);
96 let diff_res = diff(expected, actual.as_str(), "\n");
97 print_diff(expected, actual.as_str(), "\n");
98 assert_eq!(diff_res.0, 0);
99 }
100}