Coverage Report

Created: 2025-01-06 07:43

/src/wasm-tools/crates/wit-component/src/encoding/wit.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::encoding::types::{FunctionKey, ValtypeEncoder};
2
use anyhow::Result;
3
use indexmap::IndexSet;
4
use std::collections::HashMap;
5
use std::mem;
6
use wasm_encoder::*;
7
use wit_parser::*;
8
9
/// Encodes the given `package` within `resolve` to a binary WebAssembly
10
/// representation.
11
///
12
/// This function is the root of the implementation of serializing a WIT package
13
/// into a WebAssembly representation. The wasm representation serves two
14
/// purposes:
15
///
16
/// * One is to be a binary encoding of a WIT document which is ideally more
17
///   stable than the WIT textual format itself.
18
/// * Another is to provide a clear mapping of all WIT features into the
19
///   component model through use of its binary representation.
20
///
21
/// The `resolve` provided is a set of packages and types and such and the
22
/// `package` argument is an ID within the world provided. The documents within
23
/// `package` will all be encoded into the binary returned.
24
///
25
/// The binary returned can be [`decode`d](crate::decode) to recover the WIT
26
/// package provided.
27
12.0k
pub fn encode(resolve: &Resolve, package: PackageId) -> Result<Vec<u8>> {
28
12.0k
    let mut component = encode_component(resolve, package)?;
29
12.0k
    component.raw_custom_section(&crate::base_producers().raw_custom_section());
30
12.0k
    Ok(component.finish())
31
12.0k
}
32
33
/// Encodes the given `package` within `resolve` to a binary WebAssembly
34
/// representation.
35
///
36
/// This function is the root of the implementation of serializing a WIT package
37
/// into a WebAssembly representation. The wasm representation serves two
38
/// purposes:
39
///
40
/// * One is to be a binary encoding of a WIT document which is ideally more
41
///   stable than the WIT textual format itself.
42
/// * Another is to provide a clear mapping of all WIT features into the
43
///   component model through use of its binary representation.
44
///
45
/// The `resolve` provided is a set of packages and types and such and the
46
/// `package` argument is an ID within the world provided. The documents within
47
/// `package` will all be encoded into the binary returned.
48
///
49
/// The binary returned can be [`decode`d](crate::decode) to recover the WIT
50
/// package provided.
51
12.0k
pub fn encode_component(resolve: &Resolve, package: PackageId) -> Result<ComponentBuilder> {
52
12.0k
    let mut encoder = Encoder {
53
12.0k
        component: ComponentBuilder::default(),
54
12.0k
        resolve,
55
12.0k
        package,
56
12.0k
    };
57
12.0k
    encoder.run()?;
58
59
12.0k
    let package_metadata = PackageMetadata::extract(resolve, package);
60
12.0k
    encoder.component.custom_section(&CustomSection {
61
12.0k
        name: PackageMetadata::SECTION_NAME.into(),
62
12.0k
        data: package_metadata.encode()?.into(),
63
12.0k
    });
64
12.0k
65
12.0k
    Ok(encoder.component)
66
12.0k
}
67
68
/// Encodes a `world` as a component type.
69
31.9k
pub fn encode_world(resolve: &Resolve, world_id: WorldId) -> Result<ComponentType> {
70
31.9k
    let mut component = InterfaceEncoder::new(resolve);
71
31.9k
    let world = &resolve.worlds[world_id];
72
31.9k
    log::trace!("encoding world {}", world.name);
73
74
    // This sort is similar in purpose to the sort below in
75
    // `encode_instance`, but different in its sort. The purpose here is
76
    // to ensure that when a document is either printed as WIT or
77
    // encoded as wasm that decoding from those artifacts produces the
78
    // same WIT package. Namely both encoding processes should encode
79
    // things in the same order.
80
    //
81
    // When printing worlds in WIT freestanding function imports are
82
    // printed first, then types. Resource functions are attached to
83
    // types which means that they all come last. Sort all
84
    // resource-related functions here to the back of the `imports` list
85
    // while keeping everything else in front, using a stable sort to
86
    // preserve preexisting ordering.
87
31.9k
    let mut imports = world.imports.iter().collect::<Vec<_>>();
88
129k
    imports.sort_by_key(|(_name, import)| match import {
89
45.8k
        WorldItem::Function(f) => match f.kind {
90
6.64k
            FunctionKind::Freestanding => 0,
91
39.1k
            _ => 1,
92
        },
93
83.4k
        _ => 0,
94
129k
    });
95
96
    // Encode the imports
97
114k
    for (name, import) in imports {
98
82.3k
        let name = resolve.name_world_key(name);
99
82.3k
        log::trace!("encoding import {name}");
100
82.3k
        let ty = match import {
101
19.5k
            WorldItem::Interface { id, .. } => {
102
19.5k
                component.interface = Some(*id);
103
19.5k
                let idx = component.encode_instance(*id)?;
104
19.5k
                ComponentTypeRef::Instance(idx)
105
            }
106
25.1k
            WorldItem::Function(f) => {
107
25.1k
                component.interface = None;
108
25.1k
                let idx = component.encode_func_type(resolve, f)?;
109
25.1k
                ComponentTypeRef::Func(idx)
110
            }
111
37.6k
            WorldItem::Type(t) => {
112
37.6k
                component.interface = None;
113
37.6k
                component.import_types = true;
114
37.6k
                component.encode_valtype(resolve, &Type::Id(*t))?;
115
37.6k
                component.import_types = false;
116
37.6k
                continue;
117
            }
118
        };
119
44.6k
        component.outer.import(&name, ty);
120
    }
121
    // Encode the exports
122
53.5k
    for (name, export) in world.exports.iter() {
123
53.5k
        let name = resolve.name_world_key(name);
124
53.5k
        log::trace!("encoding export {name}");
125
53.5k
        let ty = match export {
126
49.1k
            WorldItem::Interface { id, .. } => {
127
49.1k
                component.interface = Some(*id);
128
49.1k
                let idx = component.encode_instance(*id)?;
129
49.1k
                ComponentTypeRef::Instance(idx)
130
            }
131
4.41k
            WorldItem::Function(f) => {
132
4.41k
                component.interface = None;
133
4.41k
                let idx = component.encode_func_type(resolve, f)?;
134
4.41k
                ComponentTypeRef::Func(idx)
135
            }
136
0
            WorldItem::Type(_) => unreachable!(),
137
        };
138
53.5k
        component.outer.export(&name, ty);
139
    }
140
141
31.9k
    Ok(component.outer)
142
31.9k
}
143
144
struct Encoder<'a> {
145
    component: ComponentBuilder,
