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
382pub trait Read: Sized {
383 unsafe fn read_be_aligned_full_at_unchecked<S: Storage>(
384 buf: &BitBuf<S>,
385 byte_offset: usize,
386 ) -> Self;
387
388 unsafe fn read_be_aligned_full_unchecked<S: Storage>(buf: &mut BitBuf<S>) -> Self;
389
390 unsafe fn read_be_full_at_unchecked<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Self;
391
392 unsafe fn read_be_full_unchecked<S: Storage>(buf: &mut BitBuf<S>) -> Self;
393
394 fn try_read_be_full_at<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Result<Self>;
395
396 fn try_read_be_full<S: Storage>(buf: &mut BitBuf<S>) -> Result<Self>;
397
398 fn read_be_full_at<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Self;
399
400 fn read_be_full<S: Storage>(buf: &mut BitBuf<S>) -> Self;
401}
402
403impl Read for u8 {
404 #[inline(always)]
405 unsafe fn read_be_aligned_full_at_unchecked<S: Storage>(
406 buf: &BitBuf<S>,
407 byte_offset: usize,
408 ) -> Self {
409 unsafe { buf.read_u8_be_aligned_full_at_unchecked(byte_offset) }
410 }
411
412 #[inline(always)]
413 unsafe fn read_be_aligned_full_unchecked<S: Storage>(buf: &mut BitBuf<S>) -> Self {
414 unsafe { buf.read_u8_be_aligned_full_unchecked() }
415 }
416
417 #[inline(always)]
418 unsafe fn read_be_full_at_unchecked<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Self {
419 unsafe { buf.read_u8_be_full_at_unchecked(offset) }
420 }
421
422 #[inline(always)]
423 unsafe fn read_be_full_unchecked<S: Storage>(buf: &mut BitBuf<S>) -> Self {
424 unsafe { buf.read_u8_be_full_unchecked() }
425 }
426
427 #[inline(always)]
428 fn try_read_be_full_at<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Result<Self> {
429 buf.try_read_u8_be_full_at(offset)
430 }
431
432 #[inline(always)]
433 fn try_read_be_full<S: Storage>(buf: &mut BitBuf<S>) -> Result<Self> {
434 buf.try_read_u8_be_full()
435 }
436
437 #[inline(always)]
438 fn read_be_full_at<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Self {
439 buf.read_u8_be_full_at(offset)
440 }
441
442 #[inline(always)]
443 fn read_be_full<S: Storage>(buf: &mut BitBuf<S>) -> Self {
444 buf.read_u8_be_full()
445 }
446}
447
448impl Read for u16 {
449 #[inline(always)]
450 unsafe fn read_be_aligned_full_at_unchecked<S: Storage>(
451 buf: &BitBuf<S>,
452 byte_offset: usize,
453 ) -> Self {
454 unsafe { buf.read_u16_be_aligned_full_at_unchecked(byte_offset) }
455 }
456
457 #[inline(always)]
458 unsafe fn read_be_aligned_full_unchecked<S: Storage>(buf: &mut BitBuf<S>) -> Self {
459 unsafe { buf.read_u16_be_aligned_full_unchecked() }
460 }
461
462 #[inline(always)]
463 unsafe fn read_be_full_at_unchecked<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Self {
464 unsafe { buf.read_u16_be_full_at_unchecked(offset) }
465 }
466
467 #[inline(always)]
468 unsafe fn read_be_full_unchecked<S: Storage>(buf: &mut BitBuf<S>) -> Self {
469 unsafe { buf.read_u16_be_full_unchecked() }
470 }
471
472 #[inline(always)]
473 fn try_read_be_full_at<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Result<Self> {
474 buf.try_read_u16_be_full_at(offset)
475 }
476
477 #[inline(always)]
478 fn try_read_be_full<S: Storage>(buf: &mut BitBuf<S>) -> Result<Self> {
479 buf.try_read_u16_be_full()
480 }
481
482 #[inline(always)]
483 fn read_be_full_at<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Self {
484 buf.read_u16_be_full_at(offset)
485 }
486
487 #[inline(always)]
488 fn read_be_full<S: Storage>(buf: &mut BitBuf<S>) -> Self {
489 buf.read_u16_be_full()
490 }
491}
492
493impl<S: Storage> BitBuf<S> {
494 #[inline(always)]
504 #[must_use]
505 pub unsafe fn read_be_aligned_full_at_unchecked<T: Read>(&self, byte_offset: usize) -> T {
506 unsafe { T::read_be_aligned_full_at_unchecked(self, byte_offset) }
507 }
508
509 #[inline(always)]
519 #[must_use]
520 pub unsafe fn read_be_aligned_full_unchecked<T: Read>(&mut self) -> T {
521 unsafe { T::read_be_aligned_full_unchecked(self) }
522 }
523
524 #[inline(always)]
534 #[must_use]
535 pub unsafe fn read_be_full_at_unchecked<T: Read>(&self, offset: usize) -> T {
536 unsafe { T::read_be_full_at_unchecked(self, offset) }
537 }
538
539 #[inline(always)]
549 #[must_use]
550 pub unsafe fn read_be_full_unchecked<T: Read>(&mut self) -> T {
551 unsafe { T::read_be_full_unchecked(self) }
552 }
553
554 #[inline(always)]
560 pub fn try_read_be_full_at<T: Read>(&self, offset: usize) -> Result<T> {
561 T::try_read_be_full_at(self, offset)
562 }
563
564 #[inline(always)]
570 pub fn try_read_be_full<T: Read>(&mut self) -> Result<T> {
571 T::try_read_be_full(self)
572 }
573
574 #[inline(always)]
580 #[must_use]
581 pub fn read_be_full_at<T: Read>(&self, offset: usize) -> T {
582 T::read_be_full_at(self, offset)
583 }
584
585 #[inline(always)]
591 #[must_use]
592 pub fn read_be_full<T: Read>(&mut self) -> T {
593 T::read_be_full(self)
594 }
595}