1use crate::{ComponentSection, ComponentSectionId, ComponentValType, Encode, encode_section};
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 CoreType(u32),
32 Gc,
34}
35
36impl Encode for CanonicalOption {
37 fn encode(&self, sink: &mut Vec<u8>) {
38 match self {
39 Self::UTF8 => sink.push(0x00),
40 Self::UTF16 => sink.push(0x01),
41 Self::CompactUTF16 => sink.push(0x02),
42 Self::Memory(idx) => {
43 sink.push(0x03);
44 idx.encode(sink);
45 }
46 Self::Realloc(idx) => {
47 sink.push(0x04);
48 idx.encode(sink);
49 }
50 Self::PostReturn(idx) => {
51 sink.push(0x05);
52 idx.encode(sink);
53 }
54 Self::Async => {
55 sink.push(0x06);
56 }
57 Self::Callback(idx) => {
58 sink.push(0x07);
59 idx.encode(sink);
60 }
61 Self::CoreType(idx) => {
62 sink.push(0x08);
63 idx.encode(sink);
64 }
65 Self::Gc => {
66 sink.push(0x09);
67 }
68 }
69 }
70}
71
72#[derive(Clone, Debug, Default)]
88pub struct CanonicalFunctionSection {
89 bytes: Vec<u8>,
90 num_added: u32,
91}
92
93impl CanonicalFunctionSection {
94 pub fn new() -> Self {
96 Self::default()
97 }
98
99 pub fn len(&self) -> u32 {
101 self.num_added
102 }
103
104 pub fn is_empty(&self) -> bool {
106 self.num_added == 0
107 }
108
109 pub fn lift<O>(&mut self, core_func_index: u32, type_index: u32, options: O) -> &mut Self
111 where
112 O: IntoIterator<Item = CanonicalOption>,
113 O::IntoIter: ExactSizeIterator,
114 {
115 self.bytes.push(0x00);
116 self.bytes.push(0x00);
117 core_func_index.encode(&mut self.bytes);
118 self.encode_options(options);
119 type_index.encode(&mut self.bytes);
120 self.num_added += 1;
121 self
122 }
123
124 pub fn lower<O>(&mut self, func_index: u32, options: O) -> &mut Self
126 where
127 O: IntoIterator<Item = CanonicalOption>,
128 O::IntoIter: ExactSizeIterator,
129 {
130 self.bytes.push(0x01);
131 self.bytes.push(0x00);
132 func_index.encode(&mut self.bytes);
133 self.encode_options(options);
134 self.num_added += 1;
135 self
136 }
137
138 pub fn resource_new(&mut self, ty_index: u32) -> &mut Self {
141 self.bytes.push(0x02);
142 ty_index.encode(&mut self.bytes);
143 self.num_added += 1;
144 self
145 }
146
147 pub fn resource_drop(&mut self, ty_index: u32) -> &mut Self {
149 self.bytes.push(0x03);
150 ty_index.encode(&mut self.bytes);
151 self.num_added += 1;
152 self
153 }
154
155 pub fn resource_drop_async(&mut self, ty_index: u32) -> &mut Self {
157 self.bytes.push(0x07);
158 ty_index.encode(&mut self.bytes);
159 self.num_added += 1;
160 self
161 }
162
163 pub fn resource_rep(&mut self, ty_index: u32) -> &mut Self {
166 self.bytes.push(0x04);
167 ty_index.encode(&mut self.bytes);
168 self.num_added += 1;
169 self
170 }
171
172 pub fn thread_spawn_ref(&mut self, ty_index: u32) -> &mut Self {
175 self.bytes.push(0x40);
176 ty_index.encode(&mut self.bytes);
177 self.num_added += 1;
178 self
179 }
180
181 pub fn thread_spawn_indirect(&mut self, ty_index: u32, table_index: u32) -> &mut Self {
184 self.bytes.push(0x41);
185 ty_index.encode(&mut self.bytes);
186 table_index.encode(&mut self.bytes);
187 self.num_added += 1;
188 self
189 }
190
191 pub fn thread_available_parallelism(&mut self) -> &mut Self {
194 self.bytes.push(0x42);
195 self.num_added += 1;
196 self
197 }
198
199 pub fn backpressure_set(&mut self) -> &mut Self {
204 self.bytes.push(0x08);
205 self.num_added += 1;
206 self
207 }
208
209 pub fn backpressure_inc(&mut self) -> &mut Self {
212 self.bytes.push(0x24);
213 self.num_added += 1;
214 self
215 }
216
217 pub fn backpressure_dec(&mut self) -> &mut Self {
220 self.bytes.push(0x25);
221 self.num_added += 1;
222 self
223 }
224
225 pub fn task_return<O>(&mut self, ty: Option<ComponentValType>, options: O) -> &mut Self
229 where
230 O: IntoIterator<Item = CanonicalOption>,
231 O::IntoIter: ExactSizeIterator,
232 {
233 self.bytes.push(0x09);
234 crate::encode_resultlist(&mut self.bytes, ty);
235 self.encode_options(options);
236 self.num_added += 1;
237 self
238 }
239
240 pub fn task_cancel(&mut self) -> &mut Self {
242 self.bytes.push(0x05);
243 self.num_added += 1;
244 self
245 }
246
247 pub fn context_get(&mut self, i: u32) -> &mut Self {
249 self.bytes.push(0x0a);
250 self.bytes.push(0x7f);
251 i.encode(&mut self.bytes);
252 self.num_added += 1;
253 self
254 }
255
256 pub fn context_set(&mut self, i: u32) -> &mut Self {
258 self.bytes.push(0x0b);
259 self.bytes.push(0x7f);
260 i.encode(&mut self.bytes);
261 self.num_added += 1;
262 self
263 }
264
265 pub fn thread_yield(&mut self, cancellable: bool) -> &mut Self {
270 self.bytes.push(0x0c);
271 self.bytes.push(if cancellable { 1 } else { 0 });
272 self.num_added += 1;
273 self
274 }
275
276 pub fn subtask_drop(&mut self) -> &mut Self {
278 self.bytes.push(0x0d);
279 self.num_added += 1;
280 self
281 }
282
283 pub fn subtask_cancel(&mut self, async_: bool) -> &mut Self {
285 self.bytes.push(0x06);
286 self.bytes.push(if async_ { 1 } else { 0 });
287 self.num_added += 1;
288 self
289 }
290
291 pub fn stream_new(&mut self, ty: u32) -> &mut Self {
294 self.bytes.push(0x0e);
295 ty.encode(&mut self.bytes);
296 self.num_added += 1;
297 self
298 }
299
300 pub fn stream_read<O>(&mut self, ty: u32, options: O) -> &mut Self
302 where
303 O: IntoIterator<Item = CanonicalOption>,
304 O::IntoIter: ExactSizeIterator,
305 {
306 self.bytes.push(0x0f);
307 ty.encode(&mut self.bytes);
308 self.encode_options(options);
309 self.num_added += 1;
310 self
311 }
312
313 pub fn stream_write<O>(&mut self, ty: u32, options: O) -> &mut Self
315 where
316 O: IntoIterator<Item = CanonicalOption>,
317 O::IntoIter: ExactSizeIterator,
318 {
319 self.bytes.push(0x10);
320 ty.encode(&mut self.bytes);
321 self.encode_options(options);
322 self.num_added += 1;
323 self
324 }
325
326 pub fn stream_cancel_read(&mut self, ty: u32, async_: bool) -> &mut Self {
329 self.bytes.push(0x11);
330 ty.encode(&mut self.bytes);
331 self.bytes.push(if async_ { 1 } else { 0 });
332 self.num_added += 1;
333 self
334 }
335
336 pub fn stream_cancel_write(&mut self, ty: u32, async_: bool) -> &mut Self {
339 self.bytes.push(0x12);
340 ty.encode(&mut self.bytes);
341 self.bytes.push(if async_ { 1 } else { 0 });
342 self.num_added += 1;
343 self
344 }
345
346 pub fn stream_drop_readable(&mut self, ty: u32) -> &mut Self {
349 self.bytes.push(0x13);
350 ty.encode(&mut self.bytes);
351 self.num_added += 1;
352 self
353 }
354
355 pub fn stream_drop_writable(&mut self, ty: u32) -> &mut Self {
358 self.bytes.push(0x14);
359 ty.encode(&mut self.bytes);
360 self.num_added += 1;
361 self
362 }
363
364 pub fn future_new(&mut self, ty: u32) -> &mut Self {
367 self.bytes.push(0x15);
368 ty.encode(&mut self.bytes);
369 self.num_added += 1;
370 self
371 }
372
373 pub fn future_read<O>(&mut self, ty: u32, options: O) -> &mut Self
375 where
376 O: IntoIterator<Item = CanonicalOption>,
377 O::IntoIter: ExactSizeIterator,
378 {
379 self.bytes.push(0x16);
380 ty.encode(&mut self.bytes);
381 self.encode_options(options);
382 self.num_added += 1;
383 self
384 }
385
386 pub fn future_write<O>(&mut self, ty: u32, options: O) -> &mut Self
388 where
389 O: IntoIterator<Item = CanonicalOption>,
390 O::IntoIter: ExactSizeIterator,
391 {
392 self.bytes.push(0x17);
393 ty.encode(&mut self.bytes);
394 self.encode_options(options);
395 self.num_added += 1;
396 self
397 }
398
399 pub fn future_cancel_read(&mut self, ty: u32, async_: bool) -> &mut Self {
402 self.bytes.push(0x18);
403 ty.encode(&mut self.bytes);
404 self.bytes.push(if async_ { 1 } else { 0 });
405 self.num_added += 1;
406 self
407 }
408
409 pub fn future_cancel_write(&mut self, ty: u32, async_: bool) -> &mut Self {
412 self.bytes.push(0x19);
413 ty.encode(&mut self.bytes);
414 self.bytes.push(if async_ { 1 } else { 0 });
415 self.num_added += 1;
416 self
417 }
418
419 pub fn future_drop_readable(&mut self, ty: u32) -> &mut Self {
422 self.bytes.push(0x1a);
423 ty.encode(&mut self.bytes);
424 self.num_added += 1;
425 self
426 }
427
428 pub fn future_drop_writable(&mut self, ty: u32) -> &mut Self {
431 self.bytes.push(0x1b);
432 ty.encode(&mut self.bytes);
433 self.num_added += 1;
434 self
435 }
436
437 pub fn error_context_new<O>(&mut self, options: O) -> &mut Self
440 where
441 O: IntoIterator<Item = CanonicalOption>,
442 O::IntoIter: ExactSizeIterator,
443 {
444 self.bytes.push(0x1c);
445 self.encode_options(options);
446 self.num_added += 1;
447 self
448 }
449
450 pub fn error_context_debug_message<O>(&mut self, options: O) -> &mut Self
456 where
457 O: IntoIterator<Item = CanonicalOption>,
458 O::IntoIter: ExactSizeIterator,
459 {
460 self.bytes.push(0x1d);
461 self.encode_options(options);
462 self.num_added += 1;
463 self
464 }
465
466 pub fn error_context_drop(&mut self) -> &mut Self {
468 self.bytes.push(0x1e);
469 self.num_added += 1;
470 self
471 }
472
473 pub fn waitable_set_new(&mut self) -> &mut Self {
476 self.bytes.push(0x1f);
477 self.num_added += 1;
478 self
479 }
480
481 pub fn waitable_set_wait(&mut self, async_: bool, memory: u32) -> &mut Self {
484 self.bytes.push(0x20);
485 self.bytes.push(if async_ { 1 } else { 0 });
486 memory.encode(&mut self.bytes);
487 self.num_added += 1;
488 self
489 }
490
491 pub fn waitable_set_poll(&mut self, async_: bool, memory: u32) -> &mut Self {
494 self.bytes.push(0x21);
495 self.bytes.push(if async_ { 1 } else { 0 });
496 memory.encode(&mut self.bytes);
497 self.num_added += 1;
498 self
499 }
500
501 pub fn waitable_set_drop(&mut self) -> &mut Self {
504 self.bytes.push(0x22);
505 self.num_added += 1;
506 self
507 }
508
509 pub fn waitable_join(&mut self) -> &mut Self {
512 self.bytes.push(0x23);
513 self.num_added += 1;
514 self
515 }
516
517 pub fn thread_index(&mut self) -> &mut Self {
520 self.bytes.push(0x26);
521 self.num_added += 1;
522 self
523 }
524
525 pub fn thread_new_indirect(&mut self, ty_index: u32, table_index: u32) -> &mut Self {
528 self.bytes.push(0x27);
529 ty_index.encode(&mut self.bytes);
530 table_index.encode(&mut self.bytes);
531 self.num_added += 1;
532 self
533 }
534
535 pub fn thread_switch_to(&mut self, cancellable: bool) -> &mut Self {
538 self.bytes.push(0x28);
539 self.bytes.push(if cancellable { 1 } else { 0 });
540 self.num_added += 1;
541 self
542 }
543
544 pub fn thread_suspend(&mut self, cancellable: bool) -> &mut Self {
547 self.bytes.push(0x29);
548 self.bytes.push(if cancellable { 1 } else { 0 });
549 self.num_added += 1;
550 self
551 }
552
553 pub fn thread_resume_later(&mut self) -> &mut Self {
556 self.bytes.push(0x2a);
557 self.num_added += 1;
558 self
559 }
560
561 pub fn thread_yield_to(&mut self, cancellable: bool) -> &mut Self {
564 self.bytes.push(0x2b);
565 self.bytes.push(if cancellable { 1 } else { 0 });
566 self.num_added += 1;
567 self
568 }
569
570 fn encode_options<O>(&mut self, options: O) -> &mut Self
571 where
572 O: IntoIterator<Item = CanonicalOption>,
573 O::IntoIter: ExactSizeIterator,
574 {
575 let options = options.into_iter();
576 options.len().encode(&mut self.bytes);
577 for option in options {
578 option.encode(&mut self.bytes);
579 }
580 self
581 }
582}
583
584impl Encode for CanonicalFunctionSection {
585 fn encode(&self, sink: &mut Vec<u8>) {
586 encode_section(sink, self.num_added, &self.bytes);
587 }
588}
589
590impl ComponentSection for CanonicalFunctionSection {
591 fn id(&self) -> u8 {
592 ComponentSectionId::CanonicalFunction.into()
593 }
594}