1use std::num::ParseIntError;
2
3use crate::InvalidVectorSizeError;
4
5fn byte_to_hex(byte: &u8) -> String {
6 format!("{:02x}", byte)
7}
8
9pub fn encode_hex<T: Clone + Into<Vec<u8>>>(bytes: &T) -> String {
10 let hex_vec: Vec<String> = bytes.clone().into().iter().map(byte_to_hex).collect();
11
12 hex_vec.join("")
13}
14
15pub fn decode_hex(s: &str) -> Result<Vec<u8>, ParseIntError> {
16 (0..s.len())
17 .step_by(2)
18 .map(|i| u8::from_str_radix(&s[i..i + 2], 16))
19 .collect()
20}
21
22#[derive(Debug)]
23pub enum DecodeError {
24 ParseIntError(ParseIntError),
25 InvalidVectorSizeError(InvalidVectorSizeError),
26}
27
28impl From<InvalidVectorSizeError> for DecodeError {
29 fn from(err: InvalidVectorSizeError) -> Self {
30 Self::InvalidVectorSizeError(err)
31 }
32}
33
34impl From<ParseIntError> for DecodeError {
35 fn from(err: ParseIntError) -> Self {
36 Self::ParseIntError(err)
37 }
38}
39
40pub fn decode_hex_bls_sig(s: &str) -> Result<[u8; 96], DecodeError> {
41 hex_to_array::<96>(s)
42}
43
44pub fn decode_hex_sha256(s: &str) -> Result<[u8; 32], DecodeError> {
45 hex_to_array::<32>(s)
46}
47
48pub fn hex_to_array<const N: usize>(s: &str) -> Result<[u8; N], DecodeError> {
49 let vec = decode_hex(s)?;
50 Ok(vec_to_array::<N>(&vec)?)
51}
52
53pub fn vec_to_array<const N: usize>(vec: &[u8]) -> Result<[u8; N], InvalidVectorSizeError> {
54 let mut v: [u8; N] = [0; N];
55 if v.len() != vec.len() {
57 return Err(InvalidVectorSizeError::new(v.len(), vec.len()));
58 }
59 for i in 0..vec.len() {
60 if let Some(n) = vec.get(i) {
61 v[i] = *n;
62 } else {
63 return Err(InvalidVectorSizeError::new(v.len(), vec.len()));
64 }
65 }
66 Ok(v)
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72
73 #[test]
76 fn test_encode_hex_empty() {
77 let bytes: Vec<u8> = vec![];
78 assert_eq!(encode_hex(&bytes), "");
79 }
80
81 #[test]
82 fn test_encode_hex_single_byte() {
83 let bytes: Vec<u8> = vec![0xff];
84 assert_eq!(encode_hex(&bytes), "ff");
85 }
86
87 #[test]
88 fn test_encode_hex_multiple_bytes() {
89 let bytes: Vec<u8> = vec![0xde, 0xad, 0xbe, 0xef];
90 assert_eq!(encode_hex(&bytes), "deadbeef");
91 }
92
93 #[test]
94 fn test_encode_hex_leading_zeros() {
95 let bytes: Vec<u8> = vec![0x00, 0x01, 0x0a];
96 assert_eq!(encode_hex(&bytes), "00010a");
97 }
98
99 #[test]
100 fn test_encode_hex_all_zeros() {
101 let bytes: Vec<u8> = vec![0x00, 0x00, 0x00];
102 assert_eq!(encode_hex(&bytes), "000000");
103 }
104
105 #[test]
108 fn test_decode_hex_empty() {
109 let result = decode_hex("").unwrap();
110 assert!(result.is_empty());
111 }
112
113 #[test]
114 fn test_decode_hex_valid() {
115 let result = decode_hex("deadbeef").unwrap();
116 assert_eq!(result, vec![0xde, 0xad, 0xbe, 0xef]);
117 }
118
119 #[test]
120 fn test_decode_hex_uppercase() {
121 let result = decode_hex("DEADBEEF").unwrap();
122 assert_eq!(result, vec![0xde, 0xad, 0xbe, 0xef]);
123 }
124
125 #[test]
126 fn test_decode_hex_mixed_case() {
127 let result = decode_hex("DeAdBeEf").unwrap();
128 assert_eq!(result, vec![0xde, 0xad, 0xbe, 0xef]);
129 }
130
131 #[test]
132 fn test_decode_hex_leading_zeros() {
133 let result = decode_hex("00010a").unwrap();
134 assert_eq!(result, vec![0x00, 0x01, 0x0a]);
135 }
136
137 #[test]
138 fn test_decode_hex_invalid_chars() {
139 let result = decode_hex("zzzz");
140 assert!(result.is_err());
141 }
142
143 #[test]
144 #[should_panic]
145 fn test_decode_hex_odd_length_panics() {
146 let _ = decode_hex("abc");
149 }
150
151 #[test]
154 fn test_hex_round_trip() {
155 let original: Vec<u8> = vec![0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];
156 let hex = encode_hex(&original);
157 let decoded = decode_hex(&hex).unwrap();
158 assert_eq!(original, decoded);
159 }
160
161 #[test]
162 fn test_hex_round_trip_empty() {
163 let original: Vec<u8> = vec![];
164 let hex = encode_hex(&original);
165 let decoded = decode_hex(&hex).unwrap();
166 assert_eq!(original, decoded);
167 }
168
169 #[test]
170 fn test_hex_round_trip_all_byte_values() {
171 let original: Vec<u8> = (0..=255).collect();
172 let hex = encode_hex(&original);
173 let decoded = decode_hex(&hex).unwrap();
174 assert_eq!(original, decoded);
175 }
176
177 #[test]
180 fn test_hex_to_array_valid_4_bytes() {
181 let result = hex_to_array::<4>("deadbeef").unwrap();
182 assert_eq!(result, [0xde, 0xad, 0xbe, 0xef]);
183 }
184
185 #[test]
186 fn test_hex_to_array_valid_32_bytes() {
187 let hex = "a".repeat(64); let result = hex_to_array::<32>(&hex).unwrap();
189 assert_eq!(result.len(), 32);
190 assert!(result.iter().all(|&b| b == 0xaa));
191 }
192
193 #[test]
194 fn test_hex_to_array_wrong_size() {
195 let result = hex_to_array::<2>("deadbeef");
197 assert!(result.is_err());
198 }
199
200 #[test]
201 fn test_hex_to_array_invalid_hex() {
202 let result = hex_to_array::<2>("zzzz");
203 assert!(result.is_err());
204 }
205
206 #[test]
209 fn test_vec_to_array_valid() {
210 let vec = vec![1u8, 2, 3, 4];
211 let result = vec_to_array::<4>(&vec).unwrap();
212 assert_eq!(result, [1, 2, 3, 4]);
213 }
214
215 #[test]
216 fn test_vec_to_array_too_short() {
217 let vec = vec![1u8, 2];
218 let result = vec_to_array::<4>(&vec);
219 assert!(result.is_err());
220 let err = result.unwrap_err();
221 assert_eq!(err.expected_size(), 4);
222 assert_eq!(err.actual_size(), 2);
223 }
224
225 #[test]
226 fn test_vec_to_array_too_long() {
227 let vec = vec![1u8, 2, 3, 4, 5];
228 let result = vec_to_array::<4>(&vec);
229 assert!(result.is_err());
230 let err = result.unwrap_err();
231 assert_eq!(err.expected_size(), 4);
232 assert_eq!(err.actual_size(), 5);
233 }
234
235 #[test]
236 fn test_vec_to_array_empty_to_zero() {
237 let vec: Vec<u8> = vec![];
238 let result = vec_to_array::<0>(&vec).unwrap();
239 assert_eq!(result, [0u8; 0]);
240 }
241
242 #[test]
243 fn test_vec_to_array_single_element() {
244 let vec = vec![0xffu8];
245 let result = vec_to_array::<1>(&vec).unwrap();
246 assert_eq!(result, [0xff]);
247 }
248
249 #[test]
252 fn test_decode_hex_sha256_valid() {
253 let hex = "ab".repeat(32); let result = decode_hex_sha256(&hex).unwrap();
255 assert_eq!(result.len(), 32);
256 assert!(result.iter().all(|&b| b == 0xab));
257 }
258
259 #[test]
260 fn test_decode_hex_sha256_wrong_length() {
261 let hex = "ab".repeat(16); let result = decode_hex_sha256(&hex);
263 assert!(result.is_err());
264 }
265
266 #[test]
267 fn test_decode_hex_bls_sig_valid() {
268 let hex = "cd".repeat(96); let result = decode_hex_bls_sig(&hex).unwrap();
270 assert_eq!(result.len(), 96);
271 assert!(result.iter().all(|&b| b == 0xcd));
272 }
273
274 #[test]
275 fn test_decode_hex_bls_sig_wrong_length() {
276 let hex = "cd".repeat(48); let result = decode_hex_bls_sig(&hex);
278 assert!(result.is_err());
279 }
280}