wasmer/entities/memory/
mod.rs

1pub use shared::SharedMemory;
2use wasmer_types::{MemoryError, MemoryType, Pages};
3
4use crate::{
5    AsStoreMut, AsStoreRef, ExportError, Exportable, Extern, StoreMut, StoreRef,
6    vm::{VMExtern, VMExternMemory, VMMemory},
7};
8
9pub(crate) mod buffer;
10pub(crate) mod inner;
11pub(crate) mod location;
12pub(crate) mod shared;
13pub(crate) mod view;
14
15pub(crate) use inner::*;
16pub use view::*;
17
18/// A WebAssembly `memory` instance.
19///
20/// A memory instance is the runtime representation of a linear memory.
21/// It consists of a vector of bytes and an optional maximum size.
22///
23/// The length of the vector always is a multiple of the WebAssembly
24/// page size, which is defined to be the constant 65536 – abbreviated 64Ki.
25/// Like in a memory type, the maximum size in a memory instance is
26/// given in units of this page size.
27///
28/// A memory created by the host or in WebAssembly code will be accessible and
29/// mutable from both host and WebAssembly.
30///
31/// Spec: <https://webassembly.github.io/spec/core/exec/runtime.html#memory-instances>
32#[derive(Debug, Clone, PartialEq, Eq, derive_more::From)]
33#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
34pub struct Memory(pub(crate) BackendMemory);
35
36impl Memory {
37    /// Creates a new host [`Memory`] from the provided [`MemoryType`].
38    ///
39    /// This function will construct the `Memory` using the store
40    /// `BaseTunables`.
41    ///
42    /// # Example
43    ///
44    /// ```
45    /// # use wasmer::{Memory, MemoryType, Pages, Store, Type, Value};
46    /// # let mut store = Store::default();
47    /// #
48    /// let m = Memory::new(&mut store, MemoryType::new(1, None, false)).unwrap();
49    /// ```
50    pub fn new(store: &mut impl AsStoreMut, ty: MemoryType) -> Result<Self, MemoryError> {
51        BackendMemory::new(store, ty).map(Self)
52    }
53
54    /// Create a memory object from an existing memory and attaches it to the store
55    pub fn new_from_existing<IntoVMMemory>(
56        new_store: &mut impl AsStoreMut,
57        memory: IntoVMMemory,
58    ) -> Self
59    where
60        IntoVMMemory: Into<VMMemory>,
61    {
62        Self(BackendMemory::new_from_existing(new_store, memory.into()))
63    }
64
65    /// Returns the [`MemoryType`] of the `Memory`.
66    ///
67    /// # Example
68    ///
69    /// ```
70    /// # use wasmer::{Memory, MemoryType, Pages, Store, Type, Value};
71    /// # let mut store = Store::default();
72    /// #
73    /// let mt = MemoryType::new(1, None, false);
74    /// let m = Memory::new(&mut store, mt).unwrap();
75    ///
76    /// assert_eq!(m.ty(&mut store), mt);
77    /// ```
78    pub fn ty(&self, store: &impl AsStoreRef) -> MemoryType {
79        self.0.ty(store)
80    }
81
82    /// Creates a view into the memory that then allows for
83    /// read and write
84    pub fn view<'a>(&self, store: &'a (impl AsStoreRef + ?Sized)) -> MemoryView<'a> {
85        MemoryView::new(self, store)
86    }
87
88    /// Retrieve the size of the memory in pages.
89    pub fn size(&self, store: &impl AsStoreRef) -> Pages {
90        self.0.size(store)
91    }
92
93    /// Grow memory by the specified amount of WebAssembly [`Pages`] and return
94    /// the previous memory size.
95    ///
96    /// # Example
97    ///
98    /// ```
99    /// # use wasmer::{Memory, MemoryType, Pages, Store, Type, Value, WASM_MAX_PAGES};
100    /// # let mut store = Store::default();
101    /// #
102    /// let m = Memory::new(&mut store, MemoryType::new(1, Some(3), false)).unwrap();
103    /// let p = m.grow(&mut store, 2).unwrap();
104    ///
105    /// assert_eq!(p, Pages(1));
106    /// assert_eq!(m.view(&mut store).size(), Pages(3));
107    /// ```
108    ///
109    /// # Errors
110    ///
111    /// Returns an error if memory can't be grown by the specified amount
112    /// of pages.
113    ///
114    /// ```should_panic
115    /// # use wasmer::{Memory, MemoryType, Pages, Store, Type, Value, WASM_MAX_PAGES};
116    /// # use wasmer::FunctionEnv;
117    /// # let mut store = Store::default();
118    /// # let env = FunctionEnv::new(&mut store, ());
119    /// #
120    /// let m = Memory::new(&mut store, MemoryType::new(1, Some(1), false)).unwrap();
121    ///
122    /// // This results in an error: `MemoryError::CouldNotGrow`.
123    /// let s = m.grow(&mut store, 1).unwrap();
124    /// ```
125    pub fn grow<IntoPages>(
126        &self,
127        store: &mut impl AsStoreMut,
128        delta: IntoPages,
129    ) -> Result<Pages, MemoryError>
130    where
131        IntoPages: Into<Pages>,
132    {
133        self.0.grow(store, delta)
134    }
135
136    /// Grows the memory to at least a minimum size.
137    ///
138    /// # Note
139    ///
140    /// If the memory is already big enough for the min size this function does nothing.
141    pub fn grow_at_least(
142        &self,
143        store: &mut impl AsStoreMut,
144        min_size: u64,
145    ) -> Result<(), MemoryError> {
146        self.0.grow_at_least(store, min_size)
147    }
148
149    /// Resets the memory back to zero length
150    pub fn reset(&self, store: &mut impl AsStoreMut) -> Result<(), MemoryError> {
151        self.0.reset(store)
152    }
153
154    /// Attempts to duplicate this memory (if its clonable) in a new store
155    /// (copied memory)
156    pub fn copy_to_store(
157        &self,
158        store: &impl AsStoreRef,
159        new_store: &mut impl AsStoreMut,
160    ) -> Result<Self, MemoryError> {
161        self.0.copy_to_store(store, new_store).map(Self)
162    }
163
164    pub(crate) fn from_vm_extern(store: &mut impl AsStoreMut, vm_extern: VMExternMemory) -> Self {
165        Self(BackendMemory::from_vm_extern(store, vm_extern))
166    }
167
168    /// Checks whether this `Memory` can be used with the given context.
169    pub fn is_from_store(&self, store: &impl AsStoreRef) -> bool {
170        self.0.is_from_store(store)
171    }
172
173    /// Attempt to create a new reference to the underlying memory; this new reference can then be
174    /// used within a different store (from the same implementer).
175    ///
176    /// # Errors
177    ///
178    /// Fails if the underlying memory is not clonable.
179    pub fn try_clone(&self, store: &impl AsStoreRef) -> Result<VMMemory, MemoryError> {
180        self.0.try_clone(store)
181    }
182
183    /// Attempts to clone this memory (if its clonable) in a new store
184    /// (cloned memory will be shared between those that clone it)
185    pub fn share_in_store(
186        &self,
187        store: &impl AsStoreRef,
188        new_store: &mut impl AsStoreMut,
189    ) -> Result<Self, MemoryError> {
190        self.0.share_in_store(store, new_store).map(Self)
191    }
192
193    /// Get a [`SharedMemory`].
194    ///
195    /// Only returns `Some(_)` if the memory is shared, and if the target
196    /// backend supports shared memory operations.
197    ///
198    /// See [`SharedMemory`] and its methods for more information.
199    pub fn as_shared(&self, store: &impl AsStoreRef) -> Option<SharedMemory> {
200        self.0.as_shared(store)
201    }
202
203    /// Create a [`VMExtern`] from self.
204    pub(crate) fn to_vm_extern(&self) -> VMExtern {
205        self.0.to_vm_extern()
206    }
207}
208
209impl<'a> Exportable<'a> for Memory {
210    fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> {
211        match _extern {
212            Extern::Memory(memory) => Ok(memory),
213            _ => Err(ExportError::IncompatibleType),
214        }
215    }
216}