use std::{alloc, mem, ptr};
#[repr(C)]
pub struct InnerVarchar {
len: u16,
data: [u8; 0],
}
#[derive(Debug)]
pub struct Varchar {
capacity: u16,
ptr: ptr::NonNull<InnerVarchar>,
}
unsafe impl Send for Varchar {}
impl Varchar {
pub fn new(capacity: u16) -> Self {
let mut ptr = match ptr::NonNull::new(unsafe {
alloc::alloc(layout(capacity as usize)) as *mut InnerVarchar
}) {
Some(ptr) => ptr,
None => alloc::handle_alloc_error(layout(capacity as usize)),
};
unsafe { ptr.as_mut().len = 0 };
Varchar { capacity, ptr }
}
pub fn as_bytes(&self) -> &[u8] {
let len = u16::min(self.capacity, unsafe { self.ptr.as_ref().len }) as usize;
unsafe {
let ptr = self.ptr.as_ref().data.as_ptr();
std::slice::from_raw_parts(ptr, len).get_unchecked(..len)
}
}
pub fn as_ptr(&self) -> *mut InnerVarchar {
self.ptr.as_ptr()
}
}
impl Drop for Varchar {
fn drop(&mut self) {
unsafe {
alloc::dealloc(self.ptr.as_ptr() as *mut u8, layout(self.capacity as usize));
}
}
}
fn layout(len: usize) -> alloc::Layout {
alloc::Layout::from_size_align(
mem::size_of::<InnerVarchar>() + len,
mem::align_of::<InnerVarchar>(),
)
.unwrap()
}