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::cmp::PartialEq;
10use core::ops::{Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo};
11
12#[derive(Default, PartialEq, Eq, Clone)] pub struct ByteArray {
15 pub(crate) bytes: Vec<u8>,
16}
17
18impl ByteArray {
19 pub fn new() -> Self {
22 ByteArray { bytes: vec![] }
23 }
24
25 pub fn with_capacity(size_in_bytes: usize) -> Self {
27 Self {
28 bytes: Vec::with_capacity(size_in_bytes),
29 }
30 }
31
32 #[deprecated(
58 since = "0.3.3",
59 note = "This will be renamed to with_zeros at a future version"
60 )]
61 pub fn fill_zeros(self) -> Self {
62 if self.bytes.capacity() == 0 {
63 self
64 } else {
65 ByteArray {
66 bytes: vec![0u8; self.bytes.capacity()],
67 }
68 }
69 }
70
71 #[deprecated(
99 since = "0.3.3",
100 note = "This will be renamed to with_value at a future version"
101 )]
102 pub fn fill_with(self, value: u8) -> Self {
103 if self.bytes.capacity() == 0 {
104 self
105 } else {
106 ByteArray {
107 bytes: vec![value; self.bytes.capacity()],
108 }
109 }
110 }
111
112 pub fn from_hex(hex_str: &str) -> Result<Self, ByteArrayError> {
122 if hex_str.is_empty() {
123 return Err(ByteArrayError::EmptyInput);
124 }
125
126 let bytes: Vec<u8> = hex_str.bytes().filter(|&b| b != b'_').collect();
128
129 if let Some(&invalid) = bytes.iter().find(|&&b| !b.is_ascii_hexdigit()) {
131 return Err(InvalidHexChar(invalid as char));
132 }
133
134 let hex_count = bytes.len();
135 let byte_count = hex_count / 2 + hex_count % 2;
136 let mut ret = ByteArray::with_capacity(byte_count);
137
138 let mut start = 0;
139
140 if hex_count % 2 == 1 {
142 ret.bytes
143 .push(Utils::hex_char_to_nibble_unchecked(bytes[0]));
144 start = 1;
145 }
146
147 for i in (start..hex_count).step_by(2) {
149 let byte_val = Utils::hex_char_to_nibble_unchecked(bytes[i]) << 4
150 | Utils::hex_char_to_nibble_unchecked(bytes[i + 1]);
151 ret.bytes.push(byte_val);
152 }
153
154 Ok(ret)
155 }
156
157 pub fn from_bin(bin_str: &str) -> Result<Self, ByteArrayError> {
167 if bin_str.is_empty() {
168 return Err(ByteArrayError::EmptyInput);
169 }
170
171 let bytes: Vec<u8> = bin_str.bytes().filter(|&b| b != b'_').collect();
173
174 if let Some(&invalid) = bytes.iter().find(|&&b| b != b'0' && b != b'1') {
176 return Err(InvalidBinaryChar(invalid as char));
177 }
178
179 let bit_count = bytes.len();
180 let byte_count = bit_count.div_ceil(8);
181 let mut ret = ByteArray::with_capacity(byte_count);
182
183 let rem = bit_count % 8;
184
185 let start = if rem != 0 {
187 let mut byte = 0u8;
188 #[allow(clippy::needless_range_loop)] for i in 0..rem {
190 let bit_value = bytes[i] - b'0';
191 byte |= bit_value << (rem - 1 - i);
192 }
193 ret.bytes.push(byte);
194 rem
195 } else {
196 0
197 };
198
199 for i in (start..bit_count).step_by(8) {
201 let mut byte = 0u8;
202
203 for j in 0..8 {
204 let bit_value = bytes[i + j] - b'0';
205 byte |= bit_value << (7 - j);
206 }
207
208 ret.bytes.push(byte);
209 }
210
211 Ok(ret)
212 }
213
214 pub fn init_zeros(count: usize) -> Self {
218 ByteArray {
219 bytes: vec![0u8; count],
220 }
221 }
222
223 pub fn init_value(value: u8, count: usize) -> Self {
227 ByteArray {
228 bytes: vec![value; count],
229 }
230 }
231
232 pub fn as_bytes(&self) -> &[u8] {
251 &self.bytes
252 }
253
254 #[cfg(feature = "experimental")]
255 pub fn resize(&mut self, new_capacity: usize, value: u8) {
256 unimplemented!(
257 "this is insecure and must find a way on how to handle this in a more secure fashion"
258 );
259 self.bytes.resize(new_capacity, value);
260 }
261
262 #[cfg(feature = "experimental")]
277 pub fn try_push(&mut self, value: u8) {
278 self.bytes.push(value);
279 }
280
281 #[doc(hidden)]
283 #[inline(always)]
284 fn combine(
285 lhs: ByteArray,
286 rhs: ByteArray,
287 prealloc_cap: usize,
288 ) -> Result<Self, ByteArrayError> {
289 const CAP_SAFETY_EXTENSION: usize = 10;
290 let total_cap = prealloc_cap + CAP_SAFETY_EXTENSION;
291 let mut buf = Vec::<u8>::with_capacity(total_cap);
292
293 let addr_pre_extend = buf.as_ptr();
294 buf.extend_from_slice(lhs.as_bytes());
295 if addr_pre_extend != buf.as_ptr() {
296 return Err(DataRemnanceRisk.into());
297 }
298 buf.extend_from_slice(rhs.as_bytes());
299 if addr_pre_extend != buf.as_ptr() {
300 return Err(DataRemnanceRisk.into());
301 }
302
303 drop(lhs);
306 drop(rhs);
307
308 Ok(ByteArray::from(buf))
309 }
310
311 #[inline]
335 pub fn try_extend(self, other: ByteArray) -> Result<Self, ByteArrayError> {
336 let cap = self.bytes.len() + other.bytes.len();
337 Self::combine(self, other, cap)
338 }
339
340 #[inline]
363 pub fn try_extend_with_preserve_cap(self, other: ByteArray) -> Result<Self, ByteArrayError> {
364 let cap = self.bytes.capacity() + other.bytes.capacity();
365 Self::combine(self, other, cap)
366 }
367}
368
369impl Index<usize> for ByteArray {
372 type Output = u8;
373
374 fn index(&self, index: usize) -> &Self::Output {
378 &self.bytes[index]
379 }
380}
381
382impl IndexMut<usize> for ByteArray {
383 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
387 &mut self.bytes[index]
388 }
389}
390
391impl Index<Range<usize>> for ByteArray {
392 type Output = [u8];
393
394 fn index(&self, range: Range<usize>) -> &Self::Output {
395 &self.bytes[range]
396 }
397}
398
399impl Index<RangeFrom<usize>> for ByteArray {
400 type Output = [u8];
401
402 fn index(&self, range: RangeFrom<usize>) -> &Self::Output {
403 &self.bytes[range] }
405}
406impl Index<RangeTo<usize>> for ByteArray {
407 type Output = [u8];
408
409 fn index(&self, range: RangeTo<usize>) -> &Self::Output {
410 &self.bytes[range] }
412}
413impl Index<RangeInclusive<usize>> for ByteArray {
414 type Output = [u8];
415
416 fn index(&self, range: RangeInclusive<usize>) -> &Self::Output {
417 &self.bytes[range] }
419}
420impl Index<RangeFull> for ByteArray {
421 type Output = [u8];
422
423 fn index(&self, range: RangeFull) -> &Self::Output {
424 &self.bytes[range] }
426}
427
428impl IndexMut<Range<usize>> for ByteArray {
429 fn index_mut(&mut self, range: Range<usize>) -> &mut Self::Output {
430 &mut self.bytes[range]
431 }
432}
433
434impl IndexMut<RangeFrom<usize>> for ByteArray {
435 fn index_mut(&mut self, range: RangeFrom<usize>) -> &mut Self::Output {
436 &mut self.bytes[range]
437 }
438}
439impl IndexMut<RangeTo<usize>> for ByteArray {
440 fn index_mut(&mut self, range: RangeTo<usize>) -> &mut Self::Output {
441 &mut self.bytes[range]
442 }
443}
444impl IndexMut<RangeInclusive<usize>> for ByteArray {
445 fn index_mut(&mut self, range: RangeInclusive<usize>) -> &mut Self::Output {
446 &mut self.bytes[range] }
448}
449impl IndexMut<RangeFull> for ByteArray {
450 fn index_mut(&mut self, range: RangeFull) -> &mut Self::Output {
451 &mut self.bytes[range] }
453}
454
455impl AsRef<[u8]> for ByteArray {
456 fn as_ref(&self) -> &[u8] {
457 self.as_bytes()
458 }
459}
460
461impl AsMut<[u8]> for ByteArray {
462 fn as_mut(&mut self) -> &mut [u8] {
463 &mut self.bytes
464 }
465}
466
467#[cfg(test)]
468mod tests {
469 use super::*;
470 use crate::try_hex;
471 use alloc::vec;
472 use core::str::FromStr;
473
474 fn is_normal<T: Sized + Send + Sync + Unpin>() {}
475
476 #[test]
477 fn test_thread_safety_autotraits() {
478 is_normal::<ByteArray>();
479 }
480
481 #[test]
482 fn test_hex_string_constructor() {
483 let b1: ByteArray = "0xfe81eabd5".parse().unwrap();
484
485 assert_eq!(b1.len(), 5);
486 assert_eq!(b1.bytes, vec![0x0f, 0xe8, 0x1e, 0xab, 0xd5]);
487 }
488
489 #[test]
490 fn test_ba_with_capacity() {
491 let arr = ByteArray::with_capacity(10);
492
493 assert_eq!(arr.bytes.capacity(), 10);
494 assert!(ByteArray::try_from(arr).is_ok());
495 }
496
497 #[test]
498 fn test_with_hex() {
499 let arr = ByteArray::from_hex("ffabc");
500
501 assert_eq!(arr.unwrap().bytes, vec![0x0f, 0xfa, 0xbc]);
502 }
503
504 #[test]
505 fn test_with_bin_less_than_8() {
506 let arr = ByteArray::from_bin("1101111").unwrap();
507 assert_eq!(arr.bytes, vec![0x6f]);
508 }
509
510 #[test]
511 fn test_with_bin_more_than_8() {
512 let arr = ByteArray::from_bin("110111010110111").unwrap();
513 assert_eq!(arr.bytes, vec![0x6e, 0xb7]);
514 }
515
516 #[test]
517 fn test_equality_derives() {
518 let arr: ByteArray = "0xffab12345ffaf".parse().unwrap();
519 let arr_2 = ByteArray::from_hex("ffab12345ffafdeadbeef").unwrap();
520 let arr_3 = arr.clone();
521
522 assert_ne!(arr.bytes, arr_2.bytes);
523 assert_eq!(arr.bytes, arr_3.bytes);
524 }
525
526 #[test]
527 fn test_init_zeros() {
528 let arr = ByteArray::init_zeros(8);
529
530 assert_eq!(arr.bytes, [0u8, 0, 0, 0, 0, 0, 0, 0]);
531 }
532
533 #[test]
534 fn test_init_value() {
535 let arr = ByteArray::init_value(254, 8);
536
537 assert_eq!(arr.bytes, [254, 254, 254, 254, 254, 254, 254, 254]);
538 }
539
540 #[test]
541 fn test_mutable_idx_accessor() {
542 let mut arr: ByteArray = "0xffab1245".parse().unwrap();
543
544 arr[3] = 0xbe;
545 arr[1] = 0xfa;
546
547 assert_eq!(arr.bytes, ByteArray::from_str("0xfffa12be").unwrap().bytes);
548 }
549
550 #[test]
551 #[allow(deprecated)]
552 fn test_fill_zeros() {
553 let arr = ByteArray::default().fill_zeros();
554 assert!(arr.as_bytes().is_empty());
555
556 let arr = ByteArray::with_capacity(5).fill_zeros();
557 assert_eq!(arr.as_bytes(), [0u8, 0, 0, 0, 0]);
558
559 let arr = ByteArray::with_capacity(7).fill_zeros();
560
561 assert_eq!(arr.as_bytes(), [0u8, 0, 0, 0, 0, 0, 0])
562 }
563
564 #[test]
565 #[allow(deprecated)]
566 fn test_fill_with() {
567 let arr = ByteArray::default().fill_zeros();
568 assert!(arr.as_bytes().is_empty());
569
570 let arr = ByteArray::with_capacity(5).fill_with(126);
571 assert_eq!(arr.as_bytes(), [126u8, 126, 126, 126, 126]);
572
573 let arr = ByteArray::with_capacity(7).fill_with(5);
574
575 assert_eq!(arr.as_bytes(), [5u8, 5, 5, 5, 5, 5, 5]);
576 }
577
578 #[test]
579 #[cfg(feature = "experimental")]
580 fn test_push_element() {
581 let mut arr: ByteArray = vec![1, 2].into();
582
583 arr.try_push(0xab);
584
585 assert_eq!(arr.as_bytes(), [1, 2, 0xab]);
586 }
587
588 #[test]
589 fn test_hex_with_underscores() {
590 let arr = ByteArray::from_hex("de_ad_be_ef").unwrap();
591 assert_eq!(arr.as_bytes(), [0xde, 0xad, 0xbe, 0xef]);
592 }
593
594 #[test]
595 fn test_bin_with_underscores() {
596 let arr = ByteArray::from_bin("1010_0101").unwrap();
597 assert_eq!(arr.as_bytes(), [0xa5]);
598 }
599
600 #[test]
601 fn test_bin_with_underscores_odd_length() {
602 let arr = ByteArray::from_bin("110_1111").unwrap();
603 assert_eq!(arr.as_bytes(), [0x6f]);
604 }
605
606 #[test]
607 #[should_panic]
608 fn test_as_mut_empty() {
609 let mut bytes = ByteArray::default();
610
611 let mut_ref = bytes.as_mut();
612
613 mut_ref[0] = 0x00;
614 }
615
616 #[test]
617 fn test_ranges() {
618 let bytes = try_hex!("ff_aa_fa_b8_ca_12_15_5a_5c_6f").unwrap();
619
620 assert_eq!(bytes[1..2], [0xaa]);
621 assert_eq!(bytes[0..=2], [0xff, 0xaa, 0xfa]);
622 assert_eq!(bytes[6..], [0x15, 0x5a, 0x5c, 0x6f]);
623 assert_eq!(bytes[..3], [0xff, 0xaa, 0xfa]);
624 assert_eq!(
625 bytes[..],
626 [0xff, 0xaa, 0xfa, 0xb8, 0xca, 0x12, 0x15, 0x5a, 0x5c, 0x6f]
627 );
628 }
629
630 #[test]
631 fn test_ranges_mut() {
632 let mut bytes = try_hex!("ff_aa_fa_b8_ca_12_15_5a_5c_6f").unwrap();
633
634 let slice = &mut bytes[1..3];
635 slice[0] = 0x00;
636 slice[1] = 0x01;
637 let expected: ByteArray = "0xff_00_01_b8_ca_12_15_5a_5c_6f".parse().unwrap();
638
639 assert_eq!(bytes, expected);
640
641 let slice = &mut bytes[0..=2];
642 slice[0] = 0x12;
643 slice[1] = 0xab;
644 slice[2] = 0xbc;
645
646 let expected: ByteArray = "0x12_ab_bc_b8_ca_12_15_5a_5c_6f".parse().unwrap();
647
648 assert_eq!(bytes, expected);
649
650 let slice = &mut bytes[6..];
651 slice[0] = 0x01;
652 slice[1] = 0x02;
653 slice[2] = 0x03;
654 slice[3] = 0x04;
655
656 let expected: ByteArray = "0x12_ab_bc_b8_ca_12_01_02_03_04".parse().unwrap();
657
658 assert_eq!(bytes, expected);
659
660 let slice = &mut bytes[..3];
661 slice[0] = 0x00;
662 slice[1] = 0x02;
663 slice[2] = 0x03;
664
665 let expected: ByteArray = "0x00_02_03_b8_ca_12_01_02_03_04".parse().unwrap();
666
667 assert_eq!(bytes, expected);
668
669 let slice = &mut bytes[..];
670
671 slice.iter_mut().for_each(|e| *e = 0x01);
672
673 let expected: ByteArray = "0x01_01_01_01_01_01_01_01_01_01".parse().unwrap();
674
675 assert_eq!(bytes, expected);
676 }
677
678 #[test]
679 fn test_as_ref() {
680 let bytes: ByteArray = "0x01_02_03_04_05_06_07_08".parse().unwrap();
681 let bytes_ref = bytes.as_ref();
682
683 assert_eq!(bytes.as_bytes(), bytes_ref);
684 }
685
686 #[test]
687 fn test_as_mut() {
688 let mut bytes: ByteArray = "0x01_02_03_04_05_06_07_08".parse().unwrap();
689
690 let mut_ref = bytes.as_mut();
691
692 mut_ref[0] = 0xFF;
693 mut_ref[5] = 0xab;
694 mut_ref[7] = 0x1a;
695
696 assert_eq!(
697 bytes.as_bytes(),
698 [0xff, 0x02, 0x03, 0x04, 0x05, 0xab, 0x07, 0x1a]
699 )
700 }
701
702 #[test]
703 fn test_concat_create_from() {
704 let bytes_first = ByteArray::default();
707 let bytes_second = ByteArray::default();
708
709 }
716
717 #[test]
718 fn test_concat_create_chained() {}
719
720 #[test]
723 fn test_try_extend_both_empty() {
724 let arr1 = ByteArray::default();
725 let arr2 = ByteArray::default();
726 let result = arr1.try_extend(arr2).unwrap();
727 assert_eq!(result.len(), 0);
728 }
729
730 #[test]
731 fn test_try_extend_first_empty() {
732 let arr1 = ByteArray::default();
733 let arr2 = ByteArray::from_hex("beef").unwrap();
734 let result = arr1.try_extend(arr2).unwrap();
735 assert_eq!(result.as_bytes(), [0xbe, 0xef]);
736 }
737
738 #[test]
739 fn test_try_extend_second_empty() {
740 let arr1 = ByteArray::from_hex("dead").unwrap();
741 let arr2 = ByteArray::default();
742 let result = arr1.try_extend(arr2).unwrap();
743 assert_eq!(result.as_bytes(), [0xde, 0xad]);
744 }
745
746 #[test]
747 fn test_try_extend_small_arrays() {
748 let arr1 = ByteArray::from_hex("aa").unwrap();
749 let arr2 = ByteArray::from_hex("bb").unwrap();
750 let result = arr1.try_extend(arr2).unwrap();
751 assert_eq!(result.as_bytes(), [0xaa, 0xbb]);
752 assert_eq!(result.len(), 2);
753 }
754
755 #[test]
756 fn test_try_extend_preserve_cap_empty_with_capacity() {
757 let arr1 = ByteArray::with_capacity(50); let arr2 = ByteArray::with_capacity(30); let result = arr1.try_extend_with_preserve_cap(arr2).unwrap();
760
761 assert_eq!(result.len(), 0);
762 assert_eq!(result.bytes.capacity(), 90); }
764
765 #[test]
766 fn test_try_extend_capacity_based_on_length() {
767 let arr1 = ByteArray::from_hex("aa").unwrap(); let arr2 = ByteArray::from_hex("bb").unwrap(); let result = arr1.try_extend(arr2).unwrap();
770
771 assert_eq!(result.bytes.capacity(), 12);
773 assert_eq!(result.as_bytes(), [0xaa, 0xbb]);
774 }
775
776 #[test]
777 fn test_try_extend_chaining() {
778 let arr1 = ByteArray::from_hex("aa").unwrap();
779 let arr2 = ByteArray::from_hex("bb").unwrap();
780 let arr3 = ByteArray::from_hex("cc").unwrap();
781
782 let result = arr1.try_extend(arr2).unwrap().try_extend(arr3).unwrap();
783 assert_eq!(result.as_bytes(), [0xaa, 0xbb, 0xcc]);
784 }
785}