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