1use crate::metadata::{self, Bindgen, ModuleMetadata};
75use crate::validation::{Export, ExportMap, Import, ImportInstance, ImportMap, PayloadInfo};
76use crate::StringEncoding;
77use anyhow::{anyhow, bail, Context, Result};
78use indexmap::{IndexMap, IndexSet};
79use std::borrow::Cow;
80use std::collections::HashMap;
81use std::hash::Hash;
82use std::mem;
83use wasm_encoder::*;
84use wasmparser::Validator;
85use wit_parser::{
86 abi::{AbiVariant, WasmSignature, WasmType},
87 Function, FunctionKind, InterfaceId, LiveTypes, Resolve, Stability, Type, TypeDefKind, TypeId,
88 TypeOwner, WorldItem, WorldKey,
89};
90
91const INDIRECT_TABLE_NAME: &str = "$imports";
92
93mod wit;
94pub use wit::{encode, encode_world};
95
96mod types;
97use types::{InstanceTypeEncoder, RootTypeEncoder, ValtypeEncoder};
98mod world;
99use world::{ComponentWorld, ImportedInterface, Lowering};
100
101fn to_val_type(ty: &WasmType) -> ValType {
102 match ty {
103 WasmType::I32 => ValType::I32,
104 WasmType::I64 => ValType::I64,
105 WasmType::F32 => ValType::F32,
106 WasmType::F64 => ValType::F64,
107 WasmType::Pointer => ValType::I32,
108 WasmType::PointerOrI64 => ValType::I64,
109 WasmType::Length => ValType::I32,
110 }
111}
112
113bitflags::bitflags! {
114 #[derive(Copy, Clone, Debug)]
117 pub struct RequiredOptions: u8 {
118 const MEMORY = 1 << 0;
121 const REALLOC = 1 << 1;
124 const STRING_ENCODING = 1 << 2;
127 const ASYNC = 1 << 3;
128 }
129}
130
131impl RequiredOptions {
132 fn for_import(resolve: &Resolve, func: &Function, abi: AbiVariant) -> RequiredOptions {
133 let sig = resolve.wasm_signature(abi, func);
134 let mut ret = RequiredOptions::empty();
135 ret.add_lift(TypeContents::for_types(
137 resolve,
138 func.params.iter().map(|(_, t)| t),
139 ));
140 ret.add_lower(TypeContents::for_types(resolve, &func.result));
141
142 if sig.retptr || sig.indirect_params {
145 ret |= RequiredOptions::MEMORY;
146 }
147 if abi == AbiVariant::GuestImportAsync {
148 ret |= RequiredOptions::ASYNC;
149 }
150 ret
151 }
152
153 fn for_export(resolve: &Resolve, func: &Function, abi: AbiVariant) -> RequiredOptions {
154 let sig = resolve.wasm_signature(abi, func);
155 let mut ret = RequiredOptions::empty();
156 ret.add_lower(TypeContents::for_types(
158 resolve,
159 func.params.iter().map(|(_, t)| t),
160 ));
161 ret.add_lift(TypeContents::for_types(resolve, &func.result));
162
163 if sig.retptr || sig.indirect_params {
167 ret |= RequiredOptions::MEMORY;
168 if sig.indirect_params {
169 ret |= RequiredOptions::REALLOC;
170 }
171 }
172 if let AbiVariant::GuestExportAsync | AbiVariant::GuestExportAsyncStackful = abi {
173 ret |= RequiredOptions::ASYNC;
174 }
175 ret
176 }
177
178 fn add_lower(&mut self, types: TypeContents) {
179 if types.contains(TypeContents::LIST) {
183 *self |= RequiredOptions::MEMORY | RequiredOptions::REALLOC;
184 }
185 if types.contains(TypeContents::STRING) {
186 *self |= RequiredOptions::MEMORY
187 | RequiredOptions::STRING_ENCODING
188 | RequiredOptions::REALLOC;
189 }
190 }
191
192 fn add_lift(&mut self, types: TypeContents) {
193 if types.contains(TypeContents::LIST) {
197 *self |= RequiredOptions::MEMORY;
198 }
199 if types.contains(TypeContents::STRING) {
200 *self |= RequiredOptions::MEMORY | RequiredOptions::STRING_ENCODING;
201 }
202 }
203
204 fn into_iter(
205 self,
206 encoding: StringEncoding,
207 memory_index: Option<u32>,
208 realloc_index: Option<u32>,
209 ) -> Result<impl ExactSizeIterator<Item = CanonicalOption>> {
210 #[derive(Default)]
211 struct Iter {
212 options: [Option<CanonicalOption>; 5],
213 current: usize,
214 count: usize,
215 }
216
217 impl Iter {
218 fn push(&mut self, option: CanonicalOption) {
219 assert!(self.count < self.options.len());
220 self.options[self.count] = Some(option);
221 self.count += 1;
222 }
223 }
224
225 impl Iterator for Iter {
226 type Item = CanonicalOption;
227
228 fn next(&mut self) -> Option<Self::Item> {
229 if self.current == self.count {
230 return None;
231 }
232 let option = self.options[self.current];
233 self.current += 1;
234 option
235 }
236
237 fn size_hint(&self) -> (usize, Option<usize>) {
238 (self.count - self.current, Some(self.count - self.current))
239 }
240 }
241
242 impl ExactSizeIterator for Iter {}
243
244 let mut iter = Iter::default();
245
246 if self.contains(RequiredOptions::MEMORY) {
247 iter.push(CanonicalOption::Memory(memory_index.ok_or_else(|| {
248 anyhow!("module does not export a memory named `memory`")
249 })?));
250 }
251
252 if self.contains(RequiredOptions::REALLOC) {
253 iter.push(CanonicalOption::Realloc(realloc_index.ok_or_else(
254 || anyhow!("module does not export a function named `cabi_realloc`"),
255 )?));
256 }
257
258 if self.contains(RequiredOptions::STRING_ENCODING) {
259 iter.push(encoding.into());
260 }
261
262 if self.contains(RequiredOptions::ASYNC) {
263 iter.push(CanonicalOption::Async);
264 }
265
266 Ok(iter)
267 }
268}
269
270bitflags::bitflags! {
271 struct TypeContents: u8 {
274 const STRING = 1 << 0;
275 const LIST = 1 << 1;
276 }
277}
278
279impl TypeContents {
280 fn for_types<'a>(resolve: &Resolve, types: impl IntoIterator<Item = &'a Type>) -> Self {
281 let mut cur = TypeContents::empty();
282 for ty in types {
283 cur |= Self::for_type(resolve, ty);
284 }
285 cur
286 }
287
288 fn for_optional_types<'a>(
289 resolve: &Resolve,
290 types: impl Iterator<Item = Option<&'a Type>>,
291 ) -> Self {
292 Self::for_types(resolve, types.flatten())
293 }
294
295 fn for_optional_type(resolve: &Resolve, ty: Option<&Type>) -> Self {
296 match ty {
297 Some(ty) => Self::for_type(resolve, ty),
298 None => Self::empty(),
299 }
300 }
301
302 fn for_type(resolve: &Resolve, ty: &Type) -> Self {
303 match ty {
304 Type::Id(id) => match &resolve.types[*id].kind {
305 TypeDefKind::Handle(h) => match h {
306 wit_parser::Handle::Own(_) => Self::empty(),
307 wit_parser::Handle::Borrow(_) => Self::empty(),
308 },
309 TypeDefKind::Resource => Self::empty(),
310 TypeDefKind::Record(r) => Self::for_types(resolve, r.fields.iter().map(|f| &f.ty)),
311 TypeDefKind::Tuple(t) => Self::for_types(resolve, t.types.iter()),
312 TypeDefKind::Flags(_) => Self::empty(),
313 TypeDefKind::Option(t) => Self::for_type(resolve, t),
314 TypeDefKind::Result(r) => {
315 Self::for_optional_type(resolve, r.ok.as_ref())
316 | Self::for_optional_type(resolve, r.err.as_ref())
317 }
318 TypeDefKind::Variant(v) => {
319 Self::for_optional_types(resolve, v.cases.iter().map(|c| c.ty.as_ref()))
320 }
321 TypeDefKind::Enum(_) => Self::empty(),
322 TypeDefKind::List(t) => Self::for_type(resolve, t) | Self::LIST,
323 TypeDefKind::Type(t) => Self::for_type(resolve, t),
324 TypeDefKind::Future(_) => Self::empty(),
325 TypeDefKind::Stream(_) => Self::empty(),
326 TypeDefKind::ErrorContext => Self::empty(),
327 TypeDefKind::Unknown => unreachable!(),
328 },
329 Type::String => Self::STRING,
330 _ => Self::empty(),
331 }
332 }
333}
334
335pub struct EncodingState<'a> {
337 component: ComponentBuilder,
339 module_index: Option<u32>,
343 instance_index: Option<u32>,
347 memory_index: Option<u32>,
351 shim_instance_index: Option<u32>,
355 fixups_module_index: Option<u32>,
359
360 adapter_modules: IndexMap<&'a str, u32>,
363 adapter_instances: IndexMap<&'a str, u32>,
365
366 imported_instances: IndexMap<InterfaceId, u32>,
368 imported_funcs: IndexMap<String, u32>,
369 exported_instances: IndexMap<InterfaceId, u32>,
370
371 import_type_map: HashMap<TypeId, u32>,
376 import_func_type_map: HashMap<types::FunctionKey<'a>, u32>,
377 export_type_map: HashMap<TypeId, u32>,
378 export_func_type_map: HashMap<types::FunctionKey<'a>, u32>,
379
380 aliased_core_items: HashMap<(u32, String), u32>,
386
387 info: &'a ComponentWorld<'a>,
389}
390
391impl<'a> EncodingState<'a> {
392 fn encode_core_modules(&mut self) {
393 assert!(self.module_index.is_none());
394 let idx = self.component.core_module_raw(&self.info.encoder.module);
395 self.module_index = Some(idx);
396
397 for (name, adapter) in self.info.adapters.iter() {
398 let add_meta = wasm_metadata::AddMetadata {
399 name: Some(if adapter.library_info.is_some() {
400 name.to_string()
401 } else {
402 format!("wit-component:adapter:{name}")
403 }),
404 ..Default::default()
405 };
406 let wasm = add_meta
407 .to_wasm(&adapter.wasm)
408 .expect("core wasm can get name added");
409 let idx = self.component.core_module_raw(&wasm);
410 let prev = self.adapter_modules.insert(name, idx);
411 assert!(prev.is_none());
412 }
413 }
414
415 fn root_import_type_encoder(
416 &mut self,
417 interface: Option<InterfaceId>,
418 ) -> RootTypeEncoder<'_, 'a> {
419 RootTypeEncoder {
420 state: self,
421 interface,
422 import_types: true,
423 }
424 }
425
426 fn root_export_type_encoder(
427 &mut self,
428 interface: Option<InterfaceId>,
429 ) -> RootTypeEncoder<'_, 'a> {
430 RootTypeEncoder {
431 state: self,
432 interface,
433 import_types: false,
434 }
435 }
436
437 fn instance_type_encoder(&mut self, interface: InterfaceId) -> InstanceTypeEncoder<'_, 'a> {
438 InstanceTypeEncoder {
439 state: self,
440 interface,
441 type_map: Default::default(),
442 func_type_map: Default::default(),
443 ty: Default::default(),
444 }
445 }
446
447 fn encode_imports(&mut self, name_map: &HashMap<String, String>) -> Result<()> {
448 let mut has_funcs = false;
449 for (name, info) in self.info.import_map.iter() {
450 match name {
451 Some(name) => {
452 self.encode_interface_import(name_map.get(name).unwrap_or(name), info)?
453 }
454 None => has_funcs = true,
455 }
456 }
457
458 let resolve = &self.info.encoder.metadata.resolve;
459 let world = &resolve.worlds[self.info.encoder.metadata.world];
460 for (_name, item) in world.imports.iter() {
461 if let WorldItem::Type(ty) = item {
462 self.root_import_type_encoder(None)
463 .encode_valtype(resolve, &Type::Id(*ty))?;
464 }
465 }
466
467 if has_funcs {
468 let info = &self.info.import_map[&None];
469 self.encode_root_import_funcs(info)?;
470 }
471 Ok(())
472 }
473
474 fn encode_interface_import(&mut self, name: &str, info: &ImportedInterface) -> Result<()> {
475 let resolve = &self.info.encoder.metadata.resolve;
476 let interface_id = info.interface.as_ref().unwrap();
477 let interface_id = *interface_id;
478 let interface = &resolve.interfaces[interface_id];
479 log::trace!("encoding imports for `{name}` as {:?}", interface_id);
480 let mut encoder = self.instance_type_encoder(interface_id);
481
482 if let Some(live) = encoder.state.info.live_type_imports.get(&interface_id) {
484 for ty in live {
485 log::trace!(
486 "encoding extra type {ty:?} name={:?}",
487 resolve.types[*ty].name
488 );
489 encoder.encode_valtype(resolve, &Type::Id(*ty))?;
490 }
491 }
492
493 for (_, func) in interface.functions.iter() {
496 if !(info
497 .lowerings
498 .contains_key(&(func.name.clone(), AbiVariant::GuestImport))
499 || info
500 .lowerings
501 .contains_key(&(func.name.clone(), AbiVariant::GuestImportAsync)))
502 {
503 continue;
504 }
505 log::trace!("encoding function type for `{}`", func.name);
506 let idx = encoder.encode_func_type(resolve, func)?;
507
508 encoder.ty.export(&func.name, ComponentTypeRef::Func(idx));
509 }
510
511 let ty = encoder.ty;
512 if ty.is_empty() {
515 return Ok(());
516 }
517 let instance_type_idx = self.component.type_instance(&ty);
518 let instance_idx = self
519 .component
520 .import(name, ComponentTypeRef::Instance(instance_type_idx));
521 let prev = self.imported_instances.insert(interface_id, instance_idx);
522 assert!(prev.is_none());
523 Ok(())
524 }
525
526 fn encode_root_import_funcs(&mut self, info: &ImportedInterface) -> Result<()> {
527 let resolve = &self.info.encoder.metadata.resolve;
528 let world = self.info.encoder.metadata.world;
529 for (name, item) in resolve.worlds[world].imports.iter() {
530 let func = match item {
531 WorldItem::Function(f) => f,
532 WorldItem::Interface { .. } | WorldItem::Type(_) => continue,
533 };
534 let name = resolve.name_world_key(name);
535 if !(info
536 .lowerings
537 .contains_key(&(name.clone(), AbiVariant::GuestImport))
538 || info
539 .lowerings
540 .contains_key(&(name.clone(), AbiVariant::GuestImportAsync)))
541 {
542 continue;
543 }
544 log::trace!("encoding function type for `{}`", func.name);
545 let idx = self
546 .root_import_type_encoder(None)
547 .encode_func_type(resolve, func)?;
548 let func_idx = self.component.import(&name, ComponentTypeRef::Func(idx));
549 let prev = self.imported_funcs.insert(name, func_idx);
550 assert!(prev.is_none());
551 }
552 Ok(())
553 }
554
555 fn alias_imported_type(&mut self, interface: InterfaceId, id: TypeId) -> u32 {
556 let ty = &self.info.encoder.metadata.resolve.types[id];
557 let name = ty.name.as_ref().expect("type must have a name");
558 let instance = self.imported_instances[&interface];
559 self.component
560 .alias_export(instance, name, ComponentExportKind::Type)
561 }
562
563 fn alias_exported_type(&mut self, interface: InterfaceId, id: TypeId) -> u32 {
564 let ty = &self.info.encoder.metadata.resolve.types[id];
565 let name = ty.name.as_ref().expect("type must have a name");
566 let instance = self.exported_instances[&interface];
567 self.component
568 .alias_export(instance, name, ComponentExportKind::Type)
569 }
570
571 fn encode_core_instantiation(&mut self) -> Result<()> {
572 let shims = self.encode_shim_instantiation()?;
574
575 self.declare_exported_resources(&shims);
579
580 self.instantiate_main_module(&shims)?;
584
585 let (before, after) = self
588 .info
589 .adapters
590 .iter()
591 .partition::<Vec<_>, _>(|(_, adapter)| {
592 !matches!(
593 adapter.library_info,
594 Some(LibraryInfo {
595 instantiate_after_shims: true,
596 ..
597 })
598 )
599 });
600
601 for (name, _adapter) in before {
602 self.instantiate_adapter_module(&shims, name)?;
603 }
604
605 self.encode_indirect_lowerings(&shims)?;
608
609 for (name, _adapter) in after {
610 self.instantiate_adapter_module(&shims, name)?;
611 }
612
613 self.encode_initialize_with_start()?;
614
615 Ok(())
616 }
617
618 fn lookup_resource_index(&mut self, id: TypeId) -> u32 {
619 let resolve = &self.info.encoder.metadata.resolve;
620 let ty = &resolve.types[id];
621 match ty.owner {
622 TypeOwner::World(_) => self.import_type_map[&id],
626 TypeOwner::Interface(i) => {
627 let instance = self.imported_instances[&i];
628 let name = ty.name.as_ref().expect("resources must be named");
629 self.component
630 .alias_export(instance, name, ComponentExportKind::Type)
631 }
632 TypeOwner::None => panic!("resources must have an owner"),
633 }
634 }
635
636 fn encode_exports(&mut self, module: CustomModule) -> Result<()> {
637 let resolve = &self.info.encoder.metadata.resolve;
638 let exports = match module {
639 CustomModule::Main => &self.info.encoder.main_module_exports,
640 CustomModule::Adapter(name) => &self.info.encoder.adapters[name].required_exports,
641 };
642
643 if exports.is_empty() {
644 return Ok(());
645 }
646
647 let mut interface_func_core_names = IndexMap::new();
648 let mut world_func_core_names = IndexMap::new();
649 for (core_name, export) in self.info.exports_for(module).iter() {
650 match export {
651 Export::WorldFunc(_, name, _) => {
652 let prev = world_func_core_names.insert(name, core_name);
653 assert!(prev.is_none());
654 }
655 Export::InterfaceFunc(_, id, name, _) => {
656 let prev = interface_func_core_names
657 .entry(id)
658 .or_insert(IndexMap::new())
659 .insert(name.as_str(), core_name);
660 assert!(prev.is_none());
661 }
662 Export::WorldFuncCallback(..)
663 | Export::InterfaceFuncCallback(..)
664 | Export::WorldFuncPostReturn(..)
665 | Export::InterfaceFuncPostReturn(..)
666 | Export::ResourceDtor(..)
667 | Export::Memory
668 | Export::GeneralPurposeRealloc
669 | Export::GeneralPurposeExportRealloc
670 | Export::GeneralPurposeImportRealloc
671 | Export::Initialize
672 | Export::ReallocForAdapter => continue,
673 }
674 }
675
676 let world = &resolve.worlds[self.info.encoder.metadata.world];
677
678 for export_name in exports {
679 let export_string = resolve.name_world_key(export_name);
680 match &world.exports[export_name] {
681 WorldItem::Function(func) => {
682 let ty = self
683 .root_import_type_encoder(None)
684 .encode_func_type(resolve, func)?;
685 let core_name = world_func_core_names[&func.name];
686 let idx = self.encode_lift(module, &core_name, export_name, func, ty)?;
687 self.component
688 .export(&export_string, ComponentExportKind::Func, idx, None);
689 }
690 WorldItem::Interface { id, .. } => {
691 let core_names = interface_func_core_names.get(id);
692 self.encode_interface_export(
693 &export_string,
694 module,
695 export_name,
696 *id,
697 core_names,
698 )?;
699 }
700 WorldItem::Type(_) => unreachable!(),
701 }
702 }
703
704 Ok(())
705 }
706
707 fn encode_interface_export(
708 &mut self,
709 export_name: &str,
710 module: CustomModule<'_>,
711 key: &WorldKey,
712 export: InterfaceId,
713 interface_func_core_names: Option<&IndexMap<&str, &str>>,
714 ) -> Result<()> {
715 log::trace!("encode interface export `{export_name}`");
716 let resolve = &self.info.encoder.metadata.resolve;
717
718 let mut imports = Vec::new();
725 let mut root = self.root_export_type_encoder(Some(export));
726 for (_, func) in &resolve.interfaces[export].functions {
727 let core_name = interface_func_core_names.unwrap()[func.name.as_str()];
728 let ty = root.encode_func_type(resolve, func)?;
729 let func_index = root.state.encode_lift(module, &core_name, key, func, ty)?;
730 imports.push((
731 import_func_name(func),
732 ComponentExportKind::Func,
733 func_index,
734 ));
735 }
736
737 let mut nested = NestedComponentTypeEncoder {
741 component: ComponentBuilder::default(),
742 type_map: Default::default(),
743 func_type_map: Default::default(),
744 export_types: false,
745 interface: export,
746 state: self,
747 imports: IndexMap::new(),
748 };
749
750 let mut types_to_import = LiveTypes::default();
760 types_to_import.add_interface(resolve, export);
761 let exports_used = &nested.state.info.exports_used[&export];
762 for ty in types_to_import.iter() {
763 if let TypeOwner::Interface(owner) = resolve.types[ty].owner {
764 if owner == export {
765 continue;
768 }
769
770 let mut encoder = if exports_used.contains(&owner) {
773 nested.state.root_export_type_encoder(Some(export))
774 } else {
775 nested.state.root_import_type_encoder(Some(export))
776 };
777 encoder.encode_valtype(resolve, &Type::Id(ty))?;
778
779 nested.interface = owner;
783 nested.encode_valtype(resolve, &Type::Id(ty))?;
784 }
785 }
786 nested.interface = export;
787
788 let imported_types = nested.type_map.clone();
792
793 let mut resources = HashMap::new();
799 for (_name, ty) in resolve.interfaces[export].types.iter() {
800 if !matches!(resolve.types[*ty].kind, TypeDefKind::Resource) {
801 continue;
802 }
803 let idx = match nested.encode_valtype(resolve, &Type::Id(*ty))? {
804 ComponentValType::Type(idx) => idx,
805 _ => unreachable!(),
806 };
807 resources.insert(*ty, idx);
808 }
809
810 for (_, func) in resolve.interfaces[export].functions.iter() {
814 let ty = nested.encode_func_type(resolve, func)?;
815 nested
816 .component
817 .import(&import_func_name(func), ComponentTypeRef::Func(ty));
818 }
819
820 let reverse_map = nested
827 .type_map
828 .drain()
829 .map(|p| (p.1, p.0))
830 .collect::<HashMap<_, _>>();
831 for (name, idx) in nested.imports.drain(..) {
832 let id = reverse_map[&idx];
833 let owner = match resolve.types[id].owner {
834 TypeOwner::Interface(id) => id,
835 _ => unreachable!(),
836 };
837 let idx = if owner == export || exports_used.contains(&owner) {
838 log::trace!("consulting exports for {id:?}");
839 nested.state.export_type_map[&id]
840 } else {
841 log::trace!("consulting imports for {id:?}");
842 nested.state.import_type_map[&id]
843 };
844 imports.push((name, ComponentExportKind::Type, idx))
845 }
846
847 nested.type_map = imported_types;
852
853 nested.export_types = true;
860 nested.func_type_map.clear();
861
862 for (_, id) in resolve.interfaces[export].types.iter() {
868 let ty = &resolve.types[*id];
869 match ty.kind {
870 TypeDefKind::Resource => {
871 let idx = nested.component.export(
872 ty.name.as_ref().expect("resources must be named"),
873 ComponentExportKind::Type,
874 resources[id],
875 None,
876 );
877 nested.type_map.insert(*id, idx);
878 }
879 _ => {
880 nested.encode_valtype(resolve, &Type::Id(*id))?;
881 }
882 }
883 }
884
885 for (i, (_, func)) in resolve.interfaces[export].functions.iter().enumerate() {
886 let ty = nested.encode_func_type(resolve, func)?;
887 nested.component.export(
888 &func.name,
889 ComponentExportKind::Func,
890 i as u32,
891 Some(ComponentTypeRef::Func(ty)),
892 );
893 }
894
895 let component = nested.component;
899 let component_index = self.component.component(component);
900 let instance_index = self.component.instantiate(component_index, imports);
901 let idx = self.component.export(
902 export_name,
903 ComponentExportKind::Instance,
904 instance_index,
905 None,
906 );
907 let prev = self.exported_instances.insert(export, idx);
908 assert!(prev.is_none());
909
910 for (_name, id) in resolve.interfaces[export].types.iter() {
918 self.export_type_map.remove(id);
919 }
920
921 return Ok(());
922
923 struct NestedComponentTypeEncoder<'state, 'a> {
924 component: ComponentBuilder,
925 type_map: HashMap<TypeId, u32>,
926 func_type_map: HashMap<types::FunctionKey<'a>, u32>,
927 export_types: bool,
928 interface: InterfaceId,
929 state: &'state mut EncodingState<'a>,
930 imports: IndexMap<String, u32>,
931 }
932
933 impl<'a> ValtypeEncoder<'a> for NestedComponentTypeEncoder<'_, 'a> {
934 fn defined_type(&mut self) -> (u32, ComponentDefinedTypeEncoder<'_>) {
935 self.component.type_defined()
936 }
937 fn define_function_type(&mut self) -> (u32, ComponentFuncTypeEncoder<'_>) {
938 self.component.type_function()
939 }
940 fn export_type(&mut self, idx: u32, name: &'a str) -> Option<u32> {
941 if self.export_types {
942 Some(
943 self.component
944 .export(name, ComponentExportKind::Type, idx, None),
945 )
946 } else {
947 let name = self.unique_import_name(name);
948 let ret = self
949 .component
950 .import(&name, ComponentTypeRef::Type(TypeBounds::Eq(idx)));
951 self.imports.insert(name, ret);
952 Some(ret)
953 }
954 }
955 fn export_resource(&mut self, name: &'a str) -> u32 {
956 if self.export_types {
957 panic!("resources should already be exported")
958 } else {
959 let name = self.unique_import_name(name);
960 let ret = self
961 .component
962 .import(&name, ComponentTypeRef::Type(TypeBounds::SubResource));
963 self.imports.insert(name, ret);
964 ret
965 }
966 }
967 fn import_type(&mut self, _: InterfaceId, _id: TypeId) -> u32 {
968 unreachable!()
969 }
970 fn type_map(&mut self) -> &mut HashMap<TypeId, u32> {
971 &mut self.type_map
972 }
973 fn func_type_map(&mut self) -> &mut HashMap<types::FunctionKey<'a>, u32> {
974 &mut self.func_type_map
975 }
976 fn interface(&self) -> Option<InterfaceId> {
977 Some(self.interface)
978 }
979 }
980
981 impl NestedComponentTypeEncoder<'_, '_> {
982 fn unique_import_name(&mut self, name: &str) -> String {
983 let mut name = format!("import-type-{name}");
984 let mut n = 0;
985 while self.imports.contains_key(&name) {
986 name = format!("{name}{n}");
987 n += 1;
988 }
989 name
990 }
991 }
992
993 fn import_func_name(f: &Function) -> String {
994 match f.kind {
995 FunctionKind::Freestanding => {
996 format!("import-func-{}", f.name)
997 }
998
999 FunctionKind::Method(_)
1007 | FunctionKind::Static(_)
1008 | FunctionKind::Constructor(_) => {
1009 format!(
1010 "import-{}",
1011 f.name.replace('[', "").replace([']', '.'], "-")
1012 )
1013 }
1014 }
1015 }
1016 }
1017
1018 fn encode_lift(
1019 &mut self,
1020 module: CustomModule<'_>,
1021 core_name: &str,
1022 key: &WorldKey,
1023 func: &Function,
1024 ty: u32,
1025 ) -> Result<u32> {
1026 let resolve = &self.info.encoder.metadata.resolve;
1027 let metadata = self.info.module_metadata_for(module);
1028 let instance_index = self.instance_for(module);
1029 let core_func_index = self.core_alias_export(instance_index, core_name, ExportKind::Func);
1030 let exports = self.info.exports_for(module);
1031
1032 let options = RequiredOptions::for_export(
1033 resolve,
1034 func,
1035 exports
1036 .abi(key, func)
1037 .ok_or_else(|| anyhow!("no ABI found for {}", func.name))?,
1038 );
1039
1040 let encoding = metadata
1041 .export_encodings
1042 .get(resolve, key, &func.name)
1043 .unwrap();
1044 let exports = self.info.exports_for(module);
1045 let realloc_index = exports
1046 .export_realloc_for(key, func)
1047 .map(|name| self.core_alias_export(instance_index, name, ExportKind::Func));
1048 let mut options = options
1049 .into_iter(encoding, self.memory_index, realloc_index)?
1050 .collect::<Vec<_>>();
1051
1052 if let Some(post_return) = exports.post_return(key, func) {
1053 let post_return = self.core_alias_export(instance_index, post_return, ExportKind::Func);
1054 options.push(CanonicalOption::PostReturn(post_return));
1055 }
1056 if let Some(callback) = exports.callback(key, func) {
1057 let callback = self.core_alias_export(instance_index, callback, ExportKind::Func);
1058 options.push(CanonicalOption::Callback(callback));
1059 }
1060 let func_index = self.component.lift_func(core_func_index, ty, options);
1061 Ok(func_index)
1062 }
1063
1064 fn encode_shim_instantiation(&mut self) -> Result<Shims<'a>> {
1065 let mut ret = Shims::default();
1066
1067 ret.append_indirect(self.info, CustomModule::Main)
1068 .context("failed to register indirect shims for main module")?;
1069
1070 for (adapter_name, _adapter) in self.info.adapters.iter() {
1074 ret.append_indirect(self.info, CustomModule::Adapter(adapter_name))
1075 .with_context(|| {
1076 format!("failed to register indirect shims for adapter {adapter_name}")
1077 })?;
1078 }
1079
1080 if ret.shims.is_empty() {
1081 return Ok(ret);
1082 }
1083
1084 assert!(self.shim_instance_index.is_none());
1085 assert!(self.fixups_module_index.is_none());
1086
1087 let mut types = TypeSection::new();
1096 let mut tables = TableSection::new();
1097 let mut functions = FunctionSection::new();
1098 let mut exports = ExportSection::new();
1099 let mut code = CodeSection::new();
1100 let mut sigs = IndexMap::new();
1101 let mut imports_section = ImportSection::new();
1102 let mut elements = ElementSection::new();
1103 let mut func_indexes = Vec::new();
1104 let mut func_names = NameMap::new();
1105
1106 for (i, shim) in ret.shims.values().enumerate() {
1107 let i = i as u32;
1108 let type_index = *sigs.entry(&shim.sig).or_insert_with(|| {
1109 let index = types.len();
1110 types.ty().function(
1111 shim.sig.params.iter().map(to_val_type),
1112 shim.sig.results.iter().map(to_val_type),
1113 );
1114 index
1115 });
1116
1117 functions.function(type_index);
1118 Self::encode_shim_function(type_index, i, &mut code, shim.sig.params.len() as u32);
1119 exports.export(&shim.name, ExportKind::Func, i);
1120
1121 imports_section.import("", &shim.name, EntityType::Function(type_index));
1122 func_indexes.push(i);
1123 func_names.append(i, &shim.debug_name);
1124 }
1125 let mut names = NameSection::new();
1126 names.module("wit-component:shim");
1127 names.functions(&func_names);
1128
1129 let table_type = TableType {
1130 element_type: RefType::FUNCREF,
1131 minimum: ret.shims.len() as u64,
1132 maximum: Some(ret.shims.len() as u64),
1133 table64: false,
1134 shared: false,
1135 };
1136
1137 tables.table(table_type);
1138
1139 exports.export(INDIRECT_TABLE_NAME, ExportKind::Table, 0);
1140 imports_section.import("", INDIRECT_TABLE_NAME, table_type);
1141
1142 elements.active(
1143 None,
1144 &ConstExpr::i32_const(0),
1145 Elements::Functions(func_indexes.into()),
1146 );
1147
1148 let mut shim = Module::new();
1149 shim.section(&types);
1150 shim.section(&functions);
1151 shim.section(&tables);
1152 shim.section(&exports);
1153 shim.section(&code);
1154 shim.section(&RawCustomSection(
1155 &crate::base_producers().raw_custom_section(),
1156 ));
1157 shim.section(&names);
1158
1159 let mut fixups = Module::default();
1160 fixups.section(&types);
1161 fixups.section(&imports_section);
1162 fixups.section(&elements);
1163 fixups.section(&RawCustomSection(
1164 &crate::base_producers().raw_custom_section(),
1165 ));
1166
1167 let mut names = NameSection::new();
1168 names.module("wit-component:fixups");
1169 fixups.section(&names);
1170
1171 let shim_module_index = self.component.core_module(&shim);
1172 self.fixups_module_index = Some(self.component.core_module(&fixups));
1173 self.shim_instance_index = Some(self.component.core_instantiate(shim_module_index, []));
1174
1175 return Ok(ret);
1176 }
1177
1178 fn encode_shim_function(
1179 type_index: u32,
1180 func_index: u32,
1181 code: &mut CodeSection,
1182 param_count: u32,
1183 ) {
1184 let mut func = wasm_encoder::Function::new(std::iter::empty());
1185 for i in 0..param_count {
1186 func.instructions().local_get(i);
1187 }
1188 func.instructions().i32_const(func_index as i32);
1189 func.instructions().call_indirect(0, type_index);
1190 func.instructions().end();
1191 code.function(&func);
1192 }
1193
1194 fn encode_indirect_lowerings(&mut self, shims: &Shims<'_>) -> Result<()> {
1195 if shims.shims.is_empty() {
1196 return Ok(());
1197 }
1198
1199 let shim_instance_index = self
1200 .shim_instance_index
1201 .expect("must have an instantiated shim");
1202
1203 let table_index =
1204 self.core_alias_export(shim_instance_index, INDIRECT_TABLE_NAME, ExportKind::Table);
1205
1206 let resolve = &self.info.encoder.metadata.resolve;
1207
1208 let mut exports = Vec::new();
1209 exports.push((INDIRECT_TABLE_NAME, ExportKind::Table, table_index));
1210
1211 for shim in shims.shims.values() {
1212 let core_func_index = match &shim.kind {
1213 ShimKind::IndirectLowering {
1220 interface,
1221 index,
1222 realloc,
1223 encoding,
1224 } => {
1225 let interface = &self.info.import_map[interface];
1226 let ((name, _), _) = interface.lowerings.get_index(*index).unwrap();
1227 let func_index = match &interface.interface {
1228 Some(interface_id) => {
1229 let instance_index = self.imported_instances[interface_id];
1230 self.component.alias_export(
1231 instance_index,
1232 name,
1233 ComponentExportKind::Func,
1234 )
1235 }
1236 None => self.imported_funcs[name],
1237 };
1238
1239 let realloc = self
1240 .info
1241 .exports_for(*realloc)
1242 .import_realloc_for(interface.interface, name)
1243 .map(|name| {
1244 let instance = self.instance_for(*realloc);
1245 self.core_alias_export(instance, name, ExportKind::Func)
1246 });
1247
1248 self.component.lower_func(
1249 func_index,
1250 shim.options
1251 .into_iter(*encoding, self.memory_index, realloc)?,
1252 )
1253 }
1254
1255 ShimKind::Adapter { adapter, func } => {
1260 self.core_alias_export(self.adapter_instances[adapter], func, ExportKind::Func)
1261 }
1262
1263 ShimKind::ResourceDtor { module, export } => {
1268 self.core_alias_export(self.instance_for(*module), export, ExportKind::Func)
1269 }
1270
1271 ShimKind::PayloadFunc {
1272 for_module,
1273 async_,
1274 info,
1275 kind,
1276 } => {
1277 let metadata = self.info.module_metadata_for(*for_module);
1278 let exports = self.info.exports_for(*for_module);
1279 let instance_index = self.instance_for(*for_module);
1280 let (encoding, realloc) = if info.imported {
1281 (
1282 metadata
1283 .import_encodings
1284 .get(resolve, &info.key, &info.function.name),
1285 exports.import_realloc_for(info.interface, &info.function.name),
1286 )
1287 } else {
1288 (
1289 metadata
1290 .export_encodings
1291 .get(resolve, &info.key, &info.function.name),
1292 exports.export_realloc_for(&info.key, &info.function),
1293 )
1294 };
1295 let encoding = encoding.unwrap_or(StringEncoding::UTF8);
1296 let realloc_index = realloc
1297 .map(|name| self.core_alias_export(instance_index, name, ExportKind::Func));
1298 let options = |me: &mut Self, params: Vec<Type>, results: Vec<Type>| {
1299 Ok::<_, anyhow::Error>(
1300 (RequiredOptions::for_import(
1301 resolve,
1302 &Function {
1303 name: String::new(),
1304 kind: FunctionKind::Freestanding,
1305 params: params
1306 .into_iter()
1307 .enumerate()
1308 .map(|(i, v)| (format!("a{i}"), v))
1309 .collect(),
1310 result: match &results[..] {
1311 [] => None,
1312 [ty] => Some(*ty),
1313 _ => unreachable!(),
1314 },
1315 docs: Default::default(),
1316 stability: Stability::Unknown,
1317 },
1318 if *async_ {
1319 AbiVariant::GuestImportAsync
1320 } else {
1321 AbiVariant::GuestImport
1322 },
1323 ) | RequiredOptions::MEMORY)
1324 .into_iter(encoding, me.memory_index, realloc_index)?
1325 .collect::<Vec<_>>(),
1326 )
1327 };
1328 let type_index = self.payload_type_index(info.ty, info.imported)?;
1329
1330 match kind {
1331 PayloadFuncKind::FutureWrite => {
1332 let TypeDefKind::Future(payload_type) = &resolve.types[info.ty].kind
1333 else {
1334 unreachable!()
1335 };
1336 let options = options(
1337 self,
1338 if let Some(payload_type) = payload_type {
1339 vec![*payload_type]
1340 } else {
1341 vec![]
1342 },
1343 vec![],
1344 )?;
1345 self.component.future_write(type_index, options)
1346 }
1347 PayloadFuncKind::FutureRead => {
1348 let TypeDefKind::Future(payload_type) = &resolve.types[info.ty].kind
1349 else {
1350 unreachable!()
1351 };
1352 let options = options(
1353 self,
1354 vec![],
1355 if let Some(payload_type) = payload_type {
1356 vec![*payload_type]
1357 } else {
1358 vec![]
1359 },
1360 )?;
1361 self.component.future_read(type_index, options)
1362 }
1363 PayloadFuncKind::StreamWrite => {
1364 let TypeDefKind::Stream(payload_type) = &resolve.types[info.ty].kind
1365 else {
1366 unreachable!()
1367 };
1368 let options = options(
1369 self,
1370 if let Some(payload_type) = payload_type {
1371 vec![*payload_type]
1372 } else {
1373 vec![]
1374 },
1375 vec![],
1376 )?;
1377 self.component.stream_write(type_index, options)
1378 }
1379 PayloadFuncKind::StreamRead => {
1380 let TypeDefKind::Stream(payload_type) = &resolve.types[info.ty].kind
1381 else {
1382 unreachable!()
1383 };
1384 let options = options(
1385 self,
1386 vec![],
1387 if let Some(payload_type) = payload_type {
1388 vec![*payload_type]
1389 } else {
1390 vec![]
1391 },
1392 )?;
1393 self.component.stream_read(type_index, options)
1394 }
1395 }
1396 }
1397
1398 ShimKind::TaskWait { async_ } => self
1399 .component
1400 .task_wait(*async_, self.memory_index.unwrap()),
1401 ShimKind::TaskPoll { async_ } => self
1402 .component
1403 .task_poll(*async_, self.memory_index.unwrap()),
1404 ShimKind::ErrorContextNew { encoding }
1405 | ShimKind::ErrorContextDebugMessage { encoding, .. } => match &shim.kind {
1406 ShimKind::ErrorContextNew { .. } => self.component.error_context_new(
1407 (RequiredOptions::MEMORY | RequiredOptions::STRING_ENCODING)
1408 .into_iter(*encoding, self.memory_index, None)?
1409 .collect::<Vec<_>>(),
1410 ),
1411 ShimKind::ErrorContextDebugMessage {
1412 for_module,
1413 realloc,
1414 ..
1415 } => {
1416 let instance_index = self.instance_for(*for_module);
1417 let realloc_index =
1418 Some(self.core_alias_export(instance_index, realloc, ExportKind::Func));
1419
1420 self.component.error_context_debug_message(
1421 (RequiredOptions::MEMORY
1422 | RequiredOptions::STRING_ENCODING
1423 | RequiredOptions::REALLOC)
1424 .into_iter(*encoding, self.memory_index, realloc_index)?
1425 .collect::<Vec<_>>(),
1426 )
1427 }
1428 _ => unreachable!(),
1429 },
1430 };
1431
1432 exports.push((shim.name.as_str(), ExportKind::Func, core_func_index));
1433 }
1434
1435 let instance_index = self.component.core_instantiate_exports(exports);
1436 self.component.core_instantiate(
1437 self.fixups_module_index.expect("must have fixup module"),
1438 [("", ModuleArg::Instance(instance_index))],
1439 );
1440 Ok(())
1441 }
1442
1443 fn payload_type_index(&mut self, ty: TypeId, imported: bool) -> Result<u32> {
1451 fn owner(resolve: &Resolve, ty: TypeId) -> Option<InterfaceId> {
1457 let def = &resolve.types[ty];
1458 match &def.kind {
1459 TypeDefKind::Future(Some(Type::Id(ty)))
1460 | TypeDefKind::Stream(Some(Type::Id(ty))) => owner(resolve, *ty),
1461 _ => match &def.owner {
1462 TypeOwner::World(_) | TypeOwner::None => None,
1463 TypeOwner::Interface(id) => Some(*id),
1464 },
1465 }
1466 }
1467
1468 let resolve = &self.info.encoder.metadata.resolve;
1469 let ComponentValType::Type(type_index) = if imported {
1470 self.root_import_type_encoder(None)
1471 } else {
1472 let owner = owner(resolve, ty);
1473 self.root_export_type_encoder(owner)
1474 }
1475 .encode_valtype(resolve, &Type::Id(ty))?
1476 else {
1477 unreachable!()
1478 };
1479 Ok(type_index)
1480 }
1481
1482 fn declare_exported_resources(&mut self, shims: &Shims<'_>) {
1489 let resolve = &self.info.encoder.metadata.resolve;
1490 let world = &resolve.worlds[self.info.encoder.metadata.world];
1491
1492 let main_module_keys = self.info.encoder.main_module_exports.iter();
1496 let main_module_keys = main_module_keys.map(|key| (CustomModule::Main, key));
1497 let adapter_keys = self.info.encoder.adapters.iter().flat_map(|(name, info)| {
1498 info.required_exports
1499 .iter()
1500 .map(move |key| (CustomModule::Adapter(name), key))
1501 });
1502 for (for_module, key) in main_module_keys.chain(adapter_keys) {
1503 let id = match &world.exports[key] {
1504 WorldItem::Interface { id, .. } => *id,
1505 WorldItem::Type { .. } => unreachable!(),
1506 WorldItem::Function(_) => continue,
1507 };
1508
1509 for ty in resolve.interfaces[id].types.values() {
1510 match resolve.types[*ty].kind {
1511 TypeDefKind::Resource => {}
1512 _ => continue,
1513 }
1514
1515 let exports = self.info.exports_for(for_module);
1518 let dtor = exports.resource_dtor(*ty).map(|name| {
1519 let name = &shims.shims[&ShimKind::ResourceDtor {
1520 module: for_module,
1521 export: name,
1522 }]
1523 .name;
1524 let shim = self.shim_instance_index.unwrap();
1525 self.core_alias_export(shim, name, ExportKind::Func)
1526 });
1527
1528 let resource_idx = self.component.type_resource(ValType::I32, dtor);
1532 let prev = self.export_type_map.insert(*ty, resource_idx);
1533 assert!(prev.is_none());
1534 }
1535 }
1536 }
1537
1538 fn instantiate_main_module(&mut self, shims: &Shims<'_>) -> Result<()> {
1541 assert!(self.instance_index.is_none());
1542
1543 let instance_index = self.instantiate_core_module(shims, CustomModule::Main)?;
1544
1545 if let Some(memory) = self.info.info.exports.memory() {
1546 self.memory_index =
1547 Some(self.core_alias_export(instance_index, memory, ExportKind::Memory));
1548 }
1549
1550 self.instance_index = Some(instance_index);
1551 Ok(())
1552 }
1553
1554 fn instantiate_adapter_module(&mut self, shims: &Shims<'_>, name: &'a str) -> Result<()> {
1557 let instance = self.instantiate_core_module(shims, CustomModule::Adapter(name))?;
1558 self.adapter_instances.insert(name, instance);
1559 Ok(())
1560 }
1561
1562 fn instantiate_core_module(
1569 &mut self,
1570 shims: &Shims,
1571 for_module: CustomModule<'_>,
1572 ) -> Result<u32> {
1573 let module = self.module_for(for_module);
1574
1575 let mut args = Vec::new();
1576 for (core_wasm_name, instance) in self.info.imports_for(for_module).modules() {
1577 match instance {
1578 ImportInstance::Names(names) => {
1584 let mut exports = Vec::new();
1585 for (name, import) in names {
1586 let (kind, index) = self
1587 .materialize_import(&shims, for_module, core_wasm_name, name, import)
1588 .with_context(|| {
1589 format!("failed to satisfy import `{core_wasm_name}::{name}`")
1590 })?;
1591 exports.push((name.as_str(), kind, index));
1592 }
1593 let index = self.component.core_instantiate_exports(exports);
1594 args.push((core_wasm_name.as_str(), ModuleArg::Instance(index)));
1595 }
1596
1597 ImportInstance::Whole(which) => {
1600 let instance = self.instance_for(which.to_custom_module());
1601 args.push((core_wasm_name.as_str(), ModuleArg::Instance(instance)));
1602 }
1603 }
1604 }
1605
1606 Ok(self.component.core_instantiate(module, args))
1608 }
1609
1610 fn materialize_import(
1617 &mut self,
1618 shims: &Shims<'_>,
1619 for_module: CustomModule<'_>,
1620 module: &str,
1621 field: &str,
1622 import: &'a Import,
1623 ) -> Result<(ExportKind, u32)> {
1624 log::trace!("attempting to materialize import of `{module}::{field}` for {for_module:?}");
1625 let resolve = &self.info.encoder.metadata.resolve;
1626 let payload_indirect = |me: &mut Self, async_, info, kind| {
1627 me.component.core_alias_export(
1628 me.shim_instance_index.expect("shim should be instantiated"),
1629 &shims.shims[&ShimKind::PayloadFunc {
1630 for_module,
1631 async_,
1632 info,
1633 kind,
1634 }]
1635 .name,
1636 ExportKind::Func,
1637 )
1638 };
1639 let name_tmp;
1640 let (key, name, interface_key, abi) = match import {
1641 Import::AdapterExport(_) => {
1644 assert!(self.info.encoder.adapters.contains_key(module));
1645 let shim_instance = self
1646 .shim_instance_index
1647 .expect("shim should be instantiated");
1648 let index = self.core_alias_export(
1649 shim_instance,
1650 &shims.shims[&ShimKind::Adapter {
1651 adapter: module,
1652 func: field,
1653 }]
1654 .name,
1655 ExportKind::Func,
1656 );
1657 return Ok((ExportKind::Func, index));
1658 }
1659
1660 Import::MainModuleMemory => {
1663 let index = self
1664 .memory_index
1665 .ok_or_else(|| anyhow!("main module cannot import memory"))?;
1666 return Ok((ExportKind::Memory, index));
1667 }
1668
1669 Import::MainModuleExport { name, kind } => {
1671 let instance = self.instance_index.unwrap();
1672 let index = self.core_alias_export(instance, name, *kind);
1673 return Ok((*kind, index));
1674 }
1675
1676 Import::Item(item) => {
1680 let instance = self.instance_for(item.which.to_custom_module());
1681 let index = self.core_alias_export(instance, &item.name, item.kind);
1682 return Ok((item.kind, index));
1683 }
1684
1685 Import::ExportedResourceDrop(_key, id) => {
1691 let index = self.component.resource_drop(self.export_type_map[id]);
1692 return Ok((ExportKind::Func, index));
1693 }
1694 Import::ExportedResourceRep(_key, id) => {
1695 let index = self.component.resource_rep(self.export_type_map[id]);
1696 return Ok((ExportKind::Func, index));
1697 }
1698 Import::ExportedResourceNew(_key, id) => {
1699 let index = self.component.resource_new(self.export_type_map[id]);
1700 return Ok((ExportKind::Func, index));
1701 }
1702
1703 Import::ImportedResourceDrop(key, iface, id) => {
1708 let ty = &resolve.types[*id];
1709 let name = ty.name.as_ref().unwrap();
1710 name_tmp = format!("{name}_drop");
1711 (
1712 key,
1713 &name_tmp,
1714 iface.map(|_| resolve.name_world_key(key)),
1715 AbiVariant::GuestImport,
1716 )
1717 }
1718 Import::ExportedTaskReturn(interface, function) => {
1719 let mut encoder = self.root_export_type_encoder(*interface);
1720
1721 let result = match &function.result {
1722 Some(ty) => Some(encoder.encode_valtype(resolve, ty)?),
1723 None => None,
1724 };
1725
1726 let index = self.component.task_return(result);
1727 return Ok((ExportKind::Func, index));
1728 }
1729 Import::TaskBackpressure => {
1730 let index = self.component.task_backpressure();
1731 return Ok((ExportKind::Func, index));
1732 }
1733 Import::TaskWait { async_ } => {
1734 let index = self.component.core_alias_export(
1735 self.shim_instance_index
1736 .expect("shim should be instantiated"),
1737 &shims.shims[&ShimKind::TaskWait { async_: *async_ }].name,
1738 ExportKind::Func,
1739 );
1740 return Ok((ExportKind::Func, index));
1741 }
1742 Import::TaskPoll { async_ } => {
1743 let index = self.component.core_alias_export(
1744 self.shim_instance_index
1745 .expect("shim should be instantiated"),
1746 &shims.shims[&ShimKind::TaskPoll { async_: *async_ }].name,
1747 ExportKind::Func,
1748 );
1749 return Ok((ExportKind::Func, index));
1750 }
1751 Import::TaskYield { async_ } => {
1752 let index = self.component.task_yield(*async_);
1753 return Ok((ExportKind::Func, index));
1754 }
1755 Import::SubtaskDrop => {
1756 let index = self.component.subtask_drop();
1757 return Ok((ExportKind::Func, index));
1758 }
1759 Import::StreamNew(info) => {
1760 let ty = self.payload_type_index(info.ty, info.imported)?;
1761 let index = self.component.stream_new(ty);
1762 return Ok((ExportKind::Func, index));
1763 }
1764 Import::StreamRead { async_, info } => {
1765 return Ok((
1766 ExportKind::Func,
1767 payload_indirect(self, *async_, info, PayloadFuncKind::StreamRead),
1768 ));
1769 }
1770 Import::StreamWrite { async_, info } => {
1771 return Ok((
1772 ExportKind::Func,
1773 payload_indirect(self, *async_, info, PayloadFuncKind::StreamWrite),
1774 ));
1775 }
1776 Import::StreamCancelRead {
1777 ty,
1778 imported,
1779 async_,
1780 } => {
1781 let ty = self.payload_type_index(*ty, *imported)?;
1782 let index = self.component.stream_cancel_read(ty, *async_);
1783 return Ok((ExportKind::Func, index));
1784 }
1785 Import::StreamCancelWrite {
1786 ty,
1787 imported,
1788 async_,
1789 } => {
1790 let ty = self.payload_type_index(*ty, *imported)?;
1791 let index = self.component.stream_cancel_write(ty, *async_);
1792 return Ok((ExportKind::Func, index));
1793 }
1794 Import::StreamCloseReadable { ty, imported } => {
1795 let type_index = self.payload_type_index(*ty, *imported)?;
1796 let index = self.component.stream_close_readable(type_index);
1797 return Ok((ExportKind::Func, index));
1798 }
1799 Import::StreamCloseWritable { ty, imported } => {
1800 let type_index = self.payload_type_index(*ty, *imported)?;
1801 let index = self.component.stream_close_writable(type_index);
1802 return Ok((ExportKind::Func, index));
1803 }
1804 Import::FutureNew(info) => {
1805 let ty = self.payload_type_index(info.ty, info.imported)?;
1806 let index = self.component.future_new(ty);
1807 return Ok((ExportKind::Func, index));
1808 }
1809 Import::FutureRead { async_, info } => {
1810 return Ok((
1811 ExportKind::Func,
1812 payload_indirect(self, *async_, info, PayloadFuncKind::FutureRead),
1813 ));
1814 }
1815 Import::FutureWrite { async_, info } => {
1816 return Ok((
1817 ExportKind::Func,
1818 payload_indirect(self, *async_, info, PayloadFuncKind::FutureWrite),
1819 ));
1820 }
1821 Import::FutureCancelRead {
1822 ty,
1823 imported,
1824 async_,
1825 } => {
1826 let ty = self.payload_type_index(*ty, *imported)?;
1827 let index = self.component.future_cancel_read(ty, *async_);
1828 return Ok((ExportKind::Func, index));
1829 }
1830 Import::FutureCancelWrite {
1831 ty,
1832 imported,
1833 async_,
1834 } => {
1835 let ty = self.payload_type_index(*ty, *imported)?;
1836 let index = self.component.future_cancel_write(ty, *async_);
1837 return Ok((ExportKind::Func, index));
1838 }
1839 Import::FutureCloseReadable { ty, imported } => {
1840 let type_index = self.payload_type_index(*ty, *imported)?;
1841 let index = self.component.future_close_readable(type_index);
1842 return Ok((ExportKind::Func, index));
1843 }
1844 Import::FutureCloseWritable { ty, imported } => {
1845 let type_index = self.payload_type_index(*ty, *imported)?;
1846 let index = self.component.future_close_writable(type_index);
1847 return Ok((ExportKind::Func, index));
1848 }
1849 Import::ErrorContextNew { encoding } => {
1850 let index = self.component.core_alias_export(
1851 self.shim_instance_index
1852 .expect("shim should be instantiated"),
1853 &shims.shims[&ShimKind::ErrorContextNew {
1854 encoding: *encoding,
1855 }]
1856 .name,
1857 ExportKind::Func,
1858 );
1859 return Ok((ExportKind::Func, index));
1860 }
1861 Import::ErrorContextDebugMessage { encoding, realloc } => {
1862 let index = self.component.core_alias_export(
1863 self.shim_instance_index
1864 .expect("shim should be instantiated"),
1865 &shims.shims[&ShimKind::ErrorContextDebugMessage {
1866 for_module,
1867 encoding: *encoding,
1868 realloc,
1869 }]
1870 .name,
1871 ExportKind::Func,
1872 );
1873 return Ok((ExportKind::Func, index));
1874 }
1875 Import::ErrorContextDrop => {
1876 let index = self.component.error_context_drop();
1877 return Ok((ExportKind::Func, index));
1878 }
1879 Import::WorldFunc(key, name, abi) => (key, name, None, *abi),
1880 Import::InterfaceFunc(key, _, name, abi) => {
1881 (key, name, Some(resolve.name_world_key(key)), *abi)
1882 }
1883 };
1884
1885 let import = &self.info.import_map[&interface_key];
1886 let (index, _, lowering) = import.lowerings.get_full(&(name.clone(), abi)).unwrap();
1887 let metadata = self.info.module_metadata_for(for_module);
1888
1889 let index = match lowering {
1890 Lowering::Direct => {
1893 let func_index = match &import.interface {
1894 Some(interface) => {
1895 let instance_index = self.imported_instances[interface];
1896 self.component
1897 .alias_export(instance_index, name, ComponentExportKind::Func)
1898 }
1899 None => self.imported_funcs[name],
1900 };
1901 self.component.lower_func(
1902 func_index,
1903 if let AbiVariant::GuestImportAsync = abi {
1904 vec![CanonicalOption::Async]
1905 } else {
1906 Vec::new()
1907 },
1908 )
1909 }
1910
1911 Lowering::Indirect { .. } => {
1915 let encoding = metadata.import_encodings.get(resolve, key, name).unwrap();
1916 self.core_alias_export(
1917 self.shim_instance_index
1918 .expect("shim should be instantiated"),
1919 &shims.shims[&ShimKind::IndirectLowering {
1920 interface: interface_key,
1921 index,
1922 realloc: for_module,
1923 encoding,
1924 }]
1925 .name,
1926 ExportKind::Func,
1927 )
1928 }
1929
1930 Lowering::ResourceDrop(id) => {
1933 let resource_idx = self.lookup_resource_index(*id);
1934 self.component.resource_drop(resource_idx)
1935 }
1936 };
1937 Ok((ExportKind::Func, index))
1938 }
1939
1940 fn encode_initialize_with_start(&mut self) -> Result<()> {
1959 let initialize = match self.info.info.exports.initialize() {
1960 Some(name) => name,
1961 None => return Ok(()),
1964 };
1965 let initialize_index =
1966 self.core_alias_export(self.instance_index.unwrap(), initialize, ExportKind::Func);
1967 let mut shim = Module::default();
1968 let mut section = TypeSection::new();
1969 section.ty().function([], []);
1970 shim.section(§ion);
1971 let mut section = ImportSection::new();
1972 section.import("", "", EntityType::Function(0));
1973 shim.section(§ion);
1974 shim.section(&StartSection { function_index: 0 });
1975
1976 let shim_module_index = self.component.core_module(&shim);
1981 let shim_args_instance_index =
1982 self.component
1983 .core_instantiate_exports([("", ExportKind::Func, initialize_index)]);
1984 self.component.core_instantiate(
1985 shim_module_index,
1986 [("", ModuleArg::Instance(shim_args_instance_index))],
1987 );
1988 Ok(())
1989 }
1990
1991 fn instance_for(&self, module: CustomModule) -> u32 {
1994 match module {
1995 CustomModule::Main => self.instance_index.expect("instantiated by now"),
1996 CustomModule::Adapter(name) => self.adapter_instances[name],
1997 }
1998 }
1999
2000 fn module_for(&self, module: CustomModule) -> u32 {
2003 match module {
2004 CustomModule::Main => self.module_index.unwrap(),
2005 CustomModule::Adapter(name) => self.adapter_modules[name],
2006 }
2007 }
2008
2009 fn core_alias_export(&mut self, instance: u32, name: &str, kind: ExportKind) -> u32 {
2012 *self
2013 .aliased_core_items
2014 .entry((instance, name.to_string()))
2015 .or_insert_with(|| self.component.core_alias_export(instance, name, kind))
2016 }
2017}
2018
2019#[derive(Default)]
2037struct Shims<'a> {
2038 shims: IndexMap<ShimKind<'a>, Shim<'a>>,
2040}
2041
2042struct Shim<'a> {
2043 options: RequiredOptions,
2046
2047 name: String,
2051
2052 debug_name: String,
2055
2056 kind: ShimKind<'a>,
2058
2059 sig: WasmSignature,
2061}
2062
2063#[derive(Debug, Clone, Hash, Eq, PartialEq)]
2066enum PayloadFuncKind {
2067 FutureWrite,
2068 FutureRead,
2069 StreamWrite,
2070 StreamRead,
2071}
2072
2073#[derive(Debug, Clone, Hash, Eq, PartialEq)]
2074enum ShimKind<'a> {
2075 IndirectLowering {
2079 interface: Option<String>,
2081 index: usize,
2083 realloc: CustomModule<'a>,
2085 encoding: StringEncoding,
2087 },
2088 Adapter {
2091 adapter: &'a str,
2093 func: &'a str,
2095 },
2096 ResourceDtor {
2099 module: CustomModule<'a>,
2101 export: &'a str,
2103 },
2104 PayloadFunc {
2108 for_module: CustomModule<'a>,
2111 async_: bool,
2113 info: &'a PayloadInfo,
2118 kind: PayloadFuncKind,
2120 },
2121 TaskWait { async_: bool },
2124 TaskPoll { async_: bool },
2127 ErrorContextNew {
2131 encoding: StringEncoding,
2133 },
2134 ErrorContextDebugMessage {
2138 for_module: CustomModule<'a>,
2140 encoding: StringEncoding,
2142 realloc: &'a str,
2145 },
2146}
2147
2148#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
2158enum CustomModule<'a> {
2159 Main,
2162 Adapter(&'a str),
2165}
2166
2167impl<'a> Shims<'a> {
2168 fn append_indirect(
2173 &mut self,
2174 world: &'a ComponentWorld<'a>,
2175 for_module: CustomModule<'a>,
2176 ) -> Result<()> {
2177 let module_imports = world.imports_for(for_module);
2178 let module_exports = world.exports_for(for_module);
2179 let metadata = world.module_metadata_for(for_module);
2180 let resolve = &world.encoder.metadata.resolve;
2181
2182 let payload_push =
2183 |me: &mut Self, module, async_, info: &'a PayloadInfo, kind, params, results| {
2184 let debug_name = format!("{module}-{}", info.name);
2185 let name = me.shims.len().to_string();
2186 me.push(Shim {
2187 name,
2188 debug_name,
2189 options: RequiredOptions::empty(),
2190 kind: ShimKind::PayloadFunc {
2191 for_module,
2192 async_,
2193 info,
2194 kind,
2195 },
2196 sig: WasmSignature {
2197 params,
2198 results,
2199 indirect_params: false,
2200 retptr: false,
2201 },
2202 });
2203 };
2204
2205 for (module, field, import) in module_imports.imports() {
2206 let (key, name, interface_key, abi) = match import {
2207 Import::ImportedResourceDrop(..)
2210 | Import::MainModuleMemory
2211 | Import::MainModuleExport { .. }
2212 | Import::Item(_)
2213 | Import::ExportedResourceDrop(..)
2214 | Import::ExportedResourceRep(..)
2215 | Import::ExportedResourceNew(..)
2216 | Import::ErrorContextDrop
2217 | Import::TaskBackpressure
2218 | Import::TaskYield { .. }
2219 | Import::SubtaskDrop
2220 | Import::ExportedTaskReturn(..)
2221 | Import::FutureNew(..)
2222 | Import::StreamNew(..)
2223 | Import::FutureCancelRead { .. }
2224 | Import::FutureCancelWrite { .. }
2225 | Import::FutureCloseWritable { .. }
2226 | Import::FutureCloseReadable { .. }
2227 | Import::StreamCancelRead { .. }
2228 | Import::StreamCancelWrite { .. }
2229 | Import::StreamCloseWritable { .. }
2230 | Import::StreamCloseReadable { .. } => continue,
2231
2232 Import::FutureWrite { async_, info } => {
2233 payload_push(
2234 self,
2235 module,
2236 *async_,
2237 info,
2238 PayloadFuncKind::FutureWrite,
2239 vec![WasmType::I32; 2],
2240 vec![WasmType::I32],
2241 );
2242 continue;
2243 }
2244 Import::FutureRead { async_, info } => {
2245 payload_push(
2246 self,
2247 module,
2248 *async_,
2249 info,
2250 PayloadFuncKind::FutureRead,
2251 vec![WasmType::I32; 2],
2252 vec![WasmType::I32],
2253 );
2254 continue;
2255 }
2256 Import::StreamWrite { async_, info } => {
2257 payload_push(
2258 self,
2259 module,
2260 *async_,
2261 info,
2262 PayloadFuncKind::StreamWrite,
2263 vec![WasmType::I32; 3],
2264 vec![WasmType::I32],
2265 );
2266 continue;
2267 }
2268 Import::StreamRead { async_, info } => {
2269 payload_push(
2270 self,
2271 module,
2272 *async_,
2273 info,
2274 PayloadFuncKind::StreamRead,
2275 vec![WasmType::I32; 3],
2276 vec![WasmType::I32],
2277 );
2278 continue;
2279 }
2280
2281 Import::TaskWait { async_ } => {
2282 let name = self.shims.len().to_string();
2283 self.push(Shim {
2284 name,
2285 debug_name: "task-wait".to_string(),
2286 options: RequiredOptions::empty(),
2287 kind: ShimKind::TaskWait { async_: *async_ },
2288 sig: WasmSignature {
2289 params: vec![WasmType::I32],
2290 results: vec![WasmType::I32],
2291 indirect_params: false,
2292 retptr: false,
2293 },
2294 });
2295 continue;
2296 }
2297
2298 Import::TaskPoll { async_ } => {
2299 let name = self.shims.len().to_string();
2300 self.push(Shim {
2301 name,
2302 debug_name: "task-poll".to_string(),
2303 options: RequiredOptions::empty(),
2304 kind: ShimKind::TaskPoll { async_: *async_ },
2305 sig: WasmSignature {
2306 params: vec![WasmType::I32],
2307 results: vec![WasmType::I32],
2308 indirect_params: false,
2309 retptr: false,
2310 },
2311 });
2312 continue;
2313 }
2314
2315 Import::ErrorContextNew { encoding } => {
2316 let name = self.shims.len().to_string();
2317 self.push(Shim {
2318 name,
2319 debug_name: "error-new".to_string(),
2320 options: RequiredOptions::empty(),
2321 kind: ShimKind::ErrorContextNew {
2322 encoding: *encoding,
2323 },
2324 sig: WasmSignature {
2325 params: vec![WasmType::I32; 2],
2326 results: vec![WasmType::I32],
2327 indirect_params: false,
2328 retptr: false,
2329 },
2330 });
2331 continue;
2332 }
2333
2334 Import::ErrorContextDebugMessage { encoding, realloc } => {
2335 let name = self.shims.len().to_string();
2336 self.push(Shim {
2337 name,
2338 debug_name: "error-debug-message".to_string(),
2339 options: RequiredOptions::empty(),
2340 kind: ShimKind::ErrorContextDebugMessage {
2341 for_module,
2342 encoding: *encoding,
2343 realloc,
2344 },
2345 sig: WasmSignature {
2346 params: vec![WasmType::I32; 2],
2347 results: vec![],
2348 indirect_params: false,
2349 retptr: false,
2350 },
2351 });
2352 continue;
2353 }
2354
2355 Import::AdapterExport(ty) => {
2358 let name = self.shims.len().to_string();
2359 log::debug!("shim {name} is adapter `{module}::{field}`");
2360 self.push(Shim {
2361 name,
2362 debug_name: format!("adapt-{module}-{field}"),
2363 options: RequiredOptions::MEMORY,
2367 kind: ShimKind::Adapter {
2368 adapter: module,
2369 func: field,
2370 },
2371 sig: WasmSignature {
2372 params: ty.params().iter().map(to_wasm_type).collect(),
2373 results: ty.results().iter().map(to_wasm_type).collect(),
2374 indirect_params: false,
2375 retptr: false,
2376 },
2377 });
2378 continue;
2379
2380 fn to_wasm_type(ty: &wasmparser::ValType) -> WasmType {
2381 match ty {
2382 wasmparser::ValType::I32 => WasmType::I32,
2383 wasmparser::ValType::I64 => WasmType::I64,
2384 wasmparser::ValType::F32 => WasmType::F32,
2385 wasmparser::ValType::F64 => WasmType::F64,
2386 _ => unreachable!(),
2387 }
2388 }
2389 }
2390
2391 Import::InterfaceFunc(key, _, name, abi) => {
2395 (key, name, Some(resolve.name_world_key(key)), *abi)
2396 }
2397 Import::WorldFunc(key, name, abi) => (key, name, None, *abi),
2398 };
2399 let interface = &world.import_map[&interface_key];
2400 let (index, _, lowering) = interface.lowerings.get_full(&(name.clone(), abi)).unwrap();
2401 let shim_name = self.shims.len().to_string();
2402 match lowering {
2403 Lowering::Direct | Lowering::ResourceDrop(_) => {}
2404
2405 Lowering::Indirect { sig, options } => {
2406 log::debug!(
2407 "shim {shim_name} is import `{module}::{field}` lowering {index} `{name}`",
2408 );
2409 let encoding = metadata
2410 .import_encodings
2411 .get(resolve, key, name)
2412 .ok_or_else(|| {
2413 anyhow::anyhow!(
2414 "missing component metadata for import of \
2415 `{module}::{field}`"
2416 )
2417 })?;
2418 self.push(Shim {
2419 name: shim_name,
2420 debug_name: format!("indirect-{module}-{field}"),
2421 options: *options,
2422 kind: ShimKind::IndirectLowering {
2423 interface: interface_key,
2424 index,
2425 realloc: for_module,
2426 encoding,
2427 },
2428 sig: sig.clone(),
2429 });
2430 }
2431 }
2432 }
2433
2434 for (export_name, export) in module_exports.iter() {
2440 let id = match export {
2441 Export::ResourceDtor(id) => id,
2442 _ => continue,
2443 };
2444 let resource = resolve.types[*id].name.as_ref().unwrap();
2445 let name = self.shims.len().to_string();
2446 self.push(Shim {
2447 name,
2448 debug_name: format!("dtor-{resource}"),
2449 options: RequiredOptions::empty(),
2450 kind: ShimKind::ResourceDtor {
2451 module: for_module,
2452 export: export_name,
2453 },
2454 sig: WasmSignature {
2455 params: vec![WasmType::I32],
2456 results: Vec::new(),
2457 indirect_params: false,
2458 retptr: false,
2459 },
2460 });
2461 }
2462
2463 Ok(())
2464 }
2465
2466 fn push(&mut self, shim: Shim<'a>) {
2467 if !self.shims.contains_key(&shim.kind) {
2471 self.shims.insert(shim.kind.clone(), shim);
2472 }
2473 }
2474}
2475
2476#[derive(Clone, Debug)]
2478pub struct Item {
2479 pub alias: String,
2480 pub kind: ExportKind,
2481 pub which: MainOrAdapter,
2482 pub name: String,
2483}
2484
2485#[derive(Debug, PartialEq, Clone)]
2487pub enum MainOrAdapter {
2488 Main,
2489 Adapter(String),
2490}
2491
2492impl MainOrAdapter {
2493 fn to_custom_module(&self) -> CustomModule<'_> {
2494 match self {
2495 MainOrAdapter::Main => CustomModule::Main,
2496 MainOrAdapter::Adapter(s) => CustomModule::Adapter(s),
2497 }
2498 }
2499}
2500
2501#[derive(Clone)]
2503pub enum Instance {
2504 MainOrAdapter(MainOrAdapter),
2506
2507 Items(Vec<Item>),
2509}
2510
2511#[derive(Clone)]
2514pub struct LibraryInfo {
2515 pub instantiate_after_shims: bool,
2517
2518 pub arguments: Vec<(String, Instance)>,
2520}
2521
2522pub(super) struct Adapter {
2524 wasm: Vec<u8>,
2526
2527 metadata: ModuleMetadata,
2529
2530 required_exports: IndexSet<WorldKey>,
2533
2534 library_info: Option<LibraryInfo>,
2539}
2540
2541#[derive(Default)]
2543pub struct ComponentEncoder {
2544 module: Vec<u8>,
2545 pub(super) metadata: Bindgen,
2546 validate: bool,
2547 pub(super) main_module_exports: IndexSet<WorldKey>,
2548 pub(super) adapters: IndexMap<String, Adapter>,
2549 import_name_map: HashMap<String, String>,
2550 realloc_via_memory_grow: bool,
2551 merge_imports_based_on_semver: Option<bool>,
2552 pub(super) reject_legacy_names: bool,
2553}
2554
2555impl ComponentEncoder {
2556 pub fn module(mut self, module: &[u8]) -> Result<Self> {
2562 let (wasm, metadata) = self.decode(module)?;
2563 let exports = self
2564 .merge_metadata(metadata)
2565 .context("failed merge WIT metadata for module with previous metadata")?;
2566 self.main_module_exports.extend(exports);
2567 self.module = if let Some(producers) = &self.metadata.producers {
2568 producers.add_to_wasm(&wasm)?
2569 } else {
2570 wasm.to_vec()
2571 };
2572 Ok(self)
2573 }
2574
2575 fn decode<'a>(&self, wasm: &'a [u8]) -> Result<(Cow<'a, [u8]>, Bindgen)> {
2576 let (bytes, metadata) = metadata::decode(wasm)?;
2577 match bytes {
2578 Some(wasm) => Ok((Cow::Owned(wasm), metadata)),
2579 None => Ok((Cow::Borrowed(wasm), metadata)),
2580 }
2581 }
2582
2583 fn merge_metadata(&mut self, metadata: Bindgen) -> Result<IndexSet<WorldKey>> {
2584 self.metadata.merge(metadata)
2585 }
2586
2587 pub fn validate(mut self, validate: bool) -> Self {
2589 self.validate = validate;
2590 self
2591 }
2592
2593 pub fn merge_imports_based_on_semver(mut self, merge: bool) -> Self {
2601 self.merge_imports_based_on_semver = Some(merge);
2602 self
2603 }
2604
2605 pub fn reject_legacy_names(mut self, reject: bool) -> Self {
2614 self.reject_legacy_names = reject;
2615 self
2616 }
2617
2618 pub fn adapter(self, name: &str, bytes: &[u8]) -> Result<Self> {
2636 self.library_or_adapter(name, bytes, None)
2637 }
2638
2639 pub fn library(self, name: &str, bytes: &[u8], library_info: LibraryInfo) -> Result<Self> {
2652 self.library_or_adapter(name, bytes, Some(library_info))
2653 }
2654
2655 fn library_or_adapter(
2656 mut self,
2657 name: &str,
2658 bytes: &[u8],
2659 library_info: Option<LibraryInfo>,
2660 ) -> Result<Self> {
2661 let (wasm, mut metadata) = self.decode(bytes)?;
2662 let adapter_metadata = mem::take(&mut metadata.metadata);
2670 let exports = self.merge_metadata(metadata).with_context(|| {
2671 format!("failed to merge WIT packages of adapter `{name}` into main packages")
2672 })?;
2673 if let Some(library_info) = &library_info {
2674 for (_, instance) in &library_info.arguments {
2676 let resolve = |which: &_| match which {
2677 MainOrAdapter::Main => Ok(()),
2678 MainOrAdapter::Adapter(name) => {
2679 if self.adapters.contains_key(name.as_str()) {
2680 Ok(())
2681 } else {
2682 Err(anyhow!("instance refers to unknown adapter `{name}`"))
2683 }
2684 }
2685 };
2686
2687 match instance {
2688 Instance::MainOrAdapter(which) => resolve(which)?,
2689 Instance::Items(items) => {
2690 for item in items {
2691 resolve(&item.which)?;
2692 }
2693 }
2694 }
2695 }
2696 }
2697 self.adapters.insert(
2698 name.to_string(),
2699 Adapter {
2700 wasm: wasm.to_vec(),
2701 metadata: adapter_metadata,
2702 required_exports: exports,
2703 library_info,
2704 },
2705 );
2706 Ok(self)
2707 }
2708
2709 pub fn realloc_via_memory_grow(mut self, value: bool) -> Self {
2714 self.realloc_via_memory_grow = value;
2715 self
2716 }
2717
2718 pub fn import_name_map(mut self, map: HashMap<String, String>) -> Self {
2729 self.import_name_map = map;
2730 self
2731 }
2732
2733 pub fn encode(&mut self) -> Result<Vec<u8>> {
2735 if self.module.is_empty() {
2736 bail!("a module is required when encoding a component");
2737 }
2738
2739 if self.merge_imports_based_on_semver.unwrap_or(true) {
2740 self.metadata
2741 .resolve
2742 .merge_world_imports_based_on_semver(self.metadata.world)?;
2743 }
2744
2745 let world = ComponentWorld::new(self).context("failed to decode world from module")?;
2746 let mut state = EncodingState {
2747 component: ComponentBuilder::default(),
2748 module_index: None,
2749 instance_index: None,
2750 memory_index: None,
2751 shim_instance_index: None,
2752 fixups_module_index: None,
2753 adapter_modules: IndexMap::new(),
2754 adapter_instances: IndexMap::new(),
2755 import_type_map: HashMap::new(),
2756 import_func_type_map: HashMap::new(),
2757 export_type_map: HashMap::new(),
2758 export_func_type_map: HashMap::new(),
2759 imported_instances: Default::default(),
2760 imported_funcs: Default::default(),
2761 exported_instances: Default::default(),
2762 aliased_core_items: Default::default(),
2763 info: &world,
2764 };
2765 state.encode_imports(&self.import_name_map)?;
2766 state.encode_core_modules();
2767 state.encode_core_instantiation()?;
2768 state.encode_exports(CustomModule::Main)?;
2769 for name in self.adapters.keys() {
2770 state.encode_exports(CustomModule::Adapter(name))?;
2771 }
2772 state
2773 .component
2774 .raw_custom_section(&crate::base_producers().raw_custom_section());
2775 let bytes = state.component.finish();
2776
2777 if self.validate {
2778 Validator::new()
2779 .validate_all(&bytes)
2780 .context("failed to validate component output")?;
2781 }
2782
2783 Ok(bytes)
2784 }
2785}
2786
2787impl ComponentWorld<'_> {
2788 fn imports_for(&self, module: CustomModule) -> &ImportMap {
2790 match module {
2791 CustomModule::Main => &self.info.imports,
2792 CustomModule::Adapter(name) => &self.adapters[name].info.imports,
2793 }
2794 }
2795
2796 fn exports_for(&self, module: CustomModule) -> &ExportMap {
2798 match module {
2799 CustomModule::Main => &self.info.exports,
2800 CustomModule::Adapter(name) => &self.adapters[name].info.exports,
2801 }
2802 }
2803
2804 fn module_metadata_for(&self, module: CustomModule) -> &ModuleMetadata {
2806 match module {
2807 CustomModule::Main => &self.encoder.metadata.metadata,
2808 CustomModule::Adapter(name) => &self.encoder.adapters[name].metadata,
2809 }
2810 }
2811}
2812
2813#[cfg(all(test, feature = "dummy-module"))]
2814mod test {
2815 use super::*;
2816 use crate::{dummy_module, embed_component_metadata};
2817 use wit_parser::ManglingAndAbi;
2818
2819 #[test]
2820 fn it_renames_imports() {
2821 let mut resolve = Resolve::new();
2822 let pkg = resolve
2823 .push_str(
2824 "test.wit",
2825 r#"
2826package test:wit;
2827
2828interface i {
2829 f: func();
2830}
2831
2832world test {
2833 import i;
2834 import foo: interface {
2835 f: func();
2836 }
2837}
2838"#,
2839 )
2840 .unwrap();
2841 let world = resolve.select_world(pkg, None).unwrap();
2842
2843 let mut module = dummy_module(&resolve, world, ManglingAndAbi::Standard32);
2844
2845 embed_component_metadata(&mut module, &resolve, world, StringEncoding::UTF8).unwrap();
2846
2847 let encoded = ComponentEncoder::default()
2848 .import_name_map(HashMap::from([
2849 (
2850 "foo".to_string(),
2851 "unlocked-dep=<foo:bar/foo@{>=1.0.0 <1.1.0}>".to_string(),
2852 ),
2853 (
2854 "test:wit/i".to_string(),
2855 "locked-dep=<foo:bar/i@1.2.3>".to_string(),
2856 ),
2857 ]))
2858 .module(&module)
2859 .unwrap()
2860 .validate(true)
2861 .encode()
2862 .unwrap();
2863
2864 let wat = wasmprinter::print_bytes(encoded).unwrap();
2865 assert!(wat.contains("unlocked-dep=<foo:bar/foo@{>=1.0.0 <1.1.0}>"));
2866 assert!(wat.contains("locked-dep=<foo:bar/i@1.2.3>"));
2867 }
2868}