1 | use super::CORE_INSTANCE_SORT; |
2 | use crate::{ |
3 | encode_section, ComponentExportKind, ComponentSection, ComponentSectionId, Encode, ExportKind, |
4 | }; |
5 | use alloc::vec::Vec; |
6 | |
7 | /// Represents an argument to a module instantiation. |
8 | #[derive (Clone, Copy, Debug, Eq, PartialEq)] |
9 | pub enum ModuleArg { |
10 | /// The argument is an instance. |
11 | Instance(u32), |
12 | } |
13 | |
14 | impl Encode for ModuleArg { |
15 | fn encode(&self, sink: &mut Vec<u8>) { |
16 | let (sort: u8, idx: u32) = match self { |
17 | Self::Instance(idx: &u32) => (CORE_INSTANCE_SORT, *idx), |
18 | }; |
19 | sink.push(sort); |
20 | idx.encode(sink); |
21 | } |
22 | } |
23 | |
24 | /// An encoder for the core instance section of WebAssembly components. |
25 | /// |
26 | /// # Example |
27 | /// |
28 | /// ```rust |
29 | /// use wasm_encoder::{Component, InstanceSection, ExportKind, ModuleArg}; |
30 | /// |
31 | /// let mut instances = InstanceSection::new(); |
32 | /// instances.export_items([("foo" , ExportKind::Func, 0)]); |
33 | /// instances.instantiate(1, [("foo" , ModuleArg::Instance(0))]); |
34 | /// |
35 | /// let mut component = Component::new(); |
36 | /// component.section(&instances); |
37 | /// |
38 | /// let bytes = component.finish(); |
39 | /// ``` |
40 | #[derive (Clone, Debug, Default)] |
41 | pub struct InstanceSection { |
42 | bytes: Vec<u8>, |
43 | num_added: u32, |
44 | } |
45 | |
46 | impl InstanceSection { |
47 | /// Create a new core instance section encoder. |
48 | pub fn new() -> Self { |
49 | Self::default() |
50 | } |
51 | |
52 | /// The number of instances in the section. |
53 | pub fn len(&self) -> u32 { |
54 | self.num_added |
55 | } |
56 | |
57 | /// Determines if the section is empty. |
58 | pub fn is_empty(&self) -> bool { |
59 | self.num_added == 0 |
60 | } |
61 | |
62 | /// Define an instance by instantiating a core module. |
63 | pub fn instantiate<A, S>(&mut self, module_index: u32, args: A) -> &mut Self |
64 | where |
65 | A: IntoIterator<Item = (S, ModuleArg)>, |
66 | A::IntoIter: ExactSizeIterator, |
67 | S: AsRef<str>, |
68 | { |
69 | let args = args.into_iter(); |
70 | self.bytes.push(0x00); |
71 | module_index.encode(&mut self.bytes); |
72 | args.len().encode(&mut self.bytes); |
73 | for (name, arg) in args { |
74 | name.as_ref().encode(&mut self.bytes); |
75 | arg.encode(&mut self.bytes); |
76 | } |
77 | self.num_added += 1; |
78 | self |
79 | } |
80 | |
81 | /// Define an instance by exporting core WebAssembly items. |
82 | pub fn export_items<E, S>(&mut self, exports: E) -> &mut Self |
83 | where |
84 | E: IntoIterator<Item = (S, ExportKind, u32)>, |
85 | E::IntoIter: ExactSizeIterator, |
86 | S: AsRef<str>, |
87 | { |
88 | let exports = exports.into_iter(); |
89 | self.bytes.push(0x01); |
90 | exports.len().encode(&mut self.bytes); |
91 | for (name, kind, index) in exports { |
92 | name.as_ref().encode(&mut self.bytes); |
93 | kind.encode(&mut self.bytes); |
94 | index.encode(&mut self.bytes); |
95 | } |
96 | self.num_added += 1; |
97 | self |
98 | } |
99 | } |
100 | |
101 | impl Encode for InstanceSection { |
102 | fn encode(&self, sink: &mut Vec<u8>) { |
103 | encode_section(sink, self.num_added, &self.bytes); |
104 | } |
105 | } |
106 | |
107 | impl ComponentSection for InstanceSection { |
108 | fn id(&self) -> u8 { |
109 | ComponentSectionId::CoreInstance.into() |
110 | } |
111 | } |
112 | |
113 | /// An encoder for the instance section of WebAssembly components. |
114 | /// |
115 | /// # Example |
116 | /// |
117 | /// ```rust |
118 | /// use wasm_encoder::{Component, ComponentInstanceSection, ComponentExportKind}; |
119 | /// |
120 | /// let mut instances = ComponentInstanceSection::new(); |
121 | /// instances.export_items([("foo" , ComponentExportKind::Func, 0)]); |
122 | /// instances.instantiate(1, [("foo" , ComponentExportKind::Instance, 0)]); |
123 | /// |
124 | /// let mut component = Component::new(); |
125 | /// component.section(&instances); |
126 | /// |
127 | /// let bytes = component.finish(); |
128 | /// ``` |
129 | #[derive (Clone, Debug, Default)] |
130 | pub struct ComponentInstanceSection { |
131 | bytes: Vec<u8>, |
132 | num_added: u32, |
133 | } |
134 | |
135 | impl ComponentInstanceSection { |
136 | /// Create a new instance section encoder. |
137 | pub fn new() -> Self { |
138 | Self::default() |
139 | } |
140 | |
141 | /// The number of instances in the section. |
142 | pub fn len(&self) -> u32 { |
143 | self.num_added |
144 | } |
145 | |
146 | /// Determines if the section is empty. |
147 | pub fn is_empty(&self) -> bool { |
148 | self.num_added == 0 |
149 | } |
150 | |
151 | /// Define an instance by instantiating a component. |
152 | pub fn instantiate<A, S>(&mut self, component_index: u32, args: A) -> &mut Self |
153 | where |
154 | A: IntoIterator<Item = (S, ComponentExportKind, u32)>, |
155 | A::IntoIter: ExactSizeIterator, |
156 | S: AsRef<str>, |
157 | { |
158 | let args = args.into_iter(); |
159 | self.bytes.push(0x00); |
160 | component_index.encode(&mut self.bytes); |
161 | args.len().encode(&mut self.bytes); |
162 | for (name, kind, index) in args { |
163 | name.as_ref().encode(&mut self.bytes); |
164 | kind.encode(&mut self.bytes); |
165 | index.encode(&mut self.bytes); |
166 | } |
167 | self.num_added += 1; |
168 | self |
169 | } |
170 | |
171 | /// Define an instance by exporting items. |
172 | pub fn export_items<'a, E>(&mut self, exports: E) -> &mut Self |
173 | where |
174 | E: IntoIterator<Item = (&'a str, ComponentExportKind, u32)>, |
175 | E::IntoIter: ExactSizeIterator, |
176 | { |
177 | let exports = exports.into_iter(); |
178 | self.bytes.push(0x01); |
179 | exports.len().encode(&mut self.bytes); |
180 | for (name, kind, index) in exports { |
181 | crate::encode_component_export_name(&mut self.bytes, name); |
182 | kind.encode(&mut self.bytes); |
183 | index.encode(&mut self.bytes); |
184 | } |
185 | self.num_added += 1; |
186 | self |
187 | } |
188 | } |
189 | |
190 | impl Encode for ComponentInstanceSection { |
191 | fn encode(&self, sink: &mut Vec<u8>) { |
192 | encode_section(sink, self.num_added, &self.bytes); |
193 | } |
194 | } |
195 | |
196 | impl ComponentSection for ComponentInstanceSection { |
197 | fn id(&self) -> u8 { |
198 | ComponentSectionId::Instance.into() |
199 | } |
200 | } |
201 | |