]>
Commit | Line | Data |
---|---|---|
ba9703b0 XL |
1 | //! Generic array are commonly used as a return value for hash digests, so\r |
2 | //! it's a good idea to allow to hexlify them easily. This module implements\r | |
3 | //! `std::fmt::LowerHex` and `std::fmt::UpperHex` traits.\r | |
4 | //!\r | |
5 | //! Example:\r | |
6 | //!\r | |
7 | //! ```rust\r | |
8 | //! # #[macro_use]\r | |
9 | //! # extern crate generic_array;\r | |
10 | //! # extern crate typenum;\r | |
11 | //! # fn main() {\r | |
12 | //! let array = arr![u8; 10, 20, 30];\r | |
13 | //! assert_eq!(format!("{:x}", array), "0a141e");\r | |
14 | //! # }\r | |
15 | //! ```\r | |
16 | //!\r | |
17 | \r | |
18 | use {ArrayLength, GenericArray};\r | |
19 | use core::cmp::min;\r | |
20 | use core::fmt;\r | |
21 | use core::ops::Add;\r | |
22 | use core::str;\r | |
23 | use typenum::*;\r | |
24 | \r | |
25 | static LOWER_CHARS: &'static [u8] = b"0123456789abcdef";\r | |
26 | static UPPER_CHARS: &'static [u8] = b"0123456789ABCDEF";\r | |
27 | \r | |
28 | impl<T: ArrayLength<u8>> fmt::LowerHex for GenericArray<u8, T>\r | |
29 | where\r | |
30 | T: Add<T>,\r | |
31 | <T as Add<T>>::Output: ArrayLength<u8>,\r | |
32 | {\r | |
33 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\r | |
34 | let max_digits = f.precision().unwrap_or_else(|| self.len() * 2);\r | |
35 | let max_hex = (max_digits >> 1) + (max_digits & 1);\r | |
36 | \r | |
37 | if T::to_usize() < 1024 {\r | |
38 | // For small arrays use a stack allocated\r | |
39 | // buffer of 2x number of bytes\r | |
40 | let mut res = GenericArray::<u8, Sum<T, T>>::default();\r | |
41 | \r | |
42 | for (i, c) in self.iter().take(max_hex).enumerate() {\r | |
43 | res[i * 2] = LOWER_CHARS[(c >> 4) as usize];\r | |
44 | res[i * 2 + 1] = LOWER_CHARS[(c & 0xF) as usize];\r | |
45 | }\r | |
46 | f.write_str(unsafe { str::from_utf8_unchecked(&res[..max_digits]) })?;\r | |
47 | } else {\r | |
48 | // For large array use chunks of up to 1024 bytes (2048 hex chars)\r | |
49 | let mut buf = [0u8; 2048];\r | |
50 | let mut digits_left = max_digits;\r | |
51 | \r | |
52 | for chunk in self[..max_hex].chunks(1024) {\r | |
53 | for (i, c) in chunk.iter().enumerate() {\r | |
54 | buf[i * 2] = LOWER_CHARS[(c >> 4) as usize];\r | |
55 | buf[i * 2 + 1] = LOWER_CHARS[(c & 0xF) as usize];\r | |
56 | }\r | |
57 | let n = min(chunk.len() * 2, digits_left);\r | |
58 | f.write_str(unsafe { str::from_utf8_unchecked(&buf[..n]) })?;\r | |
59 | digits_left -= n;\r | |
60 | }\r | |
61 | }\r | |
62 | Ok(())\r | |
63 | }\r | |
64 | }\r | |
65 | \r | |
66 | impl<T: ArrayLength<u8>> fmt::UpperHex for GenericArray<u8, T>\r | |
67 | where\r | |
68 | T: Add<T>,\r | |
69 | <T as Add<T>>::Output: ArrayLength<u8>,\r | |
70 | {\r | |
71 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\r | |
72 | let max_digits = f.precision().unwrap_or_else(|| self.len() * 2);\r | |
73 | let max_hex = (max_digits >> 1) + (max_digits & 1);\r | |
74 | \r | |
75 | if T::to_usize() < 1024 {\r | |
76 | // For small arrays use a stack allocated\r | |
77 | // buffer of 2x number of bytes\r | |
78 | let mut res = GenericArray::<u8, Sum<T, T>>::default();\r | |
79 | \r | |
80 | for (i, c) in self.iter().take(max_hex).enumerate() {\r | |
81 | res[i * 2] = UPPER_CHARS[(c >> 4) as usize];\r | |
82 | res[i * 2 + 1] = UPPER_CHARS[(c & 0xF) as usize];\r | |
83 | }\r | |
84 | f.write_str(unsafe { str::from_utf8_unchecked(&res[..max_digits]) })?;\r | |
85 | } else {\r | |
86 | // For large array use chunks of up to 1024 bytes (2048 hex chars)\r | |
87 | let mut buf = [0u8; 2048];\r | |
88 | let mut digits_left = max_digits;\r | |
89 | \r | |
90 | for chunk in self[..max_hex].chunks(1024) {\r | |
91 | for (i, c) in chunk.iter().enumerate() {\r | |
92 | buf[i * 2] = UPPER_CHARS[(c >> 4) as usize];\r | |
93 | buf[i * 2 + 1] = UPPER_CHARS[(c & 0xF) as usize];\r | |
94 | }\r | |
95 | let n = min(chunk.len() * 2, digits_left);\r | |
96 | f.write_str(unsafe { str::from_utf8_unchecked(&buf[..n]) })?;\r | |
97 | digits_left -= n;\r | |
98 | }\r | |
99 | }\r | |
100 | Ok(())\r | |
101 | }\r | |
102 | }\r |