1use crate::{
2 ComponentSection, ComponentSectionId, ComponentValType, Encode, ValType, encode_section,
3};
4use alloc::vec::Vec;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum CanonicalOption {
9 UTF8,
11 UTF16,
13 CompactUTF16,
15 Memory(u32),
19 Realloc(u32),
24 PostReturn(u32),
27 Async,
29 Callback(u32),
32 CoreType(u32),
34 Gc,
36}
37
38impl Encode for CanonicalOption {
39 fn encode(&self, sink: &mut Vec<u8>) {
40 match self {
41 Self::UTF8 => sink.push(0x00),
42 Self::UTF16 => sink.push(0x01),
43 Self::CompactUTF16 => sink.push(0x02),
44 Self::Memory(idx) => {
45 sink.push(0x03);
46 idx.encode(sink);
47 }
48 Self::Realloc(idx) => {
49 sink.push(0x04);
50 idx.encode(sink);
51 }
52 Self::PostReturn(idx) => {
53 sink.push(0x05);
54 idx.encode(sink);
55 }
56 Self::Async => {
57 sink.push(0x06);
58 }
59 Self::Callback(idx) => {
60 sink.push(0x07);
61 idx.encode(sink);
62 }
63 Self::CoreType(idx) => {
64 sink.push(0x08);
65 idx.encode(sink);
66 }
67 Self::Gc => {
68 sink.push(0x09);
69 }
70 }
71 }
72}
73
74#[derive(Clone, Debug, Default)]
90pub struct CanonicalFunctionSection {
91 bytes: Vec<u8>,
92 num_added: u32,
93}
94
95impl CanonicalFunctionSection {
96 pub fn new() -> Self {
98 Self::default()
99 }
100
101 pub fn len(&self) -> u32 {
103 self.num_added
104 }
105
106 pub fn is_empty(&self) -> bool {
108 self.num_added == 0
109 }
110
111 pub fn lift<O>(&mut self, core_func_index: u32, type_index: u32, options: O) -> &mut Self
113 where
114 O: IntoIterator<Item = CanonicalOption>,
115 O::IntoIter: ExactSizeIterator,
116 {
117 self.bytes.push(0x00);
118 self.bytes.push(0x00);
119 core_func_index.encode(&mut self.bytes);
120 self.encode_options(options);
121 type_index.encode(&mut self.bytes);
122 self.num_added += 1;
123 self
124 }
125
126 pub fn lower<O>(&mut self, func_index: u32, options: O) -> &mut Self
128 where
129 O: IntoIterator<Item = CanonicalOption>,
130 O::IntoIter: ExactSizeIterator,
131 {
132 self.bytes.push(0x01);
133 self.bytes.push(0x00);
134 func_index.encode(&mut self.bytes);
135 self.encode_options(options);
136 self.num_added += 1;
137 self
138 }
139
140 pub fn resource_new(&mut self, ty_index: u32) -> &mut Self {
143 self.bytes.push(0x02);
144 ty_index.encode(&mut self.bytes);
145 self.num_added += 1;
146 self
147 }
148
149 pub fn resource_drop(&mut self, ty_index: u32) -> &mut Self {
151 self.bytes.push(0x03);
152 ty_index.encode(&mut self.bytes);
153 self.num_added += 1;
154 self
155 }
156
157 pub fn resource_drop_async(&mut self, ty_index: u32) -> &mut Self {
159 self.bytes.push(0x07);
160 ty_index.encode(&mut self.bytes);
161 self.num_added += 1;
162 self
163 }
164
165 pub fn resource_rep(&mut self, ty_index: u32) -> &mut Self {
168 self.bytes.push(0x04);
169 ty_index.encode(&mut self.bytes);
170 self.num_added += 1;
171 self
172 }
173
174 pub fn thread_spawn_ref(&mut self, ty_index: u32) -> &mut Self {
177 self.bytes.push(0x40);
178 ty_index.encode(&mut self.bytes);
179 self.num_added += 1;
180 self
181 }
182
183 pub fn thread_spawn_indirect(&mut self, ty_index: u32, table_index: u32) -> &mut Self {
186 self.bytes.push(0x41);
187 ty_index.encode(&mut self.bytes);
188 table_index.encode(&mut self.bytes);
189 self.num_added += 1;
190 self
191 }
192
193 pub fn thread_available_parallelism(&mut self) -> &mut Self {
196 self.bytes.push(0x42);
197 self.num_added += 1;
198 self
199 }
200
201 pub fn backpressure_inc(&mut self) -> &mut Self {
204 self.bytes.push(0x24);
205 self.num_added += 1;
206 self
207 }
208
209 pub fn backpressure_dec(&mut self) -> &mut Self {
212 self.bytes.push(0x25);
213 self.num_added += 1;
214 self
215 }
216
217 pub fn task_return<O>(&mut self, ty: Option<ComponentValType>, options: O) -> &mut Self
221 where
222 O: IntoIterator<Item = CanonicalOption>,
223 O::IntoIter: ExactSizeIterator,
224 {
225 self.bytes.push(0x09);
226 crate::encode_resultlist(&mut self.bytes, ty);
227 self.encode_options(options);
228 self.num_added += 1;
229 self
230 }
231
232 pub fn task_cancel(&mut self) -> &mut Self {
234 self.bytes.push(0x05);
235 self.num_added += 1;
236 self
237 }
238
239 pub fn context_get(&mut self, ty: ValType, i: u32) -> &mut Self {
242 self.bytes.push(0x0a);
243 ty.encode(&mut self.bytes);
244 i.encode(&mut self.bytes);
245 self.num_added += 1;
246 self
247 }
248
249 pub fn context_set(&mut self, ty: ValType, i: u32) -> &mut Self {
252 self.bytes.push(0x0b);
253 ty.encode(&mut self.bytes);
254 i.encode(&mut self.bytes);
255 self.num_added += 1;
256 self
257 }
258
259 pub fn thread_yield(&mut self, cancellable: bool) -> &mut Self {
264 self.bytes.push(0x0c);
265 self.bytes.push(if cancellable { 1 } else { 0 });
266 self.num_added += 1;
267 self
268 }
269
270 pub fn subtask_drop(&mut self) -> &mut Self {
272 self.bytes.push(0x0d);
273 self.num_added += 1;
274 self
275 }
276
277 pub fn subtask_cancel(&mut self, async_: bool) -> &mut Self {
279 self.bytes.push(0x06);
280 self.bytes.push(if async_ { 1 } else { 0 });
281 self.num_added += 1;
282 self
283 }
284
285 pub fn stream_new(&mut self, ty: u32) -> &mut Self {
288 self.bytes.push(0x0e);
289 ty.encode(&mut self.bytes);
290 self.num_added += 1;
291 self
292 }
293
294 pub fn stream_read<O>(&mut self, ty: u32, options: O) -> &mut Self
296 where
297 O: IntoIterator<Item = CanonicalOption>,
298 O::IntoIter: ExactSizeIterator,
299 {
300 self.bytes.push(0x0f);
301 ty.encode(&mut self.bytes);
302 self.encode_options(options);
303 self.num_added += 1;
304 self
305 }
306
307 pub fn stream_write<O>(&mut self, ty: u32, options: O) -> &mut Self
309 where
310 O: IntoIterator<Item = CanonicalOption>,
311 O::IntoIter: ExactSizeIterator,
312 {
313 self.bytes.push(0x10);
314 ty.encode(&mut self.bytes);
315 self.encode_options(options);
316 self.num_added += 1;
317 self
318 }
319
320 pub fn stream_cancel_read(&mut self, ty: u32, async_: bool) -> &mut Self {
323 self.bytes.push(0x11);
324 ty.encode(&mut self.bytes);
325 self.bytes.push(if async_ { 1 } else { 0 });
326 self.num_added += 1;
327 self
328 }
329
330 pub fn stream_cancel_write(&mut self, ty: u32, async_: bool) -> &mut Self {
333 self.bytes.push(0x12);
334 ty.encode(&mut self.bytes);
335 self.bytes.push(if async_ { 1 } else { 0 });
336 self.num_added += 1;
337 self
338 }
339
340 pub fn stream_drop_readable(&mut self, ty: u32) -> &mut Self {
343 self.bytes.push(0x13);
344 ty.encode(&mut self.bytes);
345 self.num_added += 1;
346 self
347 }
348
349 pub fn stream_drop_writable(&mut self, ty: u32) -> &mut Self {
352 self.bytes.push(0x14);
353 ty.encode(&mut self.bytes);
354 self.num_added += 1;
355 self
356 }
357
358 pub fn future_new(&mut self, ty: u32) -> &mut Self {
361 self.bytes.push(0x15);
362 ty.encode(&mut self.bytes);
363 self.num_added += 1;
364 self
365 }
366
367 pub fn future_read<O>(&mut self, ty: u32, options: O) -> &mut Self
369 where
370 O: IntoIterator<Item = CanonicalOption>,
371 O::IntoIter: ExactSizeIterator,
372 {
373 self.bytes.push(0x16);
374 ty.encode(&mut self.bytes);
375 self.encode_options(options);
376 self.num_added += 1;
377 self
378 }
379
380 pub fn future_write<O>(&mut self, ty: u32, options: O) -> &mut Self
382 where
383 O: IntoIterator<Item = CanonicalOption>,
384 O::IntoIter: ExactSizeIterator,
385 {
386 self.bytes.push(0x17);
387 ty.encode(&mut self.bytes);
388 self.encode_options(options);
389 self.num_added += 1;
390 self
391 }
392
393 pub fn future_cancel_read(&mut self, ty: u32, async_: bool) -> &mut Self {
396 self.bytes.push(0x18);
397 ty.encode(&mut self.bytes);
398 self.bytes.push(if async_ { 1 } else { 0 });
399 self.num_added += 1;
400 self
401 }
402
403 pub fn future_cancel_write(&mut self, ty: u32, async_: bool) -> &mut Self {
406 self.bytes.push(0x19);
407 ty.encode(&mut self.bytes);
408 self.bytes.push(if async_ { 1 } else { 0 });
409 self.num_added += 1;
410 self
411 }
412
413 pub fn future_drop_readable(&mut self, ty: u32) -> &mut Self {
416 self.bytes.push(0x1a);
417 ty.encode(&mut self.bytes);
418 self.num_added += 1;
419 self
420 }
421
422 pub fn future_drop_writable(&mut self, ty: u32) -> &mut Self {
425 self.bytes.push(0x1b);
426 ty.encode(&mut self.bytes);
427 self.num_added += 1;
428 self
429 }
430
431 pub fn error_context_new<O>(&mut self, options: O) -> &mut Self
434 where
435 O: IntoIterator<Item = CanonicalOption>,
436 O::IntoIter: ExactSizeIterator,
437 {
438 self.bytes.push(0x1c);
439 self.encode_options(options);
440 self.num_added += 1;
441 self
442 }
443
444 pub fn error_context_debug_message<O>(&mut self, options: O) -> &mut Self
450 where
451 O: IntoIterator<Item = CanonicalOption>,
452 O::IntoIter: ExactSizeIterator,
453 {
454 self.bytes.push(0x1d);
455 self.encode_options(options);
456 self.num_added += 1;
457 self
458 }
459
460 pub fn error_context_drop(&mut self) -> &mut Self {
462 self.bytes.push(0x1e);
463 self.num_added += 1;
464 self
465 }
466
467 pub fn waitable_set_new(&mut self) -> &mut Self {
470 self.bytes.push(0x1f);
471 self.num_added += 1;
472 self
473 }
474
475 pub fn waitable_set_wait(&mut self, async_: bool, memory: u32) -> &mut Self {
478 self.bytes.push(0x20);
479 self.bytes.push(if async_ { 1 } else { 0 });
480 memory.encode(&mut self.bytes);
481 self.num_added += 1;
482 self
483 }
484
485 pub fn waitable_set_poll(&mut self, async_: bool, memory: u32) -> &mut Self {
488 self.bytes.push(0x21);
489 self.bytes.push(if async_ { 1 } else { 0 });
490 memory.encode(&mut self.bytes);
491 self.num_added += 1;
492 self
493 }
494
495 pub fn waitable_set_drop(&mut self) -> &mut Self {
498 self.bytes.push(0x22);
499 self.num_added += 1;
500 self
501 }
502
503 pub fn waitable_join(&mut self) -> &mut Self {
506 self.bytes.push(0x23);
507 self.num_added += 1;
508 self
509 }
510
511 pub fn thread_index(&mut self) -> &mut Self {
514 self.bytes.push(0x26);
515 self.num_added += 1;
516 self
517 }
518
519 pub fn thread_new_indirect(&mut self, ty_index: u32, table_index: u32) -> &mut Self {
522 self.bytes.push(0x27);
523 ty_index.encode(&mut self.bytes);
524 table_index.encode(&mut self.bytes);
525 self.num_added += 1;
526 self
527 }
528
529 pub fn thread_suspend_to_suspended(&mut self, cancellable: bool) -> &mut Self {
532 self.bytes.push(0x28);
533 self.bytes.push(if cancellable { 1 } else { 0 });
534 self.num_added += 1;
535 self
536 }
537
538 pub fn thread_suspend(&mut self, cancellable: bool) -> &mut Self {
541 self.bytes.push(0x29);
542 self.bytes.push(if cancellable { 1 } else { 0 });
543 self.num_added += 1;
544 self
545 }
546
547 pub fn thread_suspend_to(&mut self, cancellable: bool) -> &mut Self {
550 self.bytes.push(0x2c);
551 self.bytes.push(if cancellable { 1 } else { 0 });
552 self.num_added += 1;
553 self
554 }
555
556 pub fn thread_unsuspend(&mut self) -> &mut Self {
559 self.bytes.push(0x2a);
560 self.num_added += 1;
561 self
562 }
563
564 pub fn thread_yield_to_suspended(&mut self, cancellable: bool) -> &mut Self {
567 self.bytes.push(0x2b);
568 self.bytes.push(if cancellable { 1 } else { 0 });
569 self.num_added += 1;
570 self
571 }
572
573 fn encode_options<O>(&mut self, options: O) -> &mut Self
574 where
575 O: IntoIterator<Item = CanonicalOption>,
576 O::IntoIter: ExactSizeIterator,
577 {
578 let options = options.into_iter();
579 options.len().encode(&mut self.bytes);
580 for option in options {
581 option.encode(&mut self.bytes);
582 }
583 self
584 }
585}
586
587impl Encode for CanonicalFunctionSection {
588 fn encode(&self, sink: &mut Vec<u8>) {
589 encode_section(sink, self.num_added, &self.bytes);
590 }
591}
592
593impl ComponentSection for CanonicalFunctionSection {
594 fn id(&self) -> u8 {
595 ComponentSectionId::CanonicalFunction.into()
596 }
597}