use std::{
cell::{Cell, UnsafeCell},
ops::Range,
};
use crate::{
buffer::{Buffer, InsertIntoBuffer, Resize},
write::{BytesSlice, WriteBytesSlice},
};
#[derive(Default)]
pub struct WriteVecBuffer<const HEADER_SIZE: usize = 0, const TRAILER_SIZE: usize = 0>(
Box<[Cell<u8>]>,
);
unsafe impl<const HEADER_SIZE: usize, const TRAILER_SIZE: usize> Buffer
for WriteVecBuffer<HEADER_SIZE, TRAILER_SIZE>
{
type Slice<'a> = BytesSlice<'a, HEADER_SIZE, TRAILER_SIZE>;
#[inline]
fn capacity(&self) -> usize {
self.0.len().saturating_sub(HEADER_SIZE + TRAILER_SIZE)
}
#[inline]
unsafe fn slice(&mut self, range: Range<usize>) -> Self::Slice<'_> {
BytesSlice::new(unsafe {
&mut *(&mut self.0[range.start..HEADER_SIZE + range.end + TRAILER_SIZE] as *mut _
as *mut [u8])
})
}
#[inline]
unsafe fn clear(&mut self, _range: Range<usize>) {}
}
unsafe impl<T, const HEADER_SIZE: usize, const TRAILER_SIZE: usize>
InsertIntoBuffer<WriteVecBuffer<HEADER_SIZE, TRAILER_SIZE>> for T
where
T: WriteBytesSlice,
{
#[inline]
fn size(&self) -> usize {
WriteBytesSlice::size(self)
}
#[inline]
unsafe fn insert_into(self, buffer: &WriteVecBuffer<HEADER_SIZE, TRAILER_SIZE>, index: usize) {
let slice =
&buffer.0[HEADER_SIZE + index..HEADER_SIZE + index + WriteBytesSlice::size(&self)];
self.write(unsafe {
&mut *UnsafeCell::raw_get(slice as *const _ as *const UnsafeCell<[u8]>)
});
}
}
impl<const HEADER_SIZE: usize, const TRAILER_SIZE: usize> Resize
for WriteVecBuffer<HEADER_SIZE, TRAILER_SIZE>
{
fn resize(&mut self, capacity: usize) {
let full_capacity = HEADER_SIZE + capacity + TRAILER_SIZE;
self.0 = unsafe {
Box::from_raw(Box::into_raw(vec![0u8; full_capacity].into_boxed_slice()) as *mut _)
};
}
}