1use crate::interface::InterfaceGenerator;
2use anyhow::{Result, bail};
3use core::panic;
4use heck::*;
5use indexmap::{IndexMap, IndexSet};
6use std::collections::{BTreeMap, HashMap, HashSet};
7use std::fmt::{self, Write as _};
8use std::mem;
9use std::path::{Path, PathBuf};
10use std::str::FromStr;
11use wit_bindgen_core::abi::{Bitcast, WasmType};
12use wit_bindgen_core::{
13 AsyncFilterSet, Files, InterfaceGenerator as _, Source, Types, WorldGenerator, dealias,
14 name_package_module, uwrite, uwriteln, wit_parser::*,
15};
16
17mod bindgen;
18mod interface;
19
20struct InterfaceName {
21 remapped: bool,
24
25 path: String,
27}
28
29#[derive(Default)]
30pub struct RustWasm {
31 types: Types,
32 src_preamble: Source,
33 src: Source,
34 opts: Opts,
35 import_modules: Vec<(String, Vec<String>)>,
36 export_modules: Vec<(String, Vec<String>)>,
37 skip: HashSet<String>,
38 interface_names: HashMap<InterfaceId, InterfaceName>,
39 exported_resources: HashSet<TypeId>,
40 import_funcs_called: bool,
41 with_name_counter: usize,
42 generated_types: HashSet<String>,
45 world: Option<WorldId>,
46
47 rt_module: IndexSet<RuntimeItem>,
48 export_macros: Vec<(String, String)>,
49
50 with: GenerationConfiguration,
52
53 future_payloads: IndexMap<Option<Type>, String>,
54 stream_payloads: IndexMap<Option<Type>, String>,
55}
56
57#[derive(Default)]
58struct GenerationConfiguration {
59 map: HashMap<String, TypeGeneration>,
60 generate_by_default: bool,
61}
62
63impl GenerationConfiguration {
64 fn get(&self, key: &str) -> Option<&TypeGeneration> {
65 self.map.get(key).or_else(|| {
66 self.generate_by_default
67 .then_some(&TypeGeneration::Generate)
68 })
69 }
70
71 fn insert(&mut self, name: String, generate: TypeGeneration) {
72 self.map.insert(name, generate);
73 }
74
75 fn iter(&self) -> impl Iterator<Item = (&String, &TypeGeneration)> {
76 self.map.iter()
77 }
78}
79
80enum TypeGeneration {
82 Remap(String),
84 Generate,
86}
87
88impl TypeGeneration {
89 fn generated(&self) -> bool {
91 match self {
92 TypeGeneration::Generate => true,
93 TypeGeneration::Remap(_) => false,
94 }
95 }
96}
97
98#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
99enum RuntimeItem {
100 AllocCrate,
101 StringType,
102 StdAllocModule,
103 VecType,
104 StringLift,
105 InvalidEnumDiscriminant,
106 CharLift,
107 BoolLift,
108 CabiDealloc,
109 RunCtorsOnce,
110 AsI32,
111 AsI64,
112 AsF32,
113 AsF64,
114 ResourceType,
115 BoxType,
116 WitMapTrait,
117}
118
119#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
120#[cfg_attr(
121 feature = "serde",
122 derive(serde::Deserialize),
123 serde(rename_all = "kebab-case")
124)]
125pub enum ExportKey {
126 World,
127 Name(String),
128}
129
130#[cfg(feature = "clap")]
131fn parse_with(s: &str) -> Result<(String, WithOption), String> {
132 let (k, v) = s.split_once('=').ok_or_else(|| {
133 format!("expected string of form `<key>=<value>[,<key>=<value>...]`; got `{s}`")
134 })?;
135 let v = match v {
136 "generate" => WithOption::Generate,
137 other => WithOption::Path(other.to_string()),
138 };
139 Ok((k.to_string(), v))
140}
141
142#[derive(Default, Debug, Clone)]
143#[cfg_attr(feature = "clap", derive(clap::Parser))]
144#[cfg_attr(
145 feature = "serde",
146 derive(serde::Deserialize),
147 serde(default, rename_all = "kebab-case")
148)]
149pub struct Opts {
150 #[cfg_attr(feature = "clap", arg(long))]
152 pub format: bool,
153
154 #[cfg_attr(feature = "clap", arg(long))]
157 pub std_feature: bool,
158
159 #[cfg_attr(feature = "clap", arg(long))]
164 pub raw_strings: bool,
165
166 #[cfg_attr(feature = "clap", arg(long, value_name = "NAME"))]
168 pub skip: Vec<String>,
169
170 #[cfg_attr(feature = "clap", arg(long))]
173 pub stubs: bool,
174
175 #[cfg_attr(feature = "clap", arg(long, value_name = "STRING"))]
179 pub export_prefix: Option<String>,
180
181 #[cfg_attr(feature = "clap", arg(long, default_value_t = Ownership::Owning))]
195 pub ownership: Ownership,
196
197 #[cfg_attr(feature = "clap", arg(long, value_name = "PATH"))]
201 pub runtime_path: Option<String>,
202
203 #[cfg_attr(feature = "clap", arg(long, value_name = "PATH"))]
213 pub map_type: Option<String>,
214
215 #[cfg_attr(feature = "clap", arg(long))]
219 pub bitflags_path: Option<String>,
220
221 #[cfg_attr(feature = "clap", arg(long, short = 'd', value_name = "DERIVE"))]
226 pub additional_derive_attributes: Vec<String>,
227
228 #[cfg_attr(feature = "clap", arg(long, value_name = "NAME"))]
235 pub additional_derive_ignore: Vec<String>,
236
237 #[cfg_attr(feature = "clap", arg(long, value_parser = parse_with, value_delimiter = ','))]
244 pub with: Vec<(String, WithOption)>,
245
246 #[cfg_attr(feature = "clap", arg(long))]
249 pub generate_all: bool,
250
251 #[cfg_attr(feature = "clap", arg(long, value_name = "STRING"))]
254 pub type_section_suffix: Option<String>,
255
256 #[cfg_attr(feature = "clap", arg(long))]
259 pub disable_run_ctors_once_workaround: bool,
260
261 #[cfg_attr(feature = "clap", arg(long, value_name = "NAME"))]
264 pub default_bindings_module: Option<String>,
265
266 #[cfg_attr(feature = "clap", arg(long, value_name = "NAME"))]
268 pub export_macro_name: Option<String>,
269
270 #[cfg_attr(feature = "clap", arg(long))]
273 pub pub_export_macro: bool,
274
275 #[cfg_attr(feature = "clap", arg(long))]
277 pub generate_unused_types: bool,
278
279 #[cfg_attr(feature = "clap", arg(long))]
285 pub disable_custom_section_link_helpers: bool,
286
287 #[cfg_attr(feature = "clap", clap(flatten))]
288 #[cfg_attr(feature = "serde", serde(flatten))]
289 pub async_: AsyncFilterSet,
290
291 #[cfg_attr(
299 feature = "clap",
300 arg(long, require_equals = true, value_name = "true|false")
301 )]
302 pub merge_structurally_equal_types: Option<Option<bool>>,
303}
304
305impl Opts {
306 pub fn build(self) -> RustWasm {
307 let mut r = RustWasm::new();
308 r.skip = self.skip.iter().cloned().collect();
309 r.opts = self;
310 r
311 }
312
313 fn merge_structurally_equal_types(&self) -> bool {
314 const DEFAULT: bool = false;
315 match self.merge_structurally_equal_types {
316 None => DEFAULT,
318 Some(None) => true,
320 Some(Some(val)) => val,
322 }
323 }
324}
325
326impl RustWasm {
327 pub fn generate_to_out_dir(mut self, world: Option<&str>) -> Result<PathBuf> {
335 let mut resolve = Resolve::default();
336 println!("cargo:rerun-if-changed=wit/");
337 let (pkg, _files) = resolve.push_path("wit")?;
338 let main_packages = vec![pkg];
339 let world = resolve.select_world(&main_packages, world)?;
340
341 let mut files = Files::default();
342 self.generate(&mut resolve, world, &mut files)?;
343 let out_dir = std::env::var("OUT_DIR").expect("cargo sets OUT_DIR");
344 let (name, contents) = files
345 .iter()
346 .next()
347 .expect("exactly one file should be generated");
348 let dst = Path::new(&out_dir).join(name);
349 std::fs::write(&dst, contents)?;
350 Ok(dst)
351 }
352
353 fn new() -> RustWasm {
354 RustWasm::default()
355 }
356
357 fn interface<'a>(
358 &'a mut self,
359 identifier: Identifier<'a>,
360 wasm_import_module: &'a str,
361 resolve: &'a Resolve,
362 in_import: bool,
363 ) -> InterfaceGenerator<'a> {
364 let mut sizes = SizeAlign::default();
365 sizes.fill(resolve);
366
367 InterfaceGenerator {
368 identifier,
369 wasm_import_module,
370 src: Source::default(),
371 in_import,
372 r#gen: self,
373 sizes,
374 resolve,
375 return_pointer_area_size: Default::default(),
376 return_pointer_area_align: Default::default(),
377 needs_runtime_module: false,
378 needs_wit_map: false,
379 }
380 }
381
382 fn emit_modules(&mut self, modules: Vec<(String, Vec<String>)>) {
383 #[derive(Default)]
384 struct Module {
385 submodules: BTreeMap<String, Module>,
386 contents: Vec<String>,
387 }
388 let mut map = Module::default();
389 for (module, path) in modules {
390 let mut cur = &mut map;
391 for name in path[..path.len() - 1].iter() {
392 cur = cur
393 .submodules
394 .entry(name.clone())
395 .or_insert(Module::default());
396 }
397 cur.contents.push(module);
398 }
399
400 emit(&mut self.src, map, &self.opts, true);
401 fn emit(me: &mut Source, module: Module, opts: &Opts, toplevel: bool) {
402 for (name, submodule) in module.submodules {
403 if toplevel {
404 if opts.format {
408 uwriteln!(me, "#[rustfmt::skip]");
409 }
410
411 uwriteln!(me, "#[allow(dead_code, clippy::all)]");
415 }
416
417 uwriteln!(me, "pub mod {name} {{");
418 emit(me, submodule, opts, false);
419 uwriteln!(me, "}}");
420 }
421 for submodule in module.contents {
422 uwriteln!(me, "{submodule}");
423 }
424 }
425 }
426
427 fn runtime_path(&self) -> &str {
428 self.opts
429 .runtime_path
430 .as_deref()
431 .unwrap_or("wit_bindgen::rt")
432 }
433
434 fn map_type_path(&self) -> String {
435 self.opts
436 .map_type
437 .clone()
438 .unwrap_or_else(|| format!("{}::Map", self.runtime_path()))
439 }
440
441 fn wit_map_path(&self) -> String {
442 format!("{}::WitMap", self.runtime_path())
443 }
444
445 fn bitflags_path(&self) -> String {
446 self.opts
447 .bitflags_path
448 .to_owned()
449 .unwrap_or(format!("{}::bitflags", self.runtime_path()))
450 }
451
452 fn async_support_path(&self) -> String {
453 format!("{}::async_support", self.runtime_path())
454 }
455
456 fn name_interface(
457 &mut self,
458 resolve: &Resolve,
459 id: InterfaceId,
460 name: &WorldKey,
461 is_export: bool,
462 ) -> Result<bool> {
463 let with_name = resolve.name_world_key(name);
464 let remapping = if is_export {
465 &TypeGeneration::Generate
466 } else {
467 match self.with.get(&with_name) {
468 Some(remapping) => remapping,
469 None => bail!(MissingWith(with_name)),
470 }
471 };
472 self.generated_types.insert(with_name);
473 let entry = match remapping {
474 TypeGeneration::Remap(remapped_path) => {
475 let name = format!("__with_name{}", self.with_name_counter);
476 self.with_name_counter += 1;
477 uwriteln!(
478 self.src,
479 "#[allow(unfulfilled_lint_expectations, unused_imports)]"
480 );
481 uwriteln!(self.src, "use {remapped_path} as {name};");
482 InterfaceName {
483 remapped: true,
484 path: name,
485 }
486 }
487 TypeGeneration::Generate => {
488 let path = compute_module_path(name, resolve, is_export).join("::");
489
490 InterfaceName {
491 remapped: false,
492 path,
493 }
494 }
495 };
496
497 let remapped = entry.remapped;
498 let prev = self.interface_names.insert(id, entry);
499 assert!(prev.is_none());
500
501 Ok(remapped)
502 }
503
504 fn finish_runtime_module(&mut self) {
505 if !self.rt_module.is_empty() {
506 if self.opts.format {
508 uwriteln!(self.src, "#[rustfmt::skip]");
509 }
510
511 self.src.push_str("mod _rt {\n");
512 self.src
513 .push_str("#![allow(dead_code, unused_imports, clippy::all)]\n");
514 let mut emitted = IndexSet::new();
515 while !self.rt_module.is_empty() {
516 for item in mem::take(&mut self.rt_module) {
517 if emitted.insert(item) {
518 self.emit_runtime_item(item);
519 }
520 }
521 }
522 self.src.push_str("}\n");
523 }
524
525 if !self.future_payloads.is_empty() {
526 let async_support = self.async_support_path();
527 self.src.push_str(&format!(
528 "\
529pub mod wit_future {{
530 #![allow(dead_code, unused_variables, clippy::all)]
531
532 #[doc(hidden)]
533 pub trait FuturePayload: Unpin + Sized + 'static {{
534 const VTABLE: &'static {async_support}::FutureVtable<Self>;
535 }}"
536 ));
537 for code in self.future_payloads.values() {
538 self.src.push_str(code);
539 }
540 self.src.push_str(&format!(
541 "\
542 /// Creates a new Component Model `future` with the specified payload type.
543 ///
544 /// The `default` function provided computes the default value to be sent in
545 /// this future if no other value was otherwise sent.
546 pub fn new<T: FuturePayload>(default: fn() -> T) -> ({async_support}::FutureWriter<T>, {async_support}::FutureReader<T>) {{
547 unsafe {{ {async_support}::future_new::<T>(default, T::VTABLE) }}
548 }}
549}}
550 ",
551 ));
552 }
553
554 if !self.stream_payloads.is_empty() {
555 let async_support = self.async_support_path();
556 self.src.push_str(&format!(
557 "\
558pub mod wit_stream {{
559 #![allow(dead_code, unused_variables, clippy::all)]
560
561 pub trait StreamPayload: Unpin + Sized + 'static {{
562 const VTABLE: &'static {async_support}::StreamVtable<Self>;
563 }}"
564 ));
565 for code in self.stream_payloads.values() {
566 self.src.push_str(code);
567 }
568 self.src.push_str(
569 &format!("\
570 /// Creates a new Component Model `stream` with the specified payload type.
571 pub fn new<T: StreamPayload>() -> ({async_support}::StreamWriter<T>, {async_support}::StreamReader<T>) {{
572 unsafe {{ {async_support}::stream_new::<T>(T::VTABLE) }}
573 }}
574}}
575 "),
576 );
577 }
578 }
579
580 fn emit_runtime_item(&mut self, item: RuntimeItem) {
581 match item {
582 RuntimeItem::AllocCrate => {
583 uwriteln!(self.src, "extern crate alloc as alloc_crate;");
584 }
585 RuntimeItem::StdAllocModule => {
586 self.rt_module.insert(RuntimeItem::AllocCrate);
587 uwriteln!(self.src, "pub use alloc_crate::alloc;");
588 }
589 RuntimeItem::StringType => {
590 self.rt_module.insert(RuntimeItem::AllocCrate);
591 uwriteln!(self.src, "pub use alloc_crate::string::String;");
592 }
593 RuntimeItem::BoxType => {
594 self.rt_module.insert(RuntimeItem::AllocCrate);
595 uwriteln!(self.src, "pub use alloc_crate::boxed::Box;");
596 }
597 RuntimeItem::VecType => {
598 self.rt_module.insert(RuntimeItem::AllocCrate);
599 uwriteln!(self.src, "pub use alloc_crate::vec::Vec;");
600 }
601 RuntimeItem::CabiDealloc => {
602 self.rt_module.insert(RuntimeItem::StdAllocModule);
603 self.src.push_str(
604 "\
605pub unsafe fn cabi_dealloc(ptr: *mut u8, size: usize, align: usize) {
606 if size == 0 {
607 return;
608 }
609 unsafe {
610 let layout = alloc::Layout::from_size_align_unchecked(size, align);
611 alloc::dealloc(ptr, layout);
612 }
613}
614 ",
615 );
616 }
617
618 RuntimeItem::StringLift => {
619 self.rt_module.insert(RuntimeItem::StringType);
620 self.src.push_str(
621 "\
622pub unsafe fn string_lift(bytes: Vec<u8>) -> String {
623 if cfg!(debug_assertions) {
624 String::from_utf8(bytes).unwrap()
625 } else {
626 unsafe { String::from_utf8_unchecked(bytes) }
627 }
628}
629 ",
630 );
631 }
632
633 RuntimeItem::InvalidEnumDiscriminant => {
634 self.src.push_str(
635 "\
636pub unsafe fn invalid_enum_discriminant<T>() -> T {
637 if cfg!(debug_assertions) {
638 panic!(\"invalid enum discriminant\")
639 } else {
640 unsafe { core::hint::unreachable_unchecked() }
641 }
642}
643 ",
644 );
645 }
646
647 RuntimeItem::CharLift => {
648 self.src.push_str(
649 "\
650pub unsafe fn char_lift(val: u32) -> char {
651 if cfg!(debug_assertions) {
652 core::char::from_u32(val).unwrap()
653 } else {
654 unsafe { core::char::from_u32_unchecked(val) }
655 }
656}
657 ",
658 );
659 }
660
661 RuntimeItem::BoolLift => {
662 self.src.push_str(
663 "\
664pub unsafe fn bool_lift(val: u8) -> bool {
665 if cfg!(debug_assertions) {
666 match val {
667 0 => false,
668 1 => true,
669 _ => panic!(\"invalid bool discriminant\"),
670 }
671 } else {
672 val != 0
673 }
674}
675 ",
676 );
677 }
678
679 RuntimeItem::RunCtorsOnce => {
680 let rt = self.runtime_path();
681 self.src.push_str(&format!(
682 r#"
683#[cfg(target_arch = "wasm32")]
684pub fn run_ctors_once() {{
685 {rt}::run_ctors_once();
686}}
687 "#,
688 ));
689 }
690
691 RuntimeItem::AsI32 => {
692 self.emit_runtime_as_trait(
693 "i32",
694 &["i32", "u32", "i16", "u16", "i8", "u8", "char", "usize"],
695 );
696 }
697
698 RuntimeItem::AsI64 => {
699 self.emit_runtime_as_trait("i64", &["i64", "u64"]);
700 }
701
702 RuntimeItem::AsF32 => {
703 self.emit_runtime_as_trait("f32", &["f32"]);
704 }
705
706 RuntimeItem::AsF64 => {
707 self.emit_runtime_as_trait("f64", &["f64"]);
708 }
709
710 RuntimeItem::WitMapTrait => {
711 let rt = self.runtime_path().to_string();
712 uwriteln!(self.src, "pub use {rt}::WitMap;");
713 }
714
715 RuntimeItem::ResourceType => {
716 self.src.push_str(
717 r#"
718
719use core::fmt;
720use core::marker;
721use core::sync::atomic::{AtomicU32, Ordering::Relaxed};
722
723/// A type which represents a component model resource, either imported or
724/// exported into this component.
725///
726/// This is a low-level wrapper which handles the lifetime of the resource
727/// (namely this has a destructor). The `T` provided defines the component model
728/// intrinsics that this wrapper uses.
729///
730/// One of the chief purposes of this type is to provide `Deref` implementations
731/// to access the underlying data when it is owned.
732///
733/// This type is primarily used in generated code for exported and imported
734/// resources.
735#[repr(transparent)]
736pub struct Resource<T: WasmResource> {
737 // NB: This would ideally be `u32` but it is not. The fact that this has
738 // interior mutability is not exposed in the API of this type except for the
739 // `take_handle` method which is supposed to in theory be private.
740 //
741 // This represents, almost all the time, a valid handle value. When it's
742 // invalid it's stored as `u32::MAX`.
743 handle: AtomicU32,
744 _marker: marker::PhantomData<T>,
745}
746
747/// A trait which all wasm resources implement, namely providing the ability to
748/// drop a resource.
749///
750/// This generally is implemented by generated code, not user-facing code.
751#[allow(clippy::missing_safety_doc)]
752pub unsafe trait WasmResource {
753 /// Invokes the `[resource-drop]...` intrinsic.
754 unsafe fn drop(handle: u32);
755}
756
757impl<T: WasmResource> Resource<T> {
758 #[doc(hidden)]
759 pub unsafe fn from_handle(handle: u32) -> Self {
760 debug_assert!(handle != 0 && handle != u32::MAX);
761 Self {
762 handle: AtomicU32::new(handle),
763 _marker: marker::PhantomData,
764 }
765 }
766
767 /// Takes ownership of the handle owned by `resource`.
768 ///
769 /// Note that this ideally would be `into_handle` taking `Resource<T>` by
770 /// ownership. The code generator does not enable that in all situations,
771 /// unfortunately, so this is provided instead.
772 ///
773 /// Also note that `take_handle` is in theory only ever called on values
774 /// owned by a generated function. For example a generated function might
775 /// take `Resource<T>` as an argument but then call `take_handle` on a
776 /// reference to that argument. In that sense the dynamic nature of
777 /// `take_handle` should only be exposed internally to generated code, not
778 /// to user code.
779 #[doc(hidden)]
780 pub fn take_handle(resource: &Resource<T>) -> u32 {
781 resource.handle.swap(u32::MAX, Relaxed)
782 }
783
784 #[doc(hidden)]
785 pub fn handle(resource: &Resource<T>) -> u32 {
786 resource.handle.load(Relaxed)
787 }
788}
789
790impl<T: WasmResource> fmt::Debug for Resource<T> {
791 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
792 f.debug_struct("Resource")
793 .field("handle", &self.handle)
794 .finish()
795 }
796}
797
798impl<T: WasmResource> Drop for Resource<T> {
799 fn drop(&mut self) {
800 unsafe {
801 match self.handle.load(Relaxed) {
802 // If this handle was "taken" then don't do anything in the
803 // destructor.
804 u32::MAX => {}
805
806 // ... but otherwise do actually destroy it with the imported
807 // component model intrinsic as defined through `T`.
808 other => T::drop(other),
809 }
810 }
811 }
812}
813 "#,
814 );
815 }
816 }
817 }
818
819 fn emit_runtime_as_trait(&mut self, ty: &str, to_convert: &[&str]) {
824 let upcase = ty.to_uppercase();
825 self.src.push_str(&format!(
826 r#"
827pub fn as_{ty}<T: As{upcase}>(t: T) -> {ty} {{
828 t.as_{ty}()
829}}
830
831pub trait As{upcase} {{
832 fn as_{ty}(self) -> {ty};
833}}
834
835impl<'a, T: Copy + As{upcase}> As{upcase} for &'a T {{
836 fn as_{ty}(self) -> {ty} {{
837 (*self).as_{ty}()
838 }}
839}}
840 "#
841 ));
842
843 for to_convert in to_convert {
844 self.src.push_str(&format!(
845 r#"
846impl As{upcase} for {to_convert} {{
847 #[inline]
848 fn as_{ty}(self) -> {ty} {{
849 self as {ty}
850 }}
851}}
852 "#
853 ));
854 }
855 }
856
857 fn finish_export_macro(&mut self, resolve: &Resolve, world_id: WorldId) {
863 if self.export_macros.is_empty() {
864 return;
865 }
866 let world = &resolve.worlds[world_id];
867 let world_name = world.name.to_snake_case();
868
869 let default_bindings_module = self
870 .opts
871 .default_bindings_module
872 .clone()
873 .unwrap_or("self".to_string());
874 let (macro_export, use_vis) = if self.opts.pub_export_macro {
875 ("#[macro_export]", "pub")
876 } else {
877 ("", "pub(crate)")
878 };
879 let export_macro_name = self
880 .opts
881 .export_macro_name
882 .as_deref()
883 .unwrap_or("export")
884 .to_string();
885 uwriteln!(
886 self.src,
887 r#"
888/// Generates `#[unsafe(no_mangle)]` functions to export the specified type as
889/// the root implementation of all generated traits.
890///
891/// For more information see the documentation of `wit_bindgen::generate!`.
892///
893/// ```rust
894/// # macro_rules! {export_macro_name} {{ ($($t:tt)*) => (); }}
895/// # trait Guest {{}}
896/// struct MyType;
897///
898/// impl Guest for MyType {{
899/// // ...
900/// }}
901///
902/// {export_macro_name}!(MyType);
903/// ```
904#[allow(unused_macros)]
905#[doc(hidden)]
906{macro_export}
907macro_rules! __export_{world_name}_impl {{
908 ($ty:ident) => ({default_bindings_module}::{export_macro_name}!($ty with_types_in {default_bindings_module}););
909 ($ty:ident with_types_in $($path_to_types_root:tt)*) => ("#
910 );
911 for (name, path_to_types) in self.export_macros.iter() {
912 let mut path = "$($path_to_types_root)*".to_string();
913 if !path_to_types.is_empty() {
914 path.push_str("::");
915 path.push_str(path_to_types)
916 }
917 uwriteln!(self.src, "{path}::{name}!($ty with_types_in {path});");
918 }
919
920 if self.opts.pub_export_macro {
922 uwriteln!(self.src, "const _: () = {{");
923 self.emit_custom_section(resolve, world_id, "imports and exports", None);
924 uwriteln!(self.src, "}};");
925 }
926
927 uwriteln!(self.src, ")\n}}");
928
929 uwriteln!(
930 self.src,
931 "#[doc(inline)]\n\
932 {use_vis} use __export_{world_name}_impl as {export_macro_name};"
933 );
934
935 if self.opts.stubs {
936 uwriteln!(self.src, "export!(Stub);");
937 }
938 }
939
940 fn emit_custom_section(
951 &mut self,
952 resolve: &Resolve,
953 world_id: WorldId,
954 section_suffix: &str,
955 func_name: Option<&str>,
956 ) {
957 if self.opts.format {
959 uwriteln!(self.src, "#[rustfmt::skip]");
960 }
961 self.src.push_str("\n#[cfg(target_arch = \"wasm32\")]\n");
962
963 let opts_suffix = self.opts.type_section_suffix.as_deref().unwrap_or("");
968 let world = &resolve.worlds[world_id];
969 let world_name = &world.name;
970 let pkg = &resolve.packages[world.package.unwrap()].name;
971 let version = env!("CARGO_PKG_VERSION");
972 self.src.push_str(&format!(
973 "#[unsafe(link_section = \"component-type:wit-bindgen:{version}:\
974 {pkg}:{world_name}:{section_suffix}{opts_suffix}\")]\n"
975 ));
976
977 let mut producers = wasm_metadata::Producers::empty();
978 producers.add(
979 "processed-by",
980 env!("CARGO_PKG_NAME"),
981 env!("CARGO_PKG_VERSION"),
982 );
983
984 let component_type = wit_component::metadata::encode(
985 resolve,
986 world_id,
987 wit_component::StringEncoding::UTF8,
988 Some(&producers),
989 )
990 .unwrap();
991
992 self.src.push_str("#[doc(hidden)]\n");
993 self.src.push_str("#[allow(clippy::octal_escapes)]\n");
994 self.src.push_str(&format!(
995 "pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; {}] = *b\"\\\n",
996 component_type.len()
997 ));
998 let old_indent = self.src.set_indent(0);
999 let mut line_length = 0;
1000 let s = self.src.as_mut_string();
1001 for byte in component_type.iter() {
1002 if line_length >= 80 {
1003 s.push_str("\\\n");
1004 line_length = 0;
1005 }
1006 match byte {
1007 b'\\' => {
1008 s.push_str("\\\\");
1009 line_length += 2;
1010 }
1011 b'"' => {
1012 s.push_str("\\\"");
1013 line_length += 2;
1014 }
1015 b if b.is_ascii_alphanumeric() || b.is_ascii_punctuation() => {
1016 s.push(char::from(*byte));
1017 line_length += 1;
1018 }
1019 0 => {
1020 s.push_str("\\0");
1021 line_length += 2;
1022 }
1023 _ => {
1024 uwrite!(s, "\\x{:02x}", byte);
1025 line_length += 4;
1026 }
1027 }
1028 }
1029
1030 self.src.push_str("\";\n");
1031 self.src.set_indent(old_indent);
1032
1033 if let Some(func_name) = func_name {
1034 let rt = self.runtime_path().to_string();
1035 uwriteln!(
1036 self.src,
1037 "
1038 #[inline(never)]
1039 #[doc(hidden)]
1040 pub fn {func_name}() {{
1041 {rt}::maybe_link_cabi_realloc();
1042 }}
1043 ",
1044 );
1045 }
1046 }
1047
1048 fn is_async(
1049 &mut self,
1050 resolve: &Resolve,
1051 interface: Option<&WorldKey>,
1052 func: &Function,
1053 is_import: bool,
1054 ) -> bool {
1055 self.opts
1056 .async_
1057 .is_async(resolve, interface, func, is_import)
1058 }
1059}
1060
1061impl WorldGenerator for RustWasm {
1062 fn preprocess(&mut self, resolve: &Resolve, world: WorldId) {
1063 wit_bindgen_core::generated_preamble(&mut self.src_preamble, env!("CARGO_PKG_VERSION"));
1064
1065 uwriteln!(self.src_preamble, "// Options used:");
1068 if self.opts.std_feature {
1069 uwriteln!(self.src_preamble, "// * std_feature");
1070 }
1071 if self.opts.raw_strings {
1072 uwriteln!(self.src_preamble, "// * raw_strings");
1073 }
1074 if !self.opts.skip.is_empty() {
1075 uwriteln!(self.src_preamble, "// * skip: {:?}", self.opts.skip);
1076 }
1077 if self.opts.stubs {
1078 uwriteln!(self.src_preamble, "// * stubs");
1079 }
1080 if let Some(export_prefix) = &self.opts.export_prefix {
1081 uwriteln!(
1082 self.src_preamble,
1083 "// * export_prefix: {:?}",
1084 export_prefix
1085 );
1086 }
1087 if let Some(runtime_path) = &self.opts.runtime_path {
1088 uwriteln!(self.src_preamble, "// * runtime_path: {:?}", runtime_path);
1089 }
1090 if let Some(map_type) = &self.opts.map_type {
1091 uwriteln!(self.src_preamble, "// * map_type: {:?}", map_type);
1092 }
1093 if let Some(bitflags_path) = &self.opts.bitflags_path {
1094 uwriteln!(
1095 self.src_preamble,
1096 "// * bitflags_path: {:?}",
1097 bitflags_path
1098 );
1099 }
1100 if !matches!(self.opts.ownership, Ownership::Owning) {
1101 uwriteln!(
1102 self.src_preamble,
1103 "// * ownership: {:?}",
1104 self.opts.ownership
1105 );
1106 }
1107 if !self.opts.additional_derive_attributes.is_empty() {
1108 uwriteln!(
1109 self.src_preamble,
1110 "// * additional derives {:?}",
1111 self.opts.additional_derive_attributes
1112 );
1113 }
1114 if !self.opts.additional_derive_ignore.is_empty() {
1115 uwriteln!(
1116 self.src_preamble,
1117 "// * additional derives ignored {:?}",
1118 self.opts.additional_derive_ignore
1119 );
1120 }
1121 for (k, v) in self.opts.with.iter() {
1122 uwriteln!(self.src_preamble, "// * with {k:?} = {v}");
1123 }
1124 if let Some(type_section_suffix) = &self.opts.type_section_suffix {
1125 uwriteln!(
1126 self.src_preamble,
1127 "// * type_section_suffix: {:?}",
1128 type_section_suffix
1129 );
1130 }
1131 if let Some(default) = &self.opts.default_bindings_module {
1132 uwriteln!(
1133 self.src_preamble,
1134 "// * default-bindings-module: {default:?}"
1135 );
1136 }
1137 if self.opts.disable_run_ctors_once_workaround {
1138 uwriteln!(
1139 self.src_preamble,
1140 "// * disable-run-ctors-once-workaround"
1141 );
1142 }
1143 if self.opts.merge_structurally_equal_types() {
1144 uwriteln!(self.src_preamble, "// * merge_structurally_equal_types");
1145 }
1146 if let Some(s) = &self.opts.export_macro_name {
1147 uwriteln!(self.src_preamble, "// * export-macro-name: {s}");
1148 }
1149 if self.opts.pub_export_macro {
1150 uwriteln!(self.src_preamble, "// * pub-export-macro");
1151 }
1152 if self.opts.generate_unused_types {
1153 uwriteln!(self.src_preamble, "// * generate_unused_types");
1154 }
1155 if self.opts.disable_custom_section_link_helpers {
1156 uwriteln!(
1157 self.src_preamble,
1158 "// * disable_custom_section_link_helpers"
1159 );
1160 }
1161 for opt in self.opts.async_.debug_opts() {
1162 uwriteln!(self.src_preamble, "// * async: {opt}");
1163 }
1164 self.types.analyze(resolve);
1165 self.types.collect_equal_types(resolve, world, &|a| {
1166 if self.opts.merge_structurally_equal_types() {
1169 return true;
1170 }
1171
1172 match resolve.types[a].kind {
1173 TypeDefKind::Type(_)
1177 | TypeDefKind::Handle(_)
1178 | TypeDefKind::List(_)
1179 | TypeDefKind::Tuple(_)
1180 | TypeDefKind::Option(_)
1181 | TypeDefKind::Result(_)
1182 | TypeDefKind::Future(_)
1183 | TypeDefKind::Stream(_)
1184 | TypeDefKind::Map(..)
1185 | TypeDefKind::FixedLengthList(..) => true,
1186
1187 TypeDefKind::Record(_)
1191 | TypeDefKind::Variant(_)
1192 | TypeDefKind::Enum(_)
1193 | TypeDefKind::Flags(_)
1194 | TypeDefKind::Resource
1195 | TypeDefKind::Unknown => false,
1196 }
1197 });
1198 self.world = Some(world);
1199
1200 let world = &resolve.worlds[world];
1201 for (key, item) in world.imports.iter() {
1204 if let WorldItem::Interface { id, .. } = item {
1205 if resolve.interfaces[*id].package == world.package {
1206 let name = resolve.name_world_key(key);
1207 if self.with.get(&name).is_none() {
1208 self.with.insert(name, TypeGeneration::Generate);
1209 }
1210 }
1211 }
1212 }
1213
1214 for item in world.exports.values() {
1215 let WorldItem::Interface { id, .. } = item else {
1216 continue;
1217 };
1218 for id in resolve.interfaces[*id].types.values().copied() {
1219 let TypeDefKind::Resource = &resolve.types[id].kind else {
1220 continue;
1221 };
1222 assert!(self.exported_resources.insert(id));
1223 }
1224 }
1225
1226 for (k, v) in self.opts.with.iter() {
1227 self.with.insert(k.clone(), v.clone().into());
1228 }
1229 self.with.generate_by_default = self.opts.generate_all;
1230 for (key, item) in world.imports.iter() {
1231 if let WorldItem::Interface { id, .. } = item {
1232 self.name_interface(resolve, *id, &key, false).unwrap();
1233 }
1234 }
1235 for (key, item) in world.exports.iter() {
1236 if let WorldItem::Interface { id, .. } = item {
1237 self.name_interface(resolve, *id, &key, true).unwrap();
1238 }
1239 }
1240 }
1241
1242 fn import_interface(
1243 &mut self,
1244 resolve: &Resolve,
1245 name: &WorldKey,
1246 id: InterfaceId,
1247 _files: &mut Files,
1248 ) -> Result<()> {
1249 let mut to_define = Vec::new();
1250 for (name, ty_id) in resolve.interfaces[id].types.iter() {
1251 let full_name = full_wit_type_name(resolve, *ty_id);
1252 if let Some(type_gen) = self.with.get(&full_name) {
1253 if type_gen.generated() {
1255 to_define.push((name, ty_id));
1256 }
1257 } else {
1258 to_define.push((name, ty_id));
1259 }
1260 self.generated_types.insert(full_name);
1261 }
1262
1263 let wasm_import_module = resolve.name_world_key(name);
1264 let mut r#gen = self.interface(
1265 Identifier::Interface(id, name),
1266 &wasm_import_module,
1267 resolve,
1268 true,
1269 );
1270 let (snake, module_path) = r#gen.start_append_submodule(name);
1271 if r#gen.r#gen.interface_names[&id].remapped {
1272 return Ok(());
1273 }
1274
1275 for (name, ty_id) in to_define {
1276 r#gen.define_type(&name, *ty_id);
1277 }
1278
1279 r#gen.generate_imports(resolve.interfaces[id].functions.values(), Some(name));
1280
1281 let docs = &resolve.interfaces[id].docs;
1282
1283 r#gen.finish_append_submodule(&snake, module_path, docs);
1284
1285 Ok(())
1286 }
1287
1288 fn import_funcs(
1289 &mut self,
1290 resolve: &Resolve,
1291 world: WorldId,
1292 funcs: &[(&str, &Function)],
1293 _files: &mut Files,
1294 ) {
1295 self.import_funcs_called = true;
1296
1297 let mut r#gen = self.interface(Identifier::World(world), "$root", resolve, true);
1298
1299 r#gen.generate_imports(funcs.iter().map(|(_, func)| *func), None);
1300
1301 let src = r#gen.finish();
1302 self.src.push_str(&src);
1303 }
1304
1305 fn export_interface(
1306 &mut self,
1307 resolve: &Resolve,
1308 name: &WorldKey,
1309 id: InterfaceId,
1310 _files: &mut Files,
1311 ) -> Result<()> {
1312 let mut to_define = Vec::new();
1313 for (ty_name, ty_id) in resolve.interfaces[id].types.iter() {
1314 let full_name = full_wit_type_name(resolve, *ty_id);
1315 to_define.push((ty_name, ty_id));
1316 self.generated_types.insert(full_name);
1317 }
1318
1319 let wasm_import_module = format!("[export]{}", resolve.name_world_key(name));
1320 let mut r#gen = self.interface(
1321 Identifier::Interface(id, name),
1322 &wasm_import_module,
1323 resolve,
1324 false,
1325 );
1326 let (snake, module_path) = r#gen.start_append_submodule(name);
1327 if r#gen.r#gen.interface_names[&id].remapped {
1328 return Ok(());
1329 }
1330
1331 for (ty_name, ty_id) in to_define {
1332 r#gen.define_type(&ty_name, *ty_id);
1333 }
1334
1335 let macro_name =
1336 r#gen.generate_exports(Some((id, name)), resolve.interfaces[id].functions.values())?;
1337
1338 let docs = &resolve.interfaces[id].docs;
1339
1340 r#gen.finish_append_submodule(&snake, module_path, docs);
1341 self.export_macros
1342 .push((macro_name, self.interface_names[&id].path.clone()));
1343
1344 if self.opts.stubs {
1345 let world_id = self.world.unwrap();
1346 let mut r#gen = self.interface(
1347 Identifier::World(world_id),
1348 &wasm_import_module,
1349 resolve,
1350 false,
1351 );
1352 r#gen.generate_stub(Some((id, name)), resolve.interfaces[id].functions.values());
1353 let stub = r#gen.finish();
1354 self.src.push_str(&stub);
1355 }
1356 Ok(())
1357 }
1358
1359 fn export_funcs(
1360 &mut self,
1361 resolve: &Resolve,
1362 world: WorldId,
1363 funcs: &[(&str, &Function)],
1364 _files: &mut Files,
1365 ) -> Result<()> {
1366 let mut r#gen = self.interface(Identifier::World(world), "[export]$root", resolve, false);
1367 let macro_name = r#gen.generate_exports(None, funcs.iter().map(|f| f.1))?;
1368 let src = r#gen.finish();
1369 self.src.push_str(&src);
1370 self.export_macros.push((macro_name, String::new()));
1371
1372 if self.opts.stubs {
1373 let mut r#gen =
1374 self.interface(Identifier::World(world), "[export]$root", resolve, false);
1375 r#gen.generate_stub(None, funcs.iter().map(|f| f.1));
1376 let stub = r#gen.finish();
1377 self.src.push_str(&stub);
1378 }
1379 Ok(())
1380 }
1381
1382 fn import_types(
1383 &mut self,
1384 resolve: &Resolve,
1385 world: WorldId,
1386 types: &[(&str, TypeId)],
1387 _files: &mut Files,
1388 ) {
1389 let mut to_define = Vec::new();
1390 for (name, ty_id) in types {
1391 let full_name = full_wit_type_name(resolve, *ty_id);
1392 if let Some(type_gen) = self.with.get(&full_name) {
1393 if type_gen.generated() {
1395 to_define.push((name, ty_id));
1396 }
1397 } else {
1398 to_define.push((name, ty_id));
1399 }
1400 self.generated_types.insert(full_name);
1401 }
1402 let mut r#gen = self.interface(Identifier::World(world), "$root", resolve, true);
1403 for (name, ty) in to_define {
1404 r#gen.define_type(name, *ty);
1405 }
1406 let src = r#gen.finish();
1407 self.src.push_str(&src);
1408 }
1409
1410 fn finish_imports(&mut self, resolve: &Resolve, world: WorldId, files: &mut Files) {
1411 if !self.import_funcs_called {
1412 self.import_funcs(resolve, world, &[], files);
1416 }
1417 }
1418
1419 fn finish(&mut self, resolve: &Resolve, world: WorldId, files: &mut Files) -> Result<()> {
1420 let name = &resolve.worlds[world].name;
1421
1422 let imports = mem::take(&mut self.import_modules);
1423 self.emit_modules(imports);
1424 let exports = mem::take(&mut self.export_modules);
1425 self.emit_modules(exports);
1426
1427 self.finish_runtime_module();
1428 self.finish_export_macro(resolve, world);
1429
1430 let mut resolve_copy;
1469 let (resolve_to_encode, world_to_encode) = if self.opts.pub_export_macro {
1470 resolve_copy = resolve.clone();
1471 let world_copy = resolve_copy.worlds.alloc(World {
1472 exports: Default::default(),
1473 name: format!("{name}-with-all-of-its-exports-removed"),
1474 ..resolve.worlds[world].clone()
1475 });
1476 (&resolve_copy, world_copy)
1477 } else {
1478 (resolve, world)
1479 };
1480 self.emit_custom_section(
1481 resolve_to_encode,
1482 world_to_encode,
1483 "encoded world",
1484 if self.opts.disable_custom_section_link_helpers {
1485 None
1486 } else {
1487 Some("__link_custom_section_describing_imports")
1488 },
1489 );
1490
1491 if self.opts.stubs {
1492 self.src.push_str("\n#[derive(Debug)]\npub struct Stub;\n");
1493 }
1494
1495 let mut src = mem::take(&mut self.src);
1496 if self.opts.format {
1497 let syntax_tree = syn::parse_file(src.as_str()).unwrap();
1498 *src.as_mut_string() = prettyplease::unparse(&syntax_tree);
1499 }
1500
1501 let src_preamble = mem::take(&mut self.src_preamble);
1504 *src.as_mut_string() = format!("{}{}", src_preamble.as_str(), src.as_str());
1505
1506 let module_name = name.to_snake_case();
1507 files.push(&format!("{module_name}.rs"), src.as_bytes());
1508
1509 let remapped_keys = self
1510 .with
1511 .iter()
1512 .map(|(k, _)| k)
1513 .cloned()
1514 .collect::<HashSet<String>>();
1515
1516 let mut unused_keys = remapped_keys
1517 .difference(&self.generated_types)
1518 .collect::<Vec<&String>>();
1519
1520 unused_keys.sort();
1521
1522 if !unused_keys.is_empty() {
1523 bail!("unused remappings provided via `with`: {unused_keys:?}");
1524 }
1525
1526 self.opts.async_.ensure_all_used()?;
1529
1530 Ok(())
1531 }
1532}
1533
1534pub(crate) fn compute_module_path(
1535 name: &WorldKey,
1536 resolve: &Resolve,
1537 is_export: bool,
1538) -> Vec<String> {
1539 let mut path = Vec::new();
1540 if is_export {
1541 path.push("exports".to_string());
1542 }
1543 match name {
1544 WorldKey::Name(name) => {
1545 path.push(to_rust_ident(name));
1546 }
1547 WorldKey::Interface(id) => {
1548 let iface = &resolve.interfaces[*id];
1549 let pkg = iface.package.unwrap();
1550 let pkgname = resolve.packages[pkg].name.clone();
1551 path.push(to_rust_ident(&pkgname.namespace));
1552 path.push(name_package_module(resolve, pkg));
1553 path.push(to_rust_ident(iface.name.as_ref().unwrap()));
1554 }
1555 }
1556 path
1557}
1558
1559enum Identifier<'a> {
1560 World(WorldId),
1561 Interface(InterfaceId, &'a WorldKey),
1562 StreamOrFuturePayload,
1563}
1564
1565fn group_by_resource<'a>(
1566 funcs: impl Iterator<Item = &'a Function>,
1567) -> BTreeMap<Option<TypeId>, Vec<&'a Function>> {
1568 let mut by_resource = BTreeMap::<_, Vec<_>>::new();
1569 for func in funcs {
1570 by_resource
1571 .entry(func.kind.resource())
1572 .or_default()
1573 .push(func);
1574 }
1575 by_resource
1576}
1577
1578#[derive(Default, Debug, Clone, Copy)]
1579#[cfg_attr(
1580 feature = "serde",
1581 derive(serde::Deserialize),
1582 serde(rename_all = "kebab-case")
1583)]
1584pub enum Ownership {
1585 #[default]
1588 Owning,
1589
1590 Borrowing {
1594 duplicate_if_necessary: bool,
1599 },
1600}
1601
1602impl FromStr for Ownership {
1603 type Err = String;
1604
1605 fn from_str(s: &str) -> Result<Self, Self::Err> {
1606 match s {
1607 "owning" => Ok(Self::Owning),
1608 "borrowing" => Ok(Self::Borrowing {
1609 duplicate_if_necessary: false,
1610 }),
1611 "borrowing-duplicate-if-necessary" => Ok(Self::Borrowing {
1612 duplicate_if_necessary: true,
1613 }),
1614 _ => Err(format!(
1615 "unrecognized ownership: `{s}`; \
1616 expected `owning`, `borrowing`, or `borrowing-duplicate-if-necessary`"
1617 )),
1618 }
1619 }
1620}
1621
1622impl fmt::Display for Ownership {
1623 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1624 f.write_str(match self {
1625 Ownership::Owning => "owning",
1626 Ownership::Borrowing {
1627 duplicate_if_necessary: false,
1628 } => "borrowing",
1629 Ownership::Borrowing {
1630 duplicate_if_necessary: true,
1631 } => "borrowing-duplicate-if-necessary",
1632 })
1633 }
1634}
1635
1636#[derive(Debug, Clone)]
1638#[cfg_attr(
1639 feature = "serde",
1640 derive(serde::Deserialize),
1641 serde(rename_all = "kebab-case")
1642)]
1643pub enum WithOption {
1644 Path(String),
1645 Generate,
1646}
1647
1648impl std::fmt::Display for WithOption {
1649 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1650 match self {
1651 WithOption::Path(p) => f.write_fmt(format_args!("\"{p}\"")),
1652 WithOption::Generate => f.write_str("generate"),
1653 }
1654 }
1655}
1656
1657impl From<WithOption> for TypeGeneration {
1658 fn from(opt: WithOption) -> Self {
1659 match opt {
1660 WithOption::Path(p) => TypeGeneration::Remap(p),
1661 WithOption::Generate => TypeGeneration::Generate,
1662 }
1663 }
1664}
1665
1666#[derive(Default)]
1667struct FnSig {
1668 async_: bool,
1669 unsafe_: bool,
1670 private: bool,
1671 use_item_name: bool,
1672 generics: Option<String>,
1673 self_arg: Option<String>,
1674 self_is_first_param: bool,
1675}
1676
1677impl FnSig {
1678 fn update_for_func(&mut self, func: &Function) {
1679 if let FunctionKind::Method(_) | FunctionKind::AsyncMethod(_) = &func.kind {
1680 self.self_arg = Some("&self".into());
1681 self.self_is_first_param = true;
1682 }
1683 }
1684}
1685
1686pub fn to_rust_ident(name: &str) -> String {
1687 match name {
1688 "as" => "as_".into(),
1691 "break" => "break_".into(),
1692 "const" => "const_".into(),
1693 "continue" => "continue_".into(),
1694 "crate" => "crate_".into(),
1695 "else" => "else_".into(),
1696 "enum" => "enum_".into(),
1697 "extern" => "extern_".into(),
1698 "false" => "false_".into(),
1699 "fn" => "fn_".into(),
1700 "for" => "for_".into(),
1701 "if" => "if_".into(),
1702 "impl" => "impl_".into(),
1703 "in" => "in_".into(),
1704 "let" => "let_".into(),
1705 "loop" => "loop_".into(),
1706 "match" => "match_".into(),
1707 "mod" => "mod_".into(),
1708 "move" => "move_".into(),
1709 "mut" => "mut_".into(),
1710 "pub" => "pub_".into(),
1711 "ref" => "ref_".into(),
1712 "return" => "return_".into(),
1713 "self" => "self_".into(),
1714 "static" => "static_".into(),
1715 "struct" => "struct_".into(),
1716 "super" => "super_".into(),
1717 "trait" => "trait_".into(),
1718 "true" => "true_".into(),
1719 "type" => "type_".into(),
1720 "unsafe" => "unsafe_".into(),
1721 "use" => "use_".into(),
1722 "where" => "where_".into(),
1723 "while" => "while_".into(),
1724 "async" => "async_".into(),
1725 "await" => "await_".into(),
1726 "dyn" => "dyn_".into(),
1727 "abstract" => "abstract_".into(),
1728 "become" => "become_".into(),
1729 "box" => "box_".into(),
1730 "do" => "do_".into(),
1731 "final" => "final_".into(),
1732 "macro" => "macro_".into(),
1733 "override" => "override_".into(),
1734 "priv" => "priv_".into(),
1735 "typeof" => "typeof_".into(),
1736 "unsized" => "unsized_".into(),
1737 "virtual" => "virtual_".into(),
1738 "yield" => "yield_".into(),
1739 "try" => "try_".into(),
1740 s => s.to_snake_case(),
1741 }
1742}
1743
1744fn to_upper_camel_case(name: &str) -> String {
1745 match name {
1746 "guest" => "Guest_".to_string(),
1749 s => s.to_upper_camel_case(),
1750 }
1751}
1752
1753fn wasm_type(ty: WasmType) -> &'static str {
1754 match ty {
1755 WasmType::I32 => "i32",
1756 WasmType::I64 => "i64",
1757 WasmType::F32 => "f32",
1758 WasmType::F64 => "f64",
1759 WasmType::Pointer => "*mut u8",
1760 WasmType::Length => "usize",
1761
1762 WasmType::PointerOrI64 => "::core::mem::MaybeUninit::<u64>",
1768 }
1769}
1770
1771fn declare_import(
1772 wasm_import_module: &str,
1773 wasm_import_name: &str,
1774 rust_name: &str,
1775 params: &[WasmType],
1776 results: &[WasmType],
1777) -> String {
1778 let mut sig = "(".to_owned();
1779 for param in params.iter() {
1780 sig.push_str("_: ");
1781 sig.push_str(wasm_type(*param));
1782 sig.push_str(", ");
1783 }
1784 sig.push(')');
1785 assert!(results.len() < 2);
1786 for result in results.iter() {
1787 sig.push_str(" -> ");
1788 sig.push_str(wasm_type(*result));
1789 }
1790 format!(
1791 "
1792 #[cfg(target_arch = \"wasm32\")]
1793 #[link(wasm_import_module = \"{wasm_import_module}\")]
1794 unsafe extern \"C\" {{
1795 #[link_name = \"{wasm_import_name}\"]
1796 fn {rust_name}{sig};
1797 }}
1798
1799 #[cfg(not(target_arch = \"wasm32\"))]
1800 unsafe extern \"C\" fn {rust_name}{sig} {{ unreachable!() }}
1801 "
1802 )
1803}
1804
1805fn int_repr(repr: Int) -> &'static str {
1806 match repr {
1807 Int::U8 => "u8",
1808 Int::U16 => "u16",
1809 Int::U32 => "u32",
1810 Int::U64 => "u64",
1811 }
1812}
1813
1814fn bitcast(casts: &[Bitcast], operands: &[String], results: &mut Vec<String>) {
1815 for (cast, operand) in casts.iter().zip(operands) {
1816 results.push(perform_cast(operand, cast));
1817 }
1818}
1819
1820fn perform_cast(operand: &str, cast: &Bitcast) -> String {
1821 match cast {
1822 Bitcast::None => operand.to_owned(),
1823 Bitcast::I32ToI64 => format!("i64::from({operand})"),
1824 Bitcast::F32ToI32 => format!("({operand}).to_bits() as i32"),
1825 Bitcast::F64ToI64 => format!("({operand}).to_bits() as i64"),
1826 Bitcast::I64ToI32 => format!("{operand} as i32"),
1827 Bitcast::I32ToF32 => format!("f32::from_bits({operand} as u32)"),
1828 Bitcast::I64ToF64 => format!("f64::from_bits({operand} as u64)"),
1829 Bitcast::F32ToI64 => format!("i64::from(({operand}).to_bits())"),
1830 Bitcast::I64ToF32 => format!("f32::from_bits({operand} as u32)"),
1831
1832 Bitcast::I64ToP64 => format!("::core::mem::MaybeUninit::new({operand} as u64)"),
1834 Bitcast::P64ToI64 => format!("{operand}.assume_init() as i64"),
1837
1838 Bitcast::PToP64 => {
1840 format!(
1841 "{{
1842 let mut t = ::core::mem::MaybeUninit::<u64>::uninit();
1843 t.as_mut_ptr().cast::<*mut u8>().write({operand});
1844 t
1845 }}"
1846 )
1847 }
1848 Bitcast::P64ToP => {
1851 format!("{operand}.as_ptr().cast::<*mut u8>().read()")
1852 }
1853 Bitcast::I32ToP | Bitcast::LToP => {
1855 format!("{operand} as *mut u8")
1856 }
1857 Bitcast::PToI32 | Bitcast::LToI32 => {
1859 format!("{operand} as i32")
1860 }
1861 Bitcast::I32ToL | Bitcast::I64ToL | Bitcast::PToL => {
1863 format!("{operand} as usize")
1864 }
1865 Bitcast::LToI64 => {
1867 format!("{operand} as i64")
1868 }
1869 Bitcast::Sequence(sequence) => {
1870 let [first, second] = &**sequence;
1871 perform_cast(&perform_cast(operand, first), second)
1872 }
1873 }
1874}
1875
1876enum RustFlagsRepr {
1877 U8,
1878 U16,
1879 U32,
1880 U64,
1881 U128,
1882}
1883
1884impl RustFlagsRepr {
1885 fn new(f: &Flags) -> RustFlagsRepr {
1886 match f.repr() {
1887 FlagsRepr::U8 => RustFlagsRepr::U8,
1888 FlagsRepr::U16 => RustFlagsRepr::U16,
1889 FlagsRepr::U32(1) => RustFlagsRepr::U32,
1890 FlagsRepr::U32(2) => RustFlagsRepr::U64,
1891 FlagsRepr::U32(3 | 4) => RustFlagsRepr::U128,
1892 FlagsRepr::U32(n) => panic!("unsupported number of flags: {}", n * 32),
1893 }
1894 }
1895}
1896
1897impl fmt::Display for RustFlagsRepr {
1898 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1899 match self {
1900 RustFlagsRepr::U8 => "u8".fmt(f),
1901 RustFlagsRepr::U16 => "u16".fmt(f),
1902 RustFlagsRepr::U32 => "u32".fmt(f),
1903 RustFlagsRepr::U64 => "u64".fmt(f),
1904 RustFlagsRepr::U128 => "u128".fmt(f),
1905 }
1906 }
1907}
1908
1909#[derive(Debug, Clone)]
1910pub struct MissingWith(pub String);
1911
1912impl fmt::Display for MissingWith {
1913 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1914 write!(f, "missing `with` mapping for the key `{}`", self.0)
1915 }
1916}
1917
1918impl std::error::Error for MissingWith {}
1919
1920fn full_wit_type_name(resolve: &Resolve, id: TypeId) -> String {
1927 let id = dealias(resolve, id);
1928 let type_def = &resolve.types[id];
1929 let interface_name = match type_def.owner {
1930 TypeOwner::World(w) => Some(resolve.worlds[w].name.clone()),
1931 TypeOwner::Interface(id) => resolve.id_of(id),
1932 TypeOwner::None => None,
1933 };
1934 match interface_name {
1935 Some(interface_name) => format!("{}/{}", interface_name, type_def.name.clone().unwrap()),
1936 None => type_def.name.clone().unwrap(),
1937 }
1938}
1939
1940enum ConstructorReturnType {
1941 Self_,
1948
1949 Result { err: Option<Type> },
1956}
1957
1958fn classify_constructor_return_type(
1959 resolve: &Resolve,
1960 resource_id: TypeId,
1961 result: &Option<Type>,
1962) -> ConstructorReturnType {
1963 fn classify(
1964 resolve: &Resolve,
1965 resource_id: TypeId,
1966 result: &Option<Type>,
1967 ) -> Option<ConstructorReturnType> {
1968 let resource_id = dealias(resolve, resource_id);
1969 let typedef = match result.as_ref()? {
1970 Type::Id(id) => &resolve.types[dealias(resolve, *id)],
1971 _ => return None,
1972 };
1973
1974 match &typedef.kind {
1975 TypeDefKind::Handle(Handle::Own(id)) if dealias(resolve, *id) == resource_id => {
1976 Some(ConstructorReturnType::Self_)
1977 }
1978 TypeDefKind::Result(Result_ { ok, err }) => {
1979 let ok_typedef = match ok.as_ref()? {
1980 Type::Id(id) => &resolve.types[dealias(resolve, *id)],
1981 _ => return None,
1982 };
1983
1984 match &ok_typedef.kind {
1985 TypeDefKind::Handle(Handle::Own(id))
1986 if dealias(resolve, *id) == resource_id =>
1987 {
1988 Some(ConstructorReturnType::Result { err: *err })
1989 }
1990 _ => None,
1991 }
1992 }
1993 _ => None,
1994 }
1995 }
1996
1997 classify(resolve, resource_id, result).expect("invalid constructor")
1998}