1pub trait HexExt {
5 fn to_hex(&self) -> String;
7 fn from_hex(s: &str) -> Result<Self, HexError> where Self: Sized;
9}
10
11impl HexExt for [u8] {
12 fn to_hex(&self) -> String {
13 self.iter().map(|b| format!("{:02x}", b)).collect()
14 }
15}
16
17impl HexExt for Vec<u8> {
18 fn to_hex(&self) -> String {
19 self.as_slice().to_hex()
20 }
21
22 fn from_hex(s: &str) -> Result<Self, HexError> {
23 let cleaned: String = s.chars().filter(|c| c.is_ascii_hexdigit()).collect();
24 if cleaned.len() % 2 != 0 {
25 return Err(HexError::OddLength);
26 }
27
28 cleaned.as_bytes()
29 .chunks(2)
30 .map(|chunk| {
31 u8::from_str_radix(std::str::from_utf8(chunk).unwrap(), 16)
32 .map_err(|_| HexError::InvalidCharacter)
33 })
34 .collect::<Result<Vec<_>, _>>()
35 }
36}
37
38#[derive(Debug, Clone, Copy, PartialEq, Eq)]
40pub enum HexError {
41 OddLength,
43 InvalidCharacter,
45}
46
47impl core::fmt::Display for HexError {
48 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
49 match self {
50 HexError::OddLength => write!(f, "odd number of hex digits"),
51 HexError::InvalidCharacter => write!(f, "invalid hex character"),
52 }
53 }
54}
55
56impl core::error::Error for HexError {}