1use crate::{BitBuf, Error, Result, Storage, ensure};
2
3impl_read! {
4 u8;
5 bytes = 1;
6 bits = 8;
7 offset = 0;
8 [a];
9 [a, b];
10
11 read_u8_be_aligned_at_unchecked;
12 read_u8_be_aligned_unchecked;
13 read_u8_be_at_unchecked;
14 read_u8_be_unchecked;
15 try_read_u8_be_aligned_at;
16 try_read_u8_be_aligned;
17 try_read_u8_be_at;
18 try_read_u8_be;
19 read_u8_be_aligned_at;
20 read_u8_be_aligned;
21 read_u8_be_at;
22 read_u8_be;
23
24 read_u8_be_aligned_bits_at_unchecked;
25 read_u8_be_aligned_bits_unchecked;
26 try_read_u8_be_aligned_bits_at;
27 try_read_u8_be_aligned_bits;
28 read_u8_be_aligned_bits_at;
29 read_u8_be_aligned_bits;
30}
31
32impl_read! {
33 u16;
34 bytes = 2;
35 bits = 16;
36 offset = 1;
37 [a, b];
38 [a, [b], c];
39
40 read_u16_be_aligned_at_unchecked;
41 read_u16_be_aligned_unchecked;
42 read_u16_be_at_unchecked;
43 read_u16_be_unchecked;
44 try_read_u16_be_aligned_at;
45 try_read_u16_be_aligned;
46 try_read_u16_be_at;
47 try_read_u16_be;
48 read_u16_be_aligned_at;
49 read_u16_be_aligned;
50 read_u16_be_at;
51 read_u16_be;
52
53 read_u16_be_aligned_bits_at_unchecked;
54 read_u16_be_aligned_bits_unchecked;
55 try_read_u16_be_aligned_bits_at;
56 try_read_u16_be_aligned_bits;
57 read_u16_be_aligned_bits_at;
58 read_u16_be_aligned_bits;
59}
60
61impl_read! {
62 u32;
63 bytes = 4;
64 bits = 32;
65 offset = 3;
66 [a, b, c, d];
67 [a, [b, c, d], e];
68
69 read_u32_be_aligned_at_unchecked;
70 read_u32_be_aligned_unchecked;
71 read_u32_be_at_unchecked;
72 read_u32_be_unchecked;
73 try_read_u32_be_aligned_at;
74 try_read_u32_be_aligned;
75 try_read_u32_be_at;
76 try_read_u32_be;
77 read_u32_be_aligned_at;
78 read_u32_be_aligned;
79 read_u32_be_at;
80 read_u32_be;
81
82 read_u32_be_aligned_bits_at_unchecked;
83 read_u32_be_aligned_bits_unchecked;
84 try_read_u32_be_aligned_bits_at;
85 try_read_u32_be_aligned_bits;
86 read_u32_be_aligned_bits_at;
87 read_u32_be_aligned_bits;
88}
89
90impl_read! {
91 u64;
92 bytes = 8;
93 bits = 64;
94 offset = 7;
95 [a, b, c, d, e, f, g, h];
96 [a, [b, c, d, e, f, g, h], i];
97
98 read_u64_be_aligned_at_unchecked;
99 read_u64_be_aligned_unchecked;
100 read_u64_be_at_unchecked;
101 read_u64_be_unchecked;
102 try_read_u64_be_aligned_at;
103 try_read_u64_be_aligned;
104 try_read_u64_be_at;
105 try_read_u64_be;
106 read_u64_be_aligned_at;
107 read_u64_be_aligned;
108 read_u64_be_at;
109 read_u64_be;
110
111 read_u64_be_aligned_bits_at_unchecked;
112 read_u64_be_aligned_bits_unchecked;
113 try_read_u64_be_aligned_bits_at;
114 try_read_u64_be_aligned_bits;
115 read_u64_be_aligned_bits_at;
116 read_u64_be_aligned_bits;
117}
118
119impl_read! {
120 u128;
121 bytes = 16;
122 bits = 128;
123 offset = 15;
124 [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p];
125 [a, [b, c, d, e, f, g, h, i, j, k, l, m, n, o, p], q];
126
127 read_u128_be_aligned_at_unchecked;
128 read_u128_be_aligned_unchecked;
129 read_u128_be_at_unchecked;
130 read_u128_be_unchecked;
131 try_read_u128_be_aligned_at;
132 try_read_u128_be_aligned;
133 try_read_u128_be_at;
134 try_read_u128_be;
135 read_u128_be_aligned_at;
136 read_u128_be_aligned;
137 read_u128_be_at;
138 read_u128_be;
139
140 read_u128_be_aligned_bits_at_unchecked;
141 read_u128_be_aligned_bits_unchecked;
142 try_read_u128_be_aligned_bits_at;
143 try_read_u128_be_aligned_bits;
144 read_u128_be_aligned_bits_at;
145 read_u128_be_aligned_bits;
146}
147
148pub trait Read: Sized {
149 unsafe fn read_be_aligned_at_unchecked<S: Storage>(buf: &BitBuf<S>, byte_offset: usize) -> Self;
150
151 unsafe fn read_be_aligned_unchecked<S: Storage>(buf: &mut BitBuf<S>) -> Self;
152
153 unsafe fn read_be_at_unchecked<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Self;
154
155 unsafe fn read_be_unchecked<S: Storage>(buf: &mut BitBuf<S>) -> Self;
156
157 fn try_read_be_aligned_at<S: Storage>(buf: &BitBuf<S>, byte_offset: usize) -> Result<Self>;
158
159 fn try_read_be_aligned<S: Storage>(buf: &mut BitBuf<S>) -> Result<Self>;
160
161 fn try_read_be_at<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Result<Self>;
162
163 fn try_read_be<S: Storage>(buf: &mut BitBuf<S>) -> Result<Self>;
164
165 fn read_be_aligned_at<S: Storage>(buf: &BitBuf<S>, byte_offset: usize) -> Self;
166
167 fn read_be_aligned<S: Storage>(buf: &mut BitBuf<S>) -> Self;
168
169 fn read_be_at<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Self;
170
171 fn read_be<S: Storage>(buf: &mut BitBuf<S>) -> Self;
172
173 unsafe fn read_be_aligned_bits_at_unchecked<S: Storage>(
174 buf: &BitBuf<S>,
175 byte_offset: usize,
176 bits: usize,
177 ) -> Self;
178
179 unsafe fn read_be_aligned_bits_unchecked<S: Storage>(buf: &mut BitBuf<S>, bits: usize) -> Self;
180
181 fn try_read_be_aligned_bits_at<S: Storage>(
182 buf: &BitBuf<S>,
183 byte_offset: usize,
184 bits: usize,
185 ) -> Result<Self>;
186
187 fn try_read_be_aligned_bits<S: Storage>(buf: &mut BitBuf<S>, bits: usize) -> Result<Self>;
188
189 fn read_be_aligned_bits_at<S: Storage>(buf: &BitBuf<S>, byte_offset: usize, bits: usize) -> Self;
190
191 fn read_be_aligned_bits<S: Storage>(buf: &mut BitBuf<S>, bits: usize) -> Self;
192}
193
194impl<S: Storage> BitBuf<S> {
195 #[inline(always)]
205 #[must_use]
206 pub unsafe fn read_be_aligned_at_unchecked<T: Read>(&self, byte_offset: usize) -> T {
207 unsafe { T::read_be_aligned_at_unchecked(self, byte_offset) }
208 }
209
210 #[inline(always)]
220 #[must_use]
221 pub unsafe fn read_be_aligned_unchecked<T: Read>(&mut self) -> T {
222 unsafe { T::read_be_aligned_unchecked(self) }
223 }
224
225 #[inline(always)]
235 #[must_use]
236 pub unsafe fn read_be_at_unchecked<T: Read>(&self, offset: usize) -> T {
237 unsafe { T::read_be_at_unchecked(self, offset) }
238 }
239
240 #[inline(always)]
250 #[must_use]
251 pub unsafe fn read_be_unchecked<T: Read>(&mut self) -> T {
252 unsafe { T::read_be_unchecked(self) }
253 }
254
255 #[inline(always)]
261 pub fn try_read_be_aligned_at<T: Read>(&self, byte_offset: usize) -> Result<T> {
262 T::try_read_be_aligned_at(self, byte_offset)
263 }
264
265 #[inline(always)]
271 pub fn try_read_be_aligned<T: Read>(&mut self) -> Result<T> {
272 T::try_read_be_aligned(self)
273 }
274
275 #[inline(always)]
281 pub fn try_read_be_at<T: Read>(&self, offset: usize) -> Result<T> {
282 T::try_read_be_at(self, offset)
283 }
284
285 #[inline(always)]
291 pub fn try_read_be<T: Read>(&mut self) -> Result<T> {
292 T::try_read_be(self)
293 }
294
295 #[inline(always)]
301 #[must_use]
302 pub fn read_be_aligned_at<T: Read>(&self, byte_offset: usize) -> T {
303 T::read_be_aligned_at(self, byte_offset)
304 }
305
306 #[inline(always)]
312 #[must_use]
313 pub fn read_be_aligned<T: Read>(&mut self) -> T {
314 T::read_be_aligned(self)
315 }
316
317 #[inline(always)]
323 #[must_use]
324 pub fn read_be_at<T: Read>(&self, offset: usize) -> T {
325 T::read_be_at(self, offset)
326 }
327
328 #[inline(always)]
334 #[must_use]
335 pub fn read_be<T: Read>(&mut self) -> T {
336 T::read_be(self)
337 }
338
339 #[inline(always)]
349 #[must_use]
350 pub unsafe fn read_be_aligned_bits_at_unchecked<T: Read>(
351 &self,
352 byte_offset: usize,
353 bits: usize,
354 ) -> T {
355 unsafe { T::read_be_aligned_bits_at_unchecked(self, byte_offset, bits) }
356 }
357
358 #[inline(always)]
368 #[must_use]
369 pub unsafe fn read_be_aligned_bits_unchecked<T: Read>(&mut self, bits: usize) -> T {
370 unsafe { T::read_be_aligned_bits_unchecked(self, bits) }
371 }
372
373 #[inline(always)]
379 pub fn try_read_be_aligned_bits_at<T: Read>(&self, byte_offset: usize, bits: usize) -> Result<T> {
380 T::try_read_be_aligned_bits_at(self, byte_offset, bits)
381 }
382
383 #[inline(always)]
389 pub fn try_read_be_aligned_bits<T: Read>(&mut self, bits: usize) -> Result<T> {
390 T::try_read_be_aligned_bits(self, bits)
391 }
392
393 #[inline(always)]
399 #[must_use]
400 pub fn read_be_aligned_bits_at<T: Read>(&self, byte_offset: usize, bits: usize) -> T {
401 T::read_be_aligned_bits_at(self, byte_offset, bits)
402 }
403
404 #[inline(always)]
410 #[must_use]
411 pub fn read_be_aligned_bits<T: Read>(&mut self, bits: usize) -> T {
412 T::read_be_aligned_bits(self, bits)
413 }
414}
415
416macro_rules! impl_read {
417 (
418 $ty:ident;
419 bytes = $bytes:literal;
420 bits = $bits:literal;
421 offset = $offset:literal;
422 [$($byte:ident),*];
423 [$first:ident, $([$($middle:ident),*],)? $last:ident];
424
425 $read_be_aligned_at_unchecked:ident;
426 $read_be_aligned_unchecked:ident;
427 $read_be_at_unchecked:ident;
428 $read_be_unchecked:ident;
429 $try_read_be_aligned_at:ident;
430 $try_read_be_aligned:ident;
431 $try_read_be_at:ident;
432 $try_read_be:ident;
433 $read_be_aligned_at:ident;
434 $read_be_aligned:ident;
435 $read_be_at:ident;
436 $read_be:ident;
437
438 $read_be_aligned_bits_at_unchecked:ident;
439 $read_be_aligned_bits_unchecked:ident;
440 $try_read_be_aligned_bits_at:ident;
441 $try_read_be_aligned_bits:ident;
442 $read_be_aligned_bits_at:ident;
443 $read_be_aligned_bits:ident;
444 ) => {
445 impl<S: Storage> BitBuf<S> {
446 #[doc = concat!("Read a [`", stringify!($ty), "`] in [BE-bit, BE-byte] order from `byte_offset`, without performing bound checks")]
447 #[doc = concat!("* This is UB if <code>byte_offset + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
451 #[doc = concat!("* Panics in debug mode if <code>byte_offset + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
455 #[inline(always)]
456 #[must_use]
457 pub unsafe fn $read_be_aligned_at_unchecked(&self, byte_offset: usize) -> $ty {
458 let bytes = self.bytes();
459 let len = bytes.len();
460
461 ensure!(
462 byte_offset + $offset < len;
463
464 concat!(
465 "BitBuf::",
466 stringify!($read_be_aligned_at_unchecked),
467 ": index out of bounds! len is {}, offset is {}"
468 ),
469 len,
470 byte_offset + $offset,
471 );
472
473 unsafe {
474 $ty::from_be_bytes(
475 *bytes[byte_offset..byte_offset + $bytes]
476 .as_array()
477 .unwrap_unchecked(),
478 )
479 }
480 }
481
482 #[doc = concat!("Read the next [`", stringify!($ty), "`] in [BE-bit, BE-byte] order, without validating cursor alignment or performing bound checks, advancing the internal cursor")]
483 #[doc = concat!("* This is UB if <code>[self.byte_pos()][Self::byte_pos] + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
488 #[doc = concat!("* Panics in debug mode if <code>[self.byte_pos()][Self::byte_pos] + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
493 #[inline(always)]
494 #[must_use]
495 pub unsafe fn $read_be_aligned_unchecked(&mut self) -> $ty {
496 ensure!(
497 self.is_aligned();
498
499 concat!(
500 "BitBuf::",
501 stringify!($read_be_aligned_unchecked),
502 " called at unaligned bit position: {}",
503 ),
504 self.pos(),
505 );
506
507 let v = unsafe { self.$read_be_aligned_at_unchecked(self.byte_pos()) };
508 self.advance_bytes($bytes);
509 v
510 }
511
512 #[doc = concat!("Read a [`", stringify!($ty), "`] in [BE-bit, BE-byte] order from `offset`, without performing bound checks")]
513 #[doc = concat!("* This is UB if <code>(offset / 8) + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
517 #[doc = concat!("* This is UB if <code>(offset % 8 != 0) && (offset / 8) + ", stringify!($bytes), " >= [self.bytes()][Self::bytes].len()</code>")]
518 #[doc = concat!("* Panics in debug mode if <code>(offset / 8) + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
522 #[doc = concat!("* Panics in debug mode if <code>(offset % 8 != 0) && (offset / 8) + ", stringify!($bytes), " >= [self.bytes()][Self::bytes].len()</code>")]
523 #[inline(always)]
524 #[must_use]
525 pub unsafe fn $read_be_at_unchecked(&self, offset: usize) -> $ty {
526 let byte_idx = offset / 8;
527 let shift = offset % 8;
528
529 let bytes = self.bytes();
530 let len = bytes.len();
531
532 ensure!(
533 byte_idx + $offset < len;
534
535 concat!(
536 "BitBuf::",
537 stringify!($read_be_at_unchecked),
538 ": index out of bounds! len is {}, byte_idx is {}",
539 ),
540 len,
541 byte_idx + $offset,
542 );
543
544 if shift == 0 {
545 unsafe { self.$read_be_aligned_at_unchecked(byte_idx) }
546 } else {
547 ensure!(
548 byte_idx + $bytes < len;
549
550 concat!(
551 "BitBuf::",
552 stringify!($read_be_at_unchecked),
553 ": lookahead index out of bounds! len is {}, lookahead byte_idx is {}",
554 ),
555 len,
556 byte_idx + $bytes,
557 );
558
559 unsafe {
560 let ptr = bytes.as_ptr().add(byte_idx);
561 let high = $ty::from_be_bytes(*(ptr as *const [u8; $bytes]));
562 let low = *bytes.get_unchecked(byte_idx + $bytes) as $ty;
563 (high << shift) | (low >> (8 - shift))
564 }
565 }
566 }
567
568 #[doc = concat!("Read the next [`", stringify!($ty), "`] in [BE-bit, BE-byte] order, without performing bound checks, advancing the internal cursor")]
569 #[doc = concat!("* This is UB if <code>([self.pos()][Self::pos] / 8) + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
573 #[doc = concat!("* This is UB if <code>([self.pos()][Self::pos] % 8 != 0) && ([self.pos()][Self::pos] / 8) + ", stringify!($bytes), " >= [self.bytes()][Self::bytes].len()</code>")]
574 #[doc = concat!("* Panics in debug mode if <code>([self.pos()][Self::pos] / 8) + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
578 #[doc = concat!("* Panics in debug mode if <code>([self.pos()][Self::pos] % 8 != 0) && ([self.pos()][Self::pos] / 8) + ", stringify!($bytes), " >= [self.bytes()][Self::bytes].len()</code>")]
579 #[inline(always)]
580 #[must_use]
581 pub unsafe fn $read_be_unchecked(&mut self) -> $ty {
582 let v = unsafe { self.$read_be_at_unchecked(self.pos()) };
583 self.advance_bytes($bytes);
584 v
585 }
586
587 #[doc = concat!("Read a [`", stringify!($ty), "`] in [BE-bit, BE-byte] order from `byte_offset`, performing bound checks")]
588 #[doc = concat!(" * if <code>byte_offset + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
593 #[inline(always)]
594 pub fn $try_read_be_aligned_at(&self, byte_offset: usize) -> Result<$ty> {
595 let len = self.bytes().len();
596
597 if byte_offset + $offset >= len {
598 return Err(Error::OutOfBounds);
599 }
600
601 Ok(unsafe { self.$read_be_aligned_at_unchecked(byte_offset) })
602 }
603
604 #[doc = concat!("Read the next [`", stringify!($ty), "`] in [BE-bit, BE-byte] order, validating cursor alignment and performing bound checks, advancing the internal cursor")]
605 #[doc = concat!(" * if <code>[self.byte_pos()][Self::byte_pos] + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
612 #[inline(always)]
613 pub fn $try_read_be_aligned(&mut self) -> Result<$ty> {
614 if !self.is_aligned() {
615 return Err(Error::Unaligned);
616 }
617
618 let v = self.$try_read_be_aligned_at(self.byte_pos())?;
619 self.advance_bytes($bytes);
620 Ok(v)
621 }
622
623 #[doc = concat!("Read a [`", stringify!($ty), "`] in [BE-bit, BE-byte] order from `offset`, performing bound checks")]
624 #[doc = concat!(" * if <code>(offset / 8) + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
629 #[doc = concat!(" * if <code>(offset % 8 != 0) && (offset / 8) + ", stringify!($bytes), " >= [self.bytes()][Self::bytes].len()</code>")]
630 #[inline(always)]
631 pub fn $try_read_be_at(&self, offset: usize) -> Result<$ty> {
632 let byte_idx = offset / 8;
633 let shift = offset % 8;
634
635 let len = self.bytes().len();
636
637 if byte_idx + $offset >= len {
638 return Err(Error::OutOfBounds);
639 }
640
641 if shift != 0 && byte_idx + $bytes >= len {
642 return Err(Error::OutOfBounds);
643 }
644
645 Ok(unsafe { self.$read_be_at_unchecked(offset) })
646 }
647
648 #[doc = concat!("Read the next [`", stringify!($ty), "`] in [BE-bit, BE-byte] order, performing bound checks, advancing the internal cursor")]
649 #[doc = concat!(" * if <code>([self.pos()][Self::pos] / 8) + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
654 #[doc = concat!(" * if <code>([self.pos()][Self::pos] % 8 != 0) && ([self.pos()][Self::pos] / 8) + ", stringify!($bytes), " >= [self.bytes()][Self::bytes].len()</code>")]
655 #[inline(always)]
656 pub fn $try_read_be(&mut self) -> Result<$ty> {
657 let v = self.$try_read_be_at(self.pos())?;
658 self.advance_bytes($bytes);
659 Ok(v)
660 }
661
662 #[doc = concat!("Read a [`", stringify!($ty), "`] in [BE-bit, BE-byte] order from `byte_offset`, panicking on out of bounds")]
663 #[doc = concat!("* Panics if <code>byte_offset + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
667 #[inline(always)]
668 #[must_use]
669 pub fn $read_be_aligned_at(&self, byte_offset: usize) -> $ty {
670 self
671 .$try_read_be_aligned_at(byte_offset)
672 .expect(concat!("BitBuf::", stringify!($read_be_aligned_at), " out of bounds"))
673 }
674
675 #[doc = concat!("Read the next [`", stringify!($ty), "`] in [BE-bit, BE-byte] order, panicking on an unaligned cursor or out of bounds, advancing the internal cursor")]
676 #[doc = concat!("* if <code>[self.byte_pos()][Self::byte_pos] + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
681 #[inline(always)]
682 #[must_use]
683 pub fn $read_be_aligned(&mut self) -> $ty {
684 self
685 .$try_read_be_aligned()
686 .expect(concat!("BitBuf::", stringify!($read_be_aligned), " unaligned cursor or out of bounds"))
687 }
688
689 #[doc = concat!("Read a [`", stringify!($ty), "`] in [BE-bit, BE-byte] order from `offset`, panicking on out of bounds")]
690 #[doc = concat!("* Panics if <code>(offset / 8) + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
694 #[doc = concat!("* Panics if <code>(offset % 8 != 0) && (offset / 8) + ", stringify!($bytes), " >= [self.bytes()][Self::bytes].len()</code>")]
695 #[inline(always)]
696 #[must_use]
697 pub fn $read_be_at(&self, offset: usize) -> $ty {
698 self
699 .$try_read_be_at(offset)
700 .expect(concat!("BitBuf::", stringify!($read_be_at), " out of bounds"))
701 }
702
703 #[doc = concat!("Read the next [`", stringify!($ty), "`] in [BE-bit, BE-byte] order, panicking on out of bounds, advancing the internal cursor")]
704 #[doc = concat!("* Panics if <code>([self.pos()][Self::pos] / 8) + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
708 #[doc = concat!("* Panics if <code>([self.pos()][Self::pos] % 8 != 0) && ([self.pos()][Self::pos] / 8) + ", stringify!($bytes), " >= [self.bytes()][Self::bytes].len()</code>")]
709 #[inline(always)]
710 #[must_use]
711 pub fn $read_be(&mut self) -> $ty {
712 self
713 .$try_read_be()
714 .expect(concat!("BitBuf::", stringify!($read_be), " out of bounds"))
715 }
716 }
717
718 impl<S: Storage> BitBuf<S> {
719 #[doc = concat!("Read a [`", stringify!($ty), "`] in [BE-bit, BE-byte] order using `bits` bits from `byte_offset`, without validating the bit count or performing bound checks")]
720 #[doc = concat!(" * if `bits > ", stringify!($bits), "`")]
725 #[doc = concat!(" * if <code>byte_offset + [bits.div_ceil(8)][usize::div_ceil] > [self.bytes()][Self::bytes].len()</code>")]
726 #[doc = concat!(" * if `bits > ", stringify!($bits), "`")]
731 #[doc = concat!(" * if <code>byte_offset + [bits.div_ceil(8)][usize::div_ceil] > [self.bytes()][Self::bytes].len()</code>")]
732 #[inline(always)]
733 #[must_use]
734 pub unsafe fn $read_be_aligned_bits_at_unchecked(&self, byte_offset: usize, bits: usize) -> $ty {
735 ensure!(
736 bits <= $bits;
737
738 concat!(
739 "BitBuf::",
740 stringify!($read_be_aligned_bits_at_unchecked),
741 ": bits requested ({}) exceeds ",
742 stringify!($ty),
743 " width!"
744 ),
745 bits,
746 );
747
748 if bits == 0 {
749 return 0;
750 }
751
752 let required_bytes = bits.div_ceil(8);
753
754 let bytes = self.bytes();
755 let len = bytes.len();
756
757 ensure!(
758 byte_offset + required_bytes <= len;
759
760 concat!(
761 "BitBuf::",
762 stringify!($read_be_aligned_bits_at_unchecked),
763 ": index out of bounds! len is {}, required end is {}"
764 ),
765 len,
766 byte_offset + required_bytes,
767 );
768
769 let ptr = unsafe { bytes.as_ptr().add(byte_offset) };
770
771 let v: $ty = unsafe {
779 if bits <= 8 {
780 *bytes.get_unchecked(byte_offset) as _
781 } else if bits <= 16 {
782 u16::from_be_bytes(*(ptr as *const _)) as _
783 } else if bits <= 24 {
784 let hi = u16::from_be_bytes(*(ptr as *const _)) as u32;
785 let lo = *bytes.get_unchecked(byte_offset + 2) as u32;
786 ((hi << 8) | lo) as _
787 } else if bits <= 32 {
788 u32::from_be_bytes(*(ptr as *const _)) as _
789 } else if bits <= 40 {
790 let hi = u32::from_be_bytes(*(ptr as *const _)) as u64;
791 let lo = *ptr.add(4) as u64;
792 ((hi << 8) | lo) as _
793 } else if bits <= 48 {
794 let hi = u32::from_be_bytes(*(ptr as *const _)) as u64;
795 let lo = u16::from_be_bytes(*(ptr.add(4) as *const _)) as u64;
796 ((hi << 16) | lo) as _
797 } else if bits <= 56 {
798 let hi = u32::from_be_bytes(*(ptr as *const _)) as u64;
799 let mid = u16::from_be_bytes(*(ptr.add(4) as *const _)) as u64;
800 let lo = *ptr.add(6) as u64;
801 ((hi << 24) | (mid << 8) | lo) as _
802 } else if bits <= 64 {
803 u64::from_be_bytes(*(ptr as *const _)) as _
804 }
805 else if bits <= 72 {
819 let hi = u64::from_be_bytes(*(ptr as *const _)) as u128;
820 let lo = *ptr.add(8) as u128;
821 ((hi << 8) | lo) as _
822 } else if bits <= 80 {
823 let hi = u64::from_be_bytes(*(ptr as *const _)) as u128;
824 let lo = u16::from_be_bytes(*(ptr.add(8) as *const _)) as u128;
825 ((hi << 16) | lo) as _
826 } else if bits <= 88 {
827 let hi = u64::from_be_bytes(*(ptr as *const _)) as u128;
828 let mid = u16::from_be_bytes(*(ptr.add(8) as *const _)) as u128;
829 let lo = *ptr.add(10) as u128;
830 ((hi << 24) | (mid << 8) | lo) as _
831 } else if bits <= 96 {
832 let hi = u64::from_be_bytes(*(ptr as *const _)) as u128;
833 let lo = u32::from_be_bytes(*(ptr.add(8) as *const _)) as u128;
834 ((hi << 32) | lo) as _
835 } else if bits <= 104 {
836 let hi = u64::from_be_bytes(*(ptr as *const _)) as u128;
837 let mid = u32::from_be_bytes(*(ptr.add(8) as *const _)) as u128;
838 let lo = *ptr.add(12) as u128;
839 ((hi << 40) | (mid << 8) | lo) as _
840 } else if bits <= 112 {
841 let hi = u64::from_be_bytes(*(ptr as *const _)) as u128;
842 let mid = u32::from_be_bytes(*(ptr.add(8) as *const _)) as u128;
843 let lo = u16::from_be_bytes(*(ptr.add(12) as *const _)) as u128;
844 ((hi << 48) | (mid << 16) | lo) as _
845 } else if bits <= 120 {
846 let hi = u64::from_be_bytes(*(ptr as *const _)) as u128;
847 let mid1 = u32::from_be_bytes(*(ptr.add(8) as *const _)) as u128;
848 let mid2 = u16::from_be_bytes(*(ptr.add(12) as *const _)) as u128;
849 let lo = *ptr.add(14) as u128;
850 ((hi << 56) | (mid1 << 24) | (mid2 << 8) | lo) as _
851 } else {
852 u128::from_be_bytes(*(ptr as *const _)) as _
853 }
854 };
855
856 v >> ((required_bytes * 8) - bits)
859 }
860
861 #[doc = concat!("Read the next [`", stringify!($ty), "`] in [BE-bit, BE-byte] order using `bits` bits, without validating cursor alignment, the bit count, or performing bound checks, advancing the internal cursor")]
862 #[doc = concat!(" * if `bits > ", stringify!($bits), "`")]
868 #[doc = concat!(" * if <code>[self.byte_pos()][Self::byte_pos] + [bits.div_ceil(8)][usize::div_ceil] > [self.bytes()][Self::bytes].len()</code>")]
869 #[doc = concat!(" * if `bits > ", stringify!($bits), "`")]
875 #[doc = concat!(" * if <code>[self.byte_pos()][Self::byte_pos] + [bits.div_ceil(8)][usize::div_ceil] > [self.bytes()][Self::bytes].len()</code>")]
876 #[inline(always)]
877 #[must_use]
878 pub unsafe fn $read_be_aligned_bits_unchecked(&mut self, bits: usize) -> $ty {
879 ensure!(
880 self.is_aligned();
881
882 concat!(
883 "BitBuf::",
884 stringify!($read_be_aligned_bits_unchecked),
885 " called at unaligned bit position: {}",
886 ),
887 self.pos(),
888 );
889
890 let v = unsafe { self.$read_be_aligned_bits_at_unchecked(self.byte_pos(), bits) };
891 self.advance(bits);
892 v
893 }
894
895 #[doc = concat!("Read a [`", stringify!($ty), "`] in [BE-bit, BE-byte] order using `bits` bits from `byte_offset`, validating the bit count and performing bound checks")]
896 #[doc = concat!(" * if `bits > ", stringify!($bits), "`")]
901 #[doc = concat!(" * if <code>byte_offset + [bits.div_ceil(8)][usize::div_ceil] > [self.bytes()][Self::bytes].len()</code>")]
903 #[inline(always)]
904 pub fn $try_read_be_aligned_bits_at(&self, byte_offset: usize, bits: usize) -> Result<$ty> {
905 if bits > $bits {
906 return Err(Error::InvalidBitCount);
907 }
908
909 let required_bytes = bits.div_ceil(8);
910
911 let len = self.bytes().len();
912
913 if byte_offset + required_bytes > len {
914 return Err(Error::OutOfBounds);
915 }
916
917 Ok(unsafe { self.$read_be_aligned_bits_at_unchecked(byte_offset, bits) })
918 }
919
920 #[doc = concat!("Read the next [`", stringify!($ty), "`] in [BE-bit, BE-byte] order using `bits` bits, validating cursor alignment, the bit count, and performing bound checks, advancing the internal cursor")]
921 #[doc = concat!(" * if `bits > ", stringify!($bits), "`")]
928 #[doc = concat!(" * if <code>[self.byte_pos()][Self::byte_pos] + [bits.div_ceil(8)][usize::div_ceil] > [self.bytes()][Self::bytes].len()</code>")]
930 #[inline(always)]
931 pub fn $try_read_be_aligned_bits(&mut self, bits: usize) -> Result<$ty> {
932 if !self.is_aligned() {
933 return Err(Error::Unaligned);
934 }
935
936 let v = self.$try_read_be_aligned_bits_at(self.byte_pos(), bits)?;
937 self.advance(bits);
938 Ok(v)
939 }
940
941 #[doc = concat!("Read a [`", stringify!($ty), "`] in [BE-bit, BE-byte] order using `bits` bits from `byte_offset`, panicking on an invalid bit count or out of bounds")]
942 #[doc = concat!(" * if `bits > ", stringify!($bits), "`")]
945 #[doc = concat!(" * if <code>byte_offset + [bits.div_ceil(8)][usize::div_ceil] > [self.bytes()][Self::bytes].len()</code>")]
946 #[inline(always)]
947 pub fn $read_be_aligned_bits_at(&self, byte_offset: usize, bits: usize) -> $ty {
948 self
949 .$try_read_be_aligned_bits_at(byte_offset, bits)
950 .expect(concat!("BitBuf::", stringify!($read_be_aligned_bits_at), " invalid bit count or out of bounds"))
951 }
952
953 #[doc = concat!("Read the next [`", stringify!($ty), "`] in [BE-bit, BE-byte] order using `bits` bits, panicking on an unaligned cursor, invalid bit count, or out of bounds, advancing the internal cursor")]
954 #[doc = concat!(" * if `bits > ", stringify!($bits), "`")]
958 #[doc = concat!(" * if <code>[self.byte_pos()][Self::byte_pos] + [bits.div_ceil(8)][usize::div_ceil] > [self.bytes()][Self::bytes].len()</code>")]
959 #[inline(always)]
960 pub fn $read_be_aligned_bits(&mut self, bits: usize) -> $ty {
961 self
962 .$try_read_be_aligned_bits(bits)
963 .expect(concat!("BitBuf::", stringify!($read_be_aligned_bits), " unaligned cursor, invalid bit count, or out of bounds"))
964 }
965 }
966
967 impl Read for $ty {
968 #[inline(always)]
969 unsafe fn read_be_aligned_at_unchecked<S: Storage>(buf: &BitBuf<S>, byte_offset: usize) -> Self {
970 unsafe { buf.$read_be_aligned_at_unchecked(byte_offset) }
971 }
972
973 #[inline(always)]
974 unsafe fn read_be_aligned_unchecked<S: Storage>(buf: &mut BitBuf<S>) -> Self {
975 unsafe { buf.$read_be_aligned_unchecked() }
976 }
977
978 #[inline(always)]
979 unsafe fn read_be_at_unchecked<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Self {
980 unsafe { buf.$read_be_at_unchecked(offset) }
981 }
982
983 #[inline(always)]
984 unsafe fn read_be_unchecked<S: Storage>(buf: &mut BitBuf<S>) -> Self {
985 unsafe { buf.$read_be_unchecked() }
986 }
987
988 #[inline(always)]
989 fn try_read_be_aligned_at<S: Storage>(buf: &BitBuf<S>, byte_offset: usize) -> Result<Self> {
990 buf.$try_read_be_aligned_at(byte_offset)
991 }
992
993 #[inline(always)]
994 fn try_read_be_aligned<S: Storage>(buf: &mut BitBuf<S>) -> Result<Self> {
995 buf.$try_read_be_aligned()
996 }
997
998 #[inline(always)]
999 fn try_read_be_at<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Result<Self> {
1000 buf.$try_read_be_at(offset)
1001 }
1002
1003 #[inline(always)]
1004 fn try_read_be<S: Storage>(buf: &mut BitBuf<S>) -> Result<Self> {
1005 buf.$try_read_be()
1006 }
1007
1008 #[inline(always)]
1009 fn read_be_aligned_at<S: Storage>(buf: &BitBuf<S>, byte_offset: usize) -> Self {
1010 buf.$read_be_aligned_at(byte_offset)
1011 }
1012
1013 #[inline(always)]
1014 fn read_be_aligned<S: Storage>(buf: &mut BitBuf<S>) -> Self {
1015 buf.$read_be_aligned()
1016 }
1017
1018 #[inline(always)]
1019 fn read_be_at<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Self {
1020 buf.$read_be_at(offset)
1021 }
1022
1023 #[inline(always)]
1024 fn read_be<S: Storage>(buf: &mut BitBuf<S>) -> Self {
1025 buf.$read_be()
1026 }
1027
1028 #[inline(always)]
1029 unsafe fn read_be_aligned_bits_at_unchecked<S: Storage>(buf: &BitBuf<S>, byte_offset: usize, bits: usize) -> Self {
1030 unsafe { buf.$read_be_aligned_bits_at_unchecked(byte_offset, bits) }
1031 }
1032
1033 #[inline(always)]
1034 unsafe fn read_be_aligned_bits_unchecked<S: Storage>(buf: &mut BitBuf<S>, bits: usize) -> Self {
1035 unsafe { buf.$read_be_aligned_bits_unchecked(bits) }
1036 }
1037
1038 #[inline(always)]
1039 fn try_read_be_aligned_bits_at<S: Storage>(buf: &BitBuf<S>, byte_offset: usize, bits: usize) -> Result<Self> {
1040 buf.$try_read_be_aligned_bits_at(byte_offset, bits)
1041 }
1042
1043 #[inline(always)]
1044 fn try_read_be_aligned_bits<S: Storage>(buf: &mut BitBuf<S>, bits: usize) -> Result<Self> {
1045 buf.$try_read_be_aligned_bits(bits)
1046 }
1047
1048 #[inline(always)]
1049 fn read_be_aligned_bits_at<S: Storage>(buf: &BitBuf<S>, byte_offset: usize, bits: usize) -> Self {
1050 buf.$read_be_aligned_bits_at(byte_offset, bits)
1051 }
1052
1053 #[inline(always)]
1054 fn read_be_aligned_bits<S: Storage>(buf: &mut BitBuf<S>, bits: usize) -> Self {
1055 buf.$read_be_aligned_bits(bits)
1056 }
1057 }
1058 };
1059}
1060
1061use impl_read;