clawft_kernel/workload_pkg/
codec.rs1pub fn hex_encode(bytes: &[u8]) -> String {
6 const DIGITS: &[u8; 16] = b"0123456789abcdef";
7 let mut s = String::with_capacity(bytes.len() * 2);
8 for b in bytes {
9 s.push(DIGITS[(b >> 4) as usize] as char);
10 s.push(DIGITS[(b & 0x0f) as usize] as char);
11 }
12 s
13}
14
15pub fn hex_decode_exact<const N: usize>(s: &str) -> Option<[u8; N]> {
18 if s.len() != N * 2 {
19 return None;
20 }
21 let mut out = [0u8; N];
22 let bytes = s.as_bytes();
23 for (i, slot) in out.iter_mut().enumerate() {
24 let hi = hex_val(bytes[2 * i])?;
25 let lo = hex_val(bytes[2 * i + 1])?;
26 *slot = (hi << 4) | lo;
27 }
28 Some(out)
29}
30
31pub fn is_lower_hex(s: &str, len: usize) -> bool {
33 s.len() == len && s.bytes().all(|b| hex_val(b).is_some())
34}
35
36fn hex_val(b: u8) -> Option<u8> {
37 match b {
38 b'0'..=b'9' => Some(b - b'0'),
39 b'a'..=b'f' => Some(b - b'a' + 10),
40 _ => None,
41 }
42}
43
44pub fn base64_decode(s: &str) -> Option<Vec<u8>> {
48 let trimmed = s.trim_end_matches('=');
49 if s.len() - trimmed.len() > 2 || trimmed.len() % 4 == 1 {
50 return None;
51 }
52 let mut out = Vec::with_capacity(trimmed.len() * 3 / 4);
53 let mut acc: u32 = 0;
54 let mut bits = 0u32;
55 for c in trimmed.bytes() {
56 let v = match c {
57 b'A'..=b'Z' => c - b'A',
58 b'a'..=b'z' => c - b'a' + 26,
59 b'0'..=b'9' => c - b'0' + 52,
60 b'+' | b'-' => 62,
61 b'/' | b'_' => 63,
62 _ => return None,
63 } as u32;
64 acc = (acc << 6) | v;
65 bits += 6;
66 if bits >= 8 {
67 bits -= 8;
68 out.push((acc >> bits) as u8);
69 acc &= (1 << bits) - 1;
70 }
71 }
72 if acc != 0 {
73 return None;
74 }
75 Some(out)
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81
82 #[test]
83 fn hex_round_trip_and_strictness() {
84 let bytes = [0u8, 1, 0xab, 0xff];
85 let s = hex_encode(&bytes);
86 assert_eq!(s, "0001abff");
87 assert_eq!(hex_decode_exact::<4>(&s), Some(bytes));
88 assert_eq!(hex_decode_exact::<4>("0001ABFF"), None);
89 assert_eq!(hex_decode_exact::<4>("0001ab"), None);
90 assert!(is_lower_hex("ab01", 4));
91 assert!(!is_lower_hex("ab0g", 4));
92 }
93
94 #[test]
95 fn base64_both_alphabets() {
96 assert_eq!(base64_decode("aGVsbG8").unwrap(), b"hello");
97 assert_eq!(base64_decode("aGVsbG8=").unwrap(), b"hello");
98 assert_eq!(base64_decode("-_8").unwrap(), vec![0xfb, 0xff]);
99 assert_eq!(base64_decode("+/8").unwrap(), vec![0xfb, 0xff]);
100 assert!(base64_decode("a").is_none());
101 assert!(base64_decode("aGVsbG8===").is_none());
102 assert!(base64_decode("aGVs bG8").is_none());
103 assert!(base64_decode("aGVsbG9=").is_none());
105 }
106}