wasm_ast/model/types.rs
1//! Model for types in the WebAssembly syntax.
2
3/// Number types classify numeric values.
4/// Number types are transparent, meaning that their bit patterns can be observed.
5/// Values of number type can be stored in memories.
6///
7/// See <https://webassembly.github.io/spec/core/syntax/types.html#number-types>
8///
9/// # Examples
10/// ```rust
11/// use wasm_ast::{ValueType, NumberType};
12///
13/// assert_eq!(ValueType::I32, NumberType::I32.into());
14/// assert_eq!(ValueType::I64, NumberType::I64.into());
15/// assert_eq!(ValueType::F32, NumberType::F32.into());
16/// assert_eq!(ValueType::F64, NumberType::F64.into());
17/// ```
18#[derive(Copy, Clone, Debug, Eq, PartialEq)]
19pub enum NumberType {
20 I32,
21 I64,
22 F32,
23 F64,
24}
25
26impl From<IntegerType> for NumberType {
27 fn from(kind: IntegerType) -> Self {
28 match kind {
29 IntegerType::I32 => NumberType::I32,
30 IntegerType::I64 => NumberType::I64,
31 }
32 }
33}
34
35impl From<FloatType> for NumberType {
36 fn from(kind: FloatType) -> Self {
37 match kind {
38 FloatType::F32 => NumberType::F32,
39 FloatType::F64 => NumberType::F64,
40 }
41 }
42}
43
44/// The types ππ₯π€ and ππ¨π¦ classify 32 and 64 bit integers, respectively.
45/// Integers are not inherently signed or unsigned, their interpretation is determined by individual operations.
46///
47/// # Examples
48/// ```rust
49/// use wasm_ast::{ValueType, NumberType, IntegerType};
50///
51/// assert_eq!(ValueType::I32, IntegerType::I32.into());
52/// assert_eq!(NumberType::I32, IntegerType::I32.into());
53/// assert_eq!(ValueType::I64, IntegerType::I64.into());
54/// assert_eq!(NumberType::I64, IntegerType::I64.into());
55/// ```
56#[derive(Copy, Clone, Debug, Eq, PartialEq)]
57pub enum IntegerType {
58 I32,
59 I64,
60}
61
62/// The types πΏπ₯π€ and πΏπ¨π¦ classify 32 and 64 bit floating-point data, respectively.
63/// They correspond to the respective binary floating-point representations,
64/// also known as single and double precision, as defined by the IEEE 754-2019 standard (Section 3.3).
65///
66/// # Examples
67/// ```rust
68/// use wasm_ast::{ValueType, NumberType, FloatType};
69///
70/// assert_eq!(ValueType::F32, FloatType::F32.into());
71/// assert_eq!(NumberType::F32, FloatType::F32.into());
72/// assert_eq!(ValueType::F64, FloatType::F64.into());
73/// assert_eq!(NumberType::F64, FloatType::F64.into());
74/// ```
75#[derive(Copy, Clone, Debug, Eq, PartialEq)]
76pub enum FloatType {
77 F32,
78 F64,
79}
80
81/// Reference types classify first-class references to objects in the runtime store.
82/// The type πΏπππΌππΎπΏ denotes the infinite union of all references to functions,
83/// regardless of their function types.
84/// The type πΎπππΎππππΎπΏ denotes the infinite union of all references to objects owned by the
85/// embedder and that can be passed into WebAssembly under this type.
86/// Reference types are opaque, meaning that neither their size nor their bit pattern can be observed.
87/// Values of reference type can be stored in tables.
88///
89/// See <https://webassembly.github.io/spec/core/syntax/types.html#reference-types>
90///
91/// # Examples
92/// ```rust
93/// use wasm_ast::{ValueType, ReferenceType};
94///
95/// assert_eq!(ValueType::FunctionReference, ReferenceType::Function.into());
96/// assert_eq!(ValueType::ExternalReference, ReferenceType::External.into());
97/// ```
98#[derive(Copy, Clone, Debug, Eq, PartialEq)]
99pub enum ReferenceType {
100 Function,
101 External,
102}
103
104/// Value types classify the individual values that WebAssembly code can compute with and the values that a variable accepts.
105/// They are either number types or reference types.
106///
107/// See <https://webassembly.github.io/spec/core/syntax/types.html#value-types>
108///
109/// # Examples
110/// ```rust
111/// use wasm_ast::{ValueType, ReferenceType, IntegerType, FloatType, NumberType};
112///
113/// assert_eq!(ValueType::I32, IntegerType::I32.into());
114/// assert_eq!(ValueType::I32, NumberType::I32.into());
115/// assert_eq!(ValueType::I64, IntegerType::I64.into());
116/// assert_eq!(ValueType::I64, NumberType::I64.into());
117/// assert_eq!(ValueType::F32, FloatType::F32.into());
118/// assert_eq!(ValueType::F32, NumberType::F32.into());
119/// assert_eq!(ValueType::F64, FloatType::F64.into());
120/// assert_eq!(ValueType::F64, NumberType::F64.into());
121/// assert_eq!(ValueType::FunctionReference, ReferenceType::Function.into());
122/// assert_eq!(ValueType::ExternalReference, ReferenceType::External.into());
123/// ```
124#[derive(Copy, Clone, Debug, Eq, PartialEq)]
125pub enum ValueType {
126 I32,
127 I64,
128 F32,
129 F64,
130 FunctionReference,
131 ExternalReference,
132}
133
134impl<T> From<T> for ValueType
135where
136 T: Into<NumberType>,
137{
138 fn from(kind: T) -> Self {
139 match kind.into() {
140 NumberType::I32 => ValueType::I32,
141 NumberType::I64 => ValueType::I64,
142 NumberType::F32 => ValueType::F32,
143 NumberType::F64 => ValueType::F64,
144 }
145 }
146}
147
148impl From<ReferenceType> for ValueType {
149 fn from(kind: ReferenceType) -> Self {
150 match kind {
151 ReferenceType::Function => ValueType::FunctionReference,
152 ReferenceType::External => ValueType::ExternalReference,
153 }
154 }
155}
156
157/// Result types classify the result of executing instructions or functions,
158/// which is a sequence of values, written with brackets.
159///
160/// See <https://webassembly.github.io/spec/core/syntax/types.html#result-types>
161///
162/// # Examples
163///
164/// ## Empty
165/// ```rust
166/// use wasm_ast::ResultType;
167///
168/// let result_type = ResultType::empty();
169///
170/// assert_eq!(result_type.len(), 0);
171/// assert!(result_type.is_empty());
172/// assert_eq!(result_type.kinds(), &[]);
173/// ```
174///
175/// ## Non-Empty
176/// ```rust
177/// use wasm_ast::{ResultType, IntegerType, FloatType, ReferenceType, ValueType};
178///
179/// let result_type = ResultType::new(vec![
180/// IntegerType::I32.into(),
181/// IntegerType::I64.into(),
182/// FloatType::F32.into(),
183/// FloatType::F64.into(),
184/// ReferenceType::Function.into(),
185/// ReferenceType::External.into(),
186/// ]);
187///
188/// assert_eq!(result_type.len(), 6);
189/// assert!(!result_type.is_empty());
190/// assert_eq!(
191/// result_type.kinds(),
192/// &[
193/// ValueType::I32,
194/// ValueType::I64,
195/// ValueType::F32,
196/// ValueType::F64,
197/// ValueType::FunctionReference,
198/// ValueType::ExternalReference,
199/// ]
200/// );
201/// assert_eq!(
202/// result_type,
203/// vec![
204/// ValueType::I32,
205/// ValueType::I64,
206/// ValueType::F32,
207/// ValueType::F64,
208/// ValueType::FunctionReference,
209/// ValueType::ExternalReference,
210/// ].into()
211/// );
212/// ```
213#[derive(Clone, Debug, Eq, PartialEq)]
214pub struct ResultType {
215 kinds: Vec<ValueType>,
216}
217
218impl ResultType {
219 /// Creates a new `ResultType` with the given value types.
220 pub fn new(kinds: Vec<ValueType>) -> Self {
221 ResultType { kinds }
222 }
223
224 /// Creates a new empty `ResultType`.
225 pub fn empty() -> Self {
226 ResultType { kinds: vec![] }
227 }
228
229 /// A reference to a slice of the `ValueType`s.
230 pub fn kinds(&self) -> &[ValueType] {
231 &self.kinds
232 }
233
234 /// The length of the `ValueType` vector.
235 pub fn len(&self) -> usize {
236 self.kinds.len()
237 }
238
239 /// Returns true if this `ResultType` has a length of zero, false otherwise.
240 pub fn is_empty(&self) -> bool {
241 self.kinds.is_empty()
242 }
243}
244
245impl From<Vec<ValueType>> for ResultType {
246 fn from(kinds: Vec<ValueType>) -> Self {
247 ResultType { kinds }
248 }
249}
250
251/// Function types classify the signature of functions,
252/// mapping a vector of parameters to a vector of results.
253/// They are also used to classify the inputs and outputs of instructions
254///
255/// See <https://webassembly.github.io/spec/core/syntax/types.html#function-types>
256///
257/// # Examples
258///
259/// ## Input & Output
260/// ```rust
261/// use wasm_ast::{FunctionType, ResultType};
262///
263/// let function_type = FunctionType::new(ResultType::empty(), ResultType::empty());
264///
265/// assert!(function_type.parameters().is_empty());
266/// assert!(function_type.results().is_empty());
267/// ```
268///
269/// ## Input Only
270/// ```rust
271/// use wasm_ast::{FunctionType, ResultType, ValueType};
272///
273/// let function_type = FunctionType::side_effect(ResultType::from(vec![ValueType::I32]));
274///
275/// assert_eq!(function_type.parameters().kinds(), &[ValueType::I32]);
276/// assert!(function_type.results().is_empty());
277/// ```
278///
279/// ## Output Only
280/// ```rust
281/// use wasm_ast::{FunctionType, ResultType, ValueType};
282///
283/// let function_type = FunctionType::nullary(ResultType::from(vec![ValueType::I32]));
284///
285/// assert!(function_type.parameters().is_empty());
286/// assert_eq!(function_type.results().kinds(), &[ValueType::I32]);
287/// ```
288///
289/// ## No Input or Output
290/// ```rust
291/// use wasm_ast::{FunctionType, ResultType, ValueType};
292///
293/// let function_type = FunctionType::runnable();
294///
295/// assert!(function_type.parameters().is_empty());
296/// assert!(function_type.results().is_empty());
297/// ```
298#[derive(Clone, Debug, Eq, PartialEq)]
299pub struct FunctionType {
300 parameters: ResultType,
301 results: ResultType,
302}
303
304impl FunctionType {
305 /// Creates a new function signature with the given parameter and result types.
306 pub fn new(parameters: ResultType, results: ResultType) -> Self {
307 FunctionType {
308 parameters,
309 results,
310 }
311 }
312
313 /// Creates a new function signature with the given parameter types and no result types.
314 pub fn side_effect(parameters: ResultType) -> Self {
315 FunctionType {
316 parameters,
317 results: ResultType::empty(),
318 }
319 }
320
321 /// Creates a new function signature with the given result types and no parameter types.
322 pub fn nullary(results: ResultType) -> Self {
323 FunctionType {
324 parameters: ResultType::empty(),
325 results,
326 }
327 }
328
329 /// Creates a new function signature with the no parameter or result types.
330 pub fn runnable() -> Self {
331 FunctionType {
332 parameters: ResultType::empty(),
333 results: ResultType::empty(),
334 }
335 }
336
337 /// The parameter types of this `FunctionType`.
338 pub fn parameters(&self) -> &ResultType {
339 &self.parameters
340 }
341
342 /// The result types of this `FunctionType`.
343 pub fn results(&self) -> &ResultType {
344 &self.results
345 }
346}
347
348/// Limits classify the size range of resizeable storage associated with memory types and table types.
349///
350/// See <https://webassembly.github.io/spec/core/syntax/types.html#limits>
351///
352/// # Examples
353///
354/// ## New
355/// ```rust
356/// use wasm_ast::Limit;
357///
358/// let max = Some(2);
359/// let min = 0;
360/// let limit = Limit::new(min, max);
361///
362/// assert_eq!(limit.min(), min);
363/// assert_eq!(limit.max(), max);
364/// ```
365///
366/// ## Unbounded
367/// ```rust
368/// use wasm_ast::Limit;
369///
370/// assert_eq!(Limit::unbounded(2), Limit::new(2, None));
371/// ```
372///
373/// /// ## Unbounded
374/// ```rust
375/// use wasm_ast::Limit;
376///
377/// assert_eq!(Limit::bounded(2, 5), Limit::new(2, Some(5)));
378/// ```
379#[derive(Copy, Clone, Debug, Eq, PartialEq)]
380pub struct Limit {
381 min: u32,
382 max: Option<u32>,
383}
384
385impl Limit {
386 /// Creates a new limit with a required minimum and optional maximum.
387 pub fn new(min: u32, max: Option<u32>) -> Self {
388 Limit { min, max }
389 }
390
391 /// Creates a new limit with a required minimum and no maximum.
392 pub fn unbounded(min: u32) -> Self {
393 Limit { min, max: None }
394 }
395
396 /// Creates a new limit with a required minimum and maximum.
397 pub fn bounded(min: u32, max: u32) -> Self {
398 Limit {
399 min,
400 max: Some(max),
401 }
402 }
403
404 /// The minimum value of the limit.
405 pub fn min(&self) -> u32 {
406 self.min
407 }
408
409 /// The optional maximum value of the limit.
410 pub fn max(&self) -> Option<u32> {
411 self.max
412 }
413}
414
415/// Memory types classify linear memories and their size range.
416/// The limits constrain the minimum and optionally the maximum size of a memory.
417/// The limits are given in units of page size.
418///
419/// See <https://webassembly.github.io/spec/core/syntax/types.html#memory-types>
420///
421/// # Examples
422/// ```rust
423/// use wasm_ast::{Limit, MemoryType};
424///
425/// let limit = Limit::unbounded(0);
426/// let memory_type = MemoryType::new(limit.clone());
427///
428/// assert_eq!(memory_type.limits(), &limit);
429/// assert_eq!(memory_type, limit.into());
430/// ```
431#[derive(Copy, Clone, Debug, Eq, PartialEq)]
432pub struct MemoryType {
433 limits: Limit,
434}
435
436impl MemoryType {
437 /// Creates a new memory type from the given limits.
438 pub fn new(limit: Limit) -> Self {
439 MemoryType { limits: limit }
440 }
441
442 /// The limits of the number of pages for this `MemoryType`.
443 pub fn limits(&self) -> &Limit {
444 &self.limits
445 }
446}
447
448impl From<Limit> for MemoryType {
449 fn from(limit: Limit) -> Self {
450 MemoryType { limits: limit }
451 }
452}
453
454/// Table types classify tables over elements of reference type within a size range.
455/// Like memories, tables are constrained by limits for their minimum and optionally maximum size.
456/// The limits are given in numbers of entries.
457///
458/// See <https://webassembly.github.io/spec/core/syntax/types.html#table-types>
459///
460/// # Examples
461/// ```rust
462/// use wasm_ast::{Limit, TableType, ReferenceType};
463///
464/// let limit = Limit::unbounded(0);
465/// let table_type = TableType::new( ReferenceType::External,limit.clone());
466///
467/// assert_eq!(table_type.limits(), &limit);
468/// assert_eq!(table_type.kind(), ReferenceType::External);
469/// ```
470#[derive(Copy, Clone, Debug, Eq, PartialEq)]
471pub struct TableType {
472 limits: Limit,
473 kind: ReferenceType,
474}
475
476impl TableType {
477 /// Creates a new `TableType` for the given limits and reference type.
478 pub fn new(kind: ReferenceType, limits: Limit) -> Self {
479 TableType { limits, kind }
480 }
481
482 /// The limits of the number of elements for this `TableType`.
483 pub fn limits(&self) -> &Limit {
484 &self.limits
485 }
486
487 /// The reference type of the elements of this `TableType`.
488 pub fn kind(&self) -> ReferenceType {
489 self.kind
490 }
491}
492
493/// Global types classify global variables, which hold a value and can either be mutable or immutable.
494///
495/// See <https://webassembly.github.io/spec/core/syntax/types.html#global-types>
496///
497/// # Examples
498/// ## Mutable
499/// ```rust
500/// use wasm_ast::{ValueType, GlobalType, Mutability};
501///
502/// let mutable = GlobalType::mutable(ValueType::I64);
503///
504/// assert_eq!(mutable.mutability(), Mutability::Mutable);
505/// assert_eq!(mutable.kind(), ValueType::I64);
506/// assert_eq!(mutable, GlobalType::new( ValueType::I64,Mutability::Mutable));
507/// ```
508///
509/// ## Immutable
510/// ```rust
511/// use wasm_ast::{ValueType, GlobalType, Mutability};
512///
513/// let immutable = GlobalType::immutable(ValueType::F64);
514///
515/// assert_eq!(immutable.mutability(), Mutability::Immutable);
516/// assert_eq!(immutable.kind(), ValueType::F64);
517/// assert_eq!(immutable, GlobalType::new( ValueType::F64,Mutability::Immutable));
518/// ```
519#[derive(Copy, Clone, Debug, Eq, PartialEq)]
520pub struct GlobalType {
521 mutability: Mutability,
522 kind: ValueType,
523}
524
525impl GlobalType {
526 /// Creates a new `GlobalType` for a global variable with the given mutability and value type.
527 pub fn new(kind: ValueType, mutability: Mutability) -> Self {
528 GlobalType { mutability, kind }
529 }
530
531 /// Creates a new `GlobalType` for a mutable global variable.
532 pub fn mutable(kind: ValueType) -> Self {
533 GlobalType {
534 mutability: Mutability::Mutable,
535 kind,
536 }
537 }
538
539 /// Creates a new `GlobalType` for an immutable (i.e. constant) global variable.
540 pub fn immutable(kind: ValueType) -> Self {
541 GlobalType {
542 mutability: Mutability::Immutable,
543 kind,
544 }
545 }
546
547 /// The `ValueType` of the global variable defined by this `GlobalType`.
548 pub fn kind(&self) -> ValueType {
549 self.kind
550 }
551
552 /// The mutability (i.e. variable versus constant) of the global variable type.
553 pub fn mutability(&self) -> Mutability {
554 self.mutability
555 }
556}
557
558/// The mutability of a global variable.
559#[derive(Copy, Clone, Debug, Eq, PartialEq)]
560pub enum Mutability {
561 Mutable,
562 Immutable,
563}