1use crate::rust::{to_rust_ident, to_rust_upper_camel_case, RustGenerator, TypeMode};
2use crate::types::{TypeInfo, Types};
3use anyhow::bail;
4use heck::*;
5use indexmap::{IndexMap, IndexSet};
6use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
7use std::fmt::Write as _;
8use std::io::{Read, Write};
9use std::mem;
10use std::process::{Command, Stdio};
11use wit_parser::*;
12
13macro_rules! uwrite {
14 ($dst:expr, $($arg:tt)*) => {
15 write!($dst, $($arg)*).unwrap()
16 };
17}
18
19macro_rules! uwriteln {
20 ($dst:expr, $($arg:tt)*) => {
21 writeln!($dst, $($arg)*).unwrap()
22 };
23}
24
25mod rust;
26mod source;
27mod types;
28use source::Source;
29
30#[derive(Clone)]
31enum InterfaceName {
32 Remapped {
34 name_at_root: String,
41
42 local_path: Vec<String>,
47 },
48
49 Path(Vec<String>),
54}
55
56#[derive(Default)]
57struct Wasmtime {
58 src: Source,
59 opts: Opts,
60 import_interfaces: Vec<(String, InterfaceName)>,
66 import_functions: Vec<ImportFunction>,
67 exports: Exports,
68 types: Types,
69 sizes: SizeAlign,
70 interface_names: HashMap<InterfaceId, InterfaceName>,
71 interface_last_seen_as_import: HashMap<InterfaceId, bool>,
72 trappable_errors: IndexMap<TypeId, String>,
73 used_with_opts: HashSet<String>,
76 used_trappable_imports_opts: HashSet<String>,
78}
79
80struct ImportFunction {
81 func: Function,
82 add_to_linker: String,
83 sig: Option<String>,
84}
85
86#[derive(Default)]
87struct Exports {
88 fields: BTreeMap<String, ExportField>,
89 modules: Vec<(String, InterfaceName)>,
90 funcs: Vec<String>,
91}
92
93struct ExportField {
94 ty: String,
95 ty_pre: String,
96 getter: String,
97 getter_pre: String,
98}
99
100#[derive(Default, Debug, Clone, Copy)]
101pub enum Ownership {
102 #[default]
105 Owning,
106
107 Borrowing {
111 duplicate_if_necessary: bool,
116 },
117}
118
119#[derive(Default, Debug, Clone)]
120pub struct Opts {
121 pub rustfmt: bool,
123
124 pub tracing: bool,
126
127 pub async_: AsyncConfig,
129
130 pub trappable_error_type: Vec<TrappableError>,
133
134 pub ownership: Ownership,
136
137 pub only_interfaces: bool,
139
140 pub trappable_imports: TrappableImports,
142
143 pub with: HashMap<String, String>,
146
147 pub additional_derive_attributes: Vec<String>,
152
153 pub stringify: bool,
156
157 pub skip_mut_forwarding_impls: bool,
161
162 pub require_store_data_send: bool,
168
169 pub wasmtime_crate: Option<String>,
171}
172
173#[derive(Debug, Clone)]
174pub struct TrappableError {
175 pub wit_path: String,
177
178 pub rust_type_name: String,
180}
181
182#[derive(Default, Debug, Clone)]
183pub enum AsyncConfig {
184 #[default]
186 None,
187 All,
189 AllExceptImports(HashSet<String>),
191 OnlyImports(HashSet<String>),
196}
197
198impl AsyncConfig {
199 pub fn is_import_async(&self, f: &str) -> bool {
200 match self {
201 AsyncConfig::None => false,
202 AsyncConfig::All => true,
203 AsyncConfig::AllExceptImports(set) => !set.contains(f),
204 AsyncConfig::OnlyImports(set) => set.contains(f),
205 }
206 }
207
208 pub fn maybe_async(&self) -> bool {
209 match self {
210 AsyncConfig::None => false,
211 AsyncConfig::All | AsyncConfig::AllExceptImports(_) | AsyncConfig::OnlyImports(_) => {
212 true
213 }
214 }
215 }
216}
217
218#[derive(Default, Debug, Clone)]
219pub enum TrappableImports {
220 #[default]
222 None,
223 All,
225 Only(HashSet<String>),
227}
228
229impl TrappableImports {
230 fn can_trap(&self, f: &Function) -> bool {
231 match self {
232 TrappableImports::None => false,
233 TrappableImports::All => true,
234 TrappableImports::Only(set) => set.contains(&f.name),
235 }
236 }
237}
238
239impl Opts {
240 pub fn generate(&self, resolve: &Resolve, world: WorldId) -> anyhow::Result<String> {
241 let mut r = Wasmtime::default();
242 r.sizes.fill(resolve);
243 r.opts = self.clone();
244 r.generate(resolve, world)
245 }
246
247 fn is_store_data_send(&self) -> bool {
248 self.async_.maybe_async() || self.require_store_data_send
249 }
250}
251
252impl Wasmtime {
253 fn name_interface(
254 &mut self,
255 resolve: &Resolve,
256 id: InterfaceId,
257 name: &WorldKey,
258 is_export: bool,
259 ) -> bool {
260 let mut path = Vec::new();
261 if is_export {
262 path.push("exports".to_string());
263 }
264 match name {
265 WorldKey::Name(name) => {
266 path.push(name.to_snake_case());
267 }
268 WorldKey::Interface(_) => {
269 let iface = &resolve.interfaces[id];
270 let pkgname = &resolve.packages[iface.package.unwrap()].name;
271 path.push(pkgname.namespace.to_snake_case());
272 path.push(self.name_package_module(resolve, iface.package.unwrap()));
273 path.push(to_rust_ident(iface.name.as_ref().unwrap()));
274 }
275 }
276 let entry = if let Some(name_at_root) = self.lookup_replacement(resolve, name, None) {
277 InterfaceName::Remapped {
278 name_at_root,
279 local_path: path,
280 }
281 } else {
282 InterfaceName::Path(path)
283 };
284
285 let remapped = matches!(entry, InterfaceName::Remapped { .. });
286 self.interface_names.insert(id, entry);
287 remapped
288 }
289
290 fn name_package_module(&self, resolve: &Resolve, id: PackageId) -> String {
295 let pkg = &resolve.packages[id];
296 let versions_with_same_name = resolve
297 .packages
298 .iter()
299 .filter_map(|(_, p)| {
300 if p.name.namespace == pkg.name.namespace && p.name.name == pkg.name.name {
301 Some(&p.name.version)
302 } else {
303 None
304 }
305 })
306 .collect::<Vec<_>>();
307 let base = pkg.name.name.to_snake_case();
308 if versions_with_same_name.len() == 1 {
309 return base;
310 }
311
312 let version = match &pkg.name.version {
313 Some(version) => version,
314 None => return base,
318 };
319
320 let version = version
327 .to_string()
328 .replace('.', "_")
329 .replace('-', "_")
330 .replace('+', "_")
331 .to_snake_case();
332 format!("{base}{version}")
333 }
334
335 fn generate(&mut self, resolve: &Resolve, id: WorldId) -> anyhow::Result<String> {
336 self.types.analyze(resolve, id);
337
338 'outer: for (i, te) in self.opts.trappable_error_type.iter().enumerate() {
347 let error_name = format!("_TrappableError{i}");
348 for (id, iface) in resolve.interfaces.iter() {
349 for (key, projection) in lookup_keys(
350 resolve,
351 &WorldKey::Interface(id),
352 LookupItem::InterfaceNoPop,
353 ) {
354 assert!(projection.is_empty());
355
356 let suffix = match te.wit_path.strip_prefix(&key) {
361 Some(s) => s,
362 None => continue,
363 };
364 let suffix = match suffix.strip_prefix('/') {
365 Some(s) => s,
366 None => continue,
367 };
368 if let Some(id) = iface.types.get(suffix) {
369 uwriteln!(self.src, "type {error_name} = {};", te.rust_type_name);
370 let prev = self.trappable_errors.insert(*id, error_name);
371 assert!(prev.is_none());
372 continue 'outer;
373 }
374 }
375 }
376
377 bail!(
378 "failed to locate a WIT error type corresponding to the \
379 `trappable_error_type` name `{}` provided",
380 te.wit_path
381 )
382 }
383
384 let mut with = self.opts.with.iter_mut().collect::<Vec<_>>();
389 with.sort();
390 for (i, (_k, v)) in with.into_iter().enumerate() {
391 let name = format!("__with_name{i}");
392 uwriteln!(self.src, "#[doc(hidden)]\npub use {v} as {name};");
393 *v = name;
394 }
395
396 let world = &resolve.worlds[id];
397 for (name, import) in world.imports.iter() {
398 if !self.opts.only_interfaces || matches!(import, WorldItem::Interface { .. }) {
399 self.import(resolve, id, name, import);
400 }
401 }
402
403 for (name, export) in world.exports.iter() {
404 if !self.opts.only_interfaces || matches!(export, WorldItem::Interface { .. }) {
405 self.export(resolve, name, export);
406 }
407 }
408 self.finish(resolve, id)
409 }
410
411 fn import(&mut self, resolve: &Resolve, world: WorldId, name: &WorldKey, item: &WorldItem) {
412 let mut gen = InterfaceGenerator::new(self, resolve);
413 match item {
414 WorldItem::Function(func) => {
415 let sig = if let FunctionKind::Freestanding = func.kind {
419 gen.generate_function_trait_sig(func);
420 Some(mem::take(&mut gen.src).into())
421 } else {
422 None
423 };
424 gen.generate_add_function_to_linker(TypeOwner::World(world), func, "linker");
425 let add_to_linker = gen.src.into();
426 self.import_functions.push(ImportFunction {
427 func: func.clone(),
428 sig,
429 add_to_linker,
430 });
431 }
432 WorldItem::Interface { id, .. } => {
433 gen.gen.interface_last_seen_as_import.insert(*id, true);
434 gen.current_interface = Some((*id, name, false));
435 let snake = match name {
436 WorldKey::Name(s) => s.to_snake_case(),
437 WorldKey::Interface(id) => resolve.interfaces[*id]
438 .name
439 .as_ref()
440 .unwrap()
441 .to_snake_case(),
442 };
443 let module = if gen.gen.name_interface(resolve, *id, name, false) {
444 let name_at_root = match &gen.gen.interface_names[id] {
452 InterfaceName::Remapped { name_at_root, .. } => name_at_root,
453 InterfaceName::Path(_) => unreachable!(),
454 };
455 let path_to_root = gen.path_to_root();
456 format!(
457 "
458 pub mod {snake} {{
459 #[allow(unused_imports)]
460 pub use {path_to_root}{name_at_root}::*;
461 }}
462 "
463 )
464 } else {
465 gen.types(*id);
468 let key_name = resolve.name_world_key(name);
469 gen.generate_add_to_linker(*id, &key_name);
470
471 let module = &gen.src[..];
472 let wt = gen.gen.wasmtime_path();
473
474 format!(
475 "
476 #[allow(clippy::all)]
477 pub mod {snake} {{
478 #[allow(unused_imports)]
479 use {wt}::component::__internal::anyhow;
480
481 {module}
482 }}
483 "
484 )
485 };
486 self.import_interfaces
487 .push((module, self.interface_names[id].clone()));
488 }
489 WorldItem::Type(ty) => {
490 let name = match name {
491 WorldKey::Name(name) => name,
492 WorldKey::Interface(_) => unreachable!(),
493 };
494 gen.define_type(name, *ty);
495 let body = mem::take(&mut gen.src);
496 self.src.push_str(&body);
497 }
498 };
499 }
500
501 fn export(&mut self, resolve: &Resolve, name: &WorldKey, item: &WorldItem) {
502 let wt = self.wasmtime_path();
503 let mut gen = InterfaceGenerator::new(self, resolve);
504 let field;
505 let ty;
506 let ty_pre;
507 let getter;
508 let getter_pre;
509 match item {
510 WorldItem::Function(func) => {
511 gen.define_rust_guest_export(resolve, None, func);
512 let body = mem::take(&mut gen.src).into();
513 getter = gen.extract_typed_function(func).1;
514 assert!(gen.src.is_empty());
515 self.exports.funcs.push(body);
516 ty_pre = format!("{wt}::component::ComponentExportIndex");
517 field = func_field_name(resolve, func);
518 ty = format!("{wt}::component::Func");
519 getter_pre = format!(
520 "_component.export_index(None, \"{}\")
521 .ok_or_else(|| anyhow::anyhow!(\"no function export `{0}` found\"))?.1",
522 func.name
523 );
524 }
525 WorldItem::Type(_) => unreachable!(),
526 WorldItem::Interface { id, .. } => {
527 gen.gen.interface_last_seen_as_import.insert(*id, false);
528 gen.gen.name_interface(resolve, *id, name, true);
529 gen.current_interface = Some((*id, name, true));
530 gen.types(*id);
531 let struct_name = "Guest";
532 let iface = &resolve.interfaces[*id];
533 let iface_name = match name {
534 WorldKey::Name(name) => name,
535 WorldKey::Interface(_) => iface.name.as_ref().unwrap(),
536 };
537 uwriteln!(gen.src, "pub struct {struct_name} {{");
538 for (_, func) in iface.functions.iter() {
539 uwriteln!(
540 gen.src,
541 "{}: {wt}::component::Func,",
542 func_field_name(resolve, func)
543 );
544 }
545 uwriteln!(gen.src, "}}");
546
547 uwriteln!(gen.src, "#[derive(Clone)]");
548 uwriteln!(gen.src, "pub struct {struct_name}Pre {{");
549 for (_, func) in iface.functions.iter() {
550 uwriteln!(
551 gen.src,
552 "{}: {wt}::component::ComponentExportIndex,",
553 func_field_name(resolve, func)
554 );
555 }
556 uwriteln!(gen.src, "}}");
557
558 uwriteln!(gen.src, "impl {struct_name}Pre {{");
559 let instance_name = resolve.name_world_key(name);
560 uwrite!(
561 gen.src,
562 "
563pub fn new(
564 component: &{wt}::component::Component,
565) -> {wt}::Result<{struct_name}Pre> {{
566 let _component = component;
567 let (_, instance) = component.export_index(None, \"{instance_name}\")
568 .ok_or_else(|| anyhow::anyhow!(\"no exported instance named `{instance_name}`\"))?;
569 let _lookup = |name: &str| {{
570 _component.export_index(Some(&instance), name)
571 .map(|p| p.1)
572 .ok_or_else(|| {{
573 anyhow::anyhow!(
574 \"instance export `{instance_name}` does \\
575 not have export `{{name}}`\"
576 )
577 }})
578 }};
579 "
580 );
581 let mut fields = Vec::new();
582 for (_, func) in iface.functions.iter() {
583 let name = func_field_name(resolve, func);
584 uwriteln!(gen.src, "let {name} = _lookup(\"{}\")?;", func.name);
585 fields.push(name);
586 }
587 uwriteln!(gen.src, "Ok({struct_name}Pre {{");
588 for name in fields {
589 uwriteln!(gen.src, "{name},");
590 }
591 uwriteln!(gen.src, "}})");
592 uwriteln!(gen.src, "}}");
593
594 uwrite!(
595 gen.src,
596 "
597 pub fn load(
598 &self,
599 mut store: impl {wt}::AsContextMut,
600 instance: &{wt}::component::Instance,
601 ) -> {wt}::Result<{struct_name}> {{
602 let mut store = store.as_context_mut();
603 let _ = &mut store;
604 let _instance = instance;
605 "
606 );
607 let mut fields = Vec::new();
608 for (_, func) in iface.functions.iter() {
609 let (name, getter) = gen.extract_typed_function(func);
610 uwriteln!(gen.src, "let {name} = {getter};");
611 fields.push(name);
612 }
613 uwriteln!(gen.src, "Ok({struct_name} {{");
614 for name in fields {
615 uwriteln!(gen.src, "{name},");
616 }
617 uwriteln!(gen.src, "}})");
618 uwriteln!(gen.src, "}}"); uwriteln!(gen.src, "}}"); uwriteln!(gen.src, "impl {struct_name} {{");
622 let mut resource_methods = IndexMap::new();
623
624 for (_, func) in iface.functions.iter() {
625 match func.kind {
626 FunctionKind::Freestanding => {
627 gen.define_rust_guest_export(resolve, Some(name), func);
628 }
629 FunctionKind::Method(id)
630 | FunctionKind::Constructor(id)
631 | FunctionKind::Static(id) => {
632 resource_methods.entry(id).or_insert(Vec::new()).push(func);
633 }
634 }
635 }
636
637 for (id, _) in resource_methods.iter() {
638 let name = resolve.types[*id].name.as_ref().unwrap();
639 let snake = name.to_snake_case();
640 let camel = name.to_upper_camel_case();
641 uwriteln!(
642 gen.src,
643 "pub fn {snake}(&self) -> Guest{camel}<'_> {{
644 Guest{camel} {{ funcs: self }}
645 }}"
646 );
647 }
648
649 uwriteln!(gen.src, "}}");
650
651 for (id, methods) in resource_methods {
652 let resource_name = resolve.types[id].name.as_ref().unwrap();
653 let camel = resource_name.to_upper_camel_case();
654 uwriteln!(gen.src, "impl Guest{camel}<'_> {{");
655 for method in methods {
656 gen.define_rust_guest_export(resolve, Some(name), method);
657 }
658 uwriteln!(gen.src, "}}");
659 }
660
661 let module = &gen.src[..];
662 let snake = to_rust_ident(iface_name);
663
664 let module = format!(
665 "
666 #[allow(clippy::all)]
667 pub mod {snake} {{
668 #[allow(unused_imports)]
669 use {wt}::component::__internal::anyhow;
670
671 {module}
672 }}
673 "
674 );
675 let pkgname = match name {
676 WorldKey::Name(_) => None,
677 WorldKey::Interface(_) => {
678 Some(resolve.packages[iface.package.unwrap()].name.clone())
679 }
680 };
681 self.exports
682 .modules
683 .push((module, self.interface_names[id].clone()));
684
685 let (path, method_name) = match pkgname {
686 Some(pkgname) => (
687 format!(
688 "exports::{}::{}::{snake}::{struct_name}",
689 pkgname.namespace.to_snake_case(),
690 self.name_package_module(resolve, iface.package.unwrap()),
691 ),
692 format!(
693 "{}_{}_{snake}",
694 pkgname.namespace.to_snake_case(),
695 self.name_package_module(resolve, iface.package.unwrap())
696 ),
697 ),
698 None => (format!("exports::{snake}::{struct_name}"), snake.clone()),
699 };
700 field = format!("interface{}", self.exports.fields.len());
701 getter = format!("self.{field}.load(&mut store, &_instance)?");
702 self.exports.funcs.push(format!(
703 "
704 pub fn {method_name}(&self) -> &{path} {{
705 &self.{field}
706 }}
707 ",
708 ));
709 ty_pre = format!("{path}Pre");
710 ty = path;
711 getter_pre = format!("{ty_pre}::new(_component)?");
712 }
713 }
714 let prev = self.exports.fields.insert(
715 field,
716 ExportField {
717 ty,
718 ty_pre,
719 getter,
720 getter_pre,
721 },
722 );
723 assert!(prev.is_none());
724 }
725
726 fn build_world_struct(&mut self, resolve: &Resolve, world: WorldId) {
727 let wt = self.wasmtime_path();
728 let world_name = &resolve.worlds[world].name;
729 let camel = to_rust_upper_camel_case(&world_name);
730 let (async_, async__, where_clause, await_) = if self.opts.async_.maybe_async() {
731 ("async", "_async", "where _T: Send", ".await")
732 } else {
733 ("", "", "", "")
734 };
735 uwriteln!(
736 self.src,
737 "
738 /// Auto-generated bindings for a pre-instantiated version of a
739 /// component which implements the world `{world_name}`.
740 ///
741 /// This structure is created through [`{camel}Pre::new`] which
742 /// takes a [`InstancePre`]({wt}::component::InstancePre) that
743 /// has been created through a [`Linker`]({wt}::component::Linker).
744 pub struct {camel}Pre<T> {{"
745 );
746 uwriteln!(self.src, "instance_pre: {wt}::component::InstancePre<T>,");
747 for (name, field) in self.exports.fields.iter() {
748 uwriteln!(self.src, "{name}: {},", field.ty_pre);
749 }
750 self.src.push_str("}\n");
751
752 uwriteln!(self.src, "impl<T> Clone for {camel}Pre<T> {{");
753 uwriteln!(self.src, "fn clone(&self) -> Self {{");
754 uwriteln!(self.src, "Self {{ instance_pre: self.instance_pre.clone(),");
755 for (name, _field) in self.exports.fields.iter() {
756 uwriteln!(self.src, "{name}: self.{name}.clone(),");
757 }
758 uwriteln!(self.src, "}}"); uwriteln!(self.src, "}}"); uwriteln!(self.src, "}}"); uwriteln!(
763 self.src,
764 "
765 /// Auto-generated bindings for an instance a component which
766 /// implements the world `{world_name}`.
767 ///
768 /// This structure is created through either
769 /// [`{camel}::instantiate{async__}`] or by first creating
770 /// a [`{camel}Pre`] followed by using
771 /// [`{camel}Pre::instantiate{async__}`].
772 pub struct {camel} {{"
773 );
774 for (name, field) in self.exports.fields.iter() {
775 uwriteln!(self.src, "{name}: {},", field.ty);
776 }
777 self.src.push_str("}\n");
778
779 self.world_imports_trait(resolve, world);
780
781 uwriteln!(self.src, "const _: () = {{");
782 uwriteln!(
783 self.src,
784 "
785 #[allow(unused_imports)]
786 use {wt}::component::__internal::anyhow;
787 "
788 );
789
790 uwriteln!(
791 self.src,
792 "impl<_T> {camel}Pre<_T> {{
793 /// Creates a new copy of `{camel}Pre` bindings which can then
794 /// be used to instantiate into a particular store.
795 ///
796 /// This method may fail if the component behind `instance_pre`
797 /// does not have the required exports.
798 pub fn new(
799 instance_pre: {wt}::component::InstancePre<_T>,
800 ) -> {wt}::Result<Self> {{
801 let _component = instance_pre.component();
802 ",
803 );
804 for (name, field) in self.exports.fields.iter() {
805 uwriteln!(self.src, "let {name} = {};", field.getter_pre);
806 }
807 uwriteln!(self.src, "Ok({camel}Pre {{");
808 uwriteln!(self.src, "instance_pre,");
809 for (name, _) in self.exports.fields.iter() {
810 uwriteln!(self.src, "{name},");
811 }
812 uwriteln!(self.src, "}})");
813 uwriteln!(self.src, "}}"); uwriteln!(
816 self.src,
817 "
818 /// Instantiates a new instance of [`{camel}`] within the
819 /// `store` provided.
820 ///
821 /// This function will use `self` as the pre-instantiated
822 /// instance to perform instantiation. Afterwards the preloaded
823 /// indices in `self` are used to lookup all exports on the
824 /// resulting instance.
825 pub {async_} fn instantiate{async__}(
826 &self,
827 mut store: impl {wt}::AsContextMut<Data = _T>,
828 ) -> {wt}::Result<{camel}>
829 {where_clause}
830 {{
831 let mut store = store.as_context_mut();
832 let _instance = self.instance_pre.instantiate{async__}(&mut store){await_}?;
833 ",
834 );
835 for (name, field) in self.exports.fields.iter() {
836 uwriteln!(self.src, "let {name} = {};", field.getter);
837 }
838 uwriteln!(self.src, "Ok({camel} {{");
839 for (name, _) in self.exports.fields.iter() {
840 uwriteln!(self.src, "{name},");
841 }
842 uwriteln!(self.src, "}})");
843 uwriteln!(self.src, "}}"); uwriteln!(
845 self.src,
846 "
847 pub fn engine(&self) -> &{wt}::Engine {{
848 self.instance_pre.engine()
849 }}
850
851 pub fn instance_pre(&self) -> &{wt}::component::InstancePre<_T> {{
852 &self.instance_pre
853 }}
854 ",
855 );
856
857 uwriteln!(self.src, "}}");
858
859 uwriteln!(
860 self.src,
861 "impl {camel} {{
862 /// Convenience wrapper around [`{camel}Pre::new`] and
863 /// [`{camel}Pre::instantiate{async__}`].
864 pub {async_} fn instantiate{async__}<_T>(
865 mut store: impl {wt}::AsContextMut<Data = _T>,
866 component: &{wt}::component::Component,
867 linker: &{wt}::component::Linker<_T>,
868 ) -> {wt}::Result<{camel}>
869 {where_clause}
870 {{
871 let pre = linker.instantiate_pre(component)?;
872 {camel}Pre::new(pre)?.instantiate{async__}(store){await_}
873 }}
874 ",
875 );
876 self.world_add_to_linker(resolve, world);
877
878 for func in self.exports.funcs.iter() {
879 self.src.push_str(func);
880 }
881
882 uwriteln!(self.src, "}}"); uwriteln!(self.src, "}};"); }
886
887 fn finish(&mut self, resolve: &Resolve, world: WorldId) -> anyhow::Result<String> {
888 let remapping_keys = self.opts.with.keys().cloned().collect::<HashSet<String>>();
889
890 let mut unused_keys = remapping_keys
891 .difference(&self.used_with_opts)
892 .map(|s| s.as_str())
893 .collect::<Vec<&str>>();
894
895 unused_keys.sort();
896
897 if !unused_keys.is_empty() {
898 anyhow::bail!("interfaces were specified in the `with` config option but are not referenced in the target world: {unused_keys:?}");
899 }
900
901 if let TrappableImports::Only(only) = &self.opts.trappable_imports {
902 let mut unused_imports = Vec::from_iter(
903 only.difference(&self.used_trappable_imports_opts)
904 .map(|s| s.as_str()),
905 );
906
907 if !unused_imports.is_empty() {
908 unused_imports.sort();
909 anyhow::bail!("names specified in the `trappable_imports` config option but are not referenced in the target world: {unused_imports:?}");
910 }
911 }
912
913 if !self.opts.only_interfaces {
914 self.build_world_struct(resolve, world)
915 }
916
917 let imports = mem::take(&mut self.import_interfaces);
918 self.emit_modules(imports);
919
920 let exports = mem::take(&mut self.exports.modules);
921 self.emit_modules(exports);
922
923 let mut src = mem::take(&mut self.src);
924 if self.opts.rustfmt {
925 let mut child = Command::new("rustfmt")
926 .arg("--edition=2018")
927 .stdin(Stdio::piped())
928 .stdout(Stdio::piped())
929 .spawn()
930 .expect("failed to spawn `rustfmt`");
931 child
932 .stdin
933 .take()
934 .unwrap()
935 .write_all(src.as_bytes())
936 .unwrap();
937 src.as_mut_string().truncate(0);
938 child
939 .stdout
940 .take()
941 .unwrap()
942 .read_to_string(src.as_mut_string())
943 .unwrap();
944 let status = child.wait().unwrap();
945 assert!(status.success());
946 }
947
948 Ok(src.into())
949 }
950
951 fn emit_modules(&mut self, modules: Vec<(String, InterfaceName)>) {
952 #[derive(Default)]
953 struct Module {
954 submodules: BTreeMap<String, Module>,
955 contents: Vec<String>,
956 }
957 let mut map = Module::default();
958 for (module, name) in modules {
959 let path = match name {
960 InterfaceName::Remapped { local_path, .. } => local_path,
961 InterfaceName::Path(path) => path,
962 };
963 let mut cur = &mut map;
964 for name in path[..path.len() - 1].iter() {
965 cur = cur
966 .submodules
967 .entry(name.clone())
968 .or_insert(Module::default());
969 }
970 cur.contents.push(module);
971 }
972
973 emit(&mut self.src, map);
974
975 fn emit(me: &mut Source, module: Module) {
976 for (name, submodule) in module.submodules {
977 uwriteln!(me, "pub mod {name} {{");
978 emit(me, submodule);
979 uwriteln!(me, "}}");
980 }
981 for submodule in module.contents {
982 uwriteln!(me, "{submodule}");
983 }
984 }
985 }
986
987 fn lookup_replacement(
990 &mut self,
991 resolve: &Resolve,
992 key: &WorldKey,
993 item: Option<&str>,
994 ) -> Option<String> {
995 let item = match item {
996 Some(item) => LookupItem::Name(item),
997 None => LookupItem::None,
998 };
999
1000 for (lookup, mut projection) in lookup_keys(resolve, key, item) {
1001 if let Some(renamed) = self.opts.with.get(&lookup) {
1002 projection.push(renamed.clone());
1003 projection.reverse();
1004 self.used_with_opts.insert(lookup);
1005 return Some(projection.join("::"));
1006 }
1007 }
1008
1009 None
1010 }
1011
1012 fn wasmtime_path(&self) -> String {
1013 self.opts
1014 .wasmtime_crate
1015 .clone()
1016 .unwrap_or("wasmtime".to_string())
1017 }
1018}
1019
1020enum LookupItem<'a> {
1021 None,
1022 Name(&'a str),
1023 InterfaceNoPop,
1024}
1025
1026fn lookup_keys(
1027 resolve: &Resolve,
1028 key: &WorldKey,
1029 item: LookupItem<'_>,
1030) -> Vec<(String, Vec<String>)> {
1031 struct Name<'a> {
1032 prefix: Prefix,
1033 item: Option<&'a str>,
1034 }
1035
1036 #[derive(Copy, Clone)]
1037 enum Prefix {
1038 Namespace(PackageId),
1039 UnversionedPackage(PackageId),
1040 VersionedPackage(PackageId),
1041 UnversionedInterface(InterfaceId),
1042 VersionedInterface(InterfaceId),
1043 }
1044
1045 let prefix = match key {
1046 WorldKey::Interface(id) => Prefix::VersionedInterface(*id),
1047
1048 WorldKey::Name(key) => {
1051 let to_lookup = match item {
1052 LookupItem::Name(item) => format!("{key}/{item}"),
1053 LookupItem::None | LookupItem::InterfaceNoPop => key.to_string(),
1054 };
1055 return vec![(to_lookup, Vec::new())];
1056 }
1057 };
1058
1059 let (interface_required, item) = match item {
1069 LookupItem::None => (false, None),
1070 LookupItem::Name(s) => (false, Some(s)),
1071 LookupItem::InterfaceNoPop => (true, None),
1072 };
1073 let mut name = Name { prefix, item };
1074 let mut projection = Vec::new();
1075 let mut ret = Vec::new();
1076 loop {
1077 let lookup = name.lookup_key(resolve);
1078 ret.push((lookup, projection.clone()));
1079 if !name.pop(resolve, &mut projection) {
1080 break;
1081 }
1082 if interface_required {
1083 match name.prefix {
1084 Prefix::VersionedInterface(_) | Prefix::UnversionedInterface(_) => {}
1085 _ => break,
1086 }
1087 }
1088 }
1089
1090 return ret;
1091
1092 impl<'a> Name<'a> {
1093 fn lookup_key(&self, resolve: &Resolve) -> String {
1094 let mut s = self.prefix.lookup_key(resolve);
1095 if let Some(item) = self.item {
1096 s.push_str("/");
1097 s.push_str(item);
1098 }
1099 s
1100 }
1101
1102 fn pop(&mut self, resolve: &'a Resolve, projection: &mut Vec<String>) -> bool {
1103 match (self.item, self.prefix) {
1104 (Some(_), Prefix::VersionedInterface(id)) => {
1107 self.prefix = Prefix::UnversionedInterface(id);
1108 true
1109 }
1110 (Some(item), Prefix::UnversionedInterface(id)) => {
1114 self.prefix = Prefix::VersionedInterface(id);
1115 self.item = None;
1116 projection.push(item.to_upper_camel_case());
1117 true
1118 }
1119 (Some(_), _) => unreachable!(),
1120 (None, _) => self.prefix.pop(resolve, projection),
1121 }
1122 }
1123 }
1124
1125 impl Prefix {
1126 fn lookup_key(&self, resolve: &Resolve) -> String {
1127 match *self {
1128 Prefix::Namespace(id) => resolve.packages[id].name.namespace.clone(),
1129 Prefix::UnversionedPackage(id) => {
1130 let mut name = resolve.packages[id].name.clone();
1131 name.version = None;
1132 name.to_string()
1133 }
1134 Prefix::VersionedPackage(id) => resolve.packages[id].name.to_string(),
1135 Prefix::UnversionedInterface(id) => {
1136 let id = resolve.id_of(id).unwrap();
1137 match id.find('@') {
1138 Some(i) => id[..i].to_string(),
1139 None => id,
1140 }
1141 }
1142 Prefix::VersionedInterface(id) => resolve.id_of(id).unwrap(),
1143 }
1144 }
1145
1146 fn pop(&mut self, resolve: &Resolve, projection: &mut Vec<String>) -> bool {
1147 *self = match *self {
1148 Prefix::VersionedInterface(id) => Prefix::UnversionedInterface(id),
1150 Prefix::UnversionedInterface(id) => {
1152 let iface = &resolve.interfaces[id];
1153 let name = iface.name.as_ref().unwrap();
1154 projection.push(to_rust_ident(name));
1155 Prefix::VersionedPackage(iface.package.unwrap())
1156 }
1157 Prefix::VersionedPackage(id) => Prefix::UnversionedPackage(id),
1159 Prefix::UnversionedPackage(id) => {
1161 let name = &resolve.packages[id].name;
1162 projection.push(to_rust_ident(&name.name));
1163 Prefix::Namespace(id)
1164 }
1165 Prefix::Namespace(_) => return false,
1167 };
1168 true
1169 }
1170 }
1171}
1172
1173impl Wasmtime {
1174 fn has_world_imports_trait(&self, resolve: &Resolve, world: WorldId) -> bool {
1175 !self.import_functions.is_empty() || get_world_resources(resolve, world).count() > 0
1176 }
1177
1178 fn world_imports_trait(&mut self, resolve: &Resolve, world: WorldId) {
1179 if !self.has_world_imports_trait(resolve, world) {
1180 return;
1181 }
1182
1183 let wt = self.wasmtime_path();
1184 let world_camel = to_rust_upper_camel_case(&resolve.worlds[world].name);
1185 if self.opts.async_.maybe_async() {
1186 uwriteln!(self.src, "#[{wt}::component::__internal::async_trait]")
1187 }
1188 uwrite!(self.src, "pub trait {world_camel}Imports");
1189 let mut supertraits = vec![];
1190 if self.opts.async_.maybe_async() {
1191 supertraits.push("Send".to_string());
1192 }
1193 for resource in get_world_resources(resolve, world) {
1194 supertraits.push(format!("Host{}", resource.to_upper_camel_case()));
1195 }
1196 if !supertraits.is_empty() {
1197 uwrite!(self.src, ": {}", supertraits.join(" + "));
1198 }
1199 uwriteln!(self.src, " {{");
1200 for f in self.import_functions.iter() {
1201 if let Some(sig) = &f.sig {
1202 self.src.push_str(sig);
1203 self.src.push_str(";\n");
1204 }
1205 }
1206 uwriteln!(self.src, "}}");
1207
1208 uwriteln!(
1209 self.src,
1210 "
1211 pub trait {world_camel}ImportsGetHost<T>:
1212 Fn(T) -> <Self as {world_camel}ImportsGetHost<T>>::Host
1213 + Send
1214 + Sync
1215 + Copy
1216 + 'static
1217 {{
1218 type Host: {world_camel}Imports;
1219 }}
1220
1221 impl<F, T, O> {world_camel}ImportsGetHost<T> for F
1222 where
1223 F: Fn(T) -> O + Send + Sync + Copy + 'static,
1224 O: {world_camel}Imports
1225 {{
1226 type Host = O;
1227 }}
1228 "
1229 );
1230
1231 let (async_trait, maybe_send) = if self.opts.async_.maybe_async() {
1233 (
1234 format!("#[{wt}::component::__internal::async_trait]\n"),
1235 "+ Send",
1236 )
1237 } else {
1238 (String::new(), "")
1239 };
1240 if !self.opts.skip_mut_forwarding_impls {
1241 uwriteln!(
1242 self.src,
1243 "{async_trait}impl<_T: {world_camel}Imports + ?Sized {maybe_send}> {world_camel}Imports for &mut _T {{"
1244 );
1245 for f in self.import_functions.iter() {
1247 if let Some(sig) = &f.sig {
1248 self.src.push_str(sig);
1249 uwrite!(
1250 self.src,
1251 "{{ {world_camel}Imports::{}(*self,",
1252 rust_function_name(&f.func)
1253 );
1254 for (name, _) in f.func.params.iter() {
1255 uwrite!(self.src, "{},", to_rust_ident(name));
1256 }
1257 uwrite!(self.src, ")");
1258 if self.opts.async_.is_import_async(&f.func.name) {
1259 uwrite!(self.src, ".await");
1260 }
1261 uwriteln!(self.src, "}}");
1262 }
1263 }
1264 uwriteln!(self.src, "}}");
1265 }
1266 }
1267
1268 fn import_interface_paths(&self) -> Vec<String> {
1269 self.import_interfaces
1270 .iter()
1271 .map(|(_, name)| match name {
1272 InterfaceName::Path(path) => path.join("::"),
1273 InterfaceName::Remapped { name_at_root, .. } => name_at_root.clone(),
1274 })
1275 .collect()
1276 }
1277
1278 fn world_host_traits(&self, resolve: &Resolve, world: WorldId) -> Vec<String> {
1279 let mut traits = self
1280 .import_interface_paths()
1281 .iter()
1282 .map(|path| format!("{path}::Host"))
1283 .collect::<Vec<_>>();
1284 if self.has_world_imports_trait(resolve, world) {
1285 let world_camel = to_rust_upper_camel_case(&resolve.worlds[world].name);
1286 traits.push(format!("{world_camel}Imports"));
1287 }
1288 if self.opts.async_.maybe_async() {
1289 traits.push("Send".to_string());
1290 }
1291 traits
1292 }
1293
1294 fn world_add_to_linker(&mut self, resolve: &Resolve, world: WorldId) {
1295 let has_world_imports_trait = self.has_world_imports_trait(resolve, world);
1296 if self.import_interfaces.is_empty() && !has_world_imports_trait {
1297 return;
1298 }
1299
1300 let camel = to_rust_upper_camel_case(&resolve.worlds[world].name);
1301 let data_bounds = if self.opts.is_store_data_send() {
1302 "T: Send,"
1303 } else {
1304 ""
1305 };
1306 let wt = self.wasmtime_path();
1307 if has_world_imports_trait {
1308 uwrite!(
1309 self.src,
1310 "
1311 pub fn add_to_linker_imports_get_host<T>(
1312 linker: &mut {wt}::component::Linker<T>,
1313 host_getter: impl for<'a> {camel}ImportsGetHost<&'a mut T>,
1314 ) -> {wt}::Result<()>
1315 where {data_bounds}
1316 {{
1317 let mut linker = linker.root();
1318 "
1319 );
1320 for name in get_world_resources(resolve, world) {
1321 let camel = name.to_upper_camel_case();
1322 uwriteln!(
1323 self.src,
1324 "
1325 linker.resource(
1326 \"{name}\",
1327 {wt}::component::ResourceType::host::<{camel}>(),
1328 move |mut store, rep| -> {wt}::Result<()> {{
1329 Host{camel}::drop(&mut host_getter(store.data_mut()), {wt}::component::Resource::new_own(rep))
1330 }},
1331 )?;"
1332 );
1333 }
1334 for f in self.import_functions.iter() {
1335 self.src.push_str(&f.add_to_linker);
1336 self.src.push_str("\n");
1337 }
1338 uwriteln!(self.src, "Ok(())\n}}");
1339 }
1340
1341 let host_bounds = format!("U: {}", self.world_host_traits(resolve, world).join(" + "));
1342
1343 if !self.opts.skip_mut_forwarding_impls {
1344 uwriteln!(
1345 self.src,
1346 "
1347 pub fn add_to_linker<T, U>(
1348 linker: &mut {wt}::component::Linker<T>,
1349 get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static,
1350 ) -> {wt}::Result<()>
1351 where
1352 {data_bounds}
1353 {host_bounds}
1354 {{
1355 "
1356 );
1357 if has_world_imports_trait {
1358 uwriteln!(
1359 self.src,
1360 "Self::add_to_linker_imports_get_host(linker, get)?;"
1361 );
1362 }
1363 for path in self.import_interface_paths() {
1364 uwriteln!(self.src, "{path}::add_to_linker(linker, get)?;");
1365 }
1366 uwriteln!(self.src, "Ok(())\n}}");
1367 }
1368 }
1369}
1370
1371struct InterfaceGenerator<'a> {
1372 src: Source,
1373 gen: &'a mut Wasmtime,
1374 resolve: &'a Resolve,
1375 current_interface: Option<(InterfaceId, &'a WorldKey, bool)>,
1376}
1377
1378impl<'a> InterfaceGenerator<'a> {
1379 fn new(gen: &'a mut Wasmtime, resolve: &'a Resolve) -> InterfaceGenerator<'a> {
1380 InterfaceGenerator {
1381 src: Source::default(),
1382 gen,
1383 resolve,
1384 current_interface: None,
1385 }
1386 }
1387
1388 fn types_imported(&self) -> bool {
1389 match self.current_interface {
1390 Some((_, _, is_export)) => !is_export,
1391 None => true,
1392 }
1393 }
1394
1395 fn types(&mut self, id: InterfaceId) {
1396 for (name, id) in self.resolve.interfaces[id].types.iter() {
1397 self.define_type(name, *id);
1398 }
1399 }
1400
1401 fn define_type(&mut self, name: &str, id: TypeId) {
1402 let ty = &self.resolve.types[id];
1403 match &ty.kind {
1404 TypeDefKind::Record(record) => self.type_record(id, name, record, &ty.docs),
1405 TypeDefKind::Flags(flags) => self.type_flags(id, name, flags, &ty.docs),
1406 TypeDefKind::Tuple(tuple) => self.type_tuple(id, name, tuple, &ty.docs),
1407 TypeDefKind::Enum(enum_) => self.type_enum(id, name, enum_, &ty.docs),
1408 TypeDefKind::Variant(variant) => self.type_variant(id, name, variant, &ty.docs),
1409 TypeDefKind::Option(t) => self.type_option(id, name, t, &ty.docs),
1410 TypeDefKind::Result(r) => self.type_result(id, name, r, &ty.docs),
1411 TypeDefKind::List(t) => self.type_list(id, name, t, &ty.docs),
1412 TypeDefKind::Type(t) => self.type_alias(id, name, t, &ty.docs),
1413 TypeDefKind::Future(_) => todo!("generate for future"),
1414 TypeDefKind::Stream(_) => todo!("generate for stream"),
1415 TypeDefKind::Handle(handle) => self.type_handle(id, name, handle, &ty.docs),
1416 TypeDefKind::Resource => self.type_resource(id, name, ty, &ty.docs),
1417 TypeDefKind::Unknown => unreachable!(),
1418 }
1419 }
1420
1421 fn type_handle(&mut self, id: TypeId, name: &str, handle: &Handle, docs: &Docs) {
1422 self.rustdoc(docs);
1423 let name = name.to_upper_camel_case();
1424 uwriteln!(self.src, "pub type {name} = ");
1425 self.print_handle(handle);
1426 self.push_str(";\n");
1427 self.assert_type(id, &name);
1428 }
1429
1430 fn type_resource(&mut self, id: TypeId, name: &str, resource: &TypeDef, docs: &Docs) {
1431 let camel = name.to_upper_camel_case();
1432 let wt = self.gen.wasmtime_path();
1433
1434 if self.types_imported() {
1435 self.rustdoc(docs);
1436
1437 let replacement = match self.current_interface {
1438 Some((_, key, _)) => self.gen.lookup_replacement(self.resolve, key, Some(name)),
1439 None => {
1440 self.gen.used_with_opts.insert(name.into());
1441 self.gen.opts.with.get(name).cloned()
1442 }
1443 };
1444 match replacement {
1445 Some(path) => {
1446 uwriteln!(
1447 self.src,
1448 "pub use {}{path} as {camel};",
1449 self.path_to_root()
1450 );
1451 }
1452 None => {
1453 uwriteln!(self.src, "pub enum {camel} {{}}");
1454 }
1455 }
1456
1457 if self.gen.opts.async_.maybe_async() {
1459 uwriteln!(self.src, "#[{wt}::component::__internal::async_trait]")
1460 }
1461 uwriteln!(self.src, "pub trait Host{camel} {{");
1462
1463 let mut functions = match resource.owner {
1464 TypeOwner::World(id) => self.resolve.worlds[id]
1465 .imports
1466 .values()
1467 .filter_map(|item| match item {
1468 WorldItem::Function(f) => Some(f),
1469 _ => None,
1470 })
1471 .collect(),
1472 TypeOwner::Interface(id) => self.resolve.interfaces[id]
1473 .functions
1474 .values()
1475 .collect::<Vec<_>>(),
1476 TypeOwner::None => {
1477 panic!("A resource must be owned by a world or interface");
1478 }
1479 };
1480
1481 functions.retain(|func| match func.kind {
1482 FunctionKind::Freestanding => false,
1483 FunctionKind::Method(resource)
1484 | FunctionKind::Static(resource)
1485 | FunctionKind::Constructor(resource) => id == resource,
1486 });
1487
1488 for func in &functions {
1489 self.generate_function_trait_sig(func);
1490 self.push_str(";\n");
1491 }
1492
1493 uwrite!(
1494 self.src,
1495 "fn drop(&mut self, rep: {wt}::component::Resource<{camel}>) -> {wt}::Result<()>;"
1496 );
1497
1498 uwriteln!(self.src, "}}");
1499
1500 if !self.gen.opts.skip_mut_forwarding_impls {
1502 let (async_trait, maybe_send) = if self.gen.opts.async_.maybe_async() {
1503 (
1504 format!("#[{wt}::component::__internal::async_trait]\n"),
1505 "+ Send",
1506 )
1507 } else {
1508 (String::new(), "")
1509 };
1510 uwriteln!(
1511 self.src,
1512 "{async_trait}impl <_T: Host{camel} + ?Sized {maybe_send}> Host{camel} for &mut _T {{"
1513 );
1514 for func in &functions {
1515 self.generate_function_trait_sig(func);
1516 uwrite!(
1517 self.src,
1518 "{{ Host{camel}::{}(*self,",
1519 rust_function_name(func)
1520 );
1521 for (name, _) in func.params.iter() {
1522 uwrite!(self.src, "{},", to_rust_ident(name));
1523 }
1524 uwrite!(self.src, ")");
1525 if self.gen.opts.async_.is_import_async(&func.name) {
1526 uwrite!(self.src, ".await");
1527 }
1528 uwriteln!(self.src, "}}");
1529 }
1530 uwriteln!(self.src, "
1531 fn drop(&mut self, rep: {wt}::component::Resource<{camel}>) -> {wt}::Result<()> {{
1532 Host{camel}::drop(*self, rep)
1533 }}",
1534 );
1535 uwriteln!(self.src, "}}");
1536 }
1537 } else {
1538 self.rustdoc(docs);
1539 uwriteln!(
1540 self.src,
1541 "
1542 pub type {camel} = {wt}::component::ResourceAny;
1543
1544 pub struct Guest{camel}<'a> {{
1545 funcs: &'a Guest,
1546 }}
1547 "
1548 );
1549 }
1550 }
1551
1552 fn type_record(&mut self, id: TypeId, _name: &str, record: &Record, docs: &Docs) {
1553 let info = self.info(id);
1554 let wt = self.gen.wasmtime_path();
1555
1556 let additional_derives: BTreeSet<String> = self
1558 .gen
1559 .opts
1560 .additional_derive_attributes
1561 .iter()
1562 .cloned()
1563 .collect();
1564
1565 for (name, mode) in self.modes_of(id) {
1566 let lt = self.lifetime_for(&info, mode);
1567 self.rustdoc(docs);
1568
1569 let mut derives = additional_derives.clone();
1570
1571 uwriteln!(self.src, "#[derive({wt}::component::ComponentType)]");
1572 if lt.is_none() {
1573 uwriteln!(self.src, "#[derive({wt}::component::Lift)]");
1574 }
1575 uwriteln!(self.src, "#[derive({wt}::component::Lower)]");
1576 self.push_str("#[component(record)]\n");
1577 if let Some(path) = &self.gen.opts.wasmtime_crate {
1578 uwriteln!(self.src, "#[component(wasmtime_crate = {path})]\n");
1579 }
1580
1581 if info.is_copy() {
1582 derives.extend(["Copy", "Clone"].into_iter().map(|s| s.to_string()));
1583 } else if info.is_clone() {
1584 derives.insert("Clone".to_string());
1585 }
1586
1587 if !derives.is_empty() {
1588 self.push_str("#[derive(");
1589 self.push_str(&derives.into_iter().collect::<Vec<_>>().join(", "));
1590 self.push_str(")]\n")
1591 }
1592
1593 self.push_str(&format!("pub struct {}", name));
1594 self.print_generics(lt);
1595 self.push_str(" {\n");
1596 for field in record.fields.iter() {
1597 self.rustdoc(&field.docs);
1598 self.push_str(&format!("#[component(name = \"{}\")]\n", field.name));
1599 self.push_str("pub ");
1600 self.push_str(&to_rust_ident(&field.name));
1601 self.push_str(": ");
1602 self.print_ty(&field.ty, mode);
1603 self.push_str(",\n");
1604 }
1605 self.push_str("}\n");
1606
1607 self.push_str("impl");
1608 self.print_generics(lt);
1609 self.push_str(" core::fmt::Debug for ");
1610 self.push_str(&name);
1611 self.print_generics(lt);
1612 self.push_str(" {\n");
1613 self.push_str(
1614 "fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n",
1615 );
1616 self.push_str(&format!("f.debug_struct(\"{}\")", name));
1617 for field in record.fields.iter() {
1618 self.push_str(&format!(
1619 ".field(\"{}\", &self.{})",
1620 field.name,
1621 to_rust_ident(&field.name)
1622 ));
1623 }
1624 self.push_str(".finish()\n");
1625 self.push_str("}\n");
1626 self.push_str("}\n");
1627
1628 if info.error {
1629 self.push_str("impl");
1630 self.print_generics(lt);
1631 self.push_str(" core::fmt::Display for ");
1632 self.push_str(&name);
1633 self.print_generics(lt);
1634 self.push_str(" {\n");
1635 self.push_str(
1636 "fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n",
1637 );
1638 self.push_str("write!(f, \"{:?}\", self)\n");
1639 self.push_str("}\n");
1640 self.push_str("}\n");
1641
1642 if cfg!(feature = "std") {
1643 self.push_str("impl std::error::Error for ");
1644 self.push_str(&name);
1645 self.push_str("{}\n");
1646 }
1647 }
1648 self.assert_type(id, &name);
1649 }
1650 }
1651
1652 fn type_tuple(&mut self, id: TypeId, _name: &str, tuple: &Tuple, docs: &Docs) {
1653 let info = self.info(id);
1654 for (name, mode) in self.modes_of(id) {
1655 let lt = self.lifetime_for(&info, mode);
1656 self.rustdoc(docs);
1657 self.push_str(&format!("pub type {}", name));
1658 self.print_generics(lt);
1659 self.push_str(" = (");
1660 for ty in tuple.types.iter() {
1661 self.print_ty(ty, mode);
1662 self.push_str(",");
1663 }
1664 self.push_str(");\n");
1665 self.assert_type(id, &name);
1666 }
1667 }
1668
1669 fn type_flags(&mut self, id: TypeId, name: &str, flags: &Flags, docs: &Docs) {
1670 self.rustdoc(docs);
1671 let wt = self.gen.wasmtime_path();
1672 let rust_name = to_rust_upper_camel_case(name);
1673 uwriteln!(self.src, "{wt}::component::flags!(\n");
1674 self.src.push_str(&format!("{rust_name} {{\n"));
1675 for flag in flags.flags.iter() {
1676 uwrite!(
1678 self.src,
1679 "#[component(name=\"{}\")] const {};\n",
1680 flag.name,
1681 flag.name.to_shouty_snake_case()
1682 );
1683 }
1684 self.src.push_str("}\n");
1685 self.src.push_str(");\n\n");
1686 self.assert_type(id, &rust_name);
1687 }
1688
1689 fn type_variant(&mut self, id: TypeId, _name: &str, variant: &Variant, docs: &Docs) {
1690 self.print_rust_enum(
1691 id,
1692 variant.cases.iter().map(|c| {
1693 (
1694 c.name.to_upper_camel_case(),
1695 Some(c.name.clone()),
1696 &c.docs,
1697 c.ty.as_ref(),
1698 )
1699 }),
1700 docs,
1701 "variant",
1702 );
1703 }
1704
1705 fn type_option(&mut self, id: TypeId, _name: &str, payload: &Type, docs: &Docs) {
1706 let info = self.info(id);
1707
1708 for (name, mode) in self.modes_of(id) {
1709 self.rustdoc(docs);
1710 let lt = self.lifetime_for(&info, mode);
1711 self.push_str(&format!("pub type {}", name));
1712 self.print_generics(lt);
1713 self.push_str("= Option<");
1714 self.print_ty(payload, mode);
1715 self.push_str(">;\n");
1716 self.assert_type(id, &name);
1717 }
1718 }
1719
1720 fn assert_type(&mut self, id: TypeId, name: &str) {
1723 self.push_str("const _: () = {\n");
1724 let wt = self.gen.wasmtime_path();
1725 uwriteln!(
1726 self.src,
1727 "assert!({} == <{name} as {wt}::component::ComponentType>::SIZE32);",
1728 self.gen.sizes.size(&Type::Id(id)),
1729 );
1730 uwriteln!(
1731 self.src,
1732 "assert!({} == <{name} as {wt}::component::ComponentType>::ALIGN32);",
1733 self.gen.sizes.align(&Type::Id(id)),
1734 );
1735 self.push_str("};\n");
1736 }
1737
1738 fn print_rust_enum<'b>(
1739 &mut self,
1740 id: TypeId,
1741 cases: impl IntoIterator<Item = (String, Option<String>, &'b Docs, Option<&'b Type>)> + Clone,
1742 docs: &Docs,
1743 derive_component: &str,
1744 ) where
1745 Self: Sized,
1746 {
1747 let info = self.info(id);
1748 let wt = self.gen.wasmtime_path();
1749
1750 let additional_derives: BTreeSet<String> = self
1752 .gen
1753 .opts
1754 .additional_derive_attributes
1755 .iter()
1756 .cloned()
1757 .collect();
1758
1759 for (name, mode) in self.modes_of(id) {
1760 let name = to_rust_upper_camel_case(&name);
1761
1762 let mut derives = additional_derives.clone();
1763
1764 self.rustdoc(docs);
1765 let lt = self.lifetime_for(&info, mode);
1766 uwriteln!(self.src, "#[derive({wt}::component::ComponentType)]");
1767 if lt.is_none() {
1768 uwriteln!(self.src, "#[derive({wt}::component::Lift)]");
1769 }
1770 uwriteln!(self.src, "#[derive({wt}::component::Lower)]");
1771 self.push_str(&format!("#[component({})]\n", derive_component));
1772 if let Some(path) = &self.gen.opts.wasmtime_crate {
1773 uwriteln!(self.src, "#[component(wasmtime_crate = {path})]\n");
1774 }
1775 if info.is_copy() {
1776 derives.extend(["Copy", "Clone"].into_iter().map(|s| s.to_string()));
1777 } else if info.is_clone() {
1778 derives.insert("Clone".to_string());
1779 }
1780
1781 if !derives.is_empty() {
1782 self.push_str("#[derive(");
1783 self.push_str(&derives.into_iter().collect::<Vec<_>>().join(", "));
1784 self.push_str(")]\n")
1785 }
1786
1787 self.push_str(&format!("pub enum {name}"));
1788 self.print_generics(lt);
1789 self.push_str("{\n");
1790 for (case_name, component_name, docs, payload) in cases.clone() {
1791 self.rustdoc(docs);
1792 if let Some(n) = component_name {
1793 self.push_str(&format!("#[component(name = \"{}\")] ", n));
1794 }
1795 self.push_str(&case_name);
1796 if let Some(ty) = payload {
1797 self.push_str("(");
1798 self.print_ty(ty, mode);
1799 self.push_str(")")
1800 }
1801 self.push_str(",\n");
1802 }
1803 self.push_str("}\n");
1804
1805 self.print_rust_enum_debug(
1806 id,
1807 mode,
1808 &name,
1809 cases
1810 .clone()
1811 .into_iter()
1812 .map(|(name, _attr, _docs, ty)| (name, ty)),
1813 );
1814
1815 if info.error {
1816 self.push_str("impl");
1817 self.print_generics(lt);
1818 self.push_str(" core::fmt::Display for ");
1819 self.push_str(&name);
1820 self.print_generics(lt);
1821 self.push_str(" {\n");
1822 self.push_str(
1823 "fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n",
1824 );
1825 self.push_str("write!(f, \"{:?}\", self)");
1826 self.push_str("}\n");
1827 self.push_str("}\n");
1828 self.push_str("\n");
1829
1830 if cfg!(feature = "std") {
1831 self.push_str("impl");
1832 self.print_generics(lt);
1833 self.push_str(" std::error::Error for ");
1834 self.push_str(&name);
1835 self.print_generics(lt);
1836 self.push_str(" {}\n");
1837 }
1838 }
1839
1840 self.assert_type(id, &name);
1841 }
1842 }
1843
1844 fn print_rust_enum_debug<'b>(
1845 &mut self,
1846 id: TypeId,
1847 mode: TypeMode,
1848 name: &str,
1849 cases: impl IntoIterator<Item = (String, Option<&'b Type>)>,
1850 ) where
1851 Self: Sized,
1852 {
1853 let info = self.info(id);
1854 let lt = self.lifetime_for(&info, mode);
1855 self.push_str("impl");
1856 self.print_generics(lt);
1857 self.push_str(" core::fmt::Debug for ");
1858 self.push_str(name);
1859 self.print_generics(lt);
1860 self.push_str(" {\n");
1861 self.push_str("fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n");
1862 self.push_str("match self {\n");
1863 for (case_name, payload) in cases {
1864 self.push_str(name);
1865 self.push_str("::");
1866 self.push_str(&case_name);
1867 if payload.is_some() {
1868 self.push_str("(e)");
1869 }
1870 self.push_str(" => {\n");
1871 self.push_str(&format!("f.debug_tuple(\"{}::{}\")", name, case_name));
1872 if payload.is_some() {
1873 self.push_str(".field(e)");
1874 }
1875 self.push_str(".finish()\n");
1876 self.push_str("}\n");
1877 }
1878 self.push_str("}\n");
1879 self.push_str("}\n");
1880 self.push_str("}\n");
1881 }
1882
1883 fn type_result(&mut self, id: TypeId, _name: &str, result: &Result_, docs: &Docs) {
1884 let info = self.info(id);
1885
1886 for (name, mode) in self.modes_of(id) {
1887 self.rustdoc(docs);
1888 let lt = self.lifetime_for(&info, mode);
1889 self.push_str(&format!("pub type {}", name));
1890 self.print_generics(lt);
1891 self.push_str("= Result<");
1892 self.print_optional_ty(result.ok.as_ref(), mode);
1893 self.push_str(",");
1894 self.print_optional_ty(result.err.as_ref(), mode);
1895 self.push_str(">;\n");
1896 self.assert_type(id, &name);
1897 }
1898 }
1899
1900 fn type_enum(&mut self, id: TypeId, name: &str, enum_: &Enum, docs: &Docs) {
1901 let info = self.info(id);
1902 let wt = self.gen.wasmtime_path();
1903
1904 let mut derives: BTreeSet<String> = self
1906 .gen
1907 .opts
1908 .additional_derive_attributes
1909 .iter()
1910 .cloned()
1911 .collect();
1912
1913 derives.extend(
1914 ["Clone", "Copy", "PartialEq", "Eq"]
1915 .into_iter()
1916 .map(|s| s.to_string()),
1917 );
1918
1919 let name = to_rust_upper_camel_case(name);
1920 self.rustdoc(docs);
1921 uwriteln!(self.src, "#[derive({wt}::component::ComponentType)]");
1922 uwriteln!(self.src, "#[derive({wt}::component::Lift)]");
1923 uwriteln!(self.src, "#[derive({wt}::component::Lower)]");
1924 self.push_str("#[component(enum)]\n");
1925 if let Some(path) = &self.gen.opts.wasmtime_crate {
1926 uwriteln!(self.src, "#[component(wasmtime_crate = {path})]\n");
1927 }
1928
1929 self.push_str("#[derive(");
1930 self.push_str(&derives.into_iter().collect::<Vec<_>>().join(", "));
1931 self.push_str(")]\n");
1932
1933 self.push_str(&format!("pub enum {} {{\n", name));
1934 for case in enum_.cases.iter() {
1935 self.rustdoc(&case.docs);
1936 self.push_str(&format!("#[component(name = \"{}\")]", case.name));
1937 self.push_str(&case.name.to_upper_camel_case());
1938 self.push_str(",\n");
1939 }
1940 self.push_str("}\n");
1941
1942 if info.error {
1945 self.push_str("impl ");
1946 self.push_str(&name);
1947 self.push_str("{\n");
1948
1949 self.push_str("pub fn name(&self) -> &'static str {\n");
1950 self.push_str("match self {\n");
1951 for case in enum_.cases.iter() {
1952 self.push_str(&name);
1953 self.push_str("::");
1954 self.push_str(&case.name.to_upper_camel_case());
1955 self.push_str(" => \"");
1956 self.push_str(case.name.as_str());
1957 self.push_str("\",\n");
1958 }
1959 self.push_str("}\n");
1960 self.push_str("}\n");
1961
1962 self.push_str("pub fn message(&self) -> &'static str {\n");
1963 self.push_str("match self {\n");
1964 for case in enum_.cases.iter() {
1965 self.push_str(&name);
1966 self.push_str("::");
1967 self.push_str(&case.name.to_upper_camel_case());
1968 self.push_str(" => \"");
1969 if let Some(contents) = &case.docs.contents {
1970 self.push_str(contents.trim());
1971 }
1972 self.push_str("\",\n");
1973 }
1974 self.push_str("}\n");
1975 self.push_str("}\n");
1976
1977 self.push_str("}\n");
1978
1979 self.push_str("impl core::fmt::Debug for ");
1980 self.push_str(&name);
1981 self.push_str(
1982 "{\nfn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n",
1983 );
1984 self.push_str("f.debug_struct(\"");
1985 self.push_str(&name);
1986 self.push_str("\")\n");
1987 self.push_str(".field(\"code\", &(*self as i32))\n");
1988 self.push_str(".field(\"name\", &self.name())\n");
1989 self.push_str(".field(\"message\", &self.message())\n");
1990 self.push_str(".finish()\n");
1991 self.push_str("}\n");
1992 self.push_str("}\n");
1993
1994 self.push_str("impl core::fmt::Display for ");
1995 self.push_str(&name);
1996 self.push_str(
1997 "{\nfn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n",
1998 );
1999 self.push_str("write!(f, \"{} (error {})\", self.name(), *self as i32)");
2000 self.push_str("}\n");
2001 self.push_str("}\n");
2002 self.push_str("\n");
2003 if cfg!(feature = "std") {
2004 self.push_str("impl std::error::Error for ");
2005 self.push_str(&name);
2006 self.push_str("{}\n");
2007 }
2008 } else {
2009 self.print_rust_enum_debug(
2010 id,
2011 TypeMode::Owned,
2012 &name,
2013 enum_
2014 .cases
2015 .iter()
2016 .map(|c| (c.name.to_upper_camel_case(), None)),
2017 )
2018 }
2019 self.assert_type(id, &name);
2020 }
2021
2022 fn type_alias(&mut self, id: TypeId, _name: &str, ty: &Type, docs: &Docs) {
2023 let info = self.info(id);
2024 for (name, mode) in self.modes_of(id) {
2025 self.rustdoc(docs);
2026 self.push_str(&format!("pub type {}", name));
2027 let lt = self.lifetime_for(&info, mode);
2028 self.print_generics(lt);
2029 self.push_str(" = ");
2030 self.print_ty(ty, mode);
2031 self.push_str(";\n");
2032 let def_id = resolve_type_definition_id(self.resolve, id);
2033 if !matches!(self.resolve().types[def_id].kind, TypeDefKind::Resource) {
2034 self.assert_type(id, &name);
2035 }
2036 }
2037 }
2038
2039 fn type_list(&mut self, id: TypeId, _name: &str, ty: &Type, docs: &Docs) {
2040 let info = self.info(id);
2041 for (name, mode) in self.modes_of(id) {
2042 let lt = self.lifetime_for(&info, mode);
2043 self.rustdoc(docs);
2044 self.push_str(&format!("pub type {}", name));
2045 self.print_generics(lt);
2046 self.push_str(" = ");
2047 self.print_list(ty, mode);
2048 self.push_str(";\n");
2049 self.assert_type(id, &name);
2050 }
2051 }
2052
2053 fn print_result_ty(&mut self, results: &Results, mode: TypeMode) {
2054 match results {
2055 Results::Named(rs) => match rs.len() {
2056 0 => self.push_str("()"),
2057 1 => self.print_ty(&rs[0].1, mode),
2058 _ => {
2059 self.push_str("(");
2060 for (i, (_, ty)) in rs.iter().enumerate() {
2061 if i > 0 {
2062 self.push_str(", ")
2063 }
2064 self.print_ty(ty, mode)
2065 }
2066 self.push_str(")");
2067 }
2068 },
2069 Results::Anon(ty) => self.print_ty(ty, mode),
2070 }
2071 }
2072
2073 fn special_case_trappable_error(
2074 &mut self,
2075 func: &Function,
2076 ) -> Option<(&'a Result_, TypeId, String)> {
2077 let results = &func.results;
2078
2079 self.gen
2080 .used_trappable_imports_opts
2081 .insert(func.name.clone());
2082
2083 let mut i = results.iter_types();
2087 let id = match i.next()? {
2088 Type::Id(id) => id,
2089 _ => return None,
2090 };
2091 if i.next().is_some() {
2092 return None;
2093 }
2094 let result = match &self.resolve.types[*id].kind {
2095 TypeDefKind::Result(r) => r,
2096 _ => return None,
2097 };
2098 let error_typeid = match result.err? {
2099 Type::Id(id) => resolve_type_definition_id(&self.resolve, id),
2100 _ => return None,
2101 };
2102
2103 let name = self.gen.trappable_errors.get(&error_typeid)?;
2104
2105 let mut path = self.path_to_root();
2106 uwrite!(path, "{name}");
2107 Some((result, error_typeid, path))
2108 }
2109
2110 fn generate_add_to_linker(&mut self, id: InterfaceId, name: &str) {
2111 let iface = &self.resolve.interfaces[id];
2112 let owner = TypeOwner::Interface(id);
2113 let wt = self.gen.wasmtime_path();
2114
2115 let is_maybe_async = self.gen.opts.async_.maybe_async();
2116 if is_maybe_async {
2117 uwriteln!(self.src, "#[{wt}::component::__internal::async_trait]")
2118 }
2119 uwrite!(self.src, "pub trait Host");
2123 let mut host_supertraits = vec![];
2124 if is_maybe_async {
2125 host_supertraits.push("Send".to_string());
2126 }
2127 for resource in get_resources(self.resolve, id) {
2128 host_supertraits.push(format!("Host{}", resource.to_upper_camel_case()));
2129 }
2130 if !host_supertraits.is_empty() {
2131 uwrite!(self.src, ": {}", host_supertraits.join(" + "));
2132 }
2133 uwriteln!(self.src, " {{");
2134 for (_, func) in iface.functions.iter() {
2135 match func.kind {
2136 FunctionKind::Freestanding => {}
2137 _ => continue,
2138 }
2139 self.generate_function_trait_sig(func);
2140 self.push_str(";\n");
2141 }
2142
2143 let mut required_conversion_traits = IndexSet::new();
2146 let mut errors_converted = IndexMap::new();
2147 let mut my_error_types = iface
2148 .types
2149 .iter()
2150 .filter(|(_, id)| self.gen.trappable_errors.contains_key(*id))
2151 .map(|(_, id)| *id)
2152 .collect::<Vec<_>>();
2153 my_error_types.extend(
2154 iface
2155 .functions
2156 .iter()
2157 .filter_map(|(_, func)| self.special_case_trappable_error(func))
2158 .map(|(_, id, _)| id),
2159 );
2160 let root = self.path_to_root();
2161 for err_id in my_error_types {
2162 let custom_name = &self.gen.trappable_errors[&err_id];
2163 let err = &self.resolve.types[resolve_type_definition_id(self.resolve, err_id)];
2164 let err_name = err.name.as_ref().unwrap();
2165 let err_snake = err_name.to_snake_case();
2166 let err_camel = err_name.to_upper_camel_case();
2167 let owner = match err.owner {
2168 TypeOwner::Interface(i) => i,
2169 _ => unimplemented!(),
2170 };
2171 match self.path_to_interface(owner) {
2172 Some(path) => {
2173 required_conversion_traits.insert(format!("{path}::Host"));
2174 }
2175 None => {
2176 if errors_converted.insert(err_name, err_id).is_none() {
2177 uwriteln!(
2178 self.src,
2179 "fn convert_{err_snake}(&mut self, err: {root}{custom_name}) -> {wt}::Result<{err_camel}>;"
2180 );
2181 }
2182 }
2183 }
2184 }
2185 uwriteln!(self.src, "}}");
2186
2187 let (data_bounds, mut host_bounds) = if self.gen.opts.is_store_data_send() {
2188 ("T: Send,", "Host + Send".to_string())
2189 } else {
2190 ("", "Host".to_string())
2191 };
2192 for ty in required_conversion_traits {
2193 uwrite!(host_bounds, " + {ty}");
2194 }
2195
2196 uwriteln!(
2197 self.src,
2198 "
2199 pub trait GetHost<T>:
2200 Fn(T) -> <Self as GetHost<T>>::Host
2201 + Send
2202 + Sync
2203 + Copy
2204 + 'static
2205 {{
2206 type Host: {host_bounds};
2207 }}
2208
2209 impl<F, T, O> GetHost<T> for F
2210 where
2211 F: Fn(T) -> O + Send + Sync + Copy + 'static,
2212 O: {host_bounds},
2213 {{
2214 type Host = O;
2215 }}
2216
2217 pub fn add_to_linker_get_host<T>(
2218 linker: &mut {wt}::component::Linker<T>,
2219 host_getter: impl for<'a> GetHost<&'a mut T>,
2220 ) -> {wt}::Result<()>
2221 where {data_bounds}
2222 {{
2223 "
2224 );
2225 uwriteln!(self.src, "let mut inst = linker.instance(\"{name}\")?;");
2226
2227 for name in get_resources(self.resolve, id) {
2228 let camel = name.to_upper_camel_case();
2229 uwriteln!(
2230 self.src,
2231 "inst.resource(
2232 \"{name}\",
2233 {wt}::component::ResourceType::host::<{camel}>(),
2234 move |mut store, rep| -> {wt}::Result<()> {{
2235 Host{camel}::drop(&mut host_getter(store.data_mut()), {wt}::component::Resource::new_own(rep))
2236 }},
2237 )?;"
2238 )
2239 }
2240
2241 for (_, func) in iface.functions.iter() {
2242 self.generate_add_function_to_linker(owner, func, "inst");
2243 }
2244 uwriteln!(self.src, "Ok(())");
2245 uwriteln!(self.src, "}}");
2246
2247 if !self.gen.opts.skip_mut_forwarding_impls {
2248 uwriteln!(
2250 self.src,
2251 "
2252 pub fn add_to_linker<T, U>(
2253 linker: &mut {wt}::component::Linker<T>,
2254 get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static,
2255 ) -> {wt}::Result<()>
2256 where
2257 U: {host_bounds}, {data_bounds}
2258 {{
2259 add_to_linker_get_host(linker, get)
2260 }}
2261 "
2262 );
2263
2264 let (async_trait, maybe_send) = if is_maybe_async {
2266 (
2267 format!("#[{wt}::component::__internal::async_trait]"),
2268 "+ Send",
2269 )
2270 } else {
2271 (String::new(), "")
2272 };
2273
2274 uwriteln!(
2275 self.src,
2276 "{async_trait}impl<_T: Host + ?Sized {maybe_send}> Host for &mut _T {{"
2277 );
2278 for (_, func) in iface.functions.iter() {
2280 match func.kind {
2281 FunctionKind::Freestanding => {}
2282 _ => continue,
2283 }
2284 self.generate_function_trait_sig(func);
2285 uwrite!(self.src, "{{ Host::{}(*self,", rust_function_name(func));
2286 for (name, _) in func.params.iter() {
2287 uwrite!(self.src, "{},", to_rust_ident(name));
2288 }
2289 uwrite!(self.src, ")");
2290 if self.gen.opts.async_.is_import_async(&func.name) {
2291 uwrite!(self.src, ".await");
2292 }
2293 uwriteln!(self.src, "}}");
2294 }
2295 for (err_name, err_id) in errors_converted {
2296 uwriteln!(
2297 self.src,
2298 "fn convert_{err_snake}(&mut self, err: {root}{custom_name}) -> {wt}::Result<{err_camel}> {{
2299 Host::convert_{err_snake}(*self, err)
2300 }}",
2301 custom_name = self.gen.trappable_errors[&err_id],
2302 err_snake = err_name.to_snake_case(),
2303 err_camel = err_name.to_upper_camel_case(),
2304 );
2305 }
2306 uwriteln!(self.src, "}}");
2307 }
2308 }
2309
2310 fn generate_add_function_to_linker(&mut self, owner: TypeOwner, func: &Function, linker: &str) {
2311 uwrite!(
2312 self.src,
2313 "{linker}.{}(\"{}\", ",
2314 if self.gen.opts.async_.is_import_async(&func.name) {
2315 "func_wrap_async"
2316 } else {
2317 "func_wrap"
2318 },
2319 func.name
2320 );
2321 self.generate_guest_import_closure(owner, func);
2322 uwriteln!(self.src, ")?;")
2323 }
2324
2325 fn generate_guest_import_closure(&mut self, owner: TypeOwner, func: &Function) {
2326 let wt = self.gen.wasmtime_path();
2330 uwrite!(
2331 self.src,
2332 "move |mut caller: {wt}::StoreContextMut<'_, T>, ("
2333 );
2334 for (i, _param) in func.params.iter().enumerate() {
2335 uwrite!(self.src, "arg{},", i);
2336 }
2337 self.src.push_str(") : (");
2338
2339 for (_, ty) in func.params.iter() {
2340 self.print_ty(ty, TypeMode::Owned);
2343 self.src.push_str(", ");
2344 }
2345 self.src.push_str(") |");
2346 if self.gen.opts.async_.is_import_async(&func.name) {
2347 uwriteln!(
2348 self.src,
2349 " {wt}::component::__internal::Box::new(async move {{ "
2350 );
2351 } else {
2352 self.src.push_str(" { \n");
2353 }
2354
2355 if self.gen.opts.tracing {
2356 uwrite!(
2357 self.src,
2358 "
2359 let span = tracing::span!(
2360 tracing::Level::TRACE,
2361 \"wit-bindgen import\",
2362 module = \"{}\",
2363 function = \"{}\",
2364 );
2365 let _enter = span.enter();
2366 ",
2367 match owner {
2368 TypeOwner::Interface(id) => self.resolve.interfaces[id]
2369 .name
2370 .as_deref()
2371 .unwrap_or("<no module>"),
2372 TypeOwner::World(id) => &self.resolve.worlds[id].name,
2373 TypeOwner::None => "<no owner>",
2374 },
2375 func.name,
2376 );
2377 let mut event_fields = func
2378 .params
2379 .iter()
2380 .enumerate()
2381 .map(|(i, (name, _ty))| {
2382 let name = to_rust_ident(&name);
2383 format!("{name} = tracing::field::debug(&arg{i})")
2384 })
2385 .collect::<Vec<String>>();
2386 event_fields.push(format!("\"call\""));
2387 uwrite!(
2388 self.src,
2389 "tracing::event!(tracing::Level::TRACE, {});\n",
2390 event_fields.join(", ")
2391 );
2392 }
2393
2394 self.src
2395 .push_str("let host = &mut host_getter(caller.data_mut());\n");
2396 let func_name = rust_function_name(func);
2397 let host_trait = match func.kind {
2398 FunctionKind::Freestanding => match owner {
2399 TypeOwner::World(id) => format!(
2400 "{}Imports",
2401 self.resolve.worlds[id].name.to_upper_camel_case()
2402 ),
2403 _ => "Host".to_string(),
2404 },
2405 FunctionKind::Method(id) | FunctionKind::Static(id) | FunctionKind::Constructor(id) => {
2406 let resource = self.resolve.types[id]
2407 .name
2408 .as_ref()
2409 .unwrap()
2410 .to_upper_camel_case();
2411 format!("Host{resource}")
2412 }
2413 };
2414 uwrite!(self.src, "let r = {host_trait}::{func_name}(host, ");
2415
2416 for (i, _) in func.params.iter().enumerate() {
2417 uwrite!(self.src, "arg{},", i);
2418 }
2419 if self.gen.opts.async_.is_import_async(&func.name) {
2420 uwrite!(self.src, ").await;\n");
2421 } else {
2422 uwrite!(self.src, ");\n");
2423 }
2424
2425 if self.gen.opts.tracing {
2426 uwrite!(
2427 self.src,
2428 "tracing::event!(tracing::Level::TRACE, result = tracing::field::debug(&r), \"return\");"
2429 );
2430 }
2431
2432 if !self.gen.opts.trappable_imports.can_trap(&func) {
2433 if func.results.iter_types().len() == 1 {
2434 uwrite!(self.src, "Ok((r,))\n");
2435 } else {
2436 uwrite!(self.src, "Ok(r)\n");
2437 }
2438 } else if let Some((_, err, _)) = self.special_case_trappable_error(func) {
2439 let err = &self.resolve.types[resolve_type_definition_id(self.resolve, err)];
2440 let err_name = err.name.as_ref().unwrap();
2441 let owner = match err.owner {
2442 TypeOwner::Interface(i) => i,
2443 _ => unimplemented!(),
2444 };
2445 let convert_trait = match self.path_to_interface(owner) {
2446 Some(path) => format!("{path}::Host"),
2447 None => format!("Host"),
2448 };
2449 let convert = format!("{}::convert_{}", convert_trait, err_name.to_snake_case());
2450 uwrite!(
2451 self.src,
2452 "Ok((match r {{
2453 Ok(a) => Ok(a),
2454 Err(e) => Err({convert}(host, e)?),
2455 }},))"
2456 );
2457 } else if func.results.iter_types().len() == 1 {
2458 uwrite!(self.src, "Ok((r?,))\n");
2459 } else {
2460 uwrite!(self.src, "r\n");
2461 }
2462
2463 if self.gen.opts.async_.is_import_async(&func.name) {
2464 self.src.push_str("})");
2466 } else {
2467 self.src.push_str("}");
2468 }
2469 }
2470
2471 fn generate_function_trait_sig(&mut self, func: &Function) {
2472 let wt = self.gen.wasmtime_path();
2473 self.rustdoc(&func.docs);
2474
2475 if self.gen.opts.async_.is_import_async(&func.name) {
2476 self.push_str("async ");
2477 }
2478 self.push_str("fn ");
2479 self.push_str(&rust_function_name(func));
2480 self.push_str("(&mut self, ");
2481 for (name, param) in func.params.iter() {
2482 let name = to_rust_ident(name);
2483 self.push_str(&name);
2484 self.push_str(": ");
2485 self.print_ty(param, TypeMode::Owned);
2486 self.push_str(",");
2487 }
2488 self.push_str(")");
2489 self.push_str(" -> ");
2490
2491 if !self.gen.opts.trappable_imports.can_trap(func) {
2492 self.print_result_ty(&func.results, TypeMode::Owned);
2493 } else if let Some((r, _id, error_typename)) = self.special_case_trappable_error(func) {
2494 self.push_str("Result<");
2498 if let Some(ok) = r.ok {
2499 self.print_ty(&ok, TypeMode::Owned);
2500 } else {
2501 self.push_str("()");
2502 }
2503 self.push_str(",");
2504 self.push_str(&error_typename);
2505 self.push_str(">");
2506 } else {
2507 uwrite!(self.src, "{wt}::Result<");
2510 self.print_result_ty(&func.results, TypeMode::Owned);
2511 self.push_str(">");
2512 }
2513 }
2514
2515 fn extract_typed_function(&mut self, func: &Function) -> (String, String) {
2516 let prev = mem::take(&mut self.src);
2517 let snake = func_field_name(self.resolve, func);
2518 uwrite!(self.src, "*_instance.get_typed_func::<(");
2519 for (_, ty) in func.params.iter() {
2520 self.print_ty(ty, TypeMode::AllBorrowed("'_"));
2521 self.push_str(", ");
2522 }
2523 self.src.push_str("), (");
2524 for ty in func.results.iter_types() {
2525 self.print_ty(ty, TypeMode::Owned);
2526 self.push_str(", ");
2527 }
2528 uwriteln!(self.src, ")>(&mut store, &self.{snake})?.func()");
2529
2530 let ret = (snake, mem::take(&mut self.src).to_string());
2531 self.src = prev;
2532 ret
2533 }
2534
2535 fn define_rust_guest_export(
2536 &mut self,
2537 resolve: &Resolve,
2538 ns: Option<&WorldKey>,
2539 func: &Function,
2540 ) {
2541 let is_async = self.gen.opts.async_.maybe_async();
2544
2545 let (async_, async__, await_) = if is_async {
2546 ("async", "_async", ".await")
2547 } else {
2548 ("", "", "")
2549 };
2550
2551 self.rustdoc(&func.docs);
2552 let wt = self.gen.wasmtime_path();
2553
2554 uwrite!(
2555 self.src,
2556 "pub {async_} fn call_{}<S: {wt}::AsContextMut>(&self, mut store: S, ",
2557 func.item_name().to_snake_case(),
2558 );
2559
2560 for (i, param) in func.params.iter().enumerate() {
2561 uwrite!(self.src, "arg{}: ", i);
2562 self.print_ty(¶m.1, TypeMode::AllBorrowed("'_"));
2563 self.push_str(",");
2564 }
2565
2566 uwrite!(self.src, ") -> {wt}::Result<");
2567 self.print_result_ty(&func.results, TypeMode::Owned);
2568
2569 if is_async {
2570 uwriteln!(self.src, "> where <S as {wt}::AsContext>::Data: Send {{");
2571 } else {
2572 self.src.push_str("> {\n");
2573 }
2574
2575 if self.gen.opts.tracing {
2576 let ns = match ns {
2577 Some(key) => resolve.name_world_key(key),
2578 None => "default".to_string(),
2579 };
2580 self.src.push_str(&format!(
2581 "
2582 let span = tracing::span!(
2583 tracing::Level::TRACE,
2584 \"wit-bindgen export\",
2585 module = \"{ns}\",
2586 function = \"{}\",
2587 );
2588 let _enter = span.enter();
2589 ",
2590 func.name,
2591 ));
2592 }
2593
2594 self.src.push_str("let callee = unsafe {\n");
2595 uwrite!(self.src, "{wt}::component::TypedFunc::<(");
2596 for (_, ty) in func.params.iter() {
2597 self.print_ty(ty, TypeMode::AllBorrowed("'_"));
2598 self.push_str(", ");
2599 }
2600 self.src.push_str("), (");
2601 for ty in func.results.iter_types() {
2602 self.print_ty(ty, TypeMode::Owned);
2603 self.push_str(", ");
2604 }
2605 let projection_to_func = match &func.kind {
2606 FunctionKind::Freestanding => "",
2607 _ => ".funcs",
2608 };
2609 uwriteln!(
2610 self.src,
2611 ")>::new_unchecked(self{projection_to_func}.{})",
2612 func_field_name(self.resolve, func),
2613 );
2614 self.src.push_str("};\n");
2615 self.src.push_str("let (");
2616 for (i, _) in func.results.iter_types().enumerate() {
2617 uwrite!(self.src, "ret{},", i);
2618 }
2619 uwrite!(
2620 self.src,
2621 ") = callee.call{async__}(store.as_context_mut(), ("
2622 );
2623 for (i, _) in func.params.iter().enumerate() {
2624 uwrite!(self.src, "arg{}, ", i);
2625 }
2626 uwriteln!(self.src, ")){await_}?;");
2627
2628 uwriteln!(
2629 self.src,
2630 "callee.post_return{async__}(store.as_context_mut()){await_}?;"
2631 );
2632
2633 self.src.push_str("Ok(");
2634 if func.results.iter_types().len() == 1 {
2635 self.src.push_str("ret0");
2636 } else {
2637 self.src.push_str("(");
2638 for (i, _) in func.results.iter_types().enumerate() {
2639 uwrite!(self.src, "ret{},", i);
2640 }
2641 self.src.push_str(")");
2642 }
2643 self.src.push_str(")\n");
2644
2645 self.src.push_str("}\n");
2647 }
2648
2649 fn rustdoc(&mut self, docs: &Docs) {
2650 let docs = match &docs.contents {
2651 Some(docs) => docs,
2652 None => return,
2653 };
2654 for line in docs.trim().lines() {
2655 self.push_str("/// ");
2656 self.push_str(line);
2657 self.push_str("\n");
2658 }
2659 }
2660
2661 fn path_to_root(&self) -> String {
2662 let mut path_to_root = String::new();
2663 if let Some((_, key, is_export)) = self.current_interface {
2664 match key {
2665 WorldKey::Name(_) => {
2666 path_to_root.push_str("super::");
2667 }
2668 WorldKey::Interface(_) => {
2669 path_to_root.push_str("super::super::super::");
2670 }
2671 }
2672 if is_export {
2673 path_to_root.push_str("super::");
2674 }
2675 }
2676 path_to_root
2677 }
2678}
2679
2680impl<'a> RustGenerator<'a> for InterfaceGenerator<'a> {
2681 fn resolve(&self) -> &'a Resolve {
2682 self.resolve
2683 }
2684
2685 fn ownership(&self) -> Ownership {
2686 self.gen.opts.ownership
2687 }
2688
2689 fn path_to_interface(&self, interface: InterfaceId) -> Option<String> {
2690 if let Some((cur, _, _)) = self.current_interface {
2691 if cur == interface {
2692 return None;
2693 }
2694 }
2695 let mut path_to_root = self.path_to_root();
2696 match &self.gen.interface_names[&interface] {
2697 InterfaceName::Remapped { name_at_root, .. } => path_to_root.push_str(name_at_root),
2698 InterfaceName::Path(path) => {
2699 for (i, name) in path.iter().enumerate() {
2700 if i > 0 {
2701 path_to_root.push_str("::");
2702 }
2703 path_to_root.push_str(name);
2704 }
2705 }
2706 }
2707 Some(path_to_root)
2708 }
2709
2710 fn push_str(&mut self, s: &str) {
2711 self.src.push_str(s);
2712 }
2713
2714 fn info(&self, ty: TypeId) -> TypeInfo {
2715 self.gen.types.get(ty)
2716 }
2717
2718 fn is_imported_interface(&self, interface: InterfaceId) -> bool {
2719 self.gen.interface_last_seen_as_import[&interface]
2720 }
2721
2722 fn wasmtime_path(&self) -> String {
2723 self.gen.wasmtime_path()
2724 }
2725}
2726
2727fn resolve_type_definition_id(resolve: &Resolve, mut id: TypeId) -> TypeId {
2731 loop {
2732 match resolve.types[id].kind {
2733 TypeDefKind::Type(Type::Id(def_id)) => id = def_id,
2734 _ => return id,
2735 }
2736 }
2737}
2738
2739fn rust_function_name(func: &Function) -> String {
2740 match func.kind {
2741 FunctionKind::Method(_) | FunctionKind::Static(_) => to_rust_ident(func.item_name()),
2742 FunctionKind::Constructor(_) => "new".to_string(),
2743 FunctionKind::Freestanding => to_rust_ident(&func.name),
2744 }
2745}
2746
2747fn func_field_name(resolve: &Resolve, func: &Function) -> String {
2748 let mut name = String::new();
2749 match func.kind {
2750 FunctionKind::Method(id) => {
2751 name.push_str("method-");
2752 name.push_str(resolve.types[id].name.as_ref().unwrap());
2753 name.push_str("-");
2754 }
2755 FunctionKind::Static(id) => {
2756 name.push_str("static-");
2757 name.push_str(resolve.types[id].name.as_ref().unwrap());
2758 name.push_str("-");
2759 }
2760 FunctionKind::Constructor(id) => {
2761 name.push_str("constructor-");
2762 name.push_str(resolve.types[id].name.as_ref().unwrap());
2763 name.push_str("-");
2764 }
2765 FunctionKind::Freestanding => {}
2766 }
2767 name.push_str(func.item_name());
2768 name.to_snake_case()
2769}
2770
2771fn get_resources<'a>(resolve: &'a Resolve, id: InterfaceId) -> impl Iterator<Item = &'a str> + 'a {
2772 resolve.interfaces[id]
2773 .types
2774 .iter()
2775 .filter_map(move |(name, ty)| match resolve.types[*ty].kind {
2776 TypeDefKind::Resource => Some(name.as_str()),
2777 _ => None,
2778 })
2779}
2780
2781fn get_world_resources<'a>(
2782 resolve: &'a Resolve,
2783 id: WorldId,
2784) -> impl Iterator<Item = &'a str> + 'a {
2785 resolve.worlds[id]
2786 .imports
2787 .iter()
2788 .filter_map(move |(name, item)| match item {
2789 WorldItem::Type(id) => match resolve.types[*id].kind {
2790 TypeDefKind::Resource => Some(match name {
2791 WorldKey::Name(s) => s.as_str(),
2792 WorldKey::Interface(_) => unreachable!(),
2793 }),
2794 _ => None,
2795 },
2796 _ => None,
2797 })
2798}