wasmparser/readers/component/
canonicals.rs

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}
64
65/// A reader for the canonical section of a WebAssembly component.
66pub type ComponentCanonicalSectionReader<'a> = SectionLimited<'a, CanonicalFunction>;
67
68impl<'a> FromReader<'a> for CanonicalFunction {
69    fn from_reader(reader: &mut BinaryReader<'a>) -> Result<CanonicalFunction> {
70        Ok(match reader.read_u8()? {
71            0x00 => match reader.read_u8()? {
72                0x00 => {
73                    let core_func_index = reader.read_var_u32()?;
74                    let options = reader
75                        .read_iter(MAX_WASM_CANONICAL_OPTIONS, "canonical options")?
76                        .collect::<Result<_>>()?;
77                    let type_index = reader.read_var_u32()?;
78                    CanonicalFunction::Lift {
79                        core_func_index,
80                        options,
81                        type_index,
82                    }
83                }
84                x => return reader.invalid_leading_byte(x, "canonical function lift"),
85            },
86            0x01 => match reader.read_u8()? {
87                0x00 => CanonicalFunction::Lower {
88                    func_index: reader.read_var_u32()?,
89                    options: reader
90                        .read_iter(MAX_WASM_CANONICAL_OPTIONS, "canonical options")?
91                        .collect::<Result<_>>()?,
92                },
93                x => return reader.invalid_leading_byte(x, "canonical function lower"),
94            },
95            0x02 => CanonicalFunction::ResourceNew {
96                resource: reader.read()?,
97            },
98            0x03 => CanonicalFunction::ResourceDrop {
99                resource: reader.read()?,
100            },
101            0x04 => CanonicalFunction::ResourceRep {
102                resource: reader.read()?,
103            },
104            x => return reader.invalid_leading_byte(x, "canonical function"),
105        })
106    }
107}
108
109impl<'a> FromReader<'a> for CanonicalOption {
110    fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
111        Ok(match reader.read_u8()? {
112            0x00 => CanonicalOption::UTF8,
113            0x01 => CanonicalOption::UTF16,
114            0x02 => CanonicalOption::CompactUTF16,
115            0x03 => CanonicalOption::Memory(reader.read_var_u32()?),
116            0x04 => CanonicalOption::Realloc(reader.read_var_u32()?),
117            0x05 => CanonicalOption::PostReturn(reader.read_var_u32()?),
118            x => return reader.invalid_leading_byte(x, "canonical option"),
119        })
120    }
121}