146
    resolve: &'a Resolve,
147
    package: PackageId,
148
}
149
150
impl Encoder<'_> {
151
12.0k
    fn run(&mut self) -> Result<()> {
152
        // Encode all interfaces as component types and then export them.
153
50.5k
        for (name, &id) in self.resolve.packages[self.package].interfaces.iter() {
154
50.5k
            let component_ty = self.encode_interface(id)?;
155
50.5k
            let ty = self.component.type_component(&component_ty);
156
50.5k
            self.component
157
50.5k
                .export(name.as_ref(), ComponentExportKind::Type, ty, None);
158
        }
159
160
        // For each `world` encode it directly as a component and then create a
161
        // wrapper component that exports that component.
162
25.6k
        for (name, &world) in self.resolve.packages[self.package].worlds.iter() {
163
25.6k
            let component_ty = encode_world(self.resolve, world)?;
164
165
25.6k
            let world = &self.resolve.worlds[world];
166
25.6k
            let mut wrapper = ComponentType::new();
167
25.6k
            wrapper.ty().component(&component_ty);
168
25.6k
            let pkg = &self.resolve.packages[world.package.unwrap()];
169
25.6k
            wrapper.export(&pkg.name.interface_id(name), ComponentTypeRef::Component(0));
170
25.6k
171
25.6k
            let ty = self.component.type_component(&wrapper);
172
25.6k
            self.component
173
25.6k
                .export(name.as_ref(), ComponentExportKind::Type, ty, None);
174
        }
175
176
12.0k
        Ok(())
177
12.0k
    }
