1use std::string::String;
4
5const HEXADECIMAL: &str = "0123456789abcdef";
6
7pub struct Hex;
8
9impl Hex {
10 pub fn encode<T: AsRef<[u8]>>(data: T) -> String {
11 let bytes = data.as_ref();
12 if bytes.is_empty() {
13 return String::new();
14 }
15
16 bytes.iter().map(|byte| format!("{:02x}", byte)).collect()
17 }
18
19 pub fn encode_str(data: &str) -> String {
20 Self::encode(data.as_bytes())
21 }
22
23 pub fn decode(data: &str) -> Result<Vec<u8>, &'static str> {
24 if data.is_empty() {
25 return Ok(Vec::new());
26 }
27
28 if data.len() % 2 != 0 {
29 return Err("Invalid hexadecimal string: odd length");
30 }
31
32 if !data
33 .chars()
34 .all(|c| HEXADECIMAL.contains(c.to_ascii_lowercase()))
35 {
36 return Err("Invalid hexadecimal string: invalid characters");
37 }
38
39 (0..data.len())
40 .step_by(2)
41 .map(|i| u8::from_str_radix(&data[i..i + 2], 16))
42 .collect::<Result<Vec<u8>, _>>()
43 .map_err(|_| "Failed to parse hexadecimal")
44 }
45
46 pub fn decode_str(data: &str) -> Result<String, &'static str> {
47 let bytes = Self::decode(data)?;
48 String::from_utf8(bytes).map_err(|_| "Invalid UTF-8 sequence")
49 }
50}