wit_bindgen_rust/
lib.rs

1use crate::interface::InterfaceGenerator;
2use anyhow::{bail, Result};
3use core::panic;
4use heck::*;
5use indexmap::{IndexMap, IndexSet};
6use std::collections::{BTreeMap, HashMap, HashSet};
7use std::fmt::{self, Write as _};
8use std::mem;
9use std::str::FromStr;
10use wit_bindgen_core::abi::{Bitcast, WasmType};
11use wit_bindgen_core::{
12    dealias, name_package_module, uwrite, uwriteln, wit_parser::*, Files, InterfaceGenerator as _,
13    Source, Types, WorldGenerator,
14};
15
16mod bindgen;
17mod interface;
18
19struct InterfaceName {
20    /// True when this interface name has been remapped through the use of `with` in the `bindgen!`
21    /// macro invocation.
22    remapped: bool,
23
24    /// The string name for this interface.
25    path: String,
26}
27
28#[derive(Default)]
29struct RustWasm {
30    types: Types,
31    src_preamble: Source,
32    src: Source,
33    opts: Opts,
34    import_modules: Vec<(String, Vec<String>)>,
35    export_modules: Vec<(String, Vec<String>)>,
36    skip: HashSet<String>,
37    interface_names: HashMap<InterfaceId, InterfaceName>,
38    /// Each imported and exported interface is stored in this map. Value indicates if last use was import.
39    interface_last_seen_as_import: HashMap<InterfaceId, bool>,
40    import_funcs_called: bool,
41    with_name_counter: usize,
42    // Track which interfaces and types are generated. Remapped interfaces and types provided via `with`
43    // are required to be used.
44    generated_types: HashSet<String>,
45    world: Option<WorldId>,
46
47    rt_module: IndexSet<RuntimeItem>,
48    export_macros: Vec<(String, String)>,
49
50    /// Maps wit interface and type names to their Rust identifiers
51    with: GenerationConfiguration,
52
53    future_payloads: IndexMap<String, String>,
54    stream_payloads: IndexMap<String, String>,
55}
56
57#[derive(Default)]
58struct GenerationConfiguration {
59    map: HashMap<String, TypeGeneration>,
60    generate_by_default: bool,
61}
62
63impl GenerationConfiguration {
64    fn get(&self, key: &str) -> Option<&TypeGeneration> {
65        self.map.get(key).or_else(|| {
66            self.generate_by_default
67                .then_some(&TypeGeneration::Generate)
68        })
69    }
70
71    fn insert(&mut self, name: String, generate: TypeGeneration) {
72        self.map.insert(name, generate);
73    }
74
75    fn iter(&self) -> impl Iterator<Item = (&String, &TypeGeneration)> {
76        self.map.iter()
77    }
78}
79
80/// How a wit interface or type should be rendered in Rust
81enum TypeGeneration {
82    /// Uses a Rust identifier defined elsewhere
83    Remap(String),
84    /// Define the interface or type with this bindgen invocation
85    Generate,
86}
87
88impl TypeGeneration {
89    /// Returns true if the interface or type should be defined with this bindgen invocation
90    fn generated(&self) -> bool {
91        match self {
92            TypeGeneration::Generate => true,
93            TypeGeneration::Remap(_) => false,
94        }
95    }
96}
97
98#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
99enum RuntimeItem {
100    AllocCrate,
101    StringType,
102    StdAllocModule,
103    VecType,
104    StringLift,
105    InvalidEnumDiscriminant,
106    CharLift,
107    BoolLift,
108    CabiDealloc,
109    RunCtorsOnce,
110    AsI32,
111    AsI64,
112    AsF32,
113    AsF64,
114    ResourceType,
115    BoxType,
116}
117
118#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
119pub enum ExportKey {
120    World,
121    Name(String),
122}
123
124#[cfg(feature = "clap")]
125fn parse_with(s: &str) -> Result<(String, WithOption), String> {
126    let (k, v) = s.split_once('=').ok_or_else(|| {
127        format!("expected string of form `<key>=<value>[,<key>=<value>...]`; got `{s}`")
128    })?;
129    let v = match v {
130        "generate" => WithOption::Generate,
131        other => WithOption::Path(other.to_string()),
132    };
133    Ok((k.to_string(), v))
134}
135
136#[derive(Default, Debug, Clone)]
137pub enum AsyncConfig {
138    #[default]
139    None,
140    Some {
141        imports: Vec<String>,
142        exports: Vec<String>,
143    },
144    All,
145}
146
147#[cfg(feature = "clap")]
148fn parse_async(s: &str) -> Result<AsyncConfig, String> {
149    Ok(match s {
150        "none" => AsyncConfig::None,
151        "all" => AsyncConfig::All,
152        _ => {
153            if let Some(values) = s.strip_prefix("some=") {
154                let mut imports = Vec::new();
155                let mut exports = Vec::new();
156                for value in values.split(',') {
157                    let error = || {
158                        Err(format!(
159                            "expected string of form `import:<name>` or `export:<name>`; got `{value}`"
160                        ))
161                    };
162                    if let Some((k, v)) = value.split_once(":") {
163                        match k {
164                            "import" => imports.push(v.into()),
165                            "export" => exports.push(v.into()),
166                            _ => return error(),
167                        }
168                    } else {
169                        return error();
170                    }
171                }
172                AsyncConfig::Some { imports, exports }
173            } else {
174                return Err(format!(
175                    "expected string of form `none`, `all`, or `some=<value>[,<value>...]`; got `{s}`"
176                ));
177            }
178        }
179    })
180}
181
182#[derive(Default, Debug, Clone)]
183#[cfg_attr(feature = "clap", derive(clap::Parser))]
184pub struct Opts {
185    /// Whether or not a formatter is executed to format generated code.
186    #[cfg_attr(feature = "clap", arg(long))]
187    pub format: bool,
188
189    /// If true, code generation should qualify any features that depend on
190    /// `std` with `cfg(feature = "std")`.
191    #[cfg_attr(feature = "clap", arg(long))]
192    pub std_feature: bool,
193
194    /// If true, code generation should pass borrowed string arguments as
195    /// `&[u8]` instead of `&str`. Strings are still required to be valid
196    /// UTF-8, but this avoids the need for Rust code to do its own UTF-8
197    /// validation if it doesn't already have a `&str`.
198    #[cfg_attr(feature = "clap", arg(long))]
199    pub raw_strings: bool,
200
201    /// Names of functions to skip generating bindings for.
202    #[cfg_attr(feature = "clap", arg(long))]
203    pub skip: Vec<String>,
204
205    /// If true, generate stub implementations for any exported functions,
206    /// interfaces, and/or resources.
207    #[cfg_attr(feature = "clap", arg(long))]
208    pub stubs: bool,
209
210    /// Optionally prefix any export names with the specified value.
211    ///
212    /// This is useful to avoid name conflicts when testing.
213    #[cfg_attr(feature = "clap", arg(long))]
214    pub export_prefix: Option<String>,
215
216    /// Whether to generate owning or borrowing type definitions.
217    ///
218    /// Valid values include:
219    ///
220    /// - `owning`: Generated types will be composed entirely of owning fields,
221    /// regardless of whether they are used as parameters to imports or not.
222    ///
223    /// - `borrowing`: Generated types used as parameters to imports will be
224    /// "deeply borrowing", i.e. contain references rather than owned values
225    /// when applicable.
226    ///
227    /// - `borrowing-duplicate-if-necessary`: As above, but generating distinct
228    /// types for borrowing and owning, if necessary.
229    #[cfg_attr(feature = "clap", arg(long, default_value_t = Ownership::Owning))]
230    pub ownership: Ownership,
231
232    /// The optional path to the wit-bindgen runtime module to use.
233    ///
234    /// This defaults to `wit_bindgen::rt`.
235    #[cfg_attr(feature = "clap", arg(long))]
236    pub runtime_path: Option<String>,
237
238    /// The optional path to the bitflags crate to use.
239    ///
240    /// This defaults to `wit_bindgen::bitflags`.
241    #[cfg_attr(feature = "clap", arg(long))]
242    pub bitflags_path: Option<String>,
243
244    /// Additional derive attributes to add to generated types. If using in a CLI, this flag can be
245    /// specified multiple times to add multiple attributes.
246    ///
247    /// These derive attributes will be added to any generated structs or enums
248    #[cfg_attr(feature = "clap", arg(long, short = 'd'))]
249    pub additional_derive_attributes: Vec<String>,
250
251    /// Variants and records to ignore when applying additional derive attributes.
252    ///
253    /// These names are specified as they are listed in the wit file, i.e. in kebab case.
254    /// This feature allows some variants and records to use types for which adding traits will cause
255    /// compilation to fail, such as serde::Deserialize on wasi:io/streams.
256    ///
257    #[cfg_attr(feature = "clap", arg(long))]
258    pub additional_derive_ignore: Vec<String>,
259
260    /// Remapping of wit interface and type names to Rust module names and types.
261    ///
262    /// Argument must be of the form `k=v` and this option can be passed
263    /// multiple times or one option can be comma separated, for example
264    /// `k1=v1,k2=v2`.
265    #[cfg_attr(feature = "clap", arg(long, value_parser = parse_with, value_delimiter = ','))]
266    pub with: Vec<(String, WithOption)>,
267
268    /// Indicates that all interfaces not specified in `with` should be
269    /// generated.
270    #[cfg_attr(feature = "clap", arg(long))]
271    pub generate_all: bool,
272
273    /// Add the specified suffix to the name of the custome section containing
274    /// the component type.
275    #[cfg_attr(feature = "clap", arg(long))]
276    pub type_section_suffix: Option<String>,
277
278    /// Disable a workaround used to prevent libc ctors/dtors from being invoked
279    /// too much.
280    #[cfg_attr(feature = "clap", arg(long))]
281    pub disable_run_ctors_once_workaround: bool,
282
283    /// Changes the default module used in the generated `export!` macro to
284    /// something other than `self`.
285    #[cfg_attr(feature = "clap", arg(long))]
286    pub default_bindings_module: Option<String>,
287
288    /// Alternative name to use for the `export!` macro if one is generated.
289    #[cfg_attr(feature = "clap", arg(long))]
290    pub export_macro_name: Option<String>,
291
292    /// Ensures that the `export!` macro will be defined as `pub` so it is a
293    /// candidate for being exported outside of the crate.
294    #[cfg_attr(feature = "clap", arg(long))]
295    pub pub_export_macro: bool,
296
297    /// Whether to generate unused structures, not generated by default (false)
298    #[cfg_attr(feature = "clap", arg(long))]
299    pub generate_unused_types: bool,
300
301    /// Whether or not to generate helper function/constants to help link custom
302    /// sections into the final output.
303    ///
304    /// Disabling this can shave a few bytes off a binary but makes
305    /// library-based usage of `generate!` prone to breakage.
306    #[cfg_attr(feature = "clap", arg(long))]
307    pub disable_custom_section_link_helpers: bool,
308
309    /// Determines which functions to lift or lower `async`, if any.
310    ///
311    /// Accepted values are:
312    ///     - none
313    ///     - all
314    ///     - some=<value>[,<value>...], where each <value> is of the form:
315    ///         - import:<name> or
316    ///         - export:<name>
317    #[cfg_attr(feature = "clap", arg(long = "async", value_parser = parse_async, default_value = "none"))]
318    pub async_: AsyncConfig,
319}
320
321impl Opts {
322    pub fn build(self) -> Box<dyn WorldGenerator> {
323        let mut r = RustWasm::new();
324        r.skip = self.skip.iter().cloned().collect();
325        r.opts = self;
326        Box::new(r)
327    }
328}
329
330impl RustWasm {
331    fn new() -> RustWasm {
332        RustWasm::default()
333    }
334
335    fn interface<'a>(
336        &'a mut self,
337        identifier: Identifier<'a>,
338        wasm_import_module: &'a str,
339        resolve: &'a Resolve,
340        in_import: bool,
341    ) -> InterfaceGenerator<'a> {
342        let mut sizes = SizeAlign::default();
343        sizes.fill(resolve);
344
345        InterfaceGenerator {
346            identifier,
347            wasm_import_module,
348            src: Source::default(),
349            in_import,
350            r#gen: self,
351            sizes,
352            resolve,
353            return_pointer_area_size: Default::default(),
354            return_pointer_area_align: Default::default(),
355            needs_runtime_module: false,
356        }
357    }
358
359    fn emit_modules(&mut self, modules: Vec<(String, Vec<String>)>) {
360        #[derive(Default)]
361        struct Module {
362            submodules: BTreeMap<String, Module>,
363            contents: Vec<String>,
364        }
365        let mut map = Module::default();
366        for (module, path) in modules {
367            let mut cur = &mut map;
368            for name in path[..path.len() - 1].iter() {
369                cur = cur
370                    .submodules
371                    .entry(name.clone())
372                    .or_insert(Module::default());
373            }
374            cur.contents.push(module);
375        }
376
377        emit(&mut self.src, map, &self.opts, true);
378        fn emit(me: &mut Source, module: Module, opts: &Opts, toplevel: bool) {
379            for (name, submodule) in module.submodules {
380                if toplevel {
381                    // Disable rustfmt. By default we already format the code
382                    // using prettyplease, so we don't want `cargo fmt` to create
383                    // extra diffs for users to deal with.
384                    if opts.format {
385                        uwriteln!(me, "#[rustfmt::skip]");
386                    }
387
388                    // Ignore dead-code and clippy warnings. If the bindings are
389                    // only used within a crate, and not exported to a different
390                    // crate, some parts may be unused, and that's ok.
391                    uwriteln!(me, "#[allow(dead_code, clippy::all)]");
392                }
393
394                uwriteln!(me, "pub mod {name} {{");
395                emit(me, submodule, opts, false);
396                uwriteln!(me, "}}");
397            }
398            for submodule in module.contents {
399                uwriteln!(me, "{submodule}");
400            }
401        }
402    }
403
404    fn runtime_path(&self) -> &str {
405        self.opts
406            .runtime_path
407            .as_deref()
408            .unwrap_or("wit_bindgen::rt")
409    }
410
411    fn bitflags_path(&self) -> String {
412        self.opts
413            .bitflags_path
414            .to_owned()
415            .unwrap_or(format!("{}::bitflags", self.runtime_path()))
416    }
417
418    fn async_support_path(&self) -> String {
419        format!("{}::async_support", self.runtime_path())
420    }
421
422    fn name_interface(
423        &mut self,
424        resolve: &Resolve,
425        id: InterfaceId,
426        name: &WorldKey,
427        is_export: bool,
428    ) -> Result<bool> {
429        let with_name = resolve.name_world_key(name);
430        let Some(remapping) = self.with.get(&with_name) else {
431            bail!(MissingWith(with_name));
432        };
433        self.generated_types.insert(with_name);
434        let entry = match remapping {
435            TypeGeneration::Remap(remapped_path) => {
436                let name = format!("__with_name{}", self.with_name_counter);
437                self.with_name_counter += 1;
438                uwriteln!(self.src, "use {remapped_path} as {name};");
439                InterfaceName {
440                    remapped: true,
441                    path: name,
442                }
443            }
444            TypeGeneration::Generate => {
445                let path = compute_module_path(name, resolve, is_export).join("::");
446
447                InterfaceName {
448                    remapped: false,
449                    path,
450                }
451            }
452        };
453
454        let remapped = entry.remapped;
455        self.interface_names.insert(id, entry);
456
457        Ok(remapped)
458    }
459
460    fn finish_runtime_module(&mut self) {
461        if self.rt_module.is_empty() {
462            return;
463        }
464
465        // As above, disable rustfmt, as we use prettyplease.
466        if self.opts.format {
467            uwriteln!(self.src, "#[rustfmt::skip]");
468        }
469
470        self.src.push_str("mod _rt {\n");
471        self.src.push_str("#![allow(dead_code, clippy::all)]\n");
472        let mut emitted = IndexSet::new();
473        while !self.rt_module.is_empty() {
474            for item in mem::take(&mut self.rt_module) {
475                if emitted.insert(item) {
476                    self.emit_runtime_item(item);
477                }
478            }
479        }
480        self.src.push_str("}\n");
481
482        if !self.future_payloads.is_empty() {
483            let async_support = self.async_support_path();
484            self.src.push_str(&format!(
485                "\
486pub mod wit_future {{
487    #![allow(dead_code, unused_variables, clippy::all)]
488
489    #[doc(hidden)]
490    pub trait FuturePayload: Unpin + Sized + 'static {{
491        const VTABLE: &'static {async_support}::FutureVtable<Self>;
492    }}"
493            ));
494            for code in self.future_payloads.values() {
495                self.src.push_str(code);
496            }
497            self.src.push_str(&format!(
498                "\
499    /// Creates a new Component Model `future` with the specified payload type.
500    pub fn new<T: FuturePayload>() -> ({async_support}::FutureWriter<T>, {async_support}::FutureReader<T>) {{
501        unsafe {{ {async_support}::future_new::<T>(T::VTABLE) }}
502    }}
503}}
504                ",
505            ));
506        }
507
508        if !self.stream_payloads.is_empty() {
509            let async_support = self.async_support_path();
510            self.src.push_str(&format!(
511                "\
512pub mod wit_stream {{
513    #![allow(dead_code, unused_variables, clippy::all)]
514
515    pub trait StreamPayload: Unpin + Sized + 'static {{
516        const VTABLE: &'static {async_support}::StreamVtable<Self>;
517    }}"
518            ));
519            for code in self.stream_payloads.values() {
520                self.src.push_str(code);
521            }
522            self.src.push_str(
523                &format!("\
524    /// Creates a new Component Model `stream` with the specified payload type.
525    pub fn new<T: StreamPayload>() -> ({async_support}::StreamWriter<T>, {async_support}::StreamReader<T>) {{
526        unsafe {{ {async_support}::stream_new::<T>(T::VTABLE) }}
527    }}
528}}
529                "),
530            );
531        }
532    }
533
534    fn emit_runtime_item(&mut self, item: RuntimeItem) {
535        match item {
536            RuntimeItem::AllocCrate => {
537                uwriteln!(self.src, "extern crate alloc as alloc_crate;");
538            }
539            RuntimeItem::StdAllocModule => {
540                self.rt_module.insert(RuntimeItem::AllocCrate);
541                uwriteln!(self.src, "pub use alloc_crate::alloc;");
542            }
543            RuntimeItem::StringType => {
544                self.rt_module.insert(RuntimeItem::AllocCrate);
545                uwriteln!(self.src, "pub use alloc_crate::string::String;");
546            }
547            RuntimeItem::BoxType => {
548                self.rt_module.insert(RuntimeItem::AllocCrate);
549                uwriteln!(self.src, "pub use alloc_crate::boxed::Box;");
550            }
551            RuntimeItem::VecType => {
552                self.rt_module.insert(RuntimeItem::AllocCrate);
553                uwriteln!(self.src, "pub use alloc_crate::vec::Vec;");
554            }
555            RuntimeItem::CabiDealloc => {
556                self.rt_module.insert(RuntimeItem::StdAllocModule);
557                self.src.push_str(
558                    "\
559pub unsafe fn cabi_dealloc(ptr: *mut u8, size: usize, align: usize) {
560    if size == 0 {
561        return;
562    }
563    let layout = alloc::Layout::from_size_align_unchecked(size, align);
564    alloc::dealloc(ptr, layout);
565}
566                    ",
567                );
568            }
569
570            RuntimeItem::StringLift => {
571                self.rt_module.insert(RuntimeItem::StringType);
572                self.src.push_str(
573                    "\
574pub unsafe fn string_lift(bytes: Vec<u8>) -> String {
575    if cfg!(debug_assertions) {
576        String::from_utf8(bytes).unwrap()
577    } else {
578        String::from_utf8_unchecked(bytes)
579    }
580}
581                    ",
582                );
583            }
584
585            RuntimeItem::InvalidEnumDiscriminant => {
586                self.src.push_str(
587                    "\
588pub unsafe fn invalid_enum_discriminant<T>() -> T {
589    if cfg!(debug_assertions) {
590        panic!(\"invalid enum discriminant\")
591    } else {
592        unsafe { core::hint::unreachable_unchecked() }
593    }
594}
595                    ",
596                );
597            }
598
599            RuntimeItem::CharLift => {
600                self.src.push_str(
601                    "\
602pub unsafe fn char_lift(val: u32) -> char {
603    if cfg!(debug_assertions) {
604        core::char::from_u32(val).unwrap()
605    } else {
606        core::char::from_u32_unchecked(val)
607    }
608}
609                    ",
610                );
611            }
612
613            RuntimeItem::BoolLift => {
614                self.src.push_str(
615                    "\
616pub unsafe fn bool_lift(val: u8) -> bool {
617    if cfg!(debug_assertions) {
618        match val {
619            0 => false,
620            1 => true,
621            _ => panic!(\"invalid bool discriminant\"),
622        }
623    } else {
624        val != 0
625    }
626}
627                    ",
628                );
629            }
630
631            RuntimeItem::RunCtorsOnce => {
632                let rt = self.runtime_path();
633                self.src.push_str(&format!(
634                    r#"
635#[cfg(target_arch = "wasm32")]
636pub fn run_ctors_once() {{
637    {rt}::run_ctors_once();
638}}
639                    "#,
640                ));
641            }
642
643            RuntimeItem::AsI32 => {
644                self.emit_runtime_as_trait(
645                    "i32",
646                    &["i32", "u32", "i16", "u16", "i8", "u8", "char", "usize"],
647                );
648            }
649
650            RuntimeItem::AsI64 => {
651                self.emit_runtime_as_trait("i64", &["i64", "u64"]);
652            }
653
654            RuntimeItem::AsF32 => {
655                self.emit_runtime_as_trait("f32", &["f32"]);
656            }
657
658            RuntimeItem::AsF64 => {
659                self.emit_runtime_as_trait("f64", &["f64"]);
660            }
661
662            RuntimeItem::ResourceType => {
663                self.src.push_str(
664                    r#"
665
666use core::fmt;
667use core::marker;
668use core::sync::atomic::{AtomicU32, Ordering::Relaxed};
669
670/// A type which represents a component model resource, either imported or
671/// exported into this component.
672///
673/// This is a low-level wrapper which handles the lifetime of the resource
674/// (namely this has a destructor). The `T` provided defines the component model
675/// intrinsics that this wrapper uses.
676///
677/// One of the chief purposes of this type is to provide `Deref` implementations
678/// to access the underlying data when it is owned.
679///
680/// This type is primarily used in generated code for exported and imported
681/// resources.
682#[repr(transparent)]
683pub struct Resource<T: WasmResource> {
684    // NB: This would ideally be `u32` but it is not. The fact that this has
685    // interior mutability is not exposed in the API of this type except for the
686    // `take_handle` method which is supposed to in theory be private.
687    //
688    // This represents, almost all the time, a valid handle value. When it's
689    // invalid it's stored as `u32::MAX`.
690    handle: AtomicU32,
691    _marker: marker::PhantomData<T>,
692}
693
694/// A trait which all wasm resources implement, namely providing the ability to
695/// drop a resource.
696///
697/// This generally is implemented by generated code, not user-facing code.
698#[allow(clippy::missing_safety_doc)]
699pub unsafe trait WasmResource {
700    /// Invokes the `[resource-drop]...` intrinsic.
701    unsafe fn drop(handle: u32);
702}
703
704impl<T: WasmResource> Resource<T> {
705    #[doc(hidden)]
706    pub unsafe fn from_handle(handle: u32) -> Self {
707        debug_assert!(handle != u32::MAX);
708        Self {
709            handle: AtomicU32::new(handle),
710            _marker: marker::PhantomData,
711        }
712    }
713
714    /// Takes ownership of the handle owned by `resource`.
715    ///
716    /// Note that this ideally would be `into_handle` taking `Resource<T>` by
717    /// ownership. The code generator does not enable that in all situations,
718    /// unfortunately, so this is provided instead.
719    ///
720    /// Also note that `take_handle` is in theory only ever called on values
721    /// owned by a generated function. For example a generated function might
722    /// take `Resource<T>` as an argument but then call `take_handle` on a
723    /// reference to that argument. In that sense the dynamic nature of
724    /// `take_handle` should only be exposed internally to generated code, not
725    /// to user code.
726    #[doc(hidden)]
727    pub fn take_handle(resource: &Resource<T>) -> u32 {
728        resource.handle.swap(u32::MAX, Relaxed)
729    }
730
731    #[doc(hidden)]
732    pub fn handle(resource: &Resource<T>) -> u32 {
733        resource.handle.load(Relaxed)
734    }
735}
736
737impl<T: WasmResource> fmt::Debug for Resource<T> {
738    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
739        f.debug_struct("Resource")
740            .field("handle", &self.handle)
741            .finish()
742    }
743}
744
745impl<T: WasmResource> Drop for Resource<T> {
746    fn drop(&mut self) {
747        unsafe {
748            match self.handle.load(Relaxed) {
749                // If this handle was "taken" then don't do anything in the
750                // destructor.
751                u32::MAX => {}
752
753                // ... but otherwise do actually destroy it with the imported
754                // component model intrinsic as defined through `T`.
755                other => T::drop(other),
756            }
757        }
758    }
759}
760                    "#,
761                );
762            }
763        }
764    }
765
766    // This is a workaround for in the bindings sometimes we've got `&i32` and
767    // sometimes we've got `i32` but that should all be able to be worked with
768    // as `i32`, so these helper functions are used to boil away the
769    // indirection.
770    fn emit_runtime_as_trait(&mut self, ty: &str, to_convert: &[&str]) {
771        let upcase = ty.to_uppercase();
772        self.src.push_str(&format!(
773            r#"
774pub fn as_{ty}<T: As{upcase}>(t: T) -> {ty} {{
775    t.as_{ty}()
776}}
777
778pub trait As{upcase} {{
779    fn as_{ty}(self) -> {ty};
780}}
781
782impl<'a, T: Copy + As{upcase}> As{upcase} for &'a T {{
783    fn as_{ty}(self) -> {ty} {{
784        (*self).as_{ty}()
785    }}
786}}
787            "#
788        ));
789
790        for to_convert in to_convert {
791            self.src.push_str(&format!(
792                r#"
793impl As{upcase} for {to_convert} {{
794    #[inline]
795    fn as_{ty}(self) -> {ty} {{
796        self as {ty}
797    }}
798}}
799                "#
800            ));
801        }
802    }
803
804    /// Generates an `export!` macro for the `world_id` specified.
805    ///
806    /// This will generate a macro which will then itself invoke all the
807    /// other macros collected in `self.export_macros` prior. All these macros
808    /// are woven together in this single invocation.
809    fn finish_export_macro(&mut self, resolve: &Resolve, world_id: WorldId) {
810        if self.export_macros.is_empty() {
811            return;
812        }
813        let world = &resolve.worlds[world_id];
814        let world_name = world.name.to_snake_case();
815
816        let default_bindings_module = self
817            .opts
818            .default_bindings_module
819            .clone()
820            .unwrap_or("self".to_string());
821        let (macro_export, use_vis) = if self.opts.pub_export_macro {
822            ("#[macro_export]", "pub")
823        } else {
824            ("", "pub(crate)")
825        };
826        let export_macro_name = self
827            .opts
828            .export_macro_name
829            .as_deref()
830            .unwrap_or("export")
831            .to_string();
832        uwriteln!(
833            self.src,
834            r#"
835/// Generates `#[unsafe(no_mangle)]` functions to export the specified type as
836/// the root implementation of all generated traits.
837///
838/// For more information see the documentation of `wit_bindgen::generate!`.
839///
840/// ```rust
841/// # macro_rules! {export_macro_name} {{ ($($t:tt)*) => (); }}
842/// # trait Guest {{}}
843/// struct MyType;
844///
845/// impl Guest for MyType {{
846///     // ...
847/// }}
848///
849/// {export_macro_name}!(MyType);
850/// ```
851#[allow(unused_macros)]
852#[doc(hidden)]
853{macro_export}
854macro_rules! __export_{world_name}_impl {{
855    ($ty:ident) => ({default_bindings_module}::{export_macro_name}!($ty with_types_in {default_bindings_module}););
856    ($ty:ident with_types_in $($path_to_types_root:tt)*) => ("#
857        );
858        for (name, path_to_types) in self.export_macros.iter() {
859            let mut path = "$($path_to_types_root)*".to_string();
860            if !path_to_types.is_empty() {
861                path.push_str("::");
862                path.push_str(path_to_types)
863            }
864            uwriteln!(self.src, "{path}::{name}!($ty with_types_in {path});");
865        }
866
867        // See comments in `finish` for why this conditionally happens here.
868        if self.opts.pub_export_macro {
869            uwriteln!(self.src, "const _: () = {{");
870            self.emit_custom_section(resolve, world_id, "imports and exports", None);
871            uwriteln!(self.src, "}};");
872        }
873
874        uwriteln!(self.src, ")\n}}");
875
876        uwriteln!(
877            self.src,
878            "#[doc(inline)]\n\
879            {use_vis} use __export_{world_name}_impl as {export_macro_name};"
880        );
881
882        if self.opts.stubs {
883            uwriteln!(self.src, "export!(Stub);");
884        }
885    }
886
887    /// Generates a `#[link_section]` custom section to get smuggled through
888    /// `wasm-ld`.
889    ///
890    /// This custom section is an encoding of the component metadata and will be
891    /// used as part of the `wit-component`-based componentization process.
892    ///
893    /// The `section_suffix` here is used to distinguish the multiple sections
894    /// that this generator emits, and `func_name` is an optional function to
895    /// generate next to this which is used to force rustc to at least visit
896    /// this `static` and codegen it.
897    fn emit_custom_section(
898        &mut self,
899        resolve: &Resolve,
900        world_id: WorldId,
901        section_suffix: &str,
902        func_name: Option<&str>,
903    ) {
904        self.src.push_str("\n#[cfg(target_arch = \"wasm32\")]\n");
905
906        // The custom section name here must start with "component-type" but
907        // otherwise is attempted to be unique here to ensure that this doesn't get
908        // concatenated to other custom sections by LLD by accident since LLD will
909        // concatenate custom sections of the same name.
910        let opts_suffix = self.opts.type_section_suffix.as_deref().unwrap_or("");
911        let world = &resolve.worlds[world_id];
912        let world_name = &world.name;
913        let pkg = &resolve.packages[world.package.unwrap()].name;
914        let version = env!("CARGO_PKG_VERSION");
915        self.src.push_str(&format!(
916            "#[unsafe(link_section = \"component-type:wit-bindgen:{version}:\
917             {pkg}:{world_name}:{section_suffix}{opts_suffix}\")]\n"
918        ));
919
920        let mut producers = wasm_metadata::Producers::empty();
921        producers.add(
922            "processed-by",
923            env!("CARGO_PKG_NAME"),
924            env!("CARGO_PKG_VERSION"),
925        );
926
927        let component_type = wit_component::metadata::encode(
928            resolve,
929            world_id,
930            wit_component::StringEncoding::UTF8,
931            Some(&producers),
932        )
933        .unwrap();
934
935        self.src.push_str("#[doc(hidden)]\n");
936        self.src.push_str("#[allow(clippy::octal_escapes)]\n");
937        self.src.push_str(&format!(
938            "pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; {}] = *b\"\\\n",
939            component_type.len()
940        ));
941        let old_indent = self.src.set_indent(0);
942        let mut line_length = 0;
943        let s = self.src.as_mut_string();
944        for byte in component_type.iter() {
945            if line_length >= 80 {
946                s.push_str("\\\n");
947                line_length = 0;
948            }
949            match byte {
950                b'\\' => {
951                    s.push_str("\\\\");
952                    line_length += 2;
953                }
954                b'"' => {
955                    s.push_str("\\\"");
956                    line_length += 2;
957                }
958                b if b.is_ascii_alphanumeric() || b.is_ascii_punctuation() => {
959                    s.push(char::from(*byte));
960                    line_length += 1;
961                }
962                0 => {
963                    s.push_str("\\0");
964                    line_length += 2;
965                }
966                _ => {
967                    uwrite!(s, "\\x{:02x}", byte);
968                    line_length += 4;
969                }
970            }
971        }
972
973        self.src.push_str("\";\n");
974        self.src.set_indent(old_indent);
975
976        if let Some(func_name) = func_name {
977            let rt = self.runtime_path().to_string();
978            uwriteln!(
979                self.src,
980                "
981                #[inline(never)]
982                #[doc(hidden)]
983                pub fn {func_name}() {{
984                    {rt}::maybe_link_cabi_realloc();
985                }}
986            ",
987            );
988        }
989    }
990}
991
992impl WorldGenerator for RustWasm {
993    fn preprocess(&mut self, resolve: &Resolve, world: WorldId) {
994        wit_bindgen_core::generated_preamble(&mut self.src_preamble, env!("CARGO_PKG_VERSION"));
995
996        // Render some generator options to assist with debugging and/or to help
997        // recreate it if the original generation command is lost.
998        uwriteln!(self.src_preamble, "// Options used:");
999        if self.opts.std_feature {
1000            uwriteln!(self.src_preamble, "//   * std_feature");
1001        }
1002        if self.opts.raw_strings {
1003            uwriteln!(self.src_preamble, "//   * raw_strings");
1004        }
1005        if !self.opts.skip.is_empty() {
1006            uwriteln!(self.src_preamble, "//   * skip: {:?}", self.opts.skip);
1007        }
1008        if self.opts.stubs {
1009            uwriteln!(self.src_preamble, "//   * stubs");
1010        }
1011        if let Some(export_prefix) = &self.opts.export_prefix {
1012            uwriteln!(
1013                self.src_preamble,
1014                "//   * export_prefix: {:?}",
1015                export_prefix
1016            );
1017        }
1018        if let Some(runtime_path) = &self.opts.runtime_path {
1019            uwriteln!(self.src_preamble, "//   * runtime_path: {:?}", runtime_path);
1020        }
1021        if let Some(bitflags_path) = &self.opts.bitflags_path {
1022            uwriteln!(
1023                self.src_preamble,
1024                "//   * bitflags_path: {:?}",
1025                bitflags_path
1026            );
1027        }
1028        if !matches!(self.opts.ownership, Ownership::Owning) {
1029            uwriteln!(
1030                self.src_preamble,
1031                "//   * ownership: {:?}",
1032                self.opts.ownership
1033            );
1034        }
1035        if !self.opts.additional_derive_attributes.is_empty() {
1036            uwriteln!(
1037                self.src_preamble,
1038                "//   * additional derives {:?}",
1039                self.opts.additional_derive_attributes
1040            );
1041        }
1042        if !self.opts.additional_derive_ignore.is_empty() {
1043            uwriteln!(
1044                self.src_preamble,
1045                "//   * additional derives ignored {:?}",
1046                self.opts.additional_derive_ignore
1047            );
1048        }
1049        for (k, v) in self.opts.with.iter() {
1050            uwriteln!(self.src_preamble, "//   * with {k:?} = {v}");
1051        }
1052        if let Some(type_section_suffix) = &self.opts.type_section_suffix {
1053            uwriteln!(
1054                self.src_preamble,
1055                "//   * type_section_suffix: {:?}",
1056                type_section_suffix
1057            );
1058        }
1059        if let Some(default) = &self.opts.default_bindings_module {
1060            uwriteln!(
1061                self.src_preamble,
1062                "//   * default-bindings-module: {default:?}"
1063            );
1064        }
1065        if self.opts.disable_run_ctors_once_workaround {
1066            uwriteln!(
1067                self.src_preamble,
1068                "//   * disable-run-ctors-once-workaround"
1069            );
1070        }
1071        if let Some(s) = &self.opts.export_macro_name {
1072            uwriteln!(self.src_preamble, "//   * export-macro-name: {s}");
1073        }
1074        if self.opts.pub_export_macro {
1075            uwriteln!(self.src_preamble, "//   * pub-export-macro");
1076        }
1077        if self.opts.generate_unused_types {
1078            uwriteln!(self.src_preamble, "//   * generate_unused_types");
1079        }
1080        if self.opts.disable_custom_section_link_helpers {
1081            uwriteln!(
1082                self.src_preamble,
1083                "//   * disable_custom_section_link_helpers"
1084            );
1085        }
1086        self.types.analyze(resolve);
1087        self.world = Some(world);
1088
1089        let world = &resolve.worlds[world];
1090        // Specify that all imports local to the world's package should be generated
1091        for (key, item) in world.imports.iter().chain(world.exports.iter()) {
1092            if let WorldItem::Interface { id, .. } = item {
1093                if resolve.interfaces[*id].package == world.package {
1094                    let name = resolve.name_world_key(key);
1095                    if self.with.get(&name).is_none() {
1096                        self.with.insert(name, TypeGeneration::Generate);
1097                    }
1098                }
1099            }
1100        }
1101
1102        for (k, v) in self.opts.with.iter() {
1103            self.with.insert(k.clone(), v.clone().into());
1104        }
1105        self.with.generate_by_default = self.opts.generate_all;
1106    }
1107
1108    fn import_interface(
1109        &mut self,
1110        resolve: &Resolve,
1111        name: &WorldKey,
1112        id: InterfaceId,
1113        _files: &mut Files,
1114    ) -> Result<()> {
1115        let mut to_define = Vec::new();
1116        for (name, ty_id) in resolve.interfaces[id].types.iter() {
1117            let full_name = full_wit_type_name(resolve, *ty_id);
1118            if let Some(type_gen) = self.with.get(&full_name) {
1119                // skip type definition generation for remapped types
1120                if type_gen.generated() {
1121                    to_define.push((name, ty_id));
1122                }
1123            } else {
1124                to_define.push((name, ty_id));
1125            }
1126            self.generated_types.insert(full_name);
1127        }
1128
1129        self.interface_last_seen_as_import.insert(id, true);
1130        let wasm_import_module = resolve.name_world_key(name);
1131        let mut r#gen = self.interface(
1132            Identifier::Interface(id, name),
1133            &wasm_import_module,
1134            resolve,
1135            true,
1136        );
1137        let (snake, module_path) = r#gen.start_append_submodule(name);
1138        if r#gen.r#gen.name_interface(resolve, id, name, false)? {
1139            return Ok(());
1140        }
1141
1142        for (name, ty_id) in to_define {
1143            r#gen.define_type(&name, *ty_id);
1144        }
1145
1146        r#gen.generate_imports(resolve.interfaces[id].functions.values(), Some(name));
1147
1148        let docs = &resolve.interfaces[id].docs;
1149
1150        r#gen.finish_append_submodule(&snake, module_path, docs);
1151
1152        Ok(())
1153    }
1154
1155    fn import_funcs(
1156        &mut self,
1157        resolve: &Resolve,
1158        world: WorldId,
1159        funcs: &[(&str, &Function)],
1160        _files: &mut Files,
1161    ) {
1162        self.import_funcs_called = true;
1163
1164        let mut r#gen = self.interface(Identifier::World(world), "$root", resolve, true);
1165
1166        r#gen.generate_imports(funcs.iter().map(|(_, func)| *func), None);
1167
1168        let src = r#gen.finish();
1169        self.src.push_str(&src);
1170    }
1171
1172    fn export_interface(
1173        &mut self,
1174        resolve: &Resolve,
1175        name: &WorldKey,
1176        id: InterfaceId,
1177        _files: &mut Files,
1178    ) -> Result<()> {
1179        let mut to_define = Vec::new();
1180        for (name, ty_id) in resolve.interfaces[id].types.iter() {
1181            let full_name = full_wit_type_name(resolve, *ty_id);
1182            if let Some(type_gen) = self.with.get(&full_name) {
1183                // skip type definition generation for remapped types
1184                if type_gen.generated() {
1185                    to_define.push((name, ty_id));
1186                }
1187            } else {
1188                to_define.push((name, ty_id));
1189            }
1190            self.generated_types.insert(full_name);
1191        }
1192
1193        self.interface_last_seen_as_import.insert(id, false);
1194        let wasm_import_module = format!("[export]{}", resolve.name_world_key(name));
1195        let mut r#gen = self.interface(
1196            Identifier::Interface(id, name),
1197            &wasm_import_module,
1198            resolve,
1199            false,
1200        );
1201        let (snake, module_path) = r#gen.start_append_submodule(name);
1202        if r#gen.r#gen.name_interface(resolve, id, name, true)? {
1203            return Ok(());
1204        }
1205
1206        for (name, ty_id) in to_define {
1207            r#gen.define_type(&name, *ty_id);
1208        }
1209
1210        let macro_name =
1211            r#gen.generate_exports(Some((id, name)), resolve.interfaces[id].functions.values())?;
1212
1213        let docs = &resolve.interfaces[id].docs;
1214
1215        r#gen.finish_append_submodule(&snake, module_path, docs);
1216        self.export_macros
1217            .push((macro_name, self.interface_names[&id].path.clone()));
1218
1219        if self.opts.stubs {
1220            let world_id = self.world.unwrap();
1221            let mut r#gen = self.interface(
1222                Identifier::World(world_id),
1223                &wasm_import_module,
1224                resolve,
1225                false,
1226            );
1227            r#gen.generate_stub(Some((id, name)), resolve.interfaces[id].functions.values());
1228            let stub = r#gen.finish();
1229            self.src.push_str(&stub);
1230        }
1231        Ok(())
1232    }
1233
1234    fn export_funcs(
1235        &mut self,
1236        resolve: &Resolve,
1237        world: WorldId,
1238        funcs: &[(&str, &Function)],
1239        _files: &mut Files,
1240    ) -> Result<()> {
1241        let mut r#gen = self.interface(Identifier::World(world), "[export]$root", resolve, false);
1242        let macro_name = r#gen.generate_exports(None, funcs.iter().map(|f| f.1))?;
1243        let src = r#gen.finish();
1244        self.src.push_str(&src);
1245        self.export_macros.push((macro_name, String::new()));
1246
1247        if self.opts.stubs {
1248            let mut r#gen =
1249                self.interface(Identifier::World(world), "[export]$root", resolve, false);
1250            r#gen.generate_stub(None, funcs.iter().map(|f| f.1));
1251            let stub = r#gen.finish();
1252            self.src.push_str(&stub);
1253        }
1254        Ok(())
1255    }
1256
1257    fn import_types(
1258        &mut self,
1259        resolve: &Resolve,
1260        world: WorldId,
1261        types: &[(&str, TypeId)],
1262        _files: &mut Files,
1263    ) {
1264        let mut to_define = Vec::new();
1265        for (name, ty_id) in types {
1266            let full_name = full_wit_type_name(resolve, *ty_id);
1267            if let Some(type_gen) = self.with.get(&full_name) {
1268                // skip type definition generation for remapped types
1269                if type_gen.generated() {
1270                    to_define.push((name, ty_id));
1271                }
1272            } else {
1273                to_define.push((name, ty_id));
1274            }
1275            self.generated_types.insert(full_name);
1276        }
1277        let mut r#gen = self.interface(Identifier::World(world), "$root", resolve, true);
1278        for (name, ty) in to_define {
1279            r#gen.define_type(name, *ty);
1280        }
1281        let src = r#gen.finish();
1282        self.src.push_str(&src);
1283    }
1284
1285    fn finish_imports(&mut self, resolve: &Resolve, world: WorldId, files: &mut Files) {
1286        if !self.import_funcs_called {
1287            // We call `import_funcs` even if the world doesn't import any
1288            // functions since one of the side effects of that method is to
1289            // generate `struct`s for any imported resources.
1290            self.import_funcs(resolve, world, &[], files);
1291        }
1292    }
1293
1294    fn finish(&mut self, resolve: &Resolve, world: WorldId, files: &mut Files) -> Result<()> {
1295        let name = &resolve.worlds[world].name;
1296
1297        let imports = mem::take(&mut self.import_modules);
1298        self.emit_modules(imports);
1299        let exports = mem::take(&mut self.export_modules);
1300        self.emit_modules(exports);
1301
1302        self.finish_runtime_module();
1303        self.finish_export_macro(resolve, world);
1304
1305        // This is a bit tricky, but we sometimes want to "split" the `world` in
1306        // two and only encode the imports here.
1307        //
1308        // First, a primer. Each invocation of `generate!` has a WIT world as
1309        // input. This is one of the first steps in the build process as wasm
1310        // hasn't even been produced yet. One of the later stages of the build
1311        // process will be to emit a component, currently through the
1312        // `wit-component` crate. That crate relies on custom sections being
1313        // present to describe what WIT worlds were present in the wasm binary.
1314        //
1315        // Additionally a `generate!` macro is not the only thing in a binary.
1316        // There might be multiple `generate!` macros, perhaps even across
1317        // different languages. To handle all this `wit-component` will decode
1318        // each custom section and "union" everything together. Unioning in
1319        // general should work so long as everything has the same structure and
1320        // came from the same source.
1321        //
1322        // The problem here is that if `pub_export_macros` is turned on, meaning
1323        // that the macros are supposed to be used across crates, then neither
1324        // the imports nor the exports of this world are guaranteed to be used.
1325        // For imports that's ok because `wit-component` will drop any unused
1326        // imports automatically. For exports that's a problem because
1327        // `wit-component` unconditionally looks for a definition for all
1328        // exports.
1329        //
1330        // When `pub_export_macros` is turned on, and cross-crate usage of the
1331        // macro is expected, this is solved by emitting two custom sections:
1332        //
1333        // 1. The first section emitted here only has the imports of the world.
1334        //    This slimmed down world should be able to be unioned with the
1335        //    first world trivially and will be GC'd by `wit-component` if not
1336        //    used.
1337        // 2. The second section is emitted as part of the generated `export!`
1338        //    macro invocation. That world has all the export information as
1339        //    well as all the import information.
1340        //
1341        // In the end this is hoped to ensure that usage of crates like `wasi`
1342        // don't accidentally try to export things, for example.
1343        let mut resolve_copy;
1344        let (resolve_to_encode, world_to_encode) = if self.opts.pub_export_macro {
1345            resolve_copy = resolve.clone();
1346            let world_copy = resolve_copy.worlds.alloc(World {
1347                exports: Default::default(),
1348                name: format!("{name}-with-all-of-its-exports-removed"),
1349                ..resolve.worlds[world].clone()
1350            });
1351            (&resolve_copy, world_copy)
1352        } else {
1353            (resolve, world)
1354        };
1355        self.emit_custom_section(
1356            resolve_to_encode,
1357            world_to_encode,
1358            "encoded world",
1359            if self.opts.disable_custom_section_link_helpers {
1360                None
1361            } else {
1362                Some("__link_custom_section_describing_imports")
1363            },
1364        );
1365
1366        if self.opts.stubs {
1367            self.src.push_str("\n#[derive(Debug)]\npub struct Stub;\n");
1368        }
1369
1370        let mut src = mem::take(&mut self.src);
1371        if self.opts.format {
1372            let syntax_tree = syn::parse_file(src.as_str()).unwrap();
1373            *src.as_mut_string() = prettyplease::unparse(&syntax_tree);
1374        }
1375
1376        // Prepend the preamble. We do this after formatting because
1377        // `syn::parse_file` + `prettyplease::unparse` does not preserve comments.
1378        let src_preamble = mem::take(&mut self.src_preamble);
1379        *src.as_mut_string() = format!("{}{}", src_preamble.as_str(), src.as_str());
1380
1381        let module_name = name.to_snake_case();
1382        files.push(&format!("{module_name}.rs"), src.as_bytes());
1383
1384        let remapped_keys = self
1385            .with
1386            .iter()
1387            .map(|(k, _)| k)
1388            .cloned()
1389            .collect::<HashSet<String>>();
1390
1391        let mut unused_keys = remapped_keys
1392            .difference(&self.generated_types)
1393            .collect::<Vec<&String>>();
1394
1395        unused_keys.sort();
1396
1397        if !unused_keys.is_empty() {
1398            bail!("unused remappings provided via `with`: {unused_keys:?}");
1399        }
1400
1401        Ok(())
1402    }
1403}
1404
1405fn compute_module_path(name: &WorldKey, resolve: &Resolve, is_export: bool) -> Vec<String> {
1406    let mut path = Vec::new();
1407    if is_export {
1408        path.push("exports".to_string());
1409    }
1410    match name {
1411        WorldKey::Name(name) => {
1412            path.push(to_rust_ident(name));
1413        }
1414        WorldKey::Interface(id) => {
1415            let iface = &resolve.interfaces[*id];
1416            let pkg = iface.package.unwrap();
1417            let pkgname = resolve.packages[pkg].name.clone();
1418            path.push(to_rust_ident(&pkgname.namespace));
1419            path.push(name_package_module(resolve, pkg));
1420            path.push(to_rust_ident(iface.name.as_ref().unwrap()));
1421        }
1422    }
1423    path
1424}
1425
1426enum Identifier<'a> {
1427    World(WorldId),
1428    Interface(InterfaceId, &'a WorldKey),
1429    StreamOrFuturePayload,
1430}
1431
1432fn group_by_resource<'a>(
1433    funcs: impl Iterator<Item = &'a Function>,
1434) -> BTreeMap<Option<TypeId>, Vec<&'a Function>> {
1435    let mut by_resource = BTreeMap::<_, Vec<_>>::new();
1436    for func in funcs {
1437        by_resource
1438            .entry(func.kind.resource())
1439            .or_default()
1440            .push(func);
1441    }
1442    by_resource
1443}
1444
1445#[derive(Default, Debug, Clone, Copy)]
1446pub enum Ownership {
1447    /// Generated types will be composed entirely of owning fields, regardless
1448    /// of whether they are used as parameters to imports or not.
1449    #[default]
1450    Owning,
1451
1452    /// Generated types used as parameters to imports will be "deeply
1453    /// borrowing", i.e. contain references rather than owned values when
1454    /// applicable.
1455    Borrowing {
1456        /// Whether or not to generate "duplicate" type definitions for a single
1457        /// WIT type if necessary, for example if it's used as both an import
1458        /// and an export, or if it's used both as a parameter to an import and
1459        /// a return value from an import.
1460        duplicate_if_necessary: bool,
1461    },
1462}
1463
1464impl FromStr for Ownership {
1465    type Err = String;
1466
1467    fn from_str(s: &str) -> Result<Self, Self::Err> {
1468        match s {
1469            "owning" => Ok(Self::Owning),
1470            "borrowing" => Ok(Self::Borrowing {
1471                duplicate_if_necessary: false,
1472            }),
1473            "borrowing-duplicate-if-necessary" => Ok(Self::Borrowing {
1474                duplicate_if_necessary: true,
1475            }),
1476            _ => Err(format!(
1477                "unrecognized ownership: `{s}`; \
1478                 expected `owning`, `borrowing`, or `borrowing-duplicate-if-necessary`"
1479            )),
1480        }
1481    }
1482}
1483
1484impl fmt::Display for Ownership {
1485    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1486        f.write_str(match self {
1487            Ownership::Owning => "owning",
1488            Ownership::Borrowing {
1489                duplicate_if_necessary: false,
1490            } => "borrowing",
1491            Ownership::Borrowing {
1492                duplicate_if_necessary: true,
1493            } => "borrowing-duplicate-if-necessary",
1494        })
1495    }
1496}
1497
1498/// Options for with "with" remappings.
1499#[derive(Debug, Clone)]
1500pub enum WithOption {
1501    Path(String),
1502    Generate,
1503}
1504
1505impl std::fmt::Display for WithOption {
1506    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1507        match self {
1508            WithOption::Path(p) => f.write_fmt(format_args!("\"{p}\"")),
1509            WithOption::Generate => f.write_str("generate"),
1510        }
1511    }
1512}
1513
1514impl From<WithOption> for TypeGeneration {
1515    fn from(opt: WithOption) -> Self {
1516        match opt {
1517            WithOption::Path(p) => TypeGeneration::Remap(p),
1518            WithOption::Generate => TypeGeneration::Generate,
1519        }
1520    }
1521}
1522
1523#[derive(Default)]
1524struct FnSig {
1525    async_: bool,
1526    unsafe_: bool,
1527    private: bool,
1528    use_item_name: bool,
1529    generics: Option<String>,
1530    self_arg: Option<String>,
1531    self_is_first_param: bool,
1532}
1533
1534pub fn to_rust_ident(name: &str) -> String {
1535    match name {
1536        // Escape Rust keywords.
1537        // Source: https://doc.rust-lang.org/reference/keywords.html
1538        "as" => "as_".into(),
1539        "break" => "break_".into(),
1540        "const" => "const_".into(),
1541        "continue" => "continue_".into(),
1542        "crate" => "crate_".into(),
1543        "else" => "else_".into(),
1544        "enum" => "enum_".into(),
1545        "extern" => "extern_".into(),
1546        "false" => "false_".into(),
1547        "fn" => "fn_".into(),
1548        "for" => "for_".into(),
1549        "if" => "if_".into(),
1550        "impl" => "impl_".into(),
1551        "in" => "in_".into(),
1552        "let" => "let_".into(),
1553        "loop" => "loop_".into(),
1554        "match" => "match_".into(),
1555        "mod" => "mod_".into(),
1556        "move" => "move_".into(),
1557        "mut" => "mut_".into(),
1558        "pub" => "pub_".into(),
1559        "ref" => "ref_".into(),
1560        "return" => "return_".into(),
1561        "self" => "self_".into(),
1562        "static" => "static_".into(),
1563        "struct" => "struct_".into(),
1564        "super" => "super_".into(),
1565        "trait" => "trait_".into(),
1566        "true" => "true_".into(),
1567        "type" => "type_".into(),
1568        "unsafe" => "unsafe_".into(),
1569        "use" => "use_".into(),
1570        "where" => "where_".into(),
1571        "while" => "while_".into(),
1572        "async" => "async_".into(),
1573        "await" => "await_".into(),
1574        "dyn" => "dyn_".into(),
1575        "abstract" => "abstract_".into(),
1576        "become" => "become_".into(),
1577        "box" => "box_".into(),
1578        "do" => "do_".into(),
1579        "final" => "final_".into(),
1580        "macro" => "macro_".into(),
1581        "override" => "override_".into(),
1582        "priv" => "priv_".into(),
1583        "typeof" => "typeof_".into(),
1584        "unsized" => "unsized_".into(),
1585        "virtual" => "virtual_".into(),
1586        "yield" => "yield_".into(),
1587        "try" => "try_".into(),
1588        s => s.to_snake_case(),
1589    }
1590}
1591
1592fn to_upper_camel_case(name: &str) -> String {
1593    match name {
1594        // The name "Guest" is reserved for traits generated by exported
1595        // interfaces, so remap types defined in wit to something else.
1596        "guest" => "Guest_".to_string(),
1597        s => s.to_upper_camel_case(),
1598    }
1599}
1600
1601fn wasm_type(ty: WasmType) -> &'static str {
1602    match ty {
1603        WasmType::I32 => "i32",
1604        WasmType::I64 => "i64",
1605        WasmType::F32 => "f32",
1606        WasmType::F64 => "f64",
1607        WasmType::Pointer => "*mut u8",
1608        WasmType::Length => "usize",
1609
1610        // `PointerOrI64` can hold either a `u64` or a pointer with provenance.
1611        // Neither a `u64` nor a pointer type can portably do both, so we use
1612        // `MaybeUninit<u64>`, since `MaybeUninit` is [documented] to preserve
1613        // provenance.
1614        // [documented]: https://github.com/rust-lang/rfcs/blob/master/text/3559-rust-has-provenance.md#reference-level-explanation
1615        WasmType::PointerOrI64 => "::core::mem::MaybeUninit::<u64>",
1616    }
1617}
1618
1619fn int_repr(repr: Int) -> &'static str {
1620    match repr {
1621        Int::U8 => "u8",
1622        Int::U16 => "u16",
1623        Int::U32 => "u32",
1624        Int::U64 => "u64",
1625    }
1626}
1627
1628fn bitcast(casts: &[Bitcast], operands: &[String], results: &mut Vec<String>) {
1629    for (cast, operand) in casts.iter().zip(operands) {
1630        results.push(perform_cast(operand, cast));
1631    }
1632}
1633
1634fn perform_cast(operand: &str, cast: &Bitcast) -> String {
1635    match cast {
1636        Bitcast::None => operand.to_owned(),
1637        Bitcast::I32ToI64 => format!("i64::from({})", operand),
1638        Bitcast::F32ToI32 => format!("({}).to_bits() as i32", operand),
1639        Bitcast::F64ToI64 => format!("({}).to_bits() as i64", operand),
1640        Bitcast::I64ToI32 => format!("{} as i32", operand),
1641        Bitcast::I32ToF32 => format!("f32::from_bits({} as u32)", operand),
1642        Bitcast::I64ToF64 => format!("f64::from_bits({} as u64)", operand),
1643        Bitcast::F32ToI64 => format!("i64::from(({}).to_bits())", operand),
1644        Bitcast::I64ToF32 => format!("f32::from_bits({} as u32)", operand),
1645
1646        // Convert an `i64` into a `MaybeUninit<u64>`.
1647        Bitcast::I64ToP64 => format!("::core::mem::MaybeUninit::new({} as u64)", operand),
1648        // Convert a `MaybeUninit<u64>` holding an `i64` value back into
1649        // the `i64` value.
1650        Bitcast::P64ToI64 => format!("{}.assume_init() as i64", operand),
1651
1652        // Convert a pointer value into a `MaybeUninit<u64>`.
1653        Bitcast::PToP64 => {
1654            format!(
1655                "{{
1656                        let mut t = ::core::mem::MaybeUninit::<u64>::uninit();
1657                        t.as_mut_ptr().cast::<*mut u8>().write({});
1658                        t
1659                    }}",
1660                operand
1661            )
1662        }
1663        // Convert a `MaybeUninit<u64>` holding a pointer value back into
1664        // the pointer value.
1665        Bitcast::P64ToP => {
1666            format!("{}.as_ptr().cast::<*mut u8>().read()", operand)
1667        }
1668        // Convert an `i32` or a `usize` into a pointer.
1669        Bitcast::I32ToP | Bitcast::LToP => {
1670            format!("{} as *mut u8", operand)
1671        }
1672        // Convert a pointer or length holding an `i32` value back into the `i32`.
1673        Bitcast::PToI32 | Bitcast::LToI32 => {
1674            format!("{} as i32", operand)
1675        }
1676        // Convert an `i32`, `i64`, or pointer holding a `usize` value back into the `usize`.
1677        Bitcast::I32ToL | Bitcast::I64ToL | Bitcast::PToL => {
1678            format!("{} as usize", operand)
1679        }
1680        // Convert a `usize` into an `i64`.
1681        Bitcast::LToI64 => {
1682            format!("{} as i64", operand)
1683        }
1684        Bitcast::Sequence(sequence) => {
1685            let [first, second] = &**sequence;
1686            perform_cast(&perform_cast(operand, first), second)
1687        }
1688    }
1689}
1690
1691enum RustFlagsRepr {
1692    U8,
1693    U16,
1694    U32,
1695    U64,
1696    U128,
1697}
1698
1699impl RustFlagsRepr {
1700    fn new(f: &Flags) -> RustFlagsRepr {
1701        match f.repr() {
1702            FlagsRepr::U8 => RustFlagsRepr::U8,
1703            FlagsRepr::U16 => RustFlagsRepr::U16,
1704            FlagsRepr::U32(1) => RustFlagsRepr::U32,
1705            FlagsRepr::U32(2) => RustFlagsRepr::U64,
1706            FlagsRepr::U32(3 | 4) => RustFlagsRepr::U128,
1707            FlagsRepr::U32(n) => panic!("unsupported number of flags: {}", n * 32),
1708        }
1709    }
1710}
1711
1712impl fmt::Display for RustFlagsRepr {
1713    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1714        match self {
1715            RustFlagsRepr::U8 => "u8".fmt(f),
1716            RustFlagsRepr::U16 => "u16".fmt(f),
1717            RustFlagsRepr::U32 => "u32".fmt(f),
1718            RustFlagsRepr::U64 => "u64".fmt(f),
1719            RustFlagsRepr::U128 => "u128".fmt(f),
1720        }
1721    }
1722}
1723
1724#[derive(Debug, Clone)]
1725pub struct MissingWith(pub String);
1726
1727impl fmt::Display for MissingWith {
1728    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1729        write!(f, "missing `with` mapping for the key `{}`", self.0)
1730    }
1731}
1732
1733impl std::error::Error for MissingWith {}
1734
1735// bail!("no remapping found for {with_name:?} - use the `generate!` macro's `with` option to force the interface to be generated or specify where it is already defined:
1736// ```
1737// with: {{\n\t{with_name:?}: generate\n}}
1738// ```")
1739
1740/// Returns the full WIT type name with fully qualified interface name
1741fn full_wit_type_name(resolve: &Resolve, id: TypeId) -> String {
1742    let id = dealias(resolve, id);
1743    let type_def = &resolve.types[id];
1744    let interface_name = match type_def.owner {
1745        TypeOwner::World(w) => Some(resolve.worlds[w].name.clone()),
1746        TypeOwner::Interface(id) => resolve.id_of(id),
1747        TypeOwner::None => None,
1748    };
1749    match interface_name {
1750        Some(interface_name) => format!("{}/{}", interface_name, type_def.name.clone().unwrap()),
1751        None => type_def.name.clone().unwrap(),
1752    }
1753}