tinywasm_wasmparser/readers/component/
canonicals.rs

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