178
179
50.5k
    fn encode_interface(&mut self, id: InterfaceId) -> Result<ComponentType> {
180
50.5k
        // Build a set of interfaces reachable from this document, including the
181
50.5k
        // interfaces in the document itself. This is used to import instances
182
50.5k
        // into the component type we're encoding. Note that entire interfaces
183
50.5k
        // are imported with all their types as opposed to just the needed types
184
50.5k
        // in an interface for this document. That's done to assist with the
185
50.5k
        // decoding process where everyone's view of a foreign document agrees
186
50.5k
        // notably on the order that types are defined in to assist with
187
50.5k
        // roundtripping.
188
50.5k
        let mut interfaces = IndexSet::new();
189
50.5k
        self.add_live_interfaces(&mut interfaces, id);
190
50.5k
191
50.5k
        // Seed the set of used names with all exported interfaces to ensure
192
50.5k
        // that imported interfaces choose different names as the import names
193
50.5k
        // aren't used during decoding.
194
50.5k
        let mut used_names = IndexSet::new();
195
58.1k
        for id in interfaces.iter() {
196
58.1k
            let iface = &self.resolve.interfaces[*id];
197
58.1k
            if iface.package == Some(self.package) {
198
58.1k
                let first = used_names.insert(iface.name.as_ref().unwrap().clone());
199
58.1k
                assert!(first);
200
0
            }
201
        }
202
203
50.5k
        let mut encoder = InterfaceEncoder::new(self.resolve);
204
108k
        for interface in interfaces {
205
58.1k
            encoder.interface = Some(interface);
206
58.1k
            let iface = &self.resolve.interfaces[interface];
207
58.1k
            let name = self.resolve.id_of(interface).unwrap();
208
58.1k
            if interface == id {
209
50.5k
                let idx = encoder.encode_instance(interface)?;
210
50.5k
                log::trace!("exporting self as {idx}");
211
50.5k
                encoder.outer.export(&name, ComponentTypeRef::Instance(idx));
212
            } else {
213
7.55k
                encoder.push_instance();
214
28.9k
                for (_, id) in iface.types.iter() {
215
28.9k
                    encoder.encode_valtype(self.resolve, &Type::Id(*id))?;
216
                }
217
7.55k
                let instance = encoder.pop_instance();
218
7.55k
                let idx = encoder.outer.type_count();
219
7.55k
                encoder.outer.ty().instance(&instance);
220
7.55k
                encoder.import_map.insert(interface, encoder.instances);
221
7.55k
                encoder.instances += 1;
222
7.55k
                encoder.outer.import(&name, ComponentTypeRef::Instance(idx));
223
            }
224
        }
225
226
50.5k
        encoder.interface = None;
227
50.5k
228
50.5k
        Ok(encoder.outer)
229
50.5k
    }
230
231
    /// Recursively add all live interfaces reachable from `id` into the
232
    /// `interfaces` set, and then add `id` to the set.
233
79.9k
    fn add_live_interfaces(&self, interfaces: &mut IndexSet<InterfaceId>, id: InterfaceId) {
234
79.9k
        if interfaces.contains(&id) {
235
21.8k
            return;
236
58.1k
        }
237
58.1k
        for id in self.resolve.interface_direct_deps(id) {
238
29.4k
            self.add_live_interfaces(interfaces, id);
239
29.4k
        }
240
58.1k
        assert!(interfaces.insert(id));
241
79.9k
    }
242
}
243
244
struct InterfaceEncoder<'a> {
245
    resolve: &'a Resolve,
246
    outer: ComponentType,
247
    ty: Option<InstanceType>,
248
    func_type_map: HashMap<FunctionKey<'a>, u32>,
249
    type_map: HashMap<TypeId, u32>,
