1extern crate alloc;
2use alloc::vec::Vec;
3
4#[derive(Debug, PartialEq, Clone, Copy)]
5pub enum ByteDataError {
6 FindByteError,
7 UnpackError,
8 PackError,
9 StartDelimiterNotFound,
10 EndDelimiterNotFound,
11 InsufficientData,
12}
13
14#[derive(Debug, PartialEq, Eq, Clone, Copy, strum::EnumString)]
15#[strum(ascii_case_insensitive)]
16pub enum DataType {
17 U8,
18 I8,
19 U16,
20 I16,
21 U24,
22 I24,
23 U32,
24 I32,
25 U48,
26 I48,
27 U64,
28 I64,
29 U128,
30 I128,
31 F32,
32 F64,
33}
34
35impl DataType {
36 pub fn byte_size(&self) -> usize {
37 match self {
38 DataType::U8 => 1,
39 DataType::I8 => 1,
40 DataType::U16 => 2,
41 DataType::I16 => 2,
42 DataType::U24 => 3,
43 DataType::I24 => 3,
44 DataType::U32 => 4,
45 DataType::I32 => 4,
46 DataType::U48 => 6,
47 DataType::I48 => 6,
48 DataType::U64 => 8,
49 DataType::I64 => 8,
50 DataType::U128 => 16,
51 DataType::I128 => 16,
52 DataType::F32 => 4,
53 DataType::F64 => 8,
54 }
55 }
56}
57
58#[derive(Debug, PartialEq, Eq, Clone, Copy, strum::EnumString)]
59pub enum ByteOrderSpec {
60 BigEndian,
61 LittleEndian,
62}
63pub fn parse_byte_data_spec<S: AsRef<str>>(data: &[S]) -> Vec<(DataType, ByteOrderSpec)> {
64 data.iter()
65 .map(|d| {
66 d.as_ref()
67 .split_once(':')
68 .expect("Invalid byte data format")
69 })
70 .map(|(dt, bo)| {
71 (
72 dt.parse::<DataType>().unwrap(),
73 bo.parse::<ByteOrderSpec>().unwrap(),
74 )
75 })
76 .collect()
77}
78
79pub fn compare_bytes(data: &[u8], check: &[u8], skip_byte_indices: &[usize]) -> bool {
80 if skip_byte_indices.len() + check.len() != data.len() {
81 return false;
82 }
83
84 if skip_byte_indices.is_empty() {
85 return data == check;
86 }
87
88 let mut skipped = 0;
89 for (i, c) in data.iter().enumerate() {
90 if skip_byte_indices.contains(&i) {
91 skipped += 1;
92 continue;
93 }
94
95 let check_val = &check[i - skipped];
96 if c != check_val {
97 return false;
98 }
99 }
100
101 true
102}
103
104pub fn find_all_bytes_idx(data: &[u8], check: &[u8], skip_byte_indices: &[usize]) -> Vec<usize> {
105 let window_size = check.len() + skip_byte_indices.len();
106 data.windows(window_size)
107 .enumerate()
108 .filter(|&(_, w)| compare_bytes(w, check, skip_byte_indices))
109 .map(|(idx, _)| idx)
110 .collect()
111}
112
113pub fn rfind_all_bytes_idx(data: &[u8], check: &[u8], skip_byte_indices: &[usize]) -> Vec<usize> {
114 let window_size = check.len() + skip_byte_indices.len();
115 data.windows(window_size)
116 .rev()
117 .enumerate()
118 .filter(|&(_, w)| compare_bytes(w, check, skip_byte_indices))
119 .map(|(idx, _)| data.len() - idx - window_size)
120 .collect()
121}
122
123pub fn find_bytes_idx(
124 data: &[u8],
125 check: &[u8],
126 skip_byte_indices: &[usize],
127) -> Result<usize, ByteDataError> {
128 let window_size = check.len() + skip_byte_indices.len();
132 data.windows(window_size)
133 .enumerate()
134 .find(|&(_, w)| compare_bytes(w, check, skip_byte_indices))
135 .map(|(idx, _)| idx)
136 .ok_or(ByteDataError::FindByteError)
137}
138
139pub fn rfind_bytes_idx(
140 data: &[u8],
141 check: &[u8],
142 skip_byte_indices: &[usize],
143) -> Result<usize, ByteDataError> {
144 let window_size = check.len() + skip_byte_indices.len();
145 data.windows(window_size)
149 .rev()
150 .enumerate()
151 .find(|&(_, w)| compare_bytes(w, check, skip_byte_indices))
152 .map(|(idx, _)| data.len() - idx - window_size)
153 .ok_or(ByteDataError::FindByteError)
154}
155
156const HEX_DELIM: &str = r"\x";
157pub fn parse_string_to_bytes(data: &str) -> Vec<u8> {
158 if data.starts_with(HEX_DELIM) {
159 let split_data: Vec<&str> = data.split(HEX_DELIM).filter(|c| !c.is_empty()).collect();
160 let byte_data: Vec<u8> = split_data
161 .iter()
162 .filter_map(|c| u8::from_str_radix(c, 16).ok())
163 .collect();
164
165 if byte_data.len() == split_data.len() {
166 return byte_data;
167 }
168 }
169
170 Vec::from(data.as_bytes())
171}
172
173pub fn parse_string_to_read_delimiter(data: &str) -> (Vec<u8>, Vec<usize>) {
174 if data.starts_with(HEX_DELIM) {
175 let split_data: Vec<&str> = data.split(HEX_DELIM).filter(|c| !c.is_empty()).collect();
176 let byte_data: Vec<u8> = split_data
177 .iter()
178 .filter_map(|c| u8::from_str_radix(c, 16).ok())
179 .collect();
180
181 let skip_bytes: Vec<usize> = split_data
182 .iter()
183 .enumerate()
184 .filter_map(|(i, c)| if *c == "**" { Some(i) } else { None })
185 .collect();
186
187 if byte_data.len() + skip_bytes.len() == split_data.len() {
188 return (byte_data, skip_bytes);
189 }
190 }
191
192 (Vec::from(data.as_bytes()), Vec::new())
193}
194
195pub const BUFF_SIZE_BYTES: usize = 1024;
196
197use byteorder::ByteOrder;
198
199pub fn try_unpack_data<Endian: ByteOrder>(
200 buf: &[u8],
201 data_type: DataType,
202) -> Result<f64, ByteDataError> {
203 if buf.len() < data_type.byte_size() {
204 return Err(ByteDataError::UnpackError);
205 }
206 let val = match data_type {
207 DataType::U8 => buf[0] as f64,
208 DataType::I8 => buf[0] as i8 as f64,
209 DataType::U16 => Endian::read_u16(buf) as f64,
210 DataType::I16 => Endian::read_i16(buf) as f64,
211 DataType::U24 => Endian::read_u24(buf) as f64,
212 DataType::I24 => Endian::read_i24(buf) as f64,
213 DataType::U32 => Endian::read_u32(buf) as f64,
214 DataType::I32 => Endian::read_i32(buf) as f64,
215 DataType::U48 => Endian::read_u48(buf) as f64,
216 DataType::I48 => Endian::read_i48(buf) as f64,
217 DataType::U64 => Endian::read_u64(buf) as f64,
218 DataType::I64 => Endian::read_i64(buf) as f64,
219 DataType::U128 => Endian::read_u128(buf) as f64,
220 DataType::I128 => Endian::read_i128(buf) as f64,
221 DataType::F32 => Endian::read_f32(buf) as f64,
222 DataType::F64 => Endian::read_f64(buf),
223 };
224 Ok(val)
225}
226
227pub fn try_pack_data<Endian: ByteOrder>(
228 buf: &mut [u8],
229 value: f64,
230 data_type: DataType,
231) -> Result<usize, ByteDataError> {
232 if buf.len() < data_type.byte_size() {
233 return Err(ByteDataError::PackError);
234 }
235 match data_type {
236 DataType::U8 => buf[0] = value as u8,
237 DataType::I8 => buf[0] = value as i8 as u8,
238 DataType::U16 => Endian::write_u16(buf, value as u16),
239 DataType::I16 => Endian::write_i16(buf, value as i16),
240 DataType::U24 => Endian::write_u24(buf, value as u32),
241 DataType::I24 => Endian::write_i24(buf, value as i32),
242 DataType::U32 => Endian::write_u32(buf, value as u32),
243 DataType::I32 => Endian::write_i32(buf, value as i32),
244 DataType::U48 => Endian::write_u48(buf, value as u64),
245 DataType::I48 => Endian::write_i48(buf, value as i64),
246 DataType::U64 => Endian::write_u64(buf, value as u64),
247 DataType::I64 => Endian::write_i64(buf, value as i64),
248 DataType::U128 => Endian::write_u128(buf, value as u128),
249 DataType::I128 => Endian::write_i128(buf, value as i128),
250 DataType::F32 => Endian::write_f32(buf, value as f32),
251 DataType::F64 => Endian::write_f64(buf, value),
252 };
253 Ok(data_type.byte_size())
254}
255
256#[cfg(test)]
257mod tests {
258 use super::*;
259 use alloc::string::ToString;
260 use alloc::vec;
261 use byteorder::BigEndian;
262
263 #[test]
264 fn test_parse_byte_data_spec() {
265 let input = vec![
266 "U8:BigEndian".to_string(),
267 "I16:LittleEndian".to_string(),
268 "F32:BigEndian".to_string(),
269 ];
270
271 let expected = vec![
272 (DataType::U8, ByteOrderSpec::BigEndian),
273 (DataType::I16, ByteOrderSpec::LittleEndian),
274 (DataType::F32, ByteOrderSpec::BigEndian),
275 ];
276
277 let output = parse_byte_data_spec(&input);
278
279 assert_eq!(output, expected);
280 }
281
282 #[test]
283 fn test_compare_bytes() {
284 let result = compare_bytes(b"Hello, world!", b"Hello, world!", &[]);
285 assert!(result);
286
287 let result = compare_bytes(b"Hello, world!", b"Hello, wor", &[]);
288 assert!(!result);
289
290 let result = compare_bytes(b"012345", b"045", &[1, 2, 3]);
291 assert!(result);
292
293 let result = compare_bytes(b"012345", b"0c45", &[1, 2]);
294 assert!(!result);
295 }
296
297 #[test]
298 fn test_find_all_bytes_idx() {
299 let data = b"Hello, world! This is an example of finding bytes.";
300 let pattern = b"l";
301 let expected = vec![2, 3, 10, 30];
302 let result = find_all_bytes_idx(data, pattern, &[]);
303 assert_eq!(result, expected);
304 }
305
306 #[test]
307 fn test_find_all_bytes_idx_skip_indices() {
308 let data = b"aaa123aba123aca123";
309 let pattern = b"aa";
310 let expected = vec![0, 6, 12];
311 let result = find_all_bytes_idx(data, pattern, &[1]);
312 assert_eq!(result, expected);
313 }
314
315 #[test]
316 fn test_rfind_all_bytes_idx() {
317 let data = b"Hello, world! This is an example of finding bytes.";
318 let pattern = b"l";
319 let expected = vec![30, 10, 3, 2];
320 let result = rfind_all_bytes_idx(data, pattern, &[]);
321 assert_eq!(result, expected);
322 }
323
324 #[test]
325 fn test_rfind_all_bytes_idx_skip_indices() {
326 let data = b"aaa123aba123aca123";
327 let pattern = b"aa";
328 let expected = vec![12, 6, 0];
329 let result = rfind_all_bytes_idx(data, pattern, &[1]);
330 assert_eq!(result, expected);
331 }
332
333 #[test]
334 fn test_find_bytes_idx() {
335 let data = b"Hello, world! This is an example of finding bytes.";
336 let pattern = b"world";
337 let expected = Ok(7);
338 let result = find_bytes_idx(data, pattern, &[]);
339 assert_eq!(result, expected);
340 }
341
342 #[test]
343 fn test_find_bytes_idx_skip_indices() {
344 let data = b"aaa123aba123aca123";
345 let pattern = b"aa";
346 let expected = Ok(0);
347 let result = find_bytes_idx(data, pattern, &[1]);
348 assert_eq!(result, expected);
349 }
350
351 #[test]
352 fn test_rfind_bytes_idx() {
353 let data = b"Hello, world! This is an example of finding bytes.";
354 let pattern = b"world";
355 let expected = Ok(7);
356 let result = rfind_bytes_idx(data, pattern, &[]);
357 assert_eq!(result, expected);
358 }
359
360 #[test]
361 fn test_rfind_bytes_idx_skip_indices() {
362 let data = b"aaa123aba123aca123";
363 let pattern = b"aa";
364 let expected = Ok(12);
365 let result = rfind_bytes_idx(data, pattern, &[1]);
366 assert_eq!(result, expected);
367 }
368
369 #[test]
370 fn test_parse_string_to_bytes() {
371 let input = r"\x48\x65\x6C\x6C\x6F\x2C\x20\x77\x6F\x72\x6C\x64\x21";
372 let expected = b"Hello, world!".to_vec();
373 let result = parse_string_to_bytes(input);
374 assert_eq!(result, expected);
375 }
376
377 #[test]
378 fn test_parse_string_to_read_delimiter() {
379 let input = r"\x48\x65\x**\x6c\x**\x2C";
380 let expected = (b"\x48\x65\x6c\x2C".to_vec(), vec![2, 4]);
381 let result = parse_string_to_read_delimiter(input);
382 assert_eq!(result, expected);
383 }
384
385 #[test]
386 fn test_try_unpack_data_and_try_pack_data() {
387 let input: f64 = 1234.5678;
388 let dt = DataType::F64;
389 let mut packed_data = vec![0; dt.byte_size()];
390
391 try_pack_data::<BigEndian>(&mut packed_data, input, dt).unwrap();
392 let unpacked_data = try_unpack_data::<BigEndian>(&packed_data, dt).unwrap();
393
394 assert_eq!(input, unpacked_data);
395 }
396}