use std::alloc::{self, Layout};
use std::mem;
use std::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) {
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() as *mut u8;
unsafe { alloc::realloc(old_ptr, old_layout, new_layout.size()) }
};
self.ptr = match NonNull::new(new_ptr as *mut 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() as *mut u8,
Layout::array::<T>(self.cap).unwrap(),
);
}
}
}
}