wasmtime/runtime/vm/gc/enabled/
data.rs1use crate::V128;
4use core::mem;
5
6pub trait PodValType<const SIZE: usize>: Copy {
8 fn read_le(le_bytes: &[u8; SIZE]) -> Self;
10
11 fn write_le(&self, into: &mut [u8; SIZE]);
13}
14
15macro_rules! impl_pod_val_type {
16 ( $( $t:ty , )* ) => {
17 $(
18 impl PodValType<{mem::size_of::<$t>()}> for $t {
19 fn read_le(le_bytes: &[u8; mem::size_of::<$t>()]) -> Self {
20 <$t>::from_le_bytes(*le_bytes)
21 }
22 fn write_le(&self, into: &mut [u8; mem::size_of::<$t>()]) {
23 *into = self.to_le_bytes();
24 }
25 }
26 )*
27 };
28}
29
30impl_pod_val_type! {
31 u8,
32 u16,
33 u32,
34 u64,
35 i8,
36 i16,
37 i32,
38 i64,
39}
40
41impl PodValType<{ mem::size_of::<V128>() }> for V128 {
42 fn read_le(le_bytes: &[u8; mem::size_of::<V128>()]) -> Self {
43 u128::from_le_bytes(*le_bytes).into()
44 }
45 fn write_le(&self, into: &mut [u8; mem::size_of::<V128>()]) {
46 *into = self.as_u128().to_le_bytes();
47 }
48}
49
50#[repr(transparent)]
64pub struct VMGcObjectData {
65 data: [u8],
66}
67
68macro_rules! impl_pod_methods {
69 ( $( $T:ty, $read:ident, $write:ident; )* ) => {
70 $(
71 #[doc = stringify!($T)]
73 #[inline]
77 pub fn $read(&self, offset: u32) -> $T
78 {
79 self.read_pod::<{ mem::size_of::<$T>() }, $T>(offset)
80 }
81
82 #[doc = stringify!($T)]
84 #[inline]
88 pub fn $write(&mut self, offset: u32, val: $T)
89 {
90 self.write_pod::<{ mem::size_of::<$T>() }, $T>(offset, val);
91 }
92 )*
93 };
94}
95
96impl<'a> From<&'a [u8]> for &'a VMGcObjectData {
97 #[inline]
98 fn from(data: &'a [u8]) -> Self {
99 &VMGcObjectData::from_slice(data)
100 }
101}
102
103impl<'a> From<&'a mut [u8]> for &'a mut VMGcObjectData {
104 #[inline]
105 fn from(data: &'a mut [u8]) -> Self {
106 VMGcObjectData::from_slice_mut(data)
107 }
108}
109
110impl VMGcObjectData {
111 #[inline]
113 pub fn from_slice(data: &[u8]) -> &Self {
114 unsafe { mem::transmute(data) }
115 }
116
117 #[inline]
119 pub fn from_slice_mut(data: &mut [u8]) -> &mut Self {
120 unsafe { mem::transmute(data) }
121 }
122
123 #[inline]
130 fn read_pod<const N: usize, T>(&self, offset: u32) -> T
131 where
132 T: PodValType<N>,
133 {
134 assert_eq!(N, mem::size_of::<T>());
135 let offset = usize::try_from(offset).unwrap();
136 let end = offset.checked_add(N).unwrap();
137 let bytes = self.data.get(offset..end).expect("out of bounds field");
138 T::read_le(bytes.try_into().unwrap())
139 }
140
141 #[inline]
148 fn write_pod<const N: usize, T>(&mut self, offset: u32, val: T)
149 where
150 T: PodValType<N>,
151 {
152 assert_eq!(N, mem::size_of::<T>());
153 let offset = usize::try_from(offset).unwrap();
154 let end = offset.checked_add(N).unwrap();
155 let into = match self.data.get_mut(offset..end) {
156 Some(into) => into,
157 None => panic!(
158 "out of bounds field! field range = {offset:#x}..{end:#x}; object len = {:#x}",
159 self.data.as_mut().len(),
160 ),
161 };
162 val.write_le(into.try_into().unwrap());
163 }
164
165 #[inline]
172 pub fn slice(&self, offset: u32, len: u32) -> &[u8] {
173 let start = usize::try_from(offset).unwrap();
174 let len = usize::try_from(len).unwrap();
175 let end = start.checked_add(len).unwrap();
176 self.data.get(start..end).expect("out of bounds slice")
177 }
178
179 #[inline]
186 pub fn slice_mut(&mut self, offset: u32, len: u32) -> &mut [u8] {
187 let start = usize::try_from(offset).unwrap();
188 let len = usize::try_from(len).unwrap();
189 let end = start.checked_add(len).unwrap();
190 self.data.get_mut(start..end).expect("out of bounds slice")
191 }
192
193 #[inline]
200 pub fn copy_from_slice(&mut self, offset: u32, src: &[u8]) {
201 let offset = usize::try_from(offset).unwrap();
202 let end = offset.checked_add(src.len()).unwrap();
203 let into = self.data.get_mut(offset..end).expect("out of bounds copy");
204 into.copy_from_slice(src);
205 }
206
207 impl_pod_methods! {
208 u8, read_u8, write_u8;
209 u16, read_u16, write_u16;
210 u32, read_u32, write_u32;
211 u64, read_u64, write_u64;
212 i8, read_i8, write_i8;
213 i16, read_i16, write_i16;
214 i32, read_i32, write_i32;
215 i64, read_i64, write_i64;
216 V128, read_v128, write_v128;
217 }
218}