250
    saved_types: Option<(HashMap<TypeId, u32>, HashMap<FunctionKey<'a>, u32>)>,
251
    import_map: HashMap<InterfaceId, u32>,
252
    outer_type_map: HashMap<TypeId, u32>,
253
    instances: u32,
254
    import_types: bool,
255
    interface: Option<InterfaceId>,
256
}
257
258
impl InterfaceEncoder<'_> {
259
82.5k
    fn new(resolve: &Resolve) -> InterfaceEncoder<'_> {
260
82.5k
        InterfaceEncoder {
261
82.5k
            resolve,
262
82.5k
            outer: ComponentType::new(),
263
82.5k
            ty: None,
264
82.5k
            type_map: Default::default(),
265
82.5k
            func_type_map: Default::default(),
266
82.5k
            import_map: Default::default(),
267
82.5k
            outer_type_map: Default::default(),
268
82.5k
            instances: 0,
269
82.5k
            saved_types: None,
270
82.5k
            import_types: false,
271
82.5k
            interface: None,
272
82.5k
        }
273
82.5k
    }
274
275
119k
    fn encode_instance(&mut self, interface: InterfaceId) -> Result<u32> {
276
119k
        self.push_instance();
277
119k
        let iface = &self.resolve.interfaces[interface];
278
119k
        let mut type_order = IndexSet::new();
279
365k
        for (_, id) in iface.types.iter() {
280
365k
            self.encode_valtype(self.resolve, &Type::Id(*id))?;
281
365k
            type_order.insert(*id);
282
        }
283
284
        // Sort functions based on whether or not they're associated with
285
        // resources.
286
        //
287
        // This is done here to ensure that when a WIT package is printed as WIT
288
        // then decoded, or if it's printed as Wasm then decoded, the final
289
        // result is the same. When printing via WIT resource methods are
290
        // attached to the resource types themselves meaning that they'll appear
291
        // intermingled with the rest of the types, namely first before all
292
        // other functions. The purpose of this sort is to perform a stable sort
293
        // over all functions by shuffling the resource-related functions first,
294
        // in order of when their associated resource was encoded, and putting
295
        // freestanding functions last.
296
        //
297
        // Note that this is not actually required for correctness, it's
298
        // basically here to make fuzzing happy.
299
119k
        let mut funcs = iface.functions.iter().collect::<Vec<_>>();
300
385k
        funcs.sort_by_key(|(_name, func)| match func.kind {
301
180k
            FunctionKind::Freestanding => type_order.len(),
302
99.9k
            FunctionKind::Method(id) | FunctionKind::Constructor(id) | FunctionKind::Static(id) => {
303
205k
                type_order.get_index_of(&id).unwrap()
304
            }
305
385k
        });
306
307
322k
        for (name, func) in funcs {
308
202k
            let ty = self.encode_func_type(self.resolve, func)?;
309
202k
            self.ty
310
202k
                .as_mut()
311
202k
                .unwrap()
312
202k
                .export(name, ComponentTypeRef::Func(ty));
313
        }
314
119k
        let instance = self.pop_instance();
315
119k
        let idx = self.outer.type_count();
316
119k
        self.outer.ty().instance(&instance);
317
119k
        self.import_map.insert(interface, self.instances);
318
119k
        self.instances += 1;
319
119k
        Ok(idx)
320
119k
    }
321
322
126k
    fn push_instance(&mut self) {
323
126k
        assert!(self.ty.is_none());
324
126k
        assert!(self.saved_types.is_none());
325
126k
        self.saved_types = Some((
326
126k
            mem::take(&mut self.type_map),
327
126k
            mem::take(&mut self.func_type_map),
328
126k
        ));
329
126k
        self.ty = Some(InstanceType::default());
330
126k
    }
331
332
126k
    fn pop_instance(&mut self) -> InstanceType {
333
126k
        let (types, funcs) = self.saved_types.take().unwrap();
334
126k
        self.type_map = types;
335
126k
        self.func_type_map = funcs;
336
126k
        mem::take(&mut self.ty).unwrap()
337
126k
    }
