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_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_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_unchecked(&mut self) -> u8 {
42    debug_assert!(
43      self.is_aligned(),
44      "BitBuf::read_u8_be_aligned_unchecked called at unaligned bit position: {}",
45      self.pos(),
46    );
47
48    let b = unsafe { self.read_u8_be_aligned_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_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_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_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_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_unchecked(&mut self) -> u8 {
116    let b = unsafe { self.read_u8_be_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_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_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(&mut self) -> Result<u8> {
155    let b = self.try_read_u8_be_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_at(&self, offset: usize) -> u8 {
169    self
170      .try_read_u8_be_at(offset)
171      .expect("BitBuf::read_u8_be_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(&mut self) -> u8 {
183    self
184      .try_read_u8_be()
185      .expect("BitBuf::read_u8_be out of bounds")
186  }
187
188  /// Read a [`u8`] containing `bits` count of BE-bit-order bits from `byte_offset` without performing bound checks
189  ///
190  /// # Safety
191  ///
192  /// * This is UB if `bits > 8`
193  /// * This is UB if [`byte_offset >= self.bytes().len()`][Self::bytes]
194  ///
195  /// # Panics
196  ///
197  /// * Panics in debug mode if `bits > 8`
198  /// * Panics in debug mode if [`byte_offset >= self.bytes().len()`][Self::bytes]
199  #[inline(always)]
200  #[must_use]
201  pub unsafe fn read_u8_be_aligned_bits_at_unchecked(&self, byte_offset: usize, bits: usize) -> u8 {
202    debug_assert!(
203      bits <= 8,
204      "BitBuf::read_u8_be_aligned_bits_at_unchecked: bits requested ({}) exceeds u8 width!",
205      bits,
206    );
207
208    let bytes = self.bytes();
209
210    debug_assert!(
211      byte_offset < bytes.len(),
212      "BitBuf::read_u8_be_aligned_bits_at_unchecked: index out of bounds! len is {}, offset is {}",
213      bytes.len(),
214      byte_offset,
215    );
216
217    if bits == 0 {
218      return 0;
219    }
220
221    let b = unsafe { *bytes.get_unchecked(byte_offset) };
222
223    b >> (8 - bits)
224  }
225
226  /// Read the next [`u8`] containing `bits` count of BE-bit-order bits without performing bound checks, advancing the internal cursor
227  ///
228  /// # Safety
229  ///
230  /// * This is UB if `bits > 8`
231  /// * The internal cursor must be byte-aligned ([`self.is_aligned()`][Self::is_aligned])
232  /// * 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>)
233  ///
234  /// # Panics
235  ///
236  /// * Panics in debug mode if `bits > 8`
237  /// * Panics in debug mode if the internal cursor is not byte-aligned ([`!self.is_aligned()`][Self::is_aligned])
238  /// * 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>)
239  #[inline(always)]
240  #[must_use]
241  pub unsafe fn read_u8_be_aligned_bits_unchecked(&mut self, bits: usize) -> u8 {
242    debug_assert!(
243      bits <= 8,
244      "BitBuf::read_u8_be_aligned_bits_unchecked: bits requested ({}) exceeds u8 width!",
245      bits,
246    );
247
248    debug_assert!(
249      self.is_aligned(),
250      "BitBuf::read_u8_be_aligned_bits_unchecked called at unaligned bit position: {}",
251      self.pos(),
252    );
253
254    let b = unsafe { self.read_u8_be_aligned_bits_at_unchecked(self.byte_pos(), bits) };
255    self.advance(bits);
256    b
257  }
258
259  /// Read a [`u8`] containing `bits` count of BE-bit-order bits from `offset` without performing bound checks
260  ///
261  /// # Safety
262  ///
263  /// * This is UB if `bits > 8`
264  /// * This is UB if <code>(offset / 8) >= [`self.bytes().len()`][Self::bytes]</code>
265  /// * This is UB if <code>(offset % 8 + bits > 8) && (offset / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
266  ///
267  /// # Panics
268  ///
269  /// * Panics in debug mode if `bits > 8`
270  /// * Panics in debug mode if <code>(offset / 8) >= [`self.bytes().len()`][Self::bytes]</code>
271  /// * Panics in debug mode if <code>(offset % 8 + bits > 8) && (offset / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
272  #[inline(always)]
273  #[must_use]
274  pub unsafe fn read_u8_be_bits_at_unchecked(&self, offset: usize, bits: usize) -> u8 {
275    debug_assert!(
276      bits <= 8,
277      "BitBuf::read_u8_be_bits_at_unchecked: bits requested ({}) exceeds u8 width!",
278      bits,
279    );
280
281    if bits == 0 {
282      return 0;
283    }
284
285    let byte_idx = offset / 8;
286    let shift = offset % 8;
287
288    let bytes = self.bytes();
289
290    debug_assert!(
291      byte_idx < bytes.len(),
292      "BitBuf::read_u8_be_bits_at_unchecked: index out of bounds! len is {}, byte_idx is {}",
293      bytes.len(),
294      byte_idx,
295    );
296
297    let high = unsafe { *bytes.get_unchecked(byte_idx) };
298
299    if shift + bits <= 8 {
300      (high << shift) >> (8 - bits)
301    } else {
302      let next_idx = byte_idx + 1;
303
304      debug_assert!(
305        next_idx < bytes.len(),
306        "BitBuf::read_u8_be_bits_at_unchecked: lookahead index out of bounds! len is {}, lookahead byte_idx is {}",
307        bytes.len(),
308        next_idx,
309      );
310
311      let low = unsafe { *bytes.get_unchecked(next_idx) };
312
313      let v = ((high as u16) << 8) | (low as u16);
314      ((v << shift) >> (16 - bits)) as u8
315    }
316  }
317
318  /// Read the next [`u8`] containing `bits` count of BE-bit-order bits without performing bound checks, advancing the internal cursor
319  ///
320  /// # Safety
321  ///
322  /// * This is UB if `bits > 8`
323  /// * This is UB if <code>(self.pos() / 8) >= [`self.bytes().len()`][Self::bytes]</code>
324  /// * This is UB if <code>(self.pos() % 8 + bits > 8) && (self.pos() / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
325  ///
326  /// # Panics
327  ///
328  /// * Panics in debug mode if `bits > 8`
329  /// * Panics in debug mode if <code>(self.pos() / 8) >= [`self.bytes().len()`][Self::bytes]</code>
330  /// * Panics in debug mode if <code>(self.pos() % 8 + bits > 8) && (self.pos() / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
331  #[inline(always)]
332  #[must_use]
333  pub unsafe fn read_u8_be_bits_unchecked(&mut self, bits: usize) -> u8 {
334    let b = unsafe { self.read_u8_be_bits_at_unchecked(self.pos(), bits) };
335    self.advance(bits);
336    b
337  }
338
339  /// Read a [`u8`] containing `bits` count of BE-bit-order bits from `offset` while performing bound checks
340  ///
341  /// # Errors
342  ///
343  /// * Returns [`Error::InvalidBitCount`] if `bits > 8`
344  /// * Returns [`Error::OutOfBounds`] if <code>(offset / 8) >= [`self.bytes().len()`][Self::bytes]</code>
345  /// * Returns [`Error::OutOfBounds`] if <code>(offset % 8 + bits > 8) && (offset / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
346  #[inline(always)]
347  pub fn try_read_u8_be_bits_at(&self, offset: usize, bits: usize) -> Result<u8> {
348    if bits > 8 {
349      return Err(Error::InvalidBitCount);
350    }
351
352    if bits == 0 {
353      return Ok(0);
354    }
355
356    let byte_idx = offset / 8;
357    let shift = offset % 8;
358
359    let len = self.bytes().len();
360
361    if byte_idx >= len {
362      return Err(Error::OutOfBounds);
363    }
364
365    if shift + bits > 8 && byte_idx + 1 >= len {
366      return Err(Error::OutOfBounds);
367    }
368
369    Ok(unsafe { self.read_u8_be_bits_at_unchecked(offset, bits) })
370  }
371
372  /// Read the next [`u8`] containing `bits` count of BE-bit-order bits while performing bound checks, advancing the internal cursor
373  ///
374  /// # Errors
375  ///
376  /// * Returns [`Error::InvalidBitCount`] if `bits > 8`
377  /// * Returns [`Error::OutOfBounds`] if <code>(self.pos() / 8) >= [`self.bytes().len()`][Self::bytes]</code>
378  /// * Returns [`Error::OutOfBounds`] if <code>(self.pos() % 8 + bits > 8) && (self.pos() / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
379  #[inline(always)]
380  pub fn try_read_u8_be_bits(&mut self, bits: usize) -> Result<u8> {
381    let b = self.try_read_u8_be_bits_at(self.pos(), bits)?;
382    self.advance(bits);
383    Ok(b)
384  }
385
386  /// Read a [`u8`] containing `bits` count of BE-bit-order bits from `offset`, panicking on out of bounds or if bit count is invalid
387  ///
388  /// # Panics
389  ///
390  /// * Panics if `bits > 8`
391  /// * Panics if <code>(offset / 8) >= [`self.bytes().len()`][Self::bytes]</code>
392  /// * Panics if <code>(offset % 8 + bits > 8) && (offset / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
393  #[inline(always)]
394  #[must_use]
395  pub fn read_u8_be_bits_at(&self, offset: usize, bits: usize) -> u8 {
396    self
397      .try_read_u8_be_bits_at(offset, bits)
398      .expect("BitBuf::read_u8_be_bits_at failed")
399  }
400
401  /// Read the next [`u8`] containing `bits` count of BE-bit-order bits, panicking on out of bounds or if bit count is invalid, advancing the internal cursor
402  ///
403  /// # Panics
404  ///
405  /// * Panics if `bits > 8`
406  /// * Panics if <code>(self.pos() / 8) >= [`self.bytes().len()`][Self::bytes]</code>
407  /// * Panics if <code>(self.pos() % 8 + bits > 8) && (self.pos() / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
408  #[inline(always)]
409  #[must_use]
410  pub fn read_u8_be_bits(&mut self, bits: usize) -> u8 {
411    self
412      .try_read_u8_be_bits(bits)
413      .expect("BitBuf::read_u8_be_bits failed")
414  }
415
416  /// Read a [BE-bit, BE-byte] order [`u16`] from `byte_offset` without performing bound checks
417  ///
418  /// # Safety
419  ///
420  /// * This is UB if [`byte_offset + 1 >= self.bytes().len()`][Self::bytes]
421  ///
422  /// # Panics
423  ///
424  /// * Panics in debug mode if [`byte_offset + 1 >= self.bytes().len()`][Self::bytes]
425  #[inline(always)]
426  #[must_use]
427  pub unsafe fn read_u16_be_aligned_at_unchecked(&self, byte_offset: usize) -> u16 {
428    let bytes = self.bytes();
429
430    debug_assert!(
431      byte_offset + 1 < bytes.len(),
432      "BitBuf::read_u16_be_aligned_at_unchecked: index out of bounds! len is {}, offset is {}",
433      bytes.len(),
434      byte_offset + 1,
435    );
436
437    unsafe {
438      let high = *bytes.get_unchecked(byte_offset);
439      let low = *bytes.get_unchecked(byte_offset + 1);
440      u16::from_be_bytes([high, low])
441    }
442  }
443
444  /// Read the next [BE-bit, BE-byte] order [`u16`] without performing bound checks, advancing the internal cursor
445  ///
446  /// # Safety
447  ///
448  /// * The internal cursor must be byte-aligned ([`self.is_aligned()`][Self::is_aligned])
449  /// * 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>)
450  ///
451  /// # Panics
452  ///
453  /// * Panics in debug mode if the internal cursor is not byte-aligned ([`!self.is_aligned()`][Self::is_aligned])
454  /// * 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>)
455  #[inline(always)]
456  #[must_use]
457  pub unsafe fn read_u16_be_aligned_unchecked(&mut self) -> u16 {
458    debug_assert!(
459      self.is_aligned(),
460      "BitBuf::read_u16_be_aligned_unchecked called at unaligned bit position: {}",
461      self.pos(),
462    );
463
464    let v = unsafe { self.read_u16_be_aligned_at_unchecked(self.byte_pos()) };
465    self.advance_bytes(2);
466    v
467  }
468
469  /// Read a [BE-bit, BE-byte] order [`u16`] from `offset` without performing bound checks
470  ///
471  /// # Safety
472  ///
473  /// * This is UB if <code>(offset / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
474  /// * This is UB if <code>(offset % 8 != 0) && (offset / 8) + 2 >= [`self.bytes().len()`][Self::bytes]</code>
475  ///
476  /// # Panics
477  ///
478  /// * Panics in debug mode if <code>(offset / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
479  /// * Panics in debug mode if <code>(offset % 8 != 0) && (offset / 8) + 2 >= [`self.bytes().len()`][Self::bytes]</code>
480  #[inline(always)]
481  #[must_use]
482  pub unsafe fn read_u16_be_at_unchecked(&self, offset: usize) -> u16 {
483    let first_idx = offset / 8;
484    let shift = offset % 8;
485
486    let bytes = self.bytes();
487
488    debug_assert!(
489      first_idx + 1 < bytes.len(),
490      "BitBuf::read_u16_be_at_unchecked: index out of bounds! len is {}, byte_idx is {}",
491      bytes.len(),
492      first_idx + 1,
493    );
494
495    if shift == 0 {
496      unsafe { self.read_u16_be_aligned_at_unchecked(first_idx) }
497    } else {
498      let second_idx = first_idx + 1;
499      let third_idx = first_idx + 2;
500
501      debug_assert!(
502        third_idx < bytes.len(),
503        "BitBuf::read_u16_be_at_unchecked: lookahead index out of bounds! len is {}, lookahead byte_idx is {}",
504        bytes.len(),
505        third_idx,
506      );
507
508      let (a, b, c) = unsafe {
509        (
510          *bytes.get_unchecked(first_idx),
511          *bytes.get_unchecked(second_idx),
512          *bytes.get_unchecked(third_idx),
513        )
514      };
515
516      let high = ((a as u16) << shift) | ((b as u16) >> (8 - shift));
517      let low = ((b as u16) << shift) | ((c as u16) >> (8 - shift));
518
519      (high << 8) | (low & 0xFF)
520    }
521  }
522
523  /// Read the next [BE-bit, BE-byte] order [`u16`] without performing bound checks, advancing the internal cursor
524  ///
525  /// # Safety
526  ///
527  /// * This is UB if <code>(self.pos() / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
528  /// * This is UB if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 2 >= [`self.bytes().len()`][Self::bytes]</code>
529  ///
530  /// # Panics
531  ///
532  /// * Panics in debug mode if <code>(self.pos() / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
533  /// * Panics in debug mode if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 2 >= [`self.bytes().len()`][Self::bytes]</code>
534  #[inline(always)]
535  #[must_use]
536  pub unsafe fn read_u16_be_unchecked(&mut self) -> u16 {
537    let v = unsafe { self.read_u16_be_at_unchecked(self.pos()) };
538    self.advance_bytes(2);
539    v
540  }
541
542  /// Read a [BE-bit, BE-byte] order [`u16`] from `offset` while performing bound checks
543  ///
544  /// # Errors
545  ///
546  /// * Returns [`Error::OutOfBounds`]
547  ///   * if <code>(offset / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
548  ///   * if <code>(offset % 8 != 0) && (offset / 8) + 2 >= [`self.bytes().len()`][Self::bytes]</code>
549  #[inline(always)]
550  pub fn try_read_u16_be_at(&self, offset: usize) -> Result<u16> {
551    let first_idx = offset / 8;
552    let shift = offset % 8;
553
554    let len = self.bytes().len();
555
556    if first_idx + 1 >= len {
557      return Err(Error::OutOfBounds);
558    }
559
560    if shift != 0 && first_idx + 2 >= len {
561      return Err(Error::OutOfBounds);
562    }
563
564    Ok(unsafe { self.read_u16_be_at_unchecked(offset) })
565  }
566
567  /// Read the next [BE-bit, BE-byte] order [`u16`] while performing bound checks, advancing the internal cursor
568  ///
569  /// # Errors
570  ///
571  /// * Returns [`Error::OutOfBounds`]
572  ///   * if <code>(self.pos() / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
573  ///   * if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 2 >= [`self.bytes().len()`][Self::bytes]</code>
574  #[inline(always)]
575  pub fn try_read_u16_be(&mut self) -> Result<u16> {
576    let v = self.try_read_u16_be_at(self.pos())?;
577    self.advance_bytes(2);
578    Ok(v)
579  }
580
581  /// Read a [BE-bit, BE-byte] order [`u16`] from `offset`, panicking on out of bounds
582  ///
583  /// # Panics
584  ///
585  /// * Panics if <code>(offset / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
586  /// * Panics if <code>(offset % 8 != 0) && (offset / 8) + 2 >= [`self.bytes().len()`][Self::bytes]</code>
587  #[inline(always)]
588  #[must_use]
589  pub fn read_u16_be_at(&self, offset: usize) -> u16 {
590    self
591      .try_read_u16_be_at(offset)
592      .expect("BitBuf::read_u16_be_at out of bounds")
593  }
594
595  /// Read the next [BE-bit, BE-byte] order [`u16`], panicking on out of bounds, advancing the internal cursor
596  ///
597  /// # Panics
598  ///
599  /// * Panics if <code>(self.pos() / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
600  /// * Panics if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 2 >= [`self.bytes().len()`][Self::bytes]</code>
601  #[inline(always)]
602  #[must_use]
603  pub fn read_u16_be(&mut self) -> u16 {
604    self
605      .try_read_u16_be()
606      .expect("BitBuf::read_u16_be out of bounds")
607  }
608
609  /// Read a [`u32`] in [BE-bit, BE-byte] order at `byte_offset` without performing bound checks
610  ///
611  /// # Safety
612  ///
613  /// * This is UB if [`byte_offset + 3 >= self.bytes().len()`][Self::bytes]
614  ///
615  /// # Panics
616  ///
617  /// * Panics in debug mode if [`byte_offset + 3 >= self.bytes().len()`][Self::bytes]
618  #[inline(always)]
619  #[must_use]
620  pub unsafe fn read_u32_be_aligned_at_unchecked(&self, byte_offset: usize) -> u32 {
621    let bytes = self.bytes();
622
623    debug_assert!(
624      byte_offset + 3 < bytes.len(),
625      "BitBuf::read_u32_be_aligned_at_unchecked: index out of bounds! len is {}, offset is {}",
626      bytes.len(),
627      byte_offset + 3,
628    );
629
630    unsafe {
631      let a = *bytes.get_unchecked(byte_offset);
632      let b = *bytes.get_unchecked(byte_offset + 1);
633      let c = *bytes.get_unchecked(byte_offset + 2);
634      let d = *bytes.get_unchecked(byte_offset + 3);
635      u32::from_be_bytes([a, b, c, d])
636    }
637  }
638
639  /// Read the next [`u32`] in [BE-bit, BE-byte] order without performing bound checks, advancing the internal cursor
640  ///
641  /// # Safety
642  ///
643  /// * The internal cursor must be byte-aligned ([`self.is_aligned()`][Self::is_aligned])
644  /// * 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>)
645  ///
646  /// # Panics
647  ///
648  /// * Panics in debug mode if the internal cursor is not byte-aligned ([`!self.is_aligned()`][Self::is_aligned])
649  /// * 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>)
650  #[inline(always)]
651  #[must_use]
652  pub unsafe fn read_u32_be_aligned_unchecked(&mut self) -> u32 {
653    debug_assert!(
654      self.is_aligned(),
655      "BitBuf::read_u32_be_aligned_unchecked called at unaligned bit position: {}",
656      self.pos(),
657    );
658
659    let v = unsafe { self.read_u32_be_aligned_at_unchecked(self.byte_pos()) };
660    self.advance_bytes(4);
661    v
662  }
663
664  /// Read a [`u32`] in [BE-bit, BE-byte] order from `offset` without performing bound checks
665  ///
666  /// # Safety
667  ///
668  /// * This is UB if <code>(offset / 8) + 3 >= [`self.bytes().len()`][Self::bytes]</code>
669  /// * This is UB if <code>(offset % 8 != 0) && (offset / 8) + 4 >= [`self.bytes().len()`][Self::bytes]</code>
670  ///
671  /// # Panics
672  ///
673  /// * Panics in debug mode if <code>(offset / 8) + 3 >= [`self.bytes().len()`][Self::bytes]</code>
674  /// * Panics in debug mode if <code>(offset % 8 != 0) && (offset / 8) + 4 >= [`self.bytes().len()`][Self::bytes]</code>
675  #[inline(always)]
676  #[must_use]
677  pub unsafe fn read_u32_be_at_unchecked(&self, offset: usize) -> u32 {
678    let first_idx = offset / 8;
679    let shift = offset % 8;
680
681    let bytes = self.bytes();
682
683    debug_assert!(
684      first_idx + 3 < bytes.len(),
685      "BitBuf::read_u32_be_at_unchecked: index out of bounds! len is {}, byte_idx is {}",
686      bytes.len(),
687      first_idx + 3,
688    );
689
690    if shift == 0 {
691      unsafe { self.read_u32_be_aligned_at_unchecked(first_idx) }
692    } else {
693      let second_idx = first_idx + 1;
694      let third_idx = first_idx + 2;
695      let fourth_idx = first_idx + 3;
696      let fifth_idx = first_idx + 4;
697
698      debug_assert!(
699        fifth_idx < bytes.len(),
700        "BitBuf::read_u32_be_at_unchecked: lookahead index out of bounds! len is {}, lookahead byte_idx is {}",
701        bytes.len(),
702        fifth_idx,
703      );
704
705      let (a, b, c, d, e) = unsafe {
706        (
707          *bytes.get_unchecked(first_idx),
708          *bytes.get_unchecked(second_idx),
709          *bytes.get_unchecked(third_idx),
710          *bytes.get_unchecked(fourth_idx),
711          *bytes.get_unchecked(fifth_idx),
712        )
713      };
714
715      let b0 = ((a as u32) << shift) | ((b as u32) >> (8 - shift));
716      let b1 = ((b as u32) << shift) | ((c as u32) >> (8 - shift));
717      let b2 = ((c as u32) << shift) | ((d as u32) >> (8 - shift));
718      let b3 = ((d as u32) << shift) | ((e as u32) >> (8 - shift));
719
720      (b0 << 24) | ((b1 & 0xFF) << 16) | ((b2 & 0xFF) << 8) | (b3 & 0xFF)
721    }
722  }
723
724  /// Read the next [`u32`] in [BE-bit, BE-byte] order without performing bound checks, advancing the internal cursor
725  ///
726  /// # Safety
727  ///
728  /// * This is UB if <code>(self.pos() / 8) + 3 >= [`self.bytes().len()`][Self::bytes]</code>
729  /// * This is UB if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 4 >= [`self.bytes().len()`][Self::bytes]</code>
730  ///
731  /// # Panics
732  ///
733  /// * Panics in debug mode if <code>(self.pos() / 8) + 3 >= [`self.bytes().len()`][Self::bytes]</code>
734  /// * Panics in debug mode if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 4 >= [`self.bytes().len()`][Self::bytes]</code>
735  #[inline(always)]
736  #[must_use]
737  pub unsafe fn read_u32_be_unchecked(&mut self) -> u32 {
738    let v = unsafe { self.read_u32_be_at_unchecked(self.pos()) };
739    self.advance_bytes(4);
740    v
741  }
742
743  /// Read a [BE-bit, BE-byte] order [`u32`] from `offset` while performing bound checks
744  ///
745  /// # Errors
746  ///
747  /// * Returns [`Error::OutOfBounds`]
748  ///   * if <code>(offset / 8) + 3 >= [`self.bytes().len()`][Self::bytes]</code>
749  ///   * if <code>(offset % 8 != 0) && (offset / 8) + 4 >= [`self.bytes().len()`][Self::bytes]</code>
750  #[inline(always)]
751  pub fn try_read_u32_be_at(&self, offset: usize) -> Result<u32> {
752    let first_idx = offset / 8;
753    let shift = offset % 8;
754
755    let len = self.bytes().len();
756
757    if first_idx + 3 >= len {
758      return Err(Error::OutOfBounds);
759    }
760
761    if shift != 0 && first_idx + 4 >= len {
762      return Err(Error::OutOfBounds);
763    }
764
765    Ok(unsafe { self.read_u32_be_at_unchecked(offset) })
766  }
767
768  /// Read the next [BE-bit, BE-byte] order [`u32`] while performing bound checks, advancing the internal cursor
769  ///
770  /// # Errors
771  ///
772  /// * Returns [`Error::OutOfBounds`]
773  ///   * if <code>(self.pos() / 8) + 3 >= [`self.bytes().len()`][Self::bytes]</code>
774  ///   * if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 4 >= [`self.bytes().len()`][Self::bytes]</code>
775  #[inline(always)]
776  pub fn try_read_u32_be(&mut self) -> Result<u32> {
777    let v = self.try_read_u32_be_at(self.pos())?;
778    self.advance_bytes(4);
779    Ok(v)
780  }
781
782  /// Read a [BE-bit, BE-byte] order [`u32`] from `offset`, panicking on out of bounds
783  ///
784  /// # Panics
785  ///
786  /// * Panics if <code>(offset / 8) + 3 >= [`self.bytes().len()`][Self::bytes]</code>
787  /// * Panics if <code>(offset % 8 != 0) && (offset / 8) + 4 >= [`self.bytes().len()`][Self::bytes]</code>
788  #[inline(always)]
789  #[must_use]
790  pub fn read_u32_be_at(&self, offset: usize) -> u32 {
791    self
792      .try_read_u32_be_at(offset)
793      .expect("BitBuf::read_u32_be_at out of bounds")
794  }
795
796  /// Read the next [BE-bit, BE-byte] order [`u32`], panicking on out of bounds, advancing the internal cursor
797  ///
798  /// # Panics
799  ///
800  /// * Panics if <code>(self.pos() / 8) + 3 >= [`self.bytes().len()`][Self::bytes]</code>
801  /// * Panics if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 4 >= [`self.bytes().len()`][Self::bytes]</code>
802  #[inline(always)]
803  #[must_use]
804  pub fn read_u32_be(&mut self) -> u32 {
805    self
806      .try_read_u32_be()
807      .expect("BitBuf::read_u32_be out of bounds")
808  }
809}
810
811pub trait Read: Sized {
812  unsafe fn read_be_aligned_at_unchecked<S: Storage>(buf: &BitBuf<S>, byte_offset: usize) -> Self;
813
814  unsafe fn read_be_aligned_unchecked<S: Storage>(buf: &mut BitBuf<S>) -> Self;
815
816  unsafe fn read_be_at_unchecked<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Self;
817
818  unsafe fn read_be_unchecked<S: Storage>(buf: &mut BitBuf<S>) -> Self;
819
820  fn try_read_be_at<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Result<Self>;
821
822  fn try_read_be<S: Storage>(buf: &mut BitBuf<S>) -> Result<Self>;
823
824  fn read_be_at<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Self;
825
826  fn read_be<S: Storage>(buf: &mut BitBuf<S>) -> Self;
827}
828
829impl Read for u8 {
830  #[inline(always)]
831  unsafe fn read_be_aligned_at_unchecked<S: Storage>(buf: &BitBuf<S>, byte_offset: usize) -> Self {
832    unsafe { buf.read_u8_be_aligned_at_unchecked(byte_offset) }
833  }
834
835  #[inline(always)]
836  unsafe fn read_be_aligned_unchecked<S: Storage>(buf: &mut BitBuf<S>) -> Self {
837    unsafe { buf.read_u8_be_aligned_unchecked() }
838  }
839
840  #[inline(always)]
841  unsafe fn read_be_at_unchecked<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Self {
842    unsafe { buf.read_u8_be_at_unchecked(offset) }
843  }
844
845  #[inline(always)]
846  unsafe fn read_be_unchecked<S: Storage>(buf: &mut BitBuf<S>) -> Self {
847    unsafe { buf.read_u8_be_unchecked() }
848  }
849
850  #[inline(always)]
851  fn try_read_be_at<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Result<Self> {
852    buf.try_read_u8_be_at(offset)
853  }
854
855  #[inline(always)]
856  fn try_read_be<S: Storage>(buf: &mut BitBuf<S>) -> Result<Self> {
857    buf.try_read_u8_be()
858  }
859
860  #[inline(always)]
861  fn read_be_at<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Self {
862    buf.read_u8_be_at(offset)
863  }
864
865  #[inline(always)]
866  fn read_be<S: Storage>(buf: &mut BitBuf<S>) -> Self {
867    buf.read_u8_be()
868  }
869}
870
871impl Read for u16 {
872  #[inline(always)]
873  unsafe fn read_be_aligned_at_unchecked<S: Storage>(buf: &BitBuf<S>, byte_offset: usize) -> Self {
874    unsafe { buf.read_u16_be_aligned_at_unchecked(byte_offset) }
875  }
876
877  #[inline(always)]
878  unsafe fn read_be_aligned_unchecked<S: Storage>(buf: &mut BitBuf<S>) -> Self {
879    unsafe { buf.read_u16_be_aligned_unchecked() }
880  }
881
882  #[inline(always)]
883  unsafe fn read_be_at_unchecked<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Self {
884    unsafe { buf.read_u16_be_at_unchecked(offset) }
885  }
886
887  #[inline(always)]
888  unsafe fn read_be_unchecked<S: Storage>(buf: &mut BitBuf<S>) -> Self {
889    unsafe { buf.read_u16_be_unchecked() }
890  }
891
892  #[inline(always)]
893  fn try_read_be_at<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Result<Self> {
894    buf.try_read_u16_be_at(offset)
895  }
896
897  #[inline(always)]
898  fn try_read_be<S: Storage>(buf: &mut BitBuf<S>) -> Result<Self> {
899    buf.try_read_u16_be()
900  }
901
902  #[inline(always)]
903  fn read_be_at<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Self {
904    buf.read_u16_be_at(offset)
905  }
906
907  #[inline(always)]
908  fn read_be<S: Storage>(buf: &mut BitBuf<S>) -> Self {
909    buf.read_u16_be()
910  }
911}
912
913impl Read for u32 {
914  #[inline(always)]
915  unsafe fn read_be_aligned_at_unchecked<S: Storage>(buf: &BitBuf<S>, byte_offset: usize) -> Self {
916    unsafe { buf.read_u32_be_aligned_at_unchecked(byte_offset) }
917  }
918
919  #[inline(always)]
920  unsafe fn read_be_aligned_unchecked<S: Storage>(buf: &mut BitBuf<S>) -> Self {
921    unsafe { buf.read_u32_be_aligned_unchecked() }
922  }
923
924  #[inline(always)]
925  unsafe fn read_be_at_unchecked<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Self {
926    unsafe { buf.read_u32_be_at_unchecked(offset) }
927  }
928
929  #[inline(always)]
930  unsafe fn read_be_unchecked<S: Storage>(buf: &mut BitBuf<S>) -> Self {
931    unsafe { buf.read_u32_be_unchecked() }
932  }
933
934  #[inline(always)]
935  fn try_read_be_at<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Result<Self> {
936    buf.try_read_u32_be_at(offset)
937  }
938
939  #[inline(always)]
940  fn try_read_be<S: Storage>(buf: &mut BitBuf<S>) -> Result<Self> {
941    buf.try_read_u32_be()
942  }
943
944  #[inline(always)]
945  fn read_be_at<S: Storage>(buf: &BitBuf<S>, offset: usize) -> Self {
946    buf.read_u32_be_at(offset)
947  }
948
949  #[inline(always)]
950  fn read_be<S: Storage>(buf: &mut BitBuf<S>) -> Self {
951    buf.read_u32_be()
952  }
953}
954
955impl<S: Storage> BitBuf<S> {
956  /// Read a [BE-bit, BE-byte] order type `T` from `byte_offset` without performing bound checks
957  ///
958  /// # Safety
959  ///
960  /// All semantics of the corresponding function for the type apply
961  ///
962  /// # Panics
963  ///
964  /// All semantics of the corresponding function for the type apply
965  #[inline(always)]
966  #[must_use]
967  pub unsafe fn read_be_aligned_at_unchecked<T: Read>(&self, byte_offset: usize) -> T {
968    unsafe { T::read_be_aligned_at_unchecked(self, byte_offset) }
969  }
970
971  /// Read the next [BE-bit, BE-byte] order type `T` without performing bound checks, advancing the internal cursor
972  ///
973  /// # Safety
974  ///
975  /// All semantics of the corresponding function for the type apply
976  ///
977  /// # Panics
978  ///
979  /// All semantics of the corresponding function for the type apply
980  #[inline(always)]
981  #[must_use]
982  pub unsafe fn read_be_aligned_unchecked<T: Read>(&mut self) -> T {
983    unsafe { T::read_be_aligned_unchecked(self) }
984  }
985
986  /// Read a [BE-bit, BE-byte] order type `T` from `offset` without performing bound checks
987  ///
988  /// # Safety
989  ///
990  /// All semantics of the corresponding function for the type apply
991  ///
992  /// # Panics
993  ///
994  /// All semantics of the corresponding function for the type apply
995  #[inline(always)]
996  #[must_use]
997  pub unsafe fn read_be_at_unchecked<T: Read>(&self, offset: usize) -> T {
998    unsafe { T::read_be_at_unchecked(self, offset) }
999  }
1000
1001  /// Read the next [BE-bit, BE-byte] order type `T` without performing bound checks, advancing the internal cursor
1002  ///
1003  /// # Safety
1004  ///
1005  /// All semantics of the corresponding function for the type apply
1006  ///
1007  /// # Panics
1008  ///
1009  /// All semantics of the corresponding function for the type apply
1010  #[inline(always)]
1011  #[must_use]
1012  pub unsafe fn read_be_unchecked<T: Read>(&mut self) -> T {
1013    unsafe { T::read_be_unchecked(self) }
1014  }
1015
1016  /// Read a [BE-bit, BE-byte] order type `T` from `offset` while performing bound checks
1017  ///
1018  /// # Errors
1019  ///
1020  /// All semantics of the corresponding function for the type apply
1021  #[inline(always)]
1022  pub fn try_read_be_at<T: Read>(&self, offset: usize) -> Result<T> {
1023    T::try_read_be_at(self, offset)
1024  }
1025
1026  /// Read the next [BE-bit, BE-byte] order type `T` while performing bound checks, advancing the internal cursor
1027  ///
1028  /// # Errors
1029  ///
1030  /// All semantics of the corresponding function for the type apply
1031  #[inline(always)]
1032  pub fn try_read_be<T: Read>(&mut self) -> Result<T> {
1033    T::try_read_be(self)
1034  }
1035
1036  /// Read a [BE-bit, BE-byte] order type `T` from `offset`, panicking on out of bounds
1037  ///
1038  /// # Panics
1039  ///
1040  /// All semantics of the corresponding function for the type apply
1041  #[inline(always)]
1042  #[must_use]
1043  pub fn read_be_at<T: Read>(&self, offset: usize) -> T {
1044    T::read_be_at(self, offset)
1045  }
1046
1047  /// Read the next [BE-bit, BE-byte] order type `T`, panicking on out of bounds, advancing the internal cursor
1048  ///
1049  /// # Panics
1050  ///
1051  /// All semantics of the corresponding function for the type apply
1052  #[inline(always)]
1053  #[must_use]
1054  pub fn read_be<T: Read>(&mut self) -> T {
1055    T::read_be(self)
1056  }
1057}