Backend storage for a linear memory This is a low-level trait that abstracts over the actual storage mechanism for linear memory. This will probably change in the future to allow more efficient implementations. See [`MemoryBackend`] for a higher-level interface to configuring memory storage.
| 25 | /// This will probably change in the future to allow more efficient implementations. |
| 26 | /// See [`MemoryBackend`] for a higher-level interface to configuring memory storage. |
| 27 | pub trait LinearMemory { |
| 28 | /// Returns the current memory length in bytes. |
| 29 | fn len(&self) -> usize; |
| 30 | |
| 31 | /// Returns true if the memory is empty. |
| 32 | fn is_empty(&self) -> bool { |
| 33 | self.len() == 0 |
| 34 | } |
| 35 | |
| 36 | /// Grows the memory to `new_len` bytes. |
| 37 | /// |
| 38 | /// The runtime only calls this with lengths that are exact multiples of the Wasm page size for |
| 39 | /// the owning memory. |
| 40 | fn grow_to(&mut self, new_len: usize) -> core::result::Result<(), crate::Trap>; |
| 41 | |
| 42 | /// Reads up to `dst.len()` bytes starting at `addr` and returns the number of bytes read. |
| 43 | /// |
| 44 | /// Backends may return fewer bytes than requested even when more data is available. This lets |
| 45 | /// non-contiguous backends stop at a natural boundary such as the end of a chunk. |
| 46 | fn read(&self, addr: usize, dst: &mut [u8]) -> usize; |
| 47 | |
| 48 | /// Writes up to `src.len()` bytes starting at `addr` and returns the number of bytes written. |
| 49 | /// |
| 50 | /// Backends may return fewer bytes than requested even when more space is available. This lets |
| 51 | /// non-contiguous backends stop at a natural boundary such as the end of a chunk. |
| 52 | fn write(&mut self, addr: usize, src: &[u8]) -> usize; |
| 53 | |
| 54 | /// Writes all bytes in `src` starting at `addr`, or returns `None` if any byte could not be written. |
| 55 | fn write_all(&mut self, addr: usize, src: &[u8]) -> Option<()> { |
| 56 | let end = addr.checked_add(src.len())?; |
| 57 | if end > self.len() { |
| 58 | return None; |
| 59 | } |
| 60 | |
| 61 | let mut offset = 0; |
| 62 | while offset < src.len() { |
| 63 | let written = self.write(addr + offset, &src[offset..]); |
| 64 | if written == 0 { |
| 65 | return None; |
| 66 | } |
| 67 | offset += written; |
| 68 | } |
| 69 | |
| 70 | Some(()) |
| 71 | } |
| 72 | |
| 73 | /// Fills the range `[addr, addr + len)` with `val`. |
| 74 | fn fill(&mut self, addr: usize, len: usize, val: u8) -> Option<()> { |
| 75 | let end = addr.checked_add(len)?; |
| 76 | if end > self.len() { |
| 77 | return None; |
| 78 | } |
| 79 | |
| 80 | let mut offset = 0; |
| 81 | while offset < len { |
| 82 | let chunk_len = min(len - offset, 1024); |
| 83 | let chunk = vec![val; chunk_len]; |
| 84 | self.write_all(addr + offset, &chunk)?; |
no outgoing calls
no test coverage detected