use crate::V128;
use core::mem;
pub trait PodValType<const SIZE: usize>: Copy {
fn read_le(le_bytes: &[u8; SIZE]) -> Self;
fn write_le(&self, into: &mut [u8; SIZE]);
}
macro_rules! impl_pod_val_type {
( $( $t:ty , )* ) => {
$(
impl PodValType<{mem::size_of::<$t>()}> for $t {
fn read_le(le_bytes: &[u8; mem::size_of::<$t>()]) -> Self {
<$t>::from_le_bytes(*le_bytes)
}
fn write_le(&self, into: &mut [u8; mem::size_of::<$t>()]) {
*into = self.to_le_bytes();
}
}
)*
};
}
impl_pod_val_type! {
u8,
u16,
u32,
u64,
i8,
i16,
i32,
i64,
}
impl PodValType<{ mem::size_of::<V128>() }> for V128 {
fn read_le(le_bytes: &[u8; mem::size_of::<V128>()]) -> Self {
u128::from_le_bytes(*le_bytes).into()
}
fn write_le(&self, into: &mut [u8; mem::size_of::<V128>()]) {
*into = self.as_u128().to_le_bytes();
}
}
pub struct VMGcObjectDataMut<'a> {
data: &'a mut [u8],
}
macro_rules! impl_pod_methods {
( $( $t:ty, $read:ident, $write:ident; )* ) => {
$(
#[doc = stringify!($t)]
#[inline]
pub fn $read(&self, offset: u32) -> $t {
self.read_pod::<{ mem::size_of::<$t>() }, $t>(offset)
}
#[doc = stringify!($t)]
#[inline]
pub fn $write(&mut self, offset: u32, val: $t) {
self.write_pod::<{ mem::size_of::<$t>() }, $t>(offset, val);
}
)*
};
}
impl<'a> VMGcObjectDataMut<'a> {
#[inline]
pub fn new(data: &'a mut [u8]) -> Self {
Self { data }
}
#[inline]
fn read_pod<const N: usize, T>(&self, offset: u32) -> T
where
T: PodValType<N>,
{
assert_eq!(N, mem::size_of::<T>());
let offset = usize::try_from(offset).unwrap();
let end = offset.checked_add(N).unwrap();
let bytes = self.data.get(offset..end).expect("out of bounds field");
T::read_le(bytes.try_into().unwrap())
}
#[inline]
fn write_pod<const N: usize, T>(&mut self, offset: u32, val: T)
where
T: PodValType<N>,
{
assert_eq!(N, mem::size_of::<T>());
let offset = usize::try_from(offset).unwrap();
let end = offset.checked_add(N).unwrap();
let into = self.data.get_mut(offset..end).expect("out of bounds field");
val.write_le(into.try_into().unwrap());
}
#[inline]
pub fn copy_from_slice(&mut self, offset: u32, src: &[u8]) {
let offset = usize::try_from(offset).unwrap();
let end = offset.checked_add(src.len()).unwrap();
let into = self.data.get_mut(offset..end).expect("out of bounds copy");
into.copy_from_slice(src);
}
impl_pod_methods! {
u8, read_u8, write_u8;
u16, read_u16, write_u16;
u32, read_u32, write_u32;
u64, read_u64, write_u64;
i8, read_i8, write_i8;
i16, read_i16, write_i16;
i32, read_i32, write_i32;
i64, read_i64, write_i64;
V128, read_v128, write_v128;
}
}