stateset_crypto/
encoding.rs1use crate::CryptoError;
2
3#[must_use]
5pub const fn u32_be(n: u32) -> [u8; 4] {
6 n.to_be_bytes()
7}
8
9#[must_use]
11pub const fn u64_be(n: u64) -> [u8; 8] {
12 n.to_be_bytes()
13}
14
15#[must_use]
17pub fn encode_string(s: &str) -> Vec<u8> {
18 let bytes = s.as_bytes();
19 let mut result = Vec::with_capacity(4 + bytes.len());
20 result.extend_from_slice(&u32_be(bytes.len() as u32));
21 result.extend_from_slice(bytes);
22 result
23}
24
25pub fn uuid_to_bytes(uuid: &str) -> Result<[u8; 16], CryptoError> {
32 let hex_str: String = uuid.chars().filter(|c| *c != '-').collect();
33 if hex_str.len() != 32 {
34 return Err(CryptoError::InvalidUuid(uuid.to_string()));
35 }
36 let mut bytes = [0u8; 16];
37 hex::decode_to_slice(&hex_str, &mut bytes)
38 .map_err(|_| CryptoError::InvalidUuid(uuid.to_string()))?;
39 Ok(bytes)
40}
41
42pub fn hex_to_bytes(hex: &str) -> Result<Vec<u8>, CryptoError> {
48 let hex_str = hex.strip_prefix("0x").unwrap_or(hex);
49 hex::decode(hex_str).map_err(|e| CryptoError::InvalidHex(e.to_string()))
50}
51
52#[must_use]
54pub fn bytes_to_hex(bytes: &[u8]) -> String {
55 format!("0x{}", hex::encode(bytes))
56}
57
58#[cfg(test)]
59mod tests {
60 use super::*;
61
62 #[test]
63 fn u32_be_zero() {
64 assert_eq!(u32_be(0), [0, 0, 0, 0]);
65 }
66
67 #[test]
68 fn u32_be_one() {
69 assert_eq!(u32_be(1), [0, 0, 0, 1]);
70 }
71
72 #[test]
73 fn u32_be_max() {
74 assert_eq!(u32_be(u32::MAX), [0xFF, 0xFF, 0xFF, 0xFF]);
75 }
76
77 #[test]
78 fn u64_be_zero() {
79 assert_eq!(u64_be(0), [0, 0, 0, 0, 0, 0, 0, 0]);
80 }
81
82 #[test]
83 fn u64_be_one() {
84 assert_eq!(u64_be(1), [0, 0, 0, 0, 0, 0, 0, 1]);
85 }
86
87 #[test]
88 fn encode_string_empty() {
89 assert_eq!(encode_string(""), vec![0, 0, 0, 0]);
90 }
91
92 #[test]
93 fn encode_string_hello() {
94 let result = encode_string("hello");
95 assert_eq!(&result[..4], &[0, 0, 0, 5]);
96 assert_eq!(&result[4..], b"hello");
97 }
98
99 #[test]
100 fn uuid_to_bytes_valid() {
101 let bytes = uuid_to_bytes("550e8400-e29b-41d4-a716-446655440000").unwrap();
102 assert_eq!(bytes[0], 0x55);
103 assert_eq!(bytes.len(), 16);
104 }
105
106 #[test]
107 fn uuid_to_bytes_invalid_length() {
108 assert!(uuid_to_bytes("not-a-uuid").is_err());
109 }
110
111 #[test]
112 fn hex_to_bytes_with_prefix() {
113 let bytes = hex_to_bytes("0xdeadbeef").unwrap();
114 assert_eq!(bytes, vec![0xDE, 0xAD, 0xBE, 0xEF]);
115 }
116
117 #[test]
118 fn hex_to_bytes_without_prefix() {
119 let bytes = hex_to_bytes("deadbeef").unwrap();
120 assert_eq!(bytes, vec![0xDE, 0xAD, 0xBE, 0xEF]);
121 }
122
123 #[test]
124 fn bytes_to_hex_roundtrip() {
125 let original = vec![0xDE, 0xAD, 0xBE, 0xEF];
126 let hex_str = bytes_to_hex(&original);
127 assert_eq!(hex_str, "0xdeadbeef");
128 let back = hex_to_bytes(&hex_str).unwrap();
129 assert_eq!(back, original);
130 }
131}