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, canonical_names: bool) -> Result<Vec<u8>> {
28 let mut component = encode_component(resolve, package, canonical_names)?;
29 component.raw_custom_section(&crate::base_producers().raw_custom_section());
30 Ok(component.finish())
31}
32
33pub fn encode_component(
52 resolve: &Resolve,
53 package: PackageId,
54 canonical_names: bool,
55) -> Result<ComponentBuilder> {
56 let mut encoder = Encoder {
57 component: ComponentBuilder::default(),
58 resolve,
59 package,
60 canonical_names,
61 };
62 encoder.run()?;
63
64 let package_metadata = PackageMetadata::extract(resolve, package);
65 encoder.component.custom_section(&CustomSection {
66 name: PackageMetadata::SECTION_NAME.into(),
67 data: package_metadata.encode()?.into(),
68 });
69
70 Ok(encoder.component)
71}
72
73pub fn encode_world(
75 resolve: &Resolve,
76 world_id: WorldId,
77 canonical_names: bool,
78) -> Result<ComponentType> {
79 let mut component = InterfaceEncoder::new(resolve);
80 let world = &resolve.worlds[world_id];
81 log::trace!("encoding world {}", world.name);
82
83 for (key, import) in world.imports.iter() {
85 log::trace!("encoding import {}", resolve.name_world_key(key));
86 let ty = match import {
87 WorldItem::Interface { id, .. } => {
88 component.interface = Some(*id);
89 let idx = component.encode_instance(*id)?;
90 ComponentTypeRef::Instance(idx)
91 }
92 WorldItem::Function(f) => {
93 component.interface = None;
94 let idx = component.encode_func_type(resolve, f)?;
95 ComponentTypeRef::Func(idx)
96 }
97 WorldItem::Type { id, .. } => {
98 component.interface = None;
99 component.import_types = true;
100 component.encode_valtype(resolve, &Type::Id(*id))?;
101 component.import_types = false;
102 continue;
103 }
104 };
105 component.outer.import(
106 component_extern_name(resolve, key, import, canonical_names),
107 ty,
108 );
109 }
110 for (key, export) in world.exports.iter() {
112 log::trace!("encoding export {}", resolve.name_world_key(key));
113 let ty = match export {
114 WorldItem::Interface { id, .. } => {
115 component.interface = Some(*id);
116 let idx = component.encode_instance(*id)?;
117 ComponentTypeRef::Instance(idx)
118 }
119 WorldItem::Function(f) => {
120 component.interface = None;
121 let idx = component.encode_func_type(resolve, f)?;
122 ComponentTypeRef::Func(idx)
123 }
124 WorldItem::Type { .. } => unreachable!(),
125 };
126 component.outer.export(
127 component_extern_name(resolve, key, export, canonical_names),
128 ty,
129 );
130 }
131
132 Ok(component.outer)
133}
134
135pub(crate) fn component_extern_name(
136 resolve: &Resolve,
137 key: &WorldKey,
138 item: &WorldItem,
139 canonical_names: bool,
140) -> wasm_encoder::ComponentExternName<'static> {
141 let interface = match key {
142 WorldKey::Interface(id) => Some(*id),
143 WorldKey::Name(_) => None,
144 };
145 interface_extern_name(
146 resolve,
147 &resolve.name_world_key(key),
148 interface,
149 resolve.implements_interface(key, item),
150 resolve.external_id_value(key, item),
151 canonical_names,
152 )
153}
154
155pub(crate) fn interface_extern_name(
163 resolve: &Resolve,
164 name: &str,
165 interface: Option<InterfaceId>,
166 implements: Option<InterfaceId>,
167 external_id: Option<String>,
168 canonical_names: bool,
169) -> ComponentExternName<'static> {
170 let (name, implements, version_suffix) = if canonical_names {
171 let canonical = |id| resolve.canonicalized_id_of(id).unwrap();
172 (
173 interface.map_or_else(|| name.to_string(), canonical),
174 implements.map(canonical),
175 interface
176 .or(implements)
177 .and_then(|id| resolve.version_suffix_of(id)),
178 )
179 } else {
180 let implements = implements.map(|id| resolve.id_of(id).unwrap());
181 (name.to_string(), implements, None)
182 };
183 ComponentExternName {
184 name: name.into(),
185 implements: implements.map(|s| s.into()),
186 external_id: external_id.map(|s| s.into()),
187 version_suffix: version_suffix.map(|s| s.into()),
188 }
189}
190
191struct Encoder<'a> {
192 component: ComponentBuilder,
193 resolve: &'a Resolve,
194 package: PackageId,
195 canonical_names: bool,
196}
197
198impl Encoder<'_> {
199 fn run(&mut self) -> Result<()> {
200 for (name, &id) in self.resolve.packages[self.package].interfaces.iter() {
202 let component_ty = self.encode_interface(id)?;
203 let ty = self.component.type_component(Some(name), &component_ty);
204 self.component
205 .export(name, ComponentExportKind::Type, ty, None);
206 }
207
208 for (name, &world) in self.resolve.packages[self.package].worlds.iter() {
211 let component_ty = encode_world(self.resolve, world, self.canonical_names)?;
212
213 let world = &self.resolve.worlds[world];
214 let mut wrapper = ComponentType::new();
215 wrapper.ty().component(&component_ty);
216 let pkg = &self.resolve.packages[world.package.unwrap()];
217 wrapper.export(pkg.name.interface_id(name), ComponentTypeRef::Component(0));
218
219 let ty = self.component.type_component(Some(name), &wrapper);
220 self.component
221 .export(name, ComponentExportKind::Type, ty, None);
222 }
223
224 Ok(())
225 }
226
227 fn encode_interface(&mut self, id: InterfaceId) -> Result<ComponentType> {
228 let mut interfaces = IndexSet::new();
237 self.add_live_interfaces(&mut interfaces, id);
238
239 let mut used_names = IndexSet::new();
243 for id in interfaces.iter() {
244 let iface = &self.resolve.interfaces[*id];
245 if iface.package == Some(self.package) {
246 let first = used_names.insert(iface.name.as_ref().unwrap().clone());
247 assert!(first);
248 }
249 }
250
251 let mut encoder = InterfaceEncoder::new(self.resolve);
252 for interface in interfaces {
253 encoder.interface = Some(interface);
254 let iface = &self.resolve.interfaces[interface];
255 let extern_name = interface_extern_name(
256 self.resolve,
257 &self.resolve.id_of(interface).unwrap(),
258 Some(interface),
259 None,
260 None,
261 self.canonical_names,
262 );
263 if interface == id {
264 let idx = encoder.encode_instance(interface)?;
265 log::trace!("exporting self as {idx}");
266 encoder
267 .outer
268 .export(extern_name, ComponentTypeRef::Instance(idx));
269 } else {
270 encoder.push_instance();
271 for (_, id) in iface.types.iter() {
272 encoder.encode_valtype(self.resolve, &Type::Id(*id))?;
273 }
274 let instance = encoder.pop_instance();
275 let idx = encoder.outer.type_count();
276 encoder.outer.ty().instance(&instance);
277 encoder.import_map.insert(interface, encoder.instances);
278 encoder.instances += 1;
279 encoder
280 .outer
281 .import(extern_name, ComponentTypeRef::Instance(idx));
282 }
283 }
284
285 encoder.interface = None;
286
287 Ok(encoder.outer)
288 }
289
290 fn add_live_interfaces(&self, interfaces: &mut IndexSet<InterfaceId>, id: InterfaceId) {
293 if interfaces.contains(&id) {
294 return;
295 }
296 for id in self.resolve.interface_direct_deps(id) {
297 self.add_live_interfaces(interfaces, id);
298 }
299 assert!(interfaces.insert(id));
300 }
301}
302
303struct InterfaceEncoder<'a> {
304 resolve: &'a Resolve,
305 outer: ComponentType,
306 ty: Option<InstanceType>,
307 type_encoding_maps: TypeEncodingMaps<'a>,
308 saved_maps: Option<TypeEncodingMaps<'a>>,
309 import_map: HashMap<InterfaceId, u32>,
310 outer_type_map: HashMap<TypeId, u32>,
311 instances: u32,
312 import_types: bool,
313 interface: Option<InterfaceId>,
314}
315
316impl InterfaceEncoder<'_> {
317 fn new(resolve: &Resolve) -> InterfaceEncoder<'_> {
318 InterfaceEncoder {
319 resolve,
320 outer: ComponentType::new(),
321 ty: None,
322 type_encoding_maps: Default::default(),
323 import_map: Default::default(),
324 outer_type_map: Default::default(),
325 instances: 0,
326 saved_maps: None,
327 import_types: false,
328 interface: None,
329 }
330 }
331
332 fn encode_instance(&mut self, interface: InterfaceId) -> Result<u32> {
333 self.push_instance();
334 let iface = &self.resolve.interfaces[interface];
335 let mut type_order = IndexSet::new();
336 for (_, id) in iface.types.iter() {
337 self.encode_valtype(self.resolve, &Type::Id(*id))?;
338 type_order.insert(*id);
339 }
340
341 let mut funcs = iface.functions.iter().collect::<Vec<_>>();
357 funcs.sort_by_key(|(_name, func)| match func.kind.resource() {
358 Some(id) => type_order.get_index_of(&id).unwrap(),
359 None => type_order.len(),
360 });
361
362 for (name, func) in funcs {
363 let ty = self.encode_func_type(self.resolve, func)?;
364 self.ty.as_mut().unwrap().export(
365 extern_name(name, func.external_id.as_deref()),
366 ComponentTypeRef::Func(ty),
367 );
368 }
369 let instance = self.pop_instance();
370 let idx = self.outer.type_count();
371 self.outer.ty().instance(&instance);
372 self.import_map.insert(interface, self.instances);
373 self.instances += 1;
374 Ok(idx)
375 }
376
377 fn push_instance(&mut self) {
378 assert!(self.ty.is_none());
379 assert!(self.saved_maps.is_none());
380 self.saved_maps = Some(mem::take(&mut self.type_encoding_maps));
381 self.ty = Some(InstanceType::default());
382 }
383
384 fn pop_instance(&mut self) -> InstanceType {
385 let maps = self.saved_maps.take().unwrap();
386 self.type_encoding_maps = maps;
387 mem::take(&mut self.ty).unwrap()
388 }
389}
390
391impl<'a> ValtypeEncoder<'a> for InterfaceEncoder<'a> {
392 fn defined_type(&mut self) -> (u32, ComponentDefinedTypeEncoder<'_>) {
393 match &mut self.ty {
394 Some(ty) => (ty.type_count(), ty.ty().defined_type()),
395 None => (self.outer.type_count(), self.outer.ty().defined_type()),
396 }
397 }
398 fn define_function_type(&mut self) -> (u32, ComponentFuncTypeEncoder<'_>) {
399 match &mut self.ty {
400 Some(ty) => (ty.type_count(), ty.ty().function()),
401 None => (self.outer.type_count(), self.outer.ty().function()),
402 }
403 }
404 fn export_type(&mut self, index: u32, name: ComponentExternName<'a>) -> Option<u32> {
405 match &mut self.ty {
406 Some(ty) => {
407 assert!(!self.import_types);
408 let ret = ty.type_count();
409 ty.export(name, ComponentTypeRef::Type(TypeBounds::Eq(index)));
410 Some(ret)
411 }
412 None => {
413 let ret = self.outer.type_count();
414 if self.import_types {
415 self.outer
416 .import(name, ComponentTypeRef::Type(TypeBounds::Eq(index)));
417 } else {
418 self.outer
419 .export(name, ComponentTypeRef::Type(TypeBounds::Eq(index)));
420 }
421 Some(ret)
422 }
423 }
424 }
425 fn export_resource(&mut self, name: ComponentExternName<'a>) -> u32 {
426 let type_ref = ComponentTypeRef::Type(TypeBounds::SubResource);
427 match &mut self.ty {
428 Some(ty) => {
429 assert!(!self.import_types);
430 ty.export(name, type_ref);
431 ty.type_count() - 1
432 }
433 None => {
434 if self.import_types {
435 self.outer.import(name, type_ref);
436 } else {
437 self.outer.export(name, type_ref);
438 }
439 self.outer.type_count() - 1
440 }
441 }
442 }
443 fn type_encoding_maps(&mut self) -> &mut TypeEncodingMaps<'a> {
444 &mut self.type_encoding_maps
445 }
446 fn interface(&self) -> Option<InterfaceId> {
447 self.interface
448 }
449 fn import_type(&mut self, owner: InterfaceId, id: TypeId) -> u32 {
450 let ty = &self.resolve.types[id];
451 let instance = self.import_map[&owner];
452 let outer_idx = *self.outer_type_map.entry(id).or_insert_with(|| {
453 let ret = self.outer.type_count();
454 self.outer.alias(Alias::InstanceExport {
455 instance,
456 name: ty.name.as_ref().unwrap(),
457 kind: ComponentExportKind::Type,
458 });
459 ret
460 });
461 match &mut self.ty {
462 Some(ty) => {
463 let ret = ty.type_count();
464 ty.alias(Alias::Outer {
465 count: 1,
466 index: outer_idx,
467 kind: ComponentOuterAliasKind::Type,
468 });
469 ret
470 }
471 None => outer_idx,
472 }
473 }
474}