use std::alloc::{Layout, alloc, dealloc};
use std::ops::{Deref, DerefMut};
const ALIGNMENT: usize = 4096;
pub struct AlignedBuf {
ptr: *mut u8,
len: usize,
capacity: usize,
}
impl AlignedBuf {
pub fn zeroed(len: usize) -> Self {
if len == 0 {
return Self {
ptr: std::ptr::NonNull::dangling().as_ptr(),
len: 0,
capacity: 0,
};
}
let capacity = (len + ALIGNMENT - 1) & !(ALIGNMENT - 1);
let layout = Layout::from_size_align(capacity, ALIGNMENT).expect("invalid layout");
let ptr = unsafe { alloc(layout) };
if ptr.is_null() {
std::alloc::handle_alloc_error(layout);
}
unsafe {
std::ptr::write_bytes(ptr, 0, capacity);
}
Self { ptr, len, capacity }
}
pub fn len(&self) -> usize {
self.len
}
}
impl Deref for AlignedBuf {
type Target = [u8];
fn deref(&self) -> &[u8] {
if self.capacity == 0 {
return &[];
}
unsafe { std::slice::from_raw_parts(self.ptr, self.len) }
}
}
impl DerefMut for AlignedBuf {
fn deref_mut(&mut self) -> &mut [u8] {
if self.capacity == 0 {
return &mut [];
}
unsafe { std::slice::from_raw_parts_mut(self.ptr, self.len) }
}
}
impl Drop for AlignedBuf {
fn drop(&mut self) {
if self.capacity == 0 {
return;
}
let layout = Layout::from_size_align(self.capacity, ALIGNMENT).expect("invalid layout");
unsafe {
dealloc(self.ptr, layout);
}
}
}
unsafe impl Send for AlignedBuf {}
unsafe impl Sync for AlignedBuf {}