Coverage Report

Created: 2025-10-12 07:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wasm-tools/crates/wasm-encoder/src/component/imports.rs
Line
Count
Source
1
use crate::{
2
    ComponentExportKind, ComponentSection, ComponentSectionId, ComponentValType, Encode,
3
    encode_section,
4
};
5
use alloc::vec::Vec;
6
7
/// Represents the possible type bounds for type references.
8
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
9
pub enum TypeBounds {
10
    /// The type is bounded by equality to the type index specified.
11
    Eq(u32),
12
    /// This type is a fresh resource type,
13
    SubResource,
14
}
15
16
impl Encode for TypeBounds {
17
65.0k
    fn encode(&self, sink: &mut Vec<u8>) {
18
65.0k
        match self {
19
61.0k
            Self::Eq(i) => {
20
61.0k
                sink.push(0x00);
21
61.0k
                i.encode(sink);
22
61.0k
            }
23
3.96k
            Self::SubResource => sink.push(0x01),
24
        }
25
65.0k
    }
26
}
27
28
/// Represents a reference to a type.
29
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
30
pub enum ComponentTypeRef {
31
    /// The reference is to a core module type.
32
    ///
33
    /// The index is expected to be core type index to a core module type.
34
    Module(u32),
35
    /// The reference is to a function type.
36
    ///
37
    /// The index is expected to be a type index to a function type.
38
    Func(u32),
39
    /// The reference is to a value type.
40
    Value(ComponentValType),
41
    /// The reference is to a bounded type.
42
    Type(TypeBounds),
43
    /// The reference is to an instance type.
44
    ///
45
    /// The index is expected to be a type index to an instance type.
46
    Instance(u32),
47
    /// The reference is to a component type.
48
    ///
49
    /// The index is expected to be a type index to a component type.
50
    Component(u32),
51
}
52
53
impl ComponentTypeRef {
54
    /// Gets the export kind of the reference.
55
186k
    pub fn kind(&self) -> ComponentExportKind {
56
186k
        match self {
57
0
            Self::Module(_) => ComponentExportKind::Module,
58
33.1k
            Self::Func(_) => ComponentExportKind::Func,
59
0
            Self::Value(_) => ComponentExportKind::Value,
60
65.0k
            Self::Type(..) => ComponentExportKind::Type,
61
66.7k
            Self::Instance(_) => ComponentExportKind::Instance,
62
22.0k
            Self::Component(_) => ComponentExportKind::Component,
63
        }
64
186k
    }
65
}
66
67
impl Encode for ComponentTypeRef {
68
186k
    fn encode(&self, sink: &mut Vec<u8>) {
69
186k
        self.kind().encode(sink);
70
71
186k
        match self {
72
121k
            Self::Module(idx) | Self::Func(idx) | Self::Instance(idx) | Self::Component(idx) => {
73
121k
                idx.encode(sink);
74
121k
            }
75
0
            Self::Value(ty) => ty.encode(sink),
76
65.0k
            Self::Type(bounds) => bounds.encode(sink),
77
        }
78
186k
    }
79
}
80
81
/// An encoder for the import section of WebAssembly components.
82
///
83
/// # Example
84
///
85
/// ```rust
86
/// use wasm_encoder::{Component, ComponentTypeSection, PrimitiveValType, ComponentImportSection, ComponentTypeRef};
87
///
88
/// let mut types = ComponentTypeSection::new();
89
///
90
/// // Define a function type of `[string, string] -> string`.
91
/// types
92
///   .function()
93
///   .params(
94
///     [
95
///       ("a", PrimitiveValType::String),
96
///       ("b", PrimitiveValType::String)
97
///     ]
98
///   )
99
///   .result(Some(PrimitiveValType::String.into()));
100
///
101
/// // This imports a function named `f` with the type defined above
102
/// let mut imports = ComponentImportSection::new();
103
/// imports.import("f", ComponentTypeRef::Func(0));
104
///
105
/// let mut component = Component::new();
106
/// component.section(&types);
107
/// component.section(&imports);
108
///
109
/// let bytes = component.finish();
110
/// ```
111
#[derive(Clone, Debug, Default)]
112
pub struct ComponentImportSection {
113
    bytes: Vec<u8>,
114
    num_added: u32,
115
}
116
117
impl ComponentImportSection {
118
    /// Create a new component import section encoder.
119
5.23k
    pub fn new() -> Self {
120
5.23k
        Self::default()
121
5.23k
    }
122
123
    /// The number of imports in the section.
124
0
    pub fn len(&self) -> u32 {
125
0
        self.num_added
126
0
    }
127
128
    /// Determines if the section is empty.
129
0
    pub fn is_empty(&self) -> bool {
130
0
        self.num_added == 0
131
0
    }
132
133
    /// Define an import in the component import section.
134
5.90k
    pub fn import(&mut self, name: &str, ty: ComponentTypeRef) -> &mut Self {
135
5.90k
        encode_component_import_name(&mut self.bytes, name);
136
5.90k
        ty.encode(&mut self.bytes);
137
5.90k
        self.num_added += 1;
138
5.90k
        self
139
5.90k
    }
140
}
141
142
impl Encode for ComponentImportSection {
143
5.23k
    fn encode(&self, sink: &mut Vec<u8>) {
144
5.23k
        encode_section(sink, self.num_added, &self.bytes);
145
5.23k
    }
146
}
147
148
impl ComponentSection for ComponentImportSection {
149
5.23k
    fn id(&self) -> u8 {
150
5.23k
        ComponentSectionId::Import.into()
151
5.23k
    }
152
}
153
154
/// Prior to WebAssembly/component-model#263 import and export names were
155
/// discriminated with a leading byte indicating what kind of import they are.
156
/// After that PR though names are always prefixed with a 0x00 byte.
157
///
158
/// On 2023-10-28 in bytecodealliance/wasm-tools#1262 was landed to start
159
/// transitioning to "always lead with 0x00". That updated the validator/parser
160
/// to accept either 0x00 or 0x01 but the encoder wasn't updated at the time.
161
///
162
/// On 2024-09-03 in bytecodealliance/wasm-tools#TODO this encoder was updated
163
/// to always emit 0x00 as a leading byte.
164
///
165
/// This function corresponds with the `importname'` production in the
166
/// specification.
167
38.4k
pub(crate) fn encode_component_import_name(bytes: &mut Vec<u8>, name: &str) {
168
38.4k
    bytes.push(0x00);
169
38.4k
    name.encode(bytes);
170
38.4k
}