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, WasmFeatures};
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::Unknown => unreachable!(),
327 },
328 Type::String => Self::STRING,
329 _ => Self::empty(),
330 }
331 }
332}
333
334pub struct EncodingState<'a> {
336 component: ComponentBuilder,
338 module_index: Option<u32>,
342 instance_index: Option<u32>,
346 memory_index: Option<u32>,
350 shim_instance_index: Option<u32>,
354 fixups_module_index: Option<u32>,
358
359 adapter_modules: IndexMap<&'a str, u32>,
362 adapter_instances: IndexMap<&'a str, u32>,
364
365 imported_instances: IndexMap<InterfaceId, u32>,
367 imported_funcs: IndexMap<String, u32>,
368 exported_instances: IndexMap<InterfaceId, u32>,
369
370 import_type_map: HashMap<TypeId, u32>,
375 import_func_type_map: HashMap<types::FunctionKey<'a>, u32>,
376 export_type_map: HashMap<TypeId, u32>,
377 export_func_type_map: HashMap<types::FunctionKey<'a>, u32>,
378
379 aliased_core_items: HashMap<(u32, String), u32>,
385
386 info: &'a ComponentWorld<'a>,
388}
389
390impl<'a> EncodingState<'a> {
391 fn encode_core_modules(&mut self) {
392 assert!(self.module_index.is_none());
393 let idx = self.component.core_module_raw(&self.info.encoder.module);
394 self.module_index = Some(idx);
395
396 for (name, adapter) in self.info.adapters.iter() {
397 let add_meta = wasm_metadata::AddMetadata {
398 name: Some(if adapter.library_info.is_some() {
399 name.to_string()
400 } else {
401 format!("wit-component:adapter:{name}")
402 }),
403 ..Default::default()
404 };
405 let wasm = add_meta
406 .to_wasm(&adapter.wasm)
407 .expect("core wasm can get name added");
408 let idx = self.component.core_module_raw(&wasm);
409 let prev = self.adapter_modules.insert(name, idx);
410 assert!(prev.is_none());
411 }
412 }
413
414 fn root_import_type_encoder(
415 &mut self,
416 interface: Option<InterfaceId>,
417 ) -> RootTypeEncoder<'_, 'a> {
418 RootTypeEncoder {
419 state: self,
420 interface,
421 import_types: true,
422 }
423 }
424
425 fn root_export_type_encoder(
426 &mut self,
427 interface: Option<InterfaceId>,
428 ) -> RootTypeEncoder<'_, 'a> {
429 RootTypeEncoder {
430 state: self,
431 interface,
432 import_types: false,
433 }
434 }
435
436 fn instance_type_encoder(&mut self, interface: InterfaceId) -> InstanceTypeEncoder<'_, 'a> {
437 InstanceTypeEncoder {
438 state: self,
439 interface,
440 type_map: Default::default(),
441 func_type_map: Default::default(),
442 ty: Default::default(),
443 }
444 }
445
446 fn encode_imports(&mut self, name_map: &HashMap<String, String>) -> Result<()> {
447 let mut has_funcs = false;
448 for (name, info) in self.info.import_map.iter() {
449 match name {
450 Some(name) => {
451 self.encode_interface_import(name_map.get(name).unwrap_or(name), info)?
452 }
453 None => has_funcs = true,
454 }
455 }
456
457 let resolve = &self.info.encoder.metadata.resolve;
458 let world = &resolve.worlds[self.info.encoder.metadata.world];
459 for (_name, item) in world.imports.iter() {
460 if let WorldItem::Type(ty) = item {
461 self.root_import_type_encoder(None)
462 .encode_valtype(resolve, &Type::Id(*ty))?;
463 }
464 }
465
466 if has_funcs {
467 let info = &self.info.import_map[&None];
468 self.encode_root_import_funcs(info)?;
469 }
470 Ok(())
471 }
472
473 fn encode_interface_import(&mut self, name: &str, info: &ImportedInterface) -> Result<()> {
474 let resolve = &self.info.encoder.metadata.resolve;
475 let interface_id = info.interface.as_ref().unwrap();
476 let interface_id = *interface_id;
477 let interface = &resolve.interfaces[interface_id];
478 log::trace!("encoding imports for `{name}` as {:?}", interface_id);
479 let mut encoder = self.instance_type_encoder(interface_id);
480
481 if let Some(live) = encoder.state.info.live_type_imports.get(&interface_id) {
483 for ty in live {
484 log::trace!(
485 "encoding extra type {ty:?} name={:?}",
486 resolve.types[*ty].name
487 );
488 encoder.encode_valtype(resolve, &Type::Id(*ty))?;
489 }
490 }
491
492 for (_, func) in interface.functions.iter() {
495 if !(info
496 .lowerings
497 .contains_key(&(func.name.clone(), AbiVariant::GuestImport))
498 || info
499 .lowerings
500 .contains_key(&(func.name.clone(), AbiVariant::GuestImportAsync)))
501 {
502 continue;
503 }
504 log::trace!("encoding function type for `{}`", func.name);
505 let idx = encoder.encode_func_type(resolve, func)?;
506
507 encoder.ty.export(&func.name, ComponentTypeRef::Func(idx));
508 }
509
510 let ty = encoder.ty;
511 if ty.is_empty() {
514 return Ok(());
515 }
516 let instance_type_idx = self.component.type_instance(&ty);
517 let instance_idx = self
518 .component
519 .import(name, ComponentTypeRef::Instance(instance_type_idx));
520 let prev = self.imported_instances.insert(interface_id, instance_idx);
521 assert!(prev.is_none());
522 Ok(())
523 }
524
525 fn encode_root_import_funcs(&mut self, info: &ImportedInterface) -> Result<()> {
526 let resolve = &self.info.encoder.metadata.resolve;
527 let world = self.info.encoder.metadata.world;
528 for (name, item) in resolve.worlds[world].imports.iter() {
529 let func = match item {
530 WorldItem::Function(f) => f,
531 WorldItem::Interface { .. } | WorldItem::Type(_) => continue,
532 };
533 let name = resolve.name_world_key(name);
534 if !(info
535 .lowerings
536 .contains_key(&(name.clone(), AbiVariant::GuestImport))
537 || info
538 .lowerings
539 .contains_key(&(name.clone(), AbiVariant::GuestImportAsync)))
540 {
541 continue;
542 }
543 log::trace!("encoding function type for `{}`", func.name);
544 let idx = self
545 .root_import_type_encoder(None)
546 .encode_func_type(resolve, func)?;
547 let func_idx = self.component.import(&name, ComponentTypeRef::Func(idx));
548 let prev = self.imported_funcs.insert(name, func_idx);
549 assert!(prev.is_none());
550 }
551 Ok(())
552 }
553
554 fn alias_imported_type(&mut self, interface: InterfaceId, id: TypeId) -> u32 {
555 let ty = &self.info.encoder.metadata.resolve.types[id];
556 let name = ty.name.as_ref().expect("type must have a name");
557 let instance = self.imported_instances[&interface];
558 self.component
559 .alias_export(instance, name, ComponentExportKind::Type)
560 }
561
562 fn alias_exported_type(&mut self, interface: InterfaceId, id: TypeId) -> u32 {
563 let ty = &self.info.encoder.metadata.resolve.types[id];
564 let name = ty.name.as_ref().expect("type must have a name");
565 let instance = self.exported_instances[&interface];
566 self.component
567 .alias_export(instance, name, ComponentExportKind::Type)
568 }
569
570 fn encode_core_instantiation(&mut self) -> Result<()> {
571 let shims = self.encode_shim_instantiation()?;
573
574 self.declare_exported_resources(&shims);
578
579 self.instantiate_main_module(&shims)?;
583
584 let (before, after) = self
587 .info
588 .adapters
589 .iter()
590 .partition::<Vec<_>, _>(|(_, adapter)| {
591 !matches!(
592 adapter.library_info,
593 Some(LibraryInfo {
594 instantiate_after_shims: true,
595 ..
596 })
597 )
598 });
599
600 for (name, _adapter) in before {
601 self.instantiate_adapter_module(&shims, name)?;
602 }
603
604 self.encode_indirect_lowerings(&shims)?;
607
608 for (name, _adapter) in after {
609 self.instantiate_adapter_module(&shims, name)?;
610 }
611
612 self.encode_initialize_with_start()?;
613
614 Ok(())
615 }
616
617 fn lookup_resource_index(&mut self, id: TypeId) -> u32 {
618 let resolve = &self.info.encoder.metadata.resolve;
619 let ty = &resolve.types[id];
620 match ty.owner {
621 TypeOwner::World(_) => self.import_type_map[&id],
625 TypeOwner::Interface(i) => {
626 let instance = self.imported_instances[&i];
627 let name = ty.name.as_ref().expect("resources must be named");
628 self.component
629 .alias_export(instance, name, ComponentExportKind::Type)
630 }
631 TypeOwner::None => panic!("resources must have an owner"),
632 }
633 }
634
635 fn encode_exports(&mut self, module: CustomModule) -> Result<()> {
636 let resolve = &self.info.encoder.metadata.resolve;
637 let exports = match module {
638 CustomModule::Main => &self.info.encoder.main_module_exports,
639 CustomModule::Adapter(name) => &self.info.encoder.adapters[name].required_exports,
640 };
641
642 if exports.is_empty() {
643 return Ok(());
644 }
645
646 let mut interface_func_core_names = IndexMap::new();
647 let mut world_func_core_names = IndexMap::new();
648 for (core_name, export) in self.info.exports_for(module).iter() {
649 match export {
650 Export::WorldFunc(_, name, _) => {
651 let prev = world_func_core_names.insert(name, core_name);
652 assert!(prev.is_none());
653 }
654 Export::InterfaceFunc(_, id, name, _) => {
655 let prev = interface_func_core_names
656 .entry(id)
657 .or_insert(IndexMap::new())
658 .insert(name.as_str(), core_name);
659 assert!(prev.is_none());
660 }
661 Export::WorldFuncCallback(..)
662 | Export::InterfaceFuncCallback(..)
663 | Export::WorldFuncPostReturn(..)
664 | Export::InterfaceFuncPostReturn(..)
665 | Export::ResourceDtor(..)
666 | Export::Memory
667 | Export::GeneralPurposeRealloc
668 | Export::GeneralPurposeExportRealloc
669 | Export::GeneralPurposeImportRealloc
670 | Export::Initialize
671 | Export::ReallocForAdapter => continue,
672 }
673 }
674
675 let world = &resolve.worlds[self.info.encoder.metadata.world];
676
677 for export_name in exports {
678 let export_string = resolve.name_world_key(export_name);
679 match &world.exports[export_name] {
680 WorldItem::Function(func) => {
681 let ty = self
682 .root_import_type_encoder(None)
683 .encode_func_type(resolve, func)?;
684 let core_name = world_func_core_names[&func.name];
685 let idx = self.encode_lift(module, &core_name, export_name, func, ty)?;
686 self.component
687 .export(&export_string, ComponentExportKind::Func, idx, None);
688 }
689 WorldItem::Interface { id, .. } => {
690 let core_names = interface_func_core_names.get(id);
691 self.encode_interface_export(
692 &export_string,
693 module,
694 export_name,
695 *id,
696 core_names,
697 )?;
698 }
699 WorldItem::Type(_) => unreachable!(),
700 }
701 }
702
703 Ok(())
704 }
705
706 fn encode_interface_export(
707 &mut self,
708 export_name: &str,
709 module: CustomModule<'_>,
710 key: &WorldKey,
711 export: InterfaceId,
712 interface_func_core_names: Option<&IndexMap<&str, &str>>,
713 ) -> Result<()> {
714 log::trace!("encode interface export `{export_name}`");
715 let resolve = &self.info.encoder.metadata.resolve;
716
717 let mut imports = Vec::new();
724 let mut root = self.root_export_type_encoder(Some(export));
725 for (_, func) in &resolve.interfaces[export].functions {
726 let core_name = interface_func_core_names.unwrap()[func.name.as_str()];
727 let ty = root.encode_func_type(resolve, func)?;
728 let func_index = root.state.encode_lift(module, &core_name, key, func, ty)?;
729 imports.push((
730 import_func_name(func),
731 ComponentExportKind::Func,
732 func_index,
733 ));
734 }
735
736 let mut nested = NestedComponentTypeEncoder {
740 component: ComponentBuilder::default(),
741 type_map: Default::default(),
742 func_type_map: Default::default(),
743 export_types: false,
744 interface: export,
745 state: self,
746 imports: IndexMap::new(),
747 };
748
749 let mut types_to_import = LiveTypes::default();
759 types_to_import.add_interface(resolve, export);
760 let exports_used = &nested.state.info.exports_used[&export];
761 for ty in types_to_import.iter() {
762 if let TypeOwner::Interface(owner) = resolve.types[ty].owner {
763 if owner == export {
764 continue;
767 }
768
769 let mut encoder = if exports_used.contains(&owner) {
772 nested.state.root_export_type_encoder(Some(export))
773 } else {
774 nested.state.root_import_type_encoder(Some(export))
775 };
776 encoder.encode_valtype(resolve, &Type::Id(ty))?;
777
778 nested.interface = owner;
782 nested.encode_valtype(resolve, &Type::Id(ty))?;
783 }
784 }
785 nested.interface = export;
786
787 let imported_types = nested.type_map.clone();
791
792 let mut resources = HashMap::new();
798 for (_name, ty) in resolve.interfaces[export].types.iter() {
799 if !matches!(resolve.types[*ty].kind, TypeDefKind::Resource) {
800 continue;
801 }
802 let idx = match nested.encode_valtype(resolve, &Type::Id(*ty))? {
803 ComponentValType::Type(idx) => idx,
804 _ => unreachable!(),
805 };
806 resources.insert(*ty, idx);
807 }
808
809 for (_, func) in resolve.interfaces[export].functions.iter() {
813 let ty = nested.encode_func_type(resolve, func)?;
814 nested
815 .component
816 .import(&import_func_name(func), ComponentTypeRef::Func(ty));
817 }
818
819 let reverse_map = nested
826 .type_map
827 .drain()
828 .map(|p| (p.1, p.0))
829 .collect::<HashMap<_, _>>();
830 for (name, idx) in nested.imports.drain(..) {
831 let id = reverse_map[&idx];
832 let owner = match resolve.types[id].owner {
833 TypeOwner::Interface(id) => id,
834 _ => unreachable!(),
835 };
836 let idx = if owner == export || exports_used.contains(&owner) {
837 log::trace!("consulting exports for {id:?}");
838 nested.state.export_type_map[&id]
839 } else {
840 log::trace!("consulting imports for {id:?}");
841 nested.state.import_type_map[&id]
842 };
843 imports.push((name, ComponentExportKind::Type, idx))
844 }
845
846 nested.type_map = imported_types;
851
852 nested.export_types = true;
859 nested.func_type_map.clear();
860
861 for (_, id) in resolve.interfaces[export].types.iter() {
867 let ty = &resolve.types[*id];
868 match ty.kind {
869 TypeDefKind::Resource => {
870 let idx = nested.component.export(
871 ty.name.as_ref().expect("resources must be named"),
872 ComponentExportKind::Type,
873 resources[id],
874 None,
875 );
876 nested.type_map.insert(*id, idx);
877 }
878 _ => {
879 nested.encode_valtype(resolve, &Type::Id(*id))?;
880 }
881 }
882 }
883
884 for (i, (_, func)) in resolve.interfaces[export].functions.iter().enumerate() {
885 let ty = nested.encode_func_type(resolve, func)?;
886 nested.component.export(
887 &func.name,
888 ComponentExportKind::Func,
889 i as u32,
890 Some(ComponentTypeRef::Func(ty)),
891 );
892 }
893
894 let component = nested.component;
898 let component_index = self.component.component(component);
899 let instance_index = self.component.instantiate(component_index, imports);
900 let idx = self.component.export(
901 export_name,
902 ComponentExportKind::Instance,
903 instance_index,
904 None,
905 );
906 let prev = self.exported_instances.insert(export, idx);
907 assert!(prev.is_none());
908
909 for (_name, id) in resolve.interfaces[export].types.iter() {
917 self.export_type_map.remove(id);
918 }
919
920 return Ok(());
921
922 struct NestedComponentTypeEncoder<'state, 'a> {
923 component: ComponentBuilder,
924 type_map: HashMap<TypeId, u32>,
925 func_type_map: HashMap<types::FunctionKey<'a>, u32>,
926 export_types: bool,
927 interface: InterfaceId,
928 state: &'state mut EncodingState<'a>,
929 imports: IndexMap<String, u32>,
930 }
931
932 impl<'a> ValtypeEncoder<'a> for NestedComponentTypeEncoder<'_, 'a> {
933 fn defined_type(&mut self) -> (u32, ComponentDefinedTypeEncoder<'_>) {
934 self.component.type_defined()
935 }
936 fn define_function_type(&mut self) -> (u32, ComponentFuncTypeEncoder<'_>) {
937 self.component.type_function()
938 }
939 fn export_type(&mut self, idx: u32, name: &'a str) -> Option<u32> {
940 if self.export_types {
941 Some(
942 self.component
943 .export(name, ComponentExportKind::Type, idx, None),
944 )
945 } else {
946 let name = self.unique_import_name(name);
947 let ret = self
948 .component
949 .import(&name, ComponentTypeRef::Type(TypeBounds::Eq(idx)));
950 self.imports.insert(name, ret);
951 Some(ret)
952 }
953 }
954 fn export_resource(&mut self, name: &'a str) -> u32 {
955 if self.export_types {
956 panic!("resources should already be exported")
957 } else {
958 let name = self.unique_import_name(name);
959 let ret = self
960 .component
961 .import(&name, ComponentTypeRef::Type(TypeBounds::SubResource));
962 self.imports.insert(name, ret);
963 ret
964 }
965 }
966 fn import_type(&mut self, _: InterfaceId, _id: TypeId) -> u32 {
967 unreachable!()
968 }
969 fn type_map(&mut self) -> &mut HashMap<TypeId, u32> {
970 &mut self.type_map
971 }
972 fn func_type_map(&mut self) -> &mut HashMap<types::FunctionKey<'a>, u32> {
973 &mut self.func_type_map
974 }
975 fn interface(&self) -> Option<InterfaceId> {
976 Some(self.interface)
977 }
978 }
979
980 impl NestedComponentTypeEncoder<'_, '_> {
981 fn unique_import_name(&mut self, name: &str) -> String {
982 let mut name = format!("import-type-{name}");
983 let mut n = 0;
984 while self.imports.contains_key(&name) {
985 name = format!("{name}{n}");
986 n += 1;
987 }
988 name
989 }
990 }
991
992 fn import_func_name(f: &Function) -> String {
993 match f.kind {
994 FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => {
995 format!("import-func-{}", f.item_name())
996 }
997
998 FunctionKind::Method(_)
1006 | FunctionKind::AsyncMethod(_)
1007 | FunctionKind::Static(_)
1008 | FunctionKind::AsyncStatic(_)
1009 | FunctionKind::Constructor(_) => {
1010 format!(
1011 "import-{}",
1012 f.name.replace('[', "").replace([']', '.', ' '], "-")
1013 )
1014 }
1015 }
1016 }
1017 }
1018
1019 fn encode_lift(
1020 &mut self,
1021 module: CustomModule<'_>,
1022 core_name: &str,
1023 key: &WorldKey,
1024 func: &Function,
1025 ty: u32,
1026 ) -> Result<u32> {
1027 let resolve = &self.info.encoder.metadata.resolve;
1028 let metadata = self.info.module_metadata_for(module);
1029 let instance_index = self.instance_for(module);
1030 let core_func_index = self.core_alias_export(instance_index, core_name, ExportKind::Func);
1031 let exports = self.info.exports_for(module);
1032
1033 let options = RequiredOptions::for_export(
1034 resolve,
1035 func,
1036 exports
1037 .abi(key, func)
1038 .ok_or_else(|| anyhow!("no ABI found for {}", func.name))?,
1039 );
1040
1041 let encoding = metadata
1042 .export_encodings
1043 .get(resolve, key, &func.name)
1044 .unwrap();
1045 let exports = self.info.exports_for(module);
1046 let realloc_index = exports
1047 .export_realloc_for(key, &func.name)
1048 .map(|name| self.core_alias_export(instance_index, name, ExportKind::Func));
1049 let mut options = options
1050 .into_iter(encoding, self.memory_index, realloc_index)?
1051 .collect::<Vec<_>>();
1052
1053 if let Some(post_return) = exports.post_return(key, func) {
1054 let post_return = self.core_alias_export(instance_index, post_return, ExportKind::Func);
1055 options.push(CanonicalOption::PostReturn(post_return));
1056 }
1057 if let Some(callback) = exports.callback(key, func) {
1058 let callback = self.core_alias_export(instance_index, callback, ExportKind::Func);
1059 options.push(CanonicalOption::Callback(callback));
1060 }
1061 let func_index = self.component.lift_func(core_func_index, ty, options);
1062 Ok(func_index)
1063 }
1064
1065 fn encode_shim_instantiation(&mut self) -> Result<Shims<'a>> {
1066 let mut ret = Shims::default();
1067
1068 ret.append_indirect(self.info, CustomModule::Main)
1069 .context("failed to register indirect shims for main module")?;
1070
1071 for (adapter_name, _adapter) in self.info.adapters.iter() {
1075 ret.append_indirect(self.info, CustomModule::Adapter(adapter_name))
1076 .with_context(|| {
1077 format!("failed to register indirect shims for adapter {adapter_name}")
1078 })?;
1079 }
1080
1081 if ret.shims.is_empty() {
1082 return Ok(ret);
1083 }
1084
1085 assert!(self.shim_instance_index.is_none());
1086 assert!(self.fixups_module_index.is_none());
1087
1088 let mut types = TypeSection::new();
1097 let mut tables = TableSection::new();
1098 let mut functions = FunctionSection::new();
1099 let mut exports = ExportSection::new();
1100 let mut code = CodeSection::new();
1101 let mut sigs = IndexMap::new();
1102 let mut imports_section = ImportSection::new();
1103 let mut elements = ElementSection::new();
1104 let mut func_indexes = Vec::new();
1105 let mut func_names = NameMap::new();
1106
1107 for (i, shim) in ret.shims.values().enumerate() {
1108 let i = i as u32;
1109 let type_index = *sigs.entry(&shim.sig).or_insert_with(|| {
1110 let index = types.len();
1111 types.ty().function(
1112 shim.sig.params.iter().map(to_val_type),
1113 shim.sig.results.iter().map(to_val_type),
1114 );
1115 index
1116 });
1117
1118 functions.function(type_index);
1119 Self::encode_shim_function(type_index, i, &mut code, shim.sig.params.len() as u32);
1120 exports.export(&shim.name, ExportKind::Func, i);
1121
1122 imports_section.import("", &shim.name, EntityType::Function(type_index));
1123 func_indexes.push(i);
1124 func_names.append(i, &shim.debug_name);
1125 }
1126 let mut names = NameSection::new();
1127 names.module("wit-component:shim");
1128 names.functions(&func_names);
1129
1130 let table_type = TableType {
1131 element_type: RefType::FUNCREF,
1132 minimum: ret.shims.len() as u64,
1133 maximum: Some(ret.shims.len() as u64),
1134 table64: false,
1135 shared: false,
1136 };
1137
1138 tables.table(table_type);
1139
1140 exports.export(INDIRECT_TABLE_NAME, ExportKind::Table, 0);
1141 imports_section.import("", INDIRECT_TABLE_NAME, table_type);
1142
1143 elements.active(
1144 None,
1145 &ConstExpr::i32_const(0),
1146 Elements::Functions(func_indexes.into()),
1147 );
1148
1149 let mut shim = Module::new();
1150 shim.section(&types);
1151 shim.section(&functions);
1152 shim.section(&tables);
1153 shim.section(&exports);
1154 shim.section(&code);
1155 shim.section(&RawCustomSection(
1156 &crate::base_producers().raw_custom_section(),
1157 ));
1158 shim.section(&names);
1159
1160 let mut fixups = Module::default();
1161 fixups.section(&types);
1162 fixups.section(&imports_section);
1163 fixups.section(&elements);
1164 fixups.section(&RawCustomSection(
1165 &crate::base_producers().raw_custom_section(),
1166 ));
1167
1168 let mut names = NameSection::new();
1169 names.module("wit-component:fixups");
1170 fixups.section(&names);
1171
1172 let shim_module_index = self.component.core_module(&shim);
1173 self.fixups_module_index = Some(self.component.core_module(&fixups));
1174 self.shim_instance_index = Some(self.component.core_instantiate(shim_module_index, []));
1175
1176 return Ok(ret);
1177 }
1178
1179 fn encode_shim_function(
1180 type_index: u32,
1181 func_index: u32,
1182 code: &mut CodeSection,
1183 param_count: u32,
1184 ) {
1185 let mut func = wasm_encoder::Function::new(std::iter::empty());
1186 for i in 0..param_count {
1187 func.instructions().local_get(i);
1188 }
1189 func.instructions().i32_const(func_index as i32);
1190 func.instructions().call_indirect(0, type_index);
1191 func.instructions().end();
1192 code.function(&func);
1193 }
1194
1195 fn encode_indirect_lowerings(&mut self, shims: &Shims<'_>) -> Result<()> {
1196 if shims.shims.is_empty() {
1197 return Ok(());
1198 }
1199
1200 let shim_instance_index = self
1201 .shim_instance_index
1202 .expect("must have an instantiated shim");
1203
1204 let table_index =
1205 self.core_alias_export(shim_instance_index, INDIRECT_TABLE_NAME, ExportKind::Table);
1206
1207 let resolve = &self.info.encoder.metadata.resolve;
1208
1209 let mut exports = Vec::new();
1210 exports.push((INDIRECT_TABLE_NAME, ExportKind::Table, table_index));
1211
1212 for shim in shims.shims.values() {
1213 let core_func_index = match &shim.kind {
1214 ShimKind::IndirectLowering {
1221 interface,
1222 index,
1223 realloc,
1224 encoding,
1225 } => {
1226 let interface = &self.info.import_map[interface];
1227 let ((name, _), _) = interface.lowerings.get_index(*index).unwrap();
1228 let func_index = match &interface.interface {
1229 Some(interface_id) => {
1230 let instance_index = self.imported_instances[interface_id];
1231 self.component.alias_export(
1232 instance_index,
1233 name,
1234 ComponentExportKind::Func,
1235 )
1236 }
1237 None => self.imported_funcs[name],
1238 };
1239
1240 let realloc = self
1241 .info
1242 .exports_for(*realloc)
1243 .import_realloc_for(interface.interface, name)
1244 .map(|name| {
1245 let instance = self.instance_for(*realloc);
1246 self.core_alias_export(instance, name, ExportKind::Func)
1247 });
1248
1249 self.component.lower_func(
1250 func_index,
1251 shim.options
1252 .into_iter(*encoding, self.memory_index, realloc)?,
1253 )
1254 }
1255
1256 ShimKind::Adapter { adapter, func } => {
1261 self.core_alias_export(self.adapter_instances[adapter], func, ExportKind::Func)
1262 }
1263
1264 ShimKind::ResourceDtor { module, export } => {
1269 self.core_alias_export(self.instance_for(*module), export, ExportKind::Func)
1270 }
1271
1272 ShimKind::PayloadFunc {
1273 for_module,
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),
1285 exports.import_realloc_for(info.interface, &info.function),
1286 )
1287 } else {
1288 (
1289 metadata
1290 .export_encodings
1291 .get(resolve, &info.key, &info.function),
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 type_index = self.payload_type_index(info)?;
1299 let options =
1300 shim.options
1301 .into_iter(encoding, self.memory_index, realloc_index)?;
1302
1303 match kind {
1304 PayloadFuncKind::FutureWrite => {
1305 self.component.future_write(type_index, options)
1306 }
1307 PayloadFuncKind::FutureRead => {
1308 self.component.future_read(type_index, options)
1309 }
1310 PayloadFuncKind::StreamWrite => {
1311 self.component.stream_write(type_index, options)
1312 }
1313 PayloadFuncKind::StreamRead => {
1314 self.component.stream_read(type_index, options)
1315 }
1316 }
1317 }
1318
1319 ShimKind::WaitableSetWait { async_ } => self
1320 .component
1321 .waitable_set_wait(*async_, self.memory_index.unwrap()),
1322 ShimKind::WaitableSetPoll { async_ } => self
1323 .component
1324 .waitable_set_poll(*async_, self.memory_index.unwrap()),
1325 ShimKind::ErrorContextNew { encoding } => self.component.error_context_new(
1326 shim.options.into_iter(*encoding, self.memory_index, None)?,
1327 ),
1328 ShimKind::ErrorContextDebugMessage {
1329 for_module,
1330 encoding,
1331 } => {
1332 let instance_index = self.instance_for(*for_module);
1333 let realloc = self.info.exports_for(*for_module).import_realloc_fallback();
1334 let realloc_index = realloc
1335 .map(|r| self.core_alias_export(instance_index, r, ExportKind::Func));
1336
1337 self.component
1338 .error_context_debug_message(shim.options.into_iter(
1339 *encoding,
1340 self.memory_index,
1341 realloc_index,
1342 )?)
1343 }
1344 ShimKind::TaskReturn {
1345 interface,
1346 func,
1347 result,
1348 encoding,
1349 for_module,
1350 } => {
1351 let mut encoder = if interface.is_none() {
1354 self.root_import_type_encoder(*interface)
1355 } else {
1356 self.root_export_type_encoder(*interface)
1357 };
1358 let result = match result {
1359 Some(ty) => Some(encoder.encode_valtype(resolve, ty)?),
1360 None => None,
1361 };
1362
1363 let exports = self.info.exports_for(*for_module);
1364 let realloc = exports.import_realloc_for(*interface, func);
1365
1366 let instance_index = self.instance_for(*for_module);
1367 let realloc_index = realloc
1368 .map(|r| self.core_alias_export(instance_index, r, ExportKind::Func));
1369 let options =
1370 shim.options
1371 .into_iter(*encoding, self.memory_index, realloc_index)?;
1372 self.component.task_return(result, options)
1373 }
1374 };
1375
1376 exports.push((shim.name.as_str(), ExportKind::Func, core_func_index));
1377 }
1378
1379 let instance_index = self.component.core_instantiate_exports(exports);
1380 self.component.core_instantiate(
1381 self.fixups_module_index.expect("must have fixup module"),
1382 [("", ModuleArg::Instance(instance_index))],
1383 );
1384 Ok(())
1385 }
1386
1387 fn payload_type_index(&mut self, info: &PayloadInfo) -> Result<u32> {
1395 let resolve = &self.info.encoder.metadata.resolve;
1396 let ComponentValType::Type(type_index) = if info.imported || info.interface.is_none() {
1412 self.root_import_type_encoder(None)
1413 } else {
1414 self.root_export_type_encoder(info.interface)
1415 }
1416 .encode_valtype(resolve, &Type::Id(info.ty))?
1417 else {
1418 unreachable!()
1419 };
1420 Ok(type_index)
1421 }
1422
1423 fn declare_exported_resources(&mut self, shims: &Shims<'_>) {
1430 let resolve = &self.info.encoder.metadata.resolve;
1431 let world = &resolve.worlds[self.info.encoder.metadata.world];
1432
1433 let main_module_keys = self.info.encoder.main_module_exports.iter();
1437 let main_module_keys = main_module_keys.map(|key| (CustomModule::Main, key));
1438 let adapter_keys = self.info.encoder.adapters.iter().flat_map(|(name, info)| {
1439 info.required_exports
1440 .iter()
1441 .map(move |key| (CustomModule::Adapter(name), key))
1442 });
1443 for (for_module, key) in main_module_keys.chain(adapter_keys) {
1444 let id = match &world.exports[key] {
1445 WorldItem::Interface { id, .. } => *id,
1446 WorldItem::Type { .. } => unreachable!(),
1447 WorldItem::Function(_) => continue,
1448 };
1449
1450 for ty in resolve.interfaces[id].types.values() {
1451 match resolve.types[*ty].kind {
1452 TypeDefKind::Resource => {}
1453 _ => continue,
1454 }
1455
1456 let exports = self.info.exports_for(for_module);
1459 let dtor = exports.resource_dtor(*ty).map(|name| {
1460 let name = &shims.shims[&ShimKind::ResourceDtor {
1461 module: for_module,
1462 export: name,
1463 }]
1464 .name;
1465 let shim = self.shim_instance_index.unwrap();
1466 self.core_alias_export(shim, name, ExportKind::Func)
1467 });
1468
1469 let resource_idx = self.component.type_resource(ValType::I32, dtor);
1473 let prev = self.export_type_map.insert(*ty, resource_idx);
1474 assert!(prev.is_none());
1475 }
1476 }
1477 }
1478
1479 fn instantiate_main_module(&mut self, shims: &Shims<'_>) -> Result<()> {
1482 assert!(self.instance_index.is_none());
1483
1484 let instance_index = self.instantiate_core_module(shims, CustomModule::Main)?;
1485
1486 if let Some(memory) = self.info.info.exports.memory() {
1487 self.memory_index =
1488 Some(self.core_alias_export(instance_index, memory, ExportKind::Memory));
1489 }
1490
1491 self.instance_index = Some(instance_index);
1492 Ok(())
1493 }
1494
1495 fn instantiate_adapter_module(&mut self, shims: &Shims<'_>, name: &'a str) -> Result<()> {
1498 let instance = self.instantiate_core_module(shims, CustomModule::Adapter(name))?;
1499 self.adapter_instances.insert(name, instance);
1500 Ok(())
1501 }
1502
1503 fn instantiate_core_module(
1510 &mut self,
1511 shims: &Shims,
1512 for_module: CustomModule<'_>,
1513 ) -> Result<u32> {
1514 let module = self.module_for(for_module);
1515
1516 let mut args = Vec::new();
1517 for (core_wasm_name, instance) in self.info.imports_for(for_module).modules() {
1518 match instance {
1519 ImportInstance::Names(names) => {
1525 let mut exports = Vec::new();
1526 for (name, import) in names {
1527 let (kind, index) = self
1528 .materialize_import(&shims, for_module, core_wasm_name, name, import)
1529 .with_context(|| {
1530 format!("failed to satisfy import `{core_wasm_name}::{name}`")
1531 })?;
1532 exports.push((name.as_str(), kind, index));
1533 }
1534 let index = self.component.core_instantiate_exports(exports);
1535 args.push((core_wasm_name.as_str(), ModuleArg::Instance(index)));
1536 }
1537
1538 ImportInstance::Whole(which) => {
1541 let instance = self.instance_for(which.to_custom_module());
1542 args.push((core_wasm_name.as_str(), ModuleArg::Instance(instance)));
1543 }
1544 }
1545 }
1546
1547 Ok(self.component.core_instantiate(module, args))
1549 }
1550
1551 fn materialize_import(
1558 &mut self,
1559 shims: &Shims<'_>,
1560 for_module: CustomModule<'_>,
1561 module: &str,
1562 field: &str,
1563 import: &'a Import,
1564 ) -> Result<(ExportKind, u32)> {
1565 log::trace!("attempting to materialize import of `{module}::{field}` for {for_module:?}");
1566 let resolve = &self.info.encoder.metadata.resolve;
1567 match import {
1568 Import::AdapterExport(_) => {
1571 assert!(self.info.encoder.adapters.contains_key(module));
1572 Ok(self.materialize_shim_import(
1573 shims,
1574 &ShimKind::Adapter {
1575 adapter: module,
1576 func: field,
1577 },
1578 ))
1579 }
1580
1581 Import::MainModuleMemory => {
1584 let index = self
1585 .memory_index
1586 .ok_or_else(|| anyhow!("main module cannot import memory"))?;
1587 Ok((ExportKind::Memory, index))
1588 }
1589
1590 Import::MainModuleExport { name, kind } => {
1592 let instance = self.instance_index.unwrap();
1593 let index = self.core_alias_export(instance, name, *kind);
1594 Ok((*kind, index))
1595 }
1596
1597 Import::Item(item) => {
1601 let instance = self.instance_for(item.which.to_custom_module());
1602 let index = self.core_alias_export(instance, &item.name, item.kind);
1603 Ok((item.kind, index))
1604 }
1605
1606 Import::ExportedResourceDrop(_key, id) => {
1612 let index = self.component.resource_drop(self.export_type_map[id]);
1613 Ok((ExportKind::Func, index))
1614 }
1615 Import::ExportedResourceRep(_key, id) => {
1616 let index = self.component.resource_rep(self.export_type_map[id]);
1617 Ok((ExportKind::Func, index))
1618 }
1619 Import::ExportedResourceNew(_key, id) => {
1620 let index = self.component.resource_new(self.export_type_map[id]);
1621 Ok((ExportKind::Func, index))
1622 }
1623
1624 Import::ImportedResourceDrop(key, iface, id) => {
1629 let ty = &resolve.types[*id];
1630 let name = ty.name.as_ref().unwrap();
1631 self.materialize_wit_import(
1632 shims,
1633 for_module,
1634 iface.map(|_| resolve.name_world_key(key)),
1635 &format!("{name}_drop"),
1636 key,
1637 AbiVariant::GuestImport,
1638 )
1639 }
1640 Import::ExportedTaskReturn(key, interface, func, result) => {
1641 let (options, _sig) = task_return_options_and_type(resolve, *result);
1642 if options.is_empty() {
1643 let mut encoder = if interface.is_none() {
1649 self.root_import_type_encoder(*interface)
1650 } else {
1651 self.root_export_type_encoder(*interface)
1652 };
1653
1654 let result = match result {
1655 Some(ty) => Some(encoder.encode_valtype(resolve, ty)?),
1656 None => None,
1657 };
1658 let index = self.component.task_return(result, []);
1659 Ok((ExportKind::Func, index))
1660 } else {
1661 let metadata = &self.info.encoder.metadata.metadata;
1662 let encoding = metadata.export_encodings.get(resolve, key, func).unwrap();
1663 Ok(self.materialize_shim_import(
1664 shims,
1665 &ShimKind::TaskReturn {
1666 for_module,
1667 interface: *interface,
1668 func,
1669 result: *result,
1670 encoding,
1671 },
1672 ))
1673 }
1674 }
1675 Import::BackpressureSet => {
1676 let index = self.component.backpressure_set();
1677 Ok((ExportKind::Func, index))
1678 }
1679 Import::WaitableSetWait { async_ } => {
1680 Ok(self
1681 .materialize_shim_import(shims, &ShimKind::WaitableSetWait { async_: *async_ }))
1682 }
1683 Import::WaitableSetPoll { async_ } => {
1684 Ok(self
1685 .materialize_shim_import(shims, &ShimKind::WaitableSetPoll { async_: *async_ }))
1686 }
1687 Import::Yield { async_ } => {
1688 let index = self.component.yield_(*async_);
1689 Ok((ExportKind::Func, index))
1690 }
1691 Import::SubtaskDrop => {
1692 let index = self.component.subtask_drop();
1693 Ok((ExportKind::Func, index))
1694 }
1695 Import::StreamNew(info) => {
1696 let ty = self.payload_type_index(info)?;
1697 let index = self.component.stream_new(ty);
1698 Ok((ExportKind::Func, index))
1699 }
1700 Import::StreamRead { info, .. } => Ok(self.materialize_payload_import(
1701 shims,
1702 for_module,
1703 info,
1704 PayloadFuncKind::StreamRead,
1705 )),
1706 Import::StreamWrite { info, .. } => Ok(self.materialize_payload_import(
1707 shims,
1708 for_module,
1709 info,
1710 PayloadFuncKind::StreamWrite,
1711 )),
1712 Import::StreamCancelRead { info, async_ } => {
1713 let ty = self.payload_type_index(info)?;
1714 let index = self.component.stream_cancel_read(ty, *async_);
1715 Ok((ExportKind::Func, index))
1716 }
1717 Import::StreamCancelWrite { info, async_ } => {
1718 let ty = self.payload_type_index(info)?;
1719 let index = self.component.stream_cancel_write(ty, *async_);
1720 Ok((ExportKind::Func, index))
1721 }
1722 Import::StreamCloseReadable(info) => {
1723 let type_index = self.payload_type_index(info)?;
1724 let index = self.component.stream_close_readable(type_index);
1725 Ok((ExportKind::Func, index))
1726 }
1727 Import::StreamCloseWritable(info) => {
1728 let type_index = self.payload_type_index(info)?;
1729 let index = self.component.stream_close_writable(type_index);
1730 Ok((ExportKind::Func, index))
1731 }
1732 Import::FutureNew(info) => {
1733 let ty = self.payload_type_index(info)?;
1734 let index = self.component.future_new(ty);
1735 Ok((ExportKind::Func, index))
1736 }
1737 Import::FutureRead { info, .. } => Ok(self.materialize_payload_import(
1738 shims,
1739 for_module,
1740 info,
1741 PayloadFuncKind::FutureRead,
1742 )),
1743 Import::FutureWrite { info, .. } => Ok(self.materialize_payload_import(
1744 shims,
1745 for_module,
1746 info,
1747 PayloadFuncKind::FutureWrite,
1748 )),
1749 Import::FutureCancelRead { info, async_ } => {
1750 let ty = self.payload_type_index(info)?;
1751 let index = self.component.future_cancel_read(ty, *async_);
1752 Ok((ExportKind::Func, index))
1753 }
1754 Import::FutureCancelWrite { info, async_ } => {
1755 let ty = self.payload_type_index(info)?;
1756 let index = self.component.future_cancel_write(ty, *async_);
1757 Ok((ExportKind::Func, index))
1758 }
1759 Import::FutureCloseReadable(info) => {
1760 let type_index = self.payload_type_index(info)?;
1761 let index = self.component.future_close_readable(type_index);
1762 Ok((ExportKind::Func, index))
1763 }
1764 Import::FutureCloseWritable(info) => {
1765 let type_index = self.payload_type_index(info)?;
1766 let index = self.component.future_close_writable(type_index);
1767 Ok((ExportKind::Func, index))
1768 }
1769 Import::ErrorContextNew { encoding } => Ok(self.materialize_shim_import(
1770 shims,
1771 &ShimKind::ErrorContextNew {
1772 encoding: *encoding,
1773 },
1774 )),
1775 Import::ErrorContextDebugMessage { encoding } => Ok(self.materialize_shim_import(
1776 shims,
1777 &ShimKind::ErrorContextDebugMessage {
1778 for_module,
1779 encoding: *encoding,
1780 },
1781 )),
1782 Import::ErrorContextDrop => {
1783 let index = self.component.error_context_drop();
1784 Ok((ExportKind::Func, index))
1785 }
1786 Import::WorldFunc(key, name, abi) => {
1787 self.materialize_wit_import(shims, for_module, None, name, key, *abi)
1788 }
1789 Import::InterfaceFunc(key, _, name, abi) => self.materialize_wit_import(
1790 shims,
1791 for_module,
1792 Some(resolve.name_world_key(key)),
1793 name,
1794 key,
1795 *abi,
1796 ),
1797
1798 Import::WaitableSetNew => {
1799 let index = self.component.waitable_set_new();
1800 Ok((ExportKind::Func, index))
1801 }
1802 Import::WaitableSetDrop => {
1803 let index = self.component.waitable_set_drop();
1804 Ok((ExportKind::Func, index))
1805 }
1806 Import::WaitableJoin => {
1807 let index = self.component.waitable_join();
1808 Ok((ExportKind::Func, index))
1809 }
1810 }
1811 }
1812
1813 fn materialize_shim_import(&mut self, shims: &Shims<'_>, kind: &ShimKind) -> (ExportKind, u32) {
1816 let index = self.core_alias_export(
1817 self.shim_instance_index
1818 .expect("shim should be instantiated"),
1819 &shims.shims[kind].name,
1820 ExportKind::Func,
1821 );
1822 (ExportKind::Func, index)
1823 }
1824
1825 fn materialize_payload_import(
1828 &mut self,
1829 shims: &Shims<'_>,
1830 for_module: CustomModule<'_>,
1831 info: &PayloadInfo,
1832 kind: PayloadFuncKind,
1833 ) -> (ExportKind, u32) {
1834 self.materialize_shim_import(
1835 shims,
1836 &ShimKind::PayloadFunc {
1837 for_module,
1838 info,
1839 kind,
1840 },
1841 )
1842 }
1843
1844 fn materialize_wit_import(
1847 &mut self,
1848 shims: &Shims<'_>,
1849 for_module: CustomModule<'_>,
1850 interface_key: Option<String>,
1851 name: &String,
1852 key: &WorldKey,
1853 abi: AbiVariant,
1854 ) -> Result<(ExportKind, u32)> {
1855 let resolve = &self.info.encoder.metadata.resolve;
1856 let import = &self.info.import_map[&interface_key];
1857 let (index, _, lowering) = import.lowerings.get_full(&(name.clone(), abi)).unwrap();
1858 let metadata = self.info.module_metadata_for(for_module);
1859
1860 let index = match lowering {
1861 Lowering::Direct => {
1864 let func_index = match &import.interface {
1865 Some(interface) => {
1866 let instance_index = self.imported_instances[interface];
1867 self.component
1868 .alias_export(instance_index, name, ComponentExportKind::Func)
1869 }
1870 None => self.imported_funcs[name],
1871 };
1872 self.component.lower_func(
1873 func_index,
1874 if let AbiVariant::GuestImportAsync = abi {
1875 vec![CanonicalOption::Async]
1876 } else {
1877 Vec::new()
1878 },
1879 )
1880 }
1881
1882 Lowering::Indirect { .. } => {
1886 let encoding = metadata.import_encodings.get(resolve, key, name).unwrap();
1887 return Ok(self.materialize_shim_import(
1888 shims,
1889 &ShimKind::IndirectLowering {
1890 interface: interface_key,
1891 index,
1892 realloc: for_module,
1893 encoding,
1894 },
1895 ));
1896 }
1897
1898 Lowering::ResourceDrop(id) => {
1901 let resource_idx = self.lookup_resource_index(*id);
1902 self.component.resource_drop(resource_idx)
1903 }
1904 };
1905 Ok((ExportKind::Func, index))
1906 }
1907
1908 fn encode_initialize_with_start(&mut self) -> Result<()> {
1927 let initialize = match self.info.info.exports.initialize() {
1928 Some(name) => name,
1929 None => return Ok(()),
1932 };
1933 let initialize_index =
1934 self.core_alias_export(self.instance_index.unwrap(), initialize, ExportKind::Func);
1935 let mut shim = Module::default();
1936 let mut section = TypeSection::new();
1937 section.ty().function([], []);
1938 shim.section(§ion);
1939 let mut section = ImportSection::new();
1940 section.import("", "", EntityType::Function(0));
1941 shim.section(§ion);
1942 shim.section(&StartSection { function_index: 0 });
1943
1944 let shim_module_index = self.component.core_module(&shim);
1949 let shim_args_instance_index =
1950 self.component
1951 .core_instantiate_exports([("", ExportKind::Func, initialize_index)]);
1952 self.component.core_instantiate(
1953 shim_module_index,
1954 [("", ModuleArg::Instance(shim_args_instance_index))],
1955 );
1956 Ok(())
1957 }
1958
1959 fn instance_for(&self, module: CustomModule) -> u32 {
1962 match module {
1963 CustomModule::Main => self.instance_index.expect("instantiated by now"),
1964 CustomModule::Adapter(name) => self.adapter_instances[name],
1965 }
1966 }
1967
1968 fn module_for(&self, module: CustomModule) -> u32 {
1971 match module {
1972 CustomModule::Main => self.module_index.unwrap(),
1973 CustomModule::Adapter(name) => self.adapter_modules[name],
1974 }
1975 }
1976
1977 fn core_alias_export(&mut self, instance: u32, name: &str, kind: ExportKind) -> u32 {
1980 *self
1981 .aliased_core_items
1982 .entry((instance, name.to_string()))
1983 .or_insert_with(|| self.component.core_alias_export(instance, name, kind))
1984 }
1985}
1986
1987#[derive(Default)]
2005struct Shims<'a> {
2006 shims: IndexMap<ShimKind<'a>, Shim<'a>>,
2008}
2009
2010struct Shim<'a> {
2011 options: RequiredOptions,
2014
2015 name: String,
2019
2020 debug_name: String,
2023
2024 kind: ShimKind<'a>,
2026
2027 sig: WasmSignature,
2029}
2030
2031#[derive(Debug, Clone, Hash, Eq, PartialEq)]
2034enum PayloadFuncKind {
2035 FutureWrite,
2036 FutureRead,
2037 StreamWrite,
2038 StreamRead,
2039}
2040
2041#[derive(Debug, Clone, Hash, Eq, PartialEq)]
2042enum ShimKind<'a> {
2043 IndirectLowering {
2047 interface: Option<String>,
2049 index: usize,
2051 realloc: CustomModule<'a>,
2053 encoding: StringEncoding,
2055 },
2056 Adapter {
2059 adapter: &'a str,
2061 func: &'a str,
2063 },
2064 ResourceDtor {
2067 module: CustomModule<'a>,
2069 export: &'a str,
2071 },
2072 PayloadFunc {
2076 for_module: CustomModule<'a>,
2079 info: &'a PayloadInfo,
2084 kind: PayloadFuncKind,
2086 },
2087 WaitableSetWait { async_: bool },
2091 WaitableSetPoll { async_: bool },
2095 TaskReturn {
2097 interface: Option<InterfaceId>,
2100 func: &'a str,
2103 result: Option<Type>,
2105 for_module: CustomModule<'a>,
2107 encoding: StringEncoding,
2109 },
2110 ErrorContextNew {
2114 encoding: StringEncoding,
2116 },
2117 ErrorContextDebugMessage {
2121 for_module: CustomModule<'a>,
2123 encoding: StringEncoding,
2125 },
2126}
2127
2128#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
2138enum CustomModule<'a> {
2139 Main,
2142 Adapter(&'a str),
2145}
2146
2147impl<'a> Shims<'a> {
2148 fn append_indirect(
2153 &mut self,
2154 world: &'a ComponentWorld<'a>,
2155 for_module: CustomModule<'a>,
2156 ) -> Result<()> {
2157 let module_imports = world.imports_for(for_module);
2158 let module_exports = world.exports_for(for_module);
2159 let resolve = &world.encoder.metadata.resolve;
2160
2161 for (module, field, import) in module_imports.imports() {
2162 match import {
2163 Import::ImportedResourceDrop(..)
2166 | Import::MainModuleMemory
2167 | Import::MainModuleExport { .. }
2168 | Import::Item(_)
2169 | Import::ExportedResourceDrop(..)
2170 | Import::ExportedResourceRep(..)
2171 | Import::ExportedResourceNew(..)
2172 | Import::ErrorContextDrop
2173 | Import::BackpressureSet
2174 | Import::Yield { .. }
2175 | Import::SubtaskDrop
2176 | Import::FutureNew(..)
2177 | Import::StreamNew(..)
2178 | Import::FutureCancelRead { .. }
2179 | Import::FutureCancelWrite { .. }
2180 | Import::FutureCloseWritable { .. }
2181 | Import::FutureCloseReadable { .. }
2182 | Import::StreamCancelRead { .. }
2183 | Import::StreamCancelWrite { .. }
2184 | Import::StreamCloseWritable { .. }
2185 | Import::StreamCloseReadable { .. }
2186 | Import::WaitableSetNew
2187 | Import::WaitableSetDrop
2188 | Import::WaitableJoin => {}
2189
2190 Import::ExportedTaskReturn(key, interface, func, ty) => {
2194 let (options, sig) = task_return_options_and_type(resolve, *ty);
2195 if options.is_empty() {
2196 continue;
2197 }
2198 let name = self.shims.len().to_string();
2199 let encoding = world
2200 .module_metadata_for(for_module)
2201 .export_encodings
2202 .get(resolve, key, func)
2203 .ok_or_else(|| {
2204 anyhow::anyhow!(
2205 "missing component metadata for export of \
2206 `{module}::{field}`"
2207 )
2208 })?;
2209 self.push(Shim {
2210 name,
2211 debug_name: format!("task-return-{func}"),
2212 options,
2213 kind: ShimKind::TaskReturn {
2214 interface: *interface,
2215 func,
2216 result: *ty,
2217 for_module,
2218 encoding,
2219 },
2220 sig,
2221 });
2222 }
2223
2224 Import::FutureWrite { async_, info } => {
2225 self.append_indirect_payload_push(
2226 resolve,
2227 for_module,
2228 module,
2229 *async_,
2230 info,
2231 PayloadFuncKind::FutureWrite,
2232 vec![WasmType::I32; 2],
2233 vec![WasmType::I32],
2234 );
2235 }
2236 Import::FutureRead { async_, info } => {
2237 self.append_indirect_payload_push(
2238 resolve,
2239 for_module,
2240 module,
2241 *async_,
2242 info,
2243 PayloadFuncKind::FutureRead,
2244 vec![WasmType::I32; 2],
2245 vec![WasmType::I32],
2246 );
2247 }
2248 Import::StreamWrite { async_, info } => {
2249 self.append_indirect_payload_push(
2250 resolve,
2251 for_module,
2252 module,
2253 *async_,
2254 info,
2255 PayloadFuncKind::StreamWrite,
2256 vec![WasmType::I32; 3],
2257 vec![WasmType::I32],
2258 );
2259 }
2260 Import::StreamRead { async_, info } => {
2261 self.append_indirect_payload_push(
2262 resolve,
2263 for_module,
2264 module,
2265 *async_,
2266 info,
2267 PayloadFuncKind::StreamRead,
2268 vec![WasmType::I32; 3],
2269 vec![WasmType::I32],
2270 );
2271 }
2272
2273 Import::WaitableSetWait { async_ } => {
2274 let name = self.shims.len().to_string();
2275 self.push(Shim {
2276 name,
2277 debug_name: "waitable-set.wait".to_string(),
2278 options: RequiredOptions::empty(),
2279 kind: ShimKind::WaitableSetWait { async_: *async_ },
2280 sig: WasmSignature {
2281 params: vec![WasmType::I32; 2],
2282 results: vec![WasmType::I32],
2283 indirect_params: false,
2284 retptr: false,
2285 },
2286 });
2287 }
2288
2289 Import::WaitableSetPoll { async_ } => {
2290 let name = self.shims.len().to_string();
2291 self.push(Shim {
2292 name,
2293 debug_name: "waitable-set.poll".to_string(),
2294 options: RequiredOptions::empty(),
2295 kind: ShimKind::WaitableSetPoll { async_: *async_ },
2296 sig: WasmSignature {
2297 params: vec![WasmType::I32; 2],
2298 results: vec![WasmType::I32],
2299 indirect_params: false,
2300 retptr: false,
2301 },
2302 });
2303 }
2304
2305 Import::ErrorContextNew { encoding } => {
2306 let name = self.shims.len().to_string();
2307 self.push(Shim {
2308 name,
2309 debug_name: "error-new".to_string(),
2310 options: RequiredOptions::MEMORY | RequiredOptions::STRING_ENCODING,
2311 kind: ShimKind::ErrorContextNew {
2312 encoding: *encoding,
2313 },
2314 sig: WasmSignature {
2315 params: vec![WasmType::I32; 2],
2316 results: vec![WasmType::I32],
2317 indirect_params: false,
2318 retptr: false,
2319 },
2320 });
2321 }
2322
2323 Import::ErrorContextDebugMessage { encoding } => {
2324 let name = self.shims.len().to_string();
2325 self.push(Shim {
2326 name,
2327 debug_name: "error-debug-message".to_string(),
2328 options: RequiredOptions::MEMORY
2329 | RequiredOptions::STRING_ENCODING
2330 | RequiredOptions::REALLOC,
2331 kind: ShimKind::ErrorContextDebugMessage {
2332 for_module,
2333 encoding: *encoding,
2334 },
2335 sig: WasmSignature {
2336 params: vec![WasmType::I32; 2],
2337 results: vec![],
2338 indirect_params: false,
2339 retptr: false,
2340 },
2341 });
2342 }
2343
2344 Import::AdapterExport(ty) => {
2347 let name = self.shims.len().to_string();
2348 log::debug!("shim {name} is adapter `{module}::{field}`");
2349 self.push(Shim {
2350 name,
2351 debug_name: format!("adapt-{module}-{field}"),
2352 options: RequiredOptions::MEMORY,
2356 kind: ShimKind::Adapter {
2357 adapter: module,
2358 func: field,
2359 },
2360 sig: WasmSignature {
2361 params: ty.params().iter().map(to_wasm_type).collect(),
2362 results: ty.results().iter().map(to_wasm_type).collect(),
2363 indirect_params: false,
2364 retptr: false,
2365 },
2366 });
2367
2368 fn to_wasm_type(ty: &wasmparser::ValType) -> WasmType {
2369 match ty {
2370 wasmparser::ValType::I32 => WasmType::I32,
2371 wasmparser::ValType::I64 => WasmType::I64,
2372 wasmparser::ValType::F32 => WasmType::F32,
2373 wasmparser::ValType::F64 => WasmType::F64,
2374 _ => unreachable!(),
2375 }
2376 }
2377 }
2378
2379 Import::InterfaceFunc(key, _, name, abi) => {
2383 self.append_indirect_wit_func(
2384 world,
2385 for_module,
2386 module,
2387 field,
2388 key,
2389 name,
2390 Some(resolve.name_world_key(key)),
2391 *abi,
2392 )?;
2393 }
2394 Import::WorldFunc(key, name, abi) => {
2395 self.append_indirect_wit_func(
2396 world, for_module, module, field, key, name, None, *abi,
2397 )?;
2398 }
2399 }
2400 }
2401
2402 for (export_name, export) in module_exports.iter() {
2408 let id = match export {
2409 Export::ResourceDtor(id) => id,
2410 _ => continue,
2411 };
2412 let resource = resolve.types[*id].name.as_ref().unwrap();
2413 let name = self.shims.len().to_string();
2414 self.push(Shim {
2415 name,
2416 debug_name: format!("dtor-{resource}"),
2417 options: RequiredOptions::empty(),
2418 kind: ShimKind::ResourceDtor {
2419 module: for_module,
2420 export: export_name,
2421 },
2422 sig: WasmSignature {
2423 params: vec![WasmType::I32],
2424 results: Vec::new(),
2425 indirect_params: false,
2426 retptr: false,
2427 },
2428 });
2429 }
2430
2431 Ok(())
2432 }
2433
2434 fn append_indirect_payload_push(
2437 &mut self,
2438 resolve: &Resolve,
2439 for_module: CustomModule<'a>,
2440 module: &str,
2441 async_: bool,
2442 info: &'a PayloadInfo,
2443 kind: PayloadFuncKind,
2444 params: Vec<WasmType>,
2445 results: Vec<WasmType>,
2446 ) {
2447 let debug_name = format!("{module}-{}", info.name);
2448 let name = self.shims.len().to_string();
2449
2450 let payload = info.payload(resolve);
2451 let (wit_param, wit_result) = match kind {
2452 PayloadFuncKind::StreamRead | PayloadFuncKind::FutureRead => (None, payload),
2453 PayloadFuncKind::StreamWrite | PayloadFuncKind::FutureWrite => (payload, None),
2454 };
2455 self.push(Shim {
2456 name,
2457 debug_name,
2458 options: RequiredOptions::MEMORY
2459 | RequiredOptions::for_import(
2460 resolve,
2461 &Function {
2462 name: String::new(),
2463 kind: FunctionKind::Freestanding,
2464 params: match wit_param {
2465 Some(ty) => vec![("a".to_string(), ty)],
2466 None => Vec::new(),
2467 },
2468 result: wit_result,
2469 docs: Default::default(),
2470 stability: Stability::Unknown,
2471 },
2472 if async_ {
2473 AbiVariant::GuestImportAsync
2474 } else {
2475 AbiVariant::GuestImport
2476 },
2477 ),
2478 kind: ShimKind::PayloadFunc {
2479 for_module,
2480 info,
2481 kind,
2482 },
2483 sig: WasmSignature {
2484 params,
2485 results,
2486 indirect_params: false,
2487 retptr: false,
2488 },
2489 });
2490 }
2491
2492 fn append_indirect_wit_func(
2495 &mut self,
2496 world: &'a ComponentWorld<'a>,
2497 for_module: CustomModule<'a>,
2498 module: &str,
2499 field: &str,
2500 key: &WorldKey,
2501 name: &String,
2502 interface_key: Option<String>,
2503 abi: AbiVariant,
2504 ) -> Result<()> {
2505 let resolve = &world.encoder.metadata.resolve;
2506 let metadata = world.module_metadata_for(for_module);
2507 let interface = &world.import_map[&interface_key];
2508 let (index, _, lowering) = interface.lowerings.get_full(&(name.clone(), abi)).unwrap();
2509 let shim_name = self.shims.len().to_string();
2510 match lowering {
2511 Lowering::Direct | Lowering::ResourceDrop(_) => {}
2512
2513 Lowering::Indirect { sig, options } => {
2514 log::debug!(
2515 "shim {shim_name} is import `{module}::{field}` lowering {index} `{name}`",
2516 );
2517 let encoding = metadata
2518 .import_encodings
2519 .get(resolve, key, name)
2520 .ok_or_else(|| {
2521 anyhow::anyhow!(
2522 "missing component metadata for import of \
2523 `{module}::{field}`"
2524 )
2525 })?;
2526 self.push(Shim {
2527 name: shim_name,
2528 debug_name: format!("indirect-{module}-{field}"),
2529 options: *options,
2530 kind: ShimKind::IndirectLowering {
2531 interface: interface_key,
2532 index,
2533 realloc: for_module,
2534 encoding,
2535 },
2536 sig: sig.clone(),
2537 });
2538 }
2539 }
2540
2541 Ok(())
2542 }
2543
2544 fn push(&mut self, shim: Shim<'a>) {
2545 if !self.shims.contains_key(&shim.kind) {
2549 self.shims.insert(shim.kind.clone(), shim);
2550 }
2551 }
2552}
2553
2554fn task_return_options_and_type(
2555 resolve: &Resolve,
2556 ty: Option<Type>,
2557) -> (RequiredOptions, WasmSignature) {
2558 let func_tmp = Function {
2559 name: String::new(),
2560 kind: FunctionKind::Freestanding,
2561 params: match ty {
2562 Some(ty) => vec![("a".to_string(), ty)],
2563 None => Vec::new(),
2564 },
2565 result: None,
2566 docs: Default::default(),
2567 stability: Stability::Unknown,
2568 };
2569 let abi = AbiVariant::GuestImport;
2570 let options = RequiredOptions::for_import(resolve, &func_tmp, abi);
2571 let sig = resolve.wasm_signature(abi, &func_tmp);
2572 (options, sig)
2573}
2574
2575#[derive(Clone, Debug)]
2577pub struct Item {
2578 pub alias: String,
2579 pub kind: ExportKind,
2580 pub which: MainOrAdapter,
2581 pub name: String,
2582}
2583
2584#[derive(Debug, PartialEq, Clone)]
2586pub enum MainOrAdapter {
2587 Main,
2588 Adapter(String),
2589}
2590
2591impl MainOrAdapter {
2592 fn to_custom_module(&self) -> CustomModule<'_> {
2593 match self {
2594 MainOrAdapter::Main => CustomModule::Main,
2595 MainOrAdapter::Adapter(s) => CustomModule::Adapter(s),
2596 }
2597 }
2598}
2599
2600#[derive(Clone)]
2602pub enum Instance {
2603 MainOrAdapter(MainOrAdapter),
2605
2606 Items(Vec<Item>),
2608}
2609
2610#[derive(Clone)]
2613pub struct LibraryInfo {
2614 pub instantiate_after_shims: bool,
2616
2617 pub arguments: Vec<(String, Instance)>,
2619}
2620
2621pub(super) struct Adapter {
2623 wasm: Vec<u8>,
2625
2626 metadata: ModuleMetadata,
2628
2629 required_exports: IndexSet<WorldKey>,
2632
2633 library_info: Option<LibraryInfo>,
2638}
2639
2640#[derive(Default)]
2642pub struct ComponentEncoder {
2643 module: Vec<u8>,
2644 pub(super) metadata: Bindgen,
2645 validate: bool,
2646 pub(super) main_module_exports: IndexSet<WorldKey>,
2647 pub(super) adapters: IndexMap<String, Adapter>,
2648 import_name_map: HashMap<String, String>,
2649 realloc_via_memory_grow: bool,
2650 merge_imports_based_on_semver: Option<bool>,
2651 pub(super) reject_legacy_names: bool,
2652}
2653
2654impl ComponentEncoder {
2655 pub fn module(mut self, module: &[u8]) -> Result<Self> {
2661 let (wasm, metadata) = self.decode(module)?;
2662 let exports = self
2663 .merge_metadata(metadata)
2664 .context("failed merge WIT metadata for module with previous metadata")?;
2665 self.main_module_exports.extend(exports);
2666 self.module = if let Some(producers) = &self.metadata.producers {
2667 producers.add_to_wasm(&wasm)?
2668 } else {
2669 wasm.to_vec()
2670 };
2671 Ok(self)
2672 }
2673
2674 fn decode<'a>(&self, wasm: &'a [u8]) -> Result<(Cow<'a, [u8]>, Bindgen)> {
2675 let (bytes, metadata) = metadata::decode(wasm)?;
2676 match bytes {
2677 Some(wasm) => Ok((Cow::Owned(wasm), metadata)),
2678 None => Ok((Cow::Borrowed(wasm), metadata)),
2679 }
2680 }
2681
2682 fn merge_metadata(&mut self, metadata: Bindgen) -> Result<IndexSet<WorldKey>> {
2683 self.metadata.merge(metadata)
2684 }
2685
2686 pub fn validate(mut self, validate: bool) -> Self {
2688 self.validate = validate;
2689 self
2690 }
2691
2692 pub fn merge_imports_based_on_semver(mut self, merge: bool) -> Self {
2700 self.merge_imports_based_on_semver = Some(merge);
2701 self
2702 }
2703
2704 pub fn reject_legacy_names(mut self, reject: bool) -> Self {
2713 self.reject_legacy_names = reject;
2714 self
2715 }
2716
2717 pub fn adapter(self, name: &str, bytes: &[u8]) -> Result<Self> {
2735 self.library_or_adapter(name, bytes, None)
2736 }
2737
2738 pub fn library(self, name: &str, bytes: &[u8], library_info: LibraryInfo) -> Result<Self> {
2751 self.library_or_adapter(name, bytes, Some(library_info))
2752 }
2753
2754 fn library_or_adapter(
2755 mut self,
2756 name: &str,
2757 bytes: &[u8],
2758 library_info: Option<LibraryInfo>,
2759 ) -> Result<Self> {
2760 let (wasm, mut metadata) = self.decode(bytes)?;
2761 let adapter_metadata = mem::take(&mut metadata.metadata);
2769 let exports = self.merge_metadata(metadata).with_context(|| {
2770 format!("failed to merge WIT packages of adapter `{name}` into main packages")
2771 })?;
2772 if let Some(library_info) = &library_info {
2773 for (_, instance) in &library_info.arguments {
2775 let resolve = |which: &_| match which {
2776 MainOrAdapter::Main => Ok(()),
2777 MainOrAdapter::Adapter(name) => {
2778 if self.adapters.contains_key(name.as_str()) {
2779 Ok(())
2780 } else {
2781 Err(anyhow!("instance refers to unknown adapter `{name}`"))
2782 }
2783 }
2784 };
2785
2786 match instance {
2787 Instance::MainOrAdapter(which) => resolve(which)?,
2788 Instance::Items(items) => {
2789 for item in items {
2790 resolve(&item.which)?;
2791 }
2792 }
2793 }
2794 }
2795 }
2796 self.adapters.insert(
2797 name.to_string(),
2798 Adapter {
2799 wasm: wasm.to_vec(),
2800 metadata: adapter_metadata,
2801 required_exports: exports,
2802 library_info,
2803 },
2804 );
2805 Ok(self)
2806 }
2807
2808 pub fn realloc_via_memory_grow(mut self, value: bool) -> Self {
2813 self.realloc_via_memory_grow = value;
2814 self
2815 }
2816
2817 pub fn import_name_map(mut self, map: HashMap<String, String>) -> Self {
2828 self.import_name_map = map;
2829 self
2830 }
2831
2832 pub fn encode(&mut self) -> Result<Vec<u8>> {
2834 if self.module.is_empty() {
2835 bail!("a module is required when encoding a component");
2836 }
2837
2838 if self.merge_imports_based_on_semver.unwrap_or(true) {
2839 self.metadata
2840 .resolve
2841 .merge_world_imports_based_on_semver(self.metadata.world)?;
2842 }
2843
2844 let world = ComponentWorld::new(self).context("failed to decode world from module")?;
2845 let mut state = EncodingState {
2846 component: ComponentBuilder::default(),
2847 module_index: None,
2848 instance_index: None,
2849 memory_index: None,
2850 shim_instance_index: None,
2851 fixups_module_index: None,
2852 adapter_modules: IndexMap::new(),
2853 adapter_instances: IndexMap::new(),
2854 import_type_map: HashMap::new(),
2855 import_func_type_map: HashMap::new(),
2856 export_type_map: HashMap::new(),
2857 export_func_type_map: HashMap::new(),
2858 imported_instances: Default::default(),
2859 imported_funcs: Default::default(),
2860 exported_instances: Default::default(),
2861 aliased_core_items: Default::default(),
2862 info: &world,
2863 };
2864 state.encode_imports(&self.import_name_map)?;
2865 state.encode_core_modules();
2866 state.encode_core_instantiation()?;
2867 state.encode_exports(CustomModule::Main)?;
2868 for name in self.adapters.keys() {
2869 state.encode_exports(CustomModule::Adapter(name))?;
2870 }
2871 state
2872 .component
2873 .raw_custom_section(&crate::base_producers().raw_custom_section());
2874 let bytes = state.component.finish();
2875
2876 if self.validate {
2877 Validator::new_with_features(WasmFeatures::all())
2878 .validate_all(&bytes)
2879 .context("failed to validate component output")?;
2880 }
2881
2882 Ok(bytes)
2883 }
2884}
2885
2886impl ComponentWorld<'_> {
2887 fn imports_for(&self, module: CustomModule) -> &ImportMap {
2889 match module {
2890 CustomModule::Main => &self.info.imports,
2891 CustomModule::Adapter(name) => &self.adapters[name].info.imports,
2892 }
2893 }
2894
2895 fn exports_for(&self, module: CustomModule) -> &ExportMap {
2897 match module {
2898 CustomModule::Main => &self.info.exports,
2899 CustomModule::Adapter(name) => &self.adapters[name].info.exports,
2900 }
2901 }
2902
2903 fn module_metadata_for(&self, module: CustomModule) -> &ModuleMetadata {
2905 match module {
2906 CustomModule::Main => &self.encoder.metadata.metadata,
2907 CustomModule::Adapter(name) => &self.encoder.adapters[name].metadata,
2908 }
2909 }
2910}
2911
2912#[cfg(all(test, feature = "dummy-module"))]
2913mod test {
2914 use super::*;
2915 use crate::{dummy_module, embed_component_metadata};
2916 use wit_parser::ManglingAndAbi;
2917
2918 #[test]
2919 fn it_renames_imports() {
2920 let mut resolve = Resolve::new();
2921 let pkg = resolve
2922 .push_str(
2923 "test.wit",
2924 r#"
2925package test:wit;
2926
2927interface i {
2928 f: func();
2929}
2930
2931world test {
2932 import i;
2933 import foo: interface {
2934 f: func();
2935 }
2936}
2937"#,
2938 )
2939 .unwrap();
2940 let world = resolve.select_world(pkg, None).unwrap();
2941
2942 let mut module = dummy_module(&resolve, world, ManglingAndAbi::Standard32);
2943
2944 embed_component_metadata(&mut module, &resolve, world, StringEncoding::UTF8).unwrap();
2945
2946 let encoded = ComponentEncoder::default()
2947 .import_name_map(HashMap::from([
2948 (
2949 "foo".to_string(),
2950 "unlocked-dep=<foo:bar/foo@{>=1.0.0 <1.1.0}>".to_string(),
2951 ),
2952 (
2953 "test:wit/i".to_string(),
2954 "locked-dep=<foo:bar/i@1.2.3>".to_string(),
2955 ),
2956 ]))
2957 .module(&module)
2958 .unwrap()
2959 .validate(true)
2960 .encode()
2961 .unwrap();
2962
2963 let wat = wasmprinter::print_bytes(encoded).unwrap();
2964 assert!(wat.contains("unlocked-dep=<foo:bar/foo@{>=1.0.0 <1.1.0}>"));
2965 assert!(wat.contains("locked-dep=<foo:bar/i@1.2.3>"));
2966 }
2967}