wasmtime/
types.rs

1use std::fmt;
2use wasmtime_environ::{EntityType, Global, Memory, ModuleTypes, Table, WasmFuncType, WasmType};
3
4pub(crate) mod matching;
5
6// Type Representations
7
8// Type attributes
9
10/// Indicator of whether a global is mutable or not
11#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
12pub enum Mutability {
13    /// The global is constant and its value does not change
14    Const,
15    /// The value of the global can change over time
16    Var,
17}
18
19// Value Types
20
21/// A list of all possible value types in WebAssembly.
22#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
23pub enum ValType {
24    // NB: the ordering here is intended to match the ordering in
25    // `wasmtime_types::WasmType` to help improve codegen when converting.
26    /// Signed 32 bit integer.
27    I32,
28    /// Signed 64 bit integer.
29    I64,
30    /// Floating point 32 bit integer.
31    F32,
32    /// Floating point 64 bit integer.
33    F64,
34    /// A 128 bit number.
35    V128,
36    /// A reference to a Wasm function.
37    FuncRef,
38    /// A reference to opaque data in the Wasm instance.
39    ExternRef,
40}
41
42impl fmt::Display for ValType {
43    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
44        match self {
45            ValType::I32 => write!(f, "i32"),
46            ValType::I64 => write!(f, "i64"),
47            ValType::F32 => write!(f, "f32"),
48            ValType::F64 => write!(f, "f64"),
49            ValType::V128 => write!(f, "v128"),
50            ValType::ExternRef => write!(f, "externref"),
51            ValType::FuncRef => write!(f, "funcref"),
52        }
53    }
54}
55
56impl ValType {
57    /// Returns true if `ValType` matches any of the numeric types. (e.g. `I32`,
58    /// `I64`, `F32`, `F64`).
59    pub fn is_num(&self) -> bool {
60        match self {
61            ValType::I32 | ValType::I64 | ValType::F32 | ValType::F64 => true,
62            _ => false,
63        }
64    }
65
66    /// Returns true if `ValType` matches either of the reference types.
67    pub fn is_ref(&self) -> bool {
68        match self {
69            ValType::ExternRef | ValType::FuncRef => true,
70            _ => false,
71        }
72    }
73
74    pub(crate) fn to_wasm_type(&self) -> WasmType {
75        match self {
76            Self::I32 => WasmType::I32,
77            Self::I64 => WasmType::I64,
78            Self::F32 => WasmType::F32,
79            Self::F64 => WasmType::F64,
80            Self::V128 => WasmType::V128,
81            Self::FuncRef => WasmType::FuncRef,
82            Self::ExternRef => WasmType::ExternRef,
83        }
84    }
85
86    pub(crate) fn from_wasm_type(ty: &WasmType) -> Self {
87        match ty {
88            WasmType::I32 => Self::I32,
89            WasmType::I64 => Self::I64,
90            WasmType::F32 => Self::F32,
91            WasmType::F64 => Self::F64,
92            WasmType::V128 => Self::V128,
93            WasmType::FuncRef => Self::FuncRef,
94            WasmType::ExternRef => Self::ExternRef,
95        }
96    }
97}
98
99// External Types
100
101/// A list of all possible types which can be externally referenced from a
102/// WebAssembly module.
103///
104/// This list can be found in [`ImportType`] or [`ExportType`], so these types
105/// can either be imported or exported.
106#[derive(Debug, Clone)]
107pub enum ExternType {
108    /// This external type is the type of a WebAssembly function.
109    Func(FuncType),
110    /// This external type is the type of a WebAssembly global.
111    Global(GlobalType),
112    /// This external type is the type of a WebAssembly table.
113    Table(TableType),
114    /// This external type is the type of a WebAssembly memory.
115    Memory(MemoryType),
116}
117
118macro_rules! accessors {
119    ($(($variant:ident($ty:ty) $get:ident $unwrap:ident))*) => ($(
120        /// Attempt to return the underlying type of this external type,
121        /// returning `None` if it is a different type.
122        pub fn $get(&self) -> Option<&$ty> {
123            if let ExternType::$variant(e) = self {
124                Some(e)
125            } else {
126                None
127            }
128        }
129
130        /// Returns the underlying descriptor of this [`ExternType`], panicking
131        /// if it is a different type.
132        ///
133        /// # Panics
134        ///
135        /// Panics if `self` is not of the right type.
136        pub fn $unwrap(&self) -> &$ty {
137            self.$get().expect(concat!("expected ", stringify!($ty)))
138        }
139    )*)
140}
141
142impl ExternType {
143    accessors! {
144        (Func(FuncType) func unwrap_func)
145        (Global(GlobalType) global unwrap_global)
146        (Table(TableType) table unwrap_table)
147        (Memory(MemoryType) memory unwrap_memory)
148    }
149
150    pub(crate) fn from_wasmtime(types: &ModuleTypes, ty: &EntityType) -> ExternType {
151        match ty {
152            EntityType::Function(idx) => FuncType::from_wasm_func_type(types[*idx].clone()).into(),
153            EntityType::Global(ty) => GlobalType::from_wasmtime_global(ty).into(),
154            EntityType::Memory(ty) => MemoryType::from_wasmtime_memory(ty).into(),
155            EntityType::Table(ty) => TableType::from_wasmtime_table(ty).into(),
156            EntityType::Tag(_) => unimplemented!("wasm tag support"),
157        }
158    }
159}
160
161impl From<FuncType> for ExternType {
162    fn from(ty: FuncType) -> ExternType {
163        ExternType::Func(ty)
164    }
165}
166
167impl From<GlobalType> for ExternType {
168    fn from(ty: GlobalType) -> ExternType {
169        ExternType::Global(ty)
170    }
171}
172
173impl From<MemoryType> for ExternType {
174    fn from(ty: MemoryType) -> ExternType {
175        ExternType::Memory(ty)
176    }
177}
178
179impl From<TableType> for ExternType {
180    fn from(ty: TableType) -> ExternType {
181        ExternType::Table(ty)
182    }
183}
184
185/// A descriptor for a function in a WebAssembly module.
186///
187/// WebAssembly functions can have 0 or more parameters and results.
188#[derive(Debug, Clone, Hash, Eq, PartialEq)]
189pub struct FuncType {
190    sig: WasmFuncType,
191}
192
193impl FuncType {
194    /// Creates a new function descriptor from the given parameters and results.
195    ///
196    /// The function descriptor returned will represent a function which takes
197    /// `params` as arguments and returns `results` when it is finished.
198    pub fn new(
199        params: impl IntoIterator<Item = ValType>,
200        results: impl IntoIterator<Item = ValType>,
201    ) -> FuncType {
202        FuncType {
203            sig: WasmFuncType::new(
204                params.into_iter().map(|t| t.to_wasm_type()).collect(),
205                results.into_iter().map(|t| t.to_wasm_type()).collect(),
206            ),
207        }
208    }
209
210    /// Returns the list of parameter types for this function.
211    #[inline]
212    pub fn params(&self) -> impl ExactSizeIterator<Item = ValType> + '_ {
213        self.sig.params().iter().map(ValType::from_wasm_type)
214    }
215
216    /// Returns the list of result types for this function.
217    #[inline]
218    pub fn results(&self) -> impl ExactSizeIterator<Item = ValType> + '_ {
219        self.sig.returns().iter().map(ValType::from_wasm_type)
220    }
221
222    pub(crate) fn as_wasm_func_type(&self) -> &WasmFuncType {
223        &self.sig
224    }
225
226    pub(crate) fn from_wasm_func_type(sig: WasmFuncType) -> FuncType {
227        Self { sig }
228    }
229}
230
231// Global Types
232
233/// A WebAssembly global descriptor.
234///
235/// This type describes an instance of a global in a WebAssembly module. Globals
236/// are local to an [`Instance`](crate::Instance) and are either immutable or
237/// mutable.
238#[derive(Debug, Clone, Hash, Eq, PartialEq)]
239pub struct GlobalType {
240    content: ValType,
241    mutability: Mutability,
242}
243
244impl GlobalType {
245    /// Creates a new global descriptor of the specified `content` type and
246    /// whether or not it's mutable.
247    pub fn new(content: ValType, mutability: Mutability) -> GlobalType {
248        GlobalType {
249            content,
250            mutability,
251        }
252    }
253
254    /// Returns the value type of this global descriptor.
255    pub fn content(&self) -> &ValType {
256        &self.content
257    }
258
259    /// Returns whether or not this global is mutable.
260    pub fn mutability(&self) -> Mutability {
261        self.mutability
262    }
263
264    /// Returns `None` if the wasmtime global has a type that we can't
265    /// represent, but that should only very rarely happen and indicate a bug.
266    pub(crate) fn from_wasmtime_global(global: &Global) -> GlobalType {
267        let ty = ValType::from_wasm_type(&global.wasm_ty);
268        let mutability = if global.mutability {
269            Mutability::Var
270        } else {
271            Mutability::Const
272        };
273        GlobalType::new(ty, mutability)
274    }
275}
276
277// Table Types
278
279/// A descriptor for a table in a WebAssembly module.
280///
281/// Tables are contiguous chunks of a specific element, typically a `funcref` or
282/// an `externref`. The most common use for tables is a function table through
283/// which `call_indirect` can invoke other functions.
284#[derive(Debug, Clone, Hash, Eq, PartialEq)]
285pub struct TableType {
286    ty: Table,
287}
288
289impl TableType {
290    /// Creates a new table descriptor which will contain the specified
291    /// `element` and have the `limits` applied to its length.
292    pub fn new(element: ValType, min: u32, max: Option<u32>) -> TableType {
293        TableType {
294            ty: Table {
295                wasm_ty: element.to_wasm_type(),
296                minimum: min,
297                maximum: max,
298            },
299        }
300    }
301
302    /// Returns the element value type of this table.
303    pub fn element(&self) -> ValType {
304        ValType::from_wasm_type(&self.ty.wasm_ty)
305    }
306
307    /// Returns minimum number of elements this table must have
308    pub fn minimum(&self) -> u32 {
309        self.ty.minimum
310    }
311
312    /// Returns the optionally-specified maximum number of elements this table
313    /// can have.
314    ///
315    /// If this returns `None` then the table is not limited in size.
316    pub fn maximum(&self) -> Option<u32> {
317        self.ty.maximum
318    }
319
320    pub(crate) fn from_wasmtime_table(table: &Table) -> TableType {
321        TableType { ty: table.clone() }
322    }
323
324    pub(crate) fn wasmtime_table(&self) -> &Table {
325        &self.ty
326    }
327}
328
329// Memory Types
330
331/// A descriptor for a WebAssembly memory type.
332///
333/// Memories are described in units of pages (64KB) and represent contiguous
334/// chunks of addressable memory.
335#[derive(Debug, Clone, Hash, Eq, PartialEq)]
336pub struct MemoryType {
337    ty: Memory,
338}
339
340impl MemoryType {
341    /// Creates a new descriptor for a 32-bit WebAssembly memory given the
342    /// specified limits of the memory.
343    ///
344    /// The `minimum` and `maximum`  values here are specified in units of
345    /// WebAssembly pages, which are 64k.
346    pub fn new(minimum: u32, maximum: Option<u32>) -> MemoryType {
347        MemoryType {
348            ty: Memory {
349                memory64: false,
350                shared: false,
351                minimum: minimum.into(),
352                maximum: maximum.map(|i| i.into()),
353            },
354        }
355    }
356
357    /// Creates a new descriptor for a 64-bit WebAssembly memory given the
358    /// specified limits of the memory.
359    ///
360    /// The `minimum` and `maximum`  values here are specified in units of
361    /// WebAssembly pages, which are 64k.
362    ///
363    /// Note that 64-bit memories are part of the memory64 proposal for
364    /// WebAssembly which is not standardized yet.
365    pub fn new64(minimum: u64, maximum: Option<u64>) -> MemoryType {
366        MemoryType {
367            ty: Memory {
368                memory64: true,
369                shared: false,
370                minimum,
371                maximum,
372            },
373        }
374    }
375
376    /// Creates a new descriptor for shared WebAssembly memory given the
377    /// specified limits of the memory.
378    ///
379    /// The `minimum` and `maximum`  values here are specified in units of
380    /// WebAssembly pages, which are 64k.
381    ///
382    /// Note that shared memories are part of the threads proposal for
383    /// WebAssembly which is not standardized yet.
384    pub fn shared(minimum: u32, maximum: u32) -> MemoryType {
385        MemoryType {
386            ty: Memory {
387                memory64: false,
388                shared: true,
389                minimum: minimum.into(),
390                maximum: Some(maximum.into()),
391            },
392        }
393    }
394
395    /// Returns whether this is a 64-bit memory or not.
396    ///
397    /// Note that 64-bit memories are part of the memory64 proposal for
398    /// WebAssembly which is not standardized yet.
399    pub fn is_64(&self) -> bool {
400        self.ty.memory64
401    }
402
403    /// Returns whether this is a shared memory or not.
404    ///
405    /// Note that shared memories are part of the threads proposal for
406    /// WebAssembly which is not standardized yet.
407    pub fn is_shared(&self) -> bool {
408        self.ty.shared
409    }
410
411    /// Returns minimum number of WebAssembly pages this memory must have.
412    ///
413    /// Note that the return value, while a `u64`, will always fit into a `u32`
414    /// for 32-bit memories.
415    pub fn minimum(&self) -> u64 {
416        self.ty.minimum
417    }
418
419    /// Returns the optionally-specified maximum number of pages this memory
420    /// can have.
421    ///
422    /// If this returns `None` then the memory is not limited in size.
423    ///
424    /// Note that the return value, while a `u64`, will always fit into a `u32`
425    /// for 32-bit memories.
426    pub fn maximum(&self) -> Option<u64> {
427        self.ty.maximum
428    }
429
430    pub(crate) fn from_wasmtime_memory(memory: &Memory) -> MemoryType {
431        MemoryType { ty: memory.clone() }
432    }
433
434    pub(crate) fn wasmtime_memory(&self) -> &Memory {
435        &self.ty
436    }
437}
438
439// Import Types
440
441/// A descriptor for an imported value into a wasm module.
442///
443/// This type is primarily accessed from the
444/// [`Module::imports`](crate::Module::imports) API. Each [`ImportType`]
445/// describes an import into the wasm module with the module/name that it's
446/// imported from as well as the type of item that's being imported.
447#[derive(Clone)]
448pub struct ImportType<'module> {
449    /// The module of the import.
450    module: &'module str,
451
452    /// The field of the import.
453    name: &'module str,
454
455    /// The type of the import.
456    ty: EntityType,
457    types: &'module ModuleTypes,
458}
459
460impl<'module> ImportType<'module> {
461    /// Creates a new import descriptor which comes from `module` and `name` and
462    /// is of type `ty`.
463    pub(crate) fn new(
464        module: &'module str,
465        name: &'module str,
466        ty: EntityType,
467        types: &'module ModuleTypes,
468    ) -> ImportType<'module> {
469        ImportType {
470            module,
471            name,
472            ty,
473            types,
474        }
475    }
476
477    /// Returns the module name that this import is expected to come from.
478    pub fn module(&self) -> &'module str {
479        self.module
480    }
481
482    /// Returns the field name of the module that this import is expected to
483    /// come from.
484    pub fn name(&self) -> &'module str {
485        self.name
486    }
487
488    /// Returns the expected type of this import.
489    pub fn ty(&self) -> ExternType {
490        ExternType::from_wasmtime(self.types, &self.ty)
491    }
492}
493
494impl<'module> fmt::Debug for ImportType<'module> {
495    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
496        f.debug_struct("ImportType")
497            .field("module", &self.module())
498            .field("name", &self.name())
499            .field("ty", &self.ty())
500            .finish()
501    }
502}
503
504// Export Types
505
506/// A descriptor for an exported WebAssembly value.
507///
508/// This type is primarily accessed from the
509/// [`Module::exports`](crate::Module::exports) accessor and describes what
510/// names are exported from a wasm module and the type of the item that is
511/// exported.
512#[derive(Clone)]
513pub struct ExportType<'module> {
514    /// The name of the export.
515    name: &'module str,
516
517    /// The type of the export.
518    ty: EntityType,
519    types: &'module ModuleTypes,
520}
521
522impl<'module> ExportType<'module> {
523    /// Creates a new export which is exported with the given `name` and has the
524    /// given `ty`.
525    pub(crate) fn new(
526        name: &'module str,
527        ty: EntityType,
528        types: &'module ModuleTypes,
529    ) -> ExportType<'module> {
530        ExportType { name, ty, types }
531    }
532
533    /// Returns the name by which this export is known.
534    pub fn name(&self) -> &'module str {
535        self.name
536    }
537
538    /// Returns the type of this export.
539    pub fn ty(&self) -> ExternType {
540        ExternType::from_wasmtime(self.types, &self.ty)
541    }
542}
543
544impl<'module> fmt::Debug for ExportType<'module> {
545    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
546        f.debug_struct("ExportType")
547            .field("name", &self.name().to_owned())
548            .field("ty", &self.ty())
549            .finish()
550    }
551}