wasmparser/readers/component/
canonicals.rs

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