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