trick_data/services/convert/
to_hex.rs1use std::str::Bytes;
4
5pub trait ToHex {
6 fn to_hex(&self) -> String;
7}
8
9impl ToHex for str {
10 fn to_hex(&self) -> String {
13 if self.is_empty() {
14 return String::new();
15 }
16
17 let mut result = allocate_string(self.bytes().len());
18 result.fill_from(&mut self.bytes());
19
20 result
21 }
22}
23
24fn allocate_string(input_data_length: usize) -> String {
25 let mut result = String::new();
26
27 let hexes_size = input_data_length * 2;
29 let spaces_size = input_data_length - 1;
31
32 result.reserve(hexes_size + spaces_size);
33
34 result
35}
36
37trait Fill {
38 fn fill_from(&mut self, byte_iter: &mut Bytes<'_>);
39}
40
41impl Fill for String {
42 fn fill_from(&mut self, byte_iter: &mut Bytes<'_>) {
43 for _ in 0..(byte_iter.len() - 1) {
44 self.push_str(&format!("{:0>2x} ", byte_iter.next().unwrap()));
45 }
46 self.push_str(&format!("{:0>2x}", byte_iter.next().unwrap()));
47 }
48}
49
50#[cfg(test)]
51mod test {
52 use super::*;
53
54 macro_rules! positive_tests {
56 ($($name:ident: $value:expr,)*) => {
57 $(
58 #[test]
59 fn $name() {
60 let (input_data, expected) = $value;
62
63 let actual = input_data.to_hex();
65
66 assert_eq!(actual, expected)
68 }
69 )*
70 }
71 }
72
73 positive_tests! {
74 empty_string: (&String::new(), ""),
75 digits: ("0123456789", "30 31 32 33 34 35 36 37 38 39"),
76 lowercase_ascii: (
77 "abcdefghijklmnopqrstuvwxyz",
78 "61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a"),
79 uppercase_ascii: (
80 "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
81 "41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a"),
82 utf8_1byte_first_code_point: ("\u{0000}", "00"),
83 utf8_1byte_last_code_point: ("\u{007F}", "7f"),
84 utf8_2bytes_first_code_point: ("\u{0080}", "c2 80"),
85 utf8_2bytes_last_code_point: ("\u{07FF}", "df bf"),
86 utf8_3bytes_first_code_point: ("\u{0800}", "e0 a0 80"),
87 utf8_3bytes_last_code_point: ("\u{FFFF}", "ef bf bf"),
88 utf8_4bytes_first_code_point: ("\u{10000}", "f0 90 80 80"),
89 utf8_4bytes_last_code_point: ("\u{10FFFF}", "f4 8f bf bf"),
90 }
91
92 #[test]
93 fn returned_string_size() {
94 let response = "a".to_hex();
96 assert!(response.len() <= response.capacity());
98 }
99}