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