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
50pub struct VMGcObjectDataMut<'a> {
64 data: &'a mut [u8],
65}
66
67macro_rules! impl_pod_methods {
68 ( $( $t:ty, $read:ident, $write:ident; )* ) => {
69 $(
70 #[doc = stringify!($t)]
72 #[inline]
76 pub fn $read(&self, offset: u32) -> $t {
77 self.read_pod::<{ mem::size_of::<$t>() }, $t>(offset)
78 }
79
80 #[doc = stringify!($t)]
82 #[inline]
86 pub fn $write(&mut self, offset: u32, val: $t) {
87 self.write_pod::<{ mem::size_of::<$t>() }, $t>(offset, val);
88 }
89 )*
90 };
91}
92
93impl<'a> VMGcObjectDataMut<'a> {
94 #[inline]
96 pub fn new(data: &'a mut [u8]) -> Self {
97 Self { data }
98 }
99
100 #[inline]
107 fn read_pod<const N: usize, T>(&self, offset: u32) -> T
108 where
109 T: PodValType<N>,
110 {
111 assert_eq!(N, mem::size_of::<T>());
112 let offset = usize::try_from(offset).unwrap();
113 let end = offset.checked_add(N).unwrap();
114 let bytes = self.data.get(offset..end).expect("out of bounds field");
115 T::read_le(bytes.try_into().unwrap())
116 }
117
118 #[inline]
125 fn write_pod<const N: usize, T>(&mut self, offset: u32, val: T)
126 where
127 T: PodValType<N>,
128 {
129 assert_eq!(N, mem::size_of::<T>());
130 let offset = usize::try_from(offset).unwrap();
131 let end = offset.checked_add(N).unwrap();
132 let into = match self.data.get_mut(offset..end) {
133 Some(into) => into,
134 None => panic!(
135 "out of bounds field! field range = {offset:#x}..{end:#x}; object len = {:#x}",
136 self.data.len(),
137 ),
138 };
139 val.write_le(into.try_into().unwrap());
140 }
141
142 #[inline]
146 pub fn slice(&self, offset: u32, len: u32) -> &[u8] {
147 let start = usize::try_from(offset).unwrap();
148 let len = usize::try_from(len).unwrap();
149 let end = start.checked_add(len).unwrap();
150 self.data.get(start..end).expect("out of bounds slice")
151 }
152
153 #[inline]
157 pub fn slice_mut(&mut self, offset: u32, len: u32) -> &mut [u8] {
158 let start = usize::try_from(offset).unwrap();
159 let len = usize::try_from(len).unwrap();
160 let end = start.checked_add(len).unwrap();
161 self.data.get_mut(start..end).expect("out of bounds slice")
162 }
163
164 #[inline]
168 pub fn copy_from_slice(&mut self, offset: u32, src: &[u8]) {
169 let offset = usize::try_from(offset).unwrap();
170 let end = offset.checked_add(src.len()).unwrap();
171 let into = self.data.get_mut(offset..end).expect("out of bounds copy");
172 into.copy_from_slice(src);
173 }
174
175 impl_pod_methods! {
176 u8, read_u8, write_u8;
177 u16, read_u16, write_u16;
178 u32, read_u32, write_u32;
179 u64, read_u64, write_u64;
180 i8, read_i8, write_i8;
181 i16, read_i16, write_i16;
182 i32, read_i32, write_i32;
183 i64, read_i64, write_i64;
184 V128, read_v128, write_v128;
185 }
186}