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}
33
34impl Encode for CanonicalOption {
35 fn encode(&self, sink: &mut Vec<u8>) {
36 match self {
37 Self::UTF8 => sink.push(0x00),
38 Self::UTF16 => sink.push(0x01),
39 Self::CompactUTF16 => sink.push(0x02),
40 Self::Memory(idx) => {
41 sink.push(0x03);
42 idx.encode(sink);
43 }
44 Self::Realloc(idx) => {
45 sink.push(0x04);
46 idx.encode(sink);
47 }
48 Self::PostReturn(idx) => {
49 sink.push(0x05);
50 idx.encode(sink);
51 }
52 Self::Async => {
53 sink.push(0x06);
54 }
55 Self::Callback(idx) => {
56 sink.push(0x07);
57 idx.encode(sink);
58 }
59 Self::CoreType(idx) => {
60 sink.push(0x08);
61 idx.encode(sink);
62 }
63 }
64 }
65}
66
67#[derive(Clone, Debug, Default)]
83pub struct CanonicalFunctionSection {
84 bytes: Vec<u8>,
85 num_added: u32,
86}
87
88impl CanonicalFunctionSection {
89 pub fn new() -> Self {
91 Self::default()
92 }
93
94 pub fn len(&self) -> u32 {
96 self.num_added
97 }
98
99 pub fn is_empty(&self) -> bool {
101 self.num_added == 0
102 }
103
104 pub fn lift<O>(&mut self, core_func_index: u32, type_index: u32, options: O) -> &mut Self
106 where
107 O: IntoIterator<Item = CanonicalOption>,
108 O::IntoIter: ExactSizeIterator,
109 {
110 self.bytes.push(0x00);
111 self.bytes.push(0x00);
112 core_func_index.encode(&mut self.bytes);
113 self.encode_options(options);
114 type_index.encode(&mut self.bytes);
115 self.num_added += 1;
116 self
117 }
118
119 pub fn lower<O>(&mut self, func_index: u32, options: O) -> &mut Self
121 where
122 O: IntoIterator<Item = CanonicalOption>,
123 O::IntoIter: ExactSizeIterator,
124 {
125 self.bytes.push(0x01);
126 self.bytes.push(0x00);
127 func_index.encode(&mut self.bytes);
128 self.encode_options(options);
129 self.num_added += 1;
130 self
131 }
132
133 pub fn resource_new(&mut self, ty_index: u32) -> &mut Self {
136 self.bytes.push(0x02);
137 ty_index.encode(&mut self.bytes);
138 self.num_added += 1;
139 self
140 }
141
142 pub fn resource_drop(&mut self, ty_index: u32) -> &mut Self {
144 self.bytes.push(0x03);
145 ty_index.encode(&mut self.bytes);
146 self.num_added += 1;
147 self
148 }
149
150 pub fn resource_drop_async(&mut self, ty_index: u32) -> &mut Self {
152 self.bytes.push(0x07);
153 ty_index.encode(&mut self.bytes);
154 self.num_added += 1;
155 self
156 }
157
158 pub fn resource_rep(&mut self, ty_index: u32) -> &mut Self {
161 self.bytes.push(0x04);
162 ty_index.encode(&mut self.bytes);
163 self.num_added += 1;
164 self
165 }
166
167 pub fn thread_spawn_ref(&mut self, ty_index: u32) -> &mut Self {
170 self.bytes.push(0x40);
171 ty_index.encode(&mut self.bytes);
172 self.num_added += 1;
173 self
174 }
175
176 pub fn thread_spawn_indirect(&mut self, ty_index: u32, table_index: u32) -> &mut Self {
179 self.bytes.push(0x41);
180 ty_index.encode(&mut self.bytes);
181 table_index.encode(&mut self.bytes);
182 self.num_added += 1;
183 self
184 }
185
186 pub fn thread_available_parallelism(&mut self) -> &mut Self {
189 self.bytes.push(0x42);
190 self.num_added += 1;
191 self
192 }
193
194 pub fn backpressure_set(&mut self) -> &mut Self {
199 self.bytes.push(0x08);
200 self.num_added += 1;
201 self
202 }
203
204 pub fn task_return<O>(&mut self, ty: Option<ComponentValType>, options: O) -> &mut Self
208 where
209 O: IntoIterator<Item = CanonicalOption>,
210 O::IntoIter: ExactSizeIterator,
211 {
212 self.bytes.push(0x09);
213 crate::encode_resultlist(&mut self.bytes, ty);
214 self.encode_options(options);
215 self.num_added += 1;
216 self
217 }
218
219 pub fn task_cancel(&mut self) -> &mut Self {
221 self.bytes.push(0x05);
222 self.num_added += 1;
223 self
224 }
225
226 pub fn context_get(&mut self, i: u32) -> &mut Self {
228 self.bytes.push(0x0a);
229 self.bytes.push(0x7f);
230 i.encode(&mut self.bytes);
231 self.num_added += 1;
232 self
233 }
234
235 pub fn context_set(&mut self, i: u32) -> &mut Self {
237 self.bytes.push(0x0b);
238 self.bytes.push(0x7f);
239 i.encode(&mut self.bytes);
240 self.num_added += 1;
241 self
242 }
243
244 pub fn yield_(&mut self, async_: bool) -> &mut Self {
249 self.bytes.push(0x0c);
250 self.bytes.push(if async_ { 1 } else { 0 });
251 self.num_added += 1;
252 self
253 }
254
255 pub fn subtask_drop(&mut self) -> &mut Self {
257 self.bytes.push(0x0d);
258 self.num_added += 1;
259 self
260 }
261
262 pub fn subtask_cancel(&mut self, async_: bool) -> &mut Self {
264 self.bytes.push(0x06);
265 self.bytes.push(if async_ { 1 } else { 0 });
266 self.num_added += 1;
267 self
268 }
269
270 pub fn stream_new(&mut self, ty: u32) -> &mut Self {
273 self.bytes.push(0x0e);
274 ty.encode(&mut self.bytes);
275 self.num_added += 1;
276 self
277 }
278
279 pub fn stream_read<O>(&mut self, ty: u32, options: O) -> &mut Self
281 where
282 O: IntoIterator<Item = CanonicalOption>,
283 O::IntoIter: ExactSizeIterator,
284 {
285 self.bytes.push(0x0f);
286 ty.encode(&mut self.bytes);
287 self.encode_options(options);
288 self.num_added += 1;
289 self
290 }
291
292 pub fn stream_write<O>(&mut self, ty: u32, options: O) -> &mut Self
294 where
295 O: IntoIterator<Item = CanonicalOption>,
296 O::IntoIter: ExactSizeIterator,
297 {
298 self.bytes.push(0x10);
299 ty.encode(&mut self.bytes);
300 self.encode_options(options);
301 self.num_added += 1;
302 self
303 }
304
305 pub fn stream_cancel_read(&mut self, ty: u32, async_: bool) -> &mut Self {
308 self.bytes.push(0x11);
309 ty.encode(&mut self.bytes);
310 self.bytes.push(if async_ { 1 } else { 0 });
311 self.num_added += 1;
312 self
313 }
314
315 pub fn stream_cancel_write(&mut self, ty: u32, async_: bool) -> &mut Self {
318 self.bytes.push(0x12);
319 ty.encode(&mut self.bytes);
320 self.bytes.push(if async_ { 1 } else { 0 });
321 self.num_added += 1;
322 self
323 }
324
325 pub fn stream_close_readable(&mut self, ty: u32) -> &mut Self {
328 self.bytes.push(0x13);
329 ty.encode(&mut self.bytes);
330 self.num_added += 1;
331 self
332 }
333
334 pub fn stream_close_writable(&mut self, ty: u32) -> &mut Self {
337 self.bytes.push(0x14);
338 ty.encode(&mut self.bytes);
339 self.num_added += 1;
340 self
341 }
342
343 pub fn future_new(&mut self, ty: u32) -> &mut Self {
346 self.bytes.push(0x15);
347 ty.encode(&mut self.bytes);
348 self.num_added += 1;
349 self
350 }
351
352 pub fn future_read<O>(&mut self, ty: u32, options: O) -> &mut Self
354 where
355 O: IntoIterator<Item = CanonicalOption>,
356 O::IntoIter: ExactSizeIterator,
357 {
358 self.bytes.push(0x16);
359 ty.encode(&mut self.bytes);
360 self.encode_options(options);
361 self.num_added += 1;
362 self
363 }
364
365 pub fn future_write<O>(&mut self, ty: u32, options: O) -> &mut Self
367 where
368 O: IntoIterator<Item = CanonicalOption>,
369 O::IntoIter: ExactSizeIterator,
370 {
371 self.bytes.push(0x17);
372 ty.encode(&mut self.bytes);
373 self.encode_options(options);
374 self.num_added += 1;
375 self
376 }
377
378 pub fn future_cancel_read(&mut self, ty: u32, async_: bool) -> &mut Self {
381 self.bytes.push(0x18);
382 ty.encode(&mut self.bytes);
383 self.bytes.push(if async_ { 1 } else { 0 });
384 self.num_added += 1;
385 self
386 }
387
388 pub fn future_cancel_write(&mut self, ty: u32, async_: bool) -> &mut Self {
391 self.bytes.push(0x19);
392 ty.encode(&mut self.bytes);
393 self.bytes.push(if async_ { 1 } else { 0 });
394 self.num_added += 1;
395 self
396 }
397
398 pub fn future_close_readable(&mut self, ty: u32) -> &mut Self {
401 self.bytes.push(0x1a);
402 ty.encode(&mut self.bytes);
403 self.num_added += 1;
404 self
405 }
406
407 pub fn future_close_writable(&mut self, ty: u32) -> &mut Self {
410 self.bytes.push(0x1b);
411 ty.encode(&mut self.bytes);
412 self.num_added += 1;
413 self
414 }
415
416 pub fn error_context_new<O>(&mut self, options: O) -> &mut Self
419 where
420 O: IntoIterator<Item = CanonicalOption>,
421 O::IntoIter: ExactSizeIterator,
422 {
423 self.bytes.push(0x1c);
424 self.encode_options(options);
425 self.num_added += 1;
426 self
427 }
428
429 pub fn error_context_debug_message<O>(&mut self, options: O) -> &mut Self
435 where
436 O: IntoIterator<Item = CanonicalOption>,
437 O::IntoIter: ExactSizeIterator,
438 {
439 self.bytes.push(0x1d);
440 self.encode_options(options);
441 self.num_added += 1;
442 self
443 }
444
445 pub fn error_context_drop(&mut self) -> &mut Self {
447 self.bytes.push(0x1e);
448 self.num_added += 1;
449 self
450 }
451
452 pub fn waitable_set_new(&mut self) -> &mut Self {
455 self.bytes.push(0x1f);
456 self.num_added += 1;
457 self
458 }
459
460 pub fn waitable_set_wait(&mut self, async_: bool, memory: u32) -> &mut Self {
463 self.bytes.push(0x20);
464 self.bytes.push(if async_ { 1 } else { 0 });
465 memory.encode(&mut self.bytes);
466 self.num_added += 1;
467 self
468 }
469
470 pub fn waitable_set_poll(&mut self, async_: bool, memory: u32) -> &mut Self {
473 self.bytes.push(0x21);
474 self.bytes.push(if async_ { 1 } else { 0 });
475 memory.encode(&mut self.bytes);
476 self.num_added += 1;
477 self
478 }
479
480 pub fn waitable_set_drop(&mut self) -> &mut Self {
483 self.bytes.push(0x22);
484 self.num_added += 1;
485 self
486 }
487
488 pub fn waitable_join(&mut self) -> &mut Self {
491 self.bytes.push(0x23);
492 self.num_added += 1;
493 self
494 }
495
496 fn encode_options<O>(&mut self, options: O) -> &mut Self
497 where
498 O: IntoIterator<Item = CanonicalOption>,
499 O::IntoIter: ExactSizeIterator,
500 {
501 let options = options.into_iter();
502 options.len().encode(&mut self.bytes);
503 for option in options {
504 option.encode(&mut self.bytes);
505 }
506 self
507 }
508}
509
510impl Encode for CanonicalFunctionSection {
511 fn encode(&self, sink: &mut Vec<u8>) {
512 encode_section(sink, self.num_added, &self.bytes);
513 }
514}
515
516impl ComponentSection for CanonicalFunctionSection {
517 fn id(&self) -> u8 {
518 ComponentSectionId::CanonicalFunction.into()
519 }
520}