1use hex::FromHexError;
2
3use crate::{LOWER, UPPER};
4
5pub fn encode<T, V>(v: &T, out: impl FnOnce(&str) -> V) -> V
9where
10 T: ?Sized + AsRef<[u8]>,
11{
12 fast_serialize::<_, _, LOWER>(v, out)
13}
14
15pub fn encode_upper<T, V>(v: &T, out: impl FnOnce(&str) -> V) -> V
19where
20 T: ?Sized + AsRef<[u8]>,
21{
22 fast_serialize::<_, _, UPPER>(v, out)
23}
24
25pub(crate) const SMALL_SER_LEN: usize = 128;
26
27pub(crate) fn fast_serialize<T, V, const U: bool>(v: &T, out: impl FnOnce(&str) -> V) -> V
28where
29 T: ?Sized + AsRef<[u8]>,
30{
31 let v = v.as_ref();
32
33 let str_len = v.len() * 2;
34 let mut array;
35 let mut vec;
36 let buf;
37 if str_len <= SMALL_SER_LEN {
38 array = [0; SMALL_SER_LEN];
39 buf = &mut array[..str_len];
40 } else {
41 vec = vec![0; str_len];
42 buf = &mut vec[..];
43 }
44
45 let alpha = if U { HEX_CHARS_UPPER } else { HEX_CHARS_LOWER };
46 let _ = encode_to_slice(v, buf, alpha);
48
49 let s: &str = unsafe { std::str::from_utf8_unchecked(buf) };
51 out(s)
52}
53
54const HEX_CHARS_LOWER: &[u8; 16] = b"0123456789abcdef";
57const HEX_CHARS_UPPER: &[u8; 16] = b"0123456789ABCDEF";
58
59fn encode_to_slice<T: AsRef<[u8]>>(
61 input: T,
62 output: &mut [u8],
63 alpha: &[u8; 16],
64) -> Result<(), FromHexError> {
65 if input.as_ref().len() * 2 != output.len() {
66 return Err(FromHexError::InvalidStringLength);
67 }
68
69 for (byte, (i, j)) in input
70 .as_ref()
71 .iter()
72 .zip(generate_iter(input.as_ref().len() * 2))
73 {
74 let (high, low) = byte2hex(*byte, alpha);
75 output[i] = high;
76 output[j] = low;
77 }
78
79 Ok(())
80}
81
82#[inline]
90fn generate_iter(len: usize) -> impl Iterator<Item = (usize, usize)> {
91 (0..len).step_by(2).zip((0..len).skip(1).step_by(2))
92}
93
94#[inline]
97#[must_use]
98fn byte2hex(byte: u8, table: &[u8; 16]) -> (u8, u8) {
99 let high = table[((byte & 0xf0) >> 4) as usize];
100 let low = table[(byte & 0x0f) as usize];
101
102 (high, low)
103}