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