byte_array_ops/byte_array/model.rs
1//! This is the main model for our ByteArray Object
2
3use 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/// Enum controlling Padding behavior for odd byte arrays use by [`ByteArray`]
12///
13/// # Warning
14/// This is *NOT* padding for the entire array meaning this does *NOT* how to fill the array to capacity with zeros
15/// what this does is in case of odd byte arrays passed to the [`ByteArray`] constructor the first or last 8-bit word is padded
16/// to the left or to the right accordingly
17/// - Example left padding (default): 0xfeab123 becomes 0x0feab123
18/// - Example right padding: 0xfeab123 becomes 0xfeab1230
19///
20#[derive(Default, Copy, Clone, PartialEq, Eq, Debug)] // there is no risk of exposure here as this enum does not hold any sensitive data
21pub enum ByteArrayOddWordPad {
22 #[default]
23 LeftPadding,
24 #[cfg(feature = "experimental")]
25 RightPadding,
26}
27
28/// marker struct for uninitialized byte arrays that still require padding information for odd arrays
29/// from user. If you wish for a default constructor please check [`ByteArray::default`]. Please note
30/// that this struct represents an intermediate state and is not to be used by the client directly
31#[derive(Default)]
32pub struct UninitByteArray {
33 /// capacity of the to be create array for efficiency purposes
34 /// if this is [`None`] then no pre-allocation takes place
35 capacity: Option<usize>,
36}
37
38impl UninitByteArray {
39 /// pre initializes the capacity for more efficient pre-allocation
40 /// this returns an [Uninitialized Byte Array][`UninitByteArray`] and is used in
41 /// cases where the user wants to override the padding direction with [`UninitByteArray::with_odd_pad_dir`]
42 ///
43 /// # Note
44 /// in cases where the [Default odd array padding][`ByteArrayOddWordPad`] is sufficient and more efficient
45 /// please use [`ByteArray::with_capacity`] instead
46 ///
47 /// # Example
48 /// ```
49 /// use byte_array_ops::byte_array::model::{ByteArray, ByteArrayOddWordPad};
50 ///
51 /// let arr = ByteArray::new_uninit()
52 /// .with_capacity(20)
53 /// .with_odd_pad_dir(ByteArrayOddWordPad::LeftPadding)
54 /// .with_hex("efab123").expect("failed to convert hex");
55 ///
56 /// // In cases where the default padding is sufficient please use the direct constructor instead
57 /// let arr_2 = ByteArray::with_capacity(20)
58 /// .with_hex("efab123").expect("failed to convert");
59 ///
60 /// assert_eq!(arr,arr_2);
61 /// assert_eq!(arr_2.as_bytes(),[0x0e,0xfa,0xb1,0x23]);
62 /// ```
63 pub fn with_capacity(self, byte_size: usize) -> Self {
64 Self {
65 capacity: Some(byte_size),
66 }
67 }
68 ///
69 /// Overrides the default odd array padding to use the less common
70 /// Right padding instead of the default padding
71 ///
72 /// # Warning
73 /// Please read documentation of [`ByteArrayOddWordPad`] for an understanding of what padding
74 /// means in this context
75 ///
76 /// # Examples
77 /// ```
78 /// use byte_array_ops::byte_array::model::ByteArray;
79 ///
80 /// let array = ByteArray::new()
81 /// .create_with_odd_rpad();
82 ///
83 /// unimplemented!() // ADD assert
84 /// ```
85 #[cfg(feature = "experimental")]
86 pub fn create_with_odd_rpad(self) -> ByteArray {
87 unimplemented!("Currently only left padding is implemented");
88 /* ByteArray {
89 bytes: self.capacity.map(Vec::with_capacity).unwrap_or_else(Vec::new),
90 byte_padding: BytePadding::RightPadding
91 }*/
92 }
93
94 /// Explicitly sets the padding direction. This is not needed in general
95 /// and is only provided in cases where padding must be explicitly set for
96 /// readability purposes. By default, [`ByteArray`] uses [Left Padding][`ByteArrayOddWordPad::LeftPadding`]
97 ///
98 /// # Warning
99 /// Please read documentation of [`ByteArrayOddWordPad`] for an understanding of what padding
100 /// means in this context
101 ///
102 /// # Example
103 /// ```
104 /// use byte_array_ops::byte_array::model::{ByteArray, ByteArrayOddWordPad};
105 /// let arr = ByteArray::new_uninit()
106 /// .with_odd_pad_dir(ByteArrayOddWordPad::LeftPadding)
107 /// .with_hex("feab123").expect("failed to convert");
108 ///
109 /// assert_eq!(arr.as_bytes(),[0x0f,0xea,0xb1,0x23]);
110 /// ```
111 pub fn with_odd_pad_dir(self, pad_dir: ByteArrayOddWordPad) -> ByteArray {
112 ByteArray {
113 bytes: self.capacity.map(Vec::with_capacity).unwrap_or_default(),
114 byte_padding: pad_dir,
115 }
116 }
117}
118
119/// Debug derive and Display is intentionally left out to avoid any intentional data leakages through formatters
120#[derive(Default, PartialEq, Eq, Clone)] // TODO analyze security side effects of debug
121pub struct ByteArray {
122 pub(crate) bytes: Vec<u8>,
123 /// Defines how we pad if we have an od number of bytes should we pad left or right ? by default we use left
124 /// padding which is common in Cryptographic and Network Byte order
125 pub(super) byte_padding: ByteArrayOddWordPad,
126}
127
128impl ByteArray {
129 /// This constructor is usually needed when a custom odd array padding direction must be set.
130 /// creates a new empty byte array without reserving memory. this might not be the
131 /// most efficient option. For large byte arrays use [`ByteArray::with_capacity`] instead
132 ///
133 /// # Returns
134 ///
135 /// [`UninitByteArray`]
136 ///
137 /// # Note
138 ///
139 /// Use [`ByteArray::default`] or [`ByteArray::with_capacity`] to get a [`ByteArray`] without
140 /// intermediate structs if you do not require setting the odd word padding
141 ///
142 /// # Example
143 ///
144 /// ```
145 /// use core::str::FromStr;
146 ///
147 /// use byte_array_ops::byte_array::model::{ByteArray, ByteArrayOddWordPad};
148 ///
149 /// let arr = ByteArray::new_uninit()
150 /// .with_odd_pad_dir(ByteArrayOddWordPad::LeftPadding)
151 /// .with_hex("ffef48a").expect("failed to convert");
152 ///
153 /// assert_eq!(arr.as_bytes(),[0x0f,0xfe,0xf4,0x8a]);
154 /// ```
155 pub fn new_uninit() -> UninitByteArray {
156 UninitByteArray { capacity: None }
157 }
158
159 /// reserves memory for a certain number of bytes for efficiency purposes
160 /// uses the default [Byte padding direction][`ByteArrayOddWordPad`]
161 pub fn with_capacity(size_in_bytes: usize) -> Self {
162 Self {
163 bytes: Vec::with_capacity(size_in_bytes),
164 byte_padding: ByteArrayOddWordPad::default(),
165 }
166 }
167
168 /// fills the byte array with zeros to capacity
169 /// this is usually only useful in the rare case where an odd word padding needs to be set
170 /// in all other cases use [`ByteArray::init_zeros`]. This function does nothing if the ByteArray
171 /// capacity has not been set (is 0)
172 ///
173 /// # Example
174 /// ```
175 /// use byte_array_ops::byte_array::model::{ByteArray, ByteArrayOddWordPad};
176 /// let arr = ByteArray::default().fill_zeros(); // does nothing on an array with zero capacity
177 /// assert!(arr.as_bytes().is_empty());
178 ///
179 /// let arr = ByteArray::with_capacity(5).fill_zeros();
180 /// assert_eq!(arr.as_bytes(),[0u8,0,0,0,0]);
181 ///
182 /// // or in the rare cases where a different odd word padding is set
183 ///
184 /// let arr = ByteArray::new_uninit()
185 /// .with_capacity(7)
186 /// .with_odd_pad_dir(ByteArrayOddWordPad::LeftPadding)
187 /// .fill_zeros();
188 ///
189 /// assert_eq!(arr.as_bytes(),[0u8,0,0,0,0,0,0])
190 ///
191 ///
192 /// ```
193 ///
194 ///
195 pub fn fill_zeros(self) -> Self {
196 if self.bytes.capacity() == 0 {
197 self
198 } else {
199 ByteArray {
200 bytes: vec![0u8; self.bytes.capacity()],
201 byte_padding: self.byte_padding,
202 }
203 }
204 }
205
206 /// fills the byte array with the given `value` to capacity
207 /// this is usually only useful in the rare case where an odd word padding needs to be set
208 /// in all other cases use [`ByteArray::init_value`].
209 ///
210 /// # Note
211 /// This function does nothing (noop) if the ByteArray capacity has not been set (is 0)
212 ///
213 /// # Example
214 /// ```
215 /// use byte_array_ops::byte_array::model::{ByteArray, ByteArrayOddWordPad};
216 /// let arr = ByteArray::default().fill_zeros(); // does nothing on an array with zero capacity
217 /// assert!(arr.as_bytes().is_empty());
218 ///
219 /// let arr = ByteArray::with_capacity(5).fill_with(126);
220 /// assert_eq!(arr.as_bytes(),[126u8,126,126,126,126]);
221 ///
222 /// // or in the rare cases where a different odd word padding is set
223 ///
224 /// let arr = ByteArray::new_uninit()
225 /// .with_capacity(7)
226 /// .with_odd_pad_dir(ByteArrayOddWordPad::LeftPadding)
227 /// .fill_with(5);
228 ///
229 /// assert_eq!(arr.as_bytes(),[5u8,5,5,5,5,5,5]);
230 ///
231 ///
232 /// ```
233 ///
234 ///
235 pub fn fill_with(self, value: u8) -> Self {
236 if self.bytes.capacity() == 0 {
237 self
238 } else {
239 ByteArray {
240 bytes: vec![value; self.bytes.capacity()],
241 byte_padding: self.byte_padding,
242 }
243 }
244 }
245
246 /// chaining function to create a byte array from hex
247 ///
248 /// TODO make this more resilient by accepting 0x too
249 ///
250 /// # Example
251 /// ```
252 /// use byte_array_ops::byte_array::model::ByteArray;
253 /// let arr = ByteArray::default()
254 /// .with_hex("deadbeef").expect("failed to convert hex string");
255 ///
256 /// assert_eq!(arr.as_bytes(), [0xde, 0xad, 0xbe, 0xef]);
257 /// ```
258 pub fn with_hex(self, hex_str: &str) -> Result<Self, ByteArrayError> {
259 if hex_str.is_empty() {
260 return Err(ByteArrayError::EmptyInput);
261 }
262
263 // Filter out underscores and collect
264 let bytes: Vec<u8> = hex_str.bytes().filter(|&b| b != b'_').collect();
265
266 // Validate characters
267 if let Some(&invalid) = bytes.iter().find(|&&b| !b.is_ascii_hexdigit()) {
268 return Err(InvalidHexChar(invalid as char));
269 }
270
271 let hex_count = bytes.len();
272 let byte_count = hex_count / 2 + hex_count % 2;
273 let mut ret = ByteArray::with_capacity(byte_count);
274 ret.byte_padding = self.byte_padding;
275
276 let mut start = 0;
277
278 // Handle odd length - process first char alone (LEFT padding for network byte order)
279 if hex_count % 2 == 1 {
280 ret.bytes
281 .push(Utils::hex_char_to_nibble_unchecked(bytes[0]));
282 start = 1;
283 }
284
285 // Process remaining pairs
286 for i in (start..hex_count).step_by(2) {
287 let byte_val = Utils::hex_char_to_nibble_unchecked(bytes[i]) << 4
288 | Utils::hex_char_to_nibble_unchecked(bytes[i + 1]);
289 ret.bytes.push(byte_val);
290 }
291
292 Ok(ret)
293 }
294
295 /// chaining function to create a byte array from a binary representation
296 ///
297 /// # Example
298 /// ```
299 /// use byte_array_ops::byte_array::model::ByteArray;
300 /// let arr = ByteArray::default()
301 /// .with_bin("1010010").expect("failed to convert binary string");
302 ///
303 /// assert_eq!(arr.as_bytes(), [0x52]);
304 /// ```
305 pub fn with_bin(self, bin_str: &str) -> Result<Self, ByteArrayError> {
306 if bin_str.is_empty() {
307 return Err(ByteArrayError::EmptyInput);
308 }
309
310 // Filter out underscores and collect
311 let bytes: Vec<u8> = bin_str.bytes().filter(|&b| b != b'_').collect();
312
313 // Validate characters
314 if let Some(&invalid) = bytes.iter().find(|&&b| b != b'0' && b != b'1') {
315 return Err(InvalidBinaryChar(invalid as char));
316 }
317
318 let bit_count = bytes.len();
319 let byte_count = bit_count.div_ceil(8);
320 let mut ret = ByteArray::with_capacity(byte_count);
321 ret.byte_padding = self.byte_padding;
322
323 let rem = bit_count % 8;
324
325 // Handle partial first byte (left padding) OR entire input if < 8 bits
326 let start = if rem != 0 {
327 let mut byte = 0u8;
328 #[allow(clippy::needless_range_loop)] // our version is more readable than clippy's
329 for i in 0..rem {
330 let bit_value = bytes[i] - b'0';
331 byte |= bit_value << (rem - 1 - i);
332 }
333 ret.bytes.push(byte);
334 rem
335 } else {
336 0
337 };
338
339 // Process remaining full bytes (only if there are any left)
340 for i in (start..bit_count).step_by(8) {
341 let mut byte = 0u8;
342
343 for j in 0..8 {
344 let bit_value = bytes[i + j] - b'0';
345 byte |= bit_value << (7 - j);
346 }
347
348 ret.bytes.push(byte);
349 }
350
351 Ok(ret)
352 }
353
354 /// initialize the array with a certain amount of zeros
355 /// internally this creates the byte array representation with `vec![0u8;count]`
356 /// the rest is default initialized
357 pub fn init_zeros(count: usize) -> Self {
358 ByteArray {
359 bytes: vec![0u8; count],
360 byte_padding: ByteArrayOddWordPad::default(),
361 }
362 }
363
364 /// initialize the array with a certain amount of `value`
365 /// internally this creates the byte array representation with `vec![value;count]`
366 /// the rest is default initialized
367 pub fn init_value(value: u8, count: usize) -> Self {
368 ByteArray {
369 bytes: vec![value; count],
370 byte_padding: ByteArrayOddWordPad::default(),
371 }
372 }
373
374 /// returns a slices to the interior bytes
375 ///
376 /// # NOTE
377 /// There is another method that provides a zero-cost move of the interior bytes using the
378 /// [`Vec::from::<ByteArray>`] implementation. Please check the [`ByteArray`]'s [`From<ByteArray>`] implementation
379 /// documentation
380 ///
381 /// # Example
382 /// ```
383 /// use byte_array_ops::byte_array::model::ByteArray;
384 ///
385 /// let arr : ByteArray = "0xff2569".parse().unwrap();
386 ///
387 /// let slice = arr.as_bytes();
388 ///
389 /// assert_eq!(slice, [0xff,0x25,0x69]);
390 /// ```
391 ///
392 /// # Alternative (Zero-cost move)
393 /// ```
394 /// use byte_array_ops::byte_array::model::ByteArray;
395 /// let arr : ByteArray = "0b11101111".parse().unwrap();
396 ///
397 /// assert_eq!(arr.as_bytes(), [0xef]);
398 ///
399 /// let moved_data : Vec<u8> = arr.into();
400 /// assert_eq!(moved_data, vec![0xef]);
401 /// ```
402 ///
403 pub fn as_bytes(&self) -> &[u8] {
404 &self.bytes
405 }
406
407 /// returns the set padding
408 pub fn get_padding(&self) -> ByteArrayOddWordPad {
409 self.byte_padding
410 }
411
412 /// returns the number of bytes in the array
413 /// TODO add example
414 pub fn len(&self) -> usize {
415 self.bytes.len()
416 }
417
418 /// returns true if there are no bytes in the array
419 /// TODO example
420 pub fn is_empty(&self) -> bool {
421 self.bytes.is_empty()
422 }
423
424 #[cfg(feature = "experimental")]
425 pub fn resize(&mut self, new_capacity: usize, value: u8) {
426 unimplemented!(
427 "this is insecure and must find a way on how to handle this in a more secure fashion"
428 );
429 self.bytes.resize(new_capacity, value);
430 }
431
432 /// Tries to append an element to the back of a collection. Fails
433 ///
434 /// # Panics
435 /// if the new capacity exceeds [`isize::MAX`] bytes.
436 ///
437 /// # Examples
438 ///```
439 /// use byte_array_ops::byte_array::model::ByteArray;
440 /// let mut arr = ByteArray::default()
441 ///
442 /// arr.try_push(0xab).unwrap();
443 ///
444 /// assert_eq!(arr.as_bytes(), [1, 2, 0xab]);
445 /// ```
446 #[cfg(feature = "experimental")]
447 pub fn try_push(&mut self, value: u8) {
448 self.bytes.push(value);
449 }
450}
451
452// index handling
453
454impl Index<usize> for ByteArray {
455 type Output = u8;
456
457 /// index accessor for ByteArray
458 /// # Panics
459 /// When out of bound use [`ByteArray::get`] instead if you want a checked getter
460 fn index(&self, index: usize) -> &Self::Output {
461 &self.bytes[index]
462 }
463}
464
465impl IndexMut<usize> for ByteArray {
466 /// Mutable index accessor for ByteArray
467 /// # Panics
468 /// When out of bound use [`ByteArray::get`] instead if you want a checked getter
469 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
470 &mut self.bytes[index]
471 }
472}
473
474impl ByteArray {
475 pub fn get(&self, index: usize) -> Option<&u8> {
476 self.bytes.get(index)
477 }
478}
479
480impl AsRef<[u8]> for ByteArray {
481 fn as_ref(&self) -> &[u8] {
482 self.as_bytes()
483 }
484}
485
486impl AsMut<[u8]> for ByteArray {
487 fn as_mut(&mut self) -> &mut [u8] {
488 &mut self.bytes
489 }
490}
491
492#[cfg(test)]
493mod tests {
494 use super::*;
495 use alloc::vec;
496 use core::str::FromStr;
497
498 #[test]
499 fn test_hex_string_constructor() {
500 let b1: ByteArray = "0xfe81eabd5".parse().unwrap();
501
502 assert_eq!(b1.len(), 5);
503 assert_eq!(b1.bytes, vec![0x0f, 0xe8, 0x1e, 0xab, 0xd5]);
504 }
505 #[test]
506 fn test_ba_new() {
507 let arr = ByteArray::new_uninit();
508
509 assert_eq!(arr.capacity, None);
510 assert!(UninitByteArray::try_from(arr).is_ok())
511 }
512
513 #[test]
514 fn test_ba_with_capacity() {
515 let arr = ByteArray::with_capacity(10);
516
517 assert_eq!(arr.bytes.capacity(), 10);
518 assert!(ByteArray::try_from(arr).is_ok());
519 }
520
521 #[test]
522 fn test_with_hex() {
523 let arr = ByteArray::default().with_hex("ffabc");
524
525 assert_eq!(arr.unwrap().bytes, vec![0x0f, 0xfa, 0xbc]);
526 }
527
528 #[test]
529 fn test_with_bin_less_than_8() {
530 let arr = ByteArray::with_capacity(1).with_bin("1101111").unwrap();
531 assert_eq!(arr.bytes, vec![0x6f]);
532 }
533
534 #[test]
535 fn test_with_bin_more_than_8() {
536 let arr = ByteArray::with_capacity(1)
537 .with_bin("110111010110111")
538 .unwrap();
539 assert_eq!(arr.bytes, vec![0x6e, 0xb7]);
540 }
541
542 #[test]
543 fn test_get_padding() {
544 let arr = ByteArray::default();
545
546 assert_eq!(
547 ByteArrayOddWordPad::default(),
548 ByteArrayOddWordPad::LeftPadding
549 );
550 assert_eq!(arr.byte_padding, ByteArrayOddWordPad::LeftPadding);
551 }
552
553 #[test]
554 fn test_len() {
555 let arr = ByteArray::default()
556 .with_hex("ffab12345bc")
557 .expect("error converting");
558
559 assert_eq!(arr.len(), 6);
560 }
561
562 #[test]
563 fn test_is_empty() {
564 let arr = ByteArray::default();
565 assert_eq!(arr.is_empty(), true);
566
567 let arr = ByteArray::with_capacity(1)
568 .with_hex("bb")
569 .expect("error converting");
570
571 assert_eq!(arr.is_empty(), false);
572 }
573
574 #[test]
575 fn test_equality_derives() {
576 let arr: ByteArray = "0xffab12345ffaf".parse().unwrap();
577 let arr_2 = ByteArray::default()
578 .with_hex("ffab12345ffafdeadbeef")
579 .unwrap();
580 let arr_3 = arr.clone();
581
582 assert_ne!(arr.bytes, arr_2.bytes);
583 assert_eq!(arr.bytes, arr_3.bytes);
584 }
585
586 #[test]
587 fn test_init_zeros() {
588 let arr = ByteArray::init_zeros(8);
589
590 assert_eq!(arr.bytes, [0u8, 0, 0, 0, 0, 0, 0, 0]);
591 }
592
593 #[test]
594 fn test_init_value() {
595 let arr = ByteArray::init_value(254, 8);
596
597 assert_eq!(arr.bytes, [254, 254, 254, 254, 254, 254, 254, 254]);
598 }
599
600 #[test]
601 fn test_mutable_idx_accessor() {
602 let mut arr: ByteArray = "0xffab1245".parse().unwrap();
603
604 arr[3] = 0xbe;
605 arr[1] = 0xfa;
606
607 assert_eq!(arr.bytes, ByteArray::from_str("0xfffa12be").unwrap().bytes);
608 }
609
610 #[test]
611 fn test_fill_zeros() {
612 let arr = ByteArray::default().fill_zeros();
613 assert!(arr.as_bytes().is_empty());
614
615 let arr = ByteArray::with_capacity(5).fill_zeros();
616 assert_eq!(arr.as_bytes(), [0u8, 0, 0, 0, 0]);
617
618 let arr = ByteArray::new_uninit()
619 .with_capacity(7)
620 .with_odd_pad_dir(ByteArrayOddWordPad::LeftPadding)
621 .fill_zeros();
622
623 assert_eq!(arr.as_bytes(), [0u8, 0, 0, 0, 0, 0, 0])
624 }
625
626 #[test]
627 fn test_fill_with() {
628 let arr = ByteArray::default().fill_zeros();
629 assert!(arr.as_bytes().is_empty());
630
631 let arr = ByteArray::with_capacity(5).fill_with(126);
632 assert_eq!(arr.as_bytes(), [126u8, 126, 126, 126, 126]);
633
634 let arr = ByteArray::new_uninit()
635 .with_capacity(7)
636 .with_odd_pad_dir(ByteArrayOddWordPad::LeftPadding)
637 .fill_with(5);
638
639 assert_eq!(arr.as_bytes(), [5u8, 5, 5, 5, 5, 5, 5]);
640 }
641
642 #[test]
643 #[cfg(feature = "experimental")]
644 fn test_push_element() {
645 let mut arr: ByteArray = vec![1, 2].into();
646
647 arr.try_push(0xab);
648
649 assert_eq!(arr.as_bytes(), [1, 2, 0xab]);
650 }
651
652 #[test]
653 fn test_hex_with_underscores() {
654 let arr = ByteArray::default().with_hex("de_ad_be_ef").unwrap();
655 assert_eq!(arr.as_bytes(), [0xde, 0xad, 0xbe, 0xef]);
656 }
657
658 #[test]
659 fn test_bin_with_underscores() {
660 let arr = ByteArray::default().with_bin("1010_0101").unwrap();
661 assert_eq!(arr.as_bytes(), [0xa5]);
662 }
663
664 #[test]
665 fn test_bin_with_underscores_odd_length() {
666 let arr = ByteArray::default().with_bin("110_1111").unwrap();
667 assert_eq!(arr.as_bytes(), [0x6f]);
668 }
669
670 #[test]
671 #[should_panic]
672 fn test_as_mut_empty() {
673 let mut bytes = ByteArray::default();
674
675 let mut_ref = bytes.as_mut();
676
677 mut_ref[0] = 0x00;
678
679 }
680
681 #[test]
682 fn test_as_ref() {
683 let bytes : ByteArray = "0x01_02_03_04_05_06_07_08".parse().unwrap();
684 let bytes_ref = bytes.as_ref();
685
686 assert_eq!(bytes.as_bytes(),bytes_ref);
687 }
688
689 #[test]
690 fn test_as_mut() {
691 let mut bytes : ByteArray = "0x01_02_03_04_05_06_07_08".parse().unwrap();
692
693 let mut_ref = bytes.as_mut();
694
695 mut_ref[0] = 0xFF;
696 mut_ref[5] = 0xab;
697 mut_ref[7] = 0x1a;
698
699 assert_eq!(bytes.as_bytes(),[0xff,0x02,0x03,0x04,0x05,0xab,0x07,0x1a])
700 }
701}