mini_bitcoin_script/
hex.rs1use crate::error::ScriptError;
2
3pub fn decode_hex(hex: &str) -> Result<Vec<u8>, ScriptError> {
13 if hex.len() % 2 != 0 {
14 return Err(ScriptError::InvalidHex);
15 }
16
17 let mut bytes = Vec::with_capacity(hex.len() / 2);
18
19 for i in (0..hex.len()).step_by(2) {
20 let pair = &hex[i..i + 2];
21 let byte = u8::from_str_radix(pair, 16).map_err(|_| ScriptError::InvalidHex)?;
22 bytes.push(byte);
23 }
24
25 Ok(bytes)
26}
27
28#[cfg(test)]
29mod tests {
30 use super::*;
31
32 #[test]
33 fn empty_string() {
34 assert_eq!(decode_hex("").unwrap(), vec![]);
35 }
36
37 #[test]
38 fn single_byte() {
39 assert_eq!(decode_hex("00").unwrap(), vec![0x00]);
40 assert_eq!(decode_hex("ff").unwrap(), vec![0xff]);
41 }
42
43 #[test]
44 fn mixed_case() {
45 assert_eq!(decode_hex("FF").unwrap(), vec![0xff]);
46 assert_eq!(decode_hex("aAbB").unwrap(), vec![0xaa, 0xbb]);
47 }
48
49 #[test]
50 fn multi_byte() {
51 assert_eq!(
52 decode_hex("deadbeef").unwrap(),
53 vec![0xde, 0xad, 0xbe, 0xef]
54 );
55 }
56
57 #[test]
58 fn odd_length() {
59 assert_eq!(decode_hex("0"), Err(ScriptError::InvalidHex));
60 assert_eq!(decode_hex("abc"), Err(ScriptError::InvalidHex));
61 }
62
63 #[test]
64 fn invalid_characters() {
65 assert_eq!(decode_hex("gg"), Err(ScriptError::InvalidHex));
66 assert_eq!(decode_hex("0x00"), Err(ScriptError::InvalidHex));
67 }
68}