use core::{
ptr::{NonNull, copy_nonoverlapping, write_bytes},
slice::{from_raw_parts, from_raw_parts_mut},
};
use alloc::vec::Vec;
use super::{err::FMempError, osa_dealloc};
pub struct PoolBuffer {
size: usize,
addr: NonNull<u8>,
}
impl PoolBuffer {
pub fn new(size: usize, addr: NonNull<u8>) -> Self {
Self { size, addr }
}
pub fn copy_from_slice<T: Copy>(&mut self, src: &[T]) -> Result<(), &'static str> {
let len = size_of_val(src);
if self.size < len {
return Err("Too small to receive data!");
}
unsafe {
copy_nonoverlapping(src.as_ptr() as *mut u8, self.addr.as_ptr(), len);
}
Ok(())
}
pub fn as_slice<T>(&self) -> Result<&[T], FMempError> {
let size = size_of::<T>();
if !self.size().is_multiple_of(size) {
return Err(FMempError::SizeNotAligned);
}
unsafe {
let result = from_raw_parts(self.addr.as_ptr() as *const T, self.size() / size);
Ok(result)
}
}
pub fn as_slice_mut<T>(&self) -> Result<&[T], FMempError> {
let size = size_of::<T>();
if !self.size().is_multiple_of(size) {
return Err(FMempError::SizeNotAligned);
}
unsafe {
let result = from_raw_parts_mut(self.addr.as_ptr() as *mut T, self.size() / size);
Ok(result)
}
}
pub fn to_vec<T: Clone>(&self) -> Result<Vec<T>, FMempError> {
let slice = self.as_slice::<T>()?;
Ok(slice.to_vec())
}
pub fn clear(&mut self) {
unsafe {
write_bytes(self.addr.as_ptr(), 0, self.size);
}
}
pub fn size(&self) -> usize {
self.size
}
pub fn addr(&self) -> NonNull<u8> {
self.addr
}
}
impl Drop for PoolBuffer {
fn drop(&mut self) {
osa_dealloc(self.addr, self.size);
}
}
impl From<PoolBuffer> for Vec<u32> {
fn from(val: PoolBuffer) -> Self {
unsafe {
let slice = from_raw_parts(val.addr.as_ptr() as *const u32, val.size / 4);
slice.to_vec()
}
}
}