use core::alloc::Layout;
use core::ptr::NonNull;
use core::slice;
pub struct AlignedBuf {
ptr: NonNull<u8>,
len: usize,
capacity: usize,
alignment: usize,
}
#[expect(
unsafe_code,
reason = "raw-pointer wrapper; Send/Sync soundness justified"
)]
unsafe impl Send for AlignedBuf {}
#[expect(
unsafe_code,
reason = "raw-pointer wrapper; Send/Sync soundness justified"
)]
unsafe impl Sync for AlignedBuf {}
impl AlignedBuf {
#[must_use]
pub fn new_zeroed(capacity: usize, alignment: usize) -> Option<Self> {
if !alignment.is_power_of_two() {
return None;
}
if alignment > (isize::MAX as usize) {
return None;
}
let rounded = capacity.checked_add(alignment - 1)? & !(alignment - 1);
if rounded > (isize::MAX as usize) {
return None;
}
if rounded == 0 {
let dangling = {
#[expect(unsafe_code, reason = "non-null dangling for 0-cap buffer")]
unsafe {
NonNull::new_unchecked(core::ptr::without_provenance_mut::<u8>(alignment))
}
};
return Some(Self {
ptr: dangling,
len: 0,
capacity: 0,
alignment,
});
}
let layout = Layout::from_size_align(rounded, alignment).ok()?;
#[expect(unsafe_code, reason = "global allocator call with validated layout")]
let raw = unsafe { alloc::alloc::alloc_zeroed(layout) };
let ptr = NonNull::new(raw)?;
Some(Self {
ptr,
len: 0,
capacity: rounded,
alignment,
})
}
#[must_use]
pub const fn len(&self) -> usize {
self.len
}
#[must_use]
pub const fn capacity(&self) -> usize {
self.capacity
}
#[must_use]
pub const fn alignment(&self) -> usize {
self.alignment
}
#[must_use]
pub const fn is_empty(&self) -> bool {
self.len == 0
}
#[must_use]
pub const fn as_ptr(&self) -> *const u8 {
self.ptr.as_ptr().cast_const()
}
#[must_use]
pub const fn as_mut_ptr(&mut self) -> *mut u8 {
self.ptr.as_ptr()
}
#[must_use]
pub const fn as_slice(&self) -> &[u8] {
#[expect(unsafe_code, reason = "slice over owned aligned allocation")]
unsafe {
slice::from_raw_parts(self.ptr.as_ptr(), self.len)
}
}
#[must_use]
pub const fn as_capacity_mut(&mut self) -> &mut [u8] {
#[expect(unsafe_code, reason = "mut slice over owned aligned allocation")]
unsafe {
slice::from_raw_parts_mut(self.ptr.as_ptr(), self.capacity)
}
}
pub const fn set_len(&mut self, new_len: usize) {
assert!(
new_len <= self.capacity,
"AlignedBuf::set_len exceeds capacity",
);
self.len = new_len;
}
pub const fn clear(&mut self) {
self.len = 0;
}
}
impl Drop for AlignedBuf {
fn drop(&mut self) {
if self.capacity == 0 {
return;
}
let Ok(layout) = Layout::from_size_align(self.capacity, self.alignment) else {
return;
};
#[expect(unsafe_code, reason = "matched dealloc for owned allocation")]
unsafe {
alloc::alloc::dealloc(self.ptr.as_ptr(), layout);
}
}
}
#[cfg(test)]
#[expect(clippy::unwrap_used, reason = "test assertions")]
mod tests {
use super::*;
#[test]
fn new_zeroed_4k_aligned() {
let buf = AlignedBuf::new_zeroed(8192, 4096).unwrap();
assert_eq!(buf.capacity(), 8192);
assert_eq!(buf.len(), 0);
assert_eq!(buf.alignment(), 4096);
assert_eq!(buf.as_ptr().addr() % 4096, 0, "pointer not 4 KiB aligned");
assert!(buf.is_empty());
}
#[test]
fn new_zeroed_rounds_capacity_up_to_alignment() {
let buf = AlignedBuf::new_zeroed(5000, 4096).unwrap();
assert_eq!(buf.capacity(), 8192);
let buf = AlignedBuf::new_zeroed(8192, 4096).unwrap();
assert_eq!(buf.capacity(), 8192);
}
#[test]
fn new_zeroed_returns_zeroed_memory() {
let mut buf = AlignedBuf::new_zeroed(4096, 4096).unwrap();
let cap = buf.as_capacity_mut();
assert!(cap.iter().all(|&b| b == 0));
}
#[test]
fn new_zeroed_rejects_non_power_of_two_alignment() {
assert!(AlignedBuf::new_zeroed(4096, 3000).is_none());
assert!(AlignedBuf::new_zeroed(4096, 0).is_none());
}
#[test]
fn new_zeroed_rejects_excessive_alignment() {
assert!(AlignedBuf::new_zeroed(4096, (isize::MAX as usize) + 1).is_none());
}
#[test]
fn new_zeroed_zero_capacity_returns_dangling() {
let buf = AlignedBuf::new_zeroed(0, 4096).unwrap();
assert_eq!(buf.capacity(), 0);
assert_eq!(buf.as_ptr().addr() % 4096, 0);
assert!(buf.as_slice().is_empty());
}
#[test]
fn set_len_grows_visible_slice() {
let mut buf = AlignedBuf::new_zeroed(4096, 4096).unwrap();
assert_eq!(buf.as_slice().len(), 0);
buf.set_len(1024);
assert_eq!(buf.as_slice().len(), 1024);
assert_eq!(buf.len(), 1024);
}
#[test]
#[should_panic(expected = "AlignedBuf::set_len exceeds capacity")]
fn set_len_panics_past_capacity() {
let mut buf = AlignedBuf::new_zeroed(4096, 4096).unwrap();
buf.set_len(buf.capacity() + 1);
}
#[test]
fn clear_resets_len_but_preserves_capacity() {
let mut buf = AlignedBuf::new_zeroed(4096, 4096).unwrap();
buf.set_len(2048);
buf.clear();
assert_eq!(buf.len(), 0);
assert_eq!(buf.capacity(), 4096);
}
#[test]
fn as_capacity_mut_covers_full_capacity() {
let mut buf = AlignedBuf::new_zeroed(4096, 4096).unwrap();
let cap = buf.as_capacity_mut();
assert_eq!(cap.len(), 4096);
*cap.first_mut().unwrap() = 0xAB;
*cap.last_mut().unwrap() = 0xCD;
buf.set_len(4096);
let slice = buf.as_slice();
assert_eq!(slice.first().copied(), Some(0xAB));
assert_eq!(slice.last().copied(), Some(0xCD));
}
#[test]
fn send_sync_compile_check() {
fn assert_send_sync<T: Send + Sync>() {}
assert_send_sync::<AlignedBuf>();
}
#[test]
fn pointer_stays_stable_across_writes() {
let mut buf = AlignedBuf::new_zeroed(4096, 4096).unwrap();
let initial = buf.as_ptr();
*buf.as_capacity_mut().first_mut().unwrap() = 1;
buf.set_len(1);
assert_eq!(buf.as_ptr(), initial);
}
}