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}
31
32impl Encode for CanonicalOption {
33 fn encode(&self, sink: &mut Vec<u8>) {
34 match self {
35 Self::UTF8 => sink.push(0x00),
36 Self::UTF16 => sink.push(0x01),
37 Self::CompactUTF16 => sink.push(0x02),
38 Self::Memory(idx) => {
39 sink.push(0x03);
40 idx.encode(sink);
41 }
42 Self::Realloc(idx) => {
43 sink.push(0x04);
44 idx.encode(sink);
45 }
46 Self::PostReturn(idx) => {
47 sink.push(0x05);
48 idx.encode(sink);
49 }
50 Self::Async => {
51 sink.push(0x06);
52 }
53 Self::Callback(idx) => {
54 sink.push(0x07);
55 idx.encode(sink);
56 }
57 }
58 }
59}
60
61#[derive(Clone, Debug, Default)]
77pub struct CanonicalFunctionSection {
78 bytes: Vec<u8>,
79 num_added: u32,
80}
81
82impl CanonicalFunctionSection {
83 pub fn new() -> Self {
85 Self::default()
86 }
87
88 pub fn len(&self) -> u32 {
90 self.num_added
91 }
92
93 pub fn is_empty(&self) -> bool {
95 self.num_added == 0
96 }
97
98 pub fn lift<O>(&mut self, core_func_index: u32, type_index: u32, options: O) -> &mut Self
100 where
101 O: IntoIterator<Item = CanonicalOption>,
102 O::IntoIter: ExactSizeIterator,
103 {
104 self.bytes.push(0x00);
105 self.bytes.push(0x00);
106 core_func_index.encode(&mut self.bytes);
107 self.encode_options(options);
108 type_index.encode(&mut self.bytes);
109 self.num_added += 1;
110 self
111 }
112
113 pub fn lower<O>(&mut self, func_index: u32, options: O) -> &mut Self
115 where
116 O: IntoIterator<Item = CanonicalOption>,
117 O::IntoIter: ExactSizeIterator,
118 {
119 self.bytes.push(0x01);
120 self.bytes.push(0x00);
121 func_index.encode(&mut self.bytes);
122 self.encode_options(options);
123 self.num_added += 1;
124 self
125 }
126
127 pub fn resource_new(&mut self, ty_index: u32) -> &mut Self {
130 self.bytes.push(0x02);
131 ty_index.encode(&mut self.bytes);
132 self.num_added += 1;
133 self
134 }
135
136 pub fn resource_drop(&mut self, ty_index: u32) -> &mut Self {
138 self.bytes.push(0x03);
139 ty_index.encode(&mut self.bytes);
140 self.num_added += 1;
141 self
142 }
143
144 pub fn resource_drop_async(&mut self, ty_index: u32) -> &mut Self {
146 self.bytes.push(0x07);
147 ty_index.encode(&mut self.bytes);
148 self.num_added += 1;
149 self
150 }
151
152 pub fn resource_rep(&mut self, ty_index: u32) -> &mut Self {
155 self.bytes.push(0x04);
156 ty_index.encode(&mut self.bytes);
157 self.num_added += 1;
158 self
159 }
160
161 pub fn thread_spawn_ref(&mut self, ty_index: u32) -> &mut Self {
164 self.bytes.push(0x40);
165 ty_index.encode(&mut self.bytes);
166 self.num_added += 1;
167 self
168 }
169
170 pub fn thread_spawn_indirect(&mut self, ty_index: u32, table_index: u32) -> &mut Self {
173 self.bytes.push(0x41);
174 ty_index.encode(&mut self.bytes);
175 table_index.encode(&mut self.bytes);
176 self.num_added += 1;
177 self
178 }
179
180 pub fn thread_available_parallelism(&mut self) -> &mut Self {
183 self.bytes.push(0x42);
184 self.num_added += 1;
185 self
186 }
187
188 pub fn backpressure_set(&mut self) -> &mut Self {
193 self.bytes.push(0x08);
194 self.num_added += 1;
195 self
196 }
197
198 pub fn task_return<O>(&mut self, ty: Option<ComponentValType>, options: O) -> &mut Self
202 where
203 O: IntoIterator<Item = CanonicalOption>,
204 O::IntoIter: ExactSizeIterator,
205 {
206 self.bytes.push(0x09);
207 crate::encode_resultlist(&mut self.bytes, ty);
208 self.encode_options(options);
209 self.num_added += 1;
210 self
211 }
212
213 pub fn task_cancel(&mut self) -> &mut Self {
215 self.bytes.push(0x25);
216 self.num_added += 1;
217 self
218 }
219
220 pub fn context_get(&mut self, i: u32) -> &mut Self {
222 self.bytes.push(0x0a);
223 self.bytes.push(0x7f);
224 i.encode(&mut self.bytes);
225 self.num_added += 1;
226 self
227 }
228
229 pub fn context_set(&mut self, i: u32) -> &mut Self {
231 self.bytes.push(0x0b);
232 self.bytes.push(0x7f);
233 i.encode(&mut self.bytes);
234 self.num_added += 1;
235 self
236 }
237
238 pub fn yield_(&mut self, async_: bool) -> &mut Self {
243 self.bytes.push(0x0c);
244 self.bytes.push(if async_ { 1 } else { 0 });
245 self.num_added += 1;
246 self
247 }
248
249 pub fn subtask_drop(&mut self) -> &mut Self {
251 self.bytes.push(0x0d);
252 self.num_added += 1;
253 self
254 }
255
256 pub fn subtask_cancel(&mut self, async_: bool) -> &mut Self {
258 self.bytes.push(0x24);
259 self.bytes.push(if async_ { 1 } else { 0 });
260 self.num_added += 1;
261 self
262 }
263
264 pub fn stream_new(&mut self, ty: u32) -> &mut Self {
267 self.bytes.push(0x0e);
268 ty.encode(&mut self.bytes);
269 self.num_added += 1;
270 self
271 }
272
273 pub fn stream_read<O>(&mut self, ty: u32, options: O) -> &mut Self
275 where
276 O: IntoIterator<Item = CanonicalOption>,
277 O::IntoIter: ExactSizeIterator,
278 {
279 self.bytes.push(0x0f);
280 ty.encode(&mut self.bytes);
281 self.encode_options(options);
282 self.num_added += 1;
283 self
284 }
285
286 pub fn stream_write<O>(&mut self, ty: u32, options: O) -> &mut Self
288 where
289 O: IntoIterator<Item = CanonicalOption>,
290 O::IntoIter: ExactSizeIterator,
291 {
292 self.bytes.push(0x10);
293 ty.encode(&mut self.bytes);
294 self.encode_options(options);
295 self.num_added += 1;
296 self
297 }
298
299 pub fn stream_cancel_read(&mut self, ty: u32, async_: bool) -> &mut Self {
302 self.bytes.push(0x11);
303 ty.encode(&mut self.bytes);
304 self.bytes.push(if async_ { 1 } else { 0 });
305 self.num_added += 1;
306 self
307 }
308
309 pub fn stream_cancel_write(&mut self, ty: u32, async_: bool) -> &mut Self {
312 self.bytes.push(0x12);
313 ty.encode(&mut self.bytes);
314 self.bytes.push(if async_ { 1 } else { 0 });
315 self.num_added += 1;
316 self
317 }
318
319 pub fn stream_close_readable(&mut self, ty: u32) -> &mut Self {
322 self.bytes.push(0x13);
323 ty.encode(&mut self.bytes);
324 self.num_added += 1;
325 self
326 }
327
328 pub fn stream_close_writable(&mut self, ty: u32) -> &mut Self {
331 self.bytes.push(0x14);
332 ty.encode(&mut self.bytes);
333 self.num_added += 1;
334 self
335 }
336
337 pub fn future_new(&mut self, ty: u32) -> &mut Self {
340 self.bytes.push(0x15);
341 ty.encode(&mut self.bytes);
342 self.num_added += 1;
343 self
344 }
345
346 pub fn future_read<O>(&mut self, ty: u32, options: O) -> &mut Self
348 where
349 O: IntoIterator<Item = CanonicalOption>,
350 O::IntoIter: ExactSizeIterator,
351 {
352 self.bytes.push(0x16);
353 ty.encode(&mut self.bytes);
354 self.encode_options(options);
355 self.num_added += 1;
356 self
357 }
358
359 pub fn future_write<O>(&mut self, ty: u32, options: O) -> &mut Self
361 where
362 O: IntoIterator<Item = CanonicalOption>,
363 O::IntoIter: ExactSizeIterator,
364 {
365 self.bytes.push(0x17);
366 ty.encode(&mut self.bytes);
367 self.encode_options(options);
368 self.num_added += 1;
369 self
370 }
371
372 pub fn future_cancel_read(&mut self, ty: u32, async_: bool) -> &mut Self {
375 self.bytes.push(0x18);
376 ty.encode(&mut self.bytes);
377 self.bytes.push(if async_ { 1 } else { 0 });
378 self.num_added += 1;
379 self
380 }
381
382 pub fn future_cancel_write(&mut self, ty: u32, async_: bool) -> &mut Self {
385 self.bytes.push(0x19);
386 ty.encode(&mut self.bytes);
387 self.bytes.push(if async_ { 1 } else { 0 });
388 self.num_added += 1;
389 self
390 }
391
392 pub fn future_close_readable(&mut self, ty: u32) -> &mut Self {
395 self.bytes.push(0x1a);
396 ty.encode(&mut self.bytes);
397 self.num_added += 1;
398 self
399 }
400
401 pub fn future_close_writable(&mut self, ty: u32) -> &mut Self {
404 self.bytes.push(0x1b);
405 ty.encode(&mut self.bytes);
406 self.num_added += 1;
407 self
408 }
409
410 pub fn error_context_new<O>(&mut self, options: O) -> &mut Self
413 where
414 O: IntoIterator<Item = CanonicalOption>,
415 O::IntoIter: ExactSizeIterator,
416 {
417 self.bytes.push(0x1c);
418 self.encode_options(options);
419 self.num_added += 1;
420 self
421 }
422
423 pub fn error_context_debug_message<O>(&mut self, options: O) -> &mut Self
429 where
430 O: IntoIterator<Item = CanonicalOption>,
431 O::IntoIter: ExactSizeIterator,
432 {
433 self.bytes.push(0x1d);
434 self.encode_options(options);
435 self.num_added += 1;
436 self
437 }
438
439 pub fn error_context_drop(&mut self) -> &mut Self {
441 self.bytes.push(0x1e);
442 self.num_added += 1;
443 self
444 }
445
446 pub fn waitable_set_new(&mut self) -> &mut Self {
449 self.bytes.push(0x1f);
450 self.num_added += 1;
451 self
452 }
453
454 pub fn waitable_set_wait(&mut self, async_: bool, memory: u32) -> &mut Self {
457 self.bytes.push(0x20);
458 self.bytes.push(if async_ { 1 } else { 0 });
459 memory.encode(&mut self.bytes);
460 self.num_added += 1;
461 self
462 }
463
464 pub fn waitable_set_poll(&mut self, async_: bool, memory: u32) -> &mut Self {
467 self.bytes.push(0x21);
468 self.bytes.push(if async_ { 1 } else { 0 });
469 memory.encode(&mut self.bytes);
470 self.num_added += 1;
471 self
472 }
473
474 pub fn waitable_set_drop(&mut self) -> &mut Self {
477 self.bytes.push(0x22);
478 self.num_added += 1;
479 self
480 }
481
482 pub fn waitable_join(&mut self) -> &mut Self {
485 self.bytes.push(0x23);
486 self.num_added += 1;
487 self
488 }
489
490 fn encode_options<O>(&mut self, options: O) -> &mut Self
491 where
492 O: IntoIterator<Item = CanonicalOption>,
493 O::IntoIter: ExactSizeIterator,
494 {
495 let options = options.into_iter();
496 options.len().encode(&mut self.bytes);
497 for option in options {
498 option.encode(&mut self.bytes);
499 }
500 self
501 }
502}
503
504impl Encode for CanonicalFunctionSection {
505 fn encode(&self, sink: &mut Vec<u8>) {
506 encode_section(sink, self.num_added, &self.bytes);
507 }
508}
509
510impl ComponentSection for CanonicalFunctionSection {
511 fn id(&self) -> u8 {
512 ComponentSectionId::CanonicalFunction.into()
513 }
514}