use std::ptr;
use aligned_alloc::{aligned_alloc, aligned_free};
#[derive(Debug)]
pub struct PosixDmaBuffer {
data: ptr::NonNull<u8>,
trim: usize,
size: usize,
}
impl PosixDmaBuffer {
pub(crate) fn new(size: usize) -> Option<PosixDmaBuffer> {
let data = aligned_alloc(size, 4 << 10) as *mut u8;
let data = ptr::NonNull::new(data)?;
Some(PosixDmaBuffer {
data,
size,
trim: 0,
})
}
pub(crate) fn trim_to_size(&mut self, newsize: usize) {
assert!(newsize <= self.size);
self.size = newsize;
}
pub(crate) fn trim_front(&mut self, trim: usize) {
assert!(trim <= self.size);
self.trim += trim;
self.size -= trim;
}
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 as_mut_ptr(&mut self) -> *mut u8 {
unsafe { self.data.as_ptr().add(self.trim) }
}
pub fn as_ptr(&self) -> *const u8 {
unsafe { self.data.as_ptr().add(self.trim) }
}
pub fn read_at(&self, offset: usize, dst: &mut [u8]) -> usize {
if offset > self.size {
return 0;
}
let len = std::cmp::min(dst.len(), self.size - offset);
let me = &self.as_bytes()[offset..offset + len];
dst[0..len].copy_from_slice(me);
len
}
pub fn write_at(&mut self, offset: usize, src: &[u8]) -> usize {
if offset > self.size {
return 0;
}
let len = std::cmp::min(src.len(), self.size - offset);
let me = &mut self.as_bytes_mut()[offset..offset + len];
me.copy_from_slice(&src[0..len]);
len
}
pub fn memset(&mut self, value: u8) {
unsafe { std::ptr::write_bytes(self.as_mut_ptr(), value, self.size) }
}
}
impl Drop for PosixDmaBuffer {
fn drop(&mut self) {
unsafe {
aligned_free(self.data.as_ptr() as *mut ());
}
}
}