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