cyware_convert/encoding/
hex.rs1use 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}