buup/transformers/
hex_to_ascii.rs1use crate::{Transform, TransformError, TransformerCategory};
2
3#[derive(Debug, Clone, PartialEq, Eq, Default)]
13pub struct HexToAscii;
14
15impl Transform for HexToAscii {
16 fn name(&self) -> &'static str {
17 "Hex to ASCII"
18 }
19
20 fn id(&self) -> &'static str {
21 "hex_to_ascii"
22 }
23
24 fn description(&self) -> &'static str {
25 "Convert hexadecimal representation back to ASCII characters."
26 }
27
28 fn category(&self) -> TransformerCategory {
29 TransformerCategory::Decoder
30 }
31
32 fn transform(&self, input: &str) -> Result<String, TransformError> {
33 if input.len() % 2 != 0 {
35 return Err(TransformError::InvalidArgument(
36 "Input hex string must have an even number of characters".into(),
37 ));
38 }
39
40 let cleaned_input = input.trim().trim_start_matches("0x");
42
43 let mut bytes = Vec::with_capacity(cleaned_input.len() / 2);
44 let mut chars = cleaned_input.chars();
45
46 while let (Some(h), Some(l)) = (chars.next(), chars.next()) {
47 let hex_pair = format!("{}{}", h, l);
48 match u8::from_str_radix(&hex_pair, 16) {
49 Ok(byte) => bytes.push(byte),
50 Err(_) => {
51 return Err(TransformError::InvalidArgument(
52 format!("Invalid hex character sequence found: '{}'", hex_pair).into(),
53 ))
54 }
55 }
56 }
57
58 String::from_utf8(bytes).map_err(|_| TransformError::Utf8Error)
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65
66 #[test]
67 fn test_hex_to_ascii() {
68 let transformer = HexToAscii;
69 assert_eq!(transformer.transform("48656c6c6f").unwrap(), "Hello");
70 assert_eq!(transformer.transform("576f726c64").unwrap(), "World");
71 assert_eq!(transformer.transform("313233").unwrap(), "123");
72 assert_eq!(transformer.transform("20").unwrap(), " "); assert_eq!(transformer.transform("").unwrap(), ""); assert_eq!(transformer.transform("214023").unwrap(), "!@#");
75 }
76
77 #[test]
78 fn test_invalid_hex() {
79 let transformer = HexToAscii;
80 assert!(matches!(
82 transformer.transform("48656c6c6G"),
83 Err(TransformError::InvalidArgument(_))
84 ));
85 assert!(matches!(
87 transformer.transform("48656c6c6"),
88 Err(TransformError::InvalidArgument(_))
89 ));
90 }
91
92 #[test]
93 fn test_non_utf8_output() {
94 let transformer = HexToAscii;
95 assert!(matches!(
97 transformer.transform("80"),
98 Err(TransformError::Utf8Error)
99 ));
100 assert!(matches!(
101 transformer.transform("c0"),
102 Err(TransformError::Utf8Error)
103 )); }
105
106 #[test]
107 fn test_properties() {
108 let transformer = HexToAscii;
109 assert_eq!(transformer.name(), "Hex to ASCII");
110 assert_eq!(transformer.id(), "hex_to_ascii");
111 assert_eq!(
112 transformer.description(),
113 "Convert hexadecimal representation back to ASCII characters."
114 );
115 assert_eq!(transformer.category(), TransformerCategory::Decoder);
116 }
117}