Skip to main content

bit_buf/
write.rs

1use core::ptr;
2
3use crate::{BitBuf, Error, Result, StorageMut, ensure};
4
5impl_write! {
6  u8;
7  bytes = 1;
8  bits = 8;
9  offset = 0;
10  [a];
11  [a, b];
12
13  write_u8_be_aligned_at_unchecked;
14  write_u8_be_aligned_unchecked;
15  write_u8_be_at_unchecked;
16  write_u8_be_unchecked;
17  try_write_u8_be_aligned_at;
18  try_write_u8_be_aligned;
19  try_write_u8_be_at;
20  try_write_u8_be;
21  write_u8_be_aligned_at;
22  write_u8_be_aligned;
23  write_u8_be_at;
24  write_u8_be;
25}
26
27impl_write! {
28  u16;
29  bytes = 2;
30  bits = 16;
31  offset = 1;
32  [a, b];
33  [a, [b], c];
34
35  write_u16_be_aligned_at_unchecked;
36  write_u16_be_aligned_unchecked;
37  write_u16_be_at_unchecked;
38  write_u16_be_unchecked;
39  try_write_u16_be_aligned_at;
40  try_write_u16_be_aligned;
41  try_write_u16_be_at;
42  try_write_u16_be;
43  write_u16_be_aligned_at;
44  write_u16_be_aligned;
45  write_u16_be_at;
46  write_u16_be;
47}
48
49impl_write! {
50  u32;
51  bytes = 4;
52  bits = 32;
53  offset = 3;
54  [a, b, c, d];
55  [a, [b, c, d], e];
56
57  write_u32_be_aligned_at_unchecked;
58  write_u32_be_aligned_unchecked;
59  write_u32_be_at_unchecked;
60  write_u32_be_unchecked;
61  try_write_u32_be_aligned_at;
62  try_write_u32_be_aligned;
63  try_write_u32_be_at;
64  try_write_u32_be;
65  write_u32_be_aligned_at;
66  write_u32_be_aligned;
67  write_u32_be_at;
68  write_u32_be;
69}
70
71impl_write! {
72  u64;
73  bytes = 8;
74  bits = 64;
75  offset = 7;
76  [a, b, c, d, e, f, g, h];
77  [a, [b, c, d, e, f, g, h], i];
78
79  write_u64_be_aligned_at_unchecked;
80  write_u64_be_aligned_unchecked;
81  write_u64_be_at_unchecked;
82  write_u64_be_unchecked;
83  try_write_u64_be_aligned_at;
84  try_write_u64_be_aligned;
85  try_write_u64_be_at;
86  try_write_u64_be;
87  write_u64_be_aligned_at;
88  write_u64_be_aligned;
89  write_u64_be_at;
90  write_u64_be;
91}
92
93impl_write! {
94  u128;
95  bytes = 16;
96  bits = 128;
97  offset = 15;
98  [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p];
99  [a, [b, c, d, e, f, g, h, i, j, k, l, m, n, o, p], q];
100
101  write_u128_be_aligned_at_unchecked;
102  write_u128_be_aligned_unchecked;
103  write_u128_be_at_unchecked;
104  write_u128_be_unchecked;
105  try_write_u128_be_aligned_at;
106  try_write_u128_be_aligned;
107  try_write_u128_be_at;
108  try_write_u128_be;
109  write_u128_be_aligned_at;
110  write_u128_be_aligned;
111  write_u128_be_at;
112  write_u128_be;
113}
114
115pub trait Write: Sized {
116  unsafe fn write_be_aligned_at_unchecked<S: StorageMut>(
117    buf: &mut BitBuf<S>,
118    byte_offset: usize,
119    v: Self,
120  ) -> &mut BitBuf<S>;
121
122  unsafe fn write_be_aligned_unchecked<S: StorageMut>(
123    buf: &mut BitBuf<S>,
124    v: Self,
125  ) -> &mut BitBuf<S>;
126
127  unsafe fn write_be_at_unchecked<S: StorageMut>(
128    buf: &mut BitBuf<S>,
129    offset: usize,
130    v: Self,
131  ) -> &mut BitBuf<S>;
132
133  unsafe fn write_be_unchecked<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> &mut BitBuf<S>;
134
135  fn try_write_be_aligned_at<S: StorageMut>(
136    buf: &mut BitBuf<S>,
137    byte_offset: usize,
138    v: Self,
139  ) -> Result<&mut BitBuf<S>>;
140
141  fn try_write_be_aligned<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> Result<&mut BitBuf<S>>;
142
143  fn try_write_be_at<S: StorageMut>(
144    buf: &mut BitBuf<S>,
145    offset: usize,
146    v: Self,
147  ) -> Result<&mut BitBuf<S>>;
148
149  fn try_write_be<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> Result<&mut BitBuf<S>>;
150
151  fn write_be_aligned_at<S: StorageMut>(
152    buf: &mut BitBuf<S>,
153    offset: usize,
154    v: Self,
155  ) -> &mut BitBuf<S>;
156
157  fn write_be_aligned<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> &mut BitBuf<S>;
158
159  fn write_be_at<S: StorageMut>(buf: &mut BitBuf<S>, offset: usize, v: Self) -> &mut BitBuf<S>;
160
161  fn write_be<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> &mut BitBuf<S>;
162}
163
164impl<S: StorageMut> BitBuf<S> {
165  /// Write a `T` in [BE-bit, BE-byte] order at `byte_offset` without performing bound checks
166  ///
167  /// # Safety
168  ///
169  /// All semantics of the corresponding function for the type apply
170  ///
171  /// # Panics
172  ///
173  /// All semantics of the corresponding function for the type apply
174  #[inline(always)]
175  pub unsafe fn write_be_aligned_at_unchecked<T: Write>(
176    &mut self,
177    byte_offset: usize,
178    v: T,
179  ) -> &mut Self {
180    unsafe { T::write_be_aligned_at_unchecked(self, byte_offset, v) }
181  }
182
183  /// Write the next `T` in [BE-bit, BE-byte] order without performing bound checks, advancing the internal cursor
184  ///
185  /// # Safety
186  ///
187  /// All semantics of the corresponding function for the type apply
188  ///
189  /// # Panics
190  ///
191  /// All semantics of the corresponding function for the type apply
192  #[inline(always)]
193  pub unsafe fn write_be_aligned_unchecked<T: Write>(&mut self, v: T) -> &mut Self {
194    unsafe { T::write_be_aligned_unchecked(self, v) }
195  }
196
197  /// Write a `T` in [BE-bit, BE-byte] order at `offset` without performing bound checks
198  ///
199  /// # Safety
200  ///
201  /// All semantics of the corresponding function for the type apply
202  ///
203  /// # Panics
204  ///
205  /// All semantics of the corresponding function for the type apply
206  #[inline(always)]
207  pub unsafe fn write_be_at_unchecked<T: Write>(&mut self, offset: usize, v: T) -> &mut Self {
208    unsafe { T::write_be_at_unchecked(self, offset, v) }
209  }
210
211  /// Write the next `T` in [BE-bit, BE-byte] order without performing bound checks, advancing the internal cursor
212  ///
213  /// # Safety
214  ///
215  /// All semantics of the corresponding function for the type apply
216  ///
217  /// # Panics
218  ///
219  /// All semantics of the corresponding function for the type apply
220  #[inline(always)]
221  pub unsafe fn write_be_unchecked<T: Write>(&mut self, v: T) -> &mut Self {
222    unsafe { T::write_be_unchecked(self, v) }
223  }
224
225  /// Write a `T` in [BE-bit, BE-byte] order at `byte_offset` while performing bound checks
226  ///
227  /// # Errors
228  ///
229  /// All semantics of the corresponding function for the type apply
230  #[inline(always)]
231  pub fn try_write_be_aligned_at<T: Write>(
232    &mut self,
233    byte_offset: usize,
234    v: T,
235  ) -> Result<&mut Self> {
236    T::try_write_be_aligned_at(self, byte_offset, v)
237  }
238
239  /// Write the next `T` in [BE-bit, BE-byte] order while performing alignment and bound checks, advancing the internal cursor
240  ///
241  /// # Errors
242  ///
243  /// All semantics of the corresponding function for the type apply
244  #[inline(always)]
245  pub fn try_write_be_aligned<T: Write>(&mut self, v: T) -> Result<&mut Self> {
246    T::try_write_be_aligned(self, v)
247  }
248
249  /// Write a `T` in [BE-bit, BE-byte] order at `offset` while performing bound checks
250  ///
251  /// # Errors
252  ///
253  /// All semantics of the corresponding function for the type apply
254  #[inline(always)]
255  pub fn try_write_be_at<T: Write>(&mut self, offset: usize, v: T) -> Result<&mut Self> {
256    T::try_write_be_at(self, offset, v)
257  }
258
259  /// Write the next `T` in [BE-bit, BE-byte] order while performing bound checks, advancing the internal cursor
260  ///
261  /// # Errors
262  ///
263  /// All semantics of the corresponding function for the type apply
264  #[inline(always)]
265  pub fn try_write_be<T: Write>(&mut self, v: T) -> Result<&mut Self> {
266    T::try_write_be(self, v)
267  }
268
269  /// Write a `T` in [BE-bit, BE-byte] order at `byte_offset`, panicking on out of bounds
270  ///
271  /// # Panics
272  ///
273  /// All semantics of the corresponding function for the type apply
274  #[inline(always)]
275  pub fn write_be_aligned_at<T: Write>(&mut self, byte_offset: usize, v: T) -> &mut Self {
276    T::write_be_aligned_at(self, byte_offset, v)
277  }
278
279  /// Write the next `T` in [BE-bit, BE-byte] order panicking on an unaligned cursor or out of bounds, advancing the internal cursor
280  ///
281  /// # Panics
282  ///
283  /// All semantics of the corresponding function for the type apply
284  #[inline(always)]
285  pub fn write_be_aligned<T: Write>(&mut self, v: T) -> &mut Self {
286    T::write_be_aligned(self, v)
287  }
288
289  /// Write a `T` in [BE-bit, BE-byte] order at `offset`, panicking on out of bounds
290  ///
291  /// # Panics
292  ///
293  /// All semantics of the corresponding function for the type apply
294  #[inline(always)]
295  pub fn write_be_at<T: Write>(&mut self, offset: usize, v: T) -> &mut Self {
296    T::write_be_at(self, offset, v)
297  }
298
299  /// Write the next `T` in [BE-bit, BE-byte] order panicking on out of bounds, advancing the internal cursor
300  ///
301  /// # Panics
302  ///
303  /// All semantics of the corresponding function for the type apply
304  #[inline(always)]
305  pub fn write_be<T: Write>(&mut self, v: T) -> &mut Self {
306    T::write_be(self, v)
307  }
308}
309
310macro_rules! impl_write {
311  (
312    $ty:ident;
313    bytes = $bytes:literal;
314    bits = $bits:literal;
315    offset = $offset:literal;
316    [$($byte:ident),*];
317    [$first:ident, $([$($middle:ident),*],)? $last:ident];
318
319    $write_be_aligned_at_unchecked:ident;
320    $write_be_aligned_unchecked:ident;
321    $write_be_at_unchecked:ident;
322    $write_be_unchecked:ident;
323    $try_write_be_aligned_at:ident;
324    $try_write_be_aligned:ident;
325    $try_write_be_at:ident;
326    $try_write_be:ident;
327    $write_be_aligned_at:ident;
328    $write_be_aligned:ident;
329    $write_be_at:ident;
330    $write_be:ident;
331  ) => {
332    impl<S: StorageMut> BitBuf<S> {
333
334      #[doc = concat!("Write a [`", stringify!($ty), "`] in [BE-bit, BE-byte] order at `byte_offset` without performing bound checks")]
335      ///
336      /// # Safety
337      ///
338      #[doc = concat!("* This is UB if <code>byte_offset + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
339      ///
340      /// # Panics
341      ///
342      #[doc = concat!("* Panics in debug mode if <code>byte_offset + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
343      #[inline(always)]
344      pub unsafe fn $write_be_aligned_at_unchecked(&mut self, byte_offset: usize, v: $ty) -> &mut Self {
345        let bytes = self.bytes_mut();
346        let len = bytes.len();
347
348        ensure!(
349          byte_offset + $offset < len;
350
351          concat!(
352            "BitBuf::",
353            stringify!($write_be_aligned_at_unchecked),
354            ": index out of bounds! len is {}, offset is {}"
355          ),
356          len,
357          byte_offset + $offset,
358        );
359
360        let src_bytes = v.to_be_bytes();
361
362        #[allow(clippy::macro_metavars_in_unsafe)]
363        unsafe {
364          ptr::copy_nonoverlapping(
365            src_bytes.as_ptr(),
366            bytes.as_mut_ptr().add(byte_offset),
367            $bytes,
368          );
369        }
370
371        self
372      }
373
374      #[doc = concat!("Write the next [`", stringify!($ty), "`] in [BE-bit, BE-byte] order without performing bound checks, advancing the internal cursor")]
375      ///
376      /// # Safety
377      ///
378      /// * The internal cursor must be byte-aligned ([`self.is_aligned()`][Self::is_aligned])
379      #[doc = concat!("* This is UB if <code>[self.byte_pos()][Self::byte_pos] + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
380      ///
381      /// # Panics
382      ///
383      /// * Panics in debug mode if the internal cursor is not byte-aligned (<code>\![self.is_aligned()][Self::is_aligned]</code>)
384      #[doc = concat!("* Panics in debug mode if <code>[self.byte_pos()][Self::byte_pos] + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
385      #[inline(always)]
386      pub unsafe fn $write_be_aligned_unchecked(&mut self, v: $ty) -> &mut Self {
387        ensure!(
388          self.is_aligned();
389
390          concat!(
391            "BitBuf::",
392            stringify!($write_be_aligned_unchecked),
393            " called at unaligned bit position: {}",
394          ),
395          self.pos(),
396        );
397
398        unsafe { self.$write_be_aligned_at_unchecked(self.byte_pos(), v) };
399        self.advance_bytes($bytes);
400        self
401      }
402
403      #[doc = concat!("Write a [`", stringify!($ty), "`] in [BE-bit, BE-byte] order at `offset` without performing bound checks")]
404      ///
405      /// # Safety
406      ///
407      #[doc = concat!("* This is UB if <code>(offset / 8) + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
408      #[doc = concat!("* This is UB if <code>(offset % 8 != 0) && (offset / 8) + ", stringify!($bytes), " >= [self.bytes()][Self::bytes].len()</code>")]
409      ///
410      /// # Panics
411      ///
412      #[doc = concat!("* Panics in debug mode if <code>(offset / 8) + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
413      #[doc = concat!("* Panics in debug mode if <code>(offset % 8 != 0) && (offset / 8) + ", stringify!($bytes), " >= [self.bytes()][Self::bytes].len()</code>")]
414      #[inline(always)]
415      pub unsafe fn $write_be_at_unchecked(&mut self, offset: usize, v: $ty) -> &mut Self {
416        let byte_idx = offset / 8;
417        let shift = offset % 8;
418
419        let bytes = self.bytes_mut();
420        let len = bytes.len();
421
422        ensure!(
423          byte_idx + $offset < len;
424
425          concat!(
426            "BitBuf::",
427            stringify!($write_be_at_unchecked),
428            ": index out of bounds! len is {}, byte_idx is {}",
429          ),
430          len,
431          byte_idx + $offset,
432        );
433
434        if shift == 0 {
435          unsafe { self.$write_be_aligned_at_unchecked(byte_idx, v) };
436        } else {
437          ensure!(
438            byte_idx + $bytes < len;
439
440            concat!(
441              "BitBuf::",
442              stringify!($write_be_at_unchecked),
443              ": lookahead index out of bounds! len is {}, lookahead byte_idx is {}",
444            ),
445            len,
446            byte_idx + $bytes,
447          );
448
449          let src_bytes = v.to_be_bytes();
450
451          unsafe {
452            let mask = !0 << (8 - shift);
453            let b = bytes.get_unchecked(byte_idx) & mask;
454            let new = src_bytes[0] >> shift;
455            *bytes.get_unchecked_mut(byte_idx) = b | new;
456          }
457
458          $(
459            let mut i = 0;
460
461            #[expect(unused)]
462            unsafe {
463              $(
464                let $middle: ();
465                let hi = src_bytes[i];
466                let lo = src_bytes[i + 1];
467                *bytes.get_unchecked_mut(byte_idx + 1 + i) = hi << (8 - shift) | lo >> shift;
468                i += 1;
469              )*
470            }
471          )?
472
473          #[allow(clippy::macro_metavars_in_unsafe)]
474          unsafe {
475            let mask = !0 >> shift;
476            let b = bytes.get_unchecked(byte_idx + $bytes) & mask;
477            let new = src_bytes[$offset] << (8 - shift);
478            *bytes.get_unchecked_mut(byte_idx + $bytes) = b | new;
479          }
480        }
481
482        self
483      }
484
485      #[doc = concat!("Write the next [`", stringify!($ty), "`] in [BE-bit, BE-byte] order without performing bound checks, advancing the internal cursor")]
486      ///
487      /// # Safety
488      ///
489      #[doc = concat!("* This is UB if <code>([self.pos()][Self::pos] / 8) + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
490      #[doc = concat!("* This is UB if <code>([self.pos()][Self::pos] % 8 != 0) && ([self.pos()][Self::pos] / 8) + ", stringify!($bytes), " >= [self.bytes()][Self::bytes].len()</code>")]
491      ///
492      /// # Panics
493      ///
494      #[doc = concat!("* Panics in debug mode if <code>([self.pos()][Self::pos] / 8) + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
495      #[doc = concat!("* Panics in debug mode if <code>([self.pos()][Self::pos] % 8 != 0) && ([self.pos()][Self::pos] / 8) + ", stringify!($bytes), " >= [self.bytes()][Self::bytes].len()</code>")]
496      #[inline(always)]
497      pub unsafe fn $write_be_unchecked(&mut self, v: $ty) -> &mut Self {
498        unsafe { self.$write_be_at_unchecked(self.pos(), v) };
499        self.advance_bytes($bytes);
500        self
501      }
502
503      #[doc = concat!("Write a [`", stringify!($ty), "`] in [BE-bit, BE-byte] order at `byte_offset` while performing bound checks")]
504      ///
505      /// # Errors
506      ///
507      /// * Returns [`Error::OutOfBounds`]
508      #[doc = concat!("  * if <code>byte_offset + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
509      #[inline(always)]
510      pub fn $try_write_be_aligned_at(&mut self, byte_offset: usize, v: $ty) -> Result<&mut Self> {
511        let len = self.bytes().len();
512
513        if byte_offset + $offset >= len {
514          return Err(Error::OutOfBounds);
515        }
516
517        Ok(unsafe { self.$write_be_aligned_at_unchecked(byte_offset, v) })
518      }
519
520      #[doc = concat!("Write the next [`", stringify!($ty), "`] in [BE-bit, BE-byte] order while performing alignment and bound checks, advancing the internal cursor")]
521      ///
522      /// # Errors
523      ///
524      /// * Returns [`Error::Unaligned`]
525      ///   * if the internal cursor is not byte-aligned (<code>\![self.is_aligned()][Self::is_aligned]</code>)
526      /// * Returns [`Error::OutOfBounds`]
527      #[doc = concat!("  * if <code>[self.byte_pos()][Self::byte_pos] + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
528      #[inline(always)]
529      pub fn $try_write_be_aligned(&mut self, v: $ty) -> Result<&mut Self> {
530        if !self.is_aligned() {
531          return Err(Error::Unaligned);
532        }
533
534        self.$try_write_be_aligned_at(self.byte_pos(), v)?;
535        self.advance_bytes($bytes);
536        Ok(self)
537      }
538
539      #[doc = concat!("Write a [`", stringify!($ty), "`] in [BE-bit, BE-byte] order at `offset` while performing bound checks")]
540      ///
541      /// # Errors
542      ///
543      /// * Returns [`Error::OutOfBounds`]
544      #[doc = concat!("  * if <code>(offset / 8) + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
545      #[doc = concat!("  * if <code>(offset % 8 != 0) && (offset / 8) + ", stringify!($bytes), " >= [self.bytes()][Self::bytes].len()</code>")]
546      #[inline(always)]
547      pub fn $try_write_be_at(&mut self, offset: usize, v: $ty) -> Result<&mut Self> {
548        let byte_idx = offset / 8;
549        let shift = offset % 8;
550
551        let len = self.bytes().len();
552
553        if byte_idx + $offset >= len {
554          return Err(Error::OutOfBounds);
555        }
556
557        if shift != 0 && byte_idx + $bytes >= len {
558          return Err(Error::OutOfBounds);
559        }
560
561        Ok(unsafe { self.$write_be_at_unchecked(offset, v) })
562      }
563
564      #[doc = concat!("Write the next [`", stringify!($ty), "`] in [BE-bit, BE-byte] order while performing bound checks, advancing the internal cursor")]
565      ///
566      /// # Errors
567      ///
568      /// * Returns [`Error::OutOfBounds`]
569      #[doc = concat!("  * if <code>([self.pos()][Self::pos] / 8) + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
570      #[doc = concat!("  * if <code>([self.pos()][Self::pos] % 8 != 0) && ([self.pos()][Self::pos] / 8) + ", stringify!($bytes), " >= [self.bytes()][Self::bytes].len()</code>")]
571      #[inline(always)]
572      pub fn $try_write_be(&mut self, v: $ty) -> Result<&mut Self> {
573        self.$try_write_be_at(self.pos(), v)?;
574        self.advance_bytes($bytes);
575        Ok(self)
576      }
577
578      #[doc = concat!("Write a [`", stringify!($ty), "`] in [BE-bit, BE-byte] order at `byte_offset` panicking on out of bounds")]
579      ///
580      /// # Panics
581      ///
582      #[doc = concat!("* Panics if <code>byte_offset + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
583      #[inline(always)]
584      pub fn $write_be_aligned_at(&mut self, byte_offset: usize, v: $ty) -> &mut Self {
585        self
586          .$try_write_be_aligned_at(byte_offset, v)
587          .expect(concat!("BitBuf::", stringify!($write_be_aligned_at), " out of bounds"))
588      }
589
590      #[doc = concat!("Write the next [`", stringify!($ty), "`] in [BE-bit, BE-byte] order panicking on an unaligned cursor or out of bounds, advancing the internal cursor")]
591      ///
592      /// # Panics
593      ///
594      ///   * if the internal cursor is not byte-aligned (<code>\![self.is_aligned()][Self::is_aligned]</code>)
595      #[doc = concat!("  * if <code>[self.byte_pos()][Self::byte_pos] + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
596      #[inline(always)]
597      pub fn $write_be_aligned(&mut self, v: $ty) -> &mut Self {
598        self
599          .$try_write_be_aligned(v)
600          .expect(concat!("BitBuf::", stringify!($write_be_aligned), " unaligned cursor or out of bounds"))
601      }
602
603      #[doc = concat!("Write a [`", stringify!($ty), "`] in [BE-bit, BE-byte] order at `offset` panicking on out of bounds")]
604      ///
605      /// # Panics
606      ///
607      #[doc = concat!("* Panics if <code>(offset / 8) + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
608      #[doc = concat!("* Panics if <code>(offset % 8 != 0) && (offset / 8) + ", stringify!($bytes), " >= [self.bytes()][Self::bytes].len()</code>")]
609      #[inline(always)]
610      pub fn $write_be_at(&mut self, offset: usize, v: $ty) -> &mut Self {
611        self
612          .$try_write_be_at(offset, v)
613          .expect(concat!("BitBuf::", stringify!($write_be_at), " out of bounds"))
614      }
615
616      #[doc = concat!("Write the next [`", stringify!($ty), "`] in [BE-bit, BE-byte] order panicking on out of bounds")]
617      ///
618      /// # Panics
619      ///
620      #[doc = concat!("* Panics if <code>([self.pos()][Self::pos] / 8) + ", stringify!($offset), " >= [self.bytes()][Self::bytes].len()</code>")]
621      #[doc = concat!("* Panics if <code>([self.pos()][Self::pos] % 8 != 0) && ([self.pos()][Self::pos] / 8) + ", stringify!($bytes), " >= [self.bytes()][Self::bytes].len()</code>")]
622      #[inline(always)]
623      pub fn $write_be(&mut self, v: $ty) -> &mut Self {
624        self
625          .$try_write_be(v)
626          .expect(concat!("BitBuf::", stringify!($write_be), " out of bounds"))
627      }
628    }
629
630    impl Write for $ty {
631      #[inline(always)]
632      unsafe fn write_be_aligned_at_unchecked<S: StorageMut>(
633        buf: &mut BitBuf<S>,
634        byte_offset: usize,
635        v: Self,
636      ) -> &mut BitBuf<S> {
637        unsafe { buf.$write_be_aligned_at_unchecked(byte_offset, v) }
638      }
639
640      #[inline(always)]
641      unsafe fn write_be_aligned_unchecked<S: StorageMut>(
642        buf: &mut BitBuf<S>,
643        v: Self,
644      ) -> &mut BitBuf<S> {
645        unsafe { buf.$write_be_aligned_unchecked(v) }
646      }
647
648      #[inline(always)]
649      unsafe fn write_be_at_unchecked<S: StorageMut>(
650        buf: &mut BitBuf<S>,
651        offset: usize,
652        v: Self,
653      ) -> &mut BitBuf<S> {
654        unsafe { buf.$write_be_at_unchecked(offset, v) }
655      }
656
657      #[inline(always)]
658      unsafe fn write_be_unchecked<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> &mut BitBuf<S> {
659        unsafe { buf.$write_be_unchecked(v) }
660      }
661
662      #[inline(always)]
663      fn try_write_be_aligned_at<S: StorageMut>(
664        buf: &mut BitBuf<S>,
665        byte_offset: usize,
666        v: Self,
667      ) -> Result<&mut BitBuf<S>> {
668        buf.$try_write_be_aligned_at(byte_offset, v)
669      }
670
671      #[inline(always)]
672      fn try_write_be_aligned<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> Result<&mut BitBuf<S>> {
673        buf.$try_write_be_aligned(v)
674      }
675
676      #[inline(always)]
677      fn try_write_be_at<S: StorageMut>(
678        buf: &mut BitBuf<S>,
679        offset: usize,
680        v: Self,
681      ) -> Result<&mut BitBuf<S>> {
682        buf.$try_write_be_at(offset, v)
683      }
684
685      #[inline(always)]
686      fn try_write_be<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> Result<&mut BitBuf<S>> {
687        buf.$try_write_be(v)
688      }
689
690      #[inline(always)]
691      fn write_be_aligned_at<S: StorageMut>(buf: &mut BitBuf<S>, byte_offset: usize, v: Self) -> &mut BitBuf<S> {
692        buf.$write_be_aligned_at(byte_offset, v)
693      }
694
695      #[inline(always)]
696      fn write_be_aligned<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> &mut BitBuf<S> {
697        buf.$write_be_aligned(v)
698      }
699
700      #[inline(always)]
701      fn write_be_at<S: StorageMut>(buf: &mut BitBuf<S>, offset: usize, v: Self) -> &mut BitBuf<S> {
702        buf.$write_be_at(offset, v)
703      }
704
705      #[inline(always)]
706      fn write_be<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> &mut BitBuf<S> {
707        buf.$write_be(v)
708      }
709    }
710  };
711}
712
713use impl_write;