]> git.proxmox.com Git - rustc.git/blame - vendor/generic-array/src/hex.rs
New upstream version 1.48.0~beta.8+dfsg1
[rustc.git] / vendor / generic-array / src / hex.rs
CommitLineData
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
1b1a35ee
XL
18use core::{fmt, str, ops::Add, cmp::min};\r
19\r
ba9703b0
XL
20use typenum::*;\r
21\r
1b1a35ee
XL
22use crate::{ArrayLength, GenericArray};\r
23\r
ba9703b0
XL
24static LOWER_CHARS: &'static [u8] = b"0123456789abcdef";\r
25static UPPER_CHARS: &'static [u8] = b"0123456789ABCDEF";\r
26\r
27impl<T: ArrayLength<u8>> fmt::LowerHex for GenericArray<u8, T>\r
28where\r
29 T: Add<T>,\r
30 <T as Add<T>>::Output: ArrayLength<u8>,\r
31{\r
1b1a35ee 32 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\r
ba9703b0
XL
33 let max_digits = f.precision().unwrap_or_else(|| self.len() * 2);\r
34 let max_hex = (max_digits >> 1) + (max_digits & 1);\r
35\r
1b1a35ee 36 if T::USIZE < 1024 {\r
ba9703b0
XL
37 // For small arrays use a stack allocated\r
38 // buffer of 2x number of bytes\r
39 let mut res = GenericArray::<u8, Sum<T, T>>::default();\r
40\r
1b1a35ee 41 self.iter().take(max_hex).enumerate().for_each(|(i, c)| {\r
ba9703b0
XL
42 res[i * 2] = LOWER_CHARS[(c >> 4) as usize];\r
43 res[i * 2 + 1] = LOWER_CHARS[(c & 0xF) as usize];\r
1b1a35ee
XL
44 });\r
45\r
ba9703b0
XL
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
1b1a35ee 53 chunk.iter().enumerate().for_each(|(i, c)| {\r
ba9703b0
XL
54 buf[i * 2] = LOWER_CHARS[(c >> 4) as usize];\r
55 buf[i * 2 + 1] = LOWER_CHARS[(c & 0xF) as usize];\r
1b1a35ee
XL
56 });\r
57\r
ba9703b0
XL
58 let n = min(chunk.len() * 2, digits_left);\r
59 f.write_str(unsafe { str::from_utf8_unchecked(&buf[..n]) })?;\r
60 digits_left -= n;\r
61 }\r
62 }\r
63 Ok(())\r
64 }\r
65}\r
66\r
67impl<T: ArrayLength<u8>> fmt::UpperHex for GenericArray<u8, T>\r
68where\r
69 T: Add<T>,\r
70 <T as Add<T>>::Output: ArrayLength<u8>,\r
71{\r
1b1a35ee 72 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\r
ba9703b0
XL
73 let max_digits = f.precision().unwrap_or_else(|| self.len() * 2);\r
74 let max_hex = (max_digits >> 1) + (max_digits & 1);\r
75\r
1b1a35ee 76 if T::USIZE < 1024 {\r
ba9703b0
XL
77 // For small arrays use a stack allocated\r
78 // buffer of 2x number of bytes\r
79 let mut res = GenericArray::<u8, Sum<T, T>>::default();\r
80\r
1b1a35ee 81 self.iter().take(max_hex).enumerate().for_each(|(i, c)| {\r
ba9703b0
XL
82 res[i * 2] = UPPER_CHARS[(c >> 4) as usize];\r
83 res[i * 2 + 1] = UPPER_CHARS[(c & 0xF) as usize];\r
1b1a35ee
XL
84 });\r
85\r
ba9703b0
XL
86 f.write_str(unsafe { str::from_utf8_unchecked(&res[..max_digits]) })?;\r
87 } else {\r
88 // For large array use chunks of up to 1024 bytes (2048 hex chars)\r
89 let mut buf = [0u8; 2048];\r
90 let mut digits_left = max_digits;\r
91\r
92 for chunk in self[..max_hex].chunks(1024) {\r
1b1a35ee 93 chunk.iter().enumerate().for_each(|(i, c)| {\r
ba9703b0
XL
94 buf[i * 2] = UPPER_CHARS[(c >> 4) as usize];\r
95 buf[i * 2 + 1] = UPPER_CHARS[(c & 0xF) as usize];\r
1b1a35ee
XL
96 });\r
97\r
ba9703b0
XL
98 let n = min(chunk.len() * 2, digits_left);\r
99 f.write_str(unsafe { str::from_utf8_unchecked(&buf[..n]) })?;\r
100 digits_left -= n;\r
101 }\r
102 }\r
103 Ok(())\r
104 }\r
105}\r