use std::marker::PhantomData;
use std::mem::size_of;
use std::ptr::copy_nonoverlapping;
use std::slice;
use crate::sys::{align, Bytes};
use super::Error;
#[derive(Debug, Eq, PartialEq)]
pub struct Buffer<'a> {
ptr: *mut u8,
cur: *mut u8,
len: usize,
pha: PhantomData<&'a ()>,
}
impl<'a> Buffer<'a> {
pub fn new(buf: &mut [u8]) -> Self {
Self {
ptr: buf.as_mut_ptr(),
cur: buf.as_mut_ptr(),
len: buf.len(),
pha: PhantomData
}
}
pub fn write<T: Bytes>(&mut self, item: &T) -> Result<(), Error> {
unsafe {
let size = size_of::<T>();
let dst = self.place(size)?.0;
let src = item as *const _ as *const u8;
copy_nonoverlapping(src, dst, size);
Ok(())
}
}
pub fn copy(&mut self, bytes: &[u8]) -> Result<(), Error> {
unsafe {
let size = bytes.len();
let dst = self.place(size)?.0;
copy_nonoverlapping(bytes.as_ptr(), dst, size);
Ok(())
}
}
pub fn buffer(&mut self, size: usize) -> Result<&mut [u8], Error> {
unsafe {
let (ptr, size) = self.place(size)?;
Ok(slice::from_raw_parts_mut(ptr, size))
}
}
pub fn bytes(&self) -> &'a [u8] {
unsafe {
let x = self.cur as usize;
let y = self.ptr as usize;
slice::from_raw_parts(self.ptr, x - y)
}
}
fn place(&mut self, size: usize) -> Result<(*mut u8, usize), Error> {
unsafe {
let size = align(size);
self.len = self.len.checked_sub(size).ok_or(Error::Overrun)?;
let ptr = self.cur as *mut u8;
self.cur = self.cur.add(size);
Ok((ptr, size))
}
}
}