1use core::mem::MaybeUninit;
5use std::any::type_name;
6use std::cmp::max;
7use std::fmt::Debug;
8use std::fmt::Formatter;
9use std::io::Write;
10use std::ops::Deref;
11use std::ops::DerefMut;
12
13use bytes::Buf;
14use bytes::BufMut;
15use bytes::BytesMut;
16use bytes::buf::UninitSlice;
17use itertools::Itertools;
18use vortex_error::VortexExpect;
19use vortex_error::vortex_panic;
20
21use crate::Alignment;
22use crate::Buffer;
23use crate::ByteBufferMut;
24use crate::debug::TruncatedDebug;
25use crate::trusted_len::TrustedLen;
26
27#[derive(PartialEq, Eq)]
29pub struct BufferMut<T> {
30 pub(crate) bytes: BytesMut,
31 pub(crate) length: usize,
32 pub(crate) alignment: Alignment,
33 pub(crate) _marker: std::marker::PhantomData<T>,
34}
35
36impl<T> BufferMut<T> {
37 pub fn with_capacity(capacity: usize) -> Self {
39 Self::with_capacity_aligned(capacity, Alignment::of::<T>())
40 }
41
42 pub fn with_capacity_aligned(capacity: usize, alignment: Alignment) -> Self {
49 Self::with_capacity_preferred_aligned(
50 capacity,
51 alignment,
52 Some(Alignment::DEFAULT_ALIGNMENT),
53 )
54 }
55
56 pub fn with_capacity_preferred_aligned(
61 capacity: usize,
62 alignment: Alignment,
63 preferred_alignment: Option<Alignment>,
64 ) -> Self {
65 let actual = max(
66 alignment,
67 preferred_alignment.unwrap_or(Alignment::of::<u8>()),
68 );
69
70 if !alignment.is_aligned_to(Alignment::of::<T>()) {
71 vortex_panic!(
72 "Alignment {} must align to the scalar type's alignment {}",
73 alignment,
74 align_of::<T>()
75 );
76 }
77
78 let mut bytes = BytesMut::with_capacity((capacity * size_of::<T>()) + *actual);
79 bytes.align_empty(actual);
80
81 Self {
82 bytes,
83 length: 0,
84 alignment,
85 _marker: Default::default(),
86 }
87 }
88
89 pub fn zeroed(len: usize) -> Self {
91 Self::zeroed_aligned(len, Alignment::of::<T>())
92 }
93
94 pub fn zeroed_aligned(len: usize, alignment: Alignment) -> Self {
101 Self::zeroed_preferred_aligned(len, alignment, Some(Alignment::DEFAULT_ALIGNMENT))
102 }
103
104 pub fn zeroed_preferred_aligned(
109 len: usize,
110 alignment: Alignment,
111 preferred_alignment: Option<Alignment>,
112 ) -> Self {
113 let preferred_alignment = preferred_alignment.unwrap_or(Alignment::of::<u8>());
114 let actual_alignment = max(preferred_alignment, alignment);
115 let mut bytes = BytesMut::zeroed((len * size_of::<T>()) + *actual_alignment);
116 bytes.advance(bytes.as_ptr().align_offset(*actual_alignment));
117 unsafe { bytes.set_len(len * size_of::<T>()) };
118 let actual_len = bytes.len().checked_div(size_of::<T>()).unwrap_or(0);
119 Self {
120 bytes,
121 length: actual_len,
122 alignment,
123 _marker: Default::default(),
124 }
125 }
126
127 pub fn empty() -> Self {
129 Self::empty_aligned(Alignment::of::<T>())
130 }
131
132 pub fn empty_aligned(alignment: Alignment) -> Self {
139 Self::empty_preferred_aligned(alignment, Some(Alignment::DEFAULT_ALIGNMENT))
140 }
141
142 pub fn empty_preferred_aligned(
147 alignment: Alignment,
148 preferred_alignment: Option<Alignment>,
149 ) -> Self {
150 BufferMut::with_capacity_preferred_aligned(0, alignment, preferred_alignment)
151 }
152
153 pub fn full(item: T, len: usize) -> Self
155 where
156 T: Copy,
157 {
158 let mut buffer = BufferMut::<T>::with_capacity(len);
159 buffer.push_n(item, len);
160 buffer
161 }
162
163 pub fn copy_from(other: impl AsRef<[T]>) -> Self {
165 Self::copy_from_aligned(other, Alignment::of::<T>())
166 }
167
168 pub fn copy_from_aligned(other: impl AsRef<[T]>, alignment: Alignment) -> Self {
179 Self::copy_from_preferred_aligned(other, alignment, Some(Alignment::DEFAULT_ALIGNMENT))
180 }
181
182 pub fn copy_from_preferred_aligned(
191 other: impl AsRef<[T]>,
192 alignment: Alignment,
193 preferred_alignment: Option<Alignment>,
194 ) -> Self {
195 if !alignment.is_aligned_to(Alignment::of::<T>()) {
196 vortex_panic!("Given alignment is not aligned to type T")
197 }
198 let other = other.as_ref();
199 let mut buffer =
200 Self::with_capacity_preferred_aligned(other.len(), alignment, preferred_alignment);
201 buffer.extend_from_slice(other);
202 debug_assert_eq!(buffer.alignment(), alignment);
203 buffer
204 }
205
206 #[inline(always)]
208 pub fn alignment(&self) -> Alignment {
209 self.alignment
210 }
211
212 #[inline(always)]
214 pub fn len(&self) -> usize {
215 debug_assert_eq!(self.length, self.bytes.len() / size_of::<T>());
216 self.length
217 }
218
219 #[inline(always)]
221 pub fn is_empty(&self) -> bool {
222 self.length == 0
223 }
224
225 #[inline]
227 pub fn capacity(&self) -> usize {
228 self.bytes.capacity() / size_of::<T>()
229 }
230
231 #[inline]
233 pub fn as_slice(&self) -> &[T] {
234 let raw_slice = self.bytes.as_ref();
235 unsafe { std::slice::from_raw_parts(raw_slice.as_ptr().cast(), self.length) }
237 }
238
239 #[inline]
241 pub fn as_mut_slice(&mut self) -> &mut [T] {
242 let raw_slice = self.bytes.as_mut();
243 unsafe { std::slice::from_raw_parts_mut(raw_slice.as_mut_ptr().cast(), self.length) }
245 }
246
247 #[inline]
249 pub fn clear(&mut self) {
250 unsafe { self.bytes.set_len(0) }
251 self.length = 0;
252 }
253
254 #[inline]
262 pub fn truncate(&mut self, len: usize) {
263 if len <= self.len() {
264 unsafe { self.set_len(len) };
266 }
267 }
268
269 #[inline]
271 pub fn reserve(&mut self, additional: usize) {
272 let additional_bytes = additional * size_of::<T>();
273 if additional_bytes <= self.bytes.capacity() - self.bytes.len() {
274 return;
276 }
277
278 self.reserve_allocate(additional);
280 }
281
282 fn reserve_allocate(&mut self, additional: usize) {
285 let new_capacity: usize = ((self.length + additional) * size_of::<T>()) + *self.alignment;
286 let new_capacity = new_capacity.max(self.bytes.capacity() * 2);
288
289 let mut bytes = BytesMut::with_capacity(new_capacity);
290 bytes.align_empty(self.alignment);
291 bytes.extend_from_slice(&self.bytes);
292 self.bytes = bytes;
293 }
294
295 #[inline]
331 pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit<T>] {
332 let dst = self.bytes.spare_capacity_mut().as_mut_ptr();
333 unsafe {
334 std::slice::from_raw_parts_mut(
335 dst as *mut MaybeUninit<T>,
336 self.capacity() - self.length,
337 )
338 }
339 }
340
341 #[inline]
350 pub unsafe fn set_len(&mut self, len: usize) {
351 debug_assert!(len <= self.capacity());
352 unsafe { self.bytes.set_len(len * size_of::<T>()) };
353 self.length = len;
354 }
355
356 #[inline]
358 pub fn push(&mut self, value: T) {
359 self.reserve(1);
360 unsafe { self.push_unchecked(value) }
361 }
362
363 #[inline]
369 pub unsafe fn push_unchecked(&mut self, item: T) {
370 unsafe {
372 let dst: *mut T = self.bytes.spare_capacity_mut().as_mut_ptr().cast();
373 dst.write(item);
374 self.bytes.set_len(self.bytes.len() + size_of::<T>())
375 }
376 self.length += 1;
377 }
378
379 #[inline]
383 pub fn push_n(&mut self, item: T, n: usize)
384 where
385 T: Copy,
386 {
387 self.reserve(n);
388 unsafe { self.push_n_unchecked(item, n) }
389 }
390
391 #[inline]
397 pub unsafe fn push_n_unchecked(&mut self, item: T, n: usize)
398 where
399 T: Copy,
400 {
401 let mut dst: *mut T = self.bytes.spare_capacity_mut().as_mut_ptr().cast();
402 unsafe {
404 let end = dst.add(n);
405 while dst < end {
406 dst.write(item);
407 dst = dst.add(1);
408 }
409 self.bytes.set_len(self.bytes.len() + (n * size_of::<T>()));
410 }
411 self.length += n;
412 }
413
414 #[inline]
427 pub fn extend_from_slice(&mut self, slice: &[T]) {
428 self.reserve(slice.len());
429 let raw_slice =
430 unsafe { std::slice::from_raw_parts(slice.as_ptr().cast(), size_of_val(slice)) };
431 self.bytes.extend_from_slice(raw_slice);
432 self.length += slice.len();
433 }
434
435 pub fn split_off(&mut self, at: usize) -> Self {
445 if at > self.capacity() {
446 vortex_panic!("Cannot split buffer of capacity {} at {}", self.len(), at);
447 }
448
449 let bytes_at = at * size_of::<T>();
450 if !self.alignment.is_offset_aligned(bytes_at) {
451 vortex_panic!(
452 "Cannot split buffer at {}, resulting alignment is not {}",
453 at,
454 self.alignment
455 );
456 }
457
458 let new_bytes = self.bytes.split_off(bytes_at);
459
460 let new_length = self.length.saturating_sub(at);
462 self.length = self.length.min(at);
463
464 BufferMut {
465 bytes: new_bytes,
466 length: new_length,
467 alignment: self.alignment,
468 _marker: Default::default(),
469 }
470 }
471
472 pub fn unsplit(&mut self, other: Self) {
480 if self.alignment != other.alignment {
481 vortex_panic!(
482 "Cannot unsplit buffers with different alignments: {} and {}",
483 self.alignment,
484 other.alignment
485 );
486 }
487 self.bytes.unsplit(other.bytes);
488 self.length += other.length;
489 }
490
491 pub fn into_byte_buffer(self) -> ByteBufferMut {
493 ByteBufferMut {
494 bytes: self.bytes,
495 length: self.length * size_of::<T>(),
496 alignment: self.alignment,
497 _marker: Default::default(),
498 }
499 }
500
501 pub fn freeze(self) -> Buffer<T> {
503 Buffer {
504 bytes: self.bytes.freeze(),
505 length: self.length,
506 alignment: self.alignment,
507 _marker: Default::default(),
508 }
509 }
510
511 pub fn map_each_in_place<R, F>(self, mut f: F) -> BufferMut<R>
513 where
514 T: Copy,
515 F: FnMut(T) -> R,
516 {
517 assert_eq!(
518 size_of::<T>(),
519 size_of::<R>(),
520 "Size of T and R do not match"
521 );
522 let mut buf: BufferMut<R> = unsafe { std::mem::transmute(self) };
524 buf.iter_mut()
525 .for_each(|item| *item = f(unsafe { std::mem::transmute_copy(item) }));
526 buf
527 }
528
529 pub fn aligned(self, alignment: Alignment) -> Self {
535 if self.as_ptr().align_offset(*alignment) == 0 {
536 Self {
537 bytes: self.bytes,
538 length: self.length,
539 alignment,
540 _marker: std::marker::PhantomData,
541 }
542 } else {
543 Self::copy_from_aligned(self, alignment)
544 }
545 }
546
547 pub unsafe fn transmute<U>(self) -> BufferMut<U> {
559 assert_eq!(size_of::<T>(), size_of::<U>(), "Buffer type size mismatch");
560 assert_eq!(
561 align_of::<T>(),
562 align_of::<U>(),
563 "Buffer type alignment mismatch"
564 );
565
566 BufferMut {
567 bytes: self.bytes,
568 length: self.length,
569 alignment: self.alignment,
570 _marker: std::marker::PhantomData,
571 }
572 }
573}
574
575impl<T> Clone for BufferMut<T> {
576 fn clone(&self) -> Self {
577 let mut buffer = BufferMut::<T>::with_capacity_aligned(self.capacity(), self.alignment);
580 buffer.extend_from_slice(self.as_slice());
581 buffer
582 }
583}
584
585impl<T: Debug> Debug for BufferMut<T> {
586 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
587 f.debug_struct(&format!("BufferMut<{}>", type_name::<T>()))
588 .field("length", &self.length)
589 .field("alignment", &self.alignment)
590 .field("as_slice", &TruncatedDebug(self.as_slice()))
591 .finish()
592 }
593}
594
595impl<T> Default for BufferMut<T> {
596 fn default() -> Self {
597 Self::empty()
598 }
599}
600
601impl<T> Deref for BufferMut<T> {
602 type Target = [T];
603
604 #[inline]
605 fn deref(&self) -> &Self::Target {
606 self.as_slice()
607 }
608}
609
610impl<T> DerefMut for BufferMut<T> {
611 #[inline]
612 fn deref_mut(&mut self) -> &mut Self::Target {
613 self.as_mut_slice()
614 }
615}
616
617impl<T> AsRef<[T]> for BufferMut<T> {
618 #[inline]
619 fn as_ref(&self) -> &[T] {
620 self.as_slice()
621 }
622}
623
624impl<T> AsMut<[T]> for BufferMut<T> {
625 #[inline]
626 fn as_mut(&mut self) -> &mut [T] {
627 self.as_mut_slice()
628 }
629}
630
631impl<T> BufferMut<T> {
632 fn extend_iter(&mut self, mut iter: impl Iterator<Item = T>) {
637 let (lower_bound, _) = iter.size_hint();
640
641 self.reserve(lower_bound);
644
645 let unwritten = self.capacity() - self.len();
646
647 let begin: *const T = self.bytes.spare_capacity_mut().as_mut_ptr().cast();
649 let mut dst: *mut T = begin.cast_mut();
650
651 for _ in 0..unwritten {
653 let Some(item) = iter.next() else {
654 break;
656 };
657
658 unsafe { dst.write(item) };
661
662 unsafe { dst = dst.add(1) };
667 }
668
669 let items_written = unsafe { dst.offset_from_unsigned(begin) };
672 let length = self.len() + items_written;
673
674 unsafe { self.set_len(length) };
676
677 iter.for_each(|item| self.push(item));
680 }
681
682 pub fn extend_trusted<I: TrustedLen<Item = T>>(&mut self, iter: I) {
687 let (_, upper_bound) = iter.size_hint();
688 self.reserve(
689 upper_bound
690 .vortex_expect("`TrustedLen` iterator somehow didn't have valid upper bound"),
691 );
692
693 let begin: *const T = self.bytes.spare_capacity_mut().as_mut_ptr().cast();
694 let mut dst: *mut T = begin.cast_mut();
695
696 iter.for_each(|item| {
697 unsafe { dst.write(item) };
700
701 unsafe { dst = dst.add(1) };
706 });
707
708 let items_written = unsafe { dst.offset_from_unsigned(begin) };
711 let length = self.len() + items_written;
712
713 unsafe { self.set_len(length) };
715 }
716
717 pub fn from_trusted_len_iter<I>(iter: I) -> Self
721 where
722 I: TrustedLen<Item = T>,
723 {
724 let (_, upper_bound) = iter.size_hint();
725 let mut buffer = Self::with_capacity(
726 upper_bound
727 .vortex_expect("`TrustedLen` iterator somehow didn't have valid upper bound"),
728 );
729
730 buffer.extend_trusted(iter);
731 buffer
732 }
733
734 pub fn try_extend_trusted<E, I>(&mut self, iter: I) -> Result<(), E>
739 where
740 I: TrustedLen<Item = Result<T, E>>,
741 {
742 iter.process_results(|values| self.extend_trusted(values))
743 }
744
745 pub fn try_from_trusted_len_iter<E, I>(iter: I) -> Result<Self, E>
748 where
749 I: TrustedLen<Item = Result<T, E>>,
750 {
751 iter.process_results(|values| Self::from_trusted_len_iter(values))
752 }
753}
754
755impl<T> Extend<T> for BufferMut<T> {
756 #[inline]
757 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
758 self.extend_iter(iter.into_iter())
759 }
760}
761
762impl<'a, T> Extend<&'a T> for BufferMut<T>
763where
764 T: Copy + 'a,
765{
766 #[inline]
767 fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
768 self.extend_iter(iter.into_iter().copied())
769 }
770}
771
772impl<T> FromIterator<T> for BufferMut<T> {
773 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
774 let mut buffer = Self::with_capacity(0);
776 buffer.extend(iter);
777 buffer
778 }
779}
780
781impl Buf for ByteBufferMut {
782 fn remaining(&self) -> usize {
783 self.len()
784 }
785
786 fn chunk(&self) -> &[u8] {
787 self.as_slice()
788 }
789
790 fn advance(&mut self, cnt: usize) {
791 if !self.alignment.is_offset_aligned(cnt) {
792 vortex_panic!(
793 "Cannot advance buffer by {} items, resulting alignment is not {}",
794 cnt,
795 self.alignment
796 );
797 }
798 self.bytes.advance(cnt);
799 self.length -= cnt;
800 }
801}
802
803unsafe impl BufMut for ByteBufferMut {
807 #[inline]
808 fn remaining_mut(&self) -> usize {
809 usize::MAX - self.len()
810 }
811
812 #[inline]
813 unsafe fn advance_mut(&mut self, cnt: usize) {
814 if !self.alignment.is_offset_aligned(cnt) {
815 vortex_panic!(
816 "Cannot advance buffer by {} items, resulting alignment is not {}",
817 cnt,
818 self.alignment
819 );
820 }
821 unsafe { self.bytes.advance_mut(cnt) };
822 self.length -= cnt;
823 }
824
825 #[inline]
826 fn chunk_mut(&mut self) -> &mut UninitSlice {
827 self.bytes.chunk_mut()
828 }
829
830 fn put<T: Buf>(&mut self, mut src: T)
831 where
832 Self: Sized,
833 {
834 while src.has_remaining() {
835 let chunk = src.chunk();
836 self.extend_from_slice(chunk);
837 src.advance(chunk.len());
838 }
839 }
840
841 #[inline]
842 fn put_slice(&mut self, src: &[u8]) {
843 self.extend_from_slice(src);
844 }
845
846 #[inline]
847 fn put_bytes(&mut self, val: u8, cnt: usize) {
848 self.push_n(val, cnt)
849 }
850}
851
852trait AlignedBytesMut {
854 fn align_empty(&mut self, alignment: Alignment);
860}
861
862impl AlignedBytesMut for BytesMut {
863 fn align_empty(&mut self, alignment: Alignment) {
864 if !self.is_empty() {
866 vortex_panic!("ByteBufferMut must be empty");
867 }
868
869 let padding = self.as_ptr().align_offset(*alignment);
870 self.capacity()
871 .checked_sub(padding)
872 .vortex_expect("Not enough capacity to align buffer");
873
874 unsafe { self.set_len(padding) };
877 self.advance(padding);
878 }
879}
880
881impl Write for ByteBufferMut {
882 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
883 self.extend_from_slice(buf);
884 Ok(buf.len())
885 }
886
887 fn flush(&mut self) -> std::io::Result<()> {
888 Ok(())
889 }
890}
891
892#[cfg(test)]
893mod test {
894 use bytes::Buf;
895 use bytes::BufMut;
896
897 use crate::Alignment;
898 use crate::BufferMut;
899 use crate::ByteBufferMut;
900 use crate::buffer_mut;
901
902 #[test]
903 fn capacity() {
904 let mut n = 57;
905 let mut buf = BufferMut::<i32>::with_capacity_aligned(n, Alignment::new(1024));
906 assert!(buf.capacity() >= 57);
907
908 while n > 0 {
909 buf.push(0);
910 assert!(buf.capacity() >= n);
911 n -= 1
912 }
913
914 assert_eq!(buf.alignment(), Alignment::new(1024));
915 }
916
917 #[test]
918 fn from_iter() {
919 let buf = BufferMut::from_iter([0, 10, 20, 30]);
920 assert_eq!(buf.as_slice(), &[0, 10, 20, 30]);
921 }
922
923 #[test]
924 fn try_from_trusted_len_iter_ok() {
925 let buf = BufferMut::<i32>::try_from_trusted_len_iter(
926 [0, 10, 20, 30].iter().map(|&v| Ok::<_, ()>(v)),
927 )
928 .unwrap();
929 assert_eq!(buf.as_slice(), &[0, 10, 20, 30]);
930 }
931
932 #[test]
933 fn try_from_trusted_len_iter_err() {
934 let result: Result<BufferMut<i32>, &'static str> = BufferMut::try_from_trusted_len_iter(
935 [0, 10, 20, 30]
936 .iter()
937 .map(|&v| if v == 20 { Err("bad") } else { Ok(v) }),
938 );
939 assert_eq!(result.err(), Some("bad"));
940 }
941
942 #[test]
943 fn try_extend_trusted_retains_values_before_error() {
944 let mut buf = BufferMut::from_iter([0, 10]);
945 let result = buf.try_extend_trusted([Ok(20), Err("bad"), Ok(30)].into_iter());
946
947 assert_eq!(result, Err("bad"));
948 assert_eq!(buf.as_slice(), &[0, 10, 20]);
949 }
950
951 #[test]
952 fn extend() {
953 let mut buf = BufferMut::empty();
954 buf.extend([0i32, 10, 20, 30]);
955 buf.extend([40, 50, 60]);
956 assert_eq!(buf.as_slice(), &[0, 10, 20, 30, 40, 50, 60]);
957 }
958
959 #[test]
960 fn push() {
961 let mut buf = BufferMut::empty();
962 buf.push(1);
963 buf.push(2);
964 buf.push(3);
965 assert_eq!(buf.as_slice(), &[1, 2, 3]);
966 }
967
968 #[test]
969 fn push_n() {
970 let mut buf = BufferMut::empty();
971 buf.push_n(0, 100);
972 assert_eq!(buf.as_slice(), &[0; 100]);
973 }
974
975 #[test]
976 fn as_mut() {
977 let mut buf = buffer_mut![0, 1, 2];
978 buf[1] = 0;
980 buf.as_mut()[2] = 0;
982 assert_eq!(buf.as_slice(), &[0, 0, 0]);
983 }
984
985 #[test]
986 fn map_each() {
987 let buf = buffer_mut![0i32, 1, 2];
988 let buf = buf.map_each_in_place(|i| (i + 1) as u32);
990 assert_eq!(buf.as_slice(), &[1u32, 2, 3]);
991 }
992
993 #[test]
994 fn bytes_buf() {
995 let mut buf = ByteBufferMut::copy_from("helloworld".as_bytes());
996 assert_eq!(buf.remaining(), 10);
997 assert_eq!(buf.chunk(), b"helloworld");
998
999 buf.advance(5);
1000 assert_eq!(buf.remaining(), 5);
1001 assert_eq!(buf.as_slice(), b"world");
1002 assert_eq!(buf.chunk(), b"world");
1003 }
1004
1005 #[test]
1006 fn bytes_buf_mut() {
1007 let mut buf = ByteBufferMut::copy_from("hello".as_bytes());
1008 assert_eq!(BufMut::remaining_mut(&buf), usize::MAX - 5);
1009
1010 buf.put_slice(b"world");
1011 assert_eq!(buf.as_slice(), b"helloworld");
1012 }
1013
1014 #[test]
1015 fn buffer_mut_zeroed() {
1016 const LEN: usize = 17;
1017
1018 let mut buf = BufferMut::<u32>::zeroed(LEN);
1019
1020 assert_eq!(buf.as_ptr().align_offset(*Alignment::of::<u32>()), 0);
1021 assert_eq!(buf.as_slice(), &[0; LEN]);
1022
1023 buf[3] = 7;
1024 assert_eq!(buf.as_slice()[3], 7);
1025 }
1026
1027 #[test]
1028 fn buffer_mut_zeroed_aligned() {
1029 const LEN: usize = 17;
1030 let alignment = Alignment::new(64);
1031
1032 let mut buf = BufferMut::<u32>::zeroed_aligned(LEN, alignment);
1033
1034 assert_eq!(buf.as_ptr().align_offset(*alignment), 0);
1035 assert_eq!(buf.as_slice(), &[0; LEN]);
1036
1037 buf[3] = 7;
1038 assert_eq!(buf.as_slice()[3], 7);
1039 }
1040}