Skip to main content

tinywasm_types/
types.rs

1use alloc::boxed::Box;
2
3use crate::{Shared, TypeAddr, WasmType};
4
5/// The dense type index space of a WebAssembly module.
6///
7/// See <https://webassembly.github.io/spec/core/syntax/types.html#syntax-rectype>
8#[derive(Clone, PartialEq, Eq, Default)]
9#[cfg_attr(feature = "debug", derive(Debug))]
10#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
11pub struct TypeSection {
12    /// Types in module index order.
13    pub types: Box<[SubType]>,
14    /// Number of types in each recursive group, in section order.
15    pub rec_group_lengths: Box<[u32]>,
16}
17
18impl TypeSection {
19    #[inline]
20    pub fn get(&self, index: TypeAddr) -> Option<&SubType> {
21        self.types.get(index as usize)
22    }
23
24    #[inline]
25    pub fn len(&self) -> usize {
26        self.types.len()
27    }
28
29    #[inline]
30    pub fn is_empty(&self) -> bool {
31        self.types.is_empty()
32    }
33}
34
35/// A type with optional declared subtyping.
36///
37/// See <https://webassembly.github.io/spec/core/syntax/types.html#syntax-subtype>
38#[derive(Clone, PartialEq, Eq)]
39#[cfg_attr(feature = "debug", derive(Debug))]
40#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
41pub struct SubType {
42    pub is_final: bool,
43    pub supertype: Option<TypeAddr>,
44    pub composite: CompositeType,
45}
46
47impl SubType {
48    #[inline]
49    pub const fn as_func(&self) -> Option<&FuncType> {
50        self.composite.as_func()
51    }
52
53    #[inline]
54    pub const fn as_struct(&self) -> Option<&StructType> {
55        self.composite.as_struct()
56    }
57
58    #[inline]
59    pub const fn as_array(&self) -> Option<&ArrayType> {
60        self.composite.as_array()
61    }
62}
63
64/// A function, struct, or array type.
65///
66/// See <https://webassembly.github.io/spec/core/syntax/types.html#syntax-comptype>
67#[derive(Clone, PartialEq, Eq)]
68#[cfg_attr(feature = "debug", derive(Debug))]
69#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
70pub enum CompositeType {
71    Func(FuncType),
72    Struct(StructType),
73    Array(ArrayType),
74}
75
76impl CompositeType {
77    #[inline]
78    pub const fn as_func(&self) -> Option<&FuncType> {
79        match self {
80            Self::Func(ty) => Some(ty),
81            _ => None,
82        }
83    }
84
85    #[inline]
86    pub const fn as_struct(&self) -> Option<&StructType> {
87        match self {
88            Self::Struct(ty) => Some(ty),
89            _ => None,
90        }
91    }
92
93    #[inline]
94    pub const fn as_array(&self) -> Option<&ArrayType> {
95        match self {
96            Self::Array(ty) => Some(ty),
97            _ => None,
98        }
99    }
100}
101
102/// The type of a WebAssembly function.
103///
104/// See <https://webassembly.github.io/spec/core/syntax/types.html#function-types>
105#[derive(Clone, PartialEq, Eq, Default)]
106#[cfg_attr(feature = "debug", derive(Debug))]
107#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
108pub struct FuncType {
109    data: Shared<[WasmType]>,
110    param_count: u16,
111}
112
113impl FuncType {
114    /// Create a new function type.
115    pub fn new(params: &[WasmType], results: &[WasmType]) -> Self {
116        let data: Box<[WasmType]> = params.iter().cloned().chain(results.iter().cloned()).collect();
117        Self { data: data.into(), param_count: params.len() as u16 }
118    }
119
120    /// Get the parameter types of this function type.
121    pub fn params(&self) -> &[WasmType] {
122        &self.data[..self.param_count as usize]
123    }
124
125    /// Get the result types of this function type.
126    pub fn results(&self) -> &[WasmType] {
127        &self.data[self.param_count as usize..]
128    }
129}
130
131/// A WebAssembly struct type.
132///
133/// See <https://webassembly.github.io/spec/core/syntax/types.html#syntax-structtype>
134#[derive(Clone, PartialEq, Eq, Default)]
135#[cfg_attr(feature = "debug", derive(Debug))]
136#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
137pub struct StructType {
138    pub fields: Box<[FieldType]>,
139}
140
141/// A WebAssembly array type.
142///
143/// See <https://webassembly.github.io/spec/core/syntax/types.html#syntax-arraytype>
144#[derive(Clone, PartialEq, Eq)]
145#[cfg_attr(feature = "debug", derive(Debug))]
146#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
147pub struct ArrayType {
148    pub field: FieldType,
149}
150
151/// A struct field or array element type.
152///
153/// See <https://webassembly.github.io/spec/core/syntax/types.html#syntax-fieldtype>
154#[derive(Clone, Copy, PartialEq, Eq)]
155#[cfg_attr(feature = "debug", derive(Debug))]
156#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
157pub struct FieldType {
158    pub storage: StorageType,
159    pub mutable: bool,
160}
161
162/// A field's packed or unpacked storage type.
163///
164/// See <https://webassembly.github.io/spec/core/syntax/types.html#syntax-storagetype>
165#[derive(Clone, Copy, PartialEq, Eq)]
166#[cfg_attr(feature = "debug", derive(Debug))]
167#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
168pub enum StorageType {
169    I8,
170    I16,
171    Value(WasmType),
172}
173
174impl StorageType {
175    /// Returns the unpacked WebAssembly value type used on the stack.
176    pub const fn unpacked(self) -> WasmType {
177        match self {
178            Self::I8 | Self::I16 => WasmType::I32,
179            Self::Value(ty) => ty,
180        }
181    }
182}