wit_bindgen_rust/
lib.rs

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