1 use crate::rust::{to_rust_ident, to_rust_upper_camel_case, RustGenerator, TypeMode}; 2 use crate::types::{TypeInfo, Types}; 3 use anyhow::{bail, Context}; 4 use heck::*; 5 use indexmap::{IndexMap, IndexSet}; 6 use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; 7 use std::fmt::Write as _; 8 use std::io::{Read, Write}; 9 use std::mem; 10 use std::process::{Command, Stdio}; 11 use wit_parser::*; 12 13 macro_rules! uwrite { 14 ($dst:expr, $($arg:tt)*) => { 15 write!($dst, $($arg)*).unwrap() 16 }; 17 } 18 19 macro_rules! uwriteln { 20 ($dst:expr, $($arg:tt)*) => { 21 writeln!($dst, $($arg)*).unwrap() 22 }; 23 } 24 25 mod rust; 26 mod source; 27 mod types; 28 use source::Source; 29 30 #[derive(Clone)] 31 enum InterfaceName { 32 /// This interface was remapped using `with` to some other Rust code. 33 Remapped { 34 name_at_root: String, 35 local_path: Vec<String>, 36 }, 37 /// This interface is generated in the module hierarchy specified. 38 Path(Vec<String>), 39 } 40 41 #[derive(Default)] 42 struct Wasmtime { 43 src: Source, 44 opts: Opts, 45 import_interfaces: Vec<(String, InterfaceName)>, 46 import_functions: Vec<ImportFunction>, 47 exports: Exports, 48 types: Types, 49 sizes: SizeAlign, 50 interface_names: HashMap<InterfaceId, InterfaceName>, 51 interface_last_seen_as_import: HashMap<InterfaceId, bool>, 52 trappable_errors: IndexMap<TypeId, String>, 53 // Track the with options that were used. Remapped interfaces provided via `with` 54 // are required to be used. 55 used_with_opts: HashSet<String>, 56 } 57 58 struct ImportFunction { 59 add_to_linker: String, 60 sig: String, 61 } 62 63 #[derive(Default)] 64 struct Exports { 65 fields: BTreeMap<String, (String, String)>, 66 modules: Vec<(String, InterfaceName)>, 67 funcs: Vec<String>, 68 } 69 70 #[derive(Default, Debug, Clone, Copy)] 71 pub enum Ownership { 72 /// Generated types will be composed entirely of owning fields, regardless 73 /// of whether they are used as parameters to guest exports or not. 74 #[default] 75 Owning, 76 77 /// Generated types used as parameters to guest exports will be "deeply 78 /// borrowing", i.e. contain references rather than owned values when 79 /// applicable. 80 Borrowing { 81 /// Whether or not to generate "duplicate" type definitions for a single 82 /// WIT type if necessary, for example if it's used as both an import 83 /// and an export, or if it's used both as a parameter to an export and 84 /// a return value from an export. 85 duplicate_if_necessary: bool, 86 }, 87 } 88 89 #[derive(Default, Debug, Clone)] 90 pub struct Opts { 91 /// Whether or not `rustfmt` is executed to format generated code. 92 pub rustfmt: bool, 93 94 /// Whether or not to emit `tracing` macro calls on function entry/exit. 95 pub tracing: bool, 96 97 /// Whether or not to use async rust functions and traits. 98 pub async_: AsyncConfig, 99 100 /// A list of "trappable errors" which are used to replace the `E` in 101 /// `result<T, E>` found in WIT. 102 pub trappable_error_type: Vec<TrappableError>, 103 104 /// Whether to generate owning or borrowing type definitions. 105 pub ownership: Ownership, 106 107 /// Whether or not to generate code for only the interfaces of this wit file or not. 108 pub only_interfaces: bool, 109 110 /// Configuration of which imports are allowed to generate a trap. 111 pub trappable_imports: TrappableImports, 112 113 /// Remapping of interface names to rust module names. 114 /// TODO: is there a better type to use for the value of this map? 115 pub with: HashMap<String, String>, 116 117 /// Additional derive attributes to add to generated types. If using in a CLI, this flag can be 118 /// specified multiple times to add multiple attributes. 119 /// 120 /// These derive attributes will be added to any generated structs or enums 121 pub additional_derive_attributes: Vec<String>, 122 } 123 124 #[derive(Debug, Clone)] 125 pub struct TrappableError { 126 /// Full path to the error, such as `wasi:io/streams/error`. 127 pub wit_path: String, 128 129 /// The name, in Rust, of the error type to generate. 130 pub rust_type_name: String, 131 } 132 133 #[derive(Default, Debug, Clone)] 134 pub enum AsyncConfig { 135 /// No functions are `async`. 136 #[default] 137 None, 138 /// All generated functions should be `async`. 139 All, 140 /// These imported functions should not be async, but everything else is. 141 AllExceptImports(HashSet<String>), 142 /// These functions are the only imports that are async, all other imports 143 /// are sync. 144 /// 145 /// Note that all exports are still async in this situation. 146 OnlyImports(HashSet<String>), 147 } 148 149 impl AsyncConfig { 150 pub fn is_import_async(&self, f: &str) -> bool { 151 match self { 152 AsyncConfig::None => false, 153 AsyncConfig::All => true, 154 AsyncConfig::AllExceptImports(set) => !set.contains(f), 155 AsyncConfig::OnlyImports(set) => set.contains(f), 156 } 157 } 158 159 pub fn maybe_async(&self) -> bool { 160 match self { 161 AsyncConfig::None => false, 162 AsyncConfig::All | AsyncConfig::AllExceptImports(_) | AsyncConfig::OnlyImports(_) => { 163 true 164 } 165 } 166 } 167 } 168 169 #[derive(Default, Debug, Clone)] 170 pub enum TrappableImports { 171 /// No imports are allowed to trap. 172 #[default] 173 None, 174 /// All imports may trap. 175 All, 176 /// Only the specified set of functions may trap. 177 Only(HashSet<String>), 178 } 179 180 impl TrappableImports { 181 fn can_trap(&self, f: &Function) -> bool { 182 match self { 183 TrappableImports::None => false, 184 TrappableImports::All => true, 185 TrappableImports::Only(set) => set.contains(&f.name), 186 } 187 } 188 } 189 190 impl Opts { 191 pub fn generate(&self, resolve: &Resolve, world: WorldId) -> anyhow::Result<String> { 192 let mut r = Wasmtime::default(); 193 r.sizes.fill(resolve); 194 r.opts = self.clone(); 195 r.generate(resolve, world) 196 } 197 } 198 199 impl Wasmtime { 200 fn name_interface( 201 &mut self, 202 resolve: &Resolve, 203 id: InterfaceId, 204 name: &WorldKey, 205 is_export: bool, 206 ) -> bool { 207 let mut path = Vec::new(); 208 if is_export { 209 path.push("exports".to_string()); 210 } 211 match name { 212 WorldKey::Name(name) => { 213 path.push(name.to_snake_case()); 214 } 215 WorldKey::Interface(_) => { 216 let iface = &resolve.interfaces[id]; 217 let pkgname = &resolve.packages[iface.package.unwrap()].name; 218 path.push(pkgname.namespace.to_snake_case()); 219 path.push(self.name_package_module(resolve, iface.package.unwrap())); 220 path.push(to_rust_ident(iface.name.as_ref().unwrap())); 221 } 222 } 223 let entry = if let Some(name_at_root) = self.lookup_replacement(resolve, name, None) { 224 InterfaceName::Remapped { 225 name_at_root, 226 local_path: path, 227 } 228 } else { 229 InterfaceName::Path(path) 230 }; 231 232 let remapped = matches!(entry, InterfaceName::Remapped { .. }); 233 self.interface_names.insert(id, entry); 234 remapped 235 } 236 237 /// If the package `id` is the only package with its namespace/name combo 238 /// then pass through the name unmodified. If, however, there are multiple 239 /// versions of this package then the package module is going to get version 240 /// information. 241 fn name_package_module(&self, resolve: &Resolve, id: PackageId) -> String { 242 let pkg = &resolve.packages[id]; 243 let versions_with_same_name = resolve 244 .packages 245 .iter() 246 .filter_map(|(_, p)| { 247 if p.name.namespace == pkg.name.namespace && p.name.name == pkg.name.name { 248 Some(&p.name.version) 249 } else { 250 None 251 } 252 }) 253 .collect::<Vec<_>>(); 254 let base = pkg.name.name.to_snake_case(); 255 if versions_with_same_name.len() == 1 { 256 return base; 257 } 258 259 let version = match &pkg.name.version { 260 Some(version) => version, 261 // If this package didn't have a version then don't mangle its name 262 // and other packages with the same name but with versions present 263 // will have their names mangled. 264 None => return base, 265 }; 266 267 // Here there's multiple packages with the same name that differ only in 268 // version, so the version needs to be mangled into the Rust module name 269 // that we're generating. This in theory could look at all of 270 // `versions_with_same_name` and produce a minimal diff, e.g. for 0.1.0 271 // and 0.2.0 this could generate "foo1" and "foo2", but for now 272 // a simpler path is chosen to generate "foo0_1_0" and "foo0_2_0". 273 let version = version 274 .to_string() 275 .replace('.', "_") 276 .replace('-', "_") 277 .replace('+', "_") 278 .to_snake_case(); 279 format!("{base}{version}") 280 } 281 282 fn generate(&mut self, resolve: &Resolve, id: WorldId) -> anyhow::Result<String> { 283 self.types.analyze(resolve, id); 284 for (i, te) in self.opts.trappable_error_type.iter().enumerate() { 285 let id = resolve_type_in_package(resolve, &te.wit_path) 286 .context(format!("resolving {:?}", te)) 287 .unwrap(); 288 let name = format!("_TrappableError{i}"); 289 uwriteln!(self.src, "type {name} = {};", te.rust_type_name); 290 let prev = self.trappable_errors.insert(id, name); 291 assert!(prev.is_none()); 292 } 293 294 // Convert all entries in `with` as relative to the root of where the 295 // macro itself is invoked. This emits a `pub use` to bring the name 296 // into scope under an "anonymous name" which then replaces the `with` 297 // map entry. 298 let mut with = self.opts.with.iter_mut().collect::<Vec<_>>(); 299 with.sort(); 300 for (i, (_k, v)) in with.into_iter().enumerate() { 301 let name = format!("__with_name{i}"); 302 uwriteln!(self.src, "#[doc(hidden)]\npub use {v} as {name};"); 303 *v = name; 304 } 305 306 let world = &resolve.worlds[id]; 307 for (name, import) in world.imports.iter() { 308 if !self.opts.only_interfaces || matches!(import, WorldItem::Interface(_)) { 309 self.import(resolve, id, name, import); 310 } 311 } 312 313 for (name, export) in world.exports.iter() { 314 if !self.opts.only_interfaces || matches!(export, WorldItem::Interface(_)) { 315 self.export(resolve, name, export); 316 } 317 } 318 self.finish(resolve, id) 319 } 320 321 fn import(&mut self, resolve: &Resolve, world: WorldId, name: &WorldKey, item: &WorldItem) { 322 let mut gen = InterfaceGenerator::new(self, resolve); 323 match item { 324 WorldItem::Function(func) => { 325 // Only generate a trait signature for free functions since 326 // resource-related functions get their trait signatures 327 // during `type_resource`. 328 if let FunctionKind::Freestanding = func.kind { 329 gen.generate_function_trait_sig(func); 330 } 331 let sig = mem::take(&mut gen.src).into(); 332 gen.generate_add_function_to_linker(TypeOwner::World(world), func, "linker"); 333 let add_to_linker = gen.src.into(); 334 self.import_functions 335 .push(ImportFunction { sig, add_to_linker }); 336 } 337 WorldItem::Interface(id) => { 338 gen.gen.interface_last_seen_as_import.insert(*id, true); 339 if gen.gen.name_interface(resolve, *id, name, false) { 340 return; 341 } 342 gen.current_interface = Some((*id, name, false)); 343 gen.types(*id); 344 let key_name = resolve.name_world_key(name); 345 346 gen.generate_add_to_linker(*id, &key_name); 347 348 let module = &gen.src[..]; 349 350 let snake = match name { 351 WorldKey::Name(s) => s.to_snake_case(), 352 WorldKey::Interface(id) => resolve.interfaces[*id] 353 .name 354 .as_ref() 355 .unwrap() 356 .to_snake_case(), 357 }; 358 let module = format!( 359 " 360 #[allow(clippy::all)] 361 pub mod {snake} {{ 362 #[allow(unused_imports)] 363 use wasmtime::component::__internal::anyhow; 364 365 {module} 366 }} 367 " 368 ); 369 self.import_interfaces 370 .push((module, self.interface_names[id].clone())); 371 } 372 WorldItem::Type(ty) => { 373 let name = match name { 374 WorldKey::Name(name) => name, 375 WorldKey::Interface(_) => unreachable!(), 376 }; 377 gen.define_type(name, *ty); 378 let body = mem::take(&mut gen.src); 379 self.src.push_str(&body); 380 } 381 }; 382 } 383 384 fn export(&mut self, resolve: &Resolve, name: &WorldKey, item: &WorldItem) { 385 let mut gen = InterfaceGenerator::new(self, resolve); 386 let (field, ty, getter) = match item { 387 WorldItem::Function(func) => { 388 gen.define_rust_guest_export(resolve, None, func); 389 let body = mem::take(&mut gen.src).into(); 390 let (_name, getter) = gen.extract_typed_function(func); 391 assert!(gen.src.is_empty()); 392 self.exports.funcs.push(body); 393 ( 394 func_field_name(resolve, func), 395 "wasmtime::component::Func".to_string(), 396 getter, 397 ) 398 } 399 WorldItem::Type(_) => unreachable!(), 400 WorldItem::Interface(id) => { 401 gen.gen.interface_last_seen_as_import.insert(*id, false); 402 gen.gen.name_interface(resolve, *id, name, true); 403 gen.current_interface = Some((*id, name, true)); 404 gen.types(*id); 405 let struct_name = "Guest"; 406 let iface = &resolve.interfaces[*id]; 407 let iface_name = match name { 408 WorldKey::Name(name) => name, 409 WorldKey::Interface(_) => iface.name.as_ref().unwrap(), 410 }; 411 uwriteln!(gen.src, "pub struct {struct_name} {{"); 412 for (_, func) in iface.functions.iter() { 413 uwriteln!( 414 gen.src, 415 "{}: wasmtime::component::Func,", 416 func_field_name(resolve, func) 417 ); 418 } 419 uwriteln!(gen.src, "}}"); 420 421 uwriteln!(gen.src, "impl {struct_name} {{"); 422 uwrite!( 423 gen.src, 424 " 425 pub fn new( 426 __exports: &mut wasmtime::component::ExportInstance<'_, '_>, 427 ) -> wasmtime::Result<{struct_name}> {{ 428 " 429 ); 430 let mut fields = Vec::new(); 431 for (_, func) in iface.functions.iter() { 432 let (name, getter) = gen.extract_typed_function(func); 433 uwriteln!(gen.src, "let {name} = {getter};"); 434 fields.push(name); 435 } 436 uwriteln!(gen.src, "Ok({struct_name} {{"); 437 for name in fields { 438 uwriteln!(gen.src, "{name},"); 439 } 440 uwriteln!(gen.src, "}})"); 441 uwriteln!(gen.src, "}}"); 442 443 let mut resource_methods = IndexMap::new(); 444 445 for (_, func) in iface.functions.iter() { 446 match func.kind { 447 FunctionKind::Freestanding => { 448 gen.define_rust_guest_export(resolve, Some(name), func); 449 } 450 FunctionKind::Method(id) 451 | FunctionKind::Constructor(id) 452 | FunctionKind::Static(id) => { 453 resource_methods.entry(id).or_insert(Vec::new()).push(func); 454 } 455 } 456 } 457 458 for (id, _) in resource_methods.iter() { 459 let name = resolve.types[*id].name.as_ref().unwrap(); 460 let snake = name.to_snake_case(); 461 let camel = name.to_upper_camel_case(); 462 uwriteln!( 463 gen.src, 464 "pub fn {snake}(&self) -> Guest{camel}<'_> {{ 465 Guest{camel} {{ funcs: self }} 466 }}" 467 ); 468 } 469 470 uwriteln!(gen.src, "}}"); 471 472 for (id, methods) in resource_methods { 473 let resource_name = resolve.types[id].name.as_ref().unwrap(); 474 let camel = resource_name.to_upper_camel_case(); 475 uwriteln!(gen.src, "impl Guest{camel}<'_> {{"); 476 for method in methods { 477 gen.define_rust_guest_export(resolve, Some(name), method); 478 } 479 uwriteln!(gen.src, "}}"); 480 } 481 482 let module = &gen.src[..]; 483 let snake = to_rust_ident(iface_name); 484 485 let module = format!( 486 " 487 #[allow(clippy::all)] 488 pub mod {snake} {{ 489 #[allow(unused_imports)] 490 use wasmtime::component::__internal::anyhow; 491 492 {module} 493 }} 494 " 495 ); 496 let pkgname = match name { 497 WorldKey::Name(_) => None, 498 WorldKey::Interface(_) => { 499 Some(resolve.packages[iface.package.unwrap()].name.clone()) 500 } 501 }; 502 self.exports 503 .modules 504 .push((module, self.interface_names[id].clone())); 505 506 let name = resolve.name_world_key(name); 507 let (path, method_name) = match pkgname { 508 Some(pkgname) => ( 509 format!( 510 "exports::{}::{}::{snake}::{struct_name}", 511 pkgname.namespace.to_snake_case(), 512 self.name_package_module(resolve, iface.package.unwrap()), 513 ), 514 format!( 515 "{}_{}_{snake}", 516 pkgname.namespace.to_snake_case(), 517 self.name_package_module(resolve, iface.package.unwrap()) 518 ), 519 ), 520 None => (format!("exports::{snake}::{struct_name}"), snake.clone()), 521 }; 522 let getter = format!( 523 "\ 524 {path}::new( 525 &mut __exports.instance(\"{name}\") 526 .ok_or_else(|| anyhow::anyhow!(\"exported instance `{name}` not present\"))? 527 )?\ 528 " 529 ); 530 let field = format!("interface{}", self.exports.fields.len()); 531 self.exports.funcs.push(format!( 532 " 533 pub fn {method_name}(&self) -> &{path} {{ 534 &self.{field} 535 }} 536 ", 537 )); 538 (field, path, getter) 539 } 540 }; 541 let prev = self.exports.fields.insert(field, (ty, getter)); 542 assert!(prev.is_none()); 543 } 544 545 fn build_struct(&mut self, resolve: &Resolve, world: WorldId) { 546 let camel = to_rust_upper_camel_case(&resolve.worlds[world].name); 547 uwriteln!(self.src, "pub struct {camel} {{"); 548 for (name, (ty, _)) in self.exports.fields.iter() { 549 uwriteln!(self.src, "{name}: {ty},"); 550 } 551 self.src.push_str("}\n"); 552 553 let (async_, async__, send, await_) = if self.opts.async_.maybe_async() { 554 ("async", "_async", ":Send", ".await") 555 } else { 556 ("", "", "", "") 557 }; 558 559 self.toplevel_import_trait(resolve, world); 560 561 uwriteln!(self.src, "const _: () = {{"); 562 uwriteln!( 563 self.src, 564 " 565 #[allow(unused_imports)] 566 use wasmtime::component::__internal::anyhow; 567 " 568 ); 569 570 uwriteln!(self.src, "impl {camel} {{"); 571 self.toplevel_add_to_linker(resolve, world); 572 uwriteln!( 573 self.src, 574 " 575 /// Instantiates the provided `module` using the specified 576 /// parameters, wrapping up the result in a structure that 577 /// translates between wasm and the host. 578 pub {async_} fn instantiate{async__}<T {send}>( 579 mut store: impl wasmtime::AsContextMut<Data = T>, 580 component: &wasmtime::component::Component, 581 linker: &wasmtime::component::Linker<T>, 582 ) -> wasmtime::Result<(Self, wasmtime::component::Instance)> {{ 583 let instance = linker.instantiate{async__}(&mut store, component){await_}?; 584 Ok((Self::new(store, &instance)?, instance)) 585 }} 586 587 /// Instantiates a pre-instantiated module using the specified 588 /// parameters, wrapping up the result in a structure that 589 /// translates between wasm and the host. 590 pub {async_} fn instantiate_pre<T {send}>( 591 mut store: impl wasmtime::AsContextMut<Data = T>, 592 instance_pre: &wasmtime::component::InstancePre<T>, 593 ) -> wasmtime::Result<(Self, wasmtime::component::Instance)> {{ 594 let instance = instance_pre.instantiate{async__}(&mut store){await_}?; 595 Ok((Self::new(store, &instance)?, instance)) 596 }} 597 598 /// Low-level creation wrapper for wrapping up the exports 599 /// of the `instance` provided in this structure of wasm 600 /// exports. 601 /// 602 /// This function will extract exports from the `instance` 603 /// defined within `store` and wrap them all up in the 604 /// returned structure which can be used to interact with 605 /// the wasm module. 606 pub fn new( 607 mut store: impl wasmtime::AsContextMut, 608 instance: &wasmtime::component::Instance, 609 ) -> wasmtime::Result<Self> {{ 610 let mut store = store.as_context_mut(); 611 let mut exports = instance.exports(&mut store); 612 let mut __exports = exports.root(); 613 ", 614 ); 615 for (name, (_, get)) in self.exports.fields.iter() { 616 uwriteln!(self.src, "let {name} = {get};"); 617 } 618 uwriteln!(self.src, "Ok({camel} {{"); 619 for (name, _) in self.exports.fields.iter() { 620 uwriteln!(self.src, "{name},"); 621 } 622 uwriteln!(self.src, "}})"); 623 uwriteln!(self.src, "}}"); // close `fn new` 624 625 for func in self.exports.funcs.iter() { 626 self.src.push_str(func); 627 } 628 629 uwriteln!(self.src, "}}"); // close `impl {camel}` 630 631 uwriteln!(self.src, "}};"); // close `const _: () = ... 632 } 633 634 fn finish(&mut self, resolve: &Resolve, world: WorldId) -> anyhow::Result<String> { 635 let remapping_keys = self.opts.with.keys().cloned().collect::<HashSet<String>>(); 636 637 let mut unused_keys = remapping_keys 638 .difference(&self.used_with_opts) 639 .map(|s| s.as_str()) 640 .collect::<Vec<&str>>(); 641 642 unused_keys.sort(); 643 644 if !unused_keys.is_empty() { 645 anyhow::bail!("interfaces were specified in the `with` config option but are not referenced in the target world: {unused_keys:?}"); 646 } 647 648 if !self.opts.only_interfaces { 649 self.build_struct(resolve, world) 650 } 651 652 let imports = mem::take(&mut self.import_interfaces); 653 self.emit_modules(imports); 654 655 let exports = mem::take(&mut self.exports.modules); 656 self.emit_modules(exports); 657 658 let mut src = mem::take(&mut self.src); 659 if self.opts.rustfmt { 660 let mut child = Command::new("rustfmt") 661 .arg("--edition=2018") 662 .stdin(Stdio::piped()) 663 .stdout(Stdio::piped()) 664 .spawn() 665 .expect("failed to spawn `rustfmt`"); 666 child 667 .stdin 668 .take() 669 .unwrap() 670 .write_all(src.as_bytes()) 671 .unwrap(); 672 src.as_mut_string().truncate(0); 673 child 674 .stdout 675 .take() 676 .unwrap() 677 .read_to_string(src.as_mut_string()) 678 .unwrap(); 679 let status = child.wait().unwrap(); 680 assert!(status.success()); 681 } 682 683 Ok(src.into()) 684 } 685 686 fn emit_modules(&mut self, modules: Vec<(String, InterfaceName)>) { 687 #[derive(Default)] 688 struct Module { 689 submodules: BTreeMap<String, Module>, 690 contents: Vec<String>, 691 } 692 let mut map = Module::default(); 693 for (module, name) in modules { 694 let path = match name { 695 InterfaceName::Remapped { local_path, .. } => local_path, 696 InterfaceName::Path(path) => path, 697 }; 698 let mut cur = &mut map; 699 for name in path[..path.len() - 1].iter() { 700 cur = cur 701 .submodules 702 .entry(name.clone()) 703 .or_insert(Module::default()); 704 } 705 cur.contents.push(module); 706 } 707 708 emit(&mut self.src, map); 709 710 fn emit(me: &mut Source, module: Module) { 711 for (name, submodule) in module.submodules { 712 uwriteln!(me, "pub mod {name} {{"); 713 emit(me, submodule); 714 uwriteln!(me, "}}"); 715 } 716 for submodule in module.contents { 717 uwriteln!(me, "{submodule}"); 718 } 719 } 720 } 721 722 /// Attempts to find the `key`, possibly with the resource projection 723 /// `item`, within the `with` map provided to bindings configuration. 724 fn lookup_replacement( 725 &mut self, 726 resolve: &Resolve, 727 key: &WorldKey, 728 item: Option<&str>, 729 ) -> Option<String> { 730 struct Name<'a> { 731 prefix: Prefix, 732 item: Option<&'a str>, 733 } 734 735 #[derive(Copy, Clone)] 736 enum Prefix { 737 Namespace(PackageId), 738 UnversionedPackage(PackageId), 739 VersionedPackage(PackageId), 740 UnversionedInterface(InterfaceId), 741 VersionedInterface(InterfaceId), 742 } 743 744 let prefix = match key { 745 WorldKey::Interface(id) => Prefix::VersionedInterface(*id), 746 747 // Non-interface-keyed names don't get the lookup logic below, 748 // they're relatively uncommon so only lookup the precise key here. 749 WorldKey::Name(key) => { 750 let to_lookup = match item { 751 Some(item) => format!("{key}/{item}"), 752 None => key.to_string(), 753 }; 754 let result = self.opts.with.get(&to_lookup).cloned(); 755 if result.is_some() { 756 self.used_with_opts.insert(to_lookup.clone()); 757 } 758 return result; 759 } 760 }; 761 762 // Here names are iteratively attempted as `key` + `item` is "walked to 763 // its root" and each attempt is consulted in `self.opts.with`. This 764 // loop will start at the leaf, the most specific path, and then walk to 765 // the root, popping items, trying to find a result. 766 // 767 // Each time a name is "popped" the projection from the next path is 768 // pushed onto `projection`. This means that if we actually find a match 769 // then `projection` is a collection of namespaces that results in the 770 // final replacement name. 771 let mut name = Name { prefix, item }; 772 let mut projection = Vec::new(); 773 loop { 774 let lookup = name.lookup_key(resolve); 775 if let Some(renamed) = self.opts.with.get(&lookup) { 776 projection.push(renamed.clone()); 777 projection.reverse(); 778 self.used_with_opts.insert(lookup); 779 return Some(projection.join("::")); 780 } 781 if !name.pop(resolve, &mut projection) { 782 return None; 783 } 784 } 785 786 impl<'a> Name<'a> { 787 fn lookup_key(&self, resolve: &Resolve) -> String { 788 let mut s = self.prefix.lookup_key(resolve); 789 if let Some(item) = self.item { 790 s.push_str("/"); 791 s.push_str(item); 792 } 793 s 794 } 795 796 fn pop(&mut self, resolve: &'a Resolve, projection: &mut Vec<String>) -> bool { 797 match (self.item, self.prefix) { 798 // If this is a versioned resource name, try the unversioned 799 // resource name next. 800 (Some(_), Prefix::VersionedInterface(id)) => { 801 self.prefix = Prefix::UnversionedInterface(id); 802 true 803 } 804 // If this is an unversioned resource name then time to 805 // ignore the resource itself and move on to the next most 806 // specific item, versioned interface names. 807 (Some(item), Prefix::UnversionedInterface(id)) => { 808 self.prefix = Prefix::VersionedInterface(id); 809 self.item = None; 810 projection.push(item.to_upper_camel_case()); 811 true 812 } 813 (Some(_), _) => unreachable!(), 814 (None, _) => self.prefix.pop(resolve, projection), 815 } 816 } 817 } 818 819 impl Prefix { 820 fn lookup_key(&self, resolve: &Resolve) -> String { 821 match *self { 822 Prefix::Namespace(id) => resolve.packages[id].name.namespace.clone(), 823 Prefix::UnversionedPackage(id) => { 824 let mut name = resolve.packages[id].name.clone(); 825 name.version = None; 826 name.to_string() 827 } 828 Prefix::VersionedPackage(id) => resolve.packages[id].name.to_string(), 829 Prefix::UnversionedInterface(id) => { 830 let id = resolve.id_of(id).unwrap(); 831 match id.find('@') { 832 Some(i) => id[..i].to_string(), 833 None => id, 834 } 835 } 836 Prefix::VersionedInterface(id) => resolve.id_of(id).unwrap(), 837 } 838 } 839 840 fn pop(&mut self, resolve: &Resolve, projection: &mut Vec<String>) -> bool { 841 *self = match *self { 842 // try the unversioned interface next 843 Prefix::VersionedInterface(id) => Prefix::UnversionedInterface(id), 844 // try this interface's versioned package next 845 Prefix::UnversionedInterface(id) => { 846 let iface = &resolve.interfaces[id]; 847 let name = iface.name.as_ref().unwrap(); 848 projection.push(to_rust_ident(name)); 849 Prefix::VersionedPackage(iface.package.unwrap()) 850 } 851 // try the unversioned package next 852 Prefix::VersionedPackage(id) => Prefix::UnversionedPackage(id), 853 // try this package's namespace next 854 Prefix::UnversionedPackage(id) => { 855 let name = &resolve.packages[id].name; 856 projection.push(to_rust_ident(&name.name)); 857 Prefix::Namespace(id) 858 } 859 // nothing left to try any more 860 Prefix::Namespace(_) => return false, 861 }; 862 true 863 } 864 } 865 } 866 } 867 868 impl Wasmtime { 869 fn has_world_trait(&self, resolve: &Resolve, world: WorldId) -> bool { 870 !self.import_functions.is_empty() || get_world_resources(resolve, world).count() > 0 871 } 872 873 fn toplevel_import_trait(&mut self, resolve: &Resolve, world: WorldId) { 874 if !self.has_world_trait(resolve, world) { 875 return; 876 } 877 878 let world_camel = to_rust_upper_camel_case(&resolve.worlds[world].name); 879 if self.opts.async_.maybe_async() { 880 uwriteln!(self.src, "#[wasmtime::component::__internal::async_trait]") 881 } 882 uwrite!(self.src, "pub trait {world_camel}Imports"); 883 for (i, resource) in get_world_resources(resolve, world).enumerate() { 884 if i == 0 { 885 uwrite!(self.src, ": "); 886 } else { 887 uwrite!(self.src, " + "); 888 } 889 uwrite!(self.src, "Host{}", resource.to_upper_camel_case()); 890 } 891 uwriteln!(self.src, " {{"); 892 for f in self.import_functions.iter() { 893 self.src.push_str(&f.sig); 894 self.src.push_str("\n"); 895 } 896 uwriteln!(self.src, "}}"); 897 } 898 899 fn toplevel_add_to_linker(&mut self, resolve: &Resolve, world: WorldId) { 900 let has_world_trait = self.has_world_trait(resolve, world); 901 if self.import_interfaces.is_empty() && !has_world_trait { 902 return; 903 } 904 let mut interfaces = Vec::new(); 905 for (_, name) in self.import_interfaces.iter() { 906 let path = match name { 907 InterfaceName::Remapped { .. } => unreachable!("imported a remapped module"), 908 InterfaceName::Path(path) => path, 909 }; 910 interfaces.push(path.join("::")); 911 } 912 913 uwrite!( 914 self.src, 915 " 916 pub fn add_to_linker<T, U>( 917 linker: &mut wasmtime::component::Linker<T>, 918 get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, 919 ) -> wasmtime::Result<()> 920 where U: \ 921 " 922 ); 923 let world_camel = to_rust_upper_camel_case(&resolve.worlds[world].name); 924 let world_trait = format!("{world_camel}Imports"); 925 for (i, name) in interfaces 926 .iter() 927 .map(|n| format!("{n}::Host")) 928 .chain(if has_world_trait { 929 Some(world_trait.clone()) 930 } else { 931 None 932 }) 933 .enumerate() 934 { 935 if i > 0 { 936 self.src.push_str(" + "); 937 } 938 self.src.push_str(&name); 939 } 940 941 let maybe_send = if self.opts.async_.maybe_async() { 942 " + Send, T: Send" 943 } else { 944 "" 945 }; 946 947 self.src.push_str(maybe_send); 948 self.src.push_str(",\n{\n"); 949 for name in interfaces.iter() { 950 uwriteln!(self.src, "{name}::add_to_linker(linker, get)?;"); 951 } 952 if has_world_trait { 953 uwriteln!(self.src, "Self::add_root_to_linker(linker, get)?;"); 954 } 955 uwriteln!(self.src, "Ok(())\n}}"); 956 if !has_world_trait { 957 return; 958 } 959 960 uwrite!( 961 self.src, 962 " 963 pub fn add_root_to_linker<T, U>( 964 linker: &mut wasmtime::component::Linker<T>, 965 get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, 966 ) -> wasmtime::Result<()> 967 where U: {world_trait}{maybe_send} 968 {{ 969 let mut linker = linker.root(); 970 ", 971 ); 972 for name in get_world_resources(resolve, world) { 973 let camel = name.to_upper_camel_case(); 974 uwriteln!( 975 self.src, 976 "linker.resource( 977 \"{name}\", 978 wasmtime::component::ResourceType::host::<{camel}>(), 979 move |mut store, rep| -> wasmtime::Result<()> {{ 980 Host{camel}::drop(get(store.data_mut()), wasmtime::component::Resource::new_own(rep)) 981 }}, 982 )?;" 983 ) 984 } 985 986 for f in self.import_functions.iter() { 987 self.src.push_str(&f.add_to_linker); 988 self.src.push_str("\n"); 989 } 990 uwriteln!(self.src, "Ok(())\n}}"); 991 } 992 } 993 994 fn resolve_type_in_package(resolve: &Resolve, wit_path: &str) -> anyhow::Result<TypeId> { 995 // Build a map, `packages_to_omit_version`, where that package can be 996 // uniquely identified by its name/namespace combo and as such version 997 // information is not required. 998 let mut packages_with_same_name = HashMap::new(); 999 for (id, pkg) in resolve.packages.iter() { 1000 packages_with_same_name 1001 .entry(PackageName { 1002 version: None, 1003 ..pkg.name.clone() 1004 }) 1005 .or_insert(Vec::new()) 1006 .push(id) 1007 } 1008 let packages_to_omit_version = packages_with_same_name 1009 .iter() 1010 .filter_map( 1011 |(_name, list)| { 1012 if list.len() == 1 { 1013 Some(list) 1014 } else { 1015 None 1016 } 1017 }, 1018 ) 1019 .flat_map(|l| l) 1020 .collect::<HashSet<_>>(); 1021 1022 let mut found_interface = false; 1023 1024 // Look for an interface whose assigned prefix starts `wit_path`. Not 1025 // exactly the most efficient thing ever but is sufficient for now. 1026 for (id, interface) in resolve.interfaces.iter() { 1027 found_interface = true; 1028 1029 let iface_name = match &interface.name { 1030 Some(name) => name, 1031 None => continue, 1032 }; 1033 let pkgid = interface.package.unwrap(); 1034 let pkgname = &resolve.packages[pkgid].name; 1035 let prefix = if packages_to_omit_version.contains(&pkgid) { 1036 let mut name = pkgname.clone(); 1037 name.version = None; 1038 format!("{name}/{iface_name}") 1039 } else { 1040 resolve.id_of(id).unwrap() 1041 }; 1042 let wit_path = match wit_path.strip_prefix(&prefix) { 1043 Some(rest) => rest, 1044 None => continue, 1045 }; 1046 1047 let wit_path = match wit_path.strip_prefix('/') { 1048 Some(rest) => rest, 1049 None => continue, 1050 }; 1051 1052 match interface.types.get(wit_path).copied() { 1053 Some(type_id) => return Ok(type_id), 1054 None => continue, 1055 } 1056 } 1057 1058 if found_interface { 1059 bail!("no types found to match `{wit_path}` in interface"); 1060 } 1061 1062 bail!("no package/interface found to match `{wit_path}`") 1063 } 1064 1065 struct InterfaceGenerator<'a> { 1066 src: Source, 1067 gen: &'a mut Wasmtime, 1068 resolve: &'a Resolve, 1069 current_interface: Option<(InterfaceId, &'a WorldKey, bool)>, 1070 } 1071 1072 impl<'a> InterfaceGenerator<'a> { 1073 fn new(gen: &'a mut Wasmtime, resolve: &'a Resolve) -> InterfaceGenerator<'a> { 1074 InterfaceGenerator { 1075 src: Source::default(), 1076 gen, 1077 resolve, 1078 current_interface: None, 1079 } 1080 } 1081 1082 fn types_imported(&self) -> bool { 1083 match self.current_interface { 1084 Some((_, _, is_export)) => !is_export, 1085 None => true, 1086 } 1087 } 1088 1089 fn types(&mut self, id: InterfaceId) { 1090 for (name, id) in self.resolve.interfaces[id].types.iter() { 1091 self.define_type(name, *id); 1092 } 1093 } 1094 1095 fn define_type(&mut self, name: &str, id: TypeId) { 1096 let ty = &self.resolve.types[id]; 1097 match &ty.kind { 1098 TypeDefKind::Record(record) => self.type_record(id, name, record, &ty.docs), 1099 TypeDefKind::Flags(flags) => self.type_flags(id, name, flags, &ty.docs), 1100 TypeDefKind::Tuple(tuple) => self.type_tuple(id, name, tuple, &ty.docs), 1101 TypeDefKind::Enum(enum_) => self.type_enum(id, name, enum_, &ty.docs), 1102 TypeDefKind::Variant(variant) => self.type_variant(id, name, variant, &ty.docs), 1103 TypeDefKind::Option(t) => self.type_option(id, name, t, &ty.docs), 1104 TypeDefKind::Result(r) => self.type_result(id, name, r, &ty.docs), 1105 TypeDefKind::List(t) => self.type_list(id, name, t, &ty.docs), 1106 TypeDefKind::Type(t) => self.type_alias(id, name, t, &ty.docs), 1107 TypeDefKind::Future(_) => todo!("generate for future"), 1108 TypeDefKind::Stream(_) => todo!("generate for stream"), 1109 TypeDefKind::Handle(handle) => self.type_handle(id, name, handle, &ty.docs), 1110 TypeDefKind::Resource => self.type_resource(id, name, ty, &ty.docs), 1111 TypeDefKind::Unknown => unreachable!(), 1112 } 1113 } 1114 1115 fn type_handle(&mut self, id: TypeId, name: &str, handle: &Handle, docs: &Docs) { 1116 self.rustdoc(docs); 1117 let name = name.to_upper_camel_case(); 1118 uwriteln!(self.src, "pub type {name} = "); 1119 self.print_handle(handle); 1120 self.push_str(";\n"); 1121 self.assert_type(id, &name); 1122 } 1123 1124 fn type_resource(&mut self, id: TypeId, name: &str, resource: &TypeDef, docs: &Docs) { 1125 let camel = name.to_upper_camel_case(); 1126 1127 if self.types_imported() { 1128 self.rustdoc(docs); 1129 1130 let replacement = match self.current_interface { 1131 Some((_, key, _)) => self.gen.lookup_replacement(self.resolve, key, Some(name)), 1132 None => { 1133 self.gen.used_with_opts.insert(name.into()); 1134 self.gen.opts.with.get(name).cloned() 1135 } 1136 }; 1137 match replacement { 1138 Some(path) => { 1139 uwriteln!( 1140 self.src, 1141 "pub use {}{path} as {camel};", 1142 self.path_to_root() 1143 ); 1144 } 1145 None => { 1146 uwriteln!(self.src, "pub enum {camel} {{}}"); 1147 } 1148 } 1149 1150 if self.gen.opts.async_.maybe_async() { 1151 uwriteln!(self.src, "#[wasmtime::component::__internal::async_trait]") 1152 } 1153 1154 uwriteln!(self.src, "pub trait Host{camel} {{"); 1155 1156 let functions = match resource.owner { 1157 TypeOwner::World(id) => self.resolve.worlds[id] 1158 .imports 1159 .values() 1160 .filter_map(|item| match item { 1161 WorldItem::Function(f) => Some(f), 1162 _ => None, 1163 }) 1164 .collect(), 1165 TypeOwner::Interface(id) => self.resolve.interfaces[id] 1166 .functions 1167 .values() 1168 .collect::<Vec<_>>(), 1169 TypeOwner::None => { 1170 panic!("A resource must be owned by a world or interface"); 1171 } 1172 }; 1173 1174 for func in functions { 1175 match func.kind { 1176 FunctionKind::Method(resource) 1177 | FunctionKind::Static(resource) 1178 | FunctionKind::Constructor(resource) 1179 if id == resource => {} 1180 _ => continue, 1181 } 1182 1183 self.generate_function_trait_sig(func); 1184 } 1185 1186 uwrite!( 1187 self.src, 1188 "fn drop(&mut self, rep: wasmtime::component::Resource<{camel}>) -> wasmtime::Result<()>;"); 1189 1190 uwriteln!(self.src, "}}"); 1191 } else { 1192 self.rustdoc(docs); 1193 uwriteln!( 1194 self.src, 1195 " 1196 pub type {camel} = wasmtime::component::ResourceAny; 1197 1198 pub struct Guest{camel}<'a> {{ 1199 funcs: &'a Guest, 1200 }} 1201 " 1202 ); 1203 } 1204 } 1205 1206 fn type_record(&mut self, id: TypeId, _name: &str, record: &Record, docs: &Docs) { 1207 let info = self.info(id); 1208 1209 // We use a BTree set to make sure we don't have any duplicates and we have a stable order 1210 let additional_derives: BTreeSet<String> = self 1211 .gen 1212 .opts 1213 .additional_derive_attributes 1214 .iter() 1215 .cloned() 1216 .collect(); 1217 1218 for (name, mode) in self.modes_of(id) { 1219 let lt = self.lifetime_for(&info, mode); 1220 self.rustdoc(docs); 1221 1222 let mut derives = additional_derives.clone(); 1223 1224 self.push_str("#[derive(wasmtime::component::ComponentType)]\n"); 1225 if lt.is_none() { 1226 self.push_str("#[derive(wasmtime::component::Lift)]\n"); 1227 } 1228 self.push_str("#[derive(wasmtime::component::Lower)]\n"); 1229 self.push_str("#[component(record)]\n"); 1230 1231 if info.is_copy() { 1232 derives.extend(["Copy", "Clone"].into_iter().map(|s| s.to_string())); 1233 } else if info.is_clone() { 1234 derives.insert("Clone".to_string()); 1235 } 1236 1237 if !derives.is_empty() { 1238 self.push_str("#[derive("); 1239 self.push_str(&derives.into_iter().collect::<Vec<_>>().join(", ")); 1240 self.push_str(")]\n") 1241 } 1242 1243 self.push_str(&format!("pub struct {}", name)); 1244 self.print_generics(lt); 1245 self.push_str(" {\n"); 1246 for field in record.fields.iter() { 1247 self.rustdoc(&field.docs); 1248 self.push_str(&format!("#[component(name = \"{}\")]\n", field.name)); 1249 self.push_str("pub "); 1250 self.push_str(&to_rust_ident(&field.name)); 1251 self.push_str(": "); 1252 self.print_ty(&field.ty, mode); 1253 self.push_str(",\n"); 1254 } 1255 self.push_str("}\n"); 1256 1257 self.push_str("impl"); 1258 self.print_generics(lt); 1259 self.push_str(" core::fmt::Debug for "); 1260 self.push_str(&name); 1261 self.print_generics(lt); 1262 self.push_str(" {\n"); 1263 self.push_str( 1264 "fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n", 1265 ); 1266 self.push_str(&format!("f.debug_struct(\"{}\")", name)); 1267 for field in record.fields.iter() { 1268 self.push_str(&format!( 1269 ".field(\"{}\", &self.{})", 1270 field.name, 1271 to_rust_ident(&field.name) 1272 )); 1273 } 1274 self.push_str(".finish()\n"); 1275 self.push_str("}\n"); 1276 self.push_str("}\n"); 1277 1278 if info.error { 1279 self.push_str("impl"); 1280 self.print_generics(lt); 1281 self.push_str(" core::fmt::Display for "); 1282 self.push_str(&name); 1283 self.print_generics(lt); 1284 self.push_str(" {\n"); 1285 self.push_str( 1286 "fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n", 1287 ); 1288 self.push_str("write!(f, \"{:?}\", self)\n"); 1289 self.push_str("}\n"); 1290 self.push_str("}\n"); 1291 self.push_str("impl std::error::Error for "); 1292 self.push_str(&name); 1293 self.push_str("{}\n"); 1294 } 1295 self.assert_type(id, &name); 1296 } 1297 } 1298 1299 fn type_tuple(&mut self, id: TypeId, _name: &str, tuple: &Tuple, docs: &Docs) { 1300 let info = self.info(id); 1301 for (name, mode) in self.modes_of(id) { 1302 let lt = self.lifetime_for(&info, mode); 1303 self.rustdoc(docs); 1304 self.push_str(&format!("pub type {}", name)); 1305 self.print_generics(lt); 1306 self.push_str(" = ("); 1307 for ty in tuple.types.iter() { 1308 self.print_ty(ty, mode); 1309 self.push_str(","); 1310 } 1311 self.push_str(");\n"); 1312 self.assert_type(id, &name); 1313 } 1314 } 1315 1316 fn type_flags(&mut self, id: TypeId, name: &str, flags: &Flags, docs: &Docs) { 1317 self.rustdoc(docs); 1318 let rust_name = to_rust_upper_camel_case(name); 1319 self.src.push_str("wasmtime::component::flags!(\n"); 1320 self.src.push_str(&format!("{rust_name} {{\n")); 1321 for flag in flags.flags.iter() { 1322 // TODO wasmtime-component-macro doesnt support docs for flags rn 1323 uwrite!( 1324 self.src, 1325 "#[component(name=\"{}\")] const {};\n", 1326 flag.name, 1327 flag.name.to_shouty_snake_case() 1328 ); 1329 } 1330 self.src.push_str("}\n"); 1331 self.src.push_str(");\n\n"); 1332 self.assert_type(id, &rust_name); 1333 } 1334 1335 fn type_variant(&mut self, id: TypeId, _name: &str, variant: &Variant, docs: &Docs) { 1336 self.print_rust_enum( 1337 id, 1338 variant.cases.iter().map(|c| { 1339 ( 1340 c.name.to_upper_camel_case(), 1341 Some(c.name.clone()), 1342 &c.docs, 1343 c.ty.as_ref(), 1344 ) 1345 }), 1346 docs, 1347 "variant", 1348 ); 1349 } 1350 1351 fn type_option(&mut self, id: TypeId, _name: &str, payload: &Type, docs: &Docs) { 1352 let info = self.info(id); 1353 1354 for (name, mode) in self.modes_of(id) { 1355 self.rustdoc(docs); 1356 let lt = self.lifetime_for(&info, mode); 1357 self.push_str(&format!("pub type {}", name)); 1358 self.print_generics(lt); 1359 self.push_str("= Option<"); 1360 self.print_ty(payload, mode); 1361 self.push_str(">;\n"); 1362 self.assert_type(id, &name); 1363 } 1364 } 1365 1366 // Emit a double-check that the wit-parser-understood size of a type agrees 1367 // with the Wasmtime-understood size of a type. 1368 fn assert_type(&mut self, id: TypeId, name: &str) { 1369 self.push_str("const _: () = {\n"); 1370 uwriteln!( 1371 self.src, 1372 "assert!({} == <{name} as wasmtime::component::ComponentType>::SIZE32);", 1373 self.gen.sizes.size(&Type::Id(id)), 1374 ); 1375 uwriteln!( 1376 self.src, 1377 "assert!({} == <{name} as wasmtime::component::ComponentType>::ALIGN32);", 1378 self.gen.sizes.align(&Type::Id(id)), 1379 ); 1380 self.push_str("};\n"); 1381 } 1382 1383 fn print_rust_enum<'b>( 1384 &mut self, 1385 id: TypeId, 1386 cases: impl IntoIterator<Item = (String, Option<String>, &'b Docs, Option<&'b Type>)> + Clone, 1387 docs: &Docs, 1388 derive_component: &str, 1389 ) where 1390 Self: Sized, 1391 { 1392 let info = self.info(id); 1393 1394 // We use a BTree set to make sure we don't have any duplicates and we have a stable order 1395 let additional_derives: BTreeSet<String> = self 1396 .gen 1397 .opts 1398 .additional_derive_attributes 1399 .iter() 1400 .cloned() 1401 .collect(); 1402 1403 for (name, mode) in self.modes_of(id) { 1404 let name = to_rust_upper_camel_case(&name); 1405 1406 let mut derives = additional_derives.clone(); 1407 1408 self.rustdoc(docs); 1409 let lt = self.lifetime_for(&info, mode); 1410 self.push_str("#[derive(wasmtime::component::ComponentType)]\n"); 1411 if lt.is_none() { 1412 self.push_str("#[derive(wasmtime::component::Lift)]\n"); 1413 } 1414 self.push_str("#[derive(wasmtime::component::Lower)]\n"); 1415 self.push_str(&format!("#[component({})]\n", derive_component)); 1416 if info.is_copy() { 1417 derives.extend(["Copy", "Clone"].into_iter().map(|s| s.to_string())); 1418 } else if info.is_clone() { 1419 derives.insert("Clone".to_string()); 1420 } 1421 1422 if !derives.is_empty() { 1423 self.push_str("#[derive("); 1424 self.push_str(&derives.into_iter().collect::<Vec<_>>().join(", ")); 1425 self.push_str(")]\n") 1426 } 1427 1428 self.push_str(&format!("pub enum {name}")); 1429 self.print_generics(lt); 1430 self.push_str("{\n"); 1431 for (case_name, component_name, docs, payload) in cases.clone() { 1432 self.rustdoc(docs); 1433 if let Some(n) = component_name { 1434 self.push_str(&format!("#[component(name = \"{}\")] ", n)); 1435 } 1436 self.push_str(&case_name); 1437 if let Some(ty) = payload { 1438 self.push_str("("); 1439 self.print_ty(ty, mode); 1440 self.push_str(")") 1441 } 1442 self.push_str(",\n"); 1443 } 1444 self.push_str("}\n"); 1445 1446 self.print_rust_enum_debug( 1447 id, 1448 mode, 1449 &name, 1450 cases 1451 .clone() 1452 .into_iter() 1453 .map(|(name, _attr, _docs, ty)| (name, ty)), 1454 ); 1455 1456 if info.error { 1457 self.push_str("impl"); 1458 self.print_generics(lt); 1459 self.push_str(" core::fmt::Display for "); 1460 self.push_str(&name); 1461 self.print_generics(lt); 1462 self.push_str(" {\n"); 1463 self.push_str( 1464 "fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n", 1465 ); 1466 self.push_str("write!(f, \"{:?}\", self)"); 1467 self.push_str("}\n"); 1468 self.push_str("}\n"); 1469 self.push_str("\n"); 1470 1471 self.push_str("impl"); 1472 self.print_generics(lt); 1473 self.push_str(" std::error::Error for "); 1474 self.push_str(&name); 1475 self.print_generics(lt); 1476 self.push_str(" {}\n"); 1477 } 1478 1479 self.assert_type(id, &name); 1480 } 1481 } 1482 1483 fn print_rust_enum_debug<'b>( 1484 &mut self, 1485 id: TypeId, 1486 mode: TypeMode, 1487 name: &str, 1488 cases: impl IntoIterator<Item = (String, Option<&'b Type>)>, 1489 ) where 1490 Self: Sized, 1491 { 1492 let info = self.info(id); 1493 let lt = self.lifetime_for(&info, mode); 1494 self.push_str("impl"); 1495 self.print_generics(lt); 1496 self.push_str(" core::fmt::Debug for "); 1497 self.push_str(name); 1498 self.print_generics(lt); 1499 self.push_str(" {\n"); 1500 self.push_str("fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n"); 1501 self.push_str("match self {\n"); 1502 for (case_name, payload) in cases { 1503 self.push_str(name); 1504 self.push_str("::"); 1505 self.push_str(&case_name); 1506 if payload.is_some() { 1507 self.push_str("(e)"); 1508 } 1509 self.push_str(" => {\n"); 1510 self.push_str(&format!("f.debug_tuple(\"{}::{}\")", name, case_name)); 1511 if payload.is_some() { 1512 self.push_str(".field(e)"); 1513 } 1514 self.push_str(".finish()\n"); 1515 self.push_str("}\n"); 1516 } 1517 self.push_str("}\n"); 1518 self.push_str("}\n"); 1519 self.push_str("}\n"); 1520 } 1521 1522 fn type_result(&mut self, id: TypeId, _name: &str, result: &Result_, docs: &Docs) { 1523 let info = self.info(id); 1524 1525 for (name, mode) in self.modes_of(id) { 1526 self.rustdoc(docs); 1527 let lt = self.lifetime_for(&info, mode); 1528 self.push_str(&format!("pub type {}", name)); 1529 self.print_generics(lt); 1530 self.push_str("= Result<"); 1531 self.print_optional_ty(result.ok.as_ref(), mode); 1532 self.push_str(","); 1533 self.print_optional_ty(result.err.as_ref(), mode); 1534 self.push_str(">;\n"); 1535 self.assert_type(id, &name); 1536 } 1537 } 1538 1539 fn type_enum(&mut self, id: TypeId, name: &str, enum_: &Enum, docs: &Docs) { 1540 let info = self.info(id); 1541 1542 // We use a BTree set to make sure we don't have any duplicates and have a stable order 1543 let mut derives: BTreeSet<String> = self 1544 .gen 1545 .opts 1546 .additional_derive_attributes 1547 .iter() 1548 .cloned() 1549 .collect(); 1550 1551 derives.extend( 1552 ["Clone", "Copy", "PartialEq", "Eq"] 1553 .into_iter() 1554 .map(|s| s.to_string()), 1555 ); 1556 1557 let name = to_rust_upper_camel_case(name); 1558 self.rustdoc(docs); 1559 self.push_str("#[derive(wasmtime::component::ComponentType)]\n"); 1560 self.push_str("#[derive(wasmtime::component::Lift)]\n"); 1561 self.push_str("#[derive(wasmtime::component::Lower)]\n"); 1562 self.push_str("#[component(enum)]\n"); 1563 1564 self.push_str("#[derive("); 1565 self.push_str(&derives.into_iter().collect::<Vec<_>>().join(", ")); 1566 self.push_str(")]\n"); 1567 1568 self.push_str(&format!("pub enum {} {{\n", name)); 1569 for case in enum_.cases.iter() { 1570 self.rustdoc(&case.docs); 1571 self.push_str(&format!("#[component(name = \"{}\")]", case.name)); 1572 self.push_str(&case.name.to_upper_camel_case()); 1573 self.push_str(",\n"); 1574 } 1575 self.push_str("}\n"); 1576 1577 // Auto-synthesize an implementation of the standard `Error` trait for 1578 // error-looking types based on their name. 1579 if info.error { 1580 self.push_str("impl "); 1581 self.push_str(&name); 1582 self.push_str("{\n"); 1583 1584 self.push_str("pub fn name(&self) -> &'static str {\n"); 1585 self.push_str("match self {\n"); 1586 for case in enum_.cases.iter() { 1587 self.push_str(&name); 1588 self.push_str("::"); 1589 self.push_str(&case.name.to_upper_camel_case()); 1590 self.push_str(" => \""); 1591 self.push_str(case.name.as_str()); 1592 self.push_str("\",\n"); 1593 } 1594 self.push_str("}\n"); 1595 self.push_str("}\n"); 1596 1597 self.push_str("pub fn message(&self) -> &'static str {\n"); 1598 self.push_str("match self {\n"); 1599 for case in enum_.cases.iter() { 1600 self.push_str(&name); 1601 self.push_str("::"); 1602 self.push_str(&case.name.to_upper_camel_case()); 1603 self.push_str(" => \""); 1604 if let Some(contents) = &case.docs.contents { 1605 self.push_str(contents.trim()); 1606 } 1607 self.push_str("\",\n"); 1608 } 1609 self.push_str("}\n"); 1610 self.push_str("}\n"); 1611 1612 self.push_str("}\n"); 1613 1614 self.push_str("impl core::fmt::Debug for "); 1615 self.push_str(&name); 1616 self.push_str( 1617 "{\nfn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n", 1618 ); 1619 self.push_str("f.debug_struct(\""); 1620 self.push_str(&name); 1621 self.push_str("\")\n"); 1622 self.push_str(".field(\"code\", &(*self as i32))\n"); 1623 self.push_str(".field(\"name\", &self.name())\n"); 1624 self.push_str(".field(\"message\", &self.message())\n"); 1625 self.push_str(".finish()\n"); 1626 self.push_str("}\n"); 1627 self.push_str("}\n"); 1628 1629 self.push_str("impl core::fmt::Display for "); 1630 self.push_str(&name); 1631 self.push_str( 1632 "{\nfn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n", 1633 ); 1634 self.push_str("write!(f, \"{} (error {})\", self.name(), *self as i32)"); 1635 self.push_str("}\n"); 1636 self.push_str("}\n"); 1637 self.push_str("\n"); 1638 self.push_str("impl std::error::Error for "); 1639 self.push_str(&name); 1640 self.push_str("{}\n"); 1641 } else { 1642 self.print_rust_enum_debug( 1643 id, 1644 TypeMode::Owned, 1645 &name, 1646 enum_ 1647 .cases 1648 .iter() 1649 .map(|c| (c.name.to_upper_camel_case(), None)), 1650 ) 1651 } 1652 self.assert_type(id, &name); 1653 } 1654 1655 fn type_alias(&mut self, id: TypeId, _name: &str, ty: &Type, docs: &Docs) { 1656 let info = self.info(id); 1657 for (name, mode) in self.modes_of(id) { 1658 self.rustdoc(docs); 1659 self.push_str(&format!("pub type {}", name)); 1660 let lt = self.lifetime_for(&info, mode); 1661 self.print_generics(lt); 1662 self.push_str(" = "); 1663 self.print_ty(ty, mode); 1664 self.push_str(";\n"); 1665 let def_id = resolve_type_definition_id(self.resolve, id); 1666 if !matches!(self.resolve().types[def_id].kind, TypeDefKind::Resource) { 1667 self.assert_type(id, &name); 1668 } 1669 } 1670 } 1671 1672 fn type_list(&mut self, id: TypeId, _name: &str, ty: &Type, docs: &Docs) { 1673 let info = self.info(id); 1674 for (name, mode) in self.modes_of(id) { 1675 let lt = self.lifetime_for(&info, mode); 1676 self.rustdoc(docs); 1677 self.push_str(&format!("pub type {}", name)); 1678 self.print_generics(lt); 1679 self.push_str(" = "); 1680 self.print_list(ty, mode); 1681 self.push_str(";\n"); 1682 self.assert_type(id, &name); 1683 } 1684 } 1685 1686 fn print_result_ty(&mut self, results: &Results, mode: TypeMode) { 1687 match results { 1688 Results::Named(rs) => match rs.len() { 1689 0 => self.push_str("()"), 1690 1 => self.print_ty(&rs[0].1, mode), 1691 _ => { 1692 self.push_str("("); 1693 for (i, (_, ty)) in rs.iter().enumerate() { 1694 if i > 0 { 1695 self.push_str(", ") 1696 } 1697 self.print_ty(ty, mode) 1698 } 1699 self.push_str(")"); 1700 } 1701 }, 1702 Results::Anon(ty) => self.print_ty(ty, mode), 1703 } 1704 } 1705 1706 fn special_case_trappable_error( 1707 &self, 1708 results: &Results, 1709 ) -> Option<(&'a Result_, TypeId, String)> { 1710 // We fillin a special trappable error type in the case when a function has just one 1711 // result, which is itself a `result<a, e>`, and the `e` is *not* a primitive 1712 // (i.e. defined in std) type, and matches the typename given by the user. 1713 let mut i = results.iter_types(); 1714 let id = match i.next()? { 1715 Type::Id(id) => id, 1716 _ => return None, 1717 }; 1718 if i.next().is_some() { 1719 return None; 1720 } 1721 let result = match &self.resolve.types[*id].kind { 1722 TypeDefKind::Result(r) => r, 1723 _ => return None, 1724 }; 1725 let error_typeid = match result.err? { 1726 Type::Id(id) => resolve_type_definition_id(&self.resolve, id), 1727 _ => return None, 1728 }; 1729 1730 let name = self.gen.trappable_errors.get(&error_typeid)?; 1731 1732 let mut path = self.path_to_root(); 1733 uwrite!(path, "{name}"); 1734 Some((result, error_typeid, path)) 1735 } 1736 1737 fn generate_add_to_linker(&mut self, id: InterfaceId, name: &str) { 1738 let iface = &self.resolve.interfaces[id]; 1739 let owner = TypeOwner::Interface(id); 1740 1741 if self.gen.opts.async_.maybe_async() { 1742 uwriteln!(self.src, "#[wasmtime::component::__internal::async_trait]") 1743 } 1744 // Generate the `pub trait` which represents the host functionality for 1745 // this import which additionally inherits from all resource traits 1746 // for this interface defined by `type_resource`. 1747 uwrite!(self.src, "pub trait Host"); 1748 for (i, resource) in get_resources(self.resolve, id).enumerate() { 1749 if i == 0 { 1750 uwrite!(self.src, ": "); 1751 } else { 1752 uwrite!(self.src, " + "); 1753 } 1754 uwrite!(self.src, "Host{}", resource.to_upper_camel_case()); 1755 } 1756 uwriteln!(self.src, " {{"); 1757 for (_, func) in iface.functions.iter() { 1758 match func.kind { 1759 FunctionKind::Freestanding => {} 1760 _ => continue, 1761 } 1762 self.generate_function_trait_sig(func); 1763 } 1764 1765 // Generate `convert_*` functions to convert custom trappable errors 1766 // into the representation required by Wasmtime's component API. 1767 let mut required_conversion_traits = IndexSet::new(); 1768 let mut errors_converted = IndexSet::new(); 1769 let my_error_types = iface 1770 .types 1771 .iter() 1772 .filter(|(_, id)| self.gen.trappable_errors.contains_key(*id)) 1773 .map(|(_, id)| *id); 1774 let used_error_types = iface 1775 .functions 1776 .iter() 1777 .filter_map(|(_, func)| self.special_case_trappable_error(&func.results)) 1778 .map(|(_, id, _)| id); 1779 for err in my_error_types.chain(used_error_types).collect::<Vec<_>>() { 1780 let custom_name = &self.gen.trappable_errors[&err]; 1781 let err = &self.resolve.types[resolve_type_definition_id(self.resolve, err)]; 1782 let err_name = err.name.as_ref().unwrap(); 1783 let err_snake = err_name.to_snake_case(); 1784 let err_camel = err_name.to_upper_camel_case(); 1785 let owner = match err.owner { 1786 TypeOwner::Interface(i) => i, 1787 _ => unimplemented!(), 1788 }; 1789 match self.path_to_interface(owner) { 1790 Some(path) => { 1791 required_conversion_traits.insert(format!("{path}::Host")); 1792 } 1793 None => { 1794 if errors_converted.insert(err_name) { 1795 let root = self.path_to_root(); 1796 uwriteln!( 1797 self.src, 1798 "fn convert_{err_snake}(&mut self, err: {root}{custom_name}) -> wasmtime::Result<{err_camel}>;" 1799 ); 1800 } 1801 } 1802 } 1803 } 1804 uwriteln!(self.src, "}}"); 1805 1806 let mut where_clause = if self.gen.opts.async_.maybe_async() { 1807 "T: Send, U: Host + Send".to_string() 1808 } else { 1809 "U: Host".to_string() 1810 }; 1811 1812 for t in required_conversion_traits { 1813 where_clause.push_str(" + "); 1814 where_clause.push_str(&t); 1815 } 1816 1817 uwriteln!( 1818 self.src, 1819 " 1820 pub fn add_to_linker<T, U>( 1821 linker: &mut wasmtime::component::Linker<T>, 1822 get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, 1823 ) -> wasmtime::Result<()> 1824 where {where_clause} 1825 {{ 1826 " 1827 ); 1828 uwriteln!(self.src, "let mut inst = linker.instance(\"{name}\")?;"); 1829 1830 for name in get_resources(self.resolve, id) { 1831 let camel = name.to_upper_camel_case(); 1832 uwriteln!( 1833 self.src, 1834 "inst.resource( 1835 \"{name}\", 1836 wasmtime::component::ResourceType::host::<{camel}>(), 1837 move |mut store, rep| -> wasmtime::Result<()> {{ 1838 Host{camel}::drop(get(store.data_mut()), wasmtime::component::Resource::new_own(rep)) 1839 }}, 1840 )?;" 1841 ) 1842 } 1843 1844 for (_, func) in iface.functions.iter() { 1845 self.generate_add_function_to_linker(owner, func, "inst"); 1846 } 1847 uwriteln!(self.src, "Ok(())"); 1848 uwriteln!(self.src, "}}"); 1849 } 1850 1851 fn generate_add_function_to_linker(&mut self, owner: TypeOwner, func: &Function, linker: &str) { 1852 uwrite!( 1853 self.src, 1854 "{linker}.{}(\"{}\", ", 1855 if self.gen.opts.async_.is_import_async(&func.name) { 1856 "func_wrap_async" 1857 } else { 1858 "func_wrap" 1859 }, 1860 func.name 1861 ); 1862 self.generate_guest_import_closure(owner, func); 1863 uwriteln!(self.src, ")?;") 1864 } 1865 1866 fn generate_guest_import_closure(&mut self, owner: TypeOwner, func: &Function) { 1867 // Generate the closure that's passed to a `Linker`, the final piece of 1868 // codegen here. 1869 1870 self.src 1871 .push_str("move |mut caller: wasmtime::StoreContextMut<'_, T>, ("); 1872 for (i, _param) in func.params.iter().enumerate() { 1873 uwrite!(self.src, "arg{},", i); 1874 } 1875 self.src.push_str(") : ("); 1876 1877 for (_, ty) in func.params.iter() { 1878 // Lift is required to be impled for this type, so we can't use 1879 // a borrowed type: 1880 self.print_ty(ty, TypeMode::Owned); 1881 self.src.push_str(", "); 1882 } 1883 self.src.push_str(") |"); 1884 if self.gen.opts.async_.is_import_async(&func.name) { 1885 self.src.push_str(" Box::new(async move { \n"); 1886 } else { 1887 self.src.push_str(" { \n"); 1888 } 1889 1890 if self.gen.opts.tracing { 1891 uwrite!( 1892 self.src, 1893 " 1894 let span = tracing::span!( 1895 tracing::Level::TRACE, 1896 \"wit-bindgen import\", 1897 module = \"{}\", 1898 function = \"{}\", 1899 ); 1900 let _enter = span.enter(); 1901 ", 1902 match owner { 1903 TypeOwner::Interface(id) => self.resolve.interfaces[id] 1904 .name 1905 .as_deref() 1906 .unwrap_or("<no module>"), 1907 TypeOwner::World(id) => &self.resolve.worlds[id].name, 1908 TypeOwner::None => "<no owner>", 1909 }, 1910 func.name, 1911 ); 1912 let mut event_fields = func 1913 .params 1914 .iter() 1915 .enumerate() 1916 .map(|(i, (name, _ty))| { 1917 let name = to_rust_ident(&name); 1918 format!("{name} = tracing::field::debug(&arg{i})") 1919 }) 1920 .collect::<Vec<String>>(); 1921 event_fields.push(format!("\"call\"")); 1922 uwrite!( 1923 self.src, 1924 "tracing::event!(tracing::Level::TRACE, {});\n", 1925 event_fields.join(", ") 1926 ); 1927 } 1928 1929 self.src.push_str("let host = get(caller.data_mut());\n"); 1930 let func_name = rust_function_name(func); 1931 let host_trait = match func.kind { 1932 FunctionKind::Freestanding => match owner { 1933 TypeOwner::World(id) => format!( 1934 "{}Imports", 1935 self.resolve.worlds[id].name.to_upper_camel_case() 1936 ), 1937 _ => "Host".to_string(), 1938 }, 1939 FunctionKind::Method(id) | FunctionKind::Static(id) | FunctionKind::Constructor(id) => { 1940 let resource = self.resolve.types[id] 1941 .name 1942 .as_ref() 1943 .unwrap() 1944 .to_upper_camel_case(); 1945 format!("Host{resource}") 1946 } 1947 }; 1948 uwrite!(self.src, "let r = {host_trait}::{func_name}(host, "); 1949 1950 for (i, _) in func.params.iter().enumerate() { 1951 uwrite!(self.src, "arg{},", i); 1952 } 1953 if self.gen.opts.async_.is_import_async(&func.name) { 1954 uwrite!(self.src, ").await;\n"); 1955 } else { 1956 uwrite!(self.src, ");\n"); 1957 } 1958 1959 if self.gen.opts.tracing { 1960 uwrite!( 1961 self.src, 1962 "tracing::event!(tracing::Level::TRACE, result = tracing::field::debug(&r), \"return\");" 1963 ); 1964 } 1965 1966 if !self.gen.opts.trappable_imports.can_trap(&func) { 1967 if func.results.iter_types().len() == 1 { 1968 uwrite!(self.src, "Ok((r,))\n"); 1969 } else { 1970 uwrite!(self.src, "Ok(r)\n"); 1971 } 1972 } else if let Some((_, err, _)) = self.special_case_trappable_error(&func.results) { 1973 let err = &self.resolve.types[resolve_type_definition_id(self.resolve, err)]; 1974 let err_name = err.name.as_ref().unwrap(); 1975 let owner = match err.owner { 1976 TypeOwner::Interface(i) => i, 1977 _ => unimplemented!(), 1978 }; 1979 let convert_trait = match self.path_to_interface(owner) { 1980 Some(path) => format!("{path}::Host"), 1981 None => format!("Host"), 1982 }; 1983 let convert = format!("{}::convert_{}", convert_trait, err_name.to_snake_case()); 1984 uwrite!( 1985 self.src, 1986 "Ok((match r {{ 1987 Ok(a) => Ok(a), 1988 Err(e) => Err({convert}(host, e)?), 1989 }},))" 1990 ); 1991 } else if func.results.iter_types().len() == 1 { 1992 uwrite!(self.src, "Ok((r?,))\n"); 1993 } else { 1994 uwrite!(self.src, "r\n"); 1995 } 1996 1997 if self.gen.opts.async_.is_import_async(&func.name) { 1998 // Need to close Box::new and async block 1999 self.src.push_str("})"); 2000 } else { 2001 self.src.push_str("}"); 2002 } 2003 } 2004 2005 fn generate_function_trait_sig(&mut self, func: &Function) { 2006 self.rustdoc(&func.docs); 2007 2008 if self.gen.opts.async_.is_import_async(&func.name) { 2009 self.push_str("async "); 2010 } 2011 self.push_str("fn "); 2012 self.push_str(&rust_function_name(func)); 2013 self.push_str("(&mut self, "); 2014 for (name, param) in func.params.iter() { 2015 let name = to_rust_ident(name); 2016 self.push_str(&name); 2017 self.push_str(": "); 2018 self.print_ty(param, TypeMode::Owned); 2019 self.push_str(","); 2020 } 2021 self.push_str(")"); 2022 self.push_str(" -> "); 2023 2024 if !self.gen.opts.trappable_imports.can_trap(func) { 2025 self.print_result_ty(&func.results, TypeMode::Owned); 2026 } else if let Some((r, _id, error_typename)) = 2027 self.special_case_trappable_error(&func.results) 2028 { 2029 // Functions which have a single result `result<ok,err>` get special 2030 // cased to use the host_wasmtime_rust::Error<err>, making it possible 2031 // for them to trap or use `?` to propogate their errors 2032 self.push_str("Result<"); 2033 if let Some(ok) = r.ok { 2034 self.print_ty(&ok, TypeMode::Owned); 2035 } else { 2036 self.push_str("()"); 2037 } 2038 self.push_str(","); 2039 self.push_str(&error_typename); 2040 self.push_str(">"); 2041 } else { 2042 // All other functions get their return values wrapped in an wasmtime::Result. 2043 // Returning the anyhow::Error case can be used to trap. 2044 self.push_str("wasmtime::Result<"); 2045 self.print_result_ty(&func.results, TypeMode::Owned); 2046 self.push_str(">"); 2047 } 2048 2049 self.push_str(";\n"); 2050 } 2051 2052 fn extract_typed_function(&mut self, func: &Function) -> (String, String) { 2053 let prev = mem::take(&mut self.src); 2054 let snake = func_field_name(self.resolve, func); 2055 uwrite!(self.src, "*__exports.typed_func::<("); 2056 for (_, ty) in func.params.iter() { 2057 self.print_ty(ty, TypeMode::AllBorrowed("'_")); 2058 self.push_str(", "); 2059 } 2060 self.src.push_str("), ("); 2061 for ty in func.results.iter_types() { 2062 self.print_ty(ty, TypeMode::Owned); 2063 self.push_str(", "); 2064 } 2065 self.src.push_str(")>(\""); 2066 self.src.push_str(&func.name); 2067 self.src.push_str("\")?.func()"); 2068 2069 let ret = (snake, mem::take(&mut self.src).to_string()); 2070 self.src = prev; 2071 ret 2072 } 2073 2074 fn define_rust_guest_export( 2075 &mut self, 2076 resolve: &Resolve, 2077 ns: Option<&WorldKey>, 2078 func: &Function, 2079 ) { 2080 // Exports must be async if anything could be async, it's just imports 2081 // that get to be optionally async/sync. 2082 let is_async = self.gen.opts.async_.maybe_async(); 2083 2084 let (async_, async__, await_) = if is_async { 2085 ("async", "_async", ".await") 2086 } else { 2087 ("", "", "") 2088 }; 2089 2090 self.rustdoc(&func.docs); 2091 2092 uwrite!( 2093 self.src, 2094 "pub {async_} fn call_{}<S: wasmtime::AsContextMut>(&self, mut store: S, ", 2095 func.item_name().to_snake_case(), 2096 ); 2097 2098 for (i, param) in func.params.iter().enumerate() { 2099 uwrite!(self.src, "arg{}: ", i); 2100 self.print_ty(¶m.1, TypeMode::AllBorrowed("'_")); 2101 self.push_str(","); 2102 } 2103 2104 self.src.push_str(") -> wasmtime::Result<"); 2105 self.print_result_ty(&func.results, TypeMode::Owned); 2106 2107 if is_async { 2108 self.src 2109 .push_str("> where <S as wasmtime::AsContext>::Data: Send {\n"); 2110 } else { 2111 self.src.push_str("> {\n"); 2112 } 2113 2114 if self.gen.opts.tracing { 2115 let ns = match ns { 2116 Some(key) => resolve.name_world_key(key), 2117 None => "default".to_string(), 2118 }; 2119 self.src.push_str(&format!( 2120 " 2121 let span = tracing::span!( 2122 tracing::Level::TRACE, 2123 \"wit-bindgen export\", 2124 module = \"{ns}\", 2125 function = \"{}\", 2126 ); 2127 let _enter = span.enter(); 2128 ", 2129 func.name, 2130 )); 2131 } 2132 2133 self.src.push_str("let callee = unsafe {\n"); 2134 self.src.push_str("wasmtime::component::TypedFunc::<("); 2135 for (_, ty) in func.params.iter() { 2136 self.print_ty(ty, TypeMode::AllBorrowed("'_")); 2137 self.push_str(", "); 2138 } 2139 self.src.push_str("), ("); 2140 for ty in func.results.iter_types() { 2141 self.print_ty(ty, TypeMode::Owned); 2142 self.push_str(", "); 2143 } 2144 let projection_to_func = match &func.kind { 2145 FunctionKind::Freestanding => "", 2146 _ => ".funcs", 2147 }; 2148 uwriteln!( 2149 self.src, 2150 ")>::new_unchecked(self{projection_to_func}.{})", 2151 func_field_name(self.resolve, func), 2152 ); 2153 self.src.push_str("};\n"); 2154 self.src.push_str("let ("); 2155 for (i, _) in func.results.iter_types().enumerate() { 2156 uwrite!(self.src, "ret{},", i); 2157 } 2158 uwrite!( 2159 self.src, 2160 ") = callee.call{async__}(store.as_context_mut(), (" 2161 ); 2162 for (i, _) in func.params.iter().enumerate() { 2163 uwrite!(self.src, "arg{}, ", i); 2164 } 2165 uwriteln!(self.src, ")){await_}?;"); 2166 2167 uwriteln!( 2168 self.src, 2169 "callee.post_return{async__}(store.as_context_mut()){await_}?;" 2170 ); 2171 2172 self.src.push_str("Ok("); 2173 if func.results.iter_types().len() == 1 { 2174 self.src.push_str("ret0"); 2175 } else { 2176 self.src.push_str("("); 2177 for (i, _) in func.results.iter_types().enumerate() { 2178 uwrite!(self.src, "ret{},", i); 2179 } 2180 self.src.push_str(")"); 2181 } 2182 self.src.push_str(")\n"); 2183 2184 // End function body 2185 self.src.push_str("}\n"); 2186 } 2187 2188 fn rustdoc(&mut self, docs: &Docs) { 2189 let docs = match &docs.contents { 2190 Some(docs) => docs, 2191 None => return, 2192 }; 2193 for line in docs.trim().lines() { 2194 self.push_str("/// "); 2195 self.push_str(line); 2196 self.push_str("\n"); 2197 } 2198 } 2199 2200 fn path_to_root(&self) -> String { 2201 let mut path_to_root = String::new(); 2202 if let Some((_, key, is_export)) = self.current_interface { 2203 match key { 2204 WorldKey::Name(_) => { 2205 path_to_root.push_str("super::"); 2206 } 2207 WorldKey::Interface(_) => { 2208 path_to_root.push_str("super::super::super::"); 2209 } 2210 } 2211 if is_export { 2212 path_to_root.push_str("super::"); 2213 } 2214 } 2215 path_to_root 2216 } 2217 } 2218 2219 impl<'a> RustGenerator<'a> for InterfaceGenerator<'a> { 2220 fn resolve(&self) -> &'a Resolve { 2221 self.resolve 2222 } 2223 2224 fn ownership(&self) -> Ownership { 2225 self.gen.opts.ownership 2226 } 2227 2228 fn path_to_interface(&self, interface: InterfaceId) -> Option<String> { 2229 if let Some((cur, _, _)) = self.current_interface { 2230 if cur == interface { 2231 return None; 2232 } 2233 } 2234 let mut path_to_root = self.path_to_root(); 2235 match &self.gen.interface_names[&interface] { 2236 InterfaceName::Remapped { name_at_root, .. } => path_to_root.push_str(name_at_root), 2237 InterfaceName::Path(path) => { 2238 for (i, name) in path.iter().enumerate() { 2239 if i > 0 { 2240 path_to_root.push_str("::"); 2241 } 2242 path_to_root.push_str(name); 2243 } 2244 } 2245 } 2246 Some(path_to_root) 2247 } 2248 2249 fn push_str(&mut self, s: &str) { 2250 self.src.push_str(s); 2251 } 2252 2253 fn info(&self, ty: TypeId) -> TypeInfo { 2254 self.gen.types.get(ty) 2255 } 2256 2257 fn is_imported_interface(&self, interface: InterfaceId) -> bool { 2258 self.gen.interface_last_seen_as_import[&interface] 2259 } 2260 } 2261 2262 /// When an interface `use`s a type from another interface, it creates a new TypeId 2263 /// referring to the definition TypeId. Chase this chain of references down to 2264 /// a TypeId for type's definition. 2265 fn resolve_type_definition_id(resolve: &Resolve, mut id: TypeId) -> TypeId { 2266 loop { 2267 match resolve.types[id].kind { 2268 TypeDefKind::Type(Type::Id(def_id)) => id = def_id, 2269 _ => return id, 2270 } 2271 } 2272 } 2273 2274 fn rust_function_name(func: &Function) -> String { 2275 match func.kind { 2276 FunctionKind::Method(_) | FunctionKind::Static(_) => to_rust_ident(func.item_name()), 2277 FunctionKind::Constructor(_) => "new".to_string(), 2278 FunctionKind::Freestanding => to_rust_ident(&func.name), 2279 } 2280 } 2281 2282 fn func_field_name(resolve: &Resolve, func: &Function) -> String { 2283 let mut name = String::new(); 2284 match func.kind { 2285 FunctionKind::Method(id) => { 2286 name.push_str("method-"); 2287 name.push_str(resolve.types[id].name.as_ref().unwrap()); 2288 name.push_str("-"); 2289 } 2290 FunctionKind::Static(id) => { 2291 name.push_str("static-"); 2292 name.push_str(resolve.types[id].name.as_ref().unwrap()); 2293 name.push_str("-"); 2294 } 2295 FunctionKind::Constructor(id) => { 2296 name.push_str("constructor-"); 2297 name.push_str(resolve.types[id].name.as_ref().unwrap()); 2298 name.push_str("-"); 2299 } 2300 FunctionKind::Freestanding => {} 2301 } 2302 name.push_str(func.item_name()); 2303 name.to_snake_case() 2304 } 2305 2306 fn get_resources<'a>(resolve: &'a Resolve, id: InterfaceId) -> impl Iterator<Item = &'a str> + 'a { 2307 resolve.interfaces[id] 2308 .types 2309 .iter() 2310 .filter_map(move |(name, ty)| match resolve.types[*ty].kind { 2311 TypeDefKind::Resource => Some(name.as_str()), 2312 _ => None, 2313 }) 2314 } 2315 2316 fn get_world_resources<'a>( 2317 resolve: &'a Resolve, 2318 id: WorldId, 2319 ) -> impl Iterator<Item = &'a str> + 'a { 2320 resolve.worlds[id] 2321 .imports 2322 .iter() 2323 .filter_map(move |(name, item)| match item { 2324 WorldItem::Type(id) => match resolve.types[*id].kind { 2325 TypeDefKind::Resource => Some(match name { 2326 WorldKey::Name(s) => s.as_str(), 2327 WorldKey::Interface(_) => unreachable!(), 2328 }), 2329 _ => None, 2330 }, 2331 _ => None, 2332 }) 2333 } 2334