1 use crate::store::StoreOpaque; 2 use crate::{AsContext, Engine, ExternType, Func, Memory, SharedMemory}; 3 4 mod global; 5 mod table; 6 mod tag; 7 8 pub use global::Global; 9 pub use table::Table; 10 pub use tag::Tag; 11 12 // Externals 13 14 /// An external item to a WebAssembly module, or a list of what can possibly be 15 /// exported from a wasm module. 16 /// 17 /// This is both returned from [`Instance::exports`](crate::Instance::exports) 18 /// as well as required by [`Instance::new`](crate::Instance::new). In other 19 /// words, this is the type of extracted values from an instantiated module, and 20 /// it's also used to provide imported values when instantiating a module. 21 #[derive(Clone, Debug)] 22 pub enum Extern { 23 /// A WebAssembly `func` which can be called. 24 Func(Func), 25 /// A WebAssembly `global` which acts like a `Cell<T>` of sorts, supporting 26 /// `get` and `set` operations. 27 Global(Global), 28 /// A WebAssembly `table` which is an array of `Val` reference types. 29 Table(Table), 30 /// A WebAssembly linear memory. 31 Memory(Memory), 32 /// A WebAssembly shared memory; these are handled separately from 33 /// [`Memory`]. 34 SharedMemory(SharedMemory), 35 /// A WebAssembly exception or control tag which can be referenced 36 /// when raising an exception or stack switching. 37 Tag(Tag), 38 } 39 40 impl Extern { 41 /// Returns the underlying `Func`, if this external is a function. 42 /// 43 /// Returns `None` if this is not a function. 44 #[inline] into_func(self) -> Option<Func>45 pub fn into_func(self) -> Option<Func> { 46 match self { 47 Extern::Func(func) => Some(func), 48 _ => None, 49 } 50 } 51 52 /// Returns the underlying `Global`, if this external is a global. 53 /// 54 /// Returns `None` if this is not a global. 55 #[inline] into_global(self) -> Option<Global>56 pub fn into_global(self) -> Option<Global> { 57 match self { 58 Extern::Global(global) => Some(global), 59 _ => None, 60 } 61 } 62 63 /// Returns the underlying `Table`, if this external is a table. 64 /// 65 /// Returns `None` if this is not a table. 66 #[inline] into_table(self) -> Option<Table>67 pub fn into_table(self) -> Option<Table> { 68 match self { 69 Extern::Table(table) => Some(table), 70 _ => None, 71 } 72 } 73 74 /// Returns the underlying `Memory`, if this external is a memory. 75 /// 76 /// Returns `None` if this is not a memory. 77 #[inline] into_memory(self) -> Option<Memory>78 pub fn into_memory(self) -> Option<Memory> { 79 match self { 80 Extern::Memory(memory) => Some(memory), 81 _ => None, 82 } 83 } 84 85 /// Returns the underlying `SharedMemory`, if this external is a shared 86 /// memory. 87 /// 88 /// Returns `None` if this is not a shared memory. 89 #[inline] into_shared_memory(self) -> Option<SharedMemory>90 pub fn into_shared_memory(self) -> Option<SharedMemory> { 91 match self { 92 Extern::SharedMemory(memory) => Some(memory), 93 _ => None, 94 } 95 } 96 97 /// Returns the underlying `Tag`, if this external is a tag. 98 /// 99 /// Returns `None` if this is not a tag. 100 #[inline] into_tag(self) -> Option<Tag>101 pub fn into_tag(self) -> Option<Tag> { 102 match self { 103 Extern::Tag(tag) => Some(tag), 104 _ => None, 105 } 106 } 107 108 /// Returns the type associated with this `Extern`. 109 /// 110 /// The `store` argument provided must own this `Extern` and is used to look 111 /// up type information. 112 /// 113 /// # Panics 114 /// 115 /// Panics if this item does not belong to the `store` provided. ty(&self, store: impl AsContext) -> ExternType116 pub fn ty(&self, store: impl AsContext) -> ExternType { 117 let store = store.as_context(); 118 match self { 119 Extern::Func(ft) => ExternType::Func(ft.ty(store)), 120 Extern::Memory(ft) => ExternType::Memory(ft.ty(store)), 121 Extern::SharedMemory(ft) => ExternType::Memory(ft.ty()), 122 Extern::Table(tt) => ExternType::Table(tt.ty(store)), 123 Extern::Global(gt) => ExternType::Global(gt.ty(store)), 124 Extern::Tag(tt) => ExternType::Tag(tt.ty(store)), 125 } 126 } 127 from_wasmtime_export( wasmtime_export: crate::runtime::vm::Export, engine: &Engine, ) -> Extern128 pub(crate) fn from_wasmtime_export( 129 wasmtime_export: crate::runtime::vm::Export, 130 engine: &Engine, 131 ) -> Extern { 132 match wasmtime_export { 133 crate::runtime::vm::Export::Function(f) => Extern::Func(f), 134 crate::runtime::vm::Export::Memory(m) => Extern::Memory(m), 135 crate::runtime::vm::Export::SharedMemory(m, _) => { 136 Extern::SharedMemory(crate::SharedMemory::from_raw(m, engine.clone())) 137 } 138 crate::runtime::vm::Export::Global(g) => Extern::Global(g), 139 crate::runtime::vm::Export::Table(t) => Extern::Table(t), 140 crate::runtime::vm::Export::Tag(t) => Extern::Tag(t), 141 } 142 } 143 comes_from_same_store(&self, store: &StoreOpaque) -> bool144 pub(crate) fn comes_from_same_store(&self, store: &StoreOpaque) -> bool { 145 match self { 146 Extern::Func(f) => f.comes_from_same_store(store), 147 Extern::Global(g) => g.comes_from_same_store(store), 148 Extern::Memory(m) => m.comes_from_same_store(store), 149 Extern::SharedMemory(m) => Engine::same(m.engine(), store.engine()), 150 Extern::Table(t) => t.comes_from_same_store(store), 151 Extern::Tag(t) => t.comes_from_same_store(store), 152 } 153 } 154 } 155 156 impl From<Func> for Extern { from(r: Func) -> Self157 fn from(r: Func) -> Self { 158 Extern::Func(r) 159 } 160 } 161 162 impl From<Global> for Extern { from(r: Global) -> Self163 fn from(r: Global) -> Self { 164 Extern::Global(r) 165 } 166 } 167 168 impl From<Memory> for Extern { from(r: Memory) -> Self169 fn from(r: Memory) -> Self { 170 Extern::Memory(r) 171 } 172 } 173 174 impl From<SharedMemory> for Extern { from(r: SharedMemory) -> Self175 fn from(r: SharedMemory) -> Self { 176 Extern::SharedMemory(r) 177 } 178 } 179 180 impl From<Table> for Extern { from(r: Table) -> Self181 fn from(r: Table) -> Self { 182 Extern::Table(r) 183 } 184 } 185 186 impl From<Tag> for Extern { from(t: Tag) -> Self187 fn from(t: Tag) -> Self { 188 Extern::Tag(t) 189 } 190 } 191 192 // Exports 193 194 /// An exported WebAssembly value. 195 /// 196 /// This type is primarily accessed from the 197 /// [`Instance::exports`](crate::Instance::exports) accessor and describes what 198 /// names and items are exported from a wasm instance. 199 #[derive(Clone)] 200 pub struct Export<'instance> { 201 /// The name of the export. 202 name: &'instance str, 203 204 /// The definition of the export. 205 definition: Extern, 206 } 207 208 impl<'instance> Export<'instance> { 209 /// Creates a new export which is exported with the given `name` and has the 210 /// given `definition`. new(name: &'instance str, definition: Extern) -> Export<'instance>211 pub(crate) fn new(name: &'instance str, definition: Extern) -> Export<'instance> { 212 Export { name, definition } 213 } 214 215 /// Returns the name by which this export is known. name(&self) -> &'instance str216 pub fn name(&self) -> &'instance str { 217 self.name 218 } 219 220 /// Return the `ExternType` of this export. 221 /// 222 /// # Panics 223 /// 224 /// Panics if `store` does not own this `Extern`. ty(&self, store: impl AsContext) -> ExternType225 pub fn ty(&self, store: impl AsContext) -> ExternType { 226 self.definition.ty(store) 227 } 228 229 /// Consume this `Export` and return the contained `Extern`. into_extern(self) -> Extern230 pub fn into_extern(self) -> Extern { 231 self.definition 232 } 233 234 /// Consume this `Export` and return the contained `Func`, if it's a function, 235 /// or `None` otherwise. into_func(self) -> Option<Func>236 pub fn into_func(self) -> Option<Func> { 237 self.definition.into_func() 238 } 239 240 /// Consume this `Export` and return the contained `Table`, if it's a table, 241 /// or `None` otherwise. into_table(self) -> Option<Table>242 pub fn into_table(self) -> Option<Table> { 243 self.definition.into_table() 244 } 245 246 /// Consume this `Export` and return the contained `Memory`, if it's a memory, 247 /// or `None` otherwise. into_memory(self) -> Option<Memory>248 pub fn into_memory(self) -> Option<Memory> { 249 self.definition.into_memory() 250 } 251 252 /// Consume this `Export` and return the contained `SharedMemory`, if it's 253 /// a shared memory, or `None` otherwise. into_shared_memory(self) -> Option<SharedMemory>254 pub fn into_shared_memory(self) -> Option<SharedMemory> { 255 self.definition.into_shared_memory() 256 } 257 258 /// Consume this `Export` and return the contained `Global`, if it's a global, 259 /// or `None` otherwise. into_global(self) -> Option<Global>260 pub fn into_global(self) -> Option<Global> { 261 self.definition.into_global() 262 } 263 264 /// Consume this `Export` and return the contained `Tag`, if it's a tag, 265 /// or `None` otherwise. into_tag(self) -> Option<Tag>266 pub fn into_tag(self) -> Option<Tag> { 267 self.definition.into_tag() 268 } 269 } 270