extern crate alloc as alloc_crate;
use alloc_crate::alloc;
use alloc::Layout;
use core::mem;
use core::ptr::NonNull;
#[derive(Debug)]
pub struct Buffer<T> {
pub ptr: NonNull<T>,
pub cap: usize,
}
unsafe impl<T: Send> Send for Buffer<T> {}
unsafe impl<T: Sync> Sync for Buffer<T> {}
impl<T> Buffer<T> {
pub fn new() -> Self {
let cap = if mem::size_of::<T>() == 0 {
usize::MAX
} else {
0
};
Buffer {
ptr: NonNull::dangling(),
cap,
}
}
pub fn realloc(&mut self, new_cap: usize) {
assert!(mem::size_of::<T>() != 0, "capacity overflow");
assert!(new_cap > 0, "can't realloc to zero length");
let new_layout = Layout::array::<T>(new_cap).unwrap();
let new_ptr = if self.cap == 0 {
unsafe { alloc::alloc(new_layout) }
} else {
let old_layout = Layout::array::<T>(self.cap).unwrap();
let old_ptr = self.ptr.as_ptr().cast::<u8>();
unsafe { alloc::realloc(old_ptr, old_layout, new_layout.size()) }
};
self.ptr = match NonNull::new(new_ptr.cast::<T>()) {
Some(p) => p,
None => alloc::handle_alloc_error(new_layout),
};
self.cap = new_cap;
}
}
impl<T> Drop for Buffer<T> {
fn drop(&mut self) {
let elem_size = mem::size_of::<T>();
if self.cap != 0 && elem_size != 0 {
unsafe {
alloc::dealloc(
self.ptr.as_ptr().cast::<u8>(),
Layout::array::<T>(self.cap).unwrap(),
);
}
}
}
}