Skip to main content

bit_buf/
read.rs

1use crate::{BitBuf, Error, Result, Storage};
2
3impl<S: Storage> BitBuf<S> {
4  /// Read a BE-bit-order [`u8`] from `byte_offset` without performing bound checks
5  ///
6  /// # Safety
7  ///
8  /// * This is UB if [`byte_offset >= self.bytes().len()`][Self::bytes]
9  ///
10  /// # Panics
11  ///
12  /// * Panics in debug mode if [`byte_offset >= self.bytes().len()`][Self::bytes]
13  #[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  /// Read the next BE-bit-order [`u8`] without performing bound checks, advancing the internal cursor
29  ///
30  /// # Safety
31  ///
32  /// * The internal cursor must be byte-aligned ([`self.is_aligned()`][Self::is_aligned])
33  /// * This is UB if the internal cursor points past the end of storage (<code>[self.byte_pos()][Self::byte_pos] >= [self.bytes().len()][Self::bytes]</code>)
34  ///
35  /// # Panics
36  ///
37  /// * Panics in debug mode if the internal cursor is not byte-aligned ([`!self.is_aligned()`][Self::is_aligned])
38  /// * Panics in debug mode if the internal cursor points past the end of storage (<code>[self.byte_pos()][Self::byte_pos] >= [self.bytes().len()][Self::bytes]</code>)
39  #[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  /// Read a BE-bit-order [`u8`] from `offset` without performing bound checks
54  ///
55  /// # Safety
56  ///
57  /// * This is UB if <code>(offset / 8) >= [`self.bytes().len()`][Self::bytes]</code>
58  /// * This is UB if <code>(offset % 8 != 0) && (offset / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
59  ///
60  /// # Panics
61  ///
62  /// * Panics in debug mode if <code>(offset / 8) >= [`self.bytes().len()`][Self::bytes]</code>
63  /// * Panics in debug mode if <code>(offset % 8 != 0) && (offset / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
64  #[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  /// Read the next BE-bit-order [`u8`] without performing bound checks, advancing the internal cursor
103  ///
104  /// # Safety
105  ///
106  /// * This is UB if <code>(self.pos() / 8) >= [`self.bytes().len()`][Self::bytes]</code>
107  /// * This is UB if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
108  ///
109  /// # Panics
110  ///
111  /// * Panics in debug mode if <code>(self.pos() / 8) >= [`self.bytes().len()`][Self::bytes]</code>
112  /// * Panics in debug mode if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
113  #[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  /// Read a BE-bit-order [`u8`] from `offset` while performing bound checks
122  ///
123  /// # Errors
124  ///
125  /// * Returns [`Error::OutOfBounds`]
126  ///   * if <code>(offset / 8) >= [`self.bytes().len()`][Self::bytes]</code>
127  ///   * if <code>(offset % 8 != 0) && (offset / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
128  #[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  /// Read the next BE-bit-order [`u8`] while performing bound checks, advancing the internal cursor
147  ///
148  /// # Errors
149  ///
150  /// * Returns [`Error::OutOfBounds`]
151  ///   * if <code>(self.pos() / 8) >= [`self.bytes().len()`][Self::bytes]</code>
152  ///   * if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
153  #[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  /// Read a BE-bit-order [`u8`] from `offset`, panicking on out of bounds
161  ///
162  /// # Panics
163  ///
164  /// * Panics if <code>(offset / 8) >= [`self.bytes().len()`][Self::bytes]</code>
165  /// * Panics if <code>(offset % 8 != 0) && (offset / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
166  #[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  /// Read the next BE-bit-order [`u8`], panicking on out of bounds, advancing the internal cursor
175  ///
176  /// # Panics
177  ///
178  /// * Panics if <code>(self.pos() / 8) >= [`self.bytes().len()`][Self::bytes]</code>
179  /// * Panics if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
180  #[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  /// Read a [BE-bit, BE-byte] order [`u16`] from `byte_offset` without performing bound checks
189  ///
190  /// # Safety
191  ///
192  /// * This is UB if [`byte_offset + 1 >= self.bytes().len()`][Self::bytes]
193  ///
194  /// # Panics
195  ///
196  /// * Panics in debug mode if [`byte_offset + 1 >= self.bytes().len()`][Self::bytes]
197  #[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  /// Read the next [BE-bit, BE-byte] order [`u16`] without performing bound checks, advancing the internal cursor
217  ///
218  /// # Safety
219  ///
220  /// * The internal cursor must be byte-aligned ([`self.is_aligned()`][Self::is_aligned])
221  /// * This is UB if the internal cursor points past the end of storage (<code>[self.byte_pos()][Self::byte_pos] + 1 >= [self.bytes().len()][Self::bytes]</code>)
222  ///
223  /// # Panics
224  ///
225  /// * Panics in debug mode if the internal cursor is not byte-aligned ([`!self.is_aligned()`][Self::is_aligned])
226  /// * Panics in debug mode if the internal cursor points past the end of storage (<code>[self.byte_pos()][Self::byte_pos] + 1 >= [self.bytes().len()][Self::bytes]</code>)
227  #[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  /// Read a [BE-bit, BE-byte] order [`u16`] from `offset` without performing bound checks
242  ///
243  /// # Safety
244  ///
245  /// * This is UB if <code>(offset / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
246  /// * This is UB if <code>(offset % 8 != 0) && (offset / 8) + 2 >= [`self.bytes().len()`][Self::bytes]</code>
247  ///
248  /// # Panics
249  ///
250  /// * Panics in debug mode if <code>(offset / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
251  /// * Panics in debug mode if <code>(offset % 8 != 0) && (offset / 8) + 2 >= [`self.bytes().len()`][Self::bytes]</code>
252  #[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  /// Read the next [BE-bit, BE-byte] order [`u16`] without performing bound checks, advancing the internal cursor
296  ///
297  /// # Safety
298  ///
299  /// * This is UB if <code>(self.pos() / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
300  /// * This is UB if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 2 >= [`self.bytes().len()`][Self::bytes]</code>
301  ///
302  /// # Panics
303  ///
304  /// * Panics in debug mode if <code>(self.pos() / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
305  /// * Panics in debug mode if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 2 >= [`self.bytes().len()`][Self::bytes]</code>
306  #[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  /// Read a [BE-bit, BE-byte] order [`u16`] from `offset` while performing bound checks
315  ///
316  /// # Errors
317  ///
318  /// * Returns [`Error::OutOfBounds`]
319  ///   * if <code>(offset / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
320  ///   * if <code>(offset % 8 != 0) && (offset / 8) + 2 >= [`self.bytes().len()`][Self::bytes]</code>
321  #[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  /// Read the next [BE-bit, BE-byte] order [`u16`] while performing bound checks, advancing the internal cursor
340  ///
341  /// # Errors
342  ///
343  /// * Returns [`Error::OutOfBounds`]
344  ///   * if <code>(self.pos() / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
345  ///   * if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 2 >= [`self.bytes().len()`][Self::bytes]</code>
346  #[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  /// Read a [BE-bit, BE-byte] order [`u16`] from `offset`, panicking on out of bounds
354  ///
355  /// # Panics
356  ///
357  /// * Panics if <code>(offset / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
358  /// * Panics if <code>(offset % 8 != 0) && (offset / 8) + 2 >= [`self.bytes().len()`][Self::bytes]</code>
359  #[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  /// Read the next [BE-bit, BE-byte] order [`u16`], panicking on out of bounds, advancing the internal cursor
368  ///
369  /// # Panics
370  ///
371  /// * Panics if <code>(self.pos() / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
372  /// * Panics if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 2 >= [`self.bytes().len()`][Self::bytes]</code>
373  #[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  /// Read a [`u32`] in [BE-bit, BE-byte] order at `byte_offset` without performing bound checks
382  ///
383  /// # Safety
384  ///
385  /// * This is UB if [`byte_offset + 3 >= self.bytes().len()`][Self::bytes]
386  ///
387  /// # Panics
388  ///
389  /// * Panics in debug mode if [`byte_offset + 3 >= self.bytes().len()`][Self::bytes]
390  #[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  /// Read the next [`u32`] in [BE-bit, BE-byte] order without performing bound checks, advancing the internal cursor
412  ///
413  /// # Safety
414  ///
415  /// * The internal cursor must be byte-aligned ([`self.is_aligned()`][Self::is_aligned])
416  /// * This is UB if the internal cursor points past the end of storage (<code>[self.byte_pos()][Self::byte_pos] + 3 >= [self.bytes().len()][Self::bytes]</code>)
417  ///
418  /// # Panics
419  ///
420  /// * Panics in debug mode if the internal cursor is not byte-aligned ([`!self.is_aligned()`][Self::is_aligned])
421  /// * Panics in debug mode if the internal cursor points past the end of storage (<code>[self.byte_pos()][Self::byte_pos] + 3 >= [self.bytes().len()][Self::bytes]</code>)
422  #[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  /// Read a [`u32`] in [BE-bit, BE-byte] order from `offset` without performing bound checks
437  ///
438  /// # Safety
439  ///
440  /// * This is UB if <code>(offset / 8) + 3 >= [`self.bytes().len()`][Self::bytes]</code>
441  /// * This is UB if <code>(offset % 8 != 0) && (offset / 8) + 4 >= [`self.bytes().len()`][Self::bytes]</code>
442  ///
443  /// # Panics
444  ///
445  /// * Panics in debug mode if <code>(offset / 8) + 3 >= [`self.bytes().len()`][Self::bytes]</code>
446  /// * Panics in debug mode if <code>(offset % 8 != 0) && (offset / 8) + 4 >= [`self.bytes().len()`][Self::bytes]</code>
447  #[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  /// Read the next [`u32`] in [BE-bit, BE-byte] order without performing bound checks, advancing the internal cursor
497  ///
498  /// # Safety
499  ///
500  /// * This is UB if <code>(self.pos() / 8) + 3 >= [`self.bytes().len()`][Self::bytes]</code>
501  /// * This is UB if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 4 >= [`self.bytes().len()`][Self::bytes]</code>
502  ///
503  /// # Panics
504  ///
505  /// * Panics in debug mode if <code>(self.pos() / 8) + 3 >= [`self.bytes().len()`][Self::bytes]</code>
506  /// * Panics in debug mode if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 4 >= [`self.bytes().len()`][Self::bytes]</code>
507  #[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  /// Read a [BE-bit, BE-byte] order [`u32`] from `offset` while performing bound checks
516  ///
517  /// # Errors
518  ///
519  /// * Returns [`Error::OutOfBounds`]
520  ///   * if <code>(offset / 8) + 3 >= [`self.bytes().len()`][Self::bytes]</code>
521  ///   * if <code>(offset % 8 != 0) && (offset / 8) + 4 >= [`self.bytes().len()`][Self::bytes]</code>
522  #[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  /// Read the next [BE-bit, BE-byte] order [`u32`] while performing bound checks, advancing the internal cursor
541  ///
542  /// # Errors
543  ///
544  /// * Returns [`Error::OutOfBounds`]
545  ///   * if <code>(self.pos() / 8) + 3 >= [`self.bytes().len()`][Self::bytes]</code>
546  ///   * if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 4 >= [`self.bytes().len()`][Self::bytes]</code>
547  #[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  /// Read a [BE-bit, BE-byte] order [`u32`] from `offset`, panicking on out of bounds
555  ///
556  /// # Panics
557  ///
558  /// * Panics if <code>(offset / 8) + 3 >= [`self.bytes().len()`][Self::bytes]</code>
559  /// * Panics if <code>(offset % 8 != 0) && (offset / 8) + 4 >= [`self.bytes().len()`][Self::bytes]</code>
560  #[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  /// Read the next [BE-bit, BE-byte] order [`u32`], panicking on out of bounds, advancing the internal cursor
569  ///
570  /// # Panics
571  ///
572  /// * Panics if <code>(self.pos() / 8) + 3 >= [`self.bytes().len()`][Self::bytes]</code>
573  /// * Panics if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 4 >= [`self.bytes().len()`][Self::bytes]</code>
574  #[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  /// Read a [BE-bit, BE-byte] order type `T` from `byte_offset` without performing bound checks
741  ///
742  /// # Safety
743  ///
744  /// All semantics of the corresponding function for the type apply
745  ///
746  /// # Panics
747  ///
748  /// All semantics of the corresponding function for the type apply
749  #[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  /// Read the next [BE-bit, BE-byte] order type `T` without performing bound checks, advancing the internal cursor
756  ///
757  /// # Safety
758  ///
759  /// All semantics of the corresponding function for the type apply
760  ///
761  /// # Panics
762  ///
763  /// All semantics of the corresponding function for the type apply
764  #[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  /// Read a [BE-bit, BE-byte] order type `T` from `offset` without performing bound checks
771  ///
772  /// # Safety
773  ///
774  /// All semantics of the corresponding function for the type apply
775  ///
776  /// # Panics
777  ///
778  /// All semantics of the corresponding function for the type apply
779  #[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  /// Read the next [BE-bit, BE-byte] order type `T` without performing bound checks, advancing the internal cursor
786  ///
787  /// # Safety
788  ///
789  /// All semantics of the corresponding function for the type apply
790  ///
791  /// # Panics
792  ///
793  /// All semantics of the corresponding function for the type apply
794  #[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  /// Read a [BE-bit, BE-byte] order type `T` from `offset` while performing bound checks
801  ///
802  /// # Errors
803  ///
804  /// All semantics of the corresponding function for the type apply
805  #[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  /// Read the next [BE-bit, BE-byte] order type `T` while performing bound checks, advancing the internal cursor
811  ///
812  /// # Errors
813  ///
814  /// All semantics of the corresponding function for the type apply
815  #[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  /// Read a [BE-bit, BE-byte] order type `T` from `offset`, panicking on out of bounds
821  ///
822  /// # Panics
823  ///
824  /// All semantics of the corresponding function for the type apply
825  #[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  /// Read the next [BE-bit, BE-byte] order type `T`, panicking on out of bounds, advancing the internal cursor
832  ///
833  /// # Panics
834  ///
835  /// All semantics of the corresponding function for the type apply
836  #[inline(always)]
837  #[must_use]
838  pub fn read_be_full<T: Read>(&mut self) -> T {
839    T::read_be_full(self)
840  }
841}