1 | use crate::limits::MAX_WASM_CANONICAL_OPTIONS; |
2 | use crate::prelude::*; |
3 | use crate::{BinaryReader, FromReader, Result, SectionLimited}; |
4 | |
5 | /// Represents options for component functions. |
6 | #[derive (Debug, Clone, Copy, PartialEq, Eq)] |
7 | pub enum CanonicalOption { |
8 | /// The string types in the function signature are UTF-8 encoded. |
9 | UTF8, |
10 | /// The string types in the function signature are UTF-16 encoded. |
11 | UTF16, |
12 | /// The string types in the function signature are compact UTF-16 encoded. |
13 | CompactUTF16, |
14 | /// The memory to use if the lifting or lowering of a function requires memory access. |
15 | /// |
16 | /// The value is an index to a core memory. |
17 | Memory(u32), |
18 | /// The realloc function to use if the lifting or lowering of a function requires memory |
19 | /// allocation. |
20 | /// |
21 | /// The value is an index to a core function of type `(func (param i32 i32 i32 i32) (result i32))`. |
22 | Realloc(u32), |
23 | /// The post-return function to use if the lifting of a function requires |
24 | /// cleanup after the function returns. |
25 | PostReturn(u32), |
26 | } |
27 | |
28 | /// Represents a canonical function in a WebAssembly component. |
29 | #[derive (Debug, Clone, Eq, PartialEq)] |
30 | pub enum CanonicalFunction { |
31 | /// The function lifts a core WebAssembly function to the canonical ABI. |
32 | Lift { |
33 | /// The index of the core WebAssembly function to lift. |
34 | core_func_index: u32, |
35 | /// The index of the lifted function's type. |
36 | type_index: u32, |
37 | /// The canonical options for the function. |
38 | options: Box<[CanonicalOption]>, |
39 | }, |
40 | /// The function lowers a canonical ABI function to a core WebAssembly function. |
41 | Lower { |
42 | /// The index of the function to lower. |
43 | func_index: u32, |
44 | /// The canonical options for the function. |
45 | options: Box<[CanonicalOption]>, |
46 | }, |
47 | /// A function which creates a new owned handle to a resource. |
48 | ResourceNew { |
49 | /// The type index of the resource that's being created. |
50 | resource: u32, |
51 | }, |
52 | /// A function which is used to drop resource handles of the specified type. |
53 | ResourceDrop { |
54 | /// The type index of the resource that's being dropped. |
55 | resource: u32, |
56 | }, |
57 | /// A function which returns the underlying i32-based representation of the |
58 | /// specified resource. |
59 | ResourceRep { |
60 | /// The type index of the resource that's being accessed. |
61 | resource: u32, |
62 | }, |
63 | /// A function which spawns a new thread by invoking the shared function. |
64 | ThreadSpawn { |
65 | /// The index of the function to spawn. |
66 | func_ty_index: u32, |
67 | }, |
68 | /// A function which returns the number of threads that can be expected to |
69 | /// execute concurrently |
70 | ThreadHwConcurrency, |
71 | } |
72 | |
73 | /// A reader for the canonical section of a WebAssembly component. |
74 | pub type ComponentCanonicalSectionReader<'a> = SectionLimited<'a, CanonicalFunction>; |
75 | |
76 | impl<'a> FromReader<'a> for CanonicalFunction { |
77 | fn from_reader(reader: &mut BinaryReader<'a>) -> Result<CanonicalFunction> { |
78 | Ok(match reader.read_u8()? { |
79 | 0x00 => match reader.read_u8()? { |
80 | 0x00 => { |
81 | let core_func_index = reader.read_var_u32()?; |
82 | let options = reader |
83 | .read_iter(MAX_WASM_CANONICAL_OPTIONS, "canonical options" )? |
84 | .collect::<Result<_>>()?; |
85 | let type_index = reader.read_var_u32()?; |
86 | CanonicalFunction::Lift { |
87 | core_func_index, |
88 | options, |
89 | type_index, |
90 | } |
91 | } |
92 | x => return reader.invalid_leading_byte(x, "canonical function lift" ), |
93 | }, |
94 | 0x01 => match reader.read_u8()? { |
95 | 0x00 => CanonicalFunction::Lower { |
96 | func_index: reader.read_var_u32()?, |
97 | options: reader |
98 | .read_iter(MAX_WASM_CANONICAL_OPTIONS, "canonical options" )? |
99 | .collect::<Result<_>>()?, |
100 | }, |
101 | x => return reader.invalid_leading_byte(x, "canonical function lower" ), |
102 | }, |
103 | 0x02 => CanonicalFunction::ResourceNew { |
104 | resource: reader.read()?, |
105 | }, |
106 | 0x03 => CanonicalFunction::ResourceDrop { |
107 | resource: reader.read()?, |
108 | }, |
109 | 0x04 => CanonicalFunction::ResourceRep { |
110 | resource: reader.read()?, |
111 | }, |
112 | 0x05 => CanonicalFunction::ThreadSpawn { |
113 | func_ty_index: reader.read()?, |
114 | }, |
115 | 0x06 => CanonicalFunction::ThreadHwConcurrency, |
116 | x => return reader.invalid_leading_byte(x, "canonical function" ), |
117 | }) |
118 | } |
119 | } |
120 | |
121 | impl<'a> FromReader<'a> for CanonicalOption { |
122 | fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> { |
123 | Ok(match reader.read_u8()? { |
124 | 0x00 => CanonicalOption::UTF8, |
125 | 0x01 => CanonicalOption::UTF16, |
126 | 0x02 => CanonicalOption::CompactUTF16, |
127 | 0x03 => CanonicalOption::Memory(reader.read_var_u32()?), |
128 | 0x04 => CanonicalOption::Realloc(reader.read_var_u32()?), |
129 | 0x05 => CanonicalOption::PostReturn(reader.read_var_u32()?), |
130 | x: u8 => return reader.invalid_leading_byte(byte:x, desc:"canonical option" ), |
131 | }) |
132 | } |
133 | } |
134 | |