wit_component/encoding/
wit.rs

1use crate::encoding::types::{FunctionKey, 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    func_type_map: HashMap<FunctionKey<'a>, u32>,
227    type_map: HashMap<TypeId, u32>,
228    saved_types: Option<(HashMap<TypeId, u32>, HashMap<FunctionKey<'a>, u32>)>,
229    import_map: HashMap<InterfaceId, u32>,
230    outer_type_map: HashMap<TypeId, u32>,
231    instances: u32,
232    import_types: bool,
233    interface: Option<InterfaceId>,
234}
235
236impl InterfaceEncoder<'_> {
237    fn new(resolve: &Resolve) -> InterfaceEncoder<'_> {
238        InterfaceEncoder {
239            resolve,
240            outer: ComponentType::new(),
241            ty: None,
242            type_map: Default::default(),
243            func_type_map: Default::default(),
244            import_map: Default::default(),
245            outer_type_map: Default::default(),
246            instances: 0,
247            saved_types: None,
248            import_types: false,
249            interface: None,
250        }
251    }
252
253    fn encode_instance(&mut self, interface: InterfaceId) -> Result<u32> {
254        self.push_instance();
255        let iface = &self.resolve.interfaces[interface];
256        let mut type_order = IndexSet::new();
257        for (_, id) in iface.types.iter() {
258            self.encode_valtype(self.resolve, &Type::Id(*id))?;
259            type_order.insert(*id);
260        }
261
262        // Sort functions based on whether or not they're associated with
263        // resources.
264        //
265        // This is done here to ensure that when a WIT package is printed as WIT
266        // then decoded, or if it's printed as Wasm then decoded, the final
267        // result is the same. When printing via WIT resource methods are
268        // attached to the resource types themselves meaning that they'll appear
269        // intermingled with the rest of the types, namely first before all
270        // other functions. The purpose of this sort is to perform a stable sort
271        // over all functions by shuffling the resource-related functions first,
272        // in order of when their associated resource was encoded, and putting
273        // freestanding functions last.
274        //
275        // Note that this is not actually required for correctness, it's
276        // basically here to make fuzzing happy.
277        let mut funcs = iface.functions.iter().collect::<Vec<_>>();
278        funcs.sort_by_key(|(_name, func)| match func.kind.resource() {
279            Some(id) => type_order.get_index_of(&id).unwrap(),
280            None => type_order.len(),
281        });
282
283        for (name, func) in funcs {
284            let ty = self.encode_func_type(self.resolve, func)?;
285            self.ty
286                .as_mut()
287                .unwrap()
288                .export(name, ComponentTypeRef::Func(ty));
289        }
290        let instance = self.pop_instance();
291        let idx = self.outer.type_count();
292        self.outer.ty().instance(&instance);
293        self.import_map.insert(interface, self.instances);
294        self.instances += 1;
295        Ok(idx)
296    }
297
298    fn push_instance(&mut self) {
299        assert!(self.ty.is_none());
300        assert!(self.saved_types.is_none());
301        self.saved_types = Some((
302            mem::take(&mut self.type_map),
303            mem::take(&mut self.func_type_map),
304        ));
305        self.ty = Some(InstanceType::default());
306    }
307
308    fn pop_instance(&mut self) -> InstanceType {
309        let (types, funcs) = self.saved_types.take().unwrap();
310        self.type_map = types;
311        self.func_type_map = funcs;
312        mem::take(&mut self.ty).unwrap()
313    }
314}
315
316impl<'a> ValtypeEncoder<'a> for InterfaceEncoder<'a> {
317    fn defined_type(&mut self) -> (u32, ComponentDefinedTypeEncoder<'_>) {
318        match &mut self.ty {
319            Some(ty) => (ty.type_count(), ty.ty().defined_type()),
320            None => (self.outer.type_count(), self.outer.ty().defined_type()),
321        }
322    }
323    fn define_function_type(&mut self) -> (u32, ComponentFuncTypeEncoder<'_>) {
324        match &mut self.ty {
325            Some(ty) => (ty.type_count(), ty.ty().function()),
326            None => (self.outer.type_count(), self.outer.ty().function()),
327        }
328    }
329    fn export_type(&mut self, index: u32, name: &'a str) -> Option<u32> {
330        match &mut self.ty {
331            Some(ty) => {
332                assert!(!self.import_types);
333                let ret = ty.type_count();
334                ty.export(name, ComponentTypeRef::Type(TypeBounds::Eq(index)));
335                Some(ret)
336            }
337            None => {
338                let ret = self.outer.type_count();
339                if self.import_types {
340                    self.outer
341                        .import(name, ComponentTypeRef::Type(TypeBounds::Eq(index)));
342                } else {
343                    self.outer
344                        .export(name, ComponentTypeRef::Type(TypeBounds::Eq(index)));
345                }
346                Some(ret)
347            }
348        }
349    }
350    fn export_resource(&mut self, name: &'a str) -> u32 {
351        let type_ref = ComponentTypeRef::Type(TypeBounds::SubResource);
352        match &mut self.ty {
353            Some(ty) => {
354                assert!(!self.import_types);
355                ty.export(name, type_ref);
356                ty.type_count() - 1
357            }
358            None => {
359                if self.import_types {
360                    self.outer.import(name, type_ref);
361                } else {
362                    self.outer.export(name, type_ref);
363                }
364                self.outer.type_count() - 1
365            }
366        }
367    }
368    fn type_map(&mut self) -> &mut HashMap<TypeId, u32> {
369        &mut self.type_map
370    }
371    fn interface(&self) -> Option<InterfaceId> {
372        self.interface
373    }
374    fn import_type(&mut self, owner: InterfaceId, id: TypeId) -> u32 {
375        let ty = &self.resolve.types[id];
376        let instance = self.import_map[&owner];
377        let outer_idx = *self.outer_type_map.entry(id).or_insert_with(|| {
378            let ret = self.outer.type_count();
379            self.outer.alias(Alias::InstanceExport {
380                instance,
381                name: ty.name.as_ref().unwrap(),
382                kind: ComponentExportKind::Type,
383            });
384            ret
385        });
386        match &mut self.ty {
387            Some(ty) => {
388                let ret = ty.type_count();
389                ty.alias(Alias::Outer {
390                    count: 1,
391                    index: outer_idx,
392                    kind: ComponentOuterAliasKind::Type,
393                });
394                ret
395            }
396            None => outer_idx,
397        }
398    }
399    fn func_type_map(&mut self) -> &mut HashMap<FunctionKey<'a>, u32> {
400        &mut self.func_type_map
401    }
402}