pub trait BlockContainer {
type Data;
type ShareableData;
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
}
pub trait ReadBytes: BlockContainer {
fn get_slice_at(&self, offset: usize, size: usize) -> Option<&[u8]>;
#[inline]
fn get_slice(&self, size: usize) -> Option<&[u8]> {
self.get_slice_at(0, size)
}
#[inline]
fn get_value<T: ContainerValue>(&self, offset: usize) -> Option<&T> {
self.get_slice_at(offset, std::mem::size_of::<T>()).map(|slice| {
let ptr = slice.as_ptr() as *const T;
unsafe { &*ptr }
})
}
}
pub trait CopyBytes: BlockContainer {
fn copy_bytes_at(&self, offset: usize, dst: &mut [u8]);
fn copy_bytes(&self, dst: &mut [u8]) {
self.copy_bytes_at(0, dst)
}
}
pub trait ContainerValue: private::Sealed {}
mod private {
pub trait Sealed {}
}
macro_rules! impl_container_value {
($($type:ty),*) => {
$(
impl private::Sealed for $type {}
impl ContainerValue for $type {}
)*
};
}
impl_container_value!(u8, u16, u32, u64, i64, f64);
pub trait WriteBytes {
fn get_slice_mut_at(&mut self, offset: usize, size: usize) -> Option<&mut [u8]>;
#[inline]
fn get_slice_mut(&mut self, size: usize) -> Option<&mut [u8]> {
self.get_slice_mut_at(0, size)
}
#[inline]
fn copy_from_slice_at(&mut self, offset: usize, bytes: &[u8]) {
if let Some(slice) = self.get_slice_mut_at(offset, bytes.len()) {
slice.copy_from_slice(bytes);
}
}
#[inline]
fn copy_from_slice(&mut self, bytes: &[u8]) {
self.copy_from_slice_at(0, bytes);
}
#[inline]
fn get_value_mut<T: ContainerValue>(&mut self, offset: usize) -> Option<&mut T> {
self.get_slice_mut_at(offset, std::mem::size_of::<T>()).map(|slice| {
let ptr = slice.as_mut_ptr() as *mut T;
unsafe { &mut *ptr }
})
}
#[inline]
fn set_value<T: ContainerValue>(&mut self, offset: usize, value: T) {
if let Some(value_ref) = self.get_value_mut(offset) {
*value_ref = value;
}
}
}
impl BlockContainer for Vec<u8> {
type Data = Self;
type ShareableData = ();
#[inline]
fn len(&self) -> usize {
self.as_slice().len()
}
}
impl ReadBytes for Vec<u8> {
#[inline]
fn get_slice_at(&self, offset: usize, size: usize) -> Option<&[u8]> {
self.as_slice().get_slice_at(offset, size)
}
}
impl CopyBytes for Vec<u8> {
#[inline]
fn copy_bytes_at(&self, offset: usize, dst: &mut [u8]) {
if let Some(slice) = self.as_slice().get_slice_at(offset, dst.len()) {
dst.copy_from_slice(slice);
}
}
}
impl BlockContainer for [u8] {
type Data = ();
type ShareableData = ();
#[inline]
fn len(&self) -> usize {
<[u8]>::len(self)
}
}
impl ReadBytes for [u8] {
#[inline]
fn get_slice_at(&self, offset: usize, size: usize) -> Option<&[u8]> {
let upper_bound = offset.checked_add(size)?;
if offset >= self.len() || upper_bound > self.len() {
return None;
}
Some(&self[offset..upper_bound])
}
}
impl<const N: usize> BlockContainer for [u8; N] {
type Data = Self;
type ShareableData = ();
#[inline]
fn len(&self) -> usize {
self.as_slice().len()
}
}
impl<const N: usize> ReadBytes for [u8; N] {
#[inline]
fn get_slice_at(&self, offset: usize, size: usize) -> Option<&[u8]> {
self.as_slice().get_slice_at(offset, size)
}
}
impl<const N: usize> WriteBytes for [u8; N] {
#[inline]
fn get_slice_mut_at(&mut self, offset: usize, size: usize) -> Option<&mut [u8]> {
if offset >= self.len() {
return None;
}
let upper_bound = offset.checked_add(size)?;
if upper_bound > self.len() {
return None;
}
Some(&mut self[offset..upper_bound])
}
}