Skip to main content

wit_bindgen_rust/
lib.rs

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