wasm_encoder/component/
canonicals.rs1use 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 let options = options.into_iter();
105 self.bytes.push(0x00);
106 self.bytes.push(0x00);
107 core_func_index.encode(&mut self.bytes);
108 options.len().encode(&mut self.bytes);
109 for option in options {
110 option.encode(&mut self.bytes);
111 }
112 type_index.encode(&mut self.bytes);
113 self.num_added += 1;
114 self
115 }
116
117 pub fn lower<O>(&mut self, func_index: u32, options: O) -> &mut Self
119 where
120 O: IntoIterator<Item = CanonicalOption>,
121 O::IntoIter: ExactSizeIterator,
122 {
123 let options = options.into_iter();
124 self.bytes.push(0x01);
125 self.bytes.push(0x00);
126 func_index.encode(&mut self.bytes);
127 options.len().encode(&mut self.bytes);
128 for option in options {
129 option.encode(&mut self.bytes);
130 }
131 self.num_added += 1;
132 self
133 }
134
135 pub fn resource_new(&mut self, ty_index: u32) -> &mut Self {
138 self.bytes.push(0x02);
139 ty_index.encode(&mut self.bytes);
140 self.num_added += 1;
141 self
142 }
143
144 pub fn resource_drop(&mut self, ty_index: u32) -> &mut Self {
146 self.bytes.push(0x03);
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(&mut self, ty_index: u32) -> &mut Self {
164 self.bytes.push(0x05);
165 ty_index.encode(&mut self.bytes);
166 self.num_added += 1;
167 self
168 }
169
170 pub fn thread_available_parallelism(&mut self) -> &mut Self {
173 self.bytes.push(0x06);
174 self.num_added += 1;
175 self
176 }
177
178 pub fn task_backpressure(&mut self) -> &mut Self {
183 self.bytes.push(0x08);
184 self.num_added += 1;
185 self
186 }
187
188 pub fn task_return(&mut self, ty: Option<impl Into<ComponentValType>>) -> &mut Self {
192 self.bytes.push(0x09);
193 if let Some(ty) = ty {
194 self.bytes.push(0x00);
195 ty.into().encode(&mut self.bytes);
196 } else {
197 self.bytes.push(0x01);
198 0_usize.encode(&mut self.bytes);
199 }
200 self.num_added += 1;
201 self
202 }
203
204 pub fn task_wait(&mut self, async_: bool, memory: u32) -> &mut Self {
209 self.bytes.push(0x0a);
210 self.bytes.push(if async_ { 1 } else { 0 });
211 memory.encode(&mut self.bytes);
212 self.num_added += 1;
213 self
214 }
215
216 pub fn task_poll(&mut self, async_: bool, memory: u32) -> &mut Self {
222 self.bytes.push(0x0b);
223 self.bytes.push(if async_ { 1 } else { 0 });
224 memory.encode(&mut self.bytes);
225 self.num_added += 1;
226 self
227 }
228
229 pub fn task_yield(&mut self, async_: bool) -> &mut Self {
234 self.bytes.push(0x0c);
235 self.bytes.push(if async_ { 1 } else { 0 });
236 self.num_added += 1;
237 self
238 }
239
240 pub fn subtask_drop(&mut self) -> &mut Self {
242 self.bytes.push(0x0d);
243 self.num_added += 1;
244 self
245 }
246
247 pub fn stream_new(&mut self, ty: u32) -> &mut Self {
250 self.bytes.push(0x0e);
251 ty.encode(&mut self.bytes);
252 self.num_added += 1;
253 self
254 }
255
256 pub fn stream_read<O>(&mut self, ty: u32, options: O) -> &mut Self
258 where
259 O: IntoIterator<Item = CanonicalOption>,
260 O::IntoIter: ExactSizeIterator,
261 {
262 self.bytes.push(0x0f);
263 ty.encode(&mut self.bytes);
264 let options = options.into_iter();
265 options.len().encode(&mut self.bytes);
266 for option in options {
267 option.encode(&mut self.bytes);
268 }
269 self.num_added += 1;
270 self
271 }
272
273 pub fn stream_write<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(0x10);
280 ty.encode(&mut self.bytes);
281 let options = options.into_iter();
282 options.len().encode(&mut self.bytes);
283 for option in options {
284 option.encode(&mut self.bytes);
285 }
286 self.num_added += 1;
287 self
288 }
289
290 pub fn stream_cancel_read(&mut self, ty: u32, async_: bool) -> &mut Self {
293 self.bytes.push(0x11);
294 ty.encode(&mut self.bytes);
295 self.bytes.push(if async_ { 1 } else { 0 });
296 self.num_added += 1;
297 self
298 }
299
300 pub fn stream_cancel_write(&mut self, ty: u32, async_: bool) -> &mut Self {
303 self.bytes.push(0x12);
304 ty.encode(&mut self.bytes);
305 self.bytes.push(if async_ { 1 } else { 0 });
306 self.num_added += 1;
307 self
308 }
309
310 pub fn stream_close_readable(&mut self, ty: u32) -> &mut Self {
313 self.bytes.push(0x13);
314 ty.encode(&mut self.bytes);
315 self.num_added += 1;
316 self
317 }
318
319 pub fn stream_close_writable(&mut self, ty: u32) -> &mut Self {
322 self.bytes.push(0x14);
323 ty.encode(&mut self.bytes);
324 self.num_added += 1;
325 self
326 }
327
328 pub fn future_new(&mut self, ty: u32) -> &mut Self {
331 self.bytes.push(0x15);
332 ty.encode(&mut self.bytes);
333 self.num_added += 1;
334 self
335 }
336
337 pub fn future_read<O>(&mut self, ty: u32, options: O) -> &mut Self
339 where
340 O: IntoIterator<Item = CanonicalOption>,
341 O::IntoIter: ExactSizeIterator,
342 {
343 self.bytes.push(0x16);
344 ty.encode(&mut self.bytes);
345 let options = options.into_iter();
346 options.len().encode(&mut self.bytes);
347 for option in options {
348 option.encode(&mut self.bytes);
349 }
350 self.num_added += 1;
351 self
352 }
353
354 pub fn future_write<O>(&mut self, ty: u32, options: O) -> &mut Self
356 where
357 O: IntoIterator<Item = CanonicalOption>,
358 O::IntoIter: ExactSizeIterator,
359 {
360 self.bytes.push(0x17);
361 ty.encode(&mut self.bytes);
362 let options = options.into_iter();
363 options.len().encode(&mut self.bytes);
364 for option in options {
365 option.encode(&mut self.bytes);
366 }
367 self.num_added += 1;
368 self
369 }
370
371 pub fn future_cancel_read(&mut self, ty: u32, async_: bool) -> &mut Self {
374 self.bytes.push(0x18);
375 ty.encode(&mut self.bytes);
376 self.bytes.push(if async_ { 1 } else { 0 });
377 self.num_added += 1;
378 self
379 }
380
381 pub fn future_cancel_write(&mut self, ty: u32, async_: bool) -> &mut Self {
384 self.bytes.push(0x19);
385 ty.encode(&mut self.bytes);
386 self.bytes.push(if async_ { 1 } else { 0 });
387 self.num_added += 1;
388 self
389 }
390
391 pub fn future_close_readable(&mut self, ty: u32) -> &mut Self {
394 self.bytes.push(0x1a);
395 ty.encode(&mut self.bytes);
396 self.num_added += 1;
397 self
398 }
399
400 pub fn future_close_writable(&mut self, ty: u32) -> &mut Self {
403 self.bytes.push(0x1b);
404 ty.encode(&mut self.bytes);
405 self.num_added += 1;
406 self
407 }
408
409 pub fn error_context_new<O>(&mut self, options: O) -> &mut Self
412 where
413 O: IntoIterator<Item = CanonicalOption>,
414 O::IntoIter: ExactSizeIterator,
415 {
416 self.bytes.push(0x1c);
417 let options = options.into_iter();
418 options.len().encode(&mut self.bytes);
419 for option in options {
420 option.encode(&mut self.bytes);
421 }
422 self.num_added += 1;
423 self
424 }
425
426 pub fn error_context_debug_message<O>(&mut self, options: O) -> &mut Self
432 where
433 O: IntoIterator<Item = CanonicalOption>,
434 O::IntoIter: ExactSizeIterator,
435 {
436 self.bytes.push(0x1d);
437 let options = options.into_iter();
438 options.len().encode(&mut self.bytes);
439 for option in options {
440 option.encode(&mut self.bytes);
441 }
442 self.num_added += 1;
443 self
444 }
445
446 pub fn error_context_drop(&mut self) -> &mut Self {
448 self.bytes.push(0x1e);
449 self.num_added += 1;
450 self
451 }
452}
453
454impl Encode for CanonicalFunctionSection {
455 fn encode(&self, sink: &mut Vec<u8>) {
456 encode_section(sink, self.num_added, &self.bytes);
457 }
458}
459
460impl ComponentSection for CanonicalFunctionSection {
461 fn id(&self) -> u8 {
462 ComponentSectionId::CanonicalFunction.into()
463 }
464}