buup/transformers/
binary_decode.rs

1use crate::{Transform, TransformError};
2
3/// Binary Decode transformer
4#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
5pub struct BinaryDecode;
6
7impl Transform for BinaryDecode {
8    fn name(&self) -> &'static str {
9        "Binary Decode"
10    }
11
12    fn id(&self) -> &'static str {
13        "binarydecode"
14    }
15
16    fn description(&self) -> &'static str {
17        "Decode space-separated binary representation back to text."
18    }
19
20    fn category(&self) -> crate::TransformerCategory {
21        crate::TransformerCategory::Decoder
22    }
23
24    fn transform(&self, input: &str) -> Result<String, TransformError> {
25        if input.is_empty() {
26            return Ok(String::new());
27        }
28
29        let bytes: Result<Vec<u8>, _> = input
30            .split_whitespace()
31            .map(|s| {
32                if s.len() != 8 || !s.chars().all(|c| c == '0' || c == '1') {
33                    Err(TransformError::InvalidArgument(
34                        format!("Invalid 8-bit binary chunk: '{}'", s).into(),
35                    ))
36                } else {
37                    u8::from_str_radix(s, 2).map_err(|e| {
38                        TransformError::InvalidArgument(
39                            format!("Failed to parse binary chunk '{}': {}", s, e).into(),
40                        )
41                    })
42                }
43            })
44            .collect();
45
46        let bytes = bytes?;
47
48        String::from_utf8(bytes).map_err(|e| {
49            TransformError::InvalidArgument(format!("Invalid UTF-8 sequence: {}", e).into())
50        })
51    }
52}
53
54#[cfg(test)]
55mod tests {
56    use super::*;
57
58    #[test]
59    fn test_binary_decode_empty() {
60        let transformer = BinaryDecode;
61        let result = transformer.transform("").unwrap();
62        assert_eq!(result, "");
63    }
64
65    #[test]
66    fn test_binary_decode_simple() {
67        let transformer = BinaryDecode;
68        let result = transformer.transform("01001000 01101001").unwrap(); // "Hi"
69        assert_eq!(result, "Hi");
70    }
71
72    #[test]
73    fn test_binary_decode_with_punctuation() {
74        let transformer = BinaryDecode;
75        let input = "01001000 01100101 01101100 01101100 01101111 00101100 00100000 01010111 01101111 01110010 01101100 01100100 00100001"; // "Hello, World!"
76        let result = transformer.transform(input).unwrap();
77        assert_eq!(result, "Hello, World!");
78    }
79
80    #[test]
81    fn test_binary_decode_unicode() {
82        let transformer = BinaryDecode;
83        let input = "11100010 10011100 10010011"; // '✓'
84        let result = transformer.transform(input).unwrap();
85        assert_eq!(result, "✓");
86    }
87
88    #[test]
89    fn test_binary_decode_invalid_length() {
90        let transformer = BinaryDecode;
91        let result = transformer.transform("01001000 1101001"); // Second chunk is too short
92        assert!(result.is_err());
93        match result {
94            Err(TransformError::InvalidArgument(msg)) => {
95                assert!(msg.contains("Invalid 8-bit binary chunk: '1101001'"));
96            }
97            _ => panic!("Expected InvalidArgument error"),
98        }
99    }
100
101    #[test]
102    fn test_binary_decode_invalid_chars() {
103        let transformer = BinaryDecode;
104        let result = transformer.transform("01001000 0110100a"); // Contains 'a'
105        assert!(result.is_err());
106        match result {
107            Err(TransformError::InvalidArgument(msg)) => {
108                assert!(msg.contains("Invalid 8-bit binary chunk: '0110100a'"));
109            }
110            _ => panic!("Expected InvalidArgument error"),
111        }
112    }
113
114    #[test]
115    fn test_binary_decode_invalid_utf8() {
116        let transformer = BinaryDecode;
117        let result = transformer.transform("11110000 10011111 10011111"); // Invalid UTF-8 start byte
118        assert!(result.is_err());
119        match result {
120            Err(TransformError::InvalidArgument(msg)) => {
121                assert!(msg.contains("Invalid UTF-8 sequence"));
122            }
123            _ => panic!("Expected InvalidArgument error"),
124        }
125    }
126
127    #[test]
128    fn test_binary_decode_trailing_space() {
129        let transformer = BinaryDecode;
130        let result = transformer.transform("01001000 ").unwrap(); // "H"
131        assert_eq!(result, "H");
132    }
133
134    #[test]
135    fn test_binary_decode_leading_space() {
136        let transformer = BinaryDecode;
137        let result = transformer.transform(" 01001000").unwrap(); // "H"
138        assert_eq!(result, "H");
139    }
140}