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_rep(&mut self, ty_index: u32) -> &mut Self {
160 self.bytes.push(0x04);
161 ty_index.encode(&mut self.bytes);
162 self.num_added += 1;
163 self
164 }
165
166 pub fn thread_spawn_ref(&mut self, ty_index: u32) -> &mut Self {
169 self.bytes.push(0x40);
170 ty_index.encode(&mut self.bytes);
171 self.num_added += 1;
172 self
173 }
174
175 pub fn thread_spawn_indirect(&mut self, ty_index: u32, table_index: u32) -> &mut Self {
178 self.bytes.push(0x41);
179 ty_index.encode(&mut self.bytes);
180 table_index.encode(&mut self.bytes);
181 self.num_added += 1;
182 self
183 }
184
185 pub fn thread_available_parallelism(&mut self) -> &mut Self {
188 self.bytes.push(0x42);
189 self.num_added += 1;
190 self
191 }
192
193 pub fn backpressure_inc(&mut self) -> &mut Self {
196 self.bytes.push(0x24);
197 self.num_added += 1;
198 self
199 }
200
201 pub fn backpressure_dec(&mut self) -> &mut Self {
204 self.bytes.push(0x25);
205 self.num_added += 1;
206 self
207 }
208
209 pub fn task_return<O>(&mut self, ty: Option<ComponentValType>, options: O) -> &mut Self
213 where
214 O: IntoIterator<Item = CanonicalOption>,
215 O::IntoIter: ExactSizeIterator,
216 {
217 self.bytes.push(0x09);
218 crate::encode_resultlist(&mut self.bytes, ty);
219 self.encode_options(options);
220 self.num_added += 1;
221 self
222 }
223
224 pub fn task_cancel(&mut self) -> &mut Self {
226 self.bytes.push(0x05);
227 self.num_added += 1;
228 self
229 }
230
231 pub fn context_get(&mut self, ty: ValType, i: u32) -> &mut Self {
234 self.bytes.push(0x0a);
235 ty.encode(&mut self.bytes);
236 i.encode(&mut self.bytes);
237 self.num_added += 1;
238 self
239 }
240
241 pub fn context_set(&mut self, ty: ValType, i: u32) -> &mut Self {
244 self.bytes.push(0x0b);
245 ty.encode(&mut self.bytes);
246 i.encode(&mut self.bytes);
247 self.num_added += 1;
248 self
249 }
250
251 pub fn subtask_drop(&mut self) -> &mut Self {
253 self.bytes.push(0x0d);
254 self.num_added += 1;
255 self
256 }
257
258 pub fn subtask_cancel(&mut self, async_: bool) -> &mut Self {
260 self.bytes.push(0x06);
261 self.bytes.push(if async_ { 1 } else { 0 });
262 self.num_added += 1;
263 self
264 }
265
266 pub fn stream_new(&mut self, ty: u32) -> &mut Self {
269 self.bytes.push(0x0e);
270 ty.encode(&mut self.bytes);
271 self.num_added += 1;
272 self
273 }
274
275 pub fn stream_read<O>(&mut self, ty: u32, options: O) -> &mut Self
277 where
278 O: IntoIterator<Item = CanonicalOption>,
279 O::IntoIter: ExactSizeIterator,
280 {
281 self.bytes.push(0x0f);
282 ty.encode(&mut self.bytes);
283 self.encode_options(options);
284 self.num_added += 1;
285 self
286 }
287
288 pub fn stream_write<O>(&mut self, ty: u32, options: O) -> &mut Self
290 where
291 O: IntoIterator<Item = CanonicalOption>,
292 O::IntoIter: ExactSizeIterator,
293 {
294 self.bytes.push(0x10);
295 ty.encode(&mut self.bytes);
296 self.encode_options(options);
297 self.num_added += 1;
298 self
299 }
300
301 pub fn stream_cancel_read(&mut self, ty: u32, async_: bool) -> &mut Self {
304 self.bytes.push(0x11);
305 ty.encode(&mut self.bytes);
306 self.bytes.push(if async_ { 1 } else { 0 });
307 self.num_added += 1;
308 self
309 }
310
311 pub fn stream_cancel_write(&mut self, ty: u32, async_: bool) -> &mut Self {
314 self.bytes.push(0x12);
315 ty.encode(&mut self.bytes);
316 self.bytes.push(if async_ { 1 } else { 0 });
317 self.num_added += 1;
318 self
319 }
320
321 pub fn stream_drop_readable(&mut self, ty: u32) -> &mut Self {
324 self.bytes.push(0x13);
325 ty.encode(&mut self.bytes);
326 self.num_added += 1;
327 self
328 }
329
330 pub fn stream_drop_writable(&mut self, ty: u32) -> &mut Self {
333 self.bytes.push(0x14);
334 ty.encode(&mut self.bytes);
335 self.num_added += 1;
336 self
337 }
338
339 pub fn future_new(&mut self, ty: u32) -> &mut Self {
342 self.bytes.push(0x15);
343 ty.encode(&mut self.bytes);
344 self.num_added += 1;
345 self
346 }
347
348 pub fn future_read<O>(&mut self, ty: u32, options: O) -> &mut Self
350 where
351 O: IntoIterator<Item = CanonicalOption>,
352 O::IntoIter: ExactSizeIterator,
353 {
354 self.bytes.push(0x16);
355 ty.encode(&mut self.bytes);
356 self.encode_options(options);
357 self.num_added += 1;
358 self
359 }
360
361 pub fn future_write<O>(&mut self, ty: u32, options: O) -> &mut Self
363 where
364 O: IntoIterator<Item = CanonicalOption>,
365 O::IntoIter: ExactSizeIterator,
366 {
367 self.bytes.push(0x17);
368 ty.encode(&mut self.bytes);
369 self.encode_options(options);
370 self.num_added += 1;
371 self
372 }
373
374 pub fn future_cancel_read(&mut self, ty: u32, async_: bool) -> &mut Self {
377 self.bytes.push(0x18);
378 ty.encode(&mut self.bytes);
379 self.bytes.push(if async_ { 1 } else { 0 });
380 self.num_added += 1;
381 self
382 }
383
384 pub fn future_cancel_write(&mut self, ty: u32, async_: bool) -> &mut Self {
387 self.bytes.push(0x19);
388 ty.encode(&mut self.bytes);
389 self.bytes.push(if async_ { 1 } else { 0 });
390 self.num_added += 1;
391 self
392 }
393
394 pub fn future_drop_readable(&mut self, ty: u32) -> &mut Self {
397 self.bytes.push(0x1a);
398 ty.encode(&mut self.bytes);
399 self.num_added += 1;
400 self
401 }
402
403 pub fn future_drop_writable(&mut self, ty: u32) -> &mut Self {
406 self.bytes.push(0x1b);
407 ty.encode(&mut self.bytes);
408 self.num_added += 1;
409 self
410 }
411
412 pub fn error_context_new<O>(&mut self, options: O) -> &mut Self
415 where
416 O: IntoIterator<Item = CanonicalOption>,
417 O::IntoIter: ExactSizeIterator,
418 {
419 self.bytes.push(0x1c);
420 self.encode_options(options);
421 self.num_added += 1;
422 self
423 }
424
425 pub fn error_context_debug_message<O>(&mut self, options: O) -> &mut Self
431 where
432 O: IntoIterator<Item = CanonicalOption>,
433 O::IntoIter: ExactSizeIterator,
434 {
435 self.bytes.push(0x1d);
436 self.encode_options(options);
437 self.num_added += 1;
438 self
439 }
440
441 pub fn error_context_drop(&mut self) -> &mut Self {
443 self.bytes.push(0x1e);
444 self.num_added += 1;
445 self
446 }
447
448 pub fn waitable_set_new(&mut self) -> &mut Self {
451 self.bytes.push(0x1f);
452 self.num_added += 1;
453 self
454 }
455
456 pub fn waitable_set_wait(&mut self, async_: bool, memory: u32) -> &mut Self {
459 self.bytes.push(0x20);
460 self.bytes.push(if async_ { 1 } else { 0 });
461 memory.encode(&mut self.bytes);
462 self.num_added += 1;
463 self
464 }
465
466 pub fn waitable_set_poll(&mut self, async_: bool, memory: u32) -> &mut Self {
469 self.bytes.push(0x21);
470 self.bytes.push(if async_ { 1 } else { 0 });
471 memory.encode(&mut self.bytes);
472 self.num_added += 1;
473 self
474 }
475
476 pub fn waitable_set_drop(&mut self) -> &mut Self {
479 self.bytes.push(0x22);
480 self.num_added += 1;
481 self
482 }
483
484 pub fn waitable_join(&mut self) -> &mut Self {
487 self.bytes.push(0x23);
488 self.num_added += 1;
489 self
490 }
491
492 pub fn thread_index(&mut self) -> &mut Self {
495 self.bytes.push(0x26);
496 self.num_added += 1;
497 self
498 }
499
500 pub fn thread_new_indirect(&mut self, ty_index: u32, table_index: u32) -> &mut Self {
503 self.bytes.push(0x27);
504 ty_index.encode(&mut self.bytes);
505 table_index.encode(&mut self.bytes);
506 self.num_added += 1;
507 self
508 }
509
510 pub fn thread_resume_later(&mut self) -> &mut Self {
512 self.bytes.push(0x28);
513 self.num_added += 1;
514 self
515 }
516
517 pub fn thread_suspend(&mut self, cancellable: bool) -> &mut Self {
519 self.bytes.push(0x29);
520 self.bytes.push(if cancellable { 1 } else { 0 });
521 self.num_added += 1;
522 self
523 }
524
525 pub fn thread_yield(&mut self, cancellable: bool) -> &mut Self {
527 self.bytes.push(0x0c);
528 self.bytes.push(if cancellable { 1 } else { 0 });
529 self.num_added += 1;
530 self
531 }
532
533 pub fn thread_suspend_then_resume(&mut self, cancellable: bool) -> &mut Self {
535 self.bytes.push(0x2a);
536 self.bytes.push(if cancellable { 1 } else { 0 });
537 self.num_added += 1;
538 self
539 }
540
541 pub fn thread_yield_then_resume(&mut self, cancellable: bool) -> &mut Self {
543 self.bytes.push(0x2b);
544 self.bytes.push(if cancellable { 1 } else { 0 });
545 self.num_added += 1;
546 self
547 }
548
549 pub fn thread_suspend_then_promote(&mut self, cancellable: bool) -> &mut Self {
551 self.bytes.push(0x2c);
552 self.bytes.push(if cancellable { 1 } else { 0 });
553 self.num_added += 1;
554 self
555 }
556
557 pub fn thread_yield_then_promote(&mut self, cancellable: bool) -> &mut Self {
559 self.bytes.push(0x2d);
560 self.bytes.push(if cancellable { 1 } else { 0 });
561 self.num_added += 1;
562 self
563 }
564
565 fn encode_options<O>(&mut self, options: O) -> &mut Self
566 where
567 O: IntoIterator<Item = CanonicalOption>,
568 O::IntoIter: ExactSizeIterator,
569 {
570 let options = options.into_iter();
571 options.len().encode(&mut self.bytes);
572 for option in options {
573 option.encode(&mut self.bytes);
574 }
575 self
576 }
577}
578
579impl Encode for CanonicalFunctionSection {
580 fn encode(&self, sink: &mut Vec<u8>) {
581 encode_section(sink, self.num_added, &self.bytes);
582 }
583}
584
585impl ComponentSection for CanonicalFunctionSection {
586 fn id(&self) -> u8 {
587 ComponentSectionId::CanonicalFunction.into()
588 }
589}