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 ) -> Result<InterfaceGenerator<'a>> {
412 let mut sizes = SizeAlign::default();
413 sizes.fill(resolve)?;
414
415 Ok(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 ) -> Result<()> {
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 Ok(())
1381 }
1382
1383 fn export_interface(
1384 &mut self,
1385 resolve: &Resolve,
1386 name: &WorldKey,
1387 id: InterfaceId,
1388 _files: &mut Files,
1389 ) -> Result<()> {
1390 let mut to_define = Vec::new();
1391 for (ty_name, ty_id) in resolve.interfaces[id].types.iter() {
1392 let full_name = full_wit_type_name(resolve, *ty_id);
1393 to_define.push((ty_name, ty_id));
1394 self.generated_types.insert(full_name);
1395 }
1396
1397 let wasm_import_module = format!("[export]{}", resolve.name_world_key(name));
1398 let mut r#gen = self.interface(
1399 Identifier::Interface(id, name),
1400 &wasm_import_module,
1401 resolve,
1402 false,
1403 )?;
1404 let (snake, module_path) = r#gen.start_append_submodule(name);
1405 if r#gen.r#gen.interface_names[&id].remapped {
1406 return Ok(());
1407 }
1408
1409 for (ty_name, ty_id) in to_define {
1410 r#gen.define_type(&ty_name, *ty_id);
1411 }
1412
1413 let macro_name =
1414 r#gen.generate_exports(Some((id, name)), resolve.interfaces[id].functions.values())?;
1415
1416 let docs = &resolve.interfaces[id].docs;
1417
1418 r#gen.finish_append_submodule(&snake, module_path, docs);
1419 self.export_macros
1420 .push((macro_name, self.interface_names[&id].path.clone()));
1421
1422 if self.opts.stubs {
1423 let world_id = self.world.unwrap();
1424 let mut r#gen = self.interface(
1425 Identifier::World(world_id),
1426 &wasm_import_module,
1427 resolve,
1428 false,
1429 )?;
1430 r#gen.generate_stub(Some((id, name)), resolve.interfaces[id].functions.values());
1431 let stub = r#gen.finish();
1432 self.src.push_str(&stub);
1433 }
1434 Ok(())
1435 }
1436
1437 fn export_funcs(
1438 &mut self,
1439 resolve: &Resolve,
1440 world: WorldId,
1441 funcs: &[(&str, &Function)],
1442 _files: &mut Files,
1443 ) -> Result<()> {
1444 let mut r#gen =
1445 self.interface(Identifier::World(world), "[export]$root", resolve, false)?;
1446 let macro_name = r#gen.generate_exports(None, funcs.iter().map(|f| f.1))?;
1447 let src = r#gen.finish();
1448 self.src.push_str(&src);
1449 self.export_macros.push((macro_name, String::new()));
1450
1451 if self.opts.stubs {
1452 let mut r#gen =
1453 self.interface(Identifier::World(world), "[export]$root", resolve, false)?;
1454 r#gen.generate_stub(None, funcs.iter().map(|f| f.1));
1455 let stub = r#gen.finish();
1456 self.src.push_str(&stub);
1457 }
1458 Ok(())
1459 }
1460
1461 fn import_types(
1462 &mut self,
1463 resolve: &Resolve,
1464 world: WorldId,
1465 types: &[(&str, TypeId)],
1466 _files: &mut Files,
1467 ) -> Result<()> {
1468 let mut to_define = Vec::new();
1469 for (name, ty_id) in types {
1470 let full_name = full_wit_type_name(resolve, *ty_id);
1471 if let Some(type_gen) = self.with.get(&full_name) {
1472 if type_gen.generated() {
1474 to_define.push((name, ty_id));
1475 }
1476 } else {
1477 to_define.push((name, ty_id));
1478 }
1479 self.generated_types.insert(full_name);
1480 }
1481 let mut r#gen = self.interface(Identifier::World(world), "$root", resolve, true)?;
1482 for (name, ty) in to_define {
1483 r#gen.define_type(name, *ty);
1484 }
1485 let src = r#gen.finish();
1486 self.src.push_str(&src);
1487 Ok(())
1488 }
1489
1490 fn finish_imports(
1491 &mut self,
1492 resolve: &Resolve,
1493 world: WorldId,
1494 files: &mut Files,
1495 ) -> Result<()> {
1496 if !self.import_funcs_called {
1497 self.import_funcs(resolve, world, &[], files)?;
1501 }
1502 Ok(())
1503 }
1504
1505 fn finish(&mut self, resolve: &Resolve, world: WorldId, files: &mut Files) -> Result<()> {
1506 let name = &resolve.worlds[world].name;
1507
1508 let imports = mem::take(&mut self.import_modules);
1509 self.emit_modules(imports);
1510 let exports = mem::take(&mut self.export_modules);
1511 self.emit_modules(exports);
1512
1513 self.finish_runtime_module();
1514 self.finish_export_macro(resolve, world);
1515
1516 let mut resolve_copy;
1555 let (resolve_to_encode, world_to_encode) = if self.opts.pub_export_macro {
1556 resolve_copy = resolve.clone();
1557 let world_copy = resolve_copy.worlds.alloc(World {
1558 exports: Default::default(),
1559 name: format!("{name}-with-all-of-its-exports-removed"),
1560 ..resolve.worlds[world].clone()
1561 });
1562 (&resolve_copy, world_copy)
1563 } else {
1564 (resolve, world)
1565 };
1566 self.emit_custom_section(
1567 resolve_to_encode,
1568 world_to_encode,
1569 "encoded world",
1570 if self.opts.disable_custom_section_link_helpers {
1571 None
1572 } else {
1573 Some("__link_custom_section_describing_imports")
1574 },
1575 );
1576
1577 if self.opts.stubs {
1578 self.src.push_str("\n#[derive(Debug)]\npub struct Stub;\n");
1579 }
1580
1581 let mut src = mem::take(&mut self.src);
1582 if self.opts.format {
1583 let syntax_tree = syn::parse_file(src.as_str()).unwrap();
1584 *src.as_mut_string() = prettyplease::unparse(&syntax_tree);
1585 }
1586
1587 let src_preamble = mem::take(&mut self.src_preamble);
1590 *src.as_mut_string() = format!("{}{}", src_preamble.as_str(), src.as_str());
1591
1592 let module_name = name.to_snake_case();
1593 files.push(&format!("{module_name}.rs"), src.as_bytes());
1594
1595 let remapped_keys = self
1596 .with
1597 .iter()
1598 .map(|(k, _)| k)
1599 .cloned()
1600 .collect::<HashSet<String>>();
1601
1602 let mut unused_keys = remapped_keys
1603 .difference(&self.generated_types)
1604 .collect::<Vec<&String>>();
1605
1606 unused_keys.sort();
1607
1608 if !unused_keys.is_empty() {
1609 bail!("unused remappings provided via `with`: {unused_keys:?}");
1610 }
1611
1612 let mut unused_selectors = self
1613 .opts
1614 .additional_type_attributes
1615 .iter()
1616 .map(|(sel, _)| sel)
1617 .filter(|sel| !self.used_type_attr_selectors.contains(*sel))
1618 .chain(
1619 self.opts
1620 .additional_member_attributes
1621 .iter()
1622 .map(|(sel, _)| sel)
1623 .filter(|sel| !self.used_member_attr_selectors.contains(*sel)),
1624 )
1625 .collect::<Vec<_>>();
1626 unused_selectors.sort();
1627 unused_selectors.dedup();
1628 if !unused_selectors.is_empty() {
1629 bail!(
1630 "unused selectors provided via `additional_type_attributes` / \
1631 `additional_member_attributes`: {unused_selectors:?}"
1632 );
1633 }
1634
1635 self.opts.async_.ensure_all_used()?;
1638 self.opts.chainable_methods.ensure_all_used()?;
1639
1640 Ok(())
1641 }
1642}
1643
1644pub(crate) fn compute_module_path(
1645 name: &WorldKey,
1646 resolve: &Resolve,
1647 is_export: bool,
1648) -> Vec<String> {
1649 let mut path = Vec::new();
1650 if is_export {
1651 path.push("exports".to_string());
1652 }
1653 match name {
1654 WorldKey::Name(name) => {
1655 path.push(to_rust_ident(name));
1656 }
1657 WorldKey::Interface(id) => {
1658 let iface = &resolve.interfaces[*id];
1659 let pkg = iface.package.unwrap();
1660 let pkgname = resolve.packages[pkg].name.clone();
1661 path.push(to_rust_ident(&pkgname.namespace));
1662 path.push(name_package_module(resolve, pkg));
1663 path.push(to_rust_ident(iface.name.as_ref().unwrap()));
1664 }
1665 }
1666 path
1667}
1668
1669enum Identifier<'a> {
1670 World(WorldId),
1671 Interface(InterfaceId, &'a WorldKey),
1672 StreamOrFuturePayload,
1673}
1674
1675fn group_by_resource<'a>(
1676 funcs: impl Iterator<Item = &'a Function>,
1677) -> BTreeMap<Option<TypeId>, Vec<&'a Function>> {
1678 let mut by_resource = BTreeMap::<_, Vec<_>>::new();
1679 for func in funcs {
1680 by_resource
1681 .entry(func.kind.resource())
1682 .or_default()
1683 .push(func);
1684 }
1685 by_resource
1686}
1687
1688#[derive(Default, Debug, Clone, Copy)]
1689#[cfg_attr(
1690 feature = "serde",
1691 derive(serde::Deserialize),
1692 serde(rename_all = "kebab-case")
1693)]
1694pub enum Ownership {
1695 #[default]
1698 Owning,
1699
1700 Borrowing {
1704 duplicate_if_necessary: bool,
1709 },
1710}
1711
1712impl FromStr for Ownership {
1713 type Err = String;
1714
1715 fn from_str(s: &str) -> Result<Self, Self::Err> {
1716 match s {
1717 "owning" => Ok(Self::Owning),
1718 "borrowing" => Ok(Self::Borrowing {
1719 duplicate_if_necessary: false,
1720 }),
1721 "borrowing-duplicate-if-necessary" => Ok(Self::Borrowing {
1722 duplicate_if_necessary: true,
1723 }),
1724 _ => Err(format!(
1725 "unrecognized ownership: `{s}`; \
1726 expected `owning`, `borrowing`, or `borrowing-duplicate-if-necessary`"
1727 )),
1728 }
1729 }
1730}
1731
1732impl fmt::Display for Ownership {
1733 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1734 f.write_str(match self {
1735 Ownership::Owning => "owning",
1736 Ownership::Borrowing {
1737 duplicate_if_necessary: false,
1738 } => "borrowing",
1739 Ownership::Borrowing {
1740 duplicate_if_necessary: true,
1741 } => "borrowing-duplicate-if-necessary",
1742 })
1743 }
1744}
1745
1746#[derive(Debug, Clone)]
1748#[cfg_attr(
1749 feature = "serde",
1750 derive(serde::Deserialize),
1751 serde(rename_all = "kebab-case")
1752)]
1753pub enum WithOption {
1754 Path(String),
1755 Generate,
1756}
1757
1758impl std::fmt::Display for WithOption {
1759 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1760 match self {
1761 WithOption::Path(p) => f.write_fmt(format_args!("\"{p}\"")),
1762 WithOption::Generate => f.write_str("generate"),
1763 }
1764 }
1765}
1766
1767impl From<WithOption> for TypeGeneration {
1768 fn from(opt: WithOption) -> Self {
1769 match opt {
1770 WithOption::Path(p) => TypeGeneration::Remap(p),
1771 WithOption::Generate => TypeGeneration::Generate,
1772 }
1773 }
1774}
1775
1776#[derive(Default)]
1777struct FnSig {
1778 async_: bool,
1779 unsafe_: bool,
1780 private: bool,
1781 use_item_name: bool,
1782 generics: Option<String>,
1783 self_arg: Option<String>,
1784 self_is_first_param: bool,
1785}
1786
1787impl FnSig {
1788 fn update_for_func(&mut self, func: &Function, return_self: Option<ChainingMode>) {
1789 if let FunctionKind::Method(_) | FunctionKind::AsyncMethod(_) = &func.kind {
1790 self.self_arg = Some(
1791 match return_self {
1792 Some(ChainingMode::Owning) => "self",
1793 _ => "&self",
1794 }
1795 .into(),
1796 );
1797 self.self_is_first_param = true;
1798 }
1799 }
1800}
1801
1802pub fn to_rust_ident(name: &str) -> String {
1803 match name {
1804 "as" => "as_".into(),
1807 "break" => "break_".into(),
1808 "const" => "const_".into(),
1809 "continue" => "continue_".into(),
1810 "crate" => "crate_".into(),
1811 "else" => "else_".into(),
1812 "enum" => "enum_".into(),
1813 "extern" => "extern_".into(),
1814 "false" => "false_".into(),
1815 "fn" => "fn_".into(),
1816 "for" => "for_".into(),
1817 "if" => "if_".into(),
1818 "impl" => "impl_".into(),
1819 "in" => "in_".into(),
1820 "let" => "let_".into(),
1821 "loop" => "loop_".into(),
1822 "match" => "match_".into(),
1823 "mod" => "mod_".into(),
1824 "move" => "move_".into(),
1825 "mut" => "mut_".into(),
1826 "pub" => "pub_".into(),
1827 "ref" => "ref_".into(),
1828 "return" => "return_".into(),
1829 "self" => "self_".into(),
1830 "static" => "static_".into(),
1831 "struct" => "struct_".into(),
1832 "super" => "super_".into(),
1833 "trait" => "trait_".into(),
1834 "true" => "true_".into(),
1835 "type" => "type_".into(),
1836 "unsafe" => "unsafe_".into(),
1837 "use" => "use_".into(),
1838 "where" => "where_".into(),
1839 "while" => "while_".into(),
1840 "async" => "async_".into(),
1841 "await" => "await_".into(),
1842 "dyn" => "dyn_".into(),
1843 "abstract" => "abstract_".into(),
1844 "become" => "become_".into(),
1845 "box" => "box_".into(),
1846 "do" => "do_".into(),
1847 "final" => "final_".into(),
1848 "macro" => "macro_".into(),
1849 "override" => "override_".into(),
1850 "priv" => "priv_".into(),
1851 "typeof" => "typeof_".into(),
1852 "unsized" => "unsized_".into(),
1853 "virtual" => "virtual_".into(),
1854 "yield" => "yield_".into(),
1855 "try" => "try_".into(),
1856 s => s.to_snake_case(),
1857 }
1858}
1859
1860fn to_upper_camel_case(name: &str) -> String {
1861 match name {
1862 "guest" => "Guest_".to_string(),
1865 s => s.to_upper_camel_case(),
1866 }
1867}
1868
1869fn wasm_type(ty: WasmType) -> &'static str {
1870 match ty {
1871 WasmType::I32 => "i32",
1872 WasmType::I64 => "i64",
1873 WasmType::F32 => "f32",
1874 WasmType::F64 => "f64",
1875 WasmType::Pointer => "*mut u8",
1876 WasmType::Length => "usize",
1877
1878 WasmType::PointerOrI64 => "::core::mem::MaybeUninit::<u64>",
1884 }
1885}
1886
1887fn declare_import(
1888 wasm_import_module: &str,
1889 wasm_import_name: &str,
1890 rust_name: &str,
1891 params: &[WasmType],
1892 results: &[WasmType],
1893) -> String {
1894 let mut sig = "(".to_owned();
1895 for param in params.iter() {
1896 sig.push_str("_: ");
1897 sig.push_str(wasm_type(*param));
1898 sig.push_str(", ");
1899 }
1900 sig.push(')');
1901 assert!(results.len() < 2);
1902 for result in results.iter() {
1903 sig.push_str(" -> ");
1904 sig.push_str(wasm_type(*result));
1905 }
1906 format!(
1907 "
1908 #[cfg(target_arch = \"wasm32\")]
1909 #[link(wasm_import_module = \"{wasm_import_module}\")]
1910 unsafe extern \"C\" {{
1911 #[link_name = \"{wasm_import_name}\"]
1912 fn {rust_name}{sig};
1913 }}
1914
1915 #[cfg(not(target_arch = \"wasm32\"))]
1916 unsafe extern \"C\" fn {rust_name}{sig} {{ unreachable!() }}
1917 "
1918 )
1919}
1920
1921fn int_repr(repr: Int) -> &'static str {
1922 match repr {
1923 Int::U8 => "u8",
1924 Int::U16 => "u16",
1925 Int::U32 => "u32",
1926 Int::U64 => "u64",
1927 }
1928}
1929
1930fn bitcast(casts: &[Bitcast], operands: &[String], results: &mut Vec<String>) {
1931 for (cast, operand) in casts.iter().zip(operands) {
1932 results.push(perform_cast(operand, cast));
1933 }
1934}
1935
1936fn perform_cast(operand: &str, cast: &Bitcast) -> String {
1937 match cast {
1938 Bitcast::None => operand.to_owned(),
1939 Bitcast::I32ToI64 => format!("i64::from({operand})"),
1940 Bitcast::F32ToI32 => format!("({operand}).to_bits() as i32"),
1941 Bitcast::F64ToI64 => format!("({operand}).to_bits() as i64"),
1942 Bitcast::I64ToI32 => format!("{operand} as i32"),
1943 Bitcast::I32ToF32 => format!("f32::from_bits({operand} as u32)"),
1944 Bitcast::I64ToF64 => format!("f64::from_bits({operand} as u64)"),
1945 Bitcast::F32ToI64 => format!("i64::from(({operand}).to_bits())"),
1946 Bitcast::I64ToF32 => format!("f32::from_bits({operand} as u32)"),
1947
1948 Bitcast::I64ToP64 => format!("::core::mem::MaybeUninit::new({operand} as u64)"),
1950 Bitcast::P64ToI64 => format!("{operand}.assume_init() as i64"),
1953
1954 Bitcast::PToP64 => {
1956 format!(
1957 "{{
1958 let mut t = ::core::mem::MaybeUninit::<u64>::uninit();
1959 t.as_mut_ptr().cast::<*mut u8>().write({operand});
1960 t
1961 }}"
1962 )
1963 }
1964 Bitcast::P64ToP => {
1967 format!("{operand}.as_ptr().cast::<*mut u8>().read()")
1968 }
1969 Bitcast::I32ToP | Bitcast::LToP => {
1971 format!("{operand} as *mut u8")
1972 }
1973 Bitcast::PToI32 | Bitcast::LToI32 => {
1975 format!("{operand} as i32")
1976 }
1977 Bitcast::I32ToL | Bitcast::I64ToL | Bitcast::PToL => {
1979 format!("{operand} as usize")
1980 }
1981 Bitcast::LToI64 => {
1983 format!("{operand} as i64")
1984 }
1985 Bitcast::Sequence(sequence) => {
1986 let [first, second] = &**sequence;
1987 perform_cast(&perform_cast(operand, first), second)
1988 }
1989 }
1990}
1991
1992enum RustFlagsRepr {
1993 U8,
1994 U16,
1995 U32,
1996 U64,
1997 U128,
1998}
1999
2000impl RustFlagsRepr {
2001 fn new(f: &Flags) -> RustFlagsRepr {
2002 match f.repr() {
2003 FlagsRepr::U8 => RustFlagsRepr::U8,
2004 FlagsRepr::U16 => RustFlagsRepr::U16,
2005 FlagsRepr::U32(1) => RustFlagsRepr::U32,
2006 FlagsRepr::U32(2) => RustFlagsRepr::U64,
2007 FlagsRepr::U32(3 | 4) => RustFlagsRepr::U128,
2008 FlagsRepr::U32(n) => panic!("unsupported number of flags: {}", n * 32),
2009 }
2010 }
2011}
2012
2013impl fmt::Display for RustFlagsRepr {
2014 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2015 match self {
2016 RustFlagsRepr::U8 => "u8".fmt(f),
2017 RustFlagsRepr::U16 => "u16".fmt(f),
2018 RustFlagsRepr::U32 => "u32".fmt(f),
2019 RustFlagsRepr::U64 => "u64".fmt(f),
2020 RustFlagsRepr::U128 => "u128".fmt(f),
2021 }
2022 }
2023}
2024
2025#[derive(Debug, Clone)]
2026pub struct MissingWith(pub String);
2027
2028impl fmt::Display for MissingWith {
2029 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2030 write!(f, "missing `with` mapping for the key `{}`", self.0)
2031 }
2032}
2033
2034impl std::error::Error for MissingWith {}
2035
2036fn full_wit_type_name(resolve: &Resolve, id: TypeId) -> String {
2043 let id = dealias(resolve, id);
2044 let type_def = &resolve.types[id];
2045 let interface_name = match type_def.owner {
2046 TypeOwner::World(w) => Some(resolve.worlds[w].name.clone()),
2047 TypeOwner::Interface(id) => resolve.id_of(id),
2048 TypeOwner::None => None,
2049 };
2050 match interface_name {
2051 Some(interface_name) => format!("{}/{}", interface_name, type_def.name.clone().unwrap()),
2052 None => type_def.name.clone().unwrap(),
2053 }
2054}
2055
2056enum ConstructorReturnType {
2057 Self_,
2064
2065 Result { err: Option<Type> },
2072}
2073
2074fn classify_constructor_return_type(
2075 resolve: &Resolve,
2076 resource_id: TypeId,
2077 result: &Option<Type>,
2078) -> ConstructorReturnType {
2079 fn classify(
2080 resolve: &Resolve,
2081 resource_id: TypeId,
2082 result: &Option<Type>,
2083 ) -> Option<ConstructorReturnType> {
2084 let resource_id = dealias(resolve, resource_id);
2085 let typedef = match result.as_ref()? {
2086 Type::Id(id) => &resolve.types[dealias(resolve, *id)],
2087 _ => return None,
2088 };
2089
2090 match &typedef.kind {
2091 TypeDefKind::Handle(Handle::Own(id)) if dealias(resolve, *id) == resource_id => {
2092 Some(ConstructorReturnType::Self_)
2093 }
2094 TypeDefKind::Result(Result_ { ok, err }) => {
2095 let ok_typedef = match ok.as_ref()? {
2096 Type::Id(id) => &resolve.types[dealias(resolve, *id)],
2097 _ => return None,
2098 };
2099
2100 match &ok_typedef.kind {
2101 TypeDefKind::Handle(Handle::Own(id))
2102 if dealias(resolve, *id) == resource_id =>
2103 {
2104 Some(ConstructorReturnType::Result { err: *err })
2105 }
2106 _ => None,
2107 }
2108 }
2109 _ => None,
2110 }
2111 }
2112
2113 classify(resolve, resource_id, result).expect("invalid constructor")
2114}