wasmtime_internal_wit_bindgen/
lib.rs

1//! > **⚠️ Warning ⚠️**: this crate is an internal-only crate for the Wasmtime
2//! > project and is not intended for general use. APIs are not strictly
3//! > reviewed for safety and usage outside of Wasmtime may have bugs. If
4//! > you're interested in using this feel free to file an issue on the
5//! > Wasmtime repository to start a discussion about doing so, but otherwise
6//! > be aware that your usage of this crate is not supported.
7
8use crate::rust::{RustGenerator, TypeMode, to_rust_ident, to_rust_upper_camel_case};
9use crate::types::{TypeInfo, Types};
10use anyhow::bail;
11use heck::*;
12use indexmap::{IndexMap, IndexSet};
13use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
14use std::fmt::Write as _;
15use std::io::{Read, Write};
16use std::mem;
17use std::process::{Command, Stdio};
18use wit_parser::*;
19
20macro_rules! uwrite {
21    ($dst:expr, $($arg:tt)*) => {
22        write!($dst, $($arg)*).unwrap()
23    };
24}
25
26macro_rules! uwriteln {
27    ($dst:expr, $($arg:tt)*) => {
28        writeln!($dst, $($arg)*).unwrap()
29    };
30}
31
32mod config;
33mod rust;
34mod source;
35mod types;
36
37pub use config::{FunctionConfig, FunctionFilter, FunctionFlags};
38use source::Source;
39
40#[derive(Clone)]
41enum InterfaceName {
42    /// This interface was remapped using `with` to some other Rust code.
43    Remapped {
44        /// This is the `::`-separated string which is the path to the mapped
45        /// item relative to the root of the `bindgen!` macro invocation.
46        ///
47        /// This path currently starts with `__with_name$N` and will then
48        /// optionally have `::` projections through to the actual item
49        /// depending on how `with` was configured.
50        name_at_root: String,
51
52        /// This is currently only used for exports and is the relative path to
53        /// where this mapped name would be located if `with` were not
54        /// specified. Basically it's the same as the `Path` variant of this
55        /// enum if the mapping weren't present.
56        local_path: Vec<String>,
57    },
58
59    /// This interface is generated in the module hierarchy specified.
60    ///
61    /// The path listed here is the path, from the root of the `bindgen!` macro,
62    /// to where this interface is generated.
63    Path(Vec<String>),
64}
65
66#[derive(Default)]
67struct Wasmtime {
68    src: Source,
69    opts: Opts,
70    /// A list of all interfaces which were imported by this world.
71    import_interfaces: Vec<ImportInterface>,
72    import_functions: Vec<Function>,
73    exports: Exports,
74    types: Types,
75    sizes: SizeAlign,
76    interface_names: HashMap<InterfaceId, InterfaceName>,
77    interface_last_seen_as_import: HashMap<InterfaceId, bool>,
78    trappable_errors: IndexMap<TypeId, String>,
79    // Track the with options that were used. Remapped interfaces provided via `with`
80    // are required to be used.
81    used_with_opts: HashSet<String>,
82    world_link_options: LinkOptionsBuilder,
83    interface_link_options: HashMap<InterfaceId, LinkOptionsBuilder>,
84}
85
86struct ImportInterface {
87    id: InterfaceId,
88    contents: String,
89    name: InterfaceName,
90    all_func_flags: FunctionFlags,
91}
92
93#[derive(Default)]
94struct Exports {
95    fields: BTreeMap<String, ExportField>,
96    modules: Vec<(InterfaceId, String, InterfaceName)>,
97    funcs: Vec<String>,
98}
99
100struct ExportField {
101    ty: String,
102    ty_index: String,
103    load: String,
104    get_index: String,
105}
106
107#[derive(Default, Debug, Clone, Copy)]
108pub enum Ownership {
109    /// Generated types will be composed entirely of owning fields, regardless
110    /// of whether they are used as parameters to guest exports or not.
111    #[default]
112    Owning,
113
114    /// Generated types used as parameters to guest exports will be "deeply
115    /// borrowing", i.e. contain references rather than owned values when
116    /// applicable.
117    Borrowing {
118        /// Whether or not to generate "duplicate" type definitions for a single
119        /// WIT type if necessary, for example if it's used as both an import
120        /// and an export, or if it's used both as a parameter to an export and
121        /// a return value from an export.
122        duplicate_if_necessary: bool,
123    },
124}
125
126#[derive(Default, Debug, Clone)]
127pub struct Opts {
128    /// Whether or not `rustfmt` is executed to format generated code.
129    pub rustfmt: bool,
130
131    /// A list of "trappable errors" which are used to replace the `E` in
132    /// `result<T, E>` found in WIT.
133    pub trappable_error_type: Vec<TrappableError>,
134
135    /// Whether to generate owning or borrowing type definitions.
136    pub ownership: Ownership,
137
138    /// Whether or not to generate code for only the interfaces of this wit file or not.
139    pub only_interfaces: bool,
140
141    /// Remapping of interface names to rust module names.
142    /// TODO: is there a better type to use for the value of this map?
143    pub with: HashMap<String, String>,
144
145    /// Additional derive attributes to add to generated types. If using in a CLI, this flag can be
146    /// specified multiple times to add multiple attributes.
147    ///
148    /// These derive attributes will be added to any generated structs or enums
149    pub additional_derive_attributes: Vec<String>,
150
151    /// Evaluate to a string literal containing the generated code rather than the generated tokens
152    /// themselves. Mostly useful for Wasmtime internal debugging and development.
153    pub stringify: bool,
154
155    /// Temporary option to skip `impl<T: Trait> Trait for &mut T` for the
156    /// `wasmtime-wasi` crate while that's given a chance to update its b
157    /// indings.
158    pub skip_mut_forwarding_impls: bool,
159
160    /// Indicates that the `T` in `Store<T>` should be send even if async is not
161    /// enabled.
162    ///
163    /// This is helpful when sync bindings depend on generated functions from
164    /// async bindings as is the case with WASI in-tree.
165    pub require_store_data_send: bool,
166
167    /// Path to the `wasmtime` crate if it's not the default path.
168    pub wasmtime_crate: Option<String>,
169
170    /// If true, write the generated bindings to a file for better error
171    /// messages from `rustc`.
172    ///
173    /// This can also be toggled via the `WASMTIME_DEBUG_BINDGEN` environment
174    /// variable, but that will affect _all_ `bindgen!` macro invocations (and
175    /// can sometimes lead to one invocation overwriting another in unpredictable
176    /// ways), whereas this option lets you specify it on a case-by-case basis.
177    pub debug: bool,
178
179    /// TODO
180    pub imports: FunctionConfig,
181    /// TODO
182    pub exports: FunctionConfig,
183}
184
185#[derive(Debug, Clone)]
186pub struct TrappableError {
187    /// Full path to the error, such as `wasi:io/streams.error`.
188    pub wit_path: String,
189
190    /// The name, in Rust, of the error type to generate.
191    pub rust_type_name: String,
192}
193
194impl Opts {
195    pub fn generate(&self, resolve: &Resolve, world: WorldId) -> anyhow::Result<String> {
196        // TODO: Should we refine this test to inspect only types reachable from
197        // the specified world?
198        if !cfg!(feature = "component-model-async")
199            && resolve
200                .types
201                .iter()
202                .any(|(_, ty)| matches!(ty.kind, TypeDefKind::Future(_) | TypeDefKind::Stream(_)))
203        {
204            anyhow::bail!(
205                "must enable `component-model-async` feature when using WIT files \
206                 containing future, stream, or error-context types"
207            );
208        }
209
210        let mut r = Wasmtime::default();
211        r.sizes.fill(resolve);
212        r.opts = self.clone();
213        r.populate_world_and_interface_options(resolve, world);
214        r.generate(resolve, world)
215    }
216}
217
218impl Wasmtime {
219    fn populate_world_and_interface_options(&mut self, resolve: &Resolve, world: WorldId) {
220        self.world_link_options.add_world(resolve, &world);
221
222        for (_, import) in resolve.worlds[world].imports.iter() {
223            match import {
224                WorldItem::Interface { id, .. } => {
225                    let mut o = LinkOptionsBuilder::default();
226                    o.add_interface(resolve, id);
227                    self.interface_link_options.insert(*id, o);
228                }
229                WorldItem::Function(_) | WorldItem::Type(_) => {}
230            }
231        }
232    }
233    fn name_interface(
234        &mut self,
235        resolve: &Resolve,
236        id: InterfaceId,
237        name: &WorldKey,
238        is_export: bool,
239    ) -> bool {
240        let mut path = Vec::new();
241        if is_export {
242            path.push("exports".to_string());
243        }
244        match name {
245            WorldKey::Name(name) => {
246                path.push(name.to_snake_case());
247            }
248            WorldKey::Interface(_) => {
249                let iface = &resolve.interfaces[id];
250                let pkgname = &resolve.packages[iface.package.unwrap()].name;
251                path.push(pkgname.namespace.to_snake_case());
252                path.push(self.name_package_module(resolve, iface.package.unwrap()));
253                path.push(to_rust_ident(iface.name.as_ref().unwrap()));
254            }
255        }
256        let entry = if let Some(name_at_root) = self.lookup_replacement(resolve, name, None) {
257            InterfaceName::Remapped {
258                name_at_root,
259                local_path: path,
260            }
261        } else {
262            InterfaceName::Path(path)
263        };
264
265        let remapped = matches!(entry, InterfaceName::Remapped { .. });
266        self.interface_names.insert(id, entry);
267        remapped
268    }
269
270    /// If the package `id` is the only package with its namespace/name combo
271    /// then pass through the name unmodified. If, however, there are multiple
272    /// versions of this package then the package module is going to get version
273    /// information.
274    fn name_package_module(&self, resolve: &Resolve, id: PackageId) -> String {
275        let pkg = &resolve.packages[id];
276        let versions_with_same_name = resolve
277            .packages
278            .iter()
279            .filter_map(|(_, p)| {
280                if p.name.namespace == pkg.name.namespace && p.name.name == pkg.name.name {
281                    Some(&p.name.version)
282                } else {
283                    None
284                }
285            })
286            .collect::<Vec<_>>();
287        let base = pkg.name.name.to_snake_case();
288        if versions_with_same_name.len() == 1 {
289            return base;
290        }
291
292        let version = match &pkg.name.version {
293            Some(version) => version,
294            // If this package didn't have a version then don't mangle its name
295            // and other packages with the same name but with versions present
296            // will have their names mangled.
297            None => return base,
298        };
299
300        // Here there's multiple packages with the same name that differ only in
301        // version, so the version needs to be mangled into the Rust module name
302        // that we're generating. This in theory could look at all of
303        // `versions_with_same_name` and produce a minimal diff, e.g. for 0.1.0
304        // and 0.2.0 this could generate "foo1" and "foo2", but for now
305        // a simpler path is chosen to generate "foo0_1_0" and "foo0_2_0".
306        let version = version
307            .to_string()
308            .replace('.', "_")
309            .replace('-', "_")
310            .replace('+', "_")
311            .to_snake_case();
312        format!("{base}{version}")
313    }
314
315    fn generate(&mut self, resolve: &Resolve, id: WorldId) -> anyhow::Result<String> {
316        self.types.analyze(resolve, id);
317
318        self.world_link_options.write_struct(&mut self.src);
319
320        // Resolve the `trappable_error_type` configuration values to `TypeId`
321        // values. This is done by iterating over each `trappable_error_type`
322        // and then locating the interface that it corresponds to as well as the
323        // type within that interface.
324        //
325        // Note that `LookupItem::InterfaceNoPop` is used here as the full
326        // hierarchical behavior of `lookup_keys` isn't used as the interface
327        // must be named here.
328        'outer: for (i, te) in self.opts.trappable_error_type.iter().enumerate() {
329            let error_name = format!("_TrappableError{i}");
330            for (id, iface) in resolve.interfaces.iter() {
331                for (key, projection) in lookup_keys(
332                    resolve,
333                    &WorldKey::Interface(id),
334                    LookupItem::InterfaceNoPop,
335                ) {
336                    assert!(projection.is_empty());
337
338                    // If `wit_path` looks like `{key}.{type_name}` where
339                    // `type_name` is a type within `iface` then we've found a
340                    // match. Otherwise continue to the next lookup key if there
341                    // is one, and failing that continue to the next interface.
342                    let suffix = match te.wit_path.strip_prefix(&key) {
343                        Some(s) => s,
344                        None => continue,
345                    };
346                    let suffix = match suffix.strip_prefix('.') {
347                        Some(s) => s,
348                        None => continue,
349                    };
350                    if let Some(id) = iface.types.get(suffix) {
351                        uwriteln!(self.src, "type {error_name} = {};", te.rust_type_name);
352                        let prev = self.trappable_errors.insert(*id, error_name);
353                        assert!(prev.is_none());
354                        continue 'outer;
355                    }
356                }
357            }
358
359            bail!(
360                "failed to locate a WIT error type corresponding to the \
361                 `trappable_error_type` name `{}` provided",
362                te.wit_path
363            )
364        }
365
366        // Convert all entries in `with` as relative to the root of where the
367        // macro itself is invoked. This emits a `pub use` to bring the name
368        // into scope under an "anonymous name" which then replaces the `with`
369        // map entry.
370        let mut with = self.opts.with.iter_mut().collect::<Vec<_>>();
371        with.sort();
372        for (i, (_k, v)) in with.into_iter().enumerate() {
373            let name = format!("__with_name{i}");
374            uwriteln!(self.src, "#[doc(hidden)]\npub use {v} as {name};");
375            *v = name;
376        }
377
378        let world = &resolve.worlds[id];
379        for (name, import) in world.imports.iter() {
380            if !self.opts.only_interfaces || matches!(import, WorldItem::Interface { .. }) {
381                self.import(resolve, name, import);
382            }
383        }
384
385        for (name, export) in world.exports.iter() {
386            if !self.opts.only_interfaces || matches!(export, WorldItem::Interface { .. }) {
387                self.export(resolve, name, export);
388            }
389        }
390        self.finish(resolve, id)
391    }
392
393    fn import(&mut self, resolve: &Resolve, name: &WorldKey, item: &WorldItem) {
394        let mut generator = InterfaceGenerator::new(self, resolve);
395        match item {
396            WorldItem::Function(func) => {
397                self.import_functions.push(func.clone());
398            }
399            WorldItem::Interface { id, .. } => {
400                generator
401                    .generator
402                    .interface_last_seen_as_import
403                    .insert(*id, true);
404                generator.current_interface = Some((*id, name, false));
405                let snake = to_rust_ident(&match name {
406                    WorldKey::Name(s) => s.to_snake_case(),
407                    WorldKey::Interface(id) => resolve.interfaces[*id]
408                        .name
409                        .as_ref()
410                        .unwrap()
411                        .to_snake_case(),
412                });
413                let module = if generator
414                    .generator
415                    .name_interface(resolve, *id, name, false)
416                {
417                    // If this interface is remapped then that means that it was
418                    // provided via the `with` key in the bindgen configuration.
419                    // That means that bindings generation is skipped here. To
420                    // accommodate future bindgens depending on this bindgen
421                    // though we still generate a module which reexports the
422                    // original module. This helps maintain the same output
423                    // structure regardless of whether `with` is used.
424                    let name_at_root = match &generator.generator.interface_names[id] {
425                        InterfaceName::Remapped { name_at_root, .. } => name_at_root,
426                        InterfaceName::Path(_) => unreachable!(),
427                    };
428                    let path_to_root = generator.path_to_root();
429                    format!(
430                        "
431                            pub mod {snake} {{
432                                #[allow(unused_imports)]
433                                pub use {path_to_root}{name_at_root}::*;
434                            }}
435                        "
436                    )
437                } else {
438                    // If this interface is not remapped then it's time to
439                    // actually generate bindings here.
440                    generator.generator.interface_link_options[id].write_struct(&mut generator.src);
441                    generator.types(*id);
442                    let key_name = resolve.name_world_key(name);
443                    generator.generate_add_to_linker(*id, &key_name);
444
445                    let module = &generator.src[..];
446                    let wt = generator.generator.wasmtime_path();
447
448                    format!(
449                        "
450                            #[allow(clippy::all)]
451                            pub mod {snake} {{
452                                #[allow(unused_imports)]
453                                use {wt}::component::__internal::{{anyhow, Box}};
454
455                                {module}
456                            }}
457                        "
458                    )
459                };
460                let all_func_flags = generator.all_func_flags;
461                self.import_interfaces.push(ImportInterface {
462                    id: *id,
463                    contents: module,
464                    name: self.interface_names[id].clone(),
465                    all_func_flags,
466                });
467
468                let interface_path = self.import_interface_path(id);
469                self.interface_link_options[id]
470                    .write_impl_from_world(&mut self.src, &interface_path);
471            }
472            WorldItem::Type(ty) => {
473                let name = match name {
474                    WorldKey::Name(name) => name,
475                    WorldKey::Interface(_) => unreachable!(),
476                };
477                generator.define_type(name, *ty);
478                let body = mem::take(&mut generator.src);
479                self.src.push_str(&body);
480            }
481        };
482    }
483
484    fn export(&mut self, resolve: &Resolve, name: &WorldKey, item: &WorldItem) {
485        let wt = self.wasmtime_path();
486        let mut generator = InterfaceGenerator::new(self, resolve);
487        let field;
488        let ty;
489        let ty_index;
490        let load;
491        let get_index;
492        match item {
493            WorldItem::Function(func) => {
494                generator.define_rust_guest_export(resolve, None, func);
495                let body = mem::take(&mut generator.src).into();
496                load = generator.extract_typed_function(func).1;
497                assert!(generator.src.is_empty());
498                generator.generator.exports.funcs.push(body);
499                ty_index = format!("{wt}::component::ComponentExportIndex");
500                field = func_field_name(resolve, func);
501                ty = format!("{wt}::component::Func");
502                let sig = generator.typedfunc_sig(func, TypeMode::AllBorrowed("'_"));
503                let typecheck = format!(
504                    "match item {{
505                            {wt}::component::types::ComponentItem::ComponentFunc(func) => {{
506                                anyhow::Context::context(
507                                    func.typecheck::<{sig}>(&_instance_type),
508                                    \"type-checking export func `{0}`\"
509                                )?;
510                                index
511                            }}
512                            _ => Err(anyhow::anyhow!(\"export `{0}` is not a function\"))?,
513                        }}",
514                    func.name
515                );
516                get_index = format!(
517                    "{{ let (item, index) = _component.get_export(None, \"{}\")
518                        .ok_or_else(|| anyhow::anyhow!(\"no export `{0}` found\"))?;
519                        {typecheck}
520                     }}",
521                    func.name
522                );
523            }
524            WorldItem::Type(_) => unreachable!(),
525            WorldItem::Interface { id, .. } => {
526                generator
527                    .generator
528                    .interface_last_seen_as_import
529                    .insert(*id, false);
530                generator.generator.name_interface(resolve, *id, name, true);
531                generator.current_interface = Some((*id, name, true));
532                generator.types(*id);
533                let struct_name = "Guest";
534                let iface = &resolve.interfaces[*id];
535                let iface_name = match name {
536                    WorldKey::Name(name) => name,
537                    WorldKey::Interface(_) => iface.name.as_ref().unwrap(),
538                };
539                uwriteln!(generator.src, "#[derive(Clone)]");
540                uwriteln!(generator.src, "pub struct {struct_name} {{");
541                for (_, func) in iface.functions.iter() {
542                    uwriteln!(
543                        generator.src,
544                        "{}: {wt}::component::Func,",
545                        func_field_name(resolve, func)
546                    );
547                }
548                uwriteln!(generator.src, "}}");
549
550                uwriteln!(generator.src, "#[derive(Clone)]");
551                uwriteln!(generator.src, "pub struct {struct_name}Indices {{");
552                for (_, func) in iface.functions.iter() {
553                    uwriteln!(
554                        generator.src,
555                        "{}: {wt}::component::ComponentExportIndex,",
556                        func_field_name(resolve, func)
557                    );
558                }
559                uwriteln!(generator.src, "}}");
560
561                uwriteln!(generator.src, "impl {struct_name}Indices {{");
562                let instance_name = resolve.name_world_key(name);
563                uwrite!(
564                    generator.src,
565                    "
566/// Constructor for [`{struct_name}Indices`] which takes a
567/// [`Component`]({wt}::component::Component) as input and can be executed
568/// before instantiation.
569///
570/// This constructor can be used to front-load string lookups to find exports
571/// within a component.
572pub fn new<_T>(
573    _instance_pre: &{wt}::component::InstancePre<_T>,
574) -> {wt}::Result<{struct_name}Indices> {{
575    let instance = _instance_pre.component().get_export_index(None, \"{instance_name}\")
576        .ok_or_else(|| anyhow::anyhow!(\"no exported instance named `{instance_name}`\"))?;
577    let mut lookup = move |name| {{
578        _instance_pre.component().get_export_index(Some(&instance), name).ok_or_else(|| {{
579            anyhow::anyhow!(
580                \"instance export `{instance_name}` does \\
581                  not have export `{{name}}`\"
582            )
583        }})
584    }};
585    let _ = &mut lookup;
586                    "
587                );
588                let mut fields = Vec::new();
589                for (_, func) in iface.functions.iter() {
590                    let name = func_field_name(resolve, func);
591                    uwriteln!(generator.src, "let {name} = lookup(\"{}\")?;", func.name);
592                    fields.push(name);
593                }
594                uwriteln!(generator.src, "Ok({struct_name}Indices {{");
595                for name in fields {
596                    uwriteln!(generator.src, "{name},");
597                }
598                uwriteln!(generator.src, "}})");
599                uwriteln!(generator.src, "}}"); // end `fn _new`
600
601                uwrite!(
602                    generator.src,
603                    "
604                        pub fn load(
605                            &self,
606                            mut store: impl {wt}::AsContextMut,
607                            instance: &{wt}::component::Instance,
608                        ) -> {wt}::Result<{struct_name}> {{
609                            let _instance = instance;
610                            let _instance_pre = _instance.instance_pre(&store);
611                            let _instance_type = _instance_pre.instance_type();
612                            let mut store = store.as_context_mut();
613                            let _ = &mut store;
614                    "
615                );
616                let mut fields = Vec::new();
617                for (_, func) in iface.functions.iter() {
618                    let (name, getter) = generator.extract_typed_function(func);
619                    uwriteln!(generator.src, "let {name} = {getter};");
620                    fields.push(name);
621                }
622                uwriteln!(generator.src, "Ok({struct_name} {{");
623                for name in fields {
624                    uwriteln!(generator.src, "{name},");
625                }
626                uwriteln!(generator.src, "}})");
627                uwriteln!(generator.src, "}}"); // end `fn new`
628                uwriteln!(generator.src, "}}"); // end `impl {struct_name}Indices`
629
630                uwriteln!(generator.src, "impl {struct_name} {{");
631                let mut resource_methods = IndexMap::new();
632
633                for (_, func) in iface.functions.iter() {
634                    match func.kind.resource() {
635                        None => {
636                            generator.define_rust_guest_export(resolve, Some(name), func);
637                        }
638                        Some(id) => {
639                            resource_methods.entry(id).or_insert(Vec::new()).push(func);
640                        }
641                    }
642                }
643
644                for (id, _) in resource_methods.iter() {
645                    let name = resolve.types[*id].name.as_ref().unwrap();
646                    let snake = name.to_snake_case();
647                    let camel = name.to_upper_camel_case();
648                    uwriteln!(
649                        generator.src,
650                        "pub fn {snake}(&self) -> Guest{camel}<'_> {{
651                            Guest{camel} {{ funcs: self }}
652                        }}"
653                    );
654                }
655
656                uwriteln!(generator.src, "}}");
657
658                for (id, methods) in resource_methods {
659                    let resource_name = resolve.types[id].name.as_ref().unwrap();
660                    let camel = resource_name.to_upper_camel_case();
661                    uwriteln!(generator.src, "impl Guest{camel}<'_> {{");
662                    for method in methods {
663                        generator.define_rust_guest_export(resolve, Some(name), method);
664                    }
665                    uwriteln!(generator.src, "}}");
666                }
667
668                let module = &generator.src[..];
669                let snake = to_rust_ident(iface_name);
670
671                let module = format!(
672                    "
673                        #[allow(clippy::all)]
674                        pub mod {snake} {{
675                            #[allow(unused_imports)]
676                            use {wt}::component::__internal::{{anyhow, Box}};
677
678                            {module}
679                        }}
680                    "
681                );
682                let pkgname = match name {
683                    WorldKey::Name(_) => None,
684                    WorldKey::Interface(_) => {
685                        Some(resolve.packages[iface.package.unwrap()].name.clone())
686                    }
687                };
688                self.exports
689                    .modules
690                    .push((*id, module, self.interface_names[id].clone()));
691
692                let (path, method_name) = match pkgname {
693                    Some(pkgname) => (
694                        format!(
695                            "exports::{}::{}::{snake}::{struct_name}",
696                            pkgname.namespace.to_snake_case(),
697                            self.name_package_module(resolve, iface.package.unwrap()),
698                        ),
699                        format!(
700                            "{}_{}_{snake}",
701                            pkgname.namespace.to_snake_case(),
702                            self.name_package_module(resolve, iface.package.unwrap())
703                        ),
704                    ),
705                    None => (format!("exports::{snake}::{struct_name}"), snake.clone()),
706                };
707                field = format!("interface{}", self.exports.fields.len());
708                load = format!("self.{field}.load(&mut store, &_instance)?");
709                self.exports.funcs.push(format!(
710                    "
711                        pub fn {method_name}(&self) -> &{path} {{
712                            &self.{field}
713                        }}
714                    ",
715                ));
716                ty_index = format!("{path}Indices");
717                ty = path;
718                get_index = format!("{ty_index}::new(_instance_pre)?");
719            }
720        }
721        let prev = self.exports.fields.insert(
722            field,
723            ExportField {
724                ty,
725                ty_index,
726                load,
727                get_index,
728            },
729        );
730        assert!(prev.is_none());
731    }
732
733    fn build_world_struct(&mut self, resolve: &Resolve, world: WorldId) {
734        let wt = self.wasmtime_path();
735        let world_name = &resolve.worlds[world].name;
736        let camel = to_rust_upper_camel_case(&world_name);
737        uwriteln!(
738            self.src,
739            "
740/// Auto-generated bindings for a pre-instantiated version of a
741/// component which implements the world `{world_name}`.
742///
743/// This structure is created through [`{camel}Pre::new`] which
744/// takes a [`InstancePre`]({wt}::component::InstancePre) that
745/// has been created through a [`Linker`]({wt}::component::Linker).
746///
747/// For more information see [`{camel}`] as well.
748pub struct {camel}Pre<T: 'static> {{
749    instance_pre: {wt}::component::InstancePre<T>,
750    indices: {camel}Indices,
751}}
752
753impl<T: 'static> Clone for {camel}Pre<T> {{
754    fn clone(&self) -> Self {{
755        Self {{
756            instance_pre: self.instance_pre.clone(),
757            indices: self.indices.clone(),
758        }}
759    }}
760}}
761
762impl<_T: 'static> {camel}Pre<_T> {{
763    /// Creates a new copy of `{camel}Pre` bindings which can then
764    /// be used to instantiate into a particular store.
765    ///
766    /// This method may fail if the component behind `instance_pre`
767    /// does not have the required exports.
768    pub fn new(instance_pre: {wt}::component::InstancePre<_T>) -> {wt}::Result<Self> {{
769        let indices = {camel}Indices::new(&instance_pre)?;
770        Ok(Self {{ instance_pre, indices }})
771    }}
772
773    pub fn engine(&self) -> &{wt}::Engine {{
774        self.instance_pre.engine()
775    }}
776
777    pub fn instance_pre(&self) -> &{wt}::component::InstancePre<_T> {{
778        &self.instance_pre
779    }}
780
781    /// Instantiates a new instance of [`{camel}`] within the
782    /// `store` provided.
783    ///
784    /// This function will use `self` as the pre-instantiated
785    /// instance to perform instantiation. Afterwards the preloaded
786    /// indices in `self` are used to lookup all exports on the
787    /// resulting instance.
788    pub fn instantiate(
789        &self,
790        mut store: impl {wt}::AsContextMut<Data = _T>,
791    ) -> {wt}::Result<{camel}> {{
792        let mut store = store.as_context_mut();
793        let instance = self.instance_pre.instantiate(&mut store)?;
794        self.indices.load(&mut store, &instance)
795    }}
796}}
797"
798        );
799
800        if cfg!(feature = "async") {
801            uwriteln!(
802                self.src,
803                "
804impl<_T: Send + 'static> {camel}Pre<_T> {{
805    /// Same as [`Self::instantiate`], except with `async`.
806    pub async fn instantiate_async(
807        &self,
808        mut store: impl {wt}::AsContextMut<Data = _T>,
809    ) -> {wt}::Result<{camel}> {{
810        let mut store = store.as_context_mut();
811        let instance = self.instance_pre.instantiate_async(&mut store).await?;
812        self.indices.load(&mut store, &instance)
813    }}
814}}
815"
816            );
817        }
818
819        uwriteln!(
820            self.src,
821            "
822            /// Auto-generated bindings for index of the exports of
823            /// `{world_name}`.
824            ///
825            /// This is an implementation detail of [`{camel}Pre`] and can
826            /// be constructed if needed as well.
827            ///
828            /// For more information see [`{camel}`] as well.
829            #[derive(Clone)]
830            pub struct {camel}Indices {{"
831        );
832        for (name, field) in self.exports.fields.iter() {
833            uwriteln!(self.src, "{name}: {},", field.ty_index);
834        }
835        self.src.push_str("}\n");
836
837        uwriteln!(
838            self.src,
839            "
840                /// Auto-generated bindings for an instance a component which
841                /// implements the world `{world_name}`.
842                ///
843                /// This structure can be created through a number of means
844                /// depending on your requirements and what you have on hand:
845                ///
846                /// * The most convenient way is to use
847                ///   [`{camel}::instantiate`] which only needs a
848                ///   [`Store`], [`Component`], and [`Linker`].
849                ///
850                /// * Alternatively you can create a [`{camel}Pre`] ahead of
851                ///   time with a [`Component`] to front-load string lookups
852                ///   of exports once instead of per-instantiation. This
853                ///   method then uses [`{camel}Pre::instantiate`] to
854                ///   create a [`{camel}`].
855                ///
856                /// * If you've instantiated the instance yourself already
857                ///   then you can use [`{camel}::new`].
858                ///
859                /// These methods are all equivalent to one another and move
860                /// around the tradeoff of what work is performed when.
861                ///
862                /// [`Store`]: {wt}::Store
863                /// [`Component`]: {wt}::component::Component
864                /// [`Linker`]: {wt}::component::Linker
865                pub struct {camel} {{"
866        );
867        for (name, field) in self.exports.fields.iter() {
868            uwriteln!(self.src, "{name}: {},", field.ty);
869        }
870        self.src.push_str("}\n");
871
872        let world_trait = self.world_imports_trait(resolve, world);
873
874        uwriteln!(self.src, "const _: () = {{");
875        uwriteln!(
876            self.src,
877            "
878                #[allow(unused_imports)]
879                use {wt}::component::__internal::anyhow;
880            "
881        );
882
883        uwriteln!(
884            self.src,
885            "impl {camel}Indices {{
886                /// Creates a new copy of `{camel}Indices` bindings which can then
887                /// be used to instantiate into a particular store.
888                ///
889                /// This method may fail if the component does not have the
890                /// required exports.
891                pub fn new<_T>(_instance_pre: &{wt}::component::InstancePre<_T>) -> {wt}::Result<Self> {{
892                    let _component = _instance_pre.component();
893                    let _instance_type = _instance_pre.instance_type();
894            ",
895        );
896        for (name, field) in self.exports.fields.iter() {
897            uwriteln!(self.src, "let {name} = {};", field.get_index);
898        }
899        uwriteln!(self.src, "Ok({camel}Indices {{");
900        for (name, _) in self.exports.fields.iter() {
901            uwriteln!(self.src, "{name},");
902        }
903        uwriteln!(self.src, "}})");
904        uwriteln!(self.src, "}}"); // close `fn new`
905
906        uwriteln!(
907            self.src,
908            "
909                /// Uses the indices stored in `self` to load an instance
910                /// of [`{camel}`] from the instance provided.
911                ///
912                /// Note that at this time this method will additionally
913                /// perform type-checks of all exports.
914                pub fn load(
915                    &self,
916                    mut store: impl {wt}::AsContextMut,
917                    instance: &{wt}::component::Instance,
918                ) -> {wt}::Result<{camel}> {{
919                    let _ = &mut store;
920                    let _instance = instance;
921            ",
922        );
923        for (name, field) in self.exports.fields.iter() {
924            uwriteln!(self.src, "let {name} = {};", field.load);
925        }
926        uwriteln!(self.src, "Ok({camel} {{");
927        for (name, _) in self.exports.fields.iter() {
928            uwriteln!(self.src, "{name},");
929        }
930        uwriteln!(self.src, "}})");
931        uwriteln!(self.src, "}}"); // close `fn load`
932        uwriteln!(self.src, "}}"); // close `impl {camel}Indices`
933
934        uwriteln!(
935            self.src,
936            "impl {camel} {{
937                /// Convenience wrapper around [`{camel}Pre::new`] and
938                /// [`{camel}Pre::instantiate`].
939                pub fn instantiate<_T>(
940                    store: impl {wt}::AsContextMut<Data = _T>,
941                    component: &{wt}::component::Component,
942                    linker: &{wt}::component::Linker<_T>,
943                ) -> {wt}::Result<{camel}> {{
944                    let pre = linker.instantiate_pre(component)?;
945                    {camel}Pre::new(pre)?.instantiate(store)
946                }}
947
948                /// Convenience wrapper around [`{camel}Indices::new`] and
949                /// [`{camel}Indices::load`].
950                pub fn new(
951                    mut store: impl {wt}::AsContextMut,
952                    instance: &{wt}::component::Instance,
953                ) -> {wt}::Result<{camel}> {{
954                    let indices = {camel}Indices::new(&instance.instance_pre(&store))?;
955                    indices.load(&mut store, instance)
956                }}
957            ",
958        );
959
960        if cfg!(feature = "async") {
961            uwriteln!(
962                self.src,
963                "
964                    /// Convenience wrapper around [`{camel}Pre::new`] and
965                    /// [`{camel}Pre::instantiate_async`].
966                    pub async fn instantiate_async<_T>(
967                        store: impl {wt}::AsContextMut<Data = _T>,
968                        component: &{wt}::component::Component,
969                        linker: &{wt}::component::Linker<_T>,
970                    ) -> {wt}::Result<{camel}>
971                        where _T: Send,
972                    {{
973                        let pre = linker.instantiate_pre(component)?;
974                        {camel}Pre::new(pre)?.instantiate_async(store).await
975                    }}
976                ",
977            );
978        }
979        self.world_add_to_linker(resolve, world, world_trait.as_ref());
980
981        for func in self.exports.funcs.iter() {
982            self.src.push_str(func);
983        }
984
985        uwriteln!(self.src, "}}"); // close `impl {camel}`
986
987        uwriteln!(self.src, "}};"); // close `const _: () = ...
988    }
989
990    fn finish(&mut self, resolve: &Resolve, world: WorldId) -> anyhow::Result<String> {
991        let remapping_keys = self.opts.with.keys().cloned().collect::<HashSet<String>>();
992
993        let mut unused_keys = remapping_keys
994            .difference(&self.used_with_opts)
995            .map(|s| s.as_str())
996            .collect::<Vec<&str>>();
997
998        unused_keys.sort();
999
1000        if !unused_keys.is_empty() {
1001            anyhow::bail!(
1002                "interfaces were specified in the `with` config option but are not referenced in the target world: {unused_keys:?}"
1003            );
1004        }
1005
1006        if !self.opts.only_interfaces {
1007            self.build_world_struct(resolve, world)
1008        }
1009
1010        self.opts.imports.assert_all_rules_used("imports")?;
1011        self.opts.exports.assert_all_rules_used("exports")?;
1012
1013        let imports = mem::take(&mut self.import_interfaces);
1014        self.emit_modules(
1015            imports
1016                .into_iter()
1017                .map(|i| (i.id, i.contents, i.name))
1018                .collect(),
1019        );
1020
1021        let exports = mem::take(&mut self.exports.modules);
1022        self.emit_modules(exports);
1023
1024        let mut src = mem::take(&mut self.src);
1025        if self.opts.rustfmt {
1026            let mut child = Command::new("rustfmt")
1027                .arg("--edition=2018")
1028                .stdin(Stdio::piped())
1029                .stdout(Stdio::piped())
1030                .spawn()
1031                .expect("failed to spawn `rustfmt`");
1032            child
1033                .stdin
1034                .take()
1035                .unwrap()
1036                .write_all(src.as_bytes())
1037                .unwrap();
1038            src.as_mut_string().truncate(0);
1039            child
1040                .stdout
1041                .take()
1042                .unwrap()
1043                .read_to_string(src.as_mut_string())
1044                .unwrap();
1045            let status = child.wait().unwrap();
1046            assert!(status.success());
1047        }
1048
1049        Ok(src.into())
1050    }
1051
1052    fn emit_modules(&mut self, modules: Vec<(InterfaceId, String, InterfaceName)>) {
1053        #[derive(Default)]
1054        struct Module {
1055            submodules: BTreeMap<String, Module>,
1056            contents: Vec<String>,
1057        }
1058        let mut map = Module::default();
1059        for (_, module, name) in modules {
1060            let path = match name {
1061                InterfaceName::Remapped { local_path, .. } => local_path,
1062                InterfaceName::Path(path) => path,
1063            };
1064            let mut cur = &mut map;
1065            for name in path[..path.len() - 1].iter() {
1066                cur = cur
1067                    .submodules
1068                    .entry(name.clone())
1069                    .or_insert(Module::default());
1070            }
1071            cur.contents.push(module);
1072        }
1073
1074        emit(&mut self.src, map);
1075
1076        fn emit(me: &mut Source, module: Module) {
1077            for (name, submodule) in module.submodules {
1078                uwriteln!(me, "pub mod {name} {{");
1079                emit(me, submodule);
1080                uwriteln!(me, "}}");
1081            }
1082            for submodule in module.contents {
1083                uwriteln!(me, "{submodule}");
1084            }
1085        }
1086    }
1087
1088    /// Attempts to find the `key`, possibly with the resource projection
1089    /// `item`, within the `with` map provided to bindings configuration.
1090    fn lookup_replacement(
1091        &mut self,
1092        resolve: &Resolve,
1093        key: &WorldKey,
1094        item: Option<&str>,
1095    ) -> Option<String> {
1096        let item = match item {
1097            Some(item) => LookupItem::Name(item),
1098            None => LookupItem::None,
1099        };
1100
1101        for (lookup, mut projection) in lookup_keys(resolve, key, item) {
1102            if let Some(renamed) = self.opts.with.get(&lookup) {
1103                projection.push(renamed.clone());
1104                projection.reverse();
1105                self.used_with_opts.insert(lookup);
1106                return Some(projection.join("::"));
1107            }
1108        }
1109
1110        None
1111    }
1112
1113    fn wasmtime_path(&self) -> String {
1114        self.opts
1115            .wasmtime_crate
1116            .clone()
1117            .unwrap_or("wasmtime".to_string())
1118    }
1119}
1120
1121enum LookupItem<'a> {
1122    None,
1123    Name(&'a str),
1124    InterfaceNoPop,
1125}
1126
1127fn lookup_keys(
1128    resolve: &Resolve,
1129    key: &WorldKey,
1130    item: LookupItem<'_>,
1131) -> Vec<(String, Vec<String>)> {
1132    struct Name<'a> {
1133        prefix: Prefix,
1134        item: Option<&'a str>,
1135    }
1136
1137    #[derive(Copy, Clone)]
1138    enum Prefix {
1139        Namespace(PackageId),
1140        UnversionedPackage(PackageId),
1141        VersionedPackage(PackageId),
1142        UnversionedInterface(InterfaceId),
1143        VersionedInterface(InterfaceId),
1144    }
1145
1146    let prefix = match key {
1147        WorldKey::Interface(id) => Prefix::VersionedInterface(*id),
1148
1149        // Non-interface-keyed names don't get the lookup logic below,
1150        // they're relatively uncommon so only lookup the precise key here.
1151        WorldKey::Name(key) => {
1152            let to_lookup = match item {
1153                LookupItem::Name(item) => format!("{key}.{item}"),
1154                LookupItem::None | LookupItem::InterfaceNoPop => key.to_string(),
1155            };
1156            return vec![(to_lookup, Vec::new())];
1157        }
1158    };
1159
1160    // Here names are iteratively attempted as `key` + `item` is "walked to
1161    // its root" and each attempt is consulted in `self.opts.with`. This
1162    // loop will start at the leaf, the most specific path, and then walk to
1163    // the root, popping items, trying to find a result.
1164    //
1165    // Each time a name is "popped" the projection from the next path is
1166    // pushed onto `projection`. This means that if we actually find a match
1167    // then `projection` is a collection of namespaces that results in the
1168    // final replacement name.
1169    let (interface_required, item) = match item {
1170        LookupItem::None => (false, None),
1171        LookupItem::Name(s) => (false, Some(s)),
1172        LookupItem::InterfaceNoPop => (true, None),
1173    };
1174    let mut name = Name { prefix, item };
1175    let mut projection = Vec::new();
1176    let mut ret = Vec::new();
1177    loop {
1178        let lookup = name.lookup_key(resolve);
1179        ret.push((lookup, projection.clone()));
1180        if !name.pop(resolve, &mut projection) {
1181            break;
1182        }
1183        if interface_required {
1184            match name.prefix {
1185                Prefix::VersionedInterface(_) | Prefix::UnversionedInterface(_) => {}
1186                _ => break,
1187            }
1188        }
1189    }
1190
1191    return ret;
1192
1193    impl<'a> Name<'a> {
1194        fn lookup_key(&self, resolve: &Resolve) -> String {
1195            let mut s = self.prefix.lookup_key(resolve);
1196            if let Some(item) = self.item {
1197                s.push_str(".");
1198                s.push_str(item);
1199            }
1200            s
1201        }
1202
1203        fn pop(&mut self, resolve: &'a Resolve, projection: &mut Vec<String>) -> bool {
1204            match (self.item, self.prefix) {
1205                // If this is a versioned resource name, try the unversioned
1206                // resource name next.
1207                (Some(_), Prefix::VersionedInterface(id)) => {
1208                    self.prefix = Prefix::UnversionedInterface(id);
1209                    true
1210                }
1211                // If this is an unversioned resource name then time to
1212                // ignore the resource itself and move on to the next most
1213                // specific item, versioned interface names.
1214                (Some(item), Prefix::UnversionedInterface(id)) => {
1215                    self.prefix = Prefix::VersionedInterface(id);
1216                    self.item = None;
1217                    projection.push(item.to_upper_camel_case());
1218                    true
1219                }
1220                (Some(_), _) => unreachable!(),
1221                (None, _) => self.prefix.pop(resolve, projection),
1222            }
1223        }
1224    }
1225
1226    impl Prefix {
1227        fn lookup_key(&self, resolve: &Resolve) -> String {
1228            match *self {
1229                Prefix::Namespace(id) => resolve.packages[id].name.namespace.clone(),
1230                Prefix::UnversionedPackage(id) => {
1231                    let mut name = resolve.packages[id].name.clone();
1232                    name.version = None;
1233                    name.to_string()
1234                }
1235                Prefix::VersionedPackage(id) => resolve.packages[id].name.to_string(),
1236                Prefix::UnversionedInterface(id) => {
1237                    let id = resolve.id_of(id).unwrap();
1238                    match id.find('@') {
1239                        Some(i) => id[..i].to_string(),
1240                        None => id,
1241                    }
1242                }
1243                Prefix::VersionedInterface(id) => resolve.id_of(id).unwrap(),
1244            }
1245        }
1246
1247        fn pop(&mut self, resolve: &Resolve, projection: &mut Vec<String>) -> bool {
1248            *self = match *self {
1249                // try the unversioned interface next
1250                Prefix::VersionedInterface(id) => Prefix::UnversionedInterface(id),
1251                // try this interface's versioned package next
1252                Prefix::UnversionedInterface(id) => {
1253                    let iface = &resolve.interfaces[id];
1254                    let name = iface.name.as_ref().unwrap();
1255                    projection.push(to_rust_ident(name));
1256                    Prefix::VersionedPackage(iface.package.unwrap())
1257                }
1258                // try the unversioned package next
1259                Prefix::VersionedPackage(id) => Prefix::UnversionedPackage(id),
1260                // try this package's namespace next
1261                Prefix::UnversionedPackage(id) => {
1262                    let name = &resolve.packages[id].name;
1263                    projection.push(to_rust_ident(&name.name));
1264                    Prefix::Namespace(id)
1265                }
1266                // nothing left to try any more
1267                Prefix::Namespace(_) => return false,
1268            };
1269            true
1270        }
1271    }
1272}
1273
1274impl Wasmtime {
1275    fn has_world_imports_trait(&self, resolve: &Resolve, world: WorldId) -> bool {
1276        !self.import_functions.is_empty() || get_world_resources(resolve, world).count() > 0
1277    }
1278
1279    fn world_imports_trait(&mut self, resolve: &Resolve, world: WorldId) -> Option<GeneratedTrait> {
1280        if !self.has_world_imports_trait(resolve, world) {
1281            return None;
1282        }
1283
1284        let world_camel = to_rust_upper_camel_case(&resolve.worlds[world].name);
1285
1286        let functions = self.import_functions.clone();
1287        let mut generator = InterfaceGenerator::new(self, resolve);
1288        let generated_trait = generator.generate_trait(
1289            &format!("{world_camel}Imports"),
1290            &functions
1291                .iter()
1292                .filter(|f| f.kind.resource().is_none())
1293                .collect::<Vec<_>>(),
1294            &[],
1295            &get_world_resources(resolve, world).collect::<Vec<_>>(),
1296        );
1297        let src = String::from(mem::take(&mut generator.src));
1298        self.src.push_str(&src);
1299        Some(generated_trait)
1300    }
1301
1302    fn import_interface_paths(&self) -> Vec<(InterfaceId, String)> {
1303        self.import_interfaces
1304            .iter()
1305            .map(|i| {
1306                let path = match &i.name {
1307                    InterfaceName::Path(path) => path.join("::"),
1308                    InterfaceName::Remapped { name_at_root, .. } => name_at_root.clone(),
1309                };
1310                (i.id, path)
1311            })
1312            .collect()
1313    }
1314
1315    fn import_interface_path(&self, id: &InterfaceId) -> String {
1316        match &self.interface_names[id] {
1317            InterfaceName::Path(path) => path.join("::"),
1318            InterfaceName::Remapped { name_at_root, .. } => name_at_root.clone(),
1319        }
1320    }
1321
1322    fn import_interface_all_func_flags(&self, id: InterfaceId) -> FunctionFlags {
1323        for i in self.import_interfaces.iter() {
1324            if id != i.id {
1325                continue;
1326            }
1327
1328            return i.all_func_flags;
1329        }
1330        unreachable!()
1331    }
1332
1333    fn world_host_traits(
1334        &self,
1335        world_trait: Option<&GeneratedTrait>,
1336    ) -> (Vec<String>, Vec<String>) {
1337        let mut without_store = Vec::new();
1338        let mut without_store_async = false;
1339        let mut with_store = Vec::new();
1340        let mut with_store_async = false;
1341        for (id, path) in self.import_interface_paths() {
1342            without_store.push(format!("{path}::Host"));
1343            let flags = self.import_interface_all_func_flags(id);
1344            without_store_async = without_store_async || flags.contains(FunctionFlags::ASYNC);
1345
1346            // Note that the requirement of `HostWithStore` is technically
1347            // dependent on `FunctionFlags::STORE`, but when `with` is in use we
1348            // don't necessarily know whether the other bindings generation
1349            // specified this flag or not. To handle that always assume that a
1350            // `HostWithStore` bound is needed.
1351            with_store.push(format!("{path}::HostWithStore"));
1352            with_store_async = with_store_async || flags.contains(FunctionFlags::ASYNC);
1353        }
1354        if let Some(world_trait) = world_trait {
1355            without_store.push(world_trait.name.clone());
1356            without_store_async =
1357                without_store_async || world_trait.all_func_flags.contains(FunctionFlags::ASYNC);
1358
1359            if world_trait.with_store_name.is_some() {
1360                with_store.extend(world_trait.with_store_name.clone());
1361                with_store_async =
1362                    with_store_async || world_trait.all_func_flags.contains(FunctionFlags::ASYNC);
1363            }
1364        }
1365        if without_store_async {
1366            without_store.push("Send".to_string());
1367        }
1368        if with_store_async {
1369            with_store.push("Send".to_string());
1370        }
1371        (without_store, with_store)
1372    }
1373
1374    fn world_add_to_linker(
1375        &mut self,
1376        resolve: &Resolve,
1377        world: WorldId,
1378        world_trait: Option<&GeneratedTrait>,
1379    ) {
1380        let has_world_imports_trait = self.has_world_imports_trait(resolve, world);
1381        if self.import_interfaces.is_empty() && !has_world_imports_trait {
1382            return;
1383        }
1384
1385        let (options_param, options_arg) = if self.world_link_options.has_any() {
1386            ("options: &LinkOptions,", ", options")
1387        } else {
1388            ("", "")
1389        };
1390
1391        let mut all_func_flags = FunctionFlags::empty();
1392        if let Some(world_trait) = world_trait {
1393            all_func_flags |= world_trait.all_func_flags;
1394        }
1395        for i in self.import_interfaces.iter() {
1396            all_func_flags |= i.all_func_flags;
1397        }
1398
1399        all_func_flags |= self.opts.imports.default;
1400        all_func_flags |= self.opts.exports.default;
1401
1402        let opt_t_send_bound =
1403            if all_func_flags.contains(FunctionFlags::ASYNC) || self.opts.require_store_data_send {
1404                "+ Send"
1405            } else {
1406                ""
1407            };
1408
1409        let wt = self.wasmtime_path();
1410        if let Some(world_trait) = world_trait {
1411            let d_bound = match &world_trait.with_store_name {
1412                Some(name) => name.clone(),
1413                None => format!("{wt}::component::HasData"),
1414            };
1415            uwrite!(
1416                self.src,
1417                "
1418                    pub fn add_to_linker_imports<T, D>(
1419                        linker: &mut {wt}::component::Linker<T>,
1420                        {options_param}
1421                        host_getter: fn(&mut T) -> D::Data<'_>,
1422                    ) -> {wt}::Result<()>
1423                        where
1424                            D: {d_bound},
1425                            for<'a> D::Data<'a>: {name},
1426                            T: 'static {opt_t_send_bound}
1427                    {{
1428                        let mut linker = linker.root();
1429                ",
1430                name = world_trait.name,
1431            );
1432            let gate = FeatureGate::open(&mut self.src, &resolve.worlds[world].stability);
1433            for (ty, _name) in get_world_resources(resolve, world) {
1434                self.generate_add_resource_to_linker(None, None, "linker", resolve, ty);
1435            }
1436            for f in self.import_functions.clone() {
1437                let mut generator = InterfaceGenerator::new(self, resolve);
1438                generator.generate_add_function_to_linker(TypeOwner::World(world), &f, "linker");
1439                let src = String::from(generator.src);
1440                self.src.push_str(&src);
1441                self.src.push_str("\n");
1442            }
1443            gate.close(&mut self.src);
1444            uwriteln!(self.src, "Ok(())\n}}");
1445        }
1446
1447        let (sync_bounds, concurrent_bounds) = self.world_host_traits(world_trait);
1448        let sync_bounds = sync_bounds.join(" + ");
1449        let concurrent_bounds = concurrent_bounds.join(" + ");
1450        let d_bounds = if !concurrent_bounds.is_empty() {
1451            concurrent_bounds
1452        } else {
1453            format!("{wt}::component::HasData")
1454        };
1455
1456        uwriteln!(
1457            self.src,
1458            "
1459                pub fn add_to_linker<T, D>(
1460                    linker: &mut {wt}::component::Linker<T>,
1461                    {options_param}
1462                    host_getter: fn(&mut T) -> D::Data<'_>,
1463                ) -> {wt}::Result<()>
1464                    where
1465                        D: {d_bounds},
1466                        for<'a> D::Data<'a>: {sync_bounds},
1467                        T: 'static {opt_t_send_bound}
1468                {{
1469            "
1470        );
1471        let gate = FeatureGate::open(&mut self.src, &resolve.worlds[world].stability);
1472        if has_world_imports_trait {
1473            uwriteln!(
1474                self.src,
1475                "Self::add_to_linker_imports::<T, D>(linker {options_arg}, host_getter)?;"
1476            );
1477        }
1478        for (interface_id, path) in self.import_interface_paths() {
1479            let options_arg = if self.interface_link_options[&interface_id].has_any() {
1480                ", &options.into()"
1481            } else {
1482                ""
1483            };
1484
1485            let import_stability = resolve.worlds[world]
1486                .imports
1487                .iter()
1488                .filter_map(|(_, i)| match i {
1489                    WorldItem::Interface { id, stability } if *id == interface_id => {
1490                        Some(stability.clone())
1491                    }
1492                    _ => None,
1493                })
1494                .next()
1495                .unwrap_or(Stability::Unknown);
1496
1497            let gate = FeatureGate::open(&mut self.src, &import_stability);
1498            uwriteln!(
1499                self.src,
1500                "{path}::add_to_linker::<T, D>(linker {options_arg}, host_getter)?;"
1501            );
1502            gate.close(&mut self.src);
1503        }
1504        gate.close(&mut self.src);
1505        uwriteln!(self.src, "Ok(())\n}}");
1506    }
1507
1508    fn generate_add_resource_to_linker(
1509        &mut self,
1510        key: Option<&WorldKey>,
1511        src: Option<&mut Source>,
1512        inst: &str,
1513        resolve: &Resolve,
1514        ty: TypeId,
1515    ) {
1516        let ty = &resolve.types[ty];
1517        let name = ty.name.as_ref().unwrap();
1518        let stability = &ty.stability;
1519        let wt = self.wasmtime_path();
1520        let src = src.unwrap_or(&mut self.src);
1521        let gate = FeatureGate::open(src, stability);
1522        let camel = name.to_upper_camel_case();
1523
1524        let flags = self.opts.imports.resource_drop_flags(resolve, key, name);
1525        if flags.contains(FunctionFlags::ASYNC) {
1526            if flags.contains(FunctionFlags::STORE) {
1527                uwriteln!(
1528                    src,
1529                    "{inst}.resource_concurrent(
1530                        \"{name}\",
1531                        {wt}::component::ResourceType::host::<{camel}>(),
1532                        move |caller: &{wt}::component::Accessor::<T>, rep| {{
1533                            {wt}::component::__internal::Box::pin(async move {{
1534                                let accessor = &caller.with_getter(host_getter);
1535                                Host{camel}WithStore::drop(accessor, {wt}::component::Resource::new_own(rep)).await
1536                            }})
1537                        }},
1538                    )?;"
1539                )
1540            } else {
1541                uwriteln!(
1542                    src,
1543                    "{inst}.resource_async(
1544                        \"{name}\",
1545                        {wt}::component::ResourceType::host::<{camel}>(),
1546                        move |mut store, rep| {{
1547                            {wt}::component::__internal::Box::new(async move {{
1548                                Host{camel}::drop(&mut host_getter(store.data_mut()), {wt}::component::Resource::new_own(rep)).await
1549                            }})
1550                        }},
1551                    )?;"
1552                )
1553            }
1554        } else {
1555            let (first_arg, trait_suffix) = if flags.contains(FunctionFlags::STORE) {
1556                (
1557                    format!("{wt}::component::Access::new(store, host_getter)"),
1558                    "WithStore",
1559                )
1560            } else {
1561                ("&mut host_getter(store.data_mut())".to_string(), "")
1562            };
1563            uwriteln!(
1564                src,
1565                "{inst}.resource(
1566                    \"{name}\",
1567                    {wt}::component::ResourceType::host::<{camel}>(),
1568                    move |mut store, rep| -> {wt}::Result<()> {{
1569
1570                        let resource = {wt}::component::Resource::new_own(rep);
1571                        Host{camel}{trait_suffix}::drop({first_arg}, resource)
1572                    }},
1573                )?;",
1574            )
1575        }
1576        gate.close(src);
1577    }
1578}
1579
1580struct InterfaceGenerator<'a> {
1581    src: Source,
1582    generator: &'a mut Wasmtime,
1583    resolve: &'a Resolve,
1584    current_interface: Option<(InterfaceId, &'a WorldKey, bool)>,
1585    all_func_flags: FunctionFlags,
1586}
1587
1588impl<'a> InterfaceGenerator<'a> {
1589    fn new(generator: &'a mut Wasmtime, resolve: &'a Resolve) -> InterfaceGenerator<'a> {
1590        InterfaceGenerator {
1591            src: Source::default(),
1592            generator,
1593            resolve,
1594            current_interface: None,
1595            all_func_flags: FunctionFlags::empty(),
1596        }
1597    }
1598
1599    fn types_imported(&self) -> bool {
1600        match self.current_interface {
1601            Some((_, _, is_export)) => !is_export,
1602            None => true,
1603        }
1604    }
1605
1606    fn types(&mut self, id: InterfaceId) {
1607        for (name, id) in self.resolve.interfaces[id].types.iter() {
1608            self.define_type(name, *id);
1609        }
1610    }
1611
1612    fn define_type(&mut self, name: &str, id: TypeId) {
1613        let ty = &self.resolve.types[id];
1614        match &ty.kind {
1615            TypeDefKind::Record(record) => self.type_record(id, name, record, &ty.docs),
1616            TypeDefKind::Flags(flags) => self.type_flags(id, name, flags, &ty.docs),
1617            TypeDefKind::Tuple(tuple) => self.type_tuple(id, name, tuple, &ty.docs),
1618            TypeDefKind::Enum(enum_) => self.type_enum(id, name, enum_, &ty.docs),
1619            TypeDefKind::Variant(variant) => self.type_variant(id, name, variant, &ty.docs),
1620            TypeDefKind::Option(t) => self.type_option(id, name, t, &ty.docs),
1621            TypeDefKind::Result(r) => self.type_result(id, name, r, &ty.docs),
1622            TypeDefKind::List(t) => self.type_list(id, name, t, &ty.docs),
1623            TypeDefKind::Type(t) => self.type_alias(id, name, t, &ty.docs),
1624            TypeDefKind::Future(t) => self.type_future(id, name, t.as_ref(), &ty.docs),
1625            TypeDefKind::Stream(t) => self.type_stream(id, name, t.as_ref(), &ty.docs),
1626            TypeDefKind::Handle(handle) => self.type_handle(id, name, handle, &ty.docs),
1627            TypeDefKind::Resource => self.type_resource(id, name, ty, &ty.docs),
1628            TypeDefKind::Unknown => unreachable!(),
1629            TypeDefKind::FixedSizeList(..) => todo!(),
1630        }
1631    }
1632
1633    fn type_handle(&mut self, id: TypeId, name: &str, handle: &Handle, docs: &Docs) {
1634        self.rustdoc(docs);
1635        let name = name.to_upper_camel_case();
1636        uwriteln!(self.src, "pub type {name} = ");
1637        self.print_handle(handle);
1638        self.push_str(";\n");
1639        self.assert_type(id, &name);
1640    }
1641
1642    fn type_resource(&mut self, id: TypeId, name: &str, _resource: &TypeDef, docs: &Docs) {
1643        let camel = name.to_upper_camel_case();
1644        let wt = self.generator.wasmtime_path();
1645
1646        if self.types_imported() {
1647            self.rustdoc(docs);
1648
1649            let replacement = match self.current_interface {
1650                Some((_, key, _)) => {
1651                    self.generator
1652                        .lookup_replacement(self.resolve, key, Some(name))
1653                }
1654                None => {
1655                    self.generator.used_with_opts.insert(name.into());
1656                    self.generator.opts.with.get(name).cloned()
1657                }
1658            };
1659            match replacement {
1660                Some(path) => {
1661                    uwriteln!(
1662                        self.src,
1663                        "pub use {}{path} as {camel};",
1664                        self.path_to_root()
1665                    );
1666                }
1667                None => {
1668                    uwriteln!(self.src, "pub enum {camel} {{}}");
1669                }
1670            }
1671
1672            // Generate resource trait
1673
1674            let functions = get_resource_functions(self.resolve, id);
1675            let trait_ = self.generate_trait(
1676                &format!("Host{camel}"),
1677                &functions,
1678                &[ExtraTraitMethod::ResourceDrop { name }],
1679                &[],
1680            );
1681            self.all_func_flags |= trait_.all_func_flags;
1682        } else {
1683            self.rustdoc(docs);
1684            uwriteln!(
1685                self.src,
1686                "
1687                    pub type {camel} = {wt}::component::ResourceAny;
1688
1689                    pub struct Guest{camel}<'a> {{
1690                        funcs: &'a Guest,
1691                    }}
1692                "
1693            );
1694        }
1695    }
1696
1697    fn type_record(&mut self, id: TypeId, _name: &str, record: &Record, docs: &Docs) {
1698        let info = self.info(id);
1699        let wt = self.generator.wasmtime_path();
1700
1701        // We use a BTree set to make sure we don't have any duplicates and we have a stable order
1702        let additional_derives: BTreeSet<String> = self
1703            .generator
1704            .opts
1705            .additional_derive_attributes
1706            .iter()
1707            .cloned()
1708            .collect();
1709
1710        for (name, mode) in self.modes_of(id) {
1711            let lt = self.lifetime_for(&info, mode);
1712            self.rustdoc(docs);
1713
1714            let mut derives = additional_derives.clone();
1715
1716            uwriteln!(self.src, "#[derive({wt}::component::ComponentType)]");
1717            if lt.is_none() {
1718                uwriteln!(self.src, "#[derive({wt}::component::Lift)]");
1719            }
1720            uwriteln!(self.src, "#[derive({wt}::component::Lower)]");
1721            self.push_str("#[component(record)]\n");
1722            if let Some(path) = &self.generator.opts.wasmtime_crate {
1723                uwriteln!(self.src, "#[component(wasmtime_crate = {path})]\n");
1724            }
1725
1726            if info.is_copy() {
1727                derives.extend(["Copy", "Clone"].into_iter().map(|s| s.to_string()));
1728            } else if info.is_clone() {
1729                derives.insert("Clone".to_string());
1730            }
1731
1732            if !derives.is_empty() {
1733                self.push_str("#[derive(");
1734                self.push_str(&derives.into_iter().collect::<Vec<_>>().join(", "));
1735                self.push_str(")]\n")
1736            }
1737
1738            self.push_str(&format!("pub struct {name}"));
1739            self.print_generics(lt);
1740            self.push_str(" {\n");
1741            for field in record.fields.iter() {
1742                self.rustdoc(&field.docs);
1743                self.push_str(&format!("#[component(name = \"{}\")]\n", field.name));
1744                self.push_str("pub ");
1745                self.push_str(&to_rust_ident(&field.name));
1746                self.push_str(": ");
1747                self.print_ty(&field.ty, mode);
1748                self.push_str(",\n");
1749            }
1750            self.push_str("}\n");
1751
1752            self.push_str("impl");
1753            self.print_generics(lt);
1754            self.push_str(" core::fmt::Debug for ");
1755            self.push_str(&name);
1756            self.print_generics(lt);
1757            self.push_str(" {\n");
1758            self.push_str(
1759                "fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n",
1760            );
1761            self.push_str(&format!("f.debug_struct(\"{name}\")"));
1762            for field in record.fields.iter() {
1763                self.push_str(&format!(
1764                    ".field(\"{}\", &self.{})",
1765                    field.name,
1766                    to_rust_ident(&field.name)
1767                ));
1768            }
1769            self.push_str(".finish()\n");
1770            self.push_str("}\n");
1771            self.push_str("}\n");
1772
1773            if info.error {
1774                self.push_str("impl");
1775                self.print_generics(lt);
1776                self.push_str(" core::fmt::Display for ");
1777                self.push_str(&name);
1778                self.print_generics(lt);
1779                self.push_str(" {\n");
1780                self.push_str(
1781                    "fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n",
1782                );
1783                self.push_str("write!(f, \"{:?}\", self)\n");
1784                self.push_str("}\n");
1785                self.push_str("}\n");
1786
1787                self.push_str("impl core::error::Error for ");
1788                self.push_str(&name);
1789                self.push_str("{}\n");
1790            }
1791            self.assert_type(id, &name);
1792        }
1793    }
1794
1795    fn type_tuple(&mut self, id: TypeId, _name: &str, tuple: &Tuple, docs: &Docs) {
1796        let info = self.info(id);
1797        for (name, mode) in self.modes_of(id) {
1798            let lt = self.lifetime_for(&info, mode);
1799            self.rustdoc(docs);
1800            self.push_str(&format!("pub type {name}"));
1801            self.print_generics(lt);
1802            self.push_str(" = (");
1803            for ty in tuple.types.iter() {
1804                self.print_ty(ty, mode);
1805                self.push_str(",");
1806            }
1807            self.push_str(");\n");
1808            self.assert_type(id, &name);
1809        }
1810    }
1811
1812    fn type_flags(&mut self, id: TypeId, name: &str, flags: &Flags, docs: &Docs) {
1813        self.rustdoc(docs);
1814        let wt = self.generator.wasmtime_path();
1815        let rust_name = to_rust_upper_camel_case(name);
1816        uwriteln!(self.src, "{wt}::component::flags!(\n");
1817        self.src.push_str(&format!("{rust_name} {{\n"));
1818        for flag in flags.flags.iter() {
1819            // TODO wasmtime-component-macro doesn't support docs for flags rn
1820            uwrite!(
1821                self.src,
1822                "#[component(name=\"{}\")] const {};\n",
1823                flag.name,
1824                flag.name.to_shouty_snake_case()
1825            );
1826        }
1827        self.src.push_str("}\n");
1828        self.src.push_str(");\n\n");
1829        self.assert_type(id, &rust_name);
1830    }
1831
1832    fn type_variant(&mut self, id: TypeId, _name: &str, variant: &Variant, docs: &Docs) {
1833        self.print_rust_enum(
1834            id,
1835            variant.cases.iter().map(|c| {
1836                (
1837                    c.name.to_upper_camel_case(),
1838                    Some(c.name.clone()),
1839                    &c.docs,
1840                    c.ty.as_ref(),
1841                )
1842            }),
1843            docs,
1844            "variant",
1845        );
1846    }
1847
1848    fn type_option(&mut self, id: TypeId, _name: &str, payload: &Type, docs: &Docs) {
1849        let info = self.info(id);
1850
1851        for (name, mode) in self.modes_of(id) {
1852            self.rustdoc(docs);
1853            let lt = self.lifetime_for(&info, mode);
1854            self.push_str(&format!("pub type {name}"));
1855            self.print_generics(lt);
1856            self.push_str("= Option<");
1857            self.print_ty(payload, mode);
1858            self.push_str(">;\n");
1859            self.assert_type(id, &name);
1860        }
1861    }
1862
1863    // Emit a double-check that the wit-parser-understood size of a type agrees
1864    // with the Wasmtime-understood size of a type.
1865    fn assert_type(&mut self, id: TypeId, name: &str) {
1866        self.push_str("const _: () = {\n");
1867        let wt = self.generator.wasmtime_path();
1868        uwriteln!(
1869            self.src,
1870            "assert!({} == <{name} as {wt}::component::ComponentType>::SIZE32);",
1871            self.generator.sizes.size(&Type::Id(id)).size_wasm32(),
1872        );
1873        uwriteln!(
1874            self.src,
1875            "assert!({} == <{name} as {wt}::component::ComponentType>::ALIGN32);",
1876            self.generator.sizes.align(&Type::Id(id)).align_wasm32(),
1877        );
1878        self.push_str("};\n");
1879    }
1880
1881    fn print_rust_enum<'b>(
1882        &mut self,
1883        id: TypeId,
1884        cases: impl IntoIterator<Item = (String, Option<String>, &'b Docs, Option<&'b Type>)> + Clone,
1885        docs: &Docs,
1886        derive_component: &str,
1887    ) where
1888        Self: Sized,
1889    {
1890        let info = self.info(id);
1891        let wt = self.generator.wasmtime_path();
1892
1893        // We use a BTree set to make sure we don't have any duplicates and we have a stable order
1894        let additional_derives: BTreeSet<String> = self
1895            .generator
1896            .opts
1897            .additional_derive_attributes
1898            .iter()
1899            .cloned()
1900            .collect();
1901
1902        for (name, mode) in self.modes_of(id) {
1903            let name = to_rust_upper_camel_case(&name);
1904
1905            let mut derives = additional_derives.clone();
1906
1907            self.rustdoc(docs);
1908            let lt = self.lifetime_for(&info, mode);
1909            uwriteln!(self.src, "#[derive({wt}::component::ComponentType)]");
1910            if lt.is_none() {
1911                uwriteln!(self.src, "#[derive({wt}::component::Lift)]");
1912            }
1913            uwriteln!(self.src, "#[derive({wt}::component::Lower)]");
1914            self.push_str(&format!("#[component({derive_component})]\n"));
1915            if let Some(path) = &self.generator.opts.wasmtime_crate {
1916                uwriteln!(self.src, "#[component(wasmtime_crate = {path})]\n");
1917            }
1918            if info.is_copy() {
1919                derives.extend(["Copy", "Clone"].into_iter().map(|s| s.to_string()));
1920            } else if info.is_clone() {
1921                derives.insert("Clone".to_string());
1922            }
1923
1924            if !derives.is_empty() {
1925                self.push_str("#[derive(");
1926                self.push_str(&derives.into_iter().collect::<Vec<_>>().join(", "));
1927                self.push_str(")]\n")
1928            }
1929
1930            self.push_str(&format!("pub enum {name}"));
1931            self.print_generics(lt);
1932            self.push_str("{\n");
1933            for (case_name, component_name, docs, payload) in cases.clone() {
1934                self.rustdoc(docs);
1935                if let Some(n) = component_name {
1936                    self.push_str(&format!("#[component(name = \"{n}\")] "));
1937                }
1938                self.push_str(&case_name);
1939                if let Some(ty) = payload {
1940                    self.push_str("(");
1941                    self.print_ty(ty, mode);
1942                    self.push_str(")")
1943                }
1944                self.push_str(",\n");
1945            }
1946            self.push_str("}\n");
1947
1948            self.print_rust_enum_debug(
1949                id,
1950                mode,
1951                &name,
1952                cases
1953                    .clone()
1954                    .into_iter()
1955                    .map(|(name, _attr, _docs, ty)| (name, ty)),
1956            );
1957
1958            if info.error {
1959                self.push_str("impl");
1960                self.print_generics(lt);
1961                self.push_str(" core::fmt::Display for ");
1962                self.push_str(&name);
1963                self.print_generics(lt);
1964                self.push_str(" {\n");
1965                self.push_str(
1966                    "fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n",
1967                );
1968                self.push_str("write!(f, \"{:?}\", self)\n");
1969                self.push_str("}\n");
1970                self.push_str("}\n");
1971
1972                self.push_str("impl");
1973                self.print_generics(lt);
1974                self.push_str(" core::error::Error for ");
1975                self.push_str(&name);
1976                self.print_generics(lt);
1977                self.push_str(" {}\n");
1978            }
1979
1980            self.assert_type(id, &name);
1981        }
1982    }
1983
1984    fn print_rust_enum_debug<'b>(
1985        &mut self,
1986        id: TypeId,
1987        mode: TypeMode,
1988        name: &str,
1989        cases: impl IntoIterator<Item = (String, Option<&'b Type>)>,
1990    ) where
1991        Self: Sized,
1992    {
1993        let info = self.info(id);
1994        let lt = self.lifetime_for(&info, mode);
1995        self.push_str("impl");
1996        self.print_generics(lt);
1997        self.push_str(" core::fmt::Debug for ");
1998        self.push_str(name);
1999        self.print_generics(lt);
2000        self.push_str(" {\n");
2001        self.push_str("fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n");
2002        self.push_str("match self {\n");
2003        for (case_name, payload) in cases {
2004            self.push_str(name);
2005            self.push_str("::");
2006            self.push_str(&case_name);
2007            if payload.is_some() {
2008                self.push_str("(e)");
2009            }
2010            self.push_str(" => {\n");
2011            self.push_str(&format!("f.debug_tuple(\"{name}::{case_name}\")"));
2012            if payload.is_some() {
2013                self.push_str(".field(e)");
2014            }
2015            self.push_str(".finish()\n");
2016            self.push_str("}\n");
2017        }
2018        self.push_str("}\n");
2019        self.push_str("}\n");
2020        self.push_str("}\n");
2021    }
2022
2023    fn type_result(&mut self, id: TypeId, _name: &str, result: &Result_, docs: &Docs) {
2024        let info = self.info(id);
2025
2026        for (name, mode) in self.modes_of(id) {
2027            self.rustdoc(docs);
2028            let lt = self.lifetime_for(&info, mode);
2029            self.push_str(&format!("pub type {name}"));
2030            self.print_generics(lt);
2031            self.push_str("= Result<");
2032            self.print_optional_ty(result.ok.as_ref(), mode);
2033            self.push_str(",");
2034            self.print_optional_ty(result.err.as_ref(), mode);
2035            self.push_str(">;\n");
2036            self.assert_type(id, &name);
2037        }
2038    }
2039
2040    fn type_enum(&mut self, id: TypeId, name: &str, enum_: &Enum, docs: &Docs) {
2041        let info = self.info(id);
2042        let wt = self.generator.wasmtime_path();
2043
2044        // We use a BTree set to make sure we don't have any duplicates and have a stable order
2045        let mut derives: BTreeSet<String> = self
2046            .generator
2047            .opts
2048            .additional_derive_attributes
2049            .iter()
2050            .cloned()
2051            .collect();
2052
2053        derives.extend(
2054            ["Clone", "Copy", "PartialEq", "Eq"]
2055                .into_iter()
2056                .map(|s| s.to_string()),
2057        );
2058
2059        let name = to_rust_upper_camel_case(name);
2060        self.rustdoc(docs);
2061        uwriteln!(self.src, "#[derive({wt}::component::ComponentType)]");
2062        uwriteln!(self.src, "#[derive({wt}::component::Lift)]");
2063        uwriteln!(self.src, "#[derive({wt}::component::Lower)]");
2064        self.push_str("#[component(enum)]\n");
2065        if let Some(path) = &self.generator.opts.wasmtime_crate {
2066            uwriteln!(self.src, "#[component(wasmtime_crate = {path})]\n");
2067        }
2068
2069        self.push_str("#[derive(");
2070        self.push_str(&derives.into_iter().collect::<Vec<_>>().join(", "));
2071        self.push_str(")]\n");
2072
2073        let repr = match enum_.cases.len().ilog2() {
2074            0..=7 => "u8",
2075            8..=15 => "u16",
2076            _ => "u32",
2077        };
2078        uwriteln!(self.src, "#[repr({repr})]");
2079
2080        self.push_str(&format!("pub enum {name} {{\n"));
2081        for case in enum_.cases.iter() {
2082            self.rustdoc(&case.docs);
2083            self.push_str(&format!("#[component(name = \"{}\")]", case.name));
2084            self.push_str(&case.name.to_upper_camel_case());
2085            self.push_str(",\n");
2086        }
2087        self.push_str("}\n");
2088
2089        // Auto-synthesize an implementation of the standard `Error` trait for
2090        // error-looking types based on their name.
2091        if info.error {
2092            self.push_str("impl ");
2093            self.push_str(&name);
2094            self.push_str("{\n");
2095
2096            self.push_str("pub fn name(&self) -> &'static str {\n");
2097            self.push_str("match self {\n");
2098            for case in enum_.cases.iter() {
2099                self.push_str(&name);
2100                self.push_str("::");
2101                self.push_str(&case.name.to_upper_camel_case());
2102                self.push_str(" => \"");
2103                self.push_str(case.name.as_str());
2104                self.push_str("\",\n");
2105            }
2106            self.push_str("}\n");
2107            self.push_str("}\n");
2108
2109            self.push_str("pub fn message(&self) -> &'static str {\n");
2110            self.push_str("match self {\n");
2111            for case in enum_.cases.iter() {
2112                self.push_str(&name);
2113                self.push_str("::");
2114                self.push_str(&case.name.to_upper_camel_case());
2115                self.push_str(" => \"");
2116                if let Some(contents) = &case.docs.contents {
2117                    self.push_str(contents.trim());
2118                }
2119                self.push_str("\",\n");
2120            }
2121            self.push_str("}\n");
2122            self.push_str("}\n");
2123
2124            self.push_str("}\n");
2125
2126            self.push_str("impl core::fmt::Debug for ");
2127            self.push_str(&name);
2128            self.push_str(
2129                "{\nfn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n",
2130            );
2131            self.push_str("f.debug_struct(\"");
2132            self.push_str(&name);
2133            self.push_str("\")\n");
2134            self.push_str(".field(\"code\", &(*self as i32))\n");
2135            self.push_str(".field(\"name\", &self.name())\n");
2136            self.push_str(".field(\"message\", &self.message())\n");
2137            self.push_str(".finish()\n");
2138            self.push_str("}\n");
2139            self.push_str("}\n");
2140
2141            self.push_str("impl core::fmt::Display for ");
2142            self.push_str(&name);
2143            self.push_str(
2144                "{\nfn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n",
2145            );
2146            self.push_str("write!(f, \"{} (error {})\", self.name(), *self as i32)");
2147            self.push_str("}\n");
2148            self.push_str("}\n");
2149            self.push_str("\n");
2150            self.push_str("impl core::error::Error for ");
2151            self.push_str(&name);
2152            self.push_str("{}\n");
2153        } else {
2154            self.print_rust_enum_debug(
2155                id,
2156                TypeMode::Owned,
2157                &name,
2158                enum_
2159                    .cases
2160                    .iter()
2161                    .map(|c| (c.name.to_upper_camel_case(), None)),
2162            )
2163        }
2164        self.assert_type(id, &name);
2165    }
2166
2167    fn type_alias(&mut self, id: TypeId, _name: &str, ty: &Type, docs: &Docs) {
2168        let info = self.info(id);
2169        for (name, mode) in self.modes_of(id) {
2170            self.rustdoc(docs);
2171            self.push_str(&format!("pub type {name}"));
2172            let lt = self.lifetime_for(&info, mode);
2173            self.print_generics(lt);
2174            self.push_str(" = ");
2175            self.print_ty(ty, mode);
2176            self.push_str(";\n");
2177            let def_id = resolve_type_definition_id(self.resolve, id);
2178            if !matches!(self.resolve().types[def_id].kind, TypeDefKind::Resource) {
2179                self.assert_type(id, &name);
2180            }
2181        }
2182    }
2183
2184    fn type_list(&mut self, id: TypeId, _name: &str, ty: &Type, docs: &Docs) {
2185        let info = self.info(id);
2186        for (name, mode) in self.modes_of(id) {
2187            let lt = self.lifetime_for(&info, mode);
2188            self.rustdoc(docs);
2189            self.push_str(&format!("pub type {name}"));
2190            self.print_generics(lt);
2191            self.push_str(" = ");
2192            self.print_list(ty, mode);
2193            self.push_str(";\n");
2194            self.assert_type(id, &name);
2195        }
2196    }
2197
2198    fn type_stream(&mut self, id: TypeId, name: &str, ty: Option<&Type>, docs: &Docs) {
2199        self.rustdoc(docs);
2200        self.push_str(&format!("pub type {name}"));
2201        self.print_generics(None);
2202        self.push_str(" = ");
2203        self.print_stream(ty);
2204        self.push_str(";\n");
2205        self.assert_type(id, &name);
2206    }
2207
2208    fn type_future(&mut self, id: TypeId, name: &str, ty: Option<&Type>, docs: &Docs) {
2209        self.rustdoc(docs);
2210        self.push_str(&format!("pub type {name}"));
2211        self.print_generics(None);
2212        self.push_str(" = ");
2213        self.print_future(ty);
2214        self.push_str(";\n");
2215        self.assert_type(id, &name);
2216    }
2217
2218    fn print_result_ty(&mut self, result: Option<Type>, mode: TypeMode) {
2219        match result {
2220            Some(ty) => self.print_ty(&ty, mode),
2221            None => self.push_str("()"),
2222        }
2223    }
2224
2225    fn special_case_trappable_error(
2226        &mut self,
2227        func: &Function,
2228    ) -> Option<(&'a Result_, TypeId, String)> {
2229        let result = func.result?;
2230
2231        // We fill in a special trappable error type in the case when a function has just one
2232        // result, which is itself a `result<a, e>`, and the `e` is *not* a primitive
2233        // (i.e. defined in std) type, and matches the typename given by the user.
2234        let id = match result {
2235            Type::Id(id) => id,
2236            _ => return None,
2237        };
2238        let result = match &self.resolve.types[id].kind {
2239            TypeDefKind::Result(r) => r,
2240            _ => return None,
2241        };
2242        let error_typeid = match result.err? {
2243            Type::Id(id) => resolve_type_definition_id(&self.resolve, id),
2244            _ => return None,
2245        };
2246
2247        let name = self.generator.trappable_errors.get(&error_typeid)?;
2248
2249        let mut path = self.path_to_root();
2250        uwrite!(path, "{name}");
2251        Some((result, error_typeid, path))
2252    }
2253
2254    fn generate_add_to_linker(&mut self, id: InterfaceId, name: &str) {
2255        let iface = &self.resolve.interfaces[id];
2256        let owner = TypeOwner::Interface(id);
2257        let wt = self.generator.wasmtime_path();
2258
2259        let mut required_conversion_traits = IndexSet::new();
2260        let extra_functions = {
2261            let mut functions = Vec::new();
2262            let mut errors_converted = IndexMap::new();
2263            let mut my_error_types = iface
2264                .types
2265                .iter()
2266                .filter(|(_, id)| self.generator.trappable_errors.contains_key(*id))
2267                .map(|(_, id)| *id)
2268                .collect::<Vec<_>>();
2269            my_error_types.extend(
2270                iface
2271                    .functions
2272                    .iter()
2273                    .filter_map(|(_, func)| self.special_case_trappable_error(func))
2274                    .map(|(_, id, _)| id),
2275            );
2276            for err_id in my_error_types {
2277                let err = &self.resolve.types[resolve_type_definition_id(self.resolve, err_id)];
2278                let err_name = err.name.as_ref().unwrap();
2279                let owner = match err.owner {
2280                    TypeOwner::Interface(i) => i,
2281                    _ => unimplemented!(),
2282                };
2283                match self.path_to_interface(owner) {
2284                    Some(path) => {
2285                        required_conversion_traits.insert(format!("{path}::Host"));
2286                    }
2287                    None => {
2288                        if errors_converted.insert(err_name, err_id).is_none() {
2289                            functions.push(ExtraTraitMethod::ErrorConvert {
2290                                name: err_name,
2291                                id: err_id,
2292                            })
2293                        }
2294                    }
2295                }
2296            }
2297            functions
2298        };
2299
2300        // Generate the `pub trait` which represents the host functionality for
2301        // this import which additionally inherits from all resource traits
2302        // for this interface defined by `type_resource`.
2303        let generated_trait = self.generate_trait(
2304            "Host",
2305            &iface
2306                .functions
2307                .iter()
2308                .filter_map(|(_, f)| {
2309                    if f.kind.resource().is_none() {
2310                        Some(f)
2311                    } else {
2312                        None
2313                    }
2314                })
2315                .collect::<Vec<_>>(),
2316            &extra_functions,
2317            &get_resources(self.resolve, id).collect::<Vec<_>>(),
2318        );
2319
2320        let opt_t_send_bound = if generated_trait
2321            .all_func_flags
2322            .contains(FunctionFlags::ASYNC)
2323        {
2324            "+ Send"
2325        } else {
2326            ""
2327        };
2328
2329        let mut sync_bounds = "Host".to_string();
2330
2331        for ty in required_conversion_traits {
2332            uwrite!(sync_bounds, " + {ty}");
2333        }
2334
2335        let options_param = if self.generator.interface_link_options[&id].has_any() {
2336            "options: &LinkOptions,"
2337        } else {
2338            ""
2339        };
2340
2341        uwriteln!(
2342            self.src,
2343            "
2344                pub fn add_to_linker<T, D>(
2345                    linker: &mut {wt}::component::Linker<T>,
2346                    {options_param}
2347                    host_getter: fn(&mut T) -> D::Data<'_>,
2348                ) -> {wt}::Result<()>
2349                    where
2350                        D: HostWithStore,
2351                        for<'a> D::Data<'a>: {sync_bounds},
2352                        T: 'static {opt_t_send_bound},
2353                {{
2354            "
2355        );
2356
2357        let gate = FeatureGate::open(&mut self.src, &iface.stability);
2358        uwriteln!(self.src, "let mut inst = linker.instance(\"{name}\")?;");
2359
2360        for (ty, _name) in get_resources(self.resolve, id) {
2361            self.generator.generate_add_resource_to_linker(
2362                self.current_interface.map(|p| p.1),
2363                Some(&mut self.src),
2364                "inst",
2365                self.resolve,
2366                ty,
2367            );
2368        }
2369
2370        for (_, func) in iface.functions.iter() {
2371            self.generate_add_function_to_linker(owner, func, "inst");
2372        }
2373        gate.close(&mut self.src);
2374        uwriteln!(self.src, "Ok(())");
2375        uwriteln!(self.src, "}}");
2376    }
2377
2378    fn import_resource_drop_flags(&mut self, name: &str) -> FunctionFlags {
2379        self.generator.opts.imports.resource_drop_flags(
2380            self.resolve,
2381            self.current_interface.map(|p| p.1),
2382            name,
2383        )
2384    }
2385
2386    fn generate_add_function_to_linker(&mut self, owner: TypeOwner, func: &Function, linker: &str) {
2387        let flags = self.generator.opts.imports.flags(
2388            self.resolve,
2389            self.current_interface.map(|p| p.1),
2390            func,
2391        );
2392        self.all_func_flags |= flags;
2393        let gate = FeatureGate::open(&mut self.src, &func.stability);
2394        uwrite!(
2395            self.src,
2396            "{linker}.{}(\"{}\", ",
2397            if flags.contains(FunctionFlags::ASYNC | FunctionFlags::STORE) {
2398                "func_wrap_concurrent"
2399            } else if flags.contains(FunctionFlags::ASYNC) {
2400                "func_wrap_async"
2401            } else {
2402                "func_wrap"
2403            },
2404            func.name
2405        );
2406        self.generate_guest_import_closure(owner, func, flags);
2407        uwriteln!(self.src, ")?;");
2408        gate.close(&mut self.src);
2409    }
2410
2411    fn generate_guest_import_closure(
2412        &mut self,
2413        owner: TypeOwner,
2414        func: &Function,
2415        flags: FunctionFlags,
2416    ) {
2417        // Generate the closure that's passed to a `Linker`, the final piece of
2418        // codegen here.
2419
2420        let wt = self.generator.wasmtime_path();
2421        if flags.contains(FunctionFlags::ASYNC | FunctionFlags::STORE) {
2422            uwrite!(self.src, "move |caller: &{wt}::component::Accessor::<T>, (");
2423        } else {
2424            uwrite!(
2425                self.src,
2426                "move |mut caller: {wt}::StoreContextMut<'_, T>, ("
2427            );
2428        }
2429        for (i, _param) in func.params.iter().enumerate() {
2430            uwrite!(self.src, "arg{},", i);
2431        }
2432        self.src.push_str(") : (");
2433
2434        for (_, ty) in func.params.iter() {
2435            // Lift is required to be implied for this type, so we can't use
2436            // a borrowed type:
2437            self.print_ty(ty, TypeMode::Owned);
2438            self.src.push_str(", ");
2439        }
2440        self.src.push_str(")| {\n");
2441
2442        if flags.contains(FunctionFlags::TRACING) {
2443            if flags.contains(FunctionFlags::ASYNC) {
2444                self.src.push_str("use tracing::Instrument;\n");
2445            }
2446
2447            uwrite!(
2448                self.src,
2449                "
2450                   let span = tracing::span!(
2451                       tracing::Level::TRACE,
2452                       \"wit-bindgen import\",
2453                       module = \"{}\",
2454                       function = \"{}\",
2455                   );
2456               ",
2457                match owner {
2458                    TypeOwner::Interface(id) => self.resolve.interfaces[id]
2459                        .name
2460                        .as_deref()
2461                        .unwrap_or("<no module>"),
2462                    TypeOwner::World(id) => &self.resolve.worlds[id].name,
2463                    TypeOwner::None => "<no owner>",
2464                },
2465                func.name,
2466            );
2467        }
2468
2469        if flags.contains(FunctionFlags::ASYNC) {
2470            let ctor = if flags.contains(FunctionFlags::STORE) {
2471                "pin"
2472            } else {
2473                "new"
2474            };
2475            uwriteln!(
2476                self.src,
2477                "{wt}::component::__internal::Box::{ctor}(async move {{"
2478            );
2479        } else {
2480            // Only directly enter the span if the function is sync. Otherwise
2481            // we use tracing::Instrument to ensure that the span is not entered
2482            // across an await point.
2483            if flags.contains(FunctionFlags::TRACING) {
2484                self.push_str("let _enter = span.enter();\n");
2485            }
2486        }
2487
2488        if flags.contains(FunctionFlags::TRACING) {
2489            let mut event_fields = func
2490                .params
2491                .iter()
2492                .enumerate()
2493                .map(|(i, (name, ty))| {
2494                    let name = to_rust_ident(&name);
2495                    formatting_for_arg(&name, i, *ty, &self.resolve, flags)
2496                })
2497                .collect::<Vec<String>>();
2498            event_fields.push(format!("\"call\""));
2499            uwrite!(
2500                self.src,
2501                "tracing::event!(tracing::Level::TRACE, {});\n",
2502                event_fields.join(", ")
2503            );
2504        }
2505
2506        if flags.contains(FunctionFlags::STORE) {
2507            if flags.contains(FunctionFlags::ASYNC) {
2508                uwriteln!(self.src, "let host = &caller.with_getter(host_getter);");
2509            } else {
2510                uwriteln!(
2511                    self.src,
2512                    "let access_cx = {wt}::AsContextMut::as_context_mut(&mut caller);"
2513                );
2514                uwriteln!(
2515                    self.src,
2516                    "let host = {wt}::component::Access::new(access_cx, host_getter);"
2517                );
2518            }
2519        } else {
2520            self.src
2521                .push_str("let host = &mut host_getter(caller.data_mut());\n");
2522        }
2523        let func_name = rust_function_name(func);
2524        let host_trait = match func.kind.resource() {
2525            None => match owner {
2526                TypeOwner::World(id) => format!(
2527                    "{}Imports",
2528                    rust::to_rust_upper_camel_case(&self.resolve.worlds[id].name)
2529                ),
2530                _ => "Host".to_string(),
2531            },
2532            Some(id) => {
2533                let resource = self.resolve.types[id]
2534                    .name
2535                    .as_ref()
2536                    .unwrap()
2537                    .to_upper_camel_case();
2538                format!("Host{resource}")
2539            }
2540        };
2541
2542        if flags.contains(FunctionFlags::STORE) {
2543            uwrite!(
2544                self.src,
2545                "let r = <D as {host_trait}WithStore>::{func_name}(host, "
2546            );
2547        } else {
2548            uwrite!(self.src, "let r = {host_trait}::{func_name}(host, ");
2549        }
2550
2551        for (i, _) in func.params.iter().enumerate() {
2552            uwrite!(self.src, "arg{},", i);
2553        }
2554
2555        self.src.push_str(if flags.contains(FunctionFlags::ASYNC) {
2556            ").await;\n"
2557        } else {
2558            ");\n"
2559        });
2560
2561        if flags.contains(FunctionFlags::TRACING) {
2562            uwrite!(
2563                self.src,
2564                "tracing::event!(tracing::Level::TRACE, {}, \"return\");",
2565                formatting_for_results(func.result, &self.resolve, flags)
2566            );
2567        }
2568
2569        if !flags.contains(FunctionFlags::TRAPPABLE) {
2570            if func.result.is_some() {
2571                uwrite!(self.src, "Ok((r,))\n");
2572            } else {
2573                uwrite!(self.src, "Ok(r)\n");
2574            }
2575        } else if let Some((_, err, _)) = self.special_case_trappable_error(func) {
2576            let err = &self.resolve.types[resolve_type_definition_id(self.resolve, err)];
2577            let err_name = err.name.as_ref().unwrap();
2578            let owner = match err.owner {
2579                TypeOwner::Interface(i) => i,
2580                _ => unimplemented!(),
2581            };
2582            let convert_trait = match self.path_to_interface(owner) {
2583                Some(path) => format!("{path}::Host"),
2584                None => format!("Host"),
2585            };
2586            let convert = format!("{}::convert_{}", convert_trait, err_name.to_snake_case());
2587            let convert = if flags.contains(FunctionFlags::STORE) {
2588                if flags.contains(FunctionFlags::ASYNC) {
2589                    format!("caller.with(|mut host| {convert}(&mut host_getter(host.get()), e))?")
2590                } else {
2591                    format!("{convert}(&mut host_getter(caller.data_mut()), e)?")
2592                }
2593            } else {
2594                format!("{convert}(host, e)?")
2595            };
2596            uwrite!(
2597                self.src,
2598                "Ok((match r {{
2599                    Ok(a) => Ok(a),
2600                    Err(e) => Err({convert}),
2601                }},))"
2602            );
2603        } else if func.result.is_some() {
2604            uwrite!(self.src, "Ok((r?,))\n");
2605        } else {
2606            uwrite!(self.src, "r\n");
2607        }
2608
2609        if flags.contains(FunctionFlags::ASYNC) {
2610            if flags.contains(FunctionFlags::TRACING) {
2611                self.src.push_str("}.instrument(span))\n");
2612            } else {
2613                self.src.push_str("})\n");
2614            }
2615        }
2616
2617        self.src.push_str("}\n");
2618    }
2619
2620    fn generate_function_trait_sig(&mut self, func: &Function, flags: FunctionFlags) {
2621        let wt = self.generator.wasmtime_path();
2622        self.rustdoc(&func.docs);
2623
2624        self.push_str("fn ");
2625        self.push_str(&rust_function_name(func));
2626        if flags.contains(FunctionFlags::STORE | FunctionFlags::ASYNC) {
2627            uwrite!(
2628                self.src,
2629                "<T>(accessor: &{wt}::component::Accessor<T, Self>, "
2630            );
2631        } else if flags.contains(FunctionFlags::STORE) {
2632            uwrite!(self.src, "<T>(host: {wt}::component::Access<T, Self>, ");
2633        } else {
2634            self.push_str("(&mut self, ");
2635        }
2636        self.generate_function_params(func);
2637        self.push_str(")");
2638        self.push_str(" -> ");
2639
2640        if flags.contains(FunctionFlags::ASYNC) {
2641            uwrite!(self.src, "impl ::core::future::Future<Output = ");
2642        }
2643
2644        self.all_func_flags |= flags;
2645        self.generate_function_result(func, flags);
2646
2647        if flags.contains(FunctionFlags::ASYNC) {
2648            self.push_str("> + Send");
2649        }
2650    }
2651
2652    fn generate_function_params(&mut self, func: &Function) {
2653        for (name, param) in func.params.iter() {
2654            let name = to_rust_ident(name);
2655            self.push_str(&name);
2656            self.push_str(": ");
2657            self.print_ty(param, TypeMode::Owned);
2658            self.push_str(",");
2659        }
2660    }
2661
2662    fn generate_function_result(&mut self, func: &Function, flags: FunctionFlags) {
2663        if !flags.contains(FunctionFlags::TRAPPABLE) {
2664            self.print_result_ty(func.result, TypeMode::Owned);
2665        } else if let Some((r, _id, error_typename)) = self.special_case_trappable_error(func) {
2666            // Functions which have a single result `result<ok,err>` get special
2667            // cased to use the host_wasmtime_rust::Error<err>, making it possible
2668            // for them to trap or use `?` to propagate their errors
2669            self.push_str("Result<");
2670            if let Some(ok) = r.ok {
2671                self.print_ty(&ok, TypeMode::Owned);
2672            } else {
2673                self.push_str("()");
2674            }
2675            self.push_str(",");
2676            self.push_str(&error_typename);
2677            self.push_str(">");
2678        } else {
2679            // All other functions get their return values wrapped in an wasmtime::Result.
2680            // Returning the anyhow::Error case can be used to trap.
2681            let wt = self.generator.wasmtime_path();
2682            uwrite!(self.src, "{wt}::Result<");
2683            self.print_result_ty(func.result, TypeMode::Owned);
2684            self.push_str(">");
2685        }
2686    }
2687
2688    fn extract_typed_function(&mut self, func: &Function) -> (String, String) {
2689        let snake = func_field_name(self.resolve, func);
2690        let sig = self.typedfunc_sig(func, TypeMode::AllBorrowed("'_"));
2691        let extract =
2692            format!("*_instance.get_typed_func::<{sig}>(&mut store, &self.{snake})?.func()");
2693        (snake, extract)
2694    }
2695
2696    fn define_rust_guest_export(
2697        &mut self,
2698        resolve: &Resolve,
2699        ns: Option<&WorldKey>,
2700        func: &Function,
2701    ) {
2702        let flags = self.generator.opts.exports.flags(resolve, ns, func);
2703        let (async_, async__, await_) = if flags.contains(FunctionFlags::ASYNC) {
2704            ("async", "_async", ".await")
2705        } else {
2706            ("", "", "")
2707        };
2708
2709        self.rustdoc(&func.docs);
2710        let wt = self.generator.wasmtime_path();
2711
2712        uwrite!(
2713            self.src,
2714            "pub {async_} fn call_{}",
2715            func.item_name().to_snake_case(),
2716        );
2717        if flags.contains(FunctionFlags::ASYNC | FunctionFlags::STORE) {
2718            uwrite!(
2719                self.src,
2720                "<_T, _D>(&self, accessor: &{wt}::component::Accessor<_T, _D>, ",
2721            );
2722        } else {
2723            uwrite!(self.src, "<S: {wt}::AsContextMut>(&self, mut store: S, ",);
2724        }
2725
2726        let task_exit =
2727            flags.contains(FunctionFlags::ASYNC | FunctionFlags::STORE | FunctionFlags::TASK_EXIT);
2728
2729        let param_mode = if flags.contains(FunctionFlags::ASYNC | FunctionFlags::STORE) {
2730            TypeMode::Owned
2731        } else {
2732            TypeMode::AllBorrowed("'_")
2733        };
2734
2735        for (i, param) in func.params.iter().enumerate() {
2736            uwrite!(self.src, "arg{}: ", i);
2737            self.print_ty(&param.1, param_mode);
2738            self.push_str(",");
2739        }
2740
2741        uwrite!(self.src, ") -> {wt}::Result<");
2742        if task_exit {
2743            self.src.push_str("(");
2744        }
2745        self.print_result_ty(func.result, TypeMode::Owned);
2746        if task_exit {
2747            uwrite!(self.src, ", {wt}::component::TaskExit)");
2748        }
2749        uwrite!(self.src, ">");
2750
2751        if flags.contains(FunctionFlags::ASYNC | FunctionFlags::STORE) {
2752            uwrite!(self.src, " where _T: Send, _D: {wt}::component::HasData");
2753        } else if flags.contains(FunctionFlags::ASYNC) {
2754            uwrite!(self.src, " where <S as {wt}::AsContext>::Data: Send");
2755        }
2756        uwrite!(self.src, "{{\n");
2757
2758        if flags.contains(FunctionFlags::TRACING) {
2759            if flags.contains(FunctionFlags::ASYNC) {
2760                self.src.push_str("use tracing::Instrument;\n");
2761            }
2762
2763            let ns = match ns {
2764                Some(key) => resolve.name_world_key(key),
2765                None => "default".to_string(),
2766            };
2767            self.src.push_str(&format!(
2768                "
2769                   let span = tracing::span!(
2770                       tracing::Level::TRACE,
2771                       \"wit-bindgen export\",
2772                       module = \"{ns}\",
2773                       function = \"{}\",
2774                   );
2775               ",
2776                func.name,
2777            ));
2778
2779            if !flags.contains(FunctionFlags::ASYNC) {
2780                self.src.push_str(
2781                    "
2782                   let _enter = span.enter();
2783                   ",
2784                );
2785            }
2786        }
2787
2788        self.src.push_str("let callee = unsafe {\n");
2789        uwrite!(
2790            self.src,
2791            "{wt}::component::TypedFunc::<{}>",
2792            self.typedfunc_sig(func, param_mode)
2793        );
2794        let projection_to_func = if func.kind.resource().is_some() {
2795            ".funcs"
2796        } else {
2797            ""
2798        };
2799        uwriteln!(
2800            self.src,
2801            "::new_unchecked(self{projection_to_func}.{})",
2802            func_field_name(self.resolve, func),
2803        );
2804        self.src.push_str("};\n");
2805
2806        self.src.push_str("let (");
2807        if flags.contains(FunctionFlags::ASYNC | FunctionFlags::STORE) {
2808            self.src.push_str("(");
2809        }
2810        if func.result.is_some() {
2811            uwrite!(self.src, "ret0,");
2812        }
2813
2814        if flags.contains(FunctionFlags::ASYNC | FunctionFlags::STORE) {
2815            let task_exit = if task_exit { "task_exit" } else { "_" };
2816            uwrite!(
2817                self.src,
2818                "), {task_exit}) = callee.call_concurrent(accessor, ("
2819            );
2820        } else {
2821            uwrite!(
2822                self.src,
2823                ") = callee.call{async__}(store.as_context_mut(), ("
2824            );
2825        };
2826
2827        for (i, _) in func.params.iter().enumerate() {
2828            uwrite!(self.src, "arg{}, ", i);
2829        }
2830
2831        let instrument = if flags.contains(FunctionFlags::ASYNC | FunctionFlags::TRACING) {
2832            ".instrument(span.clone())"
2833        } else {
2834            ""
2835        };
2836        uwriteln!(self.src, ")){instrument}{await_}?;");
2837
2838        let instrument = if flags.contains(FunctionFlags::ASYNC | FunctionFlags::TRACING) {
2839            ".instrument(span)"
2840        } else {
2841            ""
2842        };
2843
2844        if !flags.contains(FunctionFlags::STORE) {
2845            uwriteln!(
2846                self.src,
2847                "callee.post_return{async__}(store.as_context_mut()){instrument}{await_}?;"
2848            );
2849        }
2850
2851        self.src.push_str("Ok(");
2852        if task_exit {
2853            self.src.push_str("(");
2854        }
2855        if func.result.is_some() {
2856            self.src.push_str("ret0");
2857        } else {
2858            self.src.push_str("()");
2859        }
2860        if task_exit {
2861            self.src.push_str(", task_exit)");
2862        }
2863        self.src.push_str(")\n");
2864
2865        // End function body
2866        self.src.push_str("}\n");
2867    }
2868
2869    fn rustdoc(&mut self, docs: &Docs) {
2870        let docs = match &docs.contents {
2871            Some(docs) => docs,
2872            None => return,
2873        };
2874        for line in docs.trim().lines() {
2875            self.push_str("/// ");
2876            self.push_str(line);
2877            self.push_str("\n");
2878        }
2879    }
2880
2881    fn path_to_root(&self) -> String {
2882        let mut path_to_root = String::new();
2883        if let Some((_, key, is_export)) = self.current_interface {
2884            match key {
2885                WorldKey::Name(_) => {
2886                    path_to_root.push_str("super::");
2887                }
2888                WorldKey::Interface(_) => {
2889                    path_to_root.push_str("super::super::super::");
2890                }
2891            }
2892            if is_export {
2893                path_to_root.push_str("super::");
2894            }
2895        }
2896        path_to_root
2897    }
2898
2899    fn partition_concurrent_funcs<'b>(
2900        &mut self,
2901        funcs: impl IntoIterator<Item = &'b Function>,
2902    ) -> FunctionPartitioning<'b> {
2903        let key = self.current_interface.map(|p| p.1);
2904        let (with_store, without_store) = funcs
2905            .into_iter()
2906            .map(|func| {
2907                let flags = self.generator.opts.imports.flags(self.resolve, key, func);
2908                (func, flags)
2909            })
2910            .partition(|(_, flags)| flags.contains(FunctionFlags::STORE));
2911        FunctionPartitioning {
2912            with_store,
2913            without_store,
2914        }
2915    }
2916
2917    fn generate_trait(
2918        &mut self,
2919        trait_name: &str,
2920        functions: &[&Function],
2921        extra_functions: &[ExtraTraitMethod<'_>],
2922        resources: &[(TypeId, &str)],
2923    ) -> GeneratedTrait {
2924        let mut ret = GeneratedTrait::default();
2925        let wt = self.generator.wasmtime_path();
2926        let partition = self.partition_concurrent_funcs(functions.iter().copied());
2927
2928        for (_, flags) in partition.with_store.iter().chain(&partition.without_store) {
2929            ret.all_func_flags |= *flags;
2930        }
2931
2932        let mut with_store_supertraits = vec![format!("{wt}::component::HasData")];
2933        let mut without_store_supertraits = vec![];
2934        for (id, name) in resources {
2935            let camel = name.to_upper_camel_case();
2936            without_store_supertraits.push(format!("Host{camel}"));
2937            let funcs = self.partition_concurrent_funcs(get_resource_functions(self.resolve, *id));
2938            for (_, flags) in funcs.with_store.iter().chain(&funcs.without_store) {
2939                ret.all_func_flags |= *flags;
2940            }
2941            ret.all_func_flags |= self.import_resource_drop_flags(name);
2942            with_store_supertraits.push(format!("Host{camel}WithStore"));
2943        }
2944        if ret.all_func_flags.contains(FunctionFlags::ASYNC) {
2945            with_store_supertraits.push("Send".to_string());
2946            without_store_supertraits.push("Send".to_string());
2947        }
2948
2949        uwriteln!(
2950            self.src,
2951            "pub trait {trait_name}WithStore: {} {{",
2952            with_store_supertraits.join(" + "),
2953        );
2954        ret.with_store_name = Some(format!("{trait_name}WithStore"));
2955
2956        let mut extra_with_store_function = false;
2957        for extra in extra_functions {
2958            match extra {
2959                ExtraTraitMethod::ResourceDrop { name } => {
2960                    let flags = self.import_resource_drop_flags(name);
2961                    if !flags.contains(FunctionFlags::STORE) {
2962                        continue;
2963                    }
2964                    let camel = name.to_upper_camel_case();
2965
2966                    if flags.contains(FunctionFlags::ASYNC) {
2967                        uwrite!(
2968                            self.src,
2969                            "
2970fn drop<T>(accessor: &{wt}::component::Accessor<T, Self>, rep: {wt}::component::Resource<{camel}>)
2971    -> impl ::core::future::Future<Output = {wt}::Result<()>> + Send where Self: Sized;
2972"
2973                        );
2974                    } else {
2975                        uwrite!(
2976                            self.src,
2977                            "
2978fn drop<T>(accessor: {wt}::component::Access<T, Self>, rep: {wt}::component::Resource<{camel}>)
2979    ->  {wt}::Result<()>;
2980"
2981                        );
2982                    }
2983
2984                    extra_with_store_function = true;
2985                }
2986                ExtraTraitMethod::ErrorConvert { .. } => {}
2987            }
2988        }
2989
2990        for (func, flags) in partition.with_store.iter() {
2991            self.generate_function_trait_sig(func, *flags);
2992            self.push_str(";\n");
2993        }
2994        uwriteln!(self.src, "}}");
2995
2996        // If `*WithStore` is empty, generate a blanket impl for the trait since
2997        // it's otherwise not necessary to implement it manually.
2998        if partition.with_store.is_empty() && !extra_with_store_function {
2999            uwriteln!(self.src, "impl<_T: ?Sized> {trait_name}WithStore for _T");
3000            uwriteln!(
3001                self.src,
3002                " where _T: {}",
3003                with_store_supertraits.join(" + ")
3004            );
3005
3006            uwriteln!(self.src, "{{}}");
3007        }
3008
3009        uwriteln!(
3010            self.src,
3011            "pub trait {trait_name}: {} {{",
3012            without_store_supertraits.join(" + ")
3013        );
3014        ret.name = trait_name.to_string();
3015        for (func, flags) in partition.without_store.iter() {
3016            self.generate_function_trait_sig(func, *flags);
3017            self.push_str(";\n");
3018        }
3019
3020        for extra in extra_functions {
3021            match extra {
3022                ExtraTraitMethod::ResourceDrop { name } => {
3023                    let flags = self.import_resource_drop_flags(name);
3024                    ret.all_func_flags |= flags;
3025                    if flags.contains(FunctionFlags::STORE) {
3026                        continue;
3027                    }
3028                    let camel = name.to_upper_camel_case();
3029                    uwrite!(
3030                        self.src,
3031                        "fn drop(&mut self, rep: {wt}::component::Resource<{camel}>) -> "
3032                    );
3033                    if flags.contains(FunctionFlags::ASYNC) {
3034                        uwrite!(self.src, "impl ::core::future::Future<Output =");
3035                    }
3036                    uwrite!(self.src, "{wt}::Result<()>");
3037                    if flags.contains(FunctionFlags::ASYNC) {
3038                        uwrite!(self.src, "> + Send");
3039                    }
3040                    uwrite!(self.src, ";");
3041                }
3042                ExtraTraitMethod::ErrorConvert { name, id } => {
3043                    let root = self.path_to_root();
3044                    let custom_name = &self.generator.trappable_errors[id];
3045                    let snake = name.to_snake_case();
3046                    let camel = name.to_upper_camel_case();
3047                    uwriteln!(
3048                        self.src,
3049                        "
3050fn convert_{snake}(&mut self, err: {root}{custom_name}) -> {wt}::Result<{camel}>;
3051                        "
3052                    );
3053                }
3054            }
3055        }
3056
3057        uwriteln!(self.src, "}}");
3058
3059        if self.generator.opts.skip_mut_forwarding_impls {
3060            return ret;
3061        }
3062
3063        // Generate impl HostResource for &mut HostResource
3064        let maybe_send = if ret.all_func_flags.contains(FunctionFlags::ASYNC) {
3065            "+ Send"
3066        } else {
3067            ""
3068        };
3069        uwriteln!(
3070            self.src,
3071            "impl <_T: {trait_name} + ?Sized {maybe_send}> {trait_name} for &mut _T {{"
3072        );
3073        for (func, flags) in partition.without_store.iter() {
3074            self.generate_function_trait_sig(func, *flags);
3075            uwriteln!(self.src, "{{");
3076            if flags.contains(FunctionFlags::ASYNC) {
3077                uwriteln!(self.src, "async move {{");
3078            }
3079            uwrite!(
3080                self.src,
3081                "{trait_name}::{}(*self,",
3082                rust_function_name(func)
3083            );
3084            for (name, _) in func.params.iter() {
3085                uwrite!(self.src, "{},", to_rust_ident(name));
3086            }
3087            uwrite!(self.src, ")");
3088            if flags.contains(FunctionFlags::ASYNC) {
3089                uwrite!(self.src, ".await\n}}");
3090            }
3091            uwriteln!(self.src, "}}");
3092        }
3093        for extra in extra_functions {
3094            match extra {
3095                ExtraTraitMethod::ResourceDrop { name } => {
3096                    let flags = self.import_resource_drop_flags(name);
3097                    if flags.contains(FunctionFlags::STORE) {
3098                        continue;
3099                    }
3100                    let camel = name.to_upper_camel_case();
3101                    let mut await_ = "";
3102                    if flags.contains(FunctionFlags::ASYNC) {
3103                        self.src.push_str("async ");
3104                        await_ = ".await";
3105                    }
3106                    uwriteln!(
3107                        self.src,
3108                        "
3109fn drop(&mut self, rep: {wt}::component::Resource<{camel}>) -> {wt}::Result<()> {{
3110    {trait_name}::drop(*self, rep){await_}
3111}}
3112                        ",
3113                    );
3114                }
3115                ExtraTraitMethod::ErrorConvert { name, id } => {
3116                    let root = self.path_to_root();
3117                    let custom_name = &self.generator.trappable_errors[id];
3118                    let snake = name.to_snake_case();
3119                    let camel = name.to_upper_camel_case();
3120                    uwriteln!(
3121                        self.src,
3122                        "
3123fn convert_{snake}(&mut self, err: {root}{custom_name}) -> {wt}::Result<{camel}> {{
3124    {trait_name}::convert_{snake}(*self, err)
3125}}
3126                        ",
3127                    );
3128                }
3129            }
3130        }
3131        uwriteln!(self.src, "}}");
3132
3133        ret
3134    }
3135}
3136
3137enum ExtraTraitMethod<'a> {
3138    ResourceDrop { name: &'a str },
3139    ErrorConvert { name: &'a str, id: TypeId },
3140}
3141
3142struct FunctionPartitioning<'a> {
3143    without_store: Vec<(&'a Function, FunctionFlags)>,
3144    with_store: Vec<(&'a Function, FunctionFlags)>,
3145}
3146
3147#[derive(Default)]
3148struct GeneratedTrait {
3149    name: String,
3150    with_store_name: Option<String>,
3151    all_func_flags: FunctionFlags,
3152}
3153
3154impl<'a> RustGenerator<'a> for InterfaceGenerator<'a> {
3155    fn resolve(&self) -> &'a Resolve {
3156        self.resolve
3157    }
3158
3159    fn ownership(&self) -> Ownership {
3160        self.generator.opts.ownership
3161    }
3162
3163    fn path_to_interface(&self, interface: InterfaceId) -> Option<String> {
3164        if let Some((cur, _, _)) = self.current_interface {
3165            if cur == interface {
3166                return None;
3167            }
3168        }
3169        let mut path_to_root = self.path_to_root();
3170        match &self.generator.interface_names[&interface] {
3171            InterfaceName::Remapped { name_at_root, .. } => path_to_root.push_str(name_at_root),
3172            InterfaceName::Path(path) => {
3173                for (i, name) in path.iter().enumerate() {
3174                    if i > 0 {
3175                        path_to_root.push_str("::");
3176                    }
3177                    path_to_root.push_str(name);
3178                }
3179            }
3180        }
3181        Some(path_to_root)
3182    }
3183
3184    fn push_str(&mut self, s: &str) {
3185        self.src.push_str(s);
3186    }
3187
3188    fn info(&self, ty: TypeId) -> TypeInfo {
3189        self.generator.types.get(ty)
3190    }
3191
3192    fn is_imported_interface(&self, interface: InterfaceId) -> bool {
3193        self.generator.interface_last_seen_as_import[&interface]
3194    }
3195
3196    fn wasmtime_path(&self) -> String {
3197        self.generator.wasmtime_path()
3198    }
3199}
3200
3201#[derive(Default)]
3202struct LinkOptionsBuilder {
3203    unstable_features: BTreeSet<String>,
3204}
3205impl LinkOptionsBuilder {
3206    fn has_any(&self) -> bool {
3207        !self.unstable_features.is_empty()
3208    }
3209    fn add_world(&mut self, resolve: &Resolve, id: &WorldId) {
3210        let world = &resolve.worlds[*id];
3211
3212        self.add_stability(&world.stability);
3213
3214        for (_, import) in world.imports.iter() {
3215            match import {
3216                WorldItem::Interface { id, stability } => {
3217                    self.add_stability(stability);
3218                    self.add_interface(resolve, id);
3219                }
3220                WorldItem::Function(f) => {
3221                    self.add_stability(&f.stability);
3222                }
3223                WorldItem::Type(t) => {
3224                    self.add_type(resolve, t);
3225                }
3226            }
3227        }
3228    }
3229    fn add_interface(&mut self, resolve: &Resolve, id: &InterfaceId) {
3230        let interface = &resolve.interfaces[*id];
3231
3232        self.add_stability(&interface.stability);
3233
3234        for (_, t) in interface.types.iter() {
3235            self.add_type(resolve, t);
3236        }
3237        for (_, f) in interface.functions.iter() {
3238            self.add_stability(&f.stability);
3239        }
3240    }
3241    fn add_type(&mut self, resolve: &Resolve, id: &TypeId) {
3242        let t = &resolve.types[*id];
3243        self.add_stability(&t.stability);
3244    }
3245    fn add_stability(&mut self, stability: &Stability) {
3246        match stability {
3247            Stability::Unstable { feature, .. } => {
3248                self.unstable_features.insert(feature.clone());
3249            }
3250            Stability::Stable { .. } | Stability::Unknown => {}
3251        }
3252    }
3253    fn write_struct(&self, src: &mut Source) {
3254        if !self.has_any() {
3255            return;
3256        }
3257
3258        let mut unstable_features = self.unstable_features.iter().cloned().collect::<Vec<_>>();
3259        unstable_features.sort();
3260
3261        uwriteln!(
3262            src,
3263            "
3264            /// Link-time configurations.
3265            #[derive(Clone, Debug, Default)]
3266            pub struct LinkOptions {{
3267            "
3268        );
3269
3270        for feature in unstable_features.iter() {
3271            let feature_rust_name = feature.to_snake_case();
3272            uwriteln!(src, "{feature_rust_name}: bool,");
3273        }
3274
3275        uwriteln!(src, "}}");
3276        uwriteln!(src, "impl LinkOptions {{");
3277
3278        for feature in unstable_features.iter() {
3279            let feature_rust_name = feature.to_snake_case();
3280            uwriteln!(
3281                src,
3282                "
3283                /// Enable members marked as `@unstable(feature = {feature})`
3284                pub fn {feature_rust_name}(&mut self, enabled: bool) -> &mut Self {{
3285                    self.{feature_rust_name} = enabled;
3286                    self
3287                }}
3288            "
3289            );
3290        }
3291
3292        uwriteln!(src, "}}");
3293    }
3294    fn write_impl_from_world(&self, src: &mut Source, path: &str) {
3295        if !self.has_any() {
3296            return;
3297        }
3298
3299        let mut unstable_features = self.unstable_features.iter().cloned().collect::<Vec<_>>();
3300        unstable_features.sort();
3301
3302        uwriteln!(
3303            src,
3304            "
3305            impl core::convert::From<LinkOptions> for {path}::LinkOptions {{
3306                fn from(src: LinkOptions) -> Self {{
3307                    (&src).into()
3308                }}
3309            }}
3310
3311            impl core::convert::From<&LinkOptions> for {path}::LinkOptions {{
3312                fn from(src: &LinkOptions) -> Self {{
3313                    let mut dest = Self::default();
3314        "
3315        );
3316
3317        for feature in unstable_features.iter() {
3318            let feature_rust_name = feature.to_snake_case();
3319            uwriteln!(src, "dest.{feature_rust_name}(src.{feature_rust_name});");
3320        }
3321
3322        uwriteln!(
3323            src,
3324            "
3325                    dest
3326                }}
3327            }}
3328        "
3329        );
3330    }
3331}
3332
3333struct FeatureGate {
3334    close: bool,
3335}
3336impl FeatureGate {
3337    fn open(src: &mut Source, stability: &Stability) -> FeatureGate {
3338        let close = if let Stability::Unstable { feature, .. } = stability {
3339            let feature_rust_name = feature.to_snake_case();
3340            uwrite!(src, "if options.{feature_rust_name} {{");
3341            true
3342        } else {
3343            false
3344        };
3345        Self { close }
3346    }
3347
3348    fn close(self, src: &mut Source) {
3349        if self.close {
3350            uwriteln!(src, "}}");
3351        }
3352    }
3353}
3354
3355/// Produce a string for tracing a function argument.
3356fn formatting_for_arg(
3357    name: &str,
3358    index: usize,
3359    ty: Type,
3360    resolve: &Resolve,
3361    flags: FunctionFlags,
3362) -> String {
3363    if !flags.contains(FunctionFlags::VERBOSE_TRACING) && type_contains_lists(ty, resolve) {
3364        return format!("{name} = tracing::field::debug(\"...\")");
3365    }
3366
3367    // Normal tracing.
3368    format!("{name} = tracing::field::debug(&arg{index})")
3369}
3370
3371/// Produce a string for tracing function results.
3372fn formatting_for_results(result: Option<Type>, resolve: &Resolve, flags: FunctionFlags) -> String {
3373    let contains_lists = match result {
3374        Some(ty) => type_contains_lists(ty, resolve),
3375        None => false,
3376    };
3377
3378    if !flags.contains(FunctionFlags::VERBOSE_TRACING) && contains_lists {
3379        return format!("result = tracing::field::debug(\"...\")");
3380    }
3381
3382    // Normal tracing.
3383    format!("result = tracing::field::debug(&r)")
3384}
3385
3386/// Test whether the given type contains lists.
3387///
3388/// Here, a `string` is not considered a list.
3389fn type_contains_lists(ty: Type, resolve: &Resolve) -> bool {
3390    match ty {
3391        Type::Id(id) => match &resolve.types[id].kind {
3392            TypeDefKind::Resource
3393            | TypeDefKind::Unknown
3394            | TypeDefKind::Flags(_)
3395            | TypeDefKind::Handle(_)
3396            | TypeDefKind::Enum(_)
3397            | TypeDefKind::Stream(_)
3398            | TypeDefKind::Future(_) => false,
3399            TypeDefKind::Option(ty) => type_contains_lists(*ty, resolve),
3400            TypeDefKind::Result(Result_ { ok, err }) => {
3401                option_type_contains_lists(*ok, resolve)
3402                    || option_type_contains_lists(*err, resolve)
3403            }
3404            TypeDefKind::Record(record) => record
3405                .fields
3406                .iter()
3407                .any(|field| type_contains_lists(field.ty, resolve)),
3408            TypeDefKind::Tuple(tuple) => tuple
3409                .types
3410                .iter()
3411                .any(|ty| type_contains_lists(*ty, resolve)),
3412            TypeDefKind::Variant(variant) => variant
3413                .cases
3414                .iter()
3415                .any(|case| option_type_contains_lists(case.ty, resolve)),
3416            TypeDefKind::Type(ty) => type_contains_lists(*ty, resolve),
3417            TypeDefKind::List(_) => true,
3418            TypeDefKind::FixedSizeList(..) => todo!(),
3419        },
3420
3421        // Technically strings are lists too, but we ignore that here because
3422        // they're usually short.
3423        _ => false,
3424    }
3425}
3426
3427fn option_type_contains_lists(ty: Option<Type>, resolve: &Resolve) -> bool {
3428    match ty {
3429        Some(ty) => type_contains_lists(ty, resolve),
3430        None => false,
3431    }
3432}
3433
3434/// When an interface `use`s a type from another interface, it creates a new TypeId
3435/// referring to the definition TypeId. Chase this chain of references down to
3436/// a TypeId for type's definition.
3437fn resolve_type_definition_id(resolve: &Resolve, mut id: TypeId) -> TypeId {
3438    loop {
3439        match resolve.types[id].kind {
3440            TypeDefKind::Type(Type::Id(def_id)) => id = def_id,
3441            _ => return id,
3442        }
3443    }
3444}
3445
3446fn rust_function_name(func: &Function) -> String {
3447    match func.kind {
3448        FunctionKind::Constructor(_) => "new".to_string(),
3449        FunctionKind::Method(_)
3450        | FunctionKind::Static(_)
3451        | FunctionKind::AsyncMethod(_)
3452        | FunctionKind::AsyncStatic(_)
3453        | FunctionKind::Freestanding
3454        | FunctionKind::AsyncFreestanding => to_rust_ident(func.item_name()),
3455    }
3456}
3457
3458fn func_field_name(resolve: &Resolve, func: &Function) -> String {
3459    let mut name = String::new();
3460    match func.kind {
3461        FunctionKind::Method(id) | FunctionKind::AsyncMethod(id) => {
3462            name.push_str("method-");
3463            name.push_str(resolve.types[id].name.as_ref().unwrap());
3464            name.push_str("-");
3465        }
3466        FunctionKind::Static(id) | FunctionKind::AsyncStatic(id) => {
3467            name.push_str("static-");
3468            name.push_str(resolve.types[id].name.as_ref().unwrap());
3469            name.push_str("-");
3470        }
3471        FunctionKind::Constructor(id) => {
3472            name.push_str("constructor-");
3473            name.push_str(resolve.types[id].name.as_ref().unwrap());
3474            name.push_str("-");
3475        }
3476        FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => {}
3477    }
3478    name.push_str(func.item_name());
3479    name.to_snake_case()
3480}
3481
3482fn get_resources<'a>(
3483    resolve: &'a Resolve,
3484    id: InterfaceId,
3485) -> impl Iterator<Item = (TypeId, &'a str)> + 'a {
3486    resolve.interfaces[id]
3487        .types
3488        .iter()
3489        .filter_map(move |(name, ty)| match &resolve.types[*ty].kind {
3490            TypeDefKind::Resource => Some((*ty, name.as_str())),
3491            _ => None,
3492        })
3493}
3494
3495fn get_resource_functions<'a>(resolve: &'a Resolve, resource_id: TypeId) -> Vec<&'a Function> {
3496    let resource = &resolve.types[resource_id];
3497    match resource.owner {
3498        TypeOwner::World(id) => resolve.worlds[id]
3499            .imports
3500            .values()
3501            .filter_map(|item| match item {
3502                WorldItem::Function(f) => Some(f),
3503                _ => None,
3504            })
3505            .filter(|f| f.kind.resource() == Some(resource_id))
3506            .collect(),
3507        TypeOwner::Interface(id) => resolve.interfaces[id]
3508            .functions
3509            .values()
3510            .filter(|f| f.kind.resource() == Some(resource_id))
3511            .collect::<Vec<_>>(),
3512        TypeOwner::None => {
3513            panic!("A resource must be owned by a world or interface");
3514        }
3515    }
3516}
3517
3518fn get_world_resources<'a>(
3519    resolve: &'a Resolve,
3520    id: WorldId,
3521) -> impl Iterator<Item = (TypeId, &'a str)> + 'a {
3522    resolve.worlds[id]
3523        .imports
3524        .iter()
3525        .filter_map(move |(name, item)| match item {
3526            WorldItem::Type(id) => match resolve.types[*id].kind {
3527                TypeDefKind::Resource => Some(match name {
3528                    WorldKey::Name(s) => (*id, s.as_str()),
3529                    WorldKey::Interface(_) => unreachable!(),
3530                }),
3531                _ => None,
3532            },
3533            _ => None,
3534        })
3535}