Coverage Report

Created: 2025-12-04 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wasm-tools/crates/wasm-smith/src/component/encode.rs
Line
Count
Source
1
use std::borrow::Cow;
2
3
use crate::core::{CompositeInnerType, CompositeType};
4
5
use super::*;
6
use wasm_encoder::{ComponentExportKind, ComponentOuterAliasKind, ExportKind};
7
8
impl Component {
9
    /// Encode this Wasm component into bytes.
10
0
    pub fn to_bytes(&self) -> Vec<u8> {
11
0
        self.encoded().finish()
12
0
    }
13
14
0
    fn encoded(&self) -> wasm_encoder::Component {
15
0
        let mut component = wasm_encoder::Component::new();
16
0
        for section in &self.sections {
17
0
            section.encode(&mut component);
18
0
        }
19
0
        component
20
0
    }
21
}
22
23
impl Section {
24
0
    fn encode(&self, component: &mut wasm_encoder::Component) {
25
0
        match self {
26
0
            Self::Custom(sec) => sec.encode(component),
27
0
            Self::CoreModule(module) => {
28
0
                let bytes = module.to_bytes();
29
0
                component.section(&wasm_encoder::RawSection {
30
0
                    id: wasm_encoder::ComponentSectionId::CoreModule as u8,
31
0
                    data: &bytes,
32
0
                });
33
0
            }
34
0
            Self::CoreInstance(_) => todo!(),
35
0
            Self::CoreType(sec) => sec.encode(component),
36
0
            Self::Component(comp) => {
37
0
                let bytes = comp.to_bytes();
38
0
                component.section(&wasm_encoder::RawSection {
39
0
                    id: wasm_encoder::ComponentSectionId::Component as u8,
40
0
                    data: &bytes,
41
0
                });
42
0
            }
43
0
            Self::Instance(_) => todo!(),
44
0
            Self::Alias(_) => todo!(),
45
0
            Self::Type(sec) => sec.encode(component),
46
0
            Self::Canonical(sec) => sec.encode(component),
47
0
            Self::Start(_) => todo!(),
48
0
            Self::Import(sec) => sec.encode(component),
49
0
            Self::Export(_) => todo!(),
50
        }
51
0
    }
52
}
53
54
impl CustomSection {
55
0
    fn encode(&self, component: &mut wasm_encoder::Component) {
56
0
        component.section(&wasm_encoder::CustomSection {
57
0
            name: (&self.name).into(),
58
0
            data: Cow::Borrowed(&self.data),
59
0
        });
60
0
    }
61
}
62
63
impl TypeSection {
64
0
    fn encode(&self, component: &mut wasm_encoder::Component) {
65
0
        let mut sec = wasm_encoder::ComponentTypeSection::new();
66
0
        for ty in &self.types {
67
0
            ty.encode(sec.ty());
68
0
        }
69
0
        component.section(&sec);
70
0
    }
71
}
72
73
impl ImportSection {
74
0
    fn encode(&self, component: &mut wasm_encoder::Component) {
75
0
        let mut sec = wasm_encoder::ComponentImportSection::new();
76
0
        for imp in &self.imports {
77
0
            sec.import(&imp.name, imp.ty);
78
0
        }
79
0
        component.section(&sec);
80
0
    }
81
}
82
83
impl CanonicalSection {
84
0
    fn encode(&self, component: &mut wasm_encoder::Component) {
85
0
        let mut sec = wasm_encoder::CanonicalFunctionSection::new();
86
0
        for func in &self.funcs {
87
0
            match func {
88
                Func::CanonLift {
89
0
                    func_ty,
90
0
                    options,
91
0
                    core_func_index,
92
0
                } => {
93
0
                    let options = translate_canon_opt(options);
94
0
                    sec.lift(*core_func_index, *func_ty, options);
95
0
                }
96
                Func::CanonLower {
97
0
                    options,
98
0
                    func_index,
99
0
                } => {
100
0
                    let options = translate_canon_opt(options);
101
0
                    sec.lower(*func_index, options);
102
0
                }
103
            }
104
        }
105
0
        component.section(&sec);
106
0
    }
107
}
108
109
impl CoreTypeSection {
110
0
    fn encode(&self, component: &mut wasm_encoder::Component) {
111
0
        let mut sec = wasm_encoder::CoreTypeSection::new();
112
0
        for ty in &self.types {
113
0
            ty.encode(sec.ty());
114
0
        }
115
0
        component.section(&sec);
116
0
    }
117
}
118
119
impl CoreType {
120
0
    fn encode(&self, enc: wasm_encoder::ComponentCoreTypeEncoder<'_>) {
121
0
        match self {
122
0
            Self::Func(ty) => {
123
0
                enc.core()
124
0
                    .function(ty.params.iter().copied(), ty.results.iter().copied());
125
0
            }
126
0
            Self::Module(mod_ty) => {
127
0
                let mut enc_mod_ty = wasm_encoder::ModuleType::new();
128
0
                for def in &mod_ty.defs {
129
0
                    match def {
130
                        ModuleTypeDef::TypeDef(CompositeType {
131
0
                            inner: CompositeInnerType::Func(func_ty),
132
                            ..
133
0
                        }) => {
134
0
                            enc_mod_ty.ty().function(
135
0
                                func_ty.params.iter().copied(),
136
0
                                func_ty.results.iter().copied(),
137
0
                            );
138
0
                        }
139
                        ModuleTypeDef::TypeDef(_) => {
140
0
                            unimplemented!("non-func types in a component's module type")
141
                        }
142
0
                        ModuleTypeDef::OuterAlias { count, i, kind } => match kind {
143
0
                            CoreOuterAliasKind::Type(_) => {
144
0
                                enc_mod_ty.alias_outer_core_type(*count, *i);
145
0
                            }
146
                        },
147
0
                        ModuleTypeDef::Import(imp) => {
148
0
                            enc_mod_ty.import(
149
0
                                &imp.module,
150
0
                                &imp.field,
151
0
                                crate::core::encode::translate_entity_type(&imp.entity_type),
152
0
                            );
153
0
                        }
154
0
                        ModuleTypeDef::Export(name, ty) => {
155
0
                            enc_mod_ty.export(name, crate::core::encode::translate_entity_type(ty));
156
0
                        }
157
                    }
158
                }
159
0
                enc.module(&enc_mod_ty);
160
            }
161
        }
162
0
    }
163
}
164
165
impl Type {
166
0
    fn encode(&self, enc: wasm_encoder::ComponentTypeEncoder<'_>) {
167
0
        match self {
168
0
            Self::Defined(ty) => {
169
0
                ty.encode(enc.defined_type());
170
0
            }
171
0
            Self::Func(func_ty) => {
172
0
                let mut f = enc.function();
173
174
0
                f.params(func_ty.params.iter().map(|(name, ty)| (name.as_str(), *ty)));
175
0
                f.result(func_ty.unnamed_result_ty());
176
            }
177
0
            Self::Component(comp_ty) => {
178
0
                let mut enc_comp_ty = wasm_encoder::ComponentType::new();
179
0
                for def in &comp_ty.defs {
180
0
                    match def {
181
0
                        ComponentTypeDef::Import(imp) => {
182
0
                            enc_comp_ty.import(&imp.name, imp.ty);
183
0
                        }
184
0
                        ComponentTypeDef::CoreType(ty) => {
185
0
                            ty.encode(enc_comp_ty.core_type());
186
0
                        }
187
0
                        ComponentTypeDef::Type(ty) => {
188
0
                            ty.encode(enc_comp_ty.ty());
189
0
                        }
190
0
                        ComponentTypeDef::Export { name, url: _, ty } => {
191
0
                            enc_comp_ty.export(name, *ty);
192
0
                        }
193
0
                        ComponentTypeDef::Alias(a) => {
194
0
                            enc_comp_ty.alias(translate_alias(a));
195
0
                        }
196
                    }
197
                }
198
0
                enc.component(&enc_comp_ty);
199
            }
200
0
            Self::Instance(inst_ty) => {
201
0
                let mut enc_inst_ty = wasm_encoder::InstanceType::new();
202
0
                for def in &inst_ty.defs {
203
0
                    match def {
204
0
                        InstanceTypeDecl::CoreType(ty) => {
205
0
                            ty.encode(enc_inst_ty.core_type());
206
0
                        }
207
0
                        InstanceTypeDecl::Type(ty) => {
208
0
                            ty.encode(enc_inst_ty.ty());
209
0
                        }
210
0
                        InstanceTypeDecl::Export { name, url: _, ty } => {
211
0
                            enc_inst_ty.export(name, *ty);
212
0
                        }
213
0
                        InstanceTypeDecl::Alias(a) => {
214
0
                            enc_inst_ty.alias(translate_alias(a));
215
0
                        }
216
                    }
217
                }
218
0
                enc.instance(&enc_inst_ty);
219
            }
220
        }
221
0
    }
222
}
223
224
impl DefinedType {
225
0
    fn encode(&self, enc: wasm_encoder::ComponentDefinedTypeEncoder<'_>) {
226
0
        match self {
227
0
            Self::Primitive(ty) => enc.primitive(*ty),
228
0
            Self::Record(ty) => {
229
0
                enc.record(ty.fields.iter().map(|(name, ty)| (name.as_str(), *ty)));
230
            }
231
0
            Self::Variant(ty) => {
232
0
                enc.variant(
233
0
                    ty.cases
234
0
                        .iter()
235
0
                        .map(|(name, ty, refines)| (name.as_str(), *ty, *refines)),
236
                );
237
            }
238
0
            Self::List(ty) => {
239
0
                enc.list(ty.elem_ty);
240
0
            }
241
0
            Self::Tuple(ty) => {
242
0
                enc.tuple(ty.fields.iter().copied());
243
0
            }
244
0
            Self::Flags(ty) => {
245
0
                enc.flags(ty.fields.iter().map(|f| f.as_str()));
246
            }
247
0
            Self::Enum(ty) => {
248
0
                enc.enum_type(ty.variants.iter().map(|v| v.as_str()));
249
            }
250
0
            Self::Option(ty) => {
251
0
                enc.option(ty.inner_ty);
252
0
            }
253
0
            Self::Result(ty) => {
254
0
                enc.result(ty.ok_ty, ty.err_ty);
255
0
            }
256
        }
257
0
    }
258
}
259
260
0
fn translate_canon_opt(options: &[CanonOpt]) -> Vec<wasm_encoder::CanonicalOption> {
261
0
    options
262
0
        .iter()
263
0
        .map(|o| match o {
264
0
            CanonOpt::StringUtf8 => wasm_encoder::CanonicalOption::UTF8,
265
0
            CanonOpt::StringUtf16 => wasm_encoder::CanonicalOption::UTF16,
266
0
            CanonOpt::StringLatin1Utf16 => wasm_encoder::CanonicalOption::CompactUTF16,
267
0
            CanonOpt::Memory(idx) => wasm_encoder::CanonicalOption::Memory(*idx),
268
0
            CanonOpt::Realloc(idx) => wasm_encoder::CanonicalOption::Realloc(*idx),
269
0
            CanonOpt::PostReturn(idx) => wasm_encoder::CanonicalOption::PostReturn(*idx),
270
0
        })
271
0
        .collect()
272
0
}
273
274
0
fn translate_alias(alias: &Alias) -> wasm_encoder::Alias<'_> {
275
0
    match alias {
276
        Alias::InstanceExport {
277
0
            instance,
278
0
            name,
279
0
            kind,
280
        } => wasm_encoder::Alias::InstanceExport {
281
0
            instance: *instance,
282
0
            name,
283
0
            kind: match kind {
284
0
                InstanceExportAliasKind::Module => ComponentExportKind::Module,
285
0
                InstanceExportAliasKind::Component => ComponentExportKind::Component,
286
0
                InstanceExportAliasKind::Instance => ComponentExportKind::Instance,
287
0
                InstanceExportAliasKind::Func => ComponentExportKind::Func,
288
0
                InstanceExportAliasKind::Value => ComponentExportKind::Value,
289
            },
290
        },
291
        Alias::CoreInstanceExport {
292
0
            instance,
293
0
            name,
294
0
            kind,
295
        } => wasm_encoder::Alias::CoreInstanceExport {
296
0
            instance: *instance,
297
0
            name,
298
0
            kind: match kind {
299
0
                CoreInstanceExportAliasKind::Func => ExportKind::Func,
300
0
                CoreInstanceExportAliasKind::Table => ExportKind::Table,
301
0
                CoreInstanceExportAliasKind::Global => ExportKind::Global,
302
0
                CoreInstanceExportAliasKind::Memory => ExportKind::Memory,
303
0
                CoreInstanceExportAliasKind::Tag => ExportKind::Tag,
304
            },
305
        },
306
0
        Alias::Outer { count, i, kind } => wasm_encoder::Alias::Outer {
307
0
            count: *count,
308
0
            index: *i,
309
0
            kind: match kind {
310
0
                OuterAliasKind::Module => ComponentOuterAliasKind::CoreModule,
311
0
                OuterAliasKind::Component => ComponentOuterAliasKind::Component,
312
0
                OuterAliasKind::Type(_) => ComponentOuterAliasKind::Type,
313
0
                OuterAliasKind::CoreType(_) => ComponentOuterAliasKind::CoreType,
314
            },
315
        },
316
    }
317
0
}