1use crate::{encode_section, ComponentSection, ComponentSectionId, ComponentValType, Encode};
2use alloc::vec::Vec;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum CanonicalOption {
7 UTF8,
9 UTF16,
11 CompactUTF16,
13 Memory(u32),
17 Realloc(u32),
22 PostReturn(u32),
25 Async,
27 Callback(u32),
30}
31
32impl Encode for CanonicalOption {
33 fn encode(&self, sink: &mut Vec<u8>) {
34 match self {
35 Self::UTF8 => sink.push(0x00),
36 Self::UTF16 => sink.push(0x01),
37 Self::CompactUTF16 => sink.push(0x02),
38 Self::Memory(idx) => {
39 sink.push(0x03);
40 idx.encode(sink);
41 }
42 Self::Realloc(idx) => {
43 sink.push(0x04);
44 idx.encode(sink);
45 }
46 Self::PostReturn(idx) => {
47 sink.push(0x05);
48 idx.encode(sink);
49 }
50 Self::Async => {
51 sink.push(0x06);
52 }
53 Self::Callback(idx) => {
54 sink.push(0x07);
55 idx.encode(sink);
56 }
57 }
58 }
59}
60
61#[derive(Clone, Debug, Default)]
77pub struct CanonicalFunctionSection {
78 bytes: Vec<u8>,
79 num_added: u32,
80}
81
82impl CanonicalFunctionSection {
83 pub fn new() -> Self {
85 Self::default()
86 }
87
88 pub fn len(&self) -> u32 {
90 self.num_added
91 }
92
93 pub fn is_empty(&self) -> bool {
95 self.num_added == 0
96 }
97
98 pub fn lift<O>(&mut self, core_func_index: u32, type_index: u32, options: O) -> &mut Self
100 where
101 O: IntoIterator<Item = CanonicalOption>,
102 O::IntoIter: ExactSizeIterator,
103 {
104 self.bytes.push(0x00);
105 self.bytes.push(0x00);
106 core_func_index.encode(&mut self.bytes);
107 self.encode_options(options);
108 type_index.encode(&mut self.bytes);
109 self.num_added += 1;
110 self
111 }
112
113 pub fn lower<O>(&mut self, func_index: u32, options: O) -> &mut Self
115 where
116 O: IntoIterator<Item = CanonicalOption>,
117 O::IntoIter: ExactSizeIterator,
118 {
119 self.bytes.push(0x01);
120 self.bytes.push(0x00);
121 func_index.encode(&mut self.bytes);
122 self.encode_options(options);
123 self.num_added += 1;
124 self
125 }
126
127 pub fn resource_new(&mut self, ty_index: u32) -> &mut Self {
130 self.bytes.push(0x02);
131 ty_index.encode(&mut self.bytes);
132 self.num_added += 1;
133 self
134 }
135
136 pub fn resource_drop(&mut self, ty_index: u32) -> &mut Self {
138 self.bytes.push(0x03);
139 ty_index.encode(&mut self.bytes);
140 self.num_added += 1;
141 self
142 }
143
144 pub fn resource_drop_async(&mut self, ty_index: u32) -> &mut Self {
146 self.bytes.push(0x07);
147 ty_index.encode(&mut self.bytes);
148 self.num_added += 1;
149 self
150 }
151
152 pub fn resource_rep(&mut self, ty_index: u32) -> &mut Self {
155 self.bytes.push(0x04);
156 ty_index.encode(&mut self.bytes);
157 self.num_added += 1;
158 self
159 }
160
161 pub fn thread_spawn_ref(&mut self, ty_index: u32) -> &mut Self {
164 self.bytes.push(0x40);
165 ty_index.encode(&mut self.bytes);
166 self.num_added += 1;
167 self
168 }
169
170 pub fn thread_spawn_indirect(&mut self, ty_index: u32, table_index: u32) -> &mut Self {
173 self.bytes.push(0x41);
174 ty_index.encode(&mut self.bytes);
175 table_index.encode(&mut self.bytes);
176 self.num_added += 1;
177 self
178 }
179
180 pub fn thread_available_parallelism(&mut self) -> &mut Self {
183 self.bytes.push(0x42);
184 self.num_added += 1;
185 self
186 }
187
188 pub fn backpressure_set(&mut self) -> &mut Self {
193 self.bytes.push(0x08);
194 self.num_added += 1;
195 self
196 }
197
198 pub fn task_return<O>(&mut self, ty: Option<ComponentValType>, options: O) -> &mut Self
202 where
203 O: IntoIterator<Item = CanonicalOption>,
204 O::IntoIter: ExactSizeIterator,
205 {
206 self.bytes.push(0x09);
207 crate::encode_resultlist(&mut self.bytes, ty);
208 self.encode_options(options);
209 self.num_added += 1;
210 self
211 }
212
213 pub fn context_get(&mut self, i: u32) -> &mut Self {
215 self.bytes.push(0x0a);
216 self.bytes.push(0x7f);
217 i.encode(&mut self.bytes);
218 self.num_added += 1;
219 self
220 }
221
222 pub fn context_set(&mut self, i: u32) -> &mut Self {
224 self.bytes.push(0x0b);
225 self.bytes.push(0x7f);
226 i.encode(&mut self.bytes);
227 self.num_added += 1;
228 self
229 }
230
231 pub fn yield_(&mut self, async_: bool) -> &mut Self {
236 self.bytes.push(0x0c);
237 self.bytes.push(if async_ { 1 } else { 0 });
238 self.num_added += 1;
239 self
240 }
241
242 pub fn subtask_drop(&mut self) -> &mut Self {
244 self.bytes.push(0x0d);
245 self.num_added += 1;
246 self
247 }
248
249 pub fn stream_new(&mut self, ty: u32) -> &mut Self {
252 self.bytes.push(0x0e);
253 ty.encode(&mut self.bytes);
254 self.num_added += 1;
255 self
256 }
257
258 pub fn stream_read<O>(&mut self, ty: u32, options: O) -> &mut Self
260 where
261 O: IntoIterator<Item = CanonicalOption>,
262 O::IntoIter: ExactSizeIterator,
263 {
264 self.bytes.push(0x0f);
265 ty.encode(&mut self.bytes);
266 self.encode_options(options);
267 self.num_added += 1;
268 self
269 }
270
271 pub fn stream_write<O>(&mut self, ty: u32, options: O) -> &mut Self
273 where
274 O: IntoIterator<Item = CanonicalOption>,
275 O::IntoIter: ExactSizeIterator,
276 {
277 self.bytes.push(0x10);
278 ty.encode(&mut self.bytes);
279 self.encode_options(options);
280 self.num_added += 1;
281 self
282 }
283
284 pub fn stream_cancel_read(&mut self, ty: u32, async_: bool) -> &mut Self {
287 self.bytes.push(0x11);
288 ty.encode(&mut self.bytes);
289 self.bytes.push(if async_ { 1 } else { 0 });
290 self.num_added += 1;
291 self
292 }
293
294 pub fn stream_cancel_write(&mut self, ty: u32, async_: bool) -> &mut Self {
297 self.bytes.push(0x12);
298 ty.encode(&mut self.bytes);
299 self.bytes.push(if async_ { 1 } else { 0 });
300 self.num_added += 1;
301 self
302 }
303
304 pub fn stream_close_readable(&mut self, ty: u32) -> &mut Self {
307 self.bytes.push(0x13);
308 ty.encode(&mut self.bytes);
309 self.num_added += 1;
310 self
311 }
312
313 pub fn stream_close_writable(&mut self, ty: u32) -> &mut Self {
316 self.bytes.push(0x14);
317 ty.encode(&mut self.bytes);
318 self.num_added += 1;
319 self
320 }
321
322 pub fn future_new(&mut self, ty: u32) -> &mut Self {
325 self.bytes.push(0x15);
326 ty.encode(&mut self.bytes);
327 self.num_added += 1;
328 self
329 }
330
331 pub fn future_read<O>(&mut self, ty: u32, options: O) -> &mut Self
333 where
334 O: IntoIterator<Item = CanonicalOption>,
335 O::IntoIter: ExactSizeIterator,
336 {
337 self.bytes.push(0x16);
338 ty.encode(&mut self.bytes);
339 self.encode_options(options);
340 self.num_added += 1;
341 self
342 }
343
344 pub fn future_write<O>(&mut self, ty: u32, options: O) -> &mut Self
346 where
347 O: IntoIterator<Item = CanonicalOption>,
348 O::IntoIter: ExactSizeIterator,
349 {
350 self.bytes.push(0x17);
351 ty.encode(&mut self.bytes);
352 self.encode_options(options);
353 self.num_added += 1;
354 self
355 }
356
357 pub fn future_cancel_read(&mut self, ty: u32, async_: bool) -> &mut Self {
360 self.bytes.push(0x18);
361 ty.encode(&mut self.bytes);
362 self.bytes.push(if async_ { 1 } else { 0 });
363 self.num_added += 1;
364 self
365 }
366
367 pub fn future_cancel_write(&mut self, ty: u32, async_: bool) -> &mut Self {
370 self.bytes.push(0x19);
371 ty.encode(&mut self.bytes);
372 self.bytes.push(if async_ { 1 } else { 0 });
373 self.num_added += 1;
374 self
375 }
376
377 pub fn future_close_readable(&mut self, ty: u32) -> &mut Self {
380 self.bytes.push(0x1a);
381 ty.encode(&mut self.bytes);
382 self.num_added += 1;
383 self
384 }
385
386 pub fn future_close_writable(&mut self, ty: u32) -> &mut Self {
389 self.bytes.push(0x1b);
390 ty.encode(&mut self.bytes);
391 self.num_added += 1;
392 self
393 }
394
395 pub fn error_context_new<O>(&mut self, options: O) -> &mut Self
398 where
399 O: IntoIterator<Item = CanonicalOption>,
400 O::IntoIter: ExactSizeIterator,
401 {
402 self.bytes.push(0x1c);
403 self.encode_options(options);
404 self.num_added += 1;
405 self
406 }
407
408 pub fn error_context_debug_message<O>(&mut self, options: O) -> &mut Self
414 where
415 O: IntoIterator<Item = CanonicalOption>,
416 O::IntoIter: ExactSizeIterator,
417 {
418 self.bytes.push(0x1d);
419 self.encode_options(options);
420 self.num_added += 1;
421 self
422 }
423
424 pub fn error_context_drop(&mut self) -> &mut Self {
426 self.bytes.push(0x1e);
427 self.num_added += 1;
428 self
429 }
430
431 pub fn waitable_set_new(&mut self) -> &mut Self {
434 self.bytes.push(0x1f);
435 self.num_added += 1;
436 self
437 }
438
439 pub fn waitable_set_wait(&mut self, async_: bool, memory: u32) -> &mut Self {
442 self.bytes.push(0x20);
443 self.bytes.push(if async_ { 1 } else { 0 });
444 memory.encode(&mut self.bytes);
445 self.num_added += 1;
446 self
447 }
448
449 pub fn waitable_set_poll(&mut self, async_: bool, memory: u32) -> &mut Self {
452 self.bytes.push(0x21);
453 self.bytes.push(if async_ { 1 } else { 0 });
454 memory.encode(&mut self.bytes);
455 self.num_added += 1;
456 self
457 }
458
459 pub fn waitable_set_drop(&mut self) -> &mut Self {
462 self.bytes.push(0x22);
463 self.num_added += 1;
464 self
465 }
466
467 pub fn waitable_join(&mut self) -> &mut Self {
470 self.bytes.push(0x23);
471 self.num_added += 1;
472 self
473 }
474
475 fn encode_options<O>(&mut self, options: O) -> &mut Self
476 where
477 O: IntoIterator<Item = CanonicalOption>,
478 O::IntoIter: ExactSizeIterator,
479 {
480 let options = options.into_iter();
481 options.len().encode(&mut self.bytes);
482 for option in options {
483 option.encode(&mut self.bytes);
484 }
485 self
486 }
487}
488
489impl Encode for CanonicalFunctionSection {
490 fn encode(&self, sink: &mut Vec<u8>) {
491 encode_section(sink, self.num_added, &self.bytes);
492 }
493}
494
495impl ComponentSection for CanonicalFunctionSection {
496 fn id(&self) -> u8 {
497 ComponentSectionId::CanonicalFunction.into()
498 }
499}