1use crate::{BitBuf, Error, Result, StorageMut};
2
3impl<S: StorageMut> BitBuf<S> {
4 #[inline(always)]
14 pub unsafe fn write_u8_be_aligned_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_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 #[inline(always)]
44 pub unsafe fn write_u8_be_aligned_unchecked(&mut self, v: u8) -> &mut Self {
45 debug_assert!(
46 self.is_aligned(),
47 "BitBuf::write_u8_be_aligned_unchecked called at unaligned bit position: {}",
48 self.pos(),
49 );
50
51 unsafe { self.write_u8_be_aligned_at_unchecked(self.byte_pos(), v) };
52 self.advance_bytes(1);
53 self
54 }
55
56 #[inline(always)]
68 pub unsafe fn write_u8_be_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_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_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_at_unchecked: lookahead index out of bounds! len is {}, lookahead byte_idx is {}",
89 bytes.len(),
90 next_idx,
91 );
92
93 unsafe {
95 let mask = !0 << (8 - shift);
97 let b = bytes.get_unchecked(byte_idx) & mask;
98 let new = v >> shift;
100 *bytes.get_unchecked_mut(byte_idx) = b | new;
101 }
102
103 unsafe {
105 let mask = !0 >> shift;
107 let b = bytes.get_unchecked(next_idx) & mask;
108 let new = v << (8 - shift);
110 *bytes.get_unchecked_mut(next_idx) = b | new;
111 }
112 }
113
114 self
115 }
116
117 #[inline(always)]
129 pub unsafe fn write_u8_be_unchecked(&mut self, v: u8) -> &mut Self {
130 unsafe { self.write_u8_be_at_unchecked(self.pos(), v) };
131 self.advance_bytes(1);
132 self
133 }
134
135 #[inline(always)]
143 pub fn try_write_u8_be_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_at_unchecked(offset, v) })
158 }
159
160 #[inline(always)]
168 pub fn try_write_u8_be(&mut self, v: u8) -> Result<&mut Self> {
169 self.try_write_u8_be_at(self.pos(), v)?;
170 self.advance_bytes(1);
171 Ok(self)
172 }
173
174 #[inline(always)]
181 pub fn write_u8_be_at(&mut self, offset: usize, v: u8) -> &mut Self {
182 self
183 .try_write_u8_be_at(offset, v)
184 .expect("BitBuf::write_u8_be_at out of bounds")
185 }
186
187 #[inline(always)]
194 pub fn write_u8_be(&mut self, v: u8) -> &mut Self {
195 self
196 .try_write_u8_be(v)
197 .expect("BitBuf::write_u8_be out of bounds")
198 }
199
200 #[inline(always)]
210 pub unsafe fn write_u16_be_aligned_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_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 #[inline(always)]
246 pub unsafe fn write_u16_be_aligned_unchecked(&mut self, v: u16) -> &mut Self {
247 debug_assert!(
248 self.is_aligned(),
249 "BitBuf::write_u16_be_aligned_unchecked called at unaligned bit position: {}",
250 self.pos(),
251 );
252
253 unsafe { self.write_u16_be_aligned_at_unchecked(self.byte_pos(), v) };
254 self.advance_bytes(2);
255 self
256 }
257
258 #[inline(always)]
270 pub unsafe fn write_u16_be_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_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_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_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 unsafe {
300 let mask = !0 << (8 - shift);
302 let b = bytes.get_unchecked(first_idx) & mask;
303 let new = high >> shift;
305 *bytes.get_unchecked_mut(first_idx) = b | new;
306 }
307
308 unsafe {
310 let b_high = high << (8 - shift);
313 let b_low = low >> shift;
315 *bytes.get_unchecked_mut(second_idx) = b_high | b_low;
316 }
317
318 unsafe {
320 let mask = !0 >> shift;
322 let b = bytes.get_unchecked(third_idx) & mask;
323 let new = low << (8 - shift);
325 *bytes.get_unchecked_mut(third_idx) = b | new;
326 }
327 }
328
329 self
330 }
331
332 #[inline(always)]
344 pub unsafe fn write_u16_be_unchecked(&mut self, v: u16) -> &mut Self {
345 unsafe { self.write_u16_be_at_unchecked(self.pos(), v) };
346 self.advance_bytes(2);
347 self
348 }
349
350 #[inline(always)]
358 pub fn try_write_u16_be_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_at_unchecked(offset, v) })
373 }
374
375 #[inline(always)]
383 pub fn try_write_u16_be(&mut self, v: u16) -> Result<&mut Self> {
384 self.try_write_u16_be_at(self.pos(), v)?;
385 self.advance_bytes(2);
386 Ok(self)
387 }
388
389 #[inline(always)]
396 pub fn write_u16_be_at(&mut self, offset: usize, v: u16) -> &mut Self {
397 self
398 .try_write_u16_be_at(offset, v)
399 .expect("BitBuf::write_u16_be_at out of bounds")
400 }
401
402 #[inline(always)]
409 pub fn write_u16_be(&mut self, v: u16) -> &mut Self {
410 self
411 .try_write_u16_be(v)
412 .expect("BitBuf::write_u16_be out of bounds")
413 }
414
415 #[inline(always)]
425 pub unsafe fn write_u32_be_aligned_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_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 #[inline(always)]
463 pub unsafe fn write_u32_be_aligned_unchecked(&mut self, v: u32) -> &mut Self {
464 debug_assert!(
465 self.is_aligned(),
466 "BitBuf::write_u32_be_aligned_unchecked called at unaligned bit position: {}",
467 self.pos(),
468 );
469
470 unsafe { self.write_u32_be_aligned_at_unchecked(self.byte_pos(), v) };
471 self.advance_bytes(4);
472 self
473 }
474
475 #[inline(always)]
487 pub unsafe fn write_u32_be_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_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_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_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 unsafe {
519 let mask = !0 << (8 - shift);
521 let byte = bytes.get_unchecked(first_idx) & mask;
522 let new = a >> shift;
524 *bytes.get_unchecked_mut(first_idx) = byte | new;
525 }
526
527 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 unsafe {
537 let mask = !0 >> shift;
539 let byte = bytes.get_unchecked(fifth_idx) & mask;
540 let new = d << (8 - shift);
542 *bytes.get_unchecked_mut(fifth_idx) = byte | new;
543 }
544 }
545
546 self
547 }
548
549 #[inline(always)]
561 pub unsafe fn write_u32_be_unchecked(&mut self, v: u32) -> &mut Self {
562 unsafe { self.write_u32_be_at_unchecked(self.pos(), v) };
563 self.advance_bytes(4);
564 self
565 }
566
567 #[inline(always)]
575 pub fn try_write_u32_be_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_at_unchecked(offset, v) })
590 }
591
592 #[inline(always)]
600 pub fn try_write_u32_be(&mut self, v: u32) -> Result<&mut Self> {
601 self.try_write_u32_be_at(self.pos(), v)?;
602 self.advance_bytes(4);
603 Ok(self)
604 }
605
606 #[inline(always)]
613 pub fn write_u32_be_at(&mut self, offset: usize, v: u32) -> &mut Self {
614 self
615 .try_write_u32_be_at(offset, v)
616 .expect("BitBuf::write_u32_be_at out of bounds")
617 }
618
619 #[inline(always)]
626 pub fn write_u32_be(&mut self, v: u32) -> &mut Self {
627 self
628 .try_write_u32_be(v)
629 .expect("BitBuf::write_u32_be out of bounds")
630 }
631}
632
633pub trait Write: Sized {
634 unsafe fn write_be_aligned_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_unchecked<S: StorageMut>(
641 buf: &mut BitBuf<S>,
642 v: Self,
643 ) -> &mut BitBuf<S>;
644
645 unsafe fn write_be_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_unchecked<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> &mut BitBuf<S>;
652
653 fn try_write_be_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<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> Result<&mut BitBuf<S>>;
660
661 fn write_be_at<S: StorageMut>(buf: &mut BitBuf<S>, offset: usize, v: Self) -> &mut BitBuf<S>;
662
663 fn write_be<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> &mut BitBuf<S>;
664}
665
666impl Write for u8 {
667 #[inline(always)]
668 unsafe fn write_be_aligned_at_unchecked<S: StorageMut>(
669 buf: &mut BitBuf<S>,
670 byte_offset: usize,
671 v: Self,
672 ) -> &mut BitBuf<S> {
673 unsafe { buf.write_u8_be_aligned_at_unchecked(byte_offset, v) }
674 }
675
676 #[inline(always)]
677 unsafe fn write_be_aligned_unchecked<S: StorageMut>(
678 buf: &mut BitBuf<S>,
679 v: Self,
680 ) -> &mut BitBuf<S> {
681 unsafe { buf.write_u8_be_aligned_unchecked(v) }
682 }
683
684 #[inline(always)]
685 unsafe fn write_be_at_unchecked<S: StorageMut>(
686 buf: &mut BitBuf<S>,
687 offset: usize,
688 v: Self,
689 ) -> &mut BitBuf<S> {
690 unsafe { buf.write_u8_be_at_unchecked(offset, v) }
691 }
692
693 #[inline(always)]
694 unsafe fn write_be_unchecked<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> &mut BitBuf<S> {
695 unsafe { buf.write_u8_be_unchecked(v) }
696 }
697
698 #[inline(always)]
699 fn try_write_be_at<S: StorageMut>(
700 buf: &mut BitBuf<S>,
701 offset: usize,
702 v: Self,
703 ) -> Result<&mut BitBuf<S>> {
704 buf.try_write_u8_be_at(offset, v)
705 }
706
707 #[inline(always)]
708 fn try_write_be<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> Result<&mut BitBuf<S>> {
709 buf.try_write_u8_be(v)
710 }
711
712 #[inline(always)]
713 fn write_be_at<S: StorageMut>(buf: &mut BitBuf<S>, offset: usize, v: Self) -> &mut BitBuf<S> {
714 buf.write_u8_be_at(offset, v)
715 }
716
717 #[inline(always)]
718 fn write_be<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> &mut BitBuf<S> {
719 buf.write_u8_be(v)
720 }
721}
722
723impl Write for u16 {
724 #[inline(always)]
725 unsafe fn write_be_aligned_at_unchecked<S: StorageMut>(
726 buf: &mut BitBuf<S>,
727 byte_offset: usize,
728 v: Self,
729 ) -> &mut BitBuf<S> {
730 unsafe { buf.write_u16_be_aligned_at_unchecked(byte_offset, v) }
731 }
732
733 #[inline(always)]
734 unsafe fn write_be_aligned_unchecked<S: StorageMut>(
735 buf: &mut BitBuf<S>,
736 v: Self,
737 ) -> &mut BitBuf<S> {
738 unsafe { buf.write_u16_be_aligned_unchecked(v) }
739 }
740
741 #[inline(always)]
742 unsafe fn write_be_at_unchecked<S: StorageMut>(
743 buf: &mut BitBuf<S>,
744 offset: usize,
745 v: Self,
746 ) -> &mut BitBuf<S> {
747 unsafe { buf.write_u16_be_at_unchecked(offset, v) }
748 }
749
750 #[inline(always)]
751 unsafe fn write_be_unchecked<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> &mut BitBuf<S> {
752 unsafe { buf.write_u16_be_unchecked(v) }
753 }
754
755 #[inline(always)]
756 fn try_write_be_at<S: StorageMut>(
757 buf: &mut BitBuf<S>,
758 offset: usize,
759 v: Self,
760 ) -> Result<&mut BitBuf<S>> {
761 buf.try_write_u16_be_at(offset, v)
762 }
763
764 #[inline(always)]
765 fn try_write_be<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> Result<&mut BitBuf<S>> {
766 buf.try_write_u16_be(v)
767 }
768
769 #[inline(always)]
770 fn write_be_at<S: StorageMut>(buf: &mut BitBuf<S>, offset: usize, v: Self) -> &mut BitBuf<S> {
771 buf.write_u16_be_at(offset, v)
772 }
773
774 #[inline(always)]
775 fn write_be<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> &mut BitBuf<S> {
776 buf.write_u16_be(v)
777 }
778}
779
780impl Write for u32 {
781 #[inline(always)]
782 unsafe fn write_be_aligned_at_unchecked<S: StorageMut>(
783 buf: &mut BitBuf<S>,
784 byte_offset: usize,
785 v: Self,
786 ) -> &mut BitBuf<S> {
787 unsafe { buf.write_u32_be_aligned_at_unchecked(byte_offset, v) }
788 }
789
790 #[inline(always)]
791 unsafe fn write_be_aligned_unchecked<S: StorageMut>(
792 buf: &mut BitBuf<S>,
793 v: Self,
794 ) -> &mut BitBuf<S> {
795 unsafe { buf.write_u32_be_aligned_unchecked(v) }
796 }
797
798 #[inline(always)]
799 unsafe fn write_be_at_unchecked<S: StorageMut>(
800 buf: &mut BitBuf<S>,
801 offset: usize,
802 v: Self,
803 ) -> &mut BitBuf<S> {
804 unsafe { buf.write_u32_be_at_unchecked(offset, v) }
805 }
806
807 #[inline(always)]
808 unsafe fn write_be_unchecked<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> &mut BitBuf<S> {
809 unsafe { buf.write_u32_be_unchecked(v) }
810 }
811
812 #[inline(always)]
813 fn try_write_be_at<S: StorageMut>(
814 buf: &mut BitBuf<S>,
815 offset: usize,
816 v: Self,
817 ) -> Result<&mut BitBuf<S>> {
818 buf.try_write_u32_be_at(offset, v)
819 }
820
821 #[inline(always)]
822 fn try_write_be<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> Result<&mut BitBuf<S>> {
823 buf.try_write_u32_be(v)
824 }
825
826 #[inline(always)]
827 fn write_be_at<S: StorageMut>(buf: &mut BitBuf<S>, offset: usize, v: Self) -> &mut BitBuf<S> {
828 buf.write_u32_be_at(offset, v)
829 }
830
831 #[inline(always)]
832 fn write_be<S: StorageMut>(buf: &mut BitBuf<S>, v: Self) -> &mut BitBuf<S> {
833 buf.write_u32_be(v)
834 }
835}
836
837impl<S: StorageMut> BitBuf<S> {
838 #[inline(always)]
848 pub unsafe fn write_be_aligned_at_unchecked<T: Write>(
849 &mut self,
850 byte_offset: usize,
851 v: T,
852 ) -> &mut Self {
853 unsafe { T::write_be_aligned_at_unchecked(self, byte_offset, v) }
854 }
855
856 #[inline(always)]
866 pub unsafe fn write_be_aligned_unchecked<T: Write>(&mut self, v: T) -> &mut Self {
867 unsafe { T::write_be_aligned_unchecked(self, v) }
868 }
869
870 #[inline(always)]
880 pub unsafe fn write_be_at_unchecked<T: Write>(&mut self, offset: usize, v: T) -> &mut Self {
881 unsafe { T::write_be_at_unchecked(self, offset, v) }
882 }
883
884 #[inline(always)]
894 pub unsafe fn write_be_unchecked<T: Write>(&mut self, v: T) -> &mut Self {
895 unsafe { T::write_be_unchecked(self, v) }
896 }
897
898 #[inline(always)]
904 pub fn try_write_be_at<T: Write>(&mut self, offset: usize, v: T) -> Result<&mut Self> {
905 T::try_write_be_at(self, offset, v)
906 }
907
908 #[inline(always)]
914 pub fn try_write_be<T: Write>(&mut self, v: T) -> Result<&mut Self> {
915 T::try_write_be(self, v)
916 }
917
918 #[inline(always)]
924 #[must_use]
925 pub fn write_be_at<T: Write>(&mut self, offset: usize, v: T) -> &mut Self {
926 T::write_be_at(self, offset, v)
927 }
928
929 #[inline(always)]
935 #[must_use]
936 pub fn write_be<T: Write>(&mut self, v: T) -> &mut Self {
937 T::write_be(self, v)
938 }
939}