use std::ptr;
use crate::sys::uring::UringBuffer;
use alloc::alloc::Layout;
#[derive(Debug)]
pub(crate) struct SysAlloc {
data: ptr::NonNull<u8>,
layout: Layout,
}
impl SysAlloc {
fn new(size: usize) -> Option<Self> {
if size == 0 {
None
} else {
let layout = Layout::from_size_align(size, 4096).unwrap();
let data = unsafe { alloc::alloc::alloc(layout) as *mut u8 };
let data = ptr::NonNull::new(data)?;
Some(SysAlloc { data, layout })
}
}
fn as_ptr(&self) -> *const u8 {
self.data.as_ptr()
}
fn as_mut_ptr(&mut self) -> *mut u8 {
self.data.as_ptr()
}
}
impl Drop for SysAlloc {
fn drop(&mut self) {
unsafe {
alloc::alloc::dealloc(self.data.as_ptr(), self.layout);
}
}
}
#[derive(Debug)]
pub(crate) enum BufferStorage {
Sys(SysAlloc),
Uring(UringBuffer),
EventFd(*mut u8),
}
impl BufferStorage {
fn as_ptr(&self) -> *const u8 {
match self {
BufferStorage::Sys(x) => x.as_ptr(),
BufferStorage::Uring(x) => x.as_ptr(),
BufferStorage::EventFd(x) => *x as *const u8,
}
}
fn as_mut_ptr(&mut self) -> *mut u8 {
match self {
BufferStorage::Sys(x) => x.as_mut_ptr(),
BufferStorage::Uring(x) => x.as_mut_ptr(),
BufferStorage::EventFd(x) => *x,
}
}
}
#[derive(Debug)]
pub struct DmaBuffer {
storage: BufferStorage,
trim: usize,
size: usize,
}
impl DmaBuffer {
pub(crate) fn new(size: usize) -> Option<DmaBuffer> {
Some(DmaBuffer {
storage: BufferStorage::Sys(SysAlloc::new(size)?),
size,
trim: 0,
})
}
pub(crate) fn with_storage(size: usize, storage: BufferStorage) -> DmaBuffer {
DmaBuffer {
storage,
size,
trim: 0,
}
}
pub(crate) fn uring_buffer_id(&self) -> Option<u32> {
match &self.storage {
BufferStorage::Uring(x) => x.uring_buffer_id(),
_ => None,
}
}
pub(crate) fn trim_to_size(&mut self, newsize: usize) {
assert!(newsize <= self.size);
self.size = newsize;
}
pub fn as_bytes(&self) -> &[u8] {
unsafe { std::slice::from_raw_parts(self.as_ptr(), self.size) }
}
pub fn as_bytes_mut(&mut self) -> &mut [u8] {
unsafe { std::slice::from_raw_parts_mut(self.as_mut_ptr(), self.size) }
}
pub fn len(&self) -> usize {
self.size
}
pub fn is_empty(&self) -> bool {
self.size == 0
}
pub fn as_mut_ptr(&mut self) -> *mut u8 {
unsafe { self.storage.as_mut_ptr().add(self.trim) }
}
pub fn as_ptr(&self) -> *const u8 {
unsafe { self.storage.as_ptr().add(self.trim) }
}
}
impl AsRef<[u8]> for DmaBuffer {
#[inline(always)]
fn as_ref(&self) -> &[u8] {
self.as_bytes()
}
}
impl AsMut<[u8]> for DmaBuffer {
#[inline(always)]
fn as_mut(&mut self) -> &mut [u8] {
self.as_bytes_mut()
}
}