1use super::common::Utils;
4use crate::errors::ByteArrayError;
5use crate::errors::ByteArrayError::{InvalidBinaryChar, InvalidHexChar};
6use crate::errors::ByteArraySecurityError::DataRemnanceRisk;
7use alloc::vec;
8use alloc::vec::Vec;
9use core::ops::{Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo};
10
11#[derive(Default, 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 {
26 Self {
27 bytes: Vec::with_capacity(size_in_bytes),
28 }
29 }
30
31 #[deprecated(
57 since = "0.3.3",
58 note = "This will be renamed to with_zeros at a future version"
59 )]
60 pub fn fill_zeros(self) -> Self {
61 if self.bytes.capacity() == 0 {
62 self
63 } else {
64 ByteArray {
65 bytes: vec![0u8; self.bytes.capacity()],
66 }
67 }
68 }
69
70 #[deprecated(
98 since = "0.3.3",
99 note = "This will be renamed to with_value at a future version"
100 )]
101 pub fn fill_with(self, value: u8) -> Self {
102 if self.bytes.capacity() == 0 {
103 self
104 } else {
105 ByteArray {
106 bytes: vec![value; self.bytes.capacity()],
107 }
108 }
109 }
110
111 pub fn from_hex(hex_str: &str) -> Result<Self, ByteArrayError> {
121 if hex_str.is_empty() {
122 return Err(ByteArrayError::EmptyInput);
123 }
124
125 let bytes: Vec<u8> = hex_str.bytes().filter(|&b| b != b'_').collect();
127
128 if let Some(&invalid) = bytes.iter().find(|&&b| !b.is_ascii_hexdigit()) {
130 return Err(InvalidHexChar(invalid as char));
131 }
132
133 let hex_count = bytes.len();
134 let byte_count = hex_count / 2 + hex_count % 2;
135 let mut ret = ByteArray::with_capacity(byte_count);
136
137 let mut start = 0;
138
139 if hex_count % 2 == 1 {
141 ret.bytes
142 .push(Utils::hex_char_to_nibble_unchecked(bytes[0]));
143 start = 1;
144 }
145
146 for i in (start..hex_count).step_by(2) {
148 let byte_val = Utils::hex_char_to_nibble_unchecked(bytes[i]) << 4
149 | Utils::hex_char_to_nibble_unchecked(bytes[i + 1]);
150 ret.bytes.push(byte_val);
151 }
152
153 Ok(ret)
154 }
155
156 pub fn from_bin(bin_str: &str) -> Result<Self, ByteArrayError> {
166 if bin_str.is_empty() {
167 return Err(ByteArrayError::EmptyInput);
168 }
169
170 let bytes: Vec<u8> = bin_str.bytes().filter(|&b| b != b'_').collect();
172
173 if let Some(&invalid) = bytes.iter().find(|&&b| b != b'0' && b != b'1') {
175 return Err(InvalidBinaryChar(invalid as char));
176 }
177
178 let bit_count = bytes.len();
179 let byte_count = bit_count.div_ceil(8);
180 let mut ret = ByteArray::with_capacity(byte_count);
181
182 let rem = bit_count % 8;
183
184 let start = if rem != 0 {
186 let mut byte = 0u8;
187 #[allow(clippy::needless_range_loop)] for i in 0..rem {
189 let bit_value = bytes[i] - b'0';
190 byte |= bit_value << (rem - 1 - i);
191 }
192 ret.bytes.push(byte);
193 rem
194 } else {
195 0
196 };
197
198 for i in (start..bit_count).step_by(8) {
200 let mut byte = 0u8;
201
202 for j in 0..8 {
203 let bit_value = bytes[i + j] - b'0';
204 byte |= bit_value << (7 - j);
205 }
206
207 ret.bytes.push(byte);
208 }
209
210 Ok(ret)
211 }
212
213 pub fn init_zeros(count: usize) -> Self {
217 ByteArray {
218 bytes: vec![0u8; count],
219 }
220 }
221
222 pub fn init_value(value: u8, count: usize) -> Self {
226 ByteArray {
227 bytes: vec![value; count],
228 }
229 }
230
231 pub fn as_bytes(&self) -> &[u8] {
250 &self.bytes
251 }
252
253 #[doc(hidden)]
255 #[inline(always)]
256 fn combine(
257 lhs: ByteArray,
258 rhs: ByteArray,
259 prealloc_cap: usize,
260 ) -> Result<Self, ByteArrayError> {
261 const CAP_SAFETY_EXTENSION: usize = 10;
262 let total_cap = prealloc_cap + CAP_SAFETY_EXTENSION;
263 let mut buf = Vec::<u8>::with_capacity(total_cap);
264
265 let addr_pre_extend = buf.as_ptr();
266 buf.extend_from_slice(lhs.as_bytes());
267 if addr_pre_extend != buf.as_ptr() {
268 return Err(DataRemnanceRisk.into());
269 }
270 buf.extend_from_slice(rhs.as_bytes());
271 if addr_pre_extend != buf.as_ptr() {
272 return Err(DataRemnanceRisk.into());
273 }
274
275 drop(lhs);
278 drop(rhs);
279
280 Ok(ByteArray::from(buf))
281 }
282
283 #[inline]
307 pub fn try_extend(self, other: ByteArray) -> Result<Self, ByteArrayError> {
308 let cap = self.bytes.len() + other.bytes.len();
309 Self::combine(self, other, cap)
310 }
311
312 #[inline]
335 pub fn try_extend_with_preserve_cap(self, other: ByteArray) -> Result<Self, ByteArrayError> {
336 let cap = self.bytes.capacity() + other.bytes.capacity();
337 Self::combine(self, other, cap)
338 }
339}
340
341impl Index<usize> for ByteArray {
344 type Output = u8;
345
346 fn index(&self, index: usize) -> &Self::Output {
350 &self.bytes[index]
351 }
352}
353
354impl IndexMut<usize> for ByteArray {
355 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
359 &mut self.bytes[index]
360 }
361}
362
363impl Index<Range<usize>> for ByteArray {
364 type Output = [u8];
365
366 fn index(&self, range: Range<usize>) -> &Self::Output {
367 &self.bytes[range]
368 }
369}
370
371impl Index<RangeFrom<usize>> for ByteArray {
372 type Output = [u8];
373
374 fn index(&self, range: RangeFrom<usize>) -> &Self::Output {
375 &self.bytes[range] }
377}
378impl Index<RangeTo<usize>> for ByteArray {
379 type Output = [u8];
380
381 fn index(&self, range: RangeTo<usize>) -> &Self::Output {
382 &self.bytes[range] }
384}
385impl Index<RangeInclusive<usize>> for ByteArray {
386 type Output = [u8];
387
388 fn index(&self, range: RangeInclusive<usize>) -> &Self::Output {
389 &self.bytes[range] }
391}
392impl Index<RangeFull> for ByteArray {
393 type Output = [u8];
394
395 fn index(&self, range: RangeFull) -> &Self::Output {
396 &self.bytes[range] }
398}
399
400impl IndexMut<Range<usize>> for ByteArray {
401 fn index_mut(&mut self, range: Range<usize>) -> &mut Self::Output {
402 &mut self.bytes[range]
403 }
404}
405
406impl IndexMut<RangeFrom<usize>> for ByteArray {
407 fn index_mut(&mut self, range: RangeFrom<usize>) -> &mut Self::Output {
408 &mut self.bytes[range]
409 }
410}
411impl IndexMut<RangeTo<usize>> for ByteArray {
412 fn index_mut(&mut self, range: RangeTo<usize>) -> &mut Self::Output {
413 &mut self.bytes[range]
414 }
415}
416impl IndexMut<RangeInclusive<usize>> for ByteArray {
417 fn index_mut(&mut self, range: RangeInclusive<usize>) -> &mut Self::Output {
418 &mut self.bytes[range] }
420}
421impl IndexMut<RangeFull> for ByteArray {
422 fn index_mut(&mut self, range: RangeFull) -> &mut Self::Output {
423 &mut self.bytes[range] }
425}
426
427impl AsRef<[u8]> for ByteArray {
428 fn as_ref(&self) -> &[u8] {
429 self.as_bytes()
430 }
431}
432
433impl AsMut<[u8]> for ByteArray {
434 fn as_mut(&mut self) -> &mut [u8] {
435 &mut self.bytes
436 }
437}
438
439#[cfg(test)]
440mod tests {
441 use super::*;
442 use crate::try_hex;
443 use alloc::vec;
444 use core::str::FromStr;
445
446 fn is_normal<T: Sized + Send + Sync + Unpin>() {}
447
448 #[test]
449 fn test_thread_safety_autotraits() {
450 is_normal::<ByteArray>();
451 }
452
453 #[test]
454 fn test_hex_string_constructor() {
455 let b1: ByteArray = "0xfe81eabd5".parse().unwrap();
456
457 assert_eq!(b1.len(), 5);
458 assert_eq!(b1.bytes, vec![0x0f, 0xe8, 0x1e, 0xab, 0xd5]);
459 }
460
461 #[test]
462 fn test_ba_with_capacity() {
463 let arr = ByteArray::with_capacity(10);
464
465 assert_eq!(arr.bytes.capacity(), 10);
466 assert!(ByteArray::try_from(arr).is_ok());
467 }
468
469 #[test]
470 fn test_with_hex() {
471 let arr = ByteArray::from_hex("ffabc");
472
473 assert_eq!(arr.unwrap().bytes, vec![0x0f, 0xfa, 0xbc]);
474 }
475
476 #[test]
477 fn test_with_bin_less_than_8() {
478 let arr = ByteArray::from_bin("1101111").unwrap();
479 assert_eq!(arr.bytes, vec![0x6f]);
480 }
481
482 #[test]
483 fn test_with_bin_more_than_8() {
484 let arr = ByteArray::from_bin("110111010110111").unwrap();
485 assert_eq!(arr.bytes, vec![0x6e, 0xb7]);
486 }
487
488 #[test]
489 fn test_equality_derives() {
490 let arr: ByteArray = "0xffab12345ffaf".parse().unwrap();
491 let arr_2 = ByteArray::from_hex("ffab12345ffafdeadbeef").unwrap();
492 let arr_3 = arr.clone();
493
494 assert_ne!(arr.bytes, arr_2.bytes);
495 assert_eq!(arr.bytes, arr_3.bytes);
496 }
497
498 #[test]
499 fn test_init_zeros() {
500 let arr = ByteArray::init_zeros(8);
501
502 assert_eq!(arr.bytes, [0u8, 0, 0, 0, 0, 0, 0, 0]);
503 }
504
505 #[test]
506 fn test_init_value() {
507 let arr = ByteArray::init_value(254, 8);
508
509 assert_eq!(arr.bytes, [254, 254, 254, 254, 254, 254, 254, 254]);
510 }
511
512 #[test]
513 fn test_mutable_idx_accessor() {
514 let mut arr: ByteArray = "0xffab1245".parse().unwrap();
515
516 arr[3] = 0xbe;
517 arr[1] = 0xfa;
518
519 assert_eq!(arr.bytes, ByteArray::from_str("0xfffa12be").unwrap().bytes);
520 }
521
522 #[test]
523 #[allow(deprecated)]
524 fn test_fill_zeros() {
525 let arr = ByteArray::default().fill_zeros();
526 assert!(arr.as_bytes().is_empty());
527
528 let arr = ByteArray::with_capacity(5).fill_zeros();
529 assert_eq!(arr.as_bytes(), [0u8, 0, 0, 0, 0]);
530
531 let arr = ByteArray::with_capacity(7).fill_zeros();
532
533 assert_eq!(arr.as_bytes(), [0u8, 0, 0, 0, 0, 0, 0])
534 }
535
536 #[test]
537 #[allow(deprecated)]
538 fn test_fill_with() {
539 let arr = ByteArray::default().fill_zeros();
540 assert!(arr.as_bytes().is_empty());
541
542 let arr = ByteArray::with_capacity(5).fill_with(126);
543 assert_eq!(arr.as_bytes(), [126u8, 126, 126, 126, 126]);
544
545 let arr = ByteArray::with_capacity(7).fill_with(5);
546
547 assert_eq!(arr.as_bytes(), [5u8, 5, 5, 5, 5, 5, 5]);
548 }
549
550 #[test]
551 fn test_hex_with_underscores() {
552 let arr = ByteArray::from_hex("de_ad_be_ef").unwrap();
553 assert_eq!(arr.as_bytes(), [0xde, 0xad, 0xbe, 0xef]);
554 }
555
556 #[test]
557 fn test_bin_with_underscores() {
558 let arr = ByteArray::from_bin("1010_0101").unwrap();
559 assert_eq!(arr.as_bytes(), [0xa5]);
560 }
561
562 #[test]
563 fn test_bin_with_underscores_odd_length() {
564 let arr = ByteArray::from_bin("110_1111").unwrap();
565 assert_eq!(arr.as_bytes(), [0x6f]);
566 }
567
568 #[test]
569 #[should_panic]
570 fn test_as_mut_empty() {
571 let mut bytes = ByteArray::default();
572
573 let mut_ref = bytes.as_mut();
574
575 mut_ref[0] = 0x00;
576 }
577
578 #[test]
579 fn test_ranges() {
580 let bytes = try_hex!("ff_aa_fa_b8_ca_12_15_5a_5c_6f").unwrap();
581
582 assert_eq!(bytes[1..2], [0xaa]);
583 assert_eq!(bytes[0..=2], [0xff, 0xaa, 0xfa]);
584 assert_eq!(bytes[6..], [0x15, 0x5a, 0x5c, 0x6f]);
585 assert_eq!(bytes[..3], [0xff, 0xaa, 0xfa]);
586 assert_eq!(
587 bytes[..],
588 [0xff, 0xaa, 0xfa, 0xb8, 0xca, 0x12, 0x15, 0x5a, 0x5c, 0x6f]
589 );
590 }
591
592 #[test]
593 fn test_ranges_mut() {
594 let mut bytes = try_hex!("ff_aa_fa_b8_ca_12_15_5a_5c_6f").unwrap();
595
596 let slice = &mut bytes[1..3];
597 slice[0] = 0x00;
598 slice[1] = 0x01;
599 let expected: ByteArray = "0xff_00_01_b8_ca_12_15_5a_5c_6f".parse().unwrap();
600
601 assert_eq!(bytes, expected);
602
603 let slice = &mut bytes[0..=2];
604 slice[0] = 0x12;
605 slice[1] = 0xab;
606 slice[2] = 0xbc;
607
608 let expected: ByteArray = "0x12_ab_bc_b8_ca_12_15_5a_5c_6f".parse().unwrap();
609
610 assert_eq!(bytes, expected);
611
612 let slice = &mut bytes[6..];
613 slice[0] = 0x01;
614 slice[1] = 0x02;
615 slice[2] = 0x03;
616 slice[3] = 0x04;
617
618 let expected: ByteArray = "0x12_ab_bc_b8_ca_12_01_02_03_04".parse().unwrap();
619
620 assert_eq!(bytes, expected);
621
622 let slice = &mut bytes[..3];
623 slice[0] = 0x00;
624 slice[1] = 0x02;
625 slice[2] = 0x03;
626
627 let expected: ByteArray = "0x00_02_03_b8_ca_12_01_02_03_04".parse().unwrap();
628
629 assert_eq!(bytes, expected);
630
631 let slice = &mut bytes[..];
632
633 slice.iter_mut().for_each(|e| *e = 0x01);
634
635 let expected: ByteArray = "0x01_01_01_01_01_01_01_01_01_01".parse().unwrap();
636
637 assert_eq!(bytes, expected);
638 }
639
640 #[test]
641 fn test_as_ref() {
642 let bytes: ByteArray = "0x01_02_03_04_05_06_07_08".parse().unwrap();
643 let bytes_ref = bytes.as_ref();
644
645 assert_eq!(bytes.as_bytes(), bytes_ref);
646 }
647
648 #[test]
649 fn test_as_mut() {
650 let mut bytes: ByteArray = "0x01_02_03_04_05_06_07_08".parse().unwrap();
651
652 let mut_ref = bytes.as_mut();
653
654 mut_ref[0] = 0xFF;
655 mut_ref[5] = 0xab;
656 mut_ref[7] = 0x1a;
657
658 assert_eq!(
659 bytes.as_bytes(),
660 [0xff, 0x02, 0x03, 0x04, 0x05, 0xab, 0x07, 0x1a]
661 )
662 }
663
664 #[test]
667 fn test_try_extend_both_empty() {
668 let arr1 = ByteArray::default();
669 let arr2 = ByteArray::default();
670 let result = arr1.try_extend(arr2).unwrap();
671 assert_eq!(result.len(), 0);
672 }
673
674 #[test]
675 fn test_try_extend_first_empty() {
676 let arr1 = ByteArray::default();
677 let arr2 = ByteArray::from_hex("beef").unwrap();
678 let result = arr1.try_extend(arr2).unwrap();
679 assert_eq!(result.as_bytes(), [0xbe, 0xef]);
680 }
681
682 #[test]
683 fn test_try_extend_second_empty() {
684 let arr1 = ByteArray::from_hex("dead").unwrap();
685 let arr2 = ByteArray::default();
686 let result = arr1.try_extend(arr2).unwrap();
687 assert_eq!(result.as_bytes(), [0xde, 0xad]);
688 }
689
690 #[test]
691 fn test_try_extend_small_arrays() {
692 let arr1 = ByteArray::from_hex("aa").unwrap();
693 let arr2 = ByteArray::from_hex("bb").unwrap();
694 let result = arr1.try_extend(arr2).unwrap();
695 assert_eq!(result.as_bytes(), [0xaa, 0xbb]);
696 assert_eq!(result.len(), 2);
697 }
698
699 #[test]
700 fn test_try_extend_preserve_cap_empty_with_capacity() {
701 let arr1 = ByteArray::with_capacity(50); let arr2 = ByteArray::with_capacity(30); let result = arr1.try_extend_with_preserve_cap(arr2).unwrap();
704
705 assert_eq!(result.len(), 0);
706 assert_eq!(result.bytes.capacity(), 90); }
708
709 #[test]
710 fn test_try_extend_capacity_based_on_length() {
711 let arr1 = ByteArray::from_hex("aa").unwrap(); let arr2 = ByteArray::from_hex("bb").unwrap(); let result = arr1.try_extend(arr2).unwrap();
714
715 assert_eq!(result.bytes.capacity(), 12);
717 assert_eq!(result.as_bytes(), [0xaa, 0xbb]);
718 }
719
720 #[test]
721 fn test_try_extend_chaining() {
722 let arr1 = ByteArray::from_hex("aa").unwrap();
723 let arr2 = ByteArray::from_hex("bb").unwrap();
724 let arr3 = ByteArray::from_hex("cc").unwrap();
725
726 let result = arr1.try_extend(arr2).unwrap().try_extend(arr3).unwrap();
727 assert_eq!(result.as_bytes(), [0xaa, 0xbb, 0xcc]);
728 }
729}