1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
use crate::Error::{InsufficientTargetSpace, IntegerOverflow};
use crate::{encode_string_unchecked, Encoder, Error, StringEncoder};
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
pub struct HexEncoder {
encoding: &'static [u8; 16],
}
impl HexEncoder {
pub const LOWER: Self = Self {
encoding: b"0123456789abcdef",
};
pub const UPPER: Self = Self {
encoding: b"0123456789ABCDEF",
};
}
impl HexEncoder {
#[inline(always)]
pub const fn encode(&self, b: u8) -> (u8, u8) {
(
self.encoding[b as usize >> 4],
self.encoding[b as usize & 0xF],
)
}
}
impl Encoder for HexEncoder {
fn encoded_len(&self, data: &[u8]) -> Result<usize, Error> {
data.len().checked_mul(2).ok_or(IntegerOverflow)
}
fn encode_slice(&self, data: &[u8], target: &mut [u8]) -> Result<usize, Error> {
let encoded_len: usize = self.encoded_len(data)?;
if target.len() < encoded_len {
Err(InsufficientTargetSpace)
} else {
let target: &mut [u8] = &mut target[..encoded_len];
for (d, t) in data.iter().zip(target.chunks_exact_mut(2)) {
let (high, low) = self.encode(*d);
t[0] = high;
t[1] = low;
}
Ok(encoded_len)
}
}
}
impl StringEncoder for HexEncoder {
fn encode_string(&self, data: &[u8], target: &mut String) -> Result<usize, Error> {
unsafe { encode_string_unchecked(self, data, target) }
}
}