1use crate::{BitBuf, Error, Result, Storage};
2
3impl<S: Storage> BitBuf<S> {
4 #[inline(always)]
14 #[must_use]
15 pub unsafe fn read_u8_be_aligned_full_at_unchecked(&self, byte_offset: usize) -> u8 {
16 let bytes = self.bytes();
17
18 debug_assert!(
19 byte_offset < bytes.len(),
20 "BitBuf::read_u8_be_aligned_full_at_unchecked: index out of bounds! len is {}, offset is {}",
21 bytes.len(),
22 byte_offset,
23 );
24
25 unsafe { *bytes.get_unchecked(byte_offset) }
26 }
27
28 #[inline(always)]
40 #[must_use]
41 pub unsafe fn read_u8_be_aligned_full_unchecked(&mut self) -> u8 {
42 debug_assert!(
43 self.is_aligned(),
44 "BitBuf::read_u8_be_aligned_full_unchecked called at unaligned bit position: {}",
45 self.pos(),
46 );
47
48 let b = unsafe { self.read_u8_be_aligned_full_at_unchecked(self.byte_pos()) };
49 self.advance_bytes(1);
50 b
51 }
52
53 #[inline(always)]
65 #[must_use]
66 pub unsafe fn read_u8_be_full_at_unchecked(&self, offset: usize) -> u8 {
67 let byte_idx = offset / 8;
68 let shift = offset % 8;
69
70 let bytes = self.bytes();
71
72 debug_assert!(
73 byte_idx < bytes.len(),
74 "BitBuf::read_u8_be_full_at_unchecked: index out of bounds! len is {}, byte_idx is {}",
75 bytes.len(),
76 byte_idx,
77 );
78
79 if shift == 0 {
80 unsafe { self.read_u8_be_aligned_full_at_unchecked(byte_idx) }
81 } else {
82 let next_idx = byte_idx + 1;
83
84 debug_assert!(
85 next_idx < bytes.len(),
86 "BitBuf::read_u8_be_full_at_unchecked: lookahead index out of bounds! len is {}, lookahead byte_idx is {}",
87 bytes.len(),
88 next_idx,
89 );
90
91 let (high, low) = unsafe {
92 (
93 *bytes.get_unchecked(byte_idx),
94 *bytes.get_unchecked(next_idx),
95 )
96 };
97
98 (high << shift) | (low >> (8 - shift))
99 }
100 }
101
102 #[inline(always)]
114 #[must_use]
115 pub unsafe fn read_u8_be_full_unchecked(&mut self) -> u8 {
116 let b = unsafe { self.read_u8_be_full_at_unchecked(self.pos()) };
117 self.advance_bytes(1);
118 b
119 }
120
121 #[inline(always)]
129 pub fn try_read_u8_be_full_at(&self, offset: usize) -> Result<u8> {
130 let byte_idx = offset / 8;
131 let shift = offset % 8;
132
133 let len = self.bytes().len();
134
135 if byte_idx >= len {
136 return Err(Error::OutOfBounds);
137 }
138
139 if shift != 0 && byte_idx + 1 >= len {
140 return Err(Error::OutOfBounds);
141 }
142
143 Ok(unsafe { self.read_u8_be_full_at_unchecked(offset) })
144 }
145
146 #[inline(always)]
154 pub fn try_read_u8_be_full(&mut self) -> Result<u8> {
155 let b = self.try_read_u8_be_full_at(self.pos())?;
156 self.advance_bytes(1);
157 Ok(b)
158 }
159
160 #[inline(always)]
167 #[must_use]
168 pub fn read_u8_be_full_at(&self, offset: usize) -> u8 {
169 self
170 .try_read_u8_be_full_at(offset)
171 .expect("BitBuf::read_u8_be_full_at out of bounds")
172 }
173
174 #[inline(always)]
181 #[must_use]
182 pub fn read_u8_be_full(&mut self) -> u8 {
183 self
184 .try_read_u8_be_full()
185 .expect("BitBuf::read_u8_be_full out of bounds")
186 }
187
188 #[inline(always)]
198 #[must_use]
199 pub unsafe fn read_u16_be_aligned_full_at_unchecked(&self, byte_offset: usize) -> u16 {
200 let bytes = self.bytes();
201
202 debug_assert!(
203 byte_offset + 1 < bytes.len(),
204 "BitBuf::read_u16_be_aligned_full_at_unchecked: index out of bounds! len is {}, offset is {}",
205 bytes.len(),
206 byte_offset + 1,
207 );
208
209 unsafe {
210 let high = *bytes.get_unchecked(byte_offset);
211 let low = *bytes.get_unchecked(byte_offset + 1);
212 u16::from_be_bytes([high, low])
213 }
214 }
215
216 #[inline(always)]
228 #[must_use]
229 pub unsafe fn read_u16_be_aligned_full_unchecked(&mut self) -> u16 {
230 debug_assert!(
231 self.is_aligned(),
232 "BitBuf::read_u16_be_aligned_full_unchecked called at unaligned bit position: {}",
233 self.pos(),
234 );
235
236 let v = unsafe { self.read_u16_be_aligned_full_at_unchecked(self.byte_pos()) };
237 self.advance_bytes(2);
238 v
239 }
240
241 #[inline(always)]
253 #[must_use]
254 pub unsafe fn read_u16_be_full_at_unchecked(&self, offset: usize) -> u16 {
255 let first_idx = offset / 8;
256 let shift = offset % 8;
257
258 let bytes = self.bytes();
259
260 debug_assert!(
261 first_idx + 1 < bytes.len(),
262 "BitBuf::read_u16_be_full_at_unchecked: index out of bounds! len is {}, byte_idx is {}",
263 bytes.len(),
264 first_idx + 1,
265 );
266
267 if shift == 0 {
268 unsafe { self.read_u16_be_aligned_full_at_unchecked(first_idx) }
269 } else {
270 let second_idx = first_idx + 1;
271 let third_idx = first_idx + 2;
272
273 debug_assert!(
274 third_idx < bytes.len(),
275 "BitBuf::read_u16_be_full_at_unchecked: lookahead index out of bounds! len is {}, lookahead byte_idx is {}",
276 bytes.len(),
277 third_idx,
278 );
279
280 let (a, b, c) = unsafe {
281 (
282 *bytes.get_unchecked(first_idx),
283 *bytes.get_unchecked(second_idx),
284 *bytes.get_unchecked(third_idx),
285 )
286 };
287
288 let high = ((a as u16) << shift) | ((b as u16) >> (8 - shift));
289 let low = ((b as u16) << shift) | ((c as u16) >> (8 - shift));
290
291 (high << 8) | (low & 0xFF)
292 }
293 }
294
295 #[inline(always)]
307 #[must_use]
308 pub unsafe fn read_u16_be_full_unchecked(&mut self) -> u16 {
309 let v = unsafe { self.read_u16_be_full_at_unchecked(self.pos()) };
310 self.advance_bytes(2);
311 v
312 }
313
314 #[inline(always)]
322 pub fn try_read_u16_be_full_at(&self, offset: usize) -> Result<u16> {
323 let first_idx = offset / 8;
324 let shift = offset % 8;
325
326 let len = self.bytes().len();
327
328 if first_idx + 1 >= len {
329 return Err(Error::OutOfBounds);
330 }
331
332 if shift != 0 && first_idx + 2 >= len {
333 return Err(Error::OutOfBounds);
334 }
335
336 Ok(unsafe { self.read_u16_be_full_at_unchecked(offset) })
337 }
338
339 #[inline(always)]
347 pub fn try_read_u16_be_full(&mut self) -> Result<u16> {
348 let v = self.try_read_u16_be_full_at(self.pos())?;
349 self.advance_bytes(2);
350 Ok(v)
351 }
352
353 #[inline(always)]
360 #[must_use]
361 pub fn read_u16_be_full_at(&self, offset: usize) -> u16 {
362 self
363 .try_read_u16_be_full_at(offset)
364 .expect("BitBuf::read_u16_be_full_at out of bounds")
365 }
366
367 #[inline(always)]
374 #[must_use]
375 pub fn read_u16_be_full(&mut self) -> u16 {
376 self
377 .try_read_u16_be_full()
378 .expect("BitBuf::read_u16_be_full out of bounds")
379 }
380
381 #[inline(always)]
391 #[must_use]
392 pub unsafe fn read_u32_be_aligned_full_at_unchecked(&self, byte_offset: usize) -> u32 {
393 let bytes = self.bytes();
394
395 debug_assert!(
396 byte_offset + 3 < bytes.len(),
397 "BitBuf::read_u32_be_aligned_full_at_unchecked: index out of bounds! len is {}, offset is {}",
398 bytes.len(),
399 byte_offset + 3,
400 );
401
402 unsafe {
403 let a = *bytes.get_unchecked(byte_offset);
404 let b = *bytes.get_unchecked(byte_offset + 1);
405 let c = *bytes.get_unchecked(byte_offset + 2);
406 let d = *bytes.get_unchecked(byte_offset + 3);
407 u32::from_be_bytes([a, b, c, d])
408 }
409 }
410
411 #[inline(always)]
423 #[must_use]
424 pub unsafe fn read_u32_be_aligned_full_unchecked(&mut self) -> u32 {
425 debug_assert!(
426 self.is_aligned(),
427 "BitBuf::read_u32_be_aligned_full_unchecked called at unaligned bit position: {}",
428 self.pos(),
429 );
430
431 let v = unsafe { self.read_u32_be_aligned_full_at_unchecked(self.byte_pos()) };
432 self.advance_bytes(4);
433 v
434 }
435
436 #[inline(always)]
448 #[must_use]
449 pub unsafe fn read_u32_be_full_at_unchecked(&self, offset: usize) -> u32 {
450 let first_idx = offset / 8;
451 let shift = offset % 8;
452
453 let bytes = self.bytes();
454
455 debug_assert!(
456 first_idx + 3 < bytes.len(),
457 "BitBuf::read_u32_be_full_at_unchecked: index out of bounds! len is {}, byte_idx is {}",
458 bytes.len(),
459 first_idx + 3,
460 );
461
462 if shift == 0 {
463 unsafe { self.read_u32_be_aligned_full_at_unchecked(first_idx) }
464 } else {
465 let second_idx = first_idx + 1;
466 let third_idx = first_idx + 2;
467 let fourth_idx = first_idx + 3;
468 let fifth_idx = first_idx + 4;
469
470 debug_assert!(
471 fifth_idx < bytes.len(),
472 "BitBuf::read_u32_be_full_at_unchecked: lookahead index out of bounds! len is {}, lookahead byte_idx is {}",
473 bytes.len(),
474 fifth_idx,
475 );
476
477 let (a, b, c, d, e) = unsafe {
478 (
479 *bytes.get_unchecked(first_idx),
480 *bytes.get_unchecked(second_idx),
481 *bytes.get_unchecked(third_idx),
482 *bytes.get_unchecked(fourth_idx),
483 *bytes.get_unchecked(fifth_idx),
484 )
485 };
486
487 let b0 = ((a as u32) << shift) | ((b as u32) >> (8 - shift));
488 let b1 = ((b as u32) << shift) | ((c as u32) >> (8 - shift));
489 let b2 = ((c as u32) << shift) | ((d as u32) >> (8 - shift));
490 let b3 = ((d as u32) << shift) | ((e as u32) >> (8 - shift));
491
492 (b0 << 24) | ((b1 & 0xFF) << 16) | ((b2 & 0xFF) << 8) | (b3 & 0xFF)
493 }
494 }
495
496 #[inline(always)]
508 #[must_use]
509 pub unsafe fn read_u32_be_full_unchecked(&mut self) -> u32 {
510 let v = unsafe { self.read_u32_be_full_at_unchecked(self.pos()) };
511 self.advance_bytes(4);
512 v
513 }
514
515 #[inline(always)]
523 pub fn try_read_u32_be_full_at(&self, offset: usize) -> Result<u32> {
524 let first_idx = offset / 8;
525 let shift = offset % 8;
526
527 let len = self.bytes().len();
528
529 if first_idx + 3 >= len {
530 return Err(Error::OutOfBounds);
531 }
532
533 if shift != 0 && first_idx + 4 >= len {
534 return Err(Error::OutOfBounds);
535 }
536
537 Ok(unsafe { self.read_u32_be_full_at_unchecked(offset) })
538 }
539
540 #[inline(always)]
548 pub fn try_read_u32_be_full(&mut self) -> Result<u32> {
549 let v = self.try_read_u32_be_full_at(self.pos())?;
550 self.advance_bytes(4);
551 Ok(v)
552 }
553
554 #[inline(always)]
561 #[must_use]
562 pub fn read_u32_be_full_at(&self, offset: usize) -> u32 {
563 self
564 .try_read_u32_be_full_at(offset)
565 .expect("BitBuf::read_u32_be_full_at out of bounds")
566 }
567
568 #[inline(always)]
575 #[must_use]
576 pub fn read_u32_be_full(&mut self) -> u32 {
577 self
578 .try_read_u32_be_full()
579 .expect("BitBuf::read_u32_be_full out of bounds")
580 }
581}
582
583pub trait Read: Sized {
584 unsafe fn read_be_aligned_full_at_unchecked<S: Storage>(
585 buf: &BitBuf<S>,
586 byte_offset: usize,
587 ) -> Self;
588
589 unsafe fn read_be_aligned_full_unchecked<S: Storage>(buf: &mut BitBuf<S>) -> Self;
590
591 unsafe fn read_be_full_at_unchecked<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Self;
592
593 unsafe fn read_be_full_unchecked<S: Storage>(buf: &mut BitBuf<S>) -> Self;
594
595 fn try_read_be_full_at<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Result<Self>;
596
597 fn try_read_be_full<S: Storage>(buf: &mut BitBuf<S>) -> Result<Self>;
598
599 fn read_be_full_at<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Self;
600
601 fn read_be_full<S: Storage>(buf: &mut BitBuf<S>) -> Self;
602}
603
604impl Read for u8 {
605 #[inline(always)]
606 unsafe fn read_be_aligned_full_at_unchecked<S: Storage>(
607 buf: &BitBuf<S>,
608 byte_offset: usize,
609 ) -> Self {
610 unsafe { buf.read_u8_be_aligned_full_at_unchecked(byte_offset) }
611 }
612
613 #[inline(always)]
614 unsafe fn read_be_aligned_full_unchecked<S: Storage>(buf: &mut BitBuf<S>) -> Self {
615 unsafe { buf.read_u8_be_aligned_full_unchecked() }
616 }
617
618 #[inline(always)]
619 unsafe fn read_be_full_at_unchecked<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Self {
620 unsafe { buf.read_u8_be_full_at_unchecked(offset) }
621 }
622
623 #[inline(always)]
624 unsafe fn read_be_full_unchecked<S: Storage>(buf: &mut BitBuf<S>) -> Self {
625 unsafe { buf.read_u8_be_full_unchecked() }
626 }
627
628 #[inline(always)]
629 fn try_read_be_full_at<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Result<Self> {
630 buf.try_read_u8_be_full_at(offset)
631 }
632
633 #[inline(always)]
634 fn try_read_be_full<S: Storage>(buf: &mut BitBuf<S>) -> Result<Self> {
635 buf.try_read_u8_be_full()
636 }
637
638 #[inline(always)]
639 fn read_be_full_at<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Self {
640 buf.read_u8_be_full_at(offset)
641 }
642
643 #[inline(always)]
644 fn read_be_full<S: Storage>(buf: &mut BitBuf<S>) -> Self {
645 buf.read_u8_be_full()
646 }
647}
648
649impl Read for u16 {
650 #[inline(always)]
651 unsafe fn read_be_aligned_full_at_unchecked<S: Storage>(
652 buf: &BitBuf<S>,
653 byte_offset: usize,
654 ) -> Self {
655 unsafe { buf.read_u16_be_aligned_full_at_unchecked(byte_offset) }
656 }
657
658 #[inline(always)]
659 unsafe fn read_be_aligned_full_unchecked<S: Storage>(buf: &mut BitBuf<S>) -> Self {
660 unsafe { buf.read_u16_be_aligned_full_unchecked() }
661 }
662
663 #[inline(always)]
664 unsafe fn read_be_full_at_unchecked<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Self {
665 unsafe { buf.read_u16_be_full_at_unchecked(offset) }
666 }
667
668 #[inline(always)]
669 unsafe fn read_be_full_unchecked<S: Storage>(buf: &mut BitBuf<S>) -> Self {
670 unsafe { buf.read_u16_be_full_unchecked() }
671 }
672
673 #[inline(always)]
674 fn try_read_be_full_at<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Result<Self> {
675 buf.try_read_u16_be_full_at(offset)
676 }
677
678 #[inline(always)]
679 fn try_read_be_full<S: Storage>(buf: &mut BitBuf<S>) -> Result<Self> {
680 buf.try_read_u16_be_full()
681 }
682
683 #[inline(always)]
684 fn read_be_full_at<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Self {
685 buf.read_u16_be_full_at(offset)
686 }
687
688 #[inline(always)]
689 fn read_be_full<S: Storage>(buf: &mut BitBuf<S>) -> Self {
690 buf.read_u16_be_full()
691 }
692}
693
694impl Read for u32 {
695 #[inline(always)]
696 unsafe fn read_be_aligned_full_at_unchecked<S: Storage>(
697 buf: &BitBuf<S>,
698 byte_offset: usize,
699 ) -> Self {
700 unsafe { buf.read_u32_be_aligned_full_at_unchecked(byte_offset) }
701 }
702
703 #[inline(always)]
704 unsafe fn read_be_aligned_full_unchecked<S: Storage>(buf: &mut BitBuf<S>) -> Self {
705 unsafe { buf.read_u32_be_aligned_full_unchecked() }
706 }
707
708 #[inline(always)]
709 unsafe fn read_be_full_at_unchecked<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Self {
710 unsafe { buf.read_u32_be_full_at_unchecked(offset) }
711 }
712
713 #[inline(always)]
714 unsafe fn read_be_full_unchecked<S: Storage>(buf: &mut BitBuf<S>) -> Self {
715 unsafe { buf.read_u32_be_full_unchecked() }
716 }
717
718 #[inline(always)]
719 fn try_read_be_full_at<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Result<Self> {
720 buf.try_read_u32_be_full_at(offset)
721 }
722
723 #[inline(always)]
724 fn try_read_be_full<S: Storage>(buf: &mut BitBuf<S>) -> Result<Self> {
725 buf.try_read_u32_be_full()
726 }
727
728 #[inline(always)]
729 fn read_be_full_at<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Self {
730 buf.read_u32_be_full_at(offset)
731 }
732
733 #[inline(always)]
734 fn read_be_full<S: Storage>(buf: &mut BitBuf<S>) -> Self {
735 buf.read_u32_be_full()
736 }
737}
738
739impl<S: Storage> BitBuf<S> {
740 #[inline(always)]
750 #[must_use]
751 pub unsafe fn read_be_aligned_full_at_unchecked<T: Read>(&self, byte_offset: usize) -> T {
752 unsafe { T::read_be_aligned_full_at_unchecked(self, byte_offset) }
753 }
754
755 #[inline(always)]
765 #[must_use]
766 pub unsafe fn read_be_aligned_full_unchecked<T: Read>(&mut self) -> T {
767 unsafe { T::read_be_aligned_full_unchecked(self) }
768 }
769
770 #[inline(always)]
780 #[must_use]
781 pub unsafe fn read_be_full_at_unchecked<T: Read>(&self, offset: usize) -> T {
782 unsafe { T::read_be_full_at_unchecked(self, offset) }
783 }
784
785 #[inline(always)]
795 #[must_use]
796 pub unsafe fn read_be_full_unchecked<T: Read>(&mut self) -> T {
797 unsafe { T::read_be_full_unchecked(self) }
798 }
799
800 #[inline(always)]
806 pub fn try_read_be_full_at<T: Read>(&self, offset: usize) -> Result<T> {
807 T::try_read_be_full_at(self, offset)
808 }
809
810 #[inline(always)]
816 pub fn try_read_be_full<T: Read>(&mut self) -> Result<T> {
817 T::try_read_be_full(self)
818 }
819
820 #[inline(always)]
826 #[must_use]
827 pub fn read_be_full_at<T: Read>(&self, offset: usize) -> T {
828 T::read_be_full_at(self, offset)
829 }
830
831 #[inline(always)]
837 #[must_use]
838 pub fn read_be_full<T: Read>(&mut self) -> T {
839 T::read_be_full(self)
840 }
841}