1use {
2 crate::{
3 data::{Data, DataEntity},
4 decode::{Decode, DecodeError, Decoder},
5 limits::Limits,
6 stack::Stack,
7 store::{Handle, HandlePair, Store, StoreId, UnguardedHandle},
8 trap::Trap,
9 },
10 std::{error::Error, fmt},
11};
12
13#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
15#[repr(transparent)]
16pub struct Mem(pub(crate) Handle<MemEntity>);
17
18impl Mem {
19 pub fn new(store: &mut Store, type_: MemType) -> Self {
25 assert!(type_.is_valid(), "invalid memory type");
26 Self(store.insert_mem(MemEntity::new(type_)))
27 }
28
29 pub fn type_(self, store: &Store) -> MemType {
31 MemType {
32 limits: self.0.as_ref(store).limits(),
33 }
34 }
35
36 pub fn bytes(self, store: &Store) -> &[u8] {
38 self.0.as_ref(store).bytes()
39 }
40
41 pub fn bytes_mut(self, store: &mut Store) -> &mut [u8] {
43 self.0.as_mut(store).bytes_mut()
44 }
45
46 pub fn size(&self, store: &Store) -> u32 {
48 self.0.as_ref(store).size()
49 }
50
51 pub fn grow(self, store: &mut Store, count: u32) -> Result<u32, MemError> {
59 self.0.as_mut(store).grow(count)
60 }
61
62 pub(crate) fn init(
63 self,
64 store: &mut Store,
65 dst_offset: u32,
66 src_data: Data,
67 src_offset: u32,
68 count: u32,
69 ) -> Result<(), Trap> {
70 let (dst_table, src_data) = HandlePair(self.0, src_data.0).as_mut_pair(store);
71 dst_table.init(dst_offset, src_data, src_offset, count)
72 }
73
74 pub(crate) unsafe fn from_unguarded(memory: UnguardedMem, store_id: StoreId) -> Self {
80 Self(Handle::from_unguarded(memory, store_id))
81 }
82
83 pub(crate) fn to_unguarded(self, store_id: StoreId) -> UnguardedMem {
89 self.0.to_unguarded(store_id)
90 }
91}
92
93pub(crate) type UnguardedMem = UnguardedHandle<MemEntity>;
95
96#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
98pub struct MemType {
99 pub limits: Limits,
101}
102
103impl MemType {
104 pub fn is_valid(&self) -> bool {
108 self.limits.is_valid(65_536)
109 }
110
111 pub fn is_subtype_of(self, other: Self) -> bool {
116 self.limits.is_sublimit_of(other.limits)
117 }
118}
119
120impl Decode for MemType {
121 fn decode(decoder: &mut Decoder<'_>) -> Result<Self, DecodeError> {
122 Ok(Self {
123 limits: Limits::decode(decoder)?,
124 })
125 }
126}
127
128#[derive(Clone, Copy, Debug)]
130#[non_exhaustive]
131pub enum MemError {
132 FailedToGrow,
133}
134
135impl fmt::Display for MemError {
136 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137 match self {
138 Self::FailedToGrow => write!(f, "memory failed to grow"),
139 }
140 }
141}
142
143impl Error for MemError {}
144
145#[derive(Debug)]
147pub(crate) struct MemEntity {
148 max: Option<u32>,
149 bytes: Vec<u8>,
150}
151
152impl MemEntity {
153 fn new(type_: MemType) -> Self {
155 Self {
156 max: type_.limits.max,
157 bytes: vec![0; (type_.limits.min as usize).checked_mul(PAGE_SIZE).unwrap()],
158 }
159 }
160
161 fn limits(&self) -> Limits {
163 Limits {
164 min: self.size(),
165 max: self.max,
166 }
167 }
168
169 pub(crate) fn bytes(&self) -> &[u8] {
171 &self.bytes
172 }
173
174 pub(crate) fn bytes_mut(&mut self) -> &mut [u8] {
176 &mut self.bytes
177 }
178
179 pub(crate) fn size(&self) -> u32 {
181 u32::try_from(self.bytes.len() / PAGE_SIZE).unwrap()
182 }
183
184 pub(crate) fn grow(&mut self, count: u32) -> Result<u32, MemError> {
192 let mut stack = Stack::lock();
193 unsafe { self.grow_with_stack(count, &mut stack) }
194 }
195
196 pub(crate) unsafe fn grow_with_stack(
197 &mut self,
198 count: u32,
199 stack: &mut Stack,
200 ) -> Result<u32, MemError> {
201 if count > self.max.unwrap_or(65_536) - self.size() {
202 return Err(MemError::FailedToGrow);
203 }
204 let old_data = self.bytes.as_mut_ptr();
205 let old_size = self.size();
206 let new_size = self.size() + count;
207 self.bytes
208 .resize((new_size as usize).checked_mul(PAGE_SIZE).unwrap(), 0);
209 let new_data = self.bytes.as_mut_ptr();
210
211 let mut ptr = stack.ptr();
217 while ptr != stack.base_ptr() {
218 ptr = *ptr.offset(-3).cast();
219 if *ptr.offset(-2).cast::<*mut u8>() == old_data {
220 *ptr.offset(-2).cast() = new_data;
221 *ptr.offset(-1).cast() = new_size;
222 }
223 }
224
225 Ok(old_size)
226 }
227
228 pub(crate) fn fill(&mut self, idx: u32, val: u8, count: u32) -> Result<(), Trap> {
229 let idx = idx as usize;
230 let count = count as usize;
231 let bytes = self
232 .bytes
233 .get_mut(idx..)
234 .and_then(|bytes| bytes.get_mut(..count))
235 .ok_or(Trap::MemAccessOutOfBounds)?;
236 bytes.fill(val);
237 Ok(())
238 }
239
240 pub(crate) fn copy_within(
241 &mut self,
242 dst_idx: u32,
243 src_idx: u32,
244 count: u32,
245 ) -> Result<(), Trap> {
246 let dst_idx = dst_idx as usize;
247 let src_idx = src_idx as usize;
248 let count = count as usize;
249 if count > self.bytes.len()
250 || dst_idx > self.bytes.len() - count
251 || src_idx > self.bytes.len() - count
252 {
253 return Err(Trap::MemAccessOutOfBounds);
254 }
255 self.bytes.copy_within(src_idx..src_idx + count, dst_idx);
256 Ok(())
257 }
258
259 pub(crate) fn init(
260 &mut self,
261 dst_idx: u32,
262 src_data: &DataEntity,
263 src_idx: u32,
264 count: u32,
265 ) -> Result<(), Trap> {
266 let dst_idx = dst_idx as usize;
267 let src_idx = src_idx as usize;
268 let count = count as usize;
269 let dst_bytes = self
270 .bytes
271 .get_mut(dst_idx..)
272 .and_then(|bytes| bytes.get_mut(..count))
273 .ok_or(Trap::MemAccessOutOfBounds)?;
274 let src_bytes = src_data
275 .bytes()
276 .get(src_idx..)
277 .and_then(|bytes| bytes.get(..count))
278 .ok_or(Trap::MemAccessOutOfBounds)?;
279 dst_bytes.copy_from_slice(src_bytes);
280 Ok(())
281 }
282}
283
284const PAGE_SIZE: usize = 65_536;