1use crate::aligned_alloc;
2use crate::boxed::AlignedBox;
3
4use alloc::alloc::alloc_zeroed;
5use core::fmt::{self, Debug};
6use core::ops::{Deref, DerefMut};
7use core::slice;
8
9pub struct AlignedBytes {
11 inner: AlignedBox<[u8]>,
12}
13
14impl AlignedBytes {
15 pub fn new_zeroed(len: usize, align: usize) -> Self {
17 let inner = unsafe {
18 let ptr = if len == 0 {
19 align as *mut u8
20 } else {
21 aligned_alloc(alloc_zeroed, len, align)
22 };
23 AlignedBox::from_raw(slice::from_raw_parts_mut(ptr, len), align)
24 };
25 debug_assert!(inner.as_ptr() as usize % align == 0);
26 Self { inner }
27 }
28
29 pub fn alignment(&self) -> usize {
31 AlignedBox::alignment(&self.inner)
32 }
33}
34
35impl Debug for AlignedBytes {
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 <[u8] as Debug>::fmt(&**self, f)
38 }
39}
40
41impl Deref for AlignedBytes {
42 type Target = [u8];
43 fn deref(&self) -> &Self::Target {
44 &*self.inner
45 }
46}
47
48impl DerefMut for AlignedBytes {
49 fn deref_mut(&mut self) -> &mut Self::Target {
50 &mut *self.inner
51 }
52}
53
54impl AsRef<[u8]> for AlignedBytes {
55 fn as_ref(&self) -> &[u8] {
56 &*self
57 }
58}
59
60impl AsMut<[u8]> for AlignedBytes {
61 fn as_mut(&mut self) -> &mut [u8] {
62 &mut *self
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use super::AlignedBytes;
69
70 #[test]
71 fn check_alignment() {
72 let align = 4096;
73 let bytes = AlignedBytes::new_zeroed(8, align);
74 assert_eq!(bytes.alignment(), align);
75 assert!(bytes.as_ptr() as usize % align == 0);
76 }
77
78 #[should_panic(expected = "Invalid layout: size = 1, align = 0")]
79 #[test]
80 fn check_layout_zero_align() {
81 AlignedBytes::new_zeroed(1, 0);
82 }
83
84 #[should_panic(expected = "Invalid layout: size = 1, align = 3")]
85 #[test]
86 fn check_layout_align_not_power_of_2() {
87 AlignedBytes::new_zeroed(1, 3);
88 }
89
90 #[should_panic]
91 #[test]
92 fn check_layout_overflow() {
93 let size = core::mem::size_of::<usize>() * 8;
94 AlignedBytes::new_zeroed((1usize << (size - 1)) + 1, 1usize << (size - 1));
95 }
96
97 #[test]
98 fn check_markers() {
99 fn require_send<T: Send>() {}
100 fn require_sync<T: Sync>() {}
101
102 require_send::<AlignedBytes>();
103 require_sync::<AlignedBytes>();
104
105 #[cfg(feature = "std")]
106 {
107 use std::panic::{RefUnwindSafe, UnwindSafe};
108 fn require_unwind_safe<T: UnwindSafe>() {}
109 fn require_ref_unwind_safe<T: RefUnwindSafe>() {}
110 require_unwind_safe::<AlignedBytes>();
111 require_ref_unwind_safe::<AlignedBytes>();
112 }
113 }
114
115 #[test]
116 fn check_zst() {
117 AlignedBytes::new_zeroed(0, 2);
118 }
119}