338
}
339
340
impl<'a> ValtypeEncoder<'a> for InterfaceEncoder<'a> {
341
739k
    fn defined_type(&mut self) -> (u32, ComponentDefinedTypeEncoder<'_>) {
342
739k
        match &mut self.ty {
343
656k
            Some(ty) => (ty.type_count(), ty.ty().defined_type()),
344
82.7k
            None => (self.outer.type_count(), self.outer.ty().defined_type()),
345
        }
346
739k
    }
347
144k
    fn define_function_type(&mut self) -> (u32, ComponentFuncTypeEncoder<'_>) {
348
144k
        match &mut self.ty {
349
123k
            Some(ty) => (ty.type_count(), ty.ty().function()),
350
20.9k
            None => (self.outer.type_count(), self.outer.ty().function()),
351
        }
352
144k
    }
353
403k
    fn export_type(&mut self, index: u32, name: &'a str) -> Option<u32> {
354
403k
        match &mut self.ty {
355
370k
            Some(ty) => {
356
370k
                assert!(!self.import_types);
357
370k
                let ret = ty.type_count();
358
370k
                ty.export(name, ComponentTypeRef::Type(TypeBounds::Eq(index)));
359
370k
                Some(ret)
360
            }
361
            None => {
362
33.5k
                let ret = self.outer.type_count();
363
33.5k
                if self.import_types {
364
33.5k
                    self.outer
365
33.5k
                        .import(name, ComponentTypeRef::Type(TypeBounds::Eq(index)));
366
33.5k
                } else {
367
0
                    self.outer
368
0
                        .export(name, ComponentTypeRef::Type(TypeBounds::Eq(index)));
369
0
                }
370
33.5k
                Some(ret)
371
            }
372
        }
373
403k
    }
374
28.8k
    fn export_resource(&mut self, name: &'a str) -> u32 {
375
28.8k
        let type_ref = ComponentTypeRef::Type(TypeBounds::SubResource);
376
28.8k
        match &mut self.ty {
377
24.7k
            Some(ty) => {
378
24.7k
                assert!(!self.import_types);
379
24.7k
                ty.export(name, type_ref);
380
24.7k
                ty.type_count() - 1
381
            }
382
            None => {
383
4.11k
                if self.import_types {
384
4.11k
                    self.outer.import(name, type_ref);
385
4.11k
                } else {
386
0
                    self.outer.export(name, type_ref);
387
0
                }
388
4.11k
                self.outer.type_count() - 1
389
            }
390
        }
391
28.8k
    }
392
1.99M
    fn type_map(&mut self) -> &mut HashMap<TypeId, u32> {
393
1.99M
        &mut self.type_map
394
1.99M
    }
395
427k
    fn interface(&self) -> Option<InterfaceId> {
396
427k
        self.interface
397
427k
    }
398
32.9k
    fn import_type(&mut self, owner: InterfaceId, id: TypeId) -> u32 {
399
32.9k
        let ty = &self.resolve.types[id];
400
32.9k
        let instance = self.import_map[&owner];
401
32.9k
        let outer_idx = *self.outer_type_map.entry(id).or_insert_with(|| {
402
24.8k
            let ret = self.outer.type_count();
403
24.8k
            self.outer.alias(Alias::InstanceExport {
404
24.8k
                instance,
405
24.8k
                name: ty.name.as_ref().unwrap(),
406
24.8k
                kind: ComponentExportKind::Type,
407
24.8k
            });
408
24.8k
            ret
409
32.9k
        });
410
32.9k
        match &mut self.ty {
411
27.0k
            Some(ty) => {
412
27.0k
                let ret = ty.type_count();
413
27.0k
                ty.alias(Alias::Outer {
414
27.0k
                    count: 1,
415
27.0k
                    index: outer_idx,
416
27.0k
                    kind: ComponentOuterAliasKind::Type,
417
27.0k
                });
418
27.0k
                ret
419
            }
420
5.86k
            None => outer_idx,
421
        }
422
32.9k
    }
423
376k
    fn func_type_map(&mut self) -> &mut HashMap<FunctionKey<'a>, u32> {
424
376k
        &mut self.func_type_map
425
376k
    }
426
}