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 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 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, i: u32) -> &mut Self {
233 self.bytes.push(0x0a);
234 self.bytes.push(0x7f);
235 i.encode(&mut self.bytes);
236 self.num_added += 1;
237 self
238 }
239
240 pub fn context_set(&mut self, i: u32) -> &mut Self {
242 self.bytes.push(0x0b);
243 self.bytes.push(0x7f);
244 i.encode(&mut self.bytes);
245 self.num_added += 1;
246 self
247 }
248
249 pub fn yield_(&mut self, async_: bool) -> &mut Self {
254 self.bytes.push(0x0c);
255 self.bytes.push(if async_ { 1 } else { 0 });
256 self.num_added += 1;
257 self
258 }
259
260 pub fn subtask_drop(&mut self) -> &mut Self {
262 self.bytes.push(0x0d);
263 self.num_added += 1;
264 self
265 }
266
267 pub fn subtask_cancel(&mut self, async_: bool) -> &mut Self {
269 self.bytes.push(0x06);
270 self.bytes.push(if async_ { 1 } else { 0 });
271 self.num_added += 1;
272 self
273 }
274
275 pub fn stream_new(&mut self, ty: u32) -> &mut Self {
278 self.bytes.push(0x0e);
279 ty.encode(&mut self.bytes);
280 self.num_added += 1;
281 self
282 }
283
284 pub fn stream_read<O>(&mut self, ty: u32, options: O) -> &mut Self
286 where
287 O: IntoIterator<Item = CanonicalOption>,
288 O::IntoIter: ExactSizeIterator,
289 {
290 self.bytes.push(0x0f);
291 ty.encode(&mut self.bytes);
292 self.encode_options(options);
293 self.num_added += 1;
294 self
295 }
296
297 pub fn stream_write<O>(&mut self, ty: u32, options: O) -> &mut Self
299 where
300 O: IntoIterator<Item = CanonicalOption>,
301 O::IntoIter: ExactSizeIterator,
302 {
303 self.bytes.push(0x10);
304 ty.encode(&mut self.bytes);
305 self.encode_options(options);
306 self.num_added += 1;
307 self
308 }
309
310 pub fn stream_cancel_read(&mut self, ty: u32, async_: bool) -> &mut Self {
313 self.bytes.push(0x11);
314 ty.encode(&mut self.bytes);
315 self.bytes.push(if async_ { 1 } else { 0 });
316 self.num_added += 1;
317 self
318 }
319
320 pub fn stream_cancel_write(&mut self, ty: u32, async_: bool) -> &mut Self {
323 self.bytes.push(0x12);
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_close_readable(&mut self, ty: u32) -> &mut Self {
333 self.bytes.push(0x13);
334 ty.encode(&mut self.bytes);
335 self.num_added += 1;
336 self
337 }
338
339 pub fn stream_close_writable(&mut self, ty: u32) -> &mut Self {
342 self.bytes.push(0x14);
343 ty.encode(&mut self.bytes);
344 self.num_added += 1;
345 self
346 }
347
348 pub fn future_new(&mut self, ty: u32) -> &mut Self {
351 self.bytes.push(0x15);
352 ty.encode(&mut self.bytes);
353 self.num_added += 1;
354 self
355 }
356
357 pub fn future_read<O>(&mut self, ty: u32, options: O) -> &mut Self
359 where
360 O: IntoIterator<Item = CanonicalOption>,
361 O::IntoIter: ExactSizeIterator,
362 {
363 self.bytes.push(0x16);
364 ty.encode(&mut self.bytes);
365 self.encode_options(options);
366 self.num_added += 1;
367 self
368 }
369
370 pub fn future_write<O>(&mut self, ty: u32, options: O) -> &mut Self
372 where
373 O: IntoIterator<Item = CanonicalOption>,
374 O::IntoIter: ExactSizeIterator,
375 {
376 self.bytes.push(0x17);
377 ty.encode(&mut self.bytes);
378 self.encode_options(options);
379 self.num_added += 1;
380 self
381 }
382
383 pub fn future_cancel_read(&mut self, ty: u32, async_: bool) -> &mut Self {
386 self.bytes.push(0x18);
387 ty.encode(&mut self.bytes);
388 self.bytes.push(if async_ { 1 } else { 0 });
389 self.num_added += 1;
390 self
391 }
392
393 pub fn future_cancel_write(&mut self, ty: u32, async_: bool) -> &mut Self {
396 self.bytes.push(0x19);
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_close_readable(&mut self, ty: u32) -> &mut Self {
406 self.bytes.push(0x1a);
407 ty.encode(&mut self.bytes);
408 self.num_added += 1;
409 self
410 }
411
412 pub fn future_close_writable(&mut self, ty: u32) -> &mut Self {
415 self.bytes.push(0x1b);
416 ty.encode(&mut self.bytes);
417 self.num_added += 1;
418 self
419 }
420
421 pub fn error_context_new<O>(&mut self, options: O) -> &mut Self
424 where
425 O: IntoIterator<Item = CanonicalOption>,
426 O::IntoIter: ExactSizeIterator,
427 {
428 self.bytes.push(0x1c);
429 self.encode_options(options);
430 self.num_added += 1;
431 self
432 }
433
434 pub fn error_context_debug_message<O>(&mut self, options: O) -> &mut Self
440 where
441 O: IntoIterator<Item = CanonicalOption>,
442 O::IntoIter: ExactSizeIterator,
443 {
444 self.bytes.push(0x1d);
445 self.encode_options(options);
446 self.num_added += 1;
447 self
448 }
449
450 pub fn error_context_drop(&mut self) -> &mut Self {
452 self.bytes.push(0x1e);
453 self.num_added += 1;
454 self
455 }
456
457 pub fn waitable_set_new(&mut self) -> &mut Self {
460 self.bytes.push(0x1f);
461 self.num_added += 1;
462 self
463 }
464
465 pub fn waitable_set_wait(&mut self, async_: bool, memory: u32) -> &mut Self {
468 self.bytes.push(0x20);
469 self.bytes.push(if async_ { 1 } else { 0 });
470 memory.encode(&mut self.bytes);
471 self.num_added += 1;
472 self
473 }
474
475 pub fn waitable_set_poll(&mut self, async_: bool, memory: u32) -> &mut Self {
478 self.bytes.push(0x21);
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_drop(&mut self) -> &mut Self {
488 self.bytes.push(0x22);
489 self.num_added += 1;
490 self
491 }
492
493 pub fn waitable_join(&mut self) -> &mut Self {
496 self.bytes.push(0x23);
497 self.num_added += 1;
498 self
499 }
500
501 fn encode_options<O>(&mut self, options: O) -> &mut Self
502 where
503 O: IntoIterator<Item = CanonicalOption>,
504 O::IntoIter: ExactSizeIterator,
505 {
506 let options = options.into_iter();
507 options.len().encode(&mut self.bytes);
508 for option in options {
509 option.encode(&mut self.bytes);
510 }
511 self
512 }
513}
514
515impl Encode for CanonicalFunctionSection {
516 fn encode(&self, sink: &mut Vec<u8>) {
517 encode_section(sink, self.num_added, &self.bytes);
518 }
519}
520
521impl ComponentSection for CanonicalFunctionSection {
522 fn id(&self) -> u8 {
523 ComponentSectionId::CanonicalFunction.into()
524 }
525}