1use crate::encoding::types::{TypeEncodingMaps, ValtypeEncoder, extern_name};
2use anyhow::Result;
3use indexmap::IndexSet;
4use std::collections::HashMap;
5use std::mem;
6use wasm_encoder::*;
7use wit_parser::*;
8
9pub 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
33pub 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
68pub 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 for (key, import) in world.imports.iter() {
76 log::trace!("encoding import {}", resolve.name_world_key(key));
77 let ty = match import {
78 WorldItem::Interface { id, .. } => {
79 component.interface = Some(*id);
80 let idx = component.encode_instance(*id)?;
81 ComponentTypeRef::Instance(idx)
82 }
83 WorldItem::Function(f) => {
84 component.interface = None;
85 let idx = component.encode_func_type(resolve, f)?;
86 ComponentTypeRef::Func(idx)
87 }
88 WorldItem::Type { id, .. } => {
89 component.interface = None;
90 component.import_types = true;
91 component.encode_valtype(resolve, &Type::Id(*id))?;
92 component.import_types = false;
93 continue;
94 }
95 };
96 component
97 .outer
98 .import(component_extern_name(resolve, key, import), ty);
99 }
100 for (key, export) in world.exports.iter() {
102 log::trace!("encoding export {}", resolve.name_world_key(key));
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
117 .outer
118 .export(component_extern_name(resolve, key, export), ty);
119 }
120
121 Ok(component.outer)
122}
123
124fn component_extern_name(
125 resolve: &Resolve,
126 key: &WorldKey,
127 item: &WorldItem,
128) -> wasm_encoder::ComponentExternName<'static> {
129 ComponentExternName {
130 name: resolve.name_world_key(key).into(),
131 implements: resolve.implements_value(key, item).map(|s| s.into()),
132 external_id: resolve.external_id_value(key, item).map(|s| s.into()),
133 version_suffix: None,
134 }
135}
136
137struct Encoder<'a> {
138 component: ComponentBuilder,
139 resolve: &'a Resolve,
140 package: PackageId,
141}
142
143impl Encoder<'_> {
144 fn run(&mut self) -> Result<()> {
145 for (name, &id) in self.resolve.packages[self.package].interfaces.iter() {
147 let component_ty = self.encode_interface(id)?;
148 let ty = self.component.type_component(Some(name), &component_ty);
149 self.component
150 .export(name, ComponentExportKind::Type, ty, None);
151 }
152
153 for (name, &world) in self.resolve.packages[self.package].worlds.iter() {
156 let component_ty = encode_world(self.resolve, world)?;
157
158 let world = &self.resolve.worlds[world];
159 let mut wrapper = ComponentType::new();
160 wrapper.ty().component(&component_ty);
161 let pkg = &self.resolve.packages[world.package.unwrap()];
162 wrapper.export(pkg.name.interface_id(name), ComponentTypeRef::Component(0));
163
164 let ty = self.component.type_component(Some(name), &wrapper);
165 self.component
166 .export(name, ComponentExportKind::Type, ty, None);
167 }
168
169 Ok(())
170 }
171
172 fn encode_interface(&mut self, id: InterfaceId) -> Result<ComponentType> {
173 let mut interfaces = IndexSet::new();
182 self.add_live_interfaces(&mut interfaces, id);
183
184 let mut used_names = IndexSet::new();
188 for id in interfaces.iter() {
189 let iface = &self.resolve.interfaces[*id];
190 if iface.package == Some(self.package) {
191 let first = used_names.insert(iface.name.as_ref().unwrap().clone());
192 assert!(first);
193 }
194 }
195
196 let mut encoder = InterfaceEncoder::new(self.resolve);
197 for interface in interfaces {
198 encoder.interface = Some(interface);
199 let iface = &self.resolve.interfaces[interface];
200 let name = self.resolve.id_of(interface).unwrap();
201 if interface == id {
202 let idx = encoder.encode_instance(interface)?;
203 log::trace!("exporting self as {idx}");
204 encoder.outer.export(name, ComponentTypeRef::Instance(idx));
205 } else {
206 encoder.push_instance();
207 for (_, id) in iface.types.iter() {
208 encoder.encode_valtype(self.resolve, &Type::Id(*id))?;
209 }
210 let instance = encoder.pop_instance();
211 let idx = encoder.outer.type_count();
212 encoder.outer.ty().instance(&instance);
213 encoder.import_map.insert(interface, encoder.instances);
214 encoder.instances += 1;
215 encoder.outer.import(name, ComponentTypeRef::Instance(idx));
216 }
217 }
218
219 encoder.interface = None;
220
221 Ok(encoder.outer)
222 }
223
224 fn add_live_interfaces(&self, interfaces: &mut IndexSet<InterfaceId>, id: InterfaceId) {
227 if interfaces.contains(&id) {
228 return;
229 }
230 for id in self.resolve.interface_direct_deps(id) {
231 self.add_live_interfaces(interfaces, id);
232 }
233 assert!(interfaces.insert(id));
234 }
235}
236
237struct InterfaceEncoder<'a> {
238 resolve: &'a Resolve,
239 outer: ComponentType,
240 ty: Option<InstanceType>,
241 type_encoding_maps: TypeEncodingMaps<'a>,
242 saved_maps: Option<TypeEncodingMaps<'a>>,
243 import_map: HashMap<InterfaceId, u32>,
244 outer_type_map: HashMap<TypeId, u32>,
245 instances: u32,
246 import_types: bool,
247 interface: Option<InterfaceId>,
248}
249
250impl InterfaceEncoder<'_> {
251 fn new(resolve: &Resolve) -> InterfaceEncoder<'_> {
252 InterfaceEncoder {
253 resolve,
254 outer: ComponentType::new(),
255 ty: None,
256 type_encoding_maps: Default::default(),
257 import_map: Default::default(),
258 outer_type_map: Default::default(),
259 instances: 0,
260 saved_maps: None,
261 import_types: false,
262 interface: None,
263 }
264 }
265
266 fn encode_instance(&mut self, interface: InterfaceId) -> Result<u32> {
267 self.push_instance();
268 let iface = &self.resolve.interfaces[interface];
269 let mut type_order = IndexSet::new();
270 for (_, id) in iface.types.iter() {
271 self.encode_valtype(self.resolve, &Type::Id(*id))?;
272 type_order.insert(*id);
273 }
274
275 let mut funcs = iface.functions.iter().collect::<Vec<_>>();
291 funcs.sort_by_key(|(_name, func)| match func.kind.resource() {
292 Some(id) => type_order.get_index_of(&id).unwrap(),
293 None => type_order.len(),
294 });
295
296 for (name, func) in funcs {
297 let ty = self.encode_func_type(self.resolve, func)?;
298 self.ty.as_mut().unwrap().export(
299 extern_name(name, func.external_id.as_deref()),
300 ComponentTypeRef::Func(ty),
301 );
302 }
303 let instance = self.pop_instance();
304 let idx = self.outer.type_count();
305 self.outer.ty().instance(&instance);
306 self.import_map.insert(interface, self.instances);
307 self.instances += 1;
308 Ok(idx)
309 }
310
311 fn push_instance(&mut self) {
312 assert!(self.ty.is_none());
313 assert!(self.saved_maps.is_none());
314 self.saved_maps = Some(mem::take(&mut self.type_encoding_maps));
315 self.ty = Some(InstanceType::default());
316 }
317
318 fn pop_instance(&mut self) -> InstanceType {
319 let maps = self.saved_maps.take().unwrap();
320 self.type_encoding_maps = maps;
321 mem::take(&mut self.ty).unwrap()
322 }
323}
324
325impl<'a> ValtypeEncoder<'a> for InterfaceEncoder<'a> {
326 fn defined_type(&mut self) -> (u32, ComponentDefinedTypeEncoder<'_>) {
327 match &mut self.ty {
328 Some(ty) => (ty.type_count(), ty.ty().defined_type()),
329 None => (self.outer.type_count(), self.outer.ty().defined_type()),
330 }
331 }
332 fn define_function_type(&mut self) -> (u32, ComponentFuncTypeEncoder<'_>) {
333 match &mut self.ty {
334 Some(ty) => (ty.type_count(), ty.ty().function()),
335 None => (self.outer.type_count(), self.outer.ty().function()),
336 }
337 }
338 fn export_type(&mut self, index: u32, name: ComponentExternName<'a>) -> Option<u32> {
339 match &mut self.ty {
340 Some(ty) => {
341 assert!(!self.import_types);
342 let ret = ty.type_count();
343 ty.export(name, ComponentTypeRef::Type(TypeBounds::Eq(index)));
344 Some(ret)
345 }
346 None => {
347 let ret = self.outer.type_count();
348 if self.import_types {
349 self.outer
350 .import(name, ComponentTypeRef::Type(TypeBounds::Eq(index)));
351 } else {
352 self.outer
353 .export(name, ComponentTypeRef::Type(TypeBounds::Eq(index)));
354 }
355 Some(ret)
356 }
357 }
358 }
359 fn export_resource(&mut self, name: ComponentExternName<'a>) -> u32 {
360 let type_ref = ComponentTypeRef::Type(TypeBounds::SubResource);
361 match &mut self.ty {
362 Some(ty) => {
363 assert!(!self.import_types);
364 ty.export(name, type_ref);
365 ty.type_count() - 1
366 }
367 None => {
368 if self.import_types {
369 self.outer.import(name, type_ref);
370 } else {
371 self.outer.export(name, type_ref);
372 }
373 self.outer.type_count() - 1
374 }
375 }
376 }
377 fn type_encoding_maps(&mut self) -> &mut TypeEncodingMaps<'a> {
378 &mut self.type_encoding_maps
379 }
380 fn interface(&self) -> Option<InterfaceId> {
381 self.interface
382 }
383 fn import_type(&mut self, owner: InterfaceId, id: TypeId) -> u32 {
384 let ty = &self.resolve.types[id];
385 let instance = self.import_map[&owner];
386 let outer_idx = *self.outer_type_map.entry(id).or_insert_with(|| {
387 let ret = self.outer.type_count();
388 self.outer.alias(Alias::InstanceExport {
389 instance,
390 name: ty.name.as_ref().unwrap(),
391 kind: ComponentExportKind::Type,
392 });
393 ret
394 });
395 match &mut self.ty {
396 Some(ty) => {
397 let ret = ty.type_count();
398 ty.alias(Alias::Outer {
399 count: 1,
400 index: outer_idx,
401 kind: ComponentOuterAliasKind::Type,
402 });
403 ret
404 }
405 None => outer_idx,
406 }
407 }
408}