Skip to main content

bit_buf/
write.rs

1use crate::{BitBuf, Error, Result, StorageMut};
2
3impl<S: StorageMut> BitBuf<S> {
4  /// Write a [`u8`] in BE-bit-order at `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  pub unsafe fn write_u8_be_aligned_full_at_unchecked(
15    &mut self,
16    byte_offset: usize,
17    v: u8,
18  ) -> &mut Self {
19    let bytes = self.bytes_mut();
20
21    debug_assert!(
22      byte_offset < bytes.len(),
23      "BitBuf::write_u8_be_aligned_full_at_unchecked: index out of bounds! len is {}, offset is {}",
24      bytes.len(),
25      byte_offset,
26    );
27
28    unsafe { *bytes.get_unchecked_mut(byte_offset) = v };
29    self
30  }
31
32  /// Write a [`u8`] in BE-bit-order without performing bound checks, advancing the internal cursor
33  ///
34  /// # Safety
35  ///
36  /// * The internal cursor must be byte-aligned ([`self.is_aligned()`][Self::is_aligned])
37  /// * 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>)
38  ///
39  /// # Panics
40  ///
41  /// * Panics in debug mode if the internal cursor is not byte-aligned ([`!self.is_aligned()`][Self::is_aligned])
42  /// * 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>)
43  #[inline(always)]
44  pub unsafe fn write_u8_be_aligned_full_unchecked(&mut self, v: u8) -> &mut Self {
45    debug_assert!(
46      self.is_aligned(),
47      "BitBuf::write_u8_be_aligned_full_unchecked called at unaligned bit position: {}",
48      self.pos(),
49    );
50
51    unsafe { self.write_u8_be_aligned_full_at_unchecked(self.byte_pos(), v) };
52    self.advance_bytes(1);
53    self
54  }
55
56  /// Write a [`u8`] in BE-bit-order at `offset` without performing bound checks
57  ///
58  /// # Safety
59  ///
60  /// * This is UB if <code>(offset / 8) >= [`self.bytes().len()`][Self::bytes]</code>
61  /// * This is UB if <code>(offset % 8 != 0) && (offset / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
62  ///
63  /// # Panics
64  ///
65  /// * Panics in debug mode if <code>(offset / 8) >= [`self.bytes().len()`][Self::bytes]</code>
66  /// * Panics in debug mode if <code>(offset % 8 != 0) && (offset / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
67  #[inline(always)]
68  pub unsafe fn write_u8_be_full_at_unchecked(&mut self, offset: usize, v: u8) -> &mut Self {
69    let byte_idx = offset / 8;
70    let shift = offset % 8;
71
72    let bytes = self.bytes_mut();
73
74    debug_assert!(
75      byte_idx < bytes.len(),
76      "BitBuf::write_u8_be_full_at_unchecked: index out of bounds! len is {}, byte_idx is {}",
77      bytes.len(),
78      byte_idx,
79    );
80
81    if shift == 0 {
82      unsafe { self.write_u8_be_aligned_full_at_unchecked(byte_idx, v) };
83    } else {
84      let next_idx = byte_idx + 1;
85
86      debug_assert!(
87        next_idx < bytes.len(),
88        "BitBuf::write_u8_be_full_at_unchecked: lookahead index out of bounds! len is {}, lookahead byte_idx is {}",
89        bytes.len(),
90        next_idx,
91      );
92
93      // first byte, higher part of value
94      unsafe {
95        // mask to keep high bits of the current byte
96        let mask = !0 << (8 - shift);
97        let b = bytes.get_unchecked(byte_idx) & mask;
98        // high bits of the value, shifted down
99        let new = v >> shift;
100        *bytes.get_unchecked_mut(byte_idx) = b | new;
101      }
102
103      // second byte, lower part of value
104      unsafe {
105        // mask to keep low bits of the current byte
106        let mask = !0 >> shift;
107        let b = bytes.get_unchecked(next_idx) & mask;
108        // low bits of the value, shifted up
109        let new = v << (8 - shift);
110        *bytes.get_unchecked_mut(next_idx) = b | new;
111      }
112    }
113
114    self
115  }
116
117  /// Write a [`u8`] in BE-bit-order without performing bound checks, advancing the internal cursor
118  ///
119  /// # Safety
120  ///
121  /// * This is UB if <code>(self.pos() / 8) >= [`self.bytes().len()`][Self::bytes]</code>
122  /// * This is UB if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
123  ///
124  /// # Panics
125  ///
126  /// * Panics in debug mode if <code>(self.pos() / 8) >= [`self.bytes().len()`][Self::bytes]</code>
127  /// * Panics in debug mode if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
128  #[inline(always)]
129  pub unsafe fn write_u8_be_full_unchecked(&mut self, v: u8) -> &mut Self {
130    unsafe { self.write_u8_be_full_at_unchecked(self.pos(), v) };
131    self.advance_bytes(1);
132    self
133  }
134
135  /// Write a BE-bit-order [`u8`] at `offset` while performing bound checks
136  ///
137  /// # Errors
138  ///
139  /// * Returns [`Error::OutOfBounds`]
140  ///   * if <code>(offset / 8) >= [`self.bytes().len()`][Self::bytes]</code>
141  ///   * if <code>(offset % 8 != 0) && (offset / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
142  #[inline(always)]
143  pub fn try_write_u8_be_full_at(&mut self, offset: usize, v: u8) -> Result<&mut Self> {
144    let byte_idx = offset / 8;
145    let shift = offset % 8;
146
147    let len = self.bytes().len();
148
149    if byte_idx >= len {
150      return Err(Error::OutOfBounds);
151    }
152
153    if shift != 0 && byte_idx + 1 >= len {
154      return Err(Error::OutOfBounds);
155    }
156
157    Ok(unsafe { self.write_u8_be_full_at_unchecked(offset, v) })
158  }
159
160  /// Write a BE-bit-order [`u8`] while performing bound checks, advancing the internal cursor
161  ///
162  /// # Errors
163  ///
164  /// * Returns [`Error::OutOfBounds`]
165  ///   * if <code>(self.pos() / 8) >= [`self.bytes().len()`][Self::bytes]</code>
166  ///   * if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
167  #[inline(always)]
168  pub fn try_write_u8_be_full(&mut self, v: u8) -> Result<&mut Self> {
169    self.try_write_u8_be_full_at(self.pos(), v)?;
170    self.advance_bytes(1);
171    Ok(self)
172  }
173
174  /// Write a BE-bit-order [`u8`] at `offset`, panicking on out of bounds
175  ///
176  /// # Panics
177  ///
178  /// * Panics if <code>(offset / 8) >= [`self.bytes().len()`][Self::bytes]</code>
179  /// * Panics if <code>(offset % 8 != 0) && (offset / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
180  #[inline(always)]
181  pub fn write_u8_be_full_at(&mut self, offset: usize, v: u8) -> &mut Self {
182    self
183      .try_write_u8_be_full_at(offset, v)
184      .expect("BitBuf::write_u8_be_full_at out of bounds")
185  }
186
187  /// Write a BE-bit-order [`u8`], panicking on out of bounds, advancing the internal cursor
188  ///
189  /// # Panics
190  ///
191  /// * Panics if <code>(self.pos() / 8) >= [`self.bytes().len()`][Self::bytes]</code>
192  /// * Panics if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
193  #[inline(always)]
194  pub fn write_u8_be_full(&mut self, v: u8) -> &mut Self {
195    self
196      .try_write_u8_be_full(v)
197      .expect("BitBuf::write_u8_be_full out of bounds")
198  }
199
200  /// Write a [`u16`] in [BE-bit, BE-byte] order at `byte_offset` without performing bound checks
201  ///
202  /// # Safety
203  ///
204  /// * This is UB if [`byte_offset + 1 >= self.bytes().len()`][Self::bytes]
205  ///
206  /// # Panics
207  ///
208  /// * Panics in debug mode if [`byte_offset + 1 >= self.bytes().len()`][Self::bytes]
209  #[inline(always)]
210  pub unsafe fn write_u16_be_aligned_full_at_unchecked(
211    &mut self,
212    byte_offset: usize,
213    v: u16,
214  ) -> &mut Self {
215    let bytes = self.bytes_mut();
216
217    debug_assert!(
218      byte_offset + 1 < bytes.len(),
219      "BitBuf::write_u16_be_aligned_full_at_unchecked: index out of bounds! len is {}, offset is {}",
220      bytes.len(),
221      byte_offset + 1,
222    );
223
224    let [high, low] = v.to_be_bytes();
225
226    unsafe {
227      *bytes.get_unchecked_mut(byte_offset) = high;
228      *bytes.get_unchecked_mut(byte_offset + 1) = low;
229    }
230
231    self
232  }
233
234  /// Write a [`u16`] in [BE-bit, BE-byte] order without performing bound checks, advancing the internal cursor
235  ///
236  /// # Safety
237  ///
238  /// * The internal cursor must be byte-aligned ([`self.is_aligned()`][Self::is_aligned])
239  /// * 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>)
240  ///
241  /// # Panics
242  ///
243  /// * Panics in debug mode if the internal cursor is not byte-aligned ([`!self.is_aligned()`][Self::is_aligned])
244  /// * 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>)
245  #[inline(always)]
246  pub unsafe fn write_u16_be_aligned_full_unchecked(&mut self, v: u16) -> &mut Self {
247    debug_assert!(
248      self.is_aligned(),
249      "BitBuf::write_u16_be_aligned_full_unchecked called at unaligned bit position: {}",
250      self.pos(),
251    );
252
253    unsafe { self.write_u16_be_aligned_full_at_unchecked(self.byte_pos(), v) };
254    self.advance_bytes(2);
255    self
256  }
257
258  /// Write a [`u16`] in [BE-bit, BE-byte] order at `offset` without performing bound checks
259  ///
260  /// # Safety
261  ///
262  /// * This is UB if <code>(offset / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
263  /// * This is UB if <code>(offset % 8 != 0) && (offset / 8) + 2 >= [`self.bytes().len()`][Self::bytes]</code>
264  ///
265  /// # Panics
266  ///
267  /// * Panics in debug mode if <code>(offset / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
268  /// * Panics in debug mode if <code>(offset % 8 != 0) && (offset / 8) + 2 >= [`self.bytes().len()`][Self::bytes]</code>
269  #[inline(always)]
270  pub unsafe fn write_u16_be_full_at_unchecked(&mut self, offset: usize, v: u16) -> &mut Self {
271    let first_idx = offset / 8;
272    let shift = offset % 8;
273
274    let bytes = self.bytes_mut();
275
276    debug_assert!(
277      first_idx + 1 < bytes.len(),
278      "BitBuf::write_u16_be_full_at_unchecked: index out of bounds! len is {}, byte_idx is {}",
279      bytes.len(),
280      first_idx + 1,
281    );
282
283    if shift == 0 {
284      unsafe { self.write_u16_be_aligned_full_at_unchecked(first_idx, v) };
285    } else {
286      let second_idx = first_idx + 1;
287      let third_idx = first_idx + 2;
288
289      debug_assert!(
290        third_idx < bytes.len(),
291        "BitBuf::write_u16_be_full_at_unchecked: lookahead index out of bounds! len is {}, lookahead byte_idx is {}",
292        bytes.len(),
293        third_idx,
294      );
295
296      let [high, low] = v.to_be_bytes();
297
298      // first byte, higher part of value
299      unsafe {
300        // mask to keep high bits of the current byte
301        let mask = !0 << (8 - shift);
302        let b = bytes.get_unchecked(first_idx) & mask;
303        // high bits of the value, shifted down
304        let new = high >> shift;
305        *bytes.get_unchecked_mut(first_idx) = b | new;
306      }
307
308      // second byte, middle part of value
309      unsafe {
310        // no need to grab byte since all 8 bits will be overwritten
311        // high middle bits of the value, shifted up
312        let b_high = high << (8 - shift);
313        // low middle bits of the value, shifted down
314        let b_low = low >> shift;
315        *bytes.get_unchecked_mut(second_idx) = b_high | b_low;
316      }
317
318      // third byte, lower part of value
319      unsafe {
320        // mask to keep low bits of the current byte
321        let mask = !0 >> shift;
322        let b = bytes.get_unchecked(third_idx) & mask;
323        // low bits of the value, shifted up
324        let new = low << (8 - shift);
325        *bytes.get_unchecked_mut(third_idx) = b | new;
326      }
327    }
328
329    self
330  }
331
332  /// Write a [`u16`] in [BE-bit, BE-byte] order without performing bound checks, advancing the internal cursor
333  ///
334  /// # Safety
335  ///
336  /// * This is UB if <code>(self.pos() / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
337  /// * This is UB if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 2 >= [`self.bytes().len()`][Self::bytes]</code>
338  ///
339  /// # Panics
340  ///
341  /// * Panics in debug mode if <code>(self.pos() / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
342  /// * Panics in debug mode if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 2 >= [`self.bytes().len()`][Self::bytes]</code>
343  #[inline(always)]
344  pub unsafe fn write_u16_be_full_unchecked(&mut self, v: u16) -> &mut Self {
345    unsafe { self.write_u16_be_full_at_unchecked(self.pos(), v) };
346    self.advance_bytes(2);
347    self
348  }
349
350  /// Write a [BE-bit, BE-byte] order [`u16`] at `offset` while performing bound checks
351  ///
352  /// # Errors
353  ///
354  /// * Returns [`Error::OutOfBounds`]
355  ///   * if <code>(offset / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
356  ///   * if <code>(offset % 8 != 0) && (offset / 8) + 2 >= [`self.bytes().len()`][Self::bytes]</code>
357  #[inline(always)]
358  pub fn try_write_u16_be_full_at(&mut self, offset: usize, v: u16) -> Result<&mut Self> {
359    let first_idx = offset / 8;
360    let shift = offset % 8;
361
362    let len = self.bytes().len();
363
364    if first_idx + 1 >= len {
365      return Err(Error::OutOfBounds);
366    }
367
368    if shift != 0 && first_idx + 2 >= len {
369      return Err(Error::OutOfBounds);
370    }
371
372    Ok(unsafe { self.write_u16_be_full_at_unchecked(offset, v) })
373  }
374
375  /// Write a [BE-bit, BE-byte] order [`u16`] while performing bound checks, advancing the internal cursor
376  ///
377  /// # Errors
378  ///
379  /// * Returns [`Error::OutOfBounds`]
380  ///   * if <code>(self.pos() / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
381  ///   * if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 2 >= [`self.bytes().len()`][Self::bytes]</code>
382  #[inline(always)]
383  pub fn try_write_u16_be_full(&mut self, v: u16) -> Result<&mut Self> {
384    self.try_write_u16_be_full_at(self.pos(), v)?;
385    self.advance_bytes(2);
386    Ok(self)
387  }
388
389  /// Write a [BE-bit, BE-byte] order [`u16`] at `offset`, panicking on out of bounds
390  ///
391  /// # Panics
392  ///
393  /// * Panics if <code>(offset / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
394  /// * Panics if <code>(offset % 8 != 0) && (offset / 8) + 2 >= [`self.bytes().len()`][Self::bytes]</code>
395  #[inline(always)]
396  pub fn write_u16_be_full_at(&mut self, offset: usize, v: u16) -> &mut Self {
397    self
398      .try_write_u16_be_full_at(offset, v)
399      .expect("BitBuf::write_u16_be_full_at out of bounds")
400  }
401
402  /// Write a [BE-bit, BE-byte] order [`u16`], panicking on out of bounds, advancing the internal cursor
403  ///
404  /// # Panics
405  ///
406  /// * Panics if <code>(self.pos() / 8) + 1 >= [`self.bytes().len()`][Self::bytes]</code>
407  /// * Panics if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 2 >= [`self.bytes().len()`][Self::bytes]</code>
408  #[inline(always)]
409  pub fn write_u16_be_full(&mut self, v: u16) -> &mut Self {
410    self
411      .try_write_u16_be_full(v)
412      .expect("BitBuf::write_u16_be_full out of bounds")
413  }
414
415  /// Write a [`u32`] in [BE-bit, BE-byte] order at `byte_offset` without performing bound checks
416  ///
417  /// # Safety
418  ///
419  /// * This is UB if [`byte_offset + 3 >= self.bytes().len()`][Self::bytes]
420  ///
421  /// # Panics
422  ///
423  /// * Panics in debug mode if [`byte_offset + 3 >= self.bytes().len()`][Self::bytes]
424  #[inline(always)]
425  pub unsafe fn write_u32_be_aligned_full_at_unchecked(
426    &mut self,
427    byte_offset: usize,
428    v: u32,
429  ) -> &mut Self {
430    let bytes = self.bytes_mut();
431
432    debug_assert!(
433      byte_offset + 3 < bytes.len(),
434      "BitBuf::write_u32_be_aligned_full_at_unchecked: index out of bounds! len is {}, offset is {}",
435      bytes.len(),
436      byte_offset + 3,
437    );
438
439    let [a, b, c, d] = v.to_be_bytes();
440
441    unsafe {
442      *bytes.get_unchecked_mut(byte_offset) = a;
443      *bytes.get_unchecked_mut(byte_offset + 1) = b;
444      *bytes.get_unchecked_mut(byte_offset + 2) = c;
445      *bytes.get_unchecked_mut(byte_offset + 3) = d;
446    }
447
448    self
449  }
450
451  /// Write a [`u32`] in [BE-bit, BE-byte] order without performing bound checks, advancing the internal cursor
452  ///
453  /// # Safety
454  ///
455  /// * The internal cursor must be byte-aligned ([`self.is_aligned()`][Self::is_aligned])
456  /// * 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>)
457  ///
458  /// # Panics
459  ///
460  /// * Panics in debug mode if the internal cursor is not byte-aligned ([`!self.is_aligned()`][Self::is_aligned])
461  /// * 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>)
462  #[inline(always)]
463  pub unsafe fn write_u32_be_aligned_full_unchecked(&mut self, v: u32) -> &mut Self {
464    debug_assert!(
465      self.is_aligned(),
466      "BitBuf::write_u32_be_aligned_full_unchecked called at unaligned bit position: {}",
467      self.pos(),
468    );
469
470    unsafe { self.write_u32_be_aligned_full_at_unchecked(self.byte_pos(), v) };
471    self.advance_bytes(4);
472    self
473  }
474
475  /// Write a [`u32`] in [BE-bit, BE-byte] order at `offset` without performing bound checks
476  ///
477  /// # Safety
478  ///
479  /// * This is UB if <code>(offset / 8) + 3 >= [`self.bytes().len()`][Self::bytes]</code>
480  /// * This is UB if <code>(offset % 8 != 0) && (offset / 8) + 4 >= [`self.bytes().len()`][Self::bytes]</code>
481  ///
482  /// # Panics
483  ///
484  /// * Panics in debug mode if <code>(offset / 8) + 3 >= [`self.bytes().len()`][Self::bytes]</code>
485  /// * Panics in debug mode if <code>(offset % 8 != 0) && (offset / 8) + 4 >= [`self.bytes().len()`][Self::bytes]</code>
486  #[inline(always)]
487  pub unsafe fn write_u32_be_full_at_unchecked(&mut self, offset: usize, v: u32) -> &mut Self {
488    let first_idx = offset / 8;
489    let shift = offset % 8;
490
491    let bytes = self.bytes_mut();
492
493    debug_assert!(
494      first_idx + 3 < bytes.len(),
495      "BitBuf::write_u32_be_full_at_unchecked: index out of bounds! len is {}, byte_idx is {}",
496      bytes.len(),
497      first_idx + 3,
498    );
499
500    if shift == 0 {
501      unsafe { self.write_u32_be_aligned_full_at_unchecked(first_idx, v) };
502    } else {
503      let second_idx = first_idx + 1;
504      let third_idx = first_idx + 2;
505      let fourth_idx = first_idx + 3;
506      let fifth_idx = first_idx + 4;
507
508      debug_assert!(
509        fifth_idx < bytes.len(),
510        "BitBuf::write_u32_be_full_at_unchecked: lookahead index out of bounds! len is {}, lookahead byte_idx is {}",
511        bytes.len(),
512        fifth_idx,
513      );
514
515      let [a, b, c, d] = v.to_be_bytes();
516
517      // first byte, higher part of value
518      unsafe {
519        // mask to keep high bits of the current byte
520        let mask = !0 << (8 - shift);
521        let byte = bytes.get_unchecked(first_idx) & mask;
522        // high bits of the value, shifted down
523        let new = a >> shift;
524        *bytes.get_unchecked_mut(first_idx) = byte | new;
525      }
526
527      // second, third, and fourth byte, middle part of value
528      // all overwritten
529      unsafe {
530        *bytes.get_unchecked_mut(second_idx) = a << (8 - shift) | b >> shift;
531        *bytes.get_unchecked_mut(third_idx) = b << (8 - shift) | c >> shift;
532        *bytes.get_unchecked_mut(fourth_idx) = c << (8 - shift) | d >> shift;
533      }
534
535      // fifth byte, lower part of value
536      unsafe {
537        // mask to keep low bits of the current byte
538        let mask = !0 >> shift;
539        let byte = bytes.get_unchecked(fifth_idx) & mask;
540        // low bits of the value, shifted up
541        let new = d << (8 - shift);
542        *bytes.get_unchecked_mut(fifth_idx) = byte | new;
543      }
544    }
545
546    self
547  }
548
549  /// Write a [`u32`] in [BE-bit, BE-byte] order without performing bound checks, advancing the internal cursor
550  ///
551  /// # Safety
552  ///
553  /// * This is UB if <code>(self.pos() / 8) + 3 >= [`self.bytes().len()`][Self::bytes]</code>
554  /// * This is UB if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 4 >= [`self.bytes().len()`][Self::bytes]</code>
555  ///
556  /// # Panics
557  ///
558  /// * Panics in debug mode if <code>(self.pos() / 8) + 3 >= [`self.bytes().len()`][Self::bytes]</code>
559  /// * Panics in debug mode if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 4 >= [`self.bytes().len()`][Self::bytes]</code>
560  #[inline(always)]
561  pub unsafe fn write_u32_be_full_unchecked(&mut self, v: u32) -> &mut Self {
562    unsafe { self.write_u32_be_full_at_unchecked(self.pos(), v) };
563    self.advance_bytes(4);
564    self
565  }
566
567  /// Write a [BE-bit, BE-byte] order [`u32`] at `offset` while performing bound checks
568  ///
569  /// # Errors
570  ///
571  /// * Returns [`Error::OutOfBounds`]
572  ///   * if <code>(offset / 8) + 3 >= [`self.bytes().len()`][Self::bytes]</code>
573  ///   * if <code>(offset % 8 != 0) && (offset / 8) + 4 >= [`self.bytes().len()`][Self::bytes]</code>
574  #[inline(always)]
575  pub fn try_write_u32_be_full_at(&mut self, offset: usize, v: u32) -> Result<&mut Self> {
576    let first_idx = offset / 8;
577    let shift = offset % 8;
578
579    let len = self.bytes().len();
580
581    if first_idx + 3 >= len {
582      return Err(Error::OutOfBounds);
583    }
584
585    if shift != 0 && first_idx + 4 >= len {
586      return Err(Error::OutOfBounds);
587    }
588
589    Ok(unsafe { self.write_u32_be_full_at_unchecked(offset, v) })
590  }
591
592  /// Write a [BE-bit, BE-byte] order [`u32`] while performing bound checks, advancing the internal cursor
593  ///
594  /// # Errors
595  ///
596  /// * Returns [`Error::OutOfBounds`]
597  ///   * if <code>(self.pos() / 8) + 3 >= [`self.bytes().len()`][Self::bytes]</code>
598  ///   * if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 4 >= [`self.bytes().len()`][Self::bytes]</code>
599  #[inline(always)]
600  pub fn try_write_u32_be_full(&mut self, v: u32) -> Result<&mut Self> {
601    self.try_write_u32_be_full_at(self.pos(), v)?;
602    self.advance_bytes(4);
603    Ok(self)
604  }
605
606  /// Write a [BE-bit, BE-byte] order [`u32`] at `offset`, panicking on out of bounds
607  ///
608  /// # Panics
609  ///
610  /// * Panics if <code>(offset / 8) + 3 >= [`self.bytes().len()`][Self::bytes]</code>
611  /// * Panics if <code>(offset % 8 != 0) && (offset / 8) + 4 >= [`self.bytes().len()`][Self::bytes]</code>
612  #[inline(always)]
613  pub fn write_u32_be_full_at(&mut self, offset: usize, v: u32) -> &mut Self {
614    self
615      .try_write_u32_be_full_at(offset, v)
616      .expect("BitBuf::write_u32_be_full_at out of bounds")
617  }
618
619  /// Write a [BE-bit, BE-byte] order [`u32`], panicking on out of bounds, advancing the internal cursor
620  ///
621  /// # Panics
622  ///
623  /// * Panics if <code>(self.pos() / 8) + 3 >= [`self.bytes().len()`][Self::bytes]</code>
624  /// * Panics if <code>(self.pos() % 8 != 0) && (self.pos() / 8) + 4 >= [`self.bytes().len()`][Self::bytes]</code>
625  #[inline(always)]
626  pub fn write_u32_be_full(&mut self, v: u32) -> &mut Self {
627    self
628      .try_write_u32_be_full(v)
629      .expect("BitBuf::write_u32_be_full out of bounds")
630  }
631}
632
633pub trait Write: Sized {
634  unsafe fn write_be_aligned_full_at_unchecked<S: StorageMut>(
635    buf: &mut BitBuf<S>,
636    byte_offset: usize,
637    v: Self,
638  ) -> &mut BitBuf<S>;
639
640  unsafe fn write_be_aligned_full_unchecked<S: StorageMut>(
641    buf: &mut BitBuf<S>,
642    v: Self,
643  ) -> &mut BitBuf<S>;
644
645  unsafe fn write_be_full_at_unchecked<S: StorageMut>(
646    buf: &mut BitBuf<S>,
647    offset: usize,
648    v: Self,
649  ) -> &mut BitBuf<S>;
650
651  unsafe fn write_be_full_unchecked<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> &mut BitBuf<S>;
652
653  fn try_write_be_full_at<S: StorageMut>(
654    buf: &mut BitBuf<S>,
655    offset: usize,
656    v: Self,
657  ) -> Result<&mut BitBuf<S>>;
658
659  fn try_write_be_full<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> Result<&mut BitBuf<S>>;
660
661  fn write_be_full_at<S: StorageMut>(buf: &mut BitBuf<S>, offset: usize, v: Self)
662  -> &mut BitBuf<S>;
663
664  fn write_be_full<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> &mut BitBuf<S>;
665}
666
667impl Write for u8 {
668  #[inline(always)]
669  unsafe fn write_be_aligned_full_at_unchecked<S: StorageMut>(
670    buf: &mut BitBuf<S>,
671    byte_offset: usize,
672    v: Self,
673  ) -> &mut BitBuf<S> {
674    unsafe { buf.write_u8_be_aligned_full_at_unchecked(byte_offset, v) }
675  }
676
677  #[inline(always)]
678  unsafe fn write_be_aligned_full_unchecked<S: StorageMut>(
679    buf: &mut BitBuf<S>,
680    v: Self,
681  ) -> &mut BitBuf<S> {
682    unsafe { buf.write_u8_be_aligned_full_unchecked(v) }
683  }
684
685  #[inline(always)]
686  unsafe fn write_be_full_at_unchecked<S: StorageMut>(
687    buf: &mut BitBuf<S>,
688    offset: usize,
689    v: Self,
690  ) -> &mut BitBuf<S> {
691    unsafe { buf.write_u8_be_full_at_unchecked(offset, v) }
692  }
693
694  #[inline(always)]
695  unsafe fn write_be_full_unchecked<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> &mut BitBuf<S> {
696    unsafe { buf.write_u8_be_full_unchecked(v) }
697  }
698
699  #[inline(always)]
700  fn try_write_be_full_at<S: StorageMut>(
701    buf: &mut BitBuf<S>,
702    offset: usize,
703    v: Self,
704  ) -> Result<&mut BitBuf<S>> {
705    buf.try_write_u8_be_full_at(offset, v)
706  }
707
708  #[inline(always)]
709  fn try_write_be_full<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> Result<&mut BitBuf<S>> {
710    buf.try_write_u8_be_full(v)
711  }
712
713  #[inline(always)]
714  fn write_be_full_at<S: StorageMut>(
715    buf: &mut BitBuf<S>,
716    offset: usize,
717    v: Self,
718  ) -> &mut BitBuf<S> {
719    buf.write_u8_be_full_at(offset, v)
720  }
721
722  #[inline(always)]
723  fn write_be_full<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> &mut BitBuf<S> {
724    buf.write_u8_be_full(v)
725  }
726}
727
728impl Write for u16 {
729  #[inline(always)]
730  unsafe fn write_be_aligned_full_at_unchecked<S: StorageMut>(
731    buf: &mut BitBuf<S>,
732    byte_offset: usize,
733    v: Self,
734  ) -> &mut BitBuf<S> {
735    unsafe { buf.write_u16_be_aligned_full_at_unchecked(byte_offset, v) }
736  }
737
738  #[inline(always)]
739  unsafe fn write_be_aligned_full_unchecked<S: StorageMut>(
740    buf: &mut BitBuf<S>,
741    v: Self,
742  ) -> &mut BitBuf<S> {
743    unsafe { buf.write_u16_be_aligned_full_unchecked(v) }
744  }
745
746  #[inline(always)]
747  unsafe fn write_be_full_at_unchecked<S: StorageMut>(
748    buf: &mut BitBuf<S>,
749    offset: usize,
750    v: Self,
751  ) -> &mut BitBuf<S> {
752    unsafe { buf.write_u16_be_full_at_unchecked(offset, v) }
753  }
754
755  #[inline(always)]
756  unsafe fn write_be_full_unchecked<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> &mut BitBuf<S> {
757    unsafe { buf.write_u16_be_full_unchecked(v) }
758  }
759
760  #[inline(always)]
761  fn try_write_be_full_at<S: StorageMut>(
762    buf: &mut BitBuf<S>,
763    offset: usize,
764    v: Self,
765  ) -> Result<&mut BitBuf<S>> {
766    buf.try_write_u16_be_full_at(offset, v)
767  }
768
769  #[inline(always)]
770  fn try_write_be_full<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> Result<&mut BitBuf<S>> {
771    buf.try_write_u16_be_full(v)
772  }
773
774  #[inline(always)]
775  fn write_be_full_at<S: StorageMut>(
776    buf: &mut BitBuf<S>,
777    offset: usize,
778    v: Self,
779  ) -> &mut BitBuf<S> {
780    buf.write_u16_be_full_at(offset, v)
781  }
782
783  #[inline(always)]
784  fn write_be_full<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> &mut BitBuf<S> {
785    buf.write_u16_be_full(v)
786  }
787}
788
789impl Write for u32 {
790  #[inline(always)]
791  unsafe fn write_be_aligned_full_at_unchecked<S: StorageMut>(
792    buf: &mut BitBuf<S>,
793    byte_offset: usize,
794    v: Self,
795  ) -> &mut BitBuf<S> {
796    unsafe { buf.write_u32_be_aligned_full_at_unchecked(byte_offset, v) }
797  }
798
799  #[inline(always)]
800  unsafe fn write_be_aligned_full_unchecked<S: StorageMut>(
801    buf: &mut BitBuf<S>,
802    v: Self,
803  ) -> &mut BitBuf<S> {
804    unsafe { buf.write_u32_be_aligned_full_unchecked(v) }
805  }
806
807  #[inline(always)]
808  unsafe fn write_be_full_at_unchecked<S: StorageMut>(
809    buf: &mut BitBuf<S>,
810    offset: usize,
811    v: Self,
812  ) -> &mut BitBuf<S> {
813    unsafe { buf.write_u32_be_full_at_unchecked(offset, v) }
814  }
815
816  #[inline(always)]
817  unsafe fn write_be_full_unchecked<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> &mut BitBuf<S> {
818    unsafe { buf.write_u32_be_full_unchecked(v) }
819  }
820
821  #[inline(always)]
822  fn try_write_be_full_at<S: StorageMut>(
823    buf: &mut BitBuf<S>,
824    offset: usize,
825    v: Self,
826  ) -> Result<&mut BitBuf<S>> {
827    buf.try_write_u32_be_full_at(offset, v)
828  }
829
830  #[inline(always)]
831  fn try_write_be_full<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> Result<&mut BitBuf<S>> {
832    buf.try_write_u32_be_full(v)
833  }
834
835  #[inline(always)]
836  fn write_be_full_at<S: StorageMut>(
837    buf: &mut BitBuf<S>,
838    offset: usize,
839    v: Self,
840  ) -> &mut BitBuf<S> {
841    buf.write_u32_be_full_at(offset, v)
842  }
843
844  #[inline(always)]
845  fn write_be_full<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> &mut BitBuf<S> {
846    buf.write_u32_be_full(v)
847  }
848}
849
850impl<S: StorageMut> BitBuf<S> {
851  /// Write a [BE-bit, BE-byte] order type `T` at `byte_offset` without performing bound checks
852  ///
853  /// # Safety
854  ///
855  /// All semantics of the corresponding function for the type apply
856  ///
857  /// # Panics
858  ///
859  /// All semantics of the corresponding function for the type apply
860  #[inline(always)]
861  pub unsafe fn write_be_aligned_full_at_unchecked<T: Write>(
862    &mut self,
863    byte_offset: usize,
864    v: T,
865  ) -> &mut Self {
866    unsafe { T::write_be_aligned_full_at_unchecked(self, byte_offset, v) }
867  }
868
869  /// Write a [BE-bit, BE-byte] order type `T` without performing bound checks, advancing the internal cursor
870  ///
871  /// # Safety
872  ///
873  /// All semantics of the corresponding function for the type apply
874  ///
875  /// # Panics
876  ///
877  /// All semantics of the corresponding function for the type apply
878  #[inline(always)]
879  pub unsafe fn write_be_aligned_full_unchecked<T: Write>(&mut self, v: T) -> &mut Self {
880    unsafe { T::write_be_aligned_full_unchecked(self, v) }
881  }
882
883  /// Write a [BE-bit, BE-byte] order type `T` at `offset` without performing bound checks
884  ///
885  /// # Safety
886  ///
887  /// All semantics of the corresponding function for the type apply
888  ///
889  /// # Panics
890  ///
891  /// All semantics of the corresponding function for the type apply
892  #[inline(always)]
893  pub unsafe fn write_be_full_at_unchecked<T: Write>(&mut self, offset: usize, v: T) -> &mut Self {
894    unsafe { T::write_be_full_at_unchecked(self, offset, v) }
895  }
896
897  /// Write a [BE-bit, BE-byte] order type `T` without performing bound checks, advancing the internal cursor
898  ///
899  /// # Safety
900  ///
901  /// All semantics of the corresponding function for the type apply
902  ///
903  /// # Panics
904  ///
905  /// All semantics of the corresponding function for the type apply
906  #[inline(always)]
907  pub unsafe fn write_be_full_unchecked<T: Write>(&mut self, v: T) -> &mut Self {
908    unsafe { T::write_be_full_unchecked(self, v) }
909  }
910
911  /// Write a [BE-bit, BE-byte] order type `T` at `offset` while performing bound checks
912  ///
913  /// # Errors
914  ///
915  /// All semantics of the corresponding function for the type apply
916  #[inline(always)]
917  pub fn try_write_be_full_at<T: Write>(&mut self, offset: usize, v: T) -> Result<&mut Self> {
918    T::try_write_be_full_at(self, offset, v)
919  }
920
921  /// Write a [BE-bit, BE-byte] order type `T` while performing bound checks, advancing the internal cursor
922  ///
923  /// # Errors
924  ///
925  /// All semantics of the corresponding function for the type apply
926  #[inline(always)]
927  pub fn try_write_be_full<T: Write>(&mut self, v: T) -> Result<&mut Self> {
928    T::try_write_be_full(self, v)
929  }
930
931  /// Write a [BE-bit, BE-byte] order type `T` at `offset`, panicking on out of bounds
932  ///
933  /// # Panics
934  ///
935  /// All semantics of the corresponding function for the type apply
936  #[inline(always)]
937  #[must_use]
938  pub fn write_be_full_at<T: Write>(&mut self, offset: usize, v: T) -> &mut Self {
939    T::write_be_full_at(self, offset, v)
940  }
941
942  /// Write a [BE-bit, BE-byte] order type `T`, panicking on out of bounds, advancing the internal cursor
943  ///
944  /// # Panics
945  ///
946  /// All semantics of the corresponding function for the type apply
947  #[inline(always)]
948  #[must_use]
949  pub fn write_be_full<T: Write>(&mut self, v: T) -> &mut Self {
950    T::write_be_full(self, v)
951  }
952}