wit_component/encoding/
wit.rs

1use crate::encoding::types::{TypeEncodingMaps, ValtypeEncoder};
2use anyhow::Result;
3use indexmap::IndexSet;
4use std::collections::HashMap;
5use std::mem;
6use wasm_encoder::*;
7use 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.
27pub fn encode(resolve: &Resolve, package: PackageId) -> Result<Vec<u8>> {
28    let mut component = encode_component(resolve, package)?;
29    component.raw_custom_section(&crate::base_producers().raw_custom_section());
30    Ok(component.finish())
31}
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.
51pub fn encode_component(resolve: &Resolve, package: PackageId) -> Result<ComponentBuilder> {
52    let mut encoder = Encoder {
53        component: ComponentBuilder::default(),
54        resolve,
55        package,
56    };
57    encoder.run()?;
58
59    let package_metadata = PackageMetadata::extract(resolve, package);
60    encoder.component.custom_section(&CustomSection {
61        name: PackageMetadata::SECTION_NAME.into(),
62        data: package_metadata.encode()?.into(),
63    });
64
65    Ok(encoder.component)
66}
67
68/// Encodes a `world` as a component type.
69pub fn encode_world(resolve: &Resolve, world_id: WorldId) -> Result<ComponentType> {
70    let mut component = InterfaceEncoder::new(resolve);
71    let world = &resolve.worlds[world_id];
72    log::trace!("encoding world {}", world.name);
73
74    // Encode the imports
75    for (name, import) in world.imports.iter() {
76        let name = resolve.name_world_key(name);
77        log::trace!("encoding import {name}");
78        let ty = match import {
79            WorldItem::Interface { id, .. } => {
80                component.interface = Some(*id);
81                let idx = component.encode_instance(*id)?;
82                ComponentTypeRef::Instance(idx)
83            }
84            WorldItem::Function(f) => {
85                component.interface = None;
86                let idx = component.encode_func_type(resolve, f)?;
87                ComponentTypeRef::Func(idx)
88            }
89            WorldItem::Type(t) => {
90                component.interface = None;
91                component.import_types = true;
92                component.encode_valtype(resolve, &Type::Id(*t))?;
93                component.import_types = false;
94                continue;
95            }
96        };
97        component.outer.import(&name, ty);
98    }
99    // Encode the exports
100    for (name, export) in world.exports.iter() {
101        let name = resolve.name_world_key(name);
102        log::trace!("encoding export {name}");
103        let ty = match export {
104            WorldItem::Interface { id, .. } => {
105                component.interface = Some(*id);
106                let idx = component.encode_instance(*id)?;
107                ComponentTypeRef::Instance(idx)
108            }
109            WorldItem::Function(f) => {
110                component.interface = None;
111                let idx = component.encode_func_type(resolve, f)?;
112                ComponentTypeRef::Func(idx)
113            }
114            WorldItem::Type(_) => unreachable!(),
115        };
116        component.outer.export(&name, ty);
117    }
118
119    Ok(component.outer)
120}
121
122struct Encoder<'a> {
123    component: ComponentBuilder,
124    resolve: &'a Resolve,
125    package: PackageId,
126}
127
128impl Encoder<'_> {
129    fn run(&mut self) -> Result<()> {
130        // Encode all interfaces as component types and then export them.
131        for (name, &id) in self.resolve.packages[self.package].interfaces.iter() {
132            let component_ty = self.encode_interface(id)?;
133            let ty = self.component.type_component(&component_ty);
134            self.component
135                .export(name.as_ref(), ComponentExportKind::Type, ty, None);
136        }
137
138        // For each `world` encode it directly as a component and then create a
139        // wrapper component that exports that component.
140        for (name, &world) in self.resolve.packages[self.package].worlds.iter() {
141            let component_ty = encode_world(self.resolve, world)?;
142
143            let world = &self.resolve.worlds[world];
144            let mut wrapper = ComponentType::new();
145            wrapper.ty().component(&component_ty);
146            let pkg = &self.resolve.packages[world.package.unwrap()];
147            wrapper.export(&pkg.name.interface_id(name), ComponentTypeRef::Component(0));
148
149            let ty = self.component.type_component(&wrapper);
150            self.component
151                .export(name.as_ref(), ComponentExportKind::Type, ty, None);
152        }
153
154        Ok(())
155    }
156
157    fn encode_interface(&mut self, id: InterfaceId) -> Result<ComponentType> {
158        // Build a set of interfaces reachable from this document, including the
159        // interfaces in the document itself. This is used to import instances
160        // into the component type we're encoding. Note that entire interfaces
161        // are imported with all their types as opposed to just the needed types
162        // in an interface for this document. That's done to assist with the
163        // decoding process where everyone's view of a foreign document agrees
164        // notably on the order that types are defined in to assist with
165        // roundtripping.
166        let mut interfaces = IndexSet::new();
167        self.add_live_interfaces(&mut interfaces, id);
168
169        // Seed the set of used names with all exported interfaces to ensure
170        // that imported interfaces choose different names as the import names
171        // aren't used during decoding.
172        let mut used_names = IndexSet::new();
173        for id in interfaces.iter() {
174            let iface = &self.resolve.interfaces[*id];
175            if iface.package == Some(self.package) {
176                let first = used_names.insert(iface.name.as_ref().unwrap().clone());
177                assert!(first);
178            }
179        }
180
181        let mut encoder = InterfaceEncoder::new(self.resolve);
182        for interface in interfaces {
183            encoder.interface = Some(interface);
184            let iface = &self.resolve.interfaces[interface];
185            let name = self.resolve.id_of(interface).unwrap();
186            if interface == id {
187                let idx = encoder.encode_instance(interface)?;
188                log::trace!("exporting self as {idx}");
189                encoder.outer.export(&name, ComponentTypeRef::Instance(idx));
190            } else {
191                encoder.push_instance();
192                for (_, id) in iface.types.iter() {
193                    encoder.encode_valtype(self.resolve, &Type::Id(*id))?;
194                }
195                let instance = encoder.pop_instance();
196                let idx = encoder.outer.type_count();
197                encoder.outer.ty().instance(&instance);
198                encoder.import_map.insert(interface, encoder.instances);
199                encoder.instances += 1;
200                encoder.outer.import(&name, ComponentTypeRef::Instance(idx));
201            }
202        }
203
204        encoder.interface = None;
205
206        Ok(encoder.outer)
207    }
208
209    /// Recursively add all live interfaces reachable from `id` into the
210    /// `interfaces` set, and then add `id` to the set.
211    fn add_live_interfaces(&self, interfaces: &mut IndexSet<InterfaceId>, id: InterfaceId) {
212        if interfaces.contains(&id) {
213            return;
214        }
215        for id in self.resolve.interface_direct_deps(id) {
216            self.add_live_interfaces(interfaces, id);
217        }
218        assert!(interfaces.insert(id));
219    }
220}
221
222struct InterfaceEncoder<'a> {
223    resolve: &'a Resolve,
224    outer: ComponentType,
225    ty: Option<InstanceType>,
226    type_encoding_maps: TypeEncodingMaps<'a>,
227    saved_maps: Option<TypeEncodingMaps<'a>>,
228    import_map: HashMap<InterfaceId, u32>,
229    outer_type_map: HashMap<TypeId, u32>,
230    instances: u32,
231    import_types: bool,
232    interface: Option<InterfaceId>,
233}
234
235impl InterfaceEncoder<'_> {
236    fn new(resolve: &Resolve) -> InterfaceEncoder<'_> {
237        InterfaceEncoder {
238            resolve,
239            outer: ComponentType::new(),
240            ty: None,
241            type_encoding_maps: Default::default(),
242            import_map: Default::default(),
243            outer_type_map: Default::default(),
244            instances: 0,
245            saved_maps: None,
246            import_types: false,
247            interface: None,
248        }
249    }
250
251    fn encode_instance(&mut self, interface: InterfaceId) -> Result<u32> {
252        self.push_instance();
253        let iface = &self.resolve.interfaces[interface];
254        let mut type_order = IndexSet::new();
255        for (_, id) in iface.types.iter() {
256            self.encode_valtype(self.resolve, &Type::Id(*id))?;
257            type_order.insert(*id);
258        }
259
260        // Sort functions based on whether or not they're associated with
261        // resources.
262        //
263        // This is done here to ensure that when a WIT package is printed as WIT
264        // then decoded, or if it's printed as Wasm then decoded, the final
265        // result is the same. When printing via WIT resource methods are
266        // attached to the resource types themselves meaning that they'll appear
267        // intermingled with the rest of the types, namely first before all
268        // other functions. The purpose of this sort is to perform a stable sort
269        // over all functions by shuffling the resource-related functions first,
270        // in order of when their associated resource was encoded, and putting
271        // freestanding functions last.
272        //
273        // Note that this is not actually required for correctness, it's
274        // basically here to make fuzzing happy.
275        let mut funcs = iface.functions.iter().collect::<Vec<_>>();
276        funcs.sort_by_key(|(_name, func)| match func.kind.resource() {
277            Some(id) => type_order.get_index_of(&id).unwrap(),
278            None => type_order.len(),
279        });
280
281        for (name, func) in funcs {
282            let ty = self.encode_func_type(self.resolve, func)?;
283            self.ty
284                .as_mut()
285                .unwrap()
286                .export(name, ComponentTypeRef::Func(ty));
287        }
288        let instance = self.pop_instance();
289        let idx = self.outer.type_count();
290        self.outer.ty().instance(&instance);
291        self.import_map.insert(interface, self.instances);
292        self.instances += 1;
293        Ok(idx)
294    }
295
296    fn push_instance(&mut self) {
297        assert!(self.ty.is_none());
298        assert!(self.saved_maps.is_none());
299        self.saved_maps = Some(mem::take(&mut self.type_encoding_maps));
300        self.ty = Some(InstanceType::default());
301    }
302
303    fn pop_instance(&mut self) -> InstanceType {
304        let maps = self.saved_maps.take().unwrap();
305        self.type_encoding_maps = maps;
306        mem::take(&mut self.ty).unwrap()
307    }
308}
309
310impl<'a> ValtypeEncoder<'a> for InterfaceEncoder<'a> {
311    fn defined_type(&mut self) -> (u32, ComponentDefinedTypeEncoder<'_>) {
312        match &mut self.ty {
313            Some(ty) => (ty.type_count(), ty.ty().defined_type()),
314            None => (self.outer.type_count(), self.outer.ty().defined_type()),
315        }
316    }
317    fn define_function_type(&mut self) -> (u32, ComponentFuncTypeEncoder<'_>) {
318        match &mut self.ty {
319            Some(ty) => (ty.type_count(), ty.ty().function()),
320            None => (self.outer.type_count(), self.outer.ty().function()),
321        }
322    }
323    fn export_type(&mut self, index: u32, name: &'a str) -> Option<u32> {
324        match &mut self.ty {
325            Some(ty) => {
326                assert!(!self.import_types);
327                let ret = ty.type_count();
328                ty.export(name, ComponentTypeRef::Type(TypeBounds::Eq(index)));
329                Some(ret)
330            }
331            None => {
332                let ret = self.outer.type_count();
333                if self.import_types {
334                    self.outer
335                        .import(name, ComponentTypeRef::Type(TypeBounds::Eq(index)));
336                } else {
337                    self.outer
338                        .export(name, ComponentTypeRef::Type(TypeBounds::Eq(index)));
339                }
340                Some(ret)
341            }
342        }
343    }
344    fn export_resource(&mut self, name: &'a str) -> u32 {
345        let type_ref = ComponentTypeRef::Type(TypeBounds::SubResource);
346        match &mut self.ty {
347            Some(ty) => {
348                assert!(!self.import_types);
349                ty.export(name, type_ref);
350                ty.type_count() - 1
351            }
352            None => {
353                if self.import_types {
354                    self.outer.import(name, type_ref);
355                } else {
356                    self.outer.export(name, type_ref);
357                }
358                self.outer.type_count() - 1
359            }
360        }
361    }
362    fn type_encoding_maps(&mut self) -> &mut TypeEncodingMaps<'a> {
363        &mut self.type_encoding_maps
364    }
365    fn interface(&self) -> Option<InterfaceId> {
366        self.interface
367    }
368    fn import_type(&mut self, owner: InterfaceId, id: TypeId) -> u32 {
369        let ty = &self.resolve.types[id];
370        let instance = self.import_map[&owner];
371        let outer_idx = *self.outer_type_map.entry(id).or_insert_with(|| {
372            let ret = self.outer.type_count();
373            self.outer.alias(Alias::InstanceExport {
374                instance,
375                name: ty.name.as_ref().unwrap(),
376                kind: ComponentExportKind::Type,
377            });
378            ret
379        });
380        match &mut self.ty {
381            Some(ty) => {
382                let ret = ty.type_count();
383                ty.alias(Alias::Outer {
384                    count: 1,
385                    index: outer_idx,
386                    kind: ComponentOuterAliasKind::Type,
387                });
388                ret
389            }
390            None => outer_idx,
391        }
392    }
393}