1use crate::limits::MAX_WASM_CANONICAL_OPTIONS;
2use crate::prelude::*;
3use crate::{BinaryReader, FromReader, Result, SectionLimited};
4
5/// Represents options for component functions.
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum CanonicalOption {
8 /// The string types in the function signature are UTF-8 encoded.
9 UTF8,
10 /// The string types in the function signature are UTF-16 encoded.
11 UTF16,
12 /// The string types in the function signature are compact UTF-16 encoded.
13 CompactUTF16,
14 /// The memory to use if the lifting or lowering of a function requires memory access.
15 ///
16 /// The value is an index to a core memory.
17 Memory(u32),
18 /// The realloc function to use if the lifting or lowering of a function requires memory
19 /// allocation.
20 ///
21 /// The value is an index to a core function of type `(func (param i32 i32 i32 i32) (result i32))`.
22 Realloc(u32),
23 /// The post-return function to use if the lifting of a function requires
24 /// cleanup after the function returns.
25 PostReturn(u32),
26}
27
28/// Represents a canonical function in a WebAssembly component.
29#[derive(Debug, Clone, Eq, PartialEq)]
30pub enum CanonicalFunction {
31 /// The function lifts a core WebAssembly function to the canonical ABI.
32 Lift {
33 /// The index of the core WebAssembly function to lift.
34 core_func_index: u32,
35 /// The index of the lifted function's type.
36 type_index: u32,
37 /// The canonical options for the function.
38 options: Box<[CanonicalOption]>,
39 },
40 /// The function lowers a canonical ABI function to a core WebAssembly function.
41 Lower {
42 /// The index of the function to lower.
43 func_index: u32,
44 /// The canonical options for the function.
45 options: Box<[CanonicalOption]>,
46 },
47 /// A function which creates a new owned handle to a resource.
48 ResourceNew {
49 /// The type index of the resource that's being created.
50 resource: u32,
51 },
52 /// A function which is used to drop resource handles of the specified type.
53 ResourceDrop {
54 /// The type index of the resource that's being dropped.
55 resource: u32,
56 },
57 /// A function which returns the underlying i32-based representation of the
58 /// specified resource.
59 ResourceRep {
60 /// The type index of the resource that's being accessed.
61 resource: u32,
62 },
63 /// A function which spawns a new thread by invoking the shared function.
64 ThreadSpawn {
65 /// The index of the function to spawn.
66 func_ty_index: u32,
67 },
68 /// A function which returns the number of threads that can be expected to
69 /// execute concurrently
70 ThreadHwConcurrency,
71}
72
73/// A reader for the canonical section of a WebAssembly component.
74pub type ComponentCanonicalSectionReader<'a> = SectionLimited<'a, CanonicalFunction>;
75
76impl<'a> FromReader<'a> for CanonicalFunction {
77 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<CanonicalFunction> {
78 Ok(match reader.read_u8()? {
79 0x00 => match reader.read_u8()? {
80 0x00 => {
81 let core_func_index = reader.read_var_u32()?;
82 let options = reader
83 .read_iter(MAX_WASM_CANONICAL_OPTIONS, "canonical options")?
84 .collect::<Result<_>>()?;
85 let type_index = reader.read_var_u32()?;
86 CanonicalFunction::Lift {
87 core_func_index,
88 options,
89 type_index,
90 }
91 }
92 x => return reader.invalid_leading_byte(x, "canonical function lift"),
93 },
94 0x01 => match reader.read_u8()? {
95 0x00 => CanonicalFunction::Lower {
96 func_index: reader.read_var_u32()?,
97 options: reader
98 .read_iter(MAX_WASM_CANONICAL_OPTIONS, "canonical options")?
99 .collect::<Result<_>>()?,
100 },
101 x => return reader.invalid_leading_byte(x, "canonical function lower"),
102 },
103 0x02 => CanonicalFunction::ResourceNew {
104 resource: reader.read()?,
105 },
106 0x03 => CanonicalFunction::ResourceDrop {
107 resource: reader.read()?,
108 },
109 0x04 => CanonicalFunction::ResourceRep {
110 resource: reader.read()?,
111 },
112 0x05 => CanonicalFunction::ThreadSpawn {
113 func_ty_index: reader.read()?,
114 },
115 0x06 => CanonicalFunction::ThreadHwConcurrency,
116 x => return reader.invalid_leading_byte(x, "canonical function"),
117 })
118 }
119}
120
121impl<'a> FromReader<'a> for CanonicalOption {
122 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
123 Ok(match reader.read_u8()? {
124 0x00 => CanonicalOption::UTF8,
125 0x01 => CanonicalOption::UTF16,
126 0x02 => CanonicalOption::CompactUTF16,
127 0x03 => CanonicalOption::Memory(reader.read_var_u32()?),
128 0x04 => CanonicalOption::Realloc(reader.read_var_u32()?),
129 0x05 => CanonicalOption::PostReturn(reader.read_var_u32()?),
130 x: u8 => return reader.invalid_leading_byte(byte:x, desc:"canonical option"),
131 })
132 }
133}
134