cyware_convert/encoding/
hex.rs

1use bstr::ByteSlice;
2use hex;
3#[cfg(target_family = "wasm")]
4use serde::{Deserialize, Serialize};
5
6use crate::Operation;
7use crate::OperationError;
8
9#[derive(Clone)]
10#[cfg_attr(target_family = "wasm", derive(Serialize, Deserialize))]
11pub struct HexDecode {
12    prefix: Option<String>,
13    delimiter: Option<String>,
14}
15
16#[derive(Clone, Copy)]
17#[cfg_attr(target_family = "wasm", derive(Serialize, Deserialize))]
18pub enum HexFormat {
19    Upper,
20    Lower,
21}
22
23impl Operation for HexDecode {
24    fn execute(&self, input: &[u8]) -> Result<Vec<u8>, OperationError> {
25        let mut input = input.to_vec();
26        if let Some(p) = &self.prefix {
27            input = input.replace(p, "");
28        };
29        if let Some(d) = &self.delimiter {
30            input = input.replace(d, "");
31        };
32        Ok(hex::decode(input)?)
33    }
34}
35
36impl HexDecode {
37    pub const fn new(prefix: Option<String>, delimiter: Option<String>) -> Self {
38        HexDecode { prefix, delimiter }
39    }
40}
41
42#[derive(Clone)]
43#[cfg_attr(target_family = "wasm", derive(Serialize, Deserialize))]
44pub struct HexEncode {
45    format: HexFormat,
46    prefix: Option<String>,
47    delimiter: Option<String>,
48}
49
50impl Operation for HexEncode {
51    fn execute(&self, input: &[u8]) -> Result<Vec<u8>, OperationError> {
52        let hex_string = match self.format {
53            HexFormat::Lower => hex::encode(input),
54            HexFormat::Upper => hex::encode_upper(input),
55        };
56        let mut output = vec![];
57        let delimiter = self
58            .delimiter
59            .clone()
60            .and_then(|d| if d.is_empty() { None } else { Some(d) });
61        let prefix = self
62            .prefix
63            .clone()
64            .and_then(|p| if p.is_empty() { None } else { Some(p) });
65        let mut chunks = hex_string.as_bytes().chunks(2).peekable();
66        while let Some(chunk) = chunks.next() {
67            if let Some(p) = &prefix {
68                output.extend_from_slice(p.as_bytes());
69            }
70            output.extend_from_slice(chunk);
71            if let Some(d) = &delimiter {
72                if chunks.peek().is_some() {
73                    output.extend_from_slice(d.as_bytes());
74                }
75            }
76        }
77        Ok(output)
78    }
79}
80
81impl HexEncode {
82    pub const fn new(format: HexFormat, prefix: Option<String>, delimiter: Option<String>) -> Self {
83        HexEncode {
84            format,
85            prefix,
86            delimiter,
87        }
88    }
89}
90
91#[cfg(test)]
92mod tests {
93    use super::*;
94
95    #[test]
96    fn hex_decode_no_prefix_no_delimiter() {
97        let encoder = HexDecode::new(None, None);
98        let actual = encoder.execute("636169646f".as_bytes()).unwrap();
99        let expected = "caido".as_bytes().to_vec();
100        assert_eq!(actual, expected);
101    }
102
103    #[test]
104    fn hex_decode_prefix() {
105        let encoder = HexDecode::new(Some("\\x".to_string()), None);
106        let actual = encoder
107            .execute("\\x63\\x61\\x69\\x64\\x6f".as_bytes())
108            .unwrap();
109        let expected = "caido".as_bytes().to_vec();
110        assert_eq!(actual, expected);
111    }
112
113    #[test]
114    fn hex_decode_delimiter() {
115        let encoder = HexDecode::new(None, Some(",".to_string()));
116        let actual = encoder.execute("63,61,69,64,6f".as_bytes()).unwrap();
117        let expected = "caido".as_bytes().to_vec();
118        assert_eq!(actual, expected);
119    }
120
121    #[test]
122    fn hex_encode_prefix_upper() {
123        let encoder = HexEncode::new(HexFormat::Upper, Some("\\x".to_string()), None);
124        let actual = encoder.execute("caido".as_bytes()).unwrap();
125        let expected = "\\x63\\x61\\x69\\x64\\x6F".as_bytes().to_vec();
126        assert_eq!(actual, expected);
127    }
128
129    #[test]
130    fn hex_encode_prefix_lower() {
131        let encoder = HexEncode::new(HexFormat::Lower, Some("0x".to_string()), None);
132        let actual = encoder.execute("caido".as_bytes()).unwrap();
133        let expected = "0x630x610x690x640x6f".as_bytes().to_vec();
134        assert_eq!(actual, expected);
135    }
136
137    #[test]
138    fn hex_encode_delimiter_lower() {
139        let encoder = HexEncode::new(HexFormat::Lower, None, Some("\n".to_string()));
140        let actual = encoder.execute("caido".as_bytes()).unwrap();
141        let expected = "63\n61\n69\n64\n6f".as_bytes().to_vec();
142        assert_eq!(actual, expected);
143    }
144
145    #[test]
146    fn hex_encode_delimiter_upper() {
147        let encoder = HexEncode::new(HexFormat::Upper, None, Some("\n".to_string()));
148        let actual = encoder.execute("caido".as_bytes()).unwrap();
149        let expected = "63\n61\n69\n64\n6F".as_bytes().to_vec();
150        assert_eq!(actual, expected);
151    }
152}