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_forward(&mut self, ty: u32) -> &mut Self {
305 self.bytes.push(0x2e);
306 ty.encode(&mut self.bytes);
307 self.num_added += 1;
308 self
309 }
310
311 pub fn stream_cancel_read(&mut self, ty: u32, async_: bool) -> &mut Self {
314 self.bytes.push(0x11);
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_cancel_write(&mut self, ty: u32, async_: bool) -> &mut Self {
324 self.bytes.push(0x12);
325 ty.encode(&mut self.bytes);
326 self.bytes.push(if async_ { 1 } else { 0 });
327 self.num_added += 1;
328 self
329 }
330
331 pub fn stream_drop_readable(&mut self, ty: u32) -> &mut Self {
334 self.bytes.push(0x13);
335 ty.encode(&mut self.bytes);
336 self.num_added += 1;
337 self
338 }
339
340 pub fn stream_drop_writable(&mut self, ty: u32) -> &mut Self {
343 self.bytes.push(0x14);
344 ty.encode(&mut self.bytes);
345 self.num_added += 1;
346 self
347 }
348
349 pub fn future_new(&mut self, ty: u32) -> &mut Self {
352 self.bytes.push(0x15);
353 ty.encode(&mut self.bytes);
354 self.num_added += 1;
355 self
356 }
357
358 pub fn future_read<O>(&mut self, ty: u32, options: O) -> &mut Self
360 where
361 O: IntoIterator<Item = CanonicalOption>,
362 O::IntoIter: ExactSizeIterator,
363 {
364 self.bytes.push(0x16);
365 ty.encode(&mut self.bytes);
366 self.encode_options(options);
367 self.num_added += 1;
368 self
369 }
370
371 pub fn future_write<O>(&mut self, ty: u32, options: O) -> &mut Self
373 where
374 O: IntoIterator<Item = CanonicalOption>,
375 O::IntoIter: ExactSizeIterator,
376 {
377 self.bytes.push(0x17);
378 ty.encode(&mut self.bytes);
379 self.encode_options(options);
380 self.num_added += 1;
381 self
382 }
383
384 pub fn future_forward(&mut self, ty: u32) -> &mut Self {
388 self.bytes.push(0x2f);
389 ty.encode(&mut self.bytes);
390 self.num_added += 1;
391 self
392 }
393
394 pub fn future_cancel_read(&mut self, ty: u32, async_: bool) -> &mut Self {
397 self.bytes.push(0x18);
398 ty.encode(&mut self.bytes);
399 self.bytes.push(if async_ { 1 } else { 0 });
400 self.num_added += 1;
401 self
402 }
403
404 pub fn future_cancel_write(&mut self, ty: u32, async_: bool) -> &mut Self {
407 self.bytes.push(0x19);
408 ty.encode(&mut self.bytes);
409 self.bytes.push(if async_ { 1 } else { 0 });
410 self.num_added += 1;
411 self
412 }
413
414 pub fn future_drop_readable(&mut self, ty: u32) -> &mut Self {
417 self.bytes.push(0x1a);
418 ty.encode(&mut self.bytes);
419 self.num_added += 1;
420 self
421 }
422
423 pub fn future_drop_writable(&mut self, ty: u32) -> &mut Self {
426 self.bytes.push(0x1b);
427 ty.encode(&mut self.bytes);
428 self.num_added += 1;
429 self
430 }
431
432 pub fn error_context_new<O>(&mut self, options: O) -> &mut Self
435 where
436 O: IntoIterator<Item = CanonicalOption>,
437 O::IntoIter: ExactSizeIterator,
438 {
439 self.bytes.push(0x1c);
440 self.encode_options(options);
441 self.num_added += 1;
442 self
443 }
444
445 pub fn error_context_debug_message<O>(&mut self, options: O) -> &mut Self
451 where
452 O: IntoIterator<Item = CanonicalOption>,
453 O::IntoIter: ExactSizeIterator,
454 {
455 self.bytes.push(0x1d);
456 self.encode_options(options);
457 self.num_added += 1;
458 self
459 }
460
461 pub fn error_context_drop(&mut self) -> &mut Self {
463 self.bytes.push(0x1e);
464 self.num_added += 1;
465 self
466 }
467
468 pub fn waitable_set_new(&mut self) -> &mut Self {
471 self.bytes.push(0x1f);
472 self.num_added += 1;
473 self
474 }
475
476 pub fn waitable_set_wait(&mut self, memory: u32) -> &mut Self {
479 self.bytes.push(0x20);
480 self.bytes.push(0);
481 memory.encode(&mut self.bytes);
482 self.num_added += 1;
483 self
484 }
485
486 pub fn waitable_set_poll(&mut self, memory: u32) -> &mut Self {
489 self.bytes.push(0x21);
490 self.bytes.push(0);
491 memory.encode(&mut self.bytes);
492 self.num_added += 1;
493 self
494 }
495
496 pub fn waitable_set_drop(&mut self) -> &mut Self {
499 self.bytes.push(0x22);
500 self.num_added += 1;
501 self
502 }
503
504 pub fn waitable_join(&mut self) -> &mut Self {
507 self.bytes.push(0x23);
508 self.num_added += 1;
509 self
510 }
511
512 pub fn thread_index(&mut self) -> &mut Self {
515 self.bytes.push(0x26);
516 self.num_added += 1;
517 self
518 }
519
520 pub fn thread_new_indirect(&mut self, ty_index: u32, table_index: u32) -> &mut Self {
523 self.bytes.push(0x27);
524 ty_index.encode(&mut self.bytes);
525 table_index.encode(&mut self.bytes);
526 self.num_added += 1;
527 self
528 }
529
530 pub fn thread_resume_later(&mut self) -> &mut Self {
532 self.bytes.push(0x28);
533 self.num_added += 1;
534 self
535 }
536
537 pub fn thread_suspend(&mut self) -> &mut Self {
539 self.bytes.push(0x29);
540 self.bytes.push(0);
541 self.num_added += 1;
542 self
543 }
544
545 pub fn thread_yield(&mut self) -> &mut Self {
547 self.bytes.push(0x0c);
548 self.bytes.push(0);
549 self.num_added += 1;
550 self
551 }
552
553 pub fn thread_suspend_then_resume(&mut self) -> &mut Self {
555 self.bytes.push(0x2a);
556 self.bytes.push(0);
557 self.num_added += 1;
558 self
559 }
560
561 pub fn thread_yield_then_resume(&mut self) -> &mut Self {
563 self.bytes.push(0x2b);
564 self.bytes.push(0);
565 self.num_added += 1;
566 self
567 }
568
569 pub fn thread_suspend_then_promote(&mut self) -> &mut Self {
571 self.bytes.push(0x2c);
572 self.bytes.push(0);
573 self.num_added += 1;
574 self
575 }
576
577 pub fn thread_yield_then_promote(&mut self) -> &mut Self {
579 self.bytes.push(0x2d);
580 self.bytes.push(0);
581 self.num_added += 1;
582 self
583 }
584
585 fn encode_options<O>(&mut self, options: O) -> &mut Self
586 where
587 O: IntoIterator<Item = CanonicalOption>,
588 O::IntoIter: ExactSizeIterator,
589 {
590 let options = options.into_iter();
591 options.len().encode(&mut self.bytes);
592 for option in options {
593 option.encode(&mut self.bytes);
594 }
595 self
596 }
597}
598
599impl Encode for CanonicalFunctionSection {
600 fn encode(&self, sink: &mut Vec<u8>) {
601 encode_section(sink, self.num_added, &self.bytes);
602 }
603}
604
605impl ComponentSection for CanonicalFunctionSection {
606 fn id(&self) -> u8 {
607 ComponentSectionId::CanonicalFunction.into()
608 }
609}