byte_array_ops/byte_array/
model.rs1use super::common::Utils;
4use crate::byte_array::errors::ByteArrayError;
5use crate::byte_array::errors::ByteArrayError::{InvalidBinaryChar, InvalidHexChar};
6use alloc::vec;
7use alloc::vec::Vec;
8use core::cmp::PartialEq;
9use core::ops::{Index, IndexMut};
10
11#[derive(Default, PartialEq, Eq, Clone)] pub struct ByteArray {
14 pub(crate) bytes: Vec<u8>,
15}
16
17impl ByteArray {
18 pub fn new() -> Self {
21 ByteArray { bytes: vec![] }
22 }
23
24 pub fn with_capacity(size_in_bytes: usize) -> Self {
27 Self {
28 bytes: Vec::with_capacity(size_in_bytes),
29 }
30 }
31
32 pub fn fill_zeros(self) -> Self {
58 if self.bytes.capacity() == 0 {
59 self
60 } else {
61 ByteArray {
62 bytes: vec![0u8; self.bytes.capacity()],
63 }
64 }
65 }
66
67 pub fn fill_with(self, value: u8) -> Self {
95 if self.bytes.capacity() == 0 {
96 self
97 } else {
98 ByteArray {
99 bytes: vec![value; self.bytes.capacity()],
100 }
101 }
102 }
103
104 pub fn from_hex(hex_str: &str) -> Result<Self, ByteArrayError> {
114 if hex_str.is_empty() {
115 return Err(ByteArrayError::EmptyInput);
116 }
117
118 let bytes: Vec<u8> = hex_str.bytes().filter(|&b| b != b'_').collect();
120
121 if let Some(&invalid) = bytes.iter().find(|&&b| !b.is_ascii_hexdigit()) {
123 return Err(InvalidHexChar(invalid as char));
124 }
125
126 let hex_count = bytes.len();
127 let byte_count = hex_count / 2 + hex_count % 2;
128 let mut ret = ByteArray::with_capacity(byte_count);
129
130 let mut start = 0;
131
132 if hex_count % 2 == 1 {
134 ret.bytes
135 .push(Utils::hex_char_to_nibble_unchecked(bytes[0]));
136 start = 1;
137 }
138
139 for i in (start..hex_count).step_by(2) {
141 let byte_val = Utils::hex_char_to_nibble_unchecked(bytes[i]) << 4
142 | Utils::hex_char_to_nibble_unchecked(bytes[i + 1]);
143 ret.bytes.push(byte_val);
144 }
145
146 Ok(ret)
147 }
148
149 pub fn from_bin(bin_str: &str) -> Result<Self, ByteArrayError> {
159 if bin_str.is_empty() {
160 return Err(ByteArrayError::EmptyInput);
161 }
162
163 let bytes: Vec<u8> = bin_str.bytes().filter(|&b| b != b'_').collect();
165
166 if let Some(&invalid) = bytes.iter().find(|&&b| b != b'0' && b != b'1') {
168 return Err(InvalidBinaryChar(invalid as char));
169 }
170
171 let bit_count = bytes.len();
172 let byte_count = bit_count.div_ceil(8);
173 let mut ret = ByteArray::with_capacity(byte_count);
174
175 let rem = bit_count % 8;
176
177 let start = if rem != 0 {
179 let mut byte = 0u8;
180 #[allow(clippy::needless_range_loop)] for i in 0..rem {
182 let bit_value = bytes[i] - b'0';
183 byte |= bit_value << (rem - 1 - i);
184 }
185 ret.bytes.push(byte);
186 rem
187 } else {
188 0
189 };
190
191 for i in (start..bit_count).step_by(8) {
193 let mut byte = 0u8;
194
195 for j in 0..8 {
196 let bit_value = bytes[i + j] - b'0';
197 byte |= bit_value << (7 - j);
198 }
199
200 ret.bytes.push(byte);
201 }
202
203 Ok(ret)
204 }
205
206 pub fn init_zeros(count: usize) -> Self {
210 ByteArray {
211 bytes: vec![0u8; count],
212 }
213 }
214
215 pub fn init_value(value: u8, count: usize) -> Self {
219 ByteArray {
220 bytes: vec![value; count],
221 }
222 }
223
224 pub fn as_bytes(&self) -> &[u8] {
254 &self.bytes
255 }
256
257 pub fn len(&self) -> usize {
260 self.bytes.len()
261 }
262
263 pub fn is_empty(&self) -> bool {
266 self.bytes.is_empty()
267 }
268
269 #[cfg(feature = "experimental")]
270 pub fn resize(&mut self, new_capacity: usize, value: u8) {
271 unimplemented!(
272 "this is insecure and must find a way on how to handle this in a more secure fashion"
273 );
274 self.bytes.resize(new_capacity, value);
275 }
276
277 #[cfg(feature = "experimental")]
292 pub fn try_push(&mut self, value: u8) {
293 self.bytes.push(value);
294 }
295}
296
297impl Index<usize> for ByteArray {
300 type Output = u8;
301
302 fn index(&self, index: usize) -> &Self::Output {
306 &self.bytes[index]
307 }
308}
309
310impl IndexMut<usize> for ByteArray {
311 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
315 &mut self.bytes[index]
316 }
317}
318
319impl ByteArray {
320 pub fn get(&self, index: usize) -> Option<&u8> {
321 self.bytes.get(index)
322 }
323}
324
325impl AsRef<[u8]> for ByteArray {
326 fn as_ref(&self) -> &[u8] {
327 self.as_bytes()
328 }
329}
330
331impl AsMut<[u8]> for ByteArray {
332 fn as_mut(&mut self) -> &mut [u8] {
333 &mut self.bytes
334 }
335}
336
337#[cfg(test)]
338mod tests {
339 use super::*;
340 use alloc::vec;
341 use core::str::FromStr;
342
343 #[test]
344 fn test_hex_string_constructor() {
345 let b1: ByteArray = "0xfe81eabd5".parse().unwrap();
346
347 assert_eq!(b1.len(), 5);
348 assert_eq!(b1.bytes, vec![0x0f, 0xe8, 0x1e, 0xab, 0xd5]);
349 }
350
351 #[test]
352 fn test_ba_with_capacity() {
353 let arr = ByteArray::with_capacity(10);
354
355 assert_eq!(arr.bytes.capacity(), 10);
356 assert!(ByteArray::try_from(arr).is_ok());
357 }
358
359 #[test]
360 fn test_with_hex() {
361 let arr = ByteArray::from_hex("ffabc");
362
363 assert_eq!(arr.unwrap().bytes, vec![0x0f, 0xfa, 0xbc]);
364 }
365
366 #[test]
367 fn test_with_bin_less_than_8() {
368 let arr = ByteArray::from_bin("1101111").unwrap();
369 assert_eq!(arr.bytes, vec![0x6f]);
370 }
371
372 #[test]
373 fn test_with_bin_more_than_8() {
374 let arr = ByteArray::from_bin("110111010110111").unwrap();
375 assert_eq!(arr.bytes, vec![0x6e, 0xb7]);
376 }
377
378 #[test]
379 fn test_len() {
380 let arr = ByteArray::from_hex("ffab12345bc").expect("error converting");
381
382 assert_eq!(arr.len(), 6);
383 }
384
385 #[test]
386 fn test_is_empty() {
387 let arr = ByteArray::default();
388 assert_eq!(arr.is_empty(), true);
389
390 let arr = ByteArray::from_hex("bb").expect("error converting");
391
392 assert_eq!(arr.is_empty(), false);
393 }
394
395 #[test]
396 fn test_equality_derives() {
397 let arr: ByteArray = "0xffab12345ffaf".parse().unwrap();
398 let arr_2 = ByteArray::from_hex("ffab12345ffafdeadbeef").unwrap();
399 let arr_3 = arr.clone();
400
401 assert_ne!(arr.bytes, arr_2.bytes);
402 assert_eq!(arr.bytes, arr_3.bytes);
403 }
404
405 #[test]
406 fn test_init_zeros() {
407 let arr = ByteArray::init_zeros(8);
408
409 assert_eq!(arr.bytes, [0u8, 0, 0, 0, 0, 0, 0, 0]);
410 }
411
412 #[test]
413 fn test_init_value() {
414 let arr = ByteArray::init_value(254, 8);
415
416 assert_eq!(arr.bytes, [254, 254, 254, 254, 254, 254, 254, 254]);
417 }
418
419 #[test]
420 fn test_mutable_idx_accessor() {
421 let mut arr: ByteArray = "0xffab1245".parse().unwrap();
422
423 arr[3] = 0xbe;
424 arr[1] = 0xfa;
425
426 assert_eq!(arr.bytes, ByteArray::from_str("0xfffa12be").unwrap().bytes);
427 }
428
429 #[test]
430 fn test_fill_zeros() {
431 let arr = ByteArray::default().fill_zeros();
432 assert!(arr.as_bytes().is_empty());
433
434 let arr = ByteArray::with_capacity(5).fill_zeros();
435 assert_eq!(arr.as_bytes(), [0u8, 0, 0, 0, 0]);
436
437 let arr = ByteArray::with_capacity(7).fill_zeros();
438
439 assert_eq!(arr.as_bytes(), [0u8, 0, 0, 0, 0, 0, 0])
440 }
441
442 #[test]
443 fn test_fill_with() {
444 let arr = ByteArray::default().fill_zeros();
445 assert!(arr.as_bytes().is_empty());
446
447 let arr = ByteArray::with_capacity(5).fill_with(126);
448 assert_eq!(arr.as_bytes(), [126u8, 126, 126, 126, 126]);
449
450 let arr = ByteArray::with_capacity(7).fill_with(5);
451
452 assert_eq!(arr.as_bytes(), [5u8, 5, 5, 5, 5, 5, 5]);
453 }
454
455 #[test]
456 #[cfg(feature = "experimental")]
457 fn test_push_element() {
458 let mut arr: ByteArray = vec![1, 2].into();
459
460 arr.try_push(0xab);
461
462 assert_eq!(arr.as_bytes(), [1, 2, 0xab]);
463 }
464
465 #[test]
466 fn test_hex_with_underscores() {
467 let arr = ByteArray::from_hex("de_ad_be_ef").unwrap();
468 assert_eq!(arr.as_bytes(), [0xde, 0xad, 0xbe, 0xef]);
469 }
470
471 #[test]
472 fn test_bin_with_underscores() {
473 let arr = ByteArray::from_bin("1010_0101").unwrap();
474 assert_eq!(arr.as_bytes(), [0xa5]);
475 }
476
477 #[test]
478 fn test_bin_with_underscores_odd_length() {
479 let arr = ByteArray::from_bin("110_1111").unwrap();
480 assert_eq!(arr.as_bytes(), [0x6f]);
481 }
482
483 #[test]
484 #[should_panic]
485 fn test_as_mut_empty() {
486 let mut bytes = ByteArray::default();
487
488 let mut_ref = bytes.as_mut();
489
490 mut_ref[0] = 0x00;
491 }
492
493 #[test]
494 fn test_as_ref() {
495 let bytes: ByteArray = "0x01_02_03_04_05_06_07_08".parse().unwrap();
496 let bytes_ref = bytes.as_ref();
497
498 assert_eq!(bytes.as_bytes(), bytes_ref);
499 }
500
501 #[test]
502 fn test_as_mut() {
503 let mut bytes: ByteArray = "0x01_02_03_04_05_06_07_08".parse().unwrap();
504
505 let mut_ref = bytes.as_mut();
506
507 mut_ref[0] = 0xFF;
508 mut_ref[5] = 0xab;
509 mut_ref[7] = 0x1a;
510
511 assert_eq!(
512 bytes.as_bytes(),
513 [0xff, 0x02, 0x03, 0x04, 0x05, 0xab, 0x07, 0x1a]
514 )
515 }
516}