rust_auth_utils/
hex.rs

1// based on https://github.com/better-auth/utils/blob/main/src/hex.ts
2
3use 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}