1use crate::{BitBuf, Error, Result, StorageMut};
2
3impl<S: StorageMut> BitBuf<S> {
4 #[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 #[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 #[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 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_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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 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_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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 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_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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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}