use super::*;
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct DataView<T> {
pub data: T,
pub offset: usize,
}
impl<T> DataView<T> {
pub const fn new(data: T) -> Self {
Self { data, offset: 0 }
}
}
impl<T: AsRef<[u8]>> DataView<T> {
#[inline]
pub fn remaining_slice(&self) -> &[u8] {
let data = self.data.as_ref();
unsafe { data.get_unchecked(self.offset.min(data.len())..) }
}
#[inline]
pub fn read<E: Endian>(&mut self) -> Option<E> {
let data = self.data.as_ref();
let total_len = self.offset + size_of::<E>();
if total_len > data.len() {
return None;
}
let num = unsafe { E::__read_at__(data.as_ptr().add(self.offset)) };
self.offset = total_len;
Some(num)
}
#[inline]
pub fn read_slice(&mut self, len: usize) -> Option<&[u8]> {
let total_len = self.offset + len;
let slice = self.data.as_ref().get(self.offset..total_len)?;
self.offset = total_len;
Some(slice)
}
#[inline]
pub fn read_buf<const N: usize>(&mut self) -> Option<[u8; N]> {
let data = self.data.as_ref();
let total_len = self.offset + N;
if total_len > data.len() {
return None;
}
let buf = unsafe { ptr::read(data.as_ptr().add(self.offset) as *const [u8; N]) };
self.offset = total_len;
Some(buf)
}
}
impl<T: AsMut<[u8]>> DataView<T> {
#[inline]
pub fn write<E: Endian>(&mut self, num: E) -> Result<(), ()> {
let data = self.data.as_mut();
let total_len = self.offset + size_of::<E>();
if total_len > data.len() {
return Err(());
}
unsafe { E::__write_at__(num, data.as_mut_ptr().add(self.offset)) };
self.offset = total_len;
Ok(())
}
#[inline]
pub fn write_slice(&mut self, slice: impl AsRef<[u8]>) -> Result<(), ()> {
let src = slice.as_ref();
let data = self.data.as_mut();
let count = src.len();
let total_len = self.offset + count;
if total_len > data.len() {
return Err(());
}
unsafe {
ptr::copy_nonoverlapping(src.as_ptr(), data.as_mut_ptr().add(self.offset), count);
}
self.offset = total_len;
Ok(())
}
}
impl<T> From<T> for DataView<T> {
#[inline]
fn from(data: T) -> Self {
Self::new(data)
}
}