1 use crate::rust::{to_rust_ident, to_rust_upper_camel_case, RustGenerator, TypeMode}; 2 use crate::types::{TypeInfo, Types}; 3 use anyhow::bail; 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 /// This is the `::`-separated string which is the path to the mapped 35 /// item relative to the root of the `bindgen!` macro invocation. 36 /// 37 /// This path currently starts with `__with_name$N` and will then 38 /// optionally have `::` projections through to the actual item 39 /// depending on how `with` was configured. 40 name_at_root: String, 41 42 /// This is currently only used for exports and is the relative path to 43 /// where this mapped name would be located if `with` were not 44 /// specified. Basically it's the same as the `Path` variant of this 45 /// enum if the mapping weren't present. 46 local_path: Vec<String>, 47 }, 48 49 /// This interface is generated in the module hierarchy specified. 50 /// 51 /// The path listed here is the path, from the root of the `bindgen!` macro, 52 /// to where this interface is generated. 53 Path(Vec<String>), 54 } 55 56 #[derive(Default)] 57 struct Wasmtime { 58 src: Source, 59 opts: Opts, 60 /// A list of all interfaces which were imported by this world. 61 /// 62 /// The first value here is the contents of the module that this interface 63 /// generated. The second value is the name of the interface as also present 64 /// in `self.interface_names`. 65 import_interfaces: Vec<(String, InterfaceName)>, 66 import_functions: Vec<ImportFunction>, 67 exports: Exports, 68 types: Types, 69 sizes: SizeAlign, 70 interface_names: HashMap<InterfaceId, InterfaceName>, 71 interface_last_seen_as_import: HashMap<InterfaceId, bool>, 72 trappable_errors: IndexMap<TypeId, String>, 73 // Track the with options that were used. Remapped interfaces provided via `with` 74 // are required to be used. 75 used_with_opts: HashSet<String>, 76 // Track the imports that matched the `trappable_imports` spec. 77 used_trappable_imports_opts: HashSet<String>, 78 } 79 80 struct ImportFunction { 81 func: Function, 82 add_to_linker: String, 83 sig: Option<String>, 84 } 85 86 #[derive(Default)] 87 struct Exports { 88 fields: BTreeMap<String, ExportField>, 89 modules: Vec<(String, InterfaceName)>, 90 funcs: Vec<String>, 91 } 92 93 struct ExportField { 94 ty: String, 95 ty_pre: String, 96 getter: String, 97 getter_pre: String, 98 } 99 100 #[derive(Default, Debug, Clone, Copy)] 101 pub enum Ownership { 102 /// Generated types will be composed entirely of owning fields, regardless 103 /// of whether they are used as parameters to guest exports or not. 104 #[default] 105 Owning, 106 107 /// Generated types used as parameters to guest exports will be "deeply 108 /// borrowing", i.e. contain references rather than owned values when 109 /// applicable. 110 Borrowing { 111 /// Whether or not to generate "duplicate" type definitions for a single 112 /// WIT type if necessary, for example if it's used as both an import 113 /// and an export, or if it's used both as a parameter to an export and 114 /// a return value from an export. 115 duplicate_if_necessary: bool, 116 }, 117 } 118 119 #[derive(Default, Debug, Clone)] 120 pub struct Opts { 121 /// Whether or not `rustfmt` is executed to format generated code. 122 pub rustfmt: bool, 123 124 /// Whether or not to emit `tracing` macro calls on function entry/exit. 125 pub tracing: bool, 126 127 /// Whether or not to use async rust functions and traits. 128 pub async_: AsyncConfig, 129 130 /// A list of "trappable errors" which are used to replace the `E` in 131 /// `result<T, E>` found in WIT. 132 pub trappable_error_type: Vec<TrappableError>, 133 134 /// Whether to generate owning or borrowing type definitions. 135 pub ownership: Ownership, 136 137 /// Whether or not to generate code for only the interfaces of this wit file or not. 138 pub only_interfaces: bool, 139 140 /// Configuration of which imports are allowed to generate a trap. 141 pub trappable_imports: TrappableImports, 142 143 /// Remapping of interface names to rust module names. 144 /// TODO: is there a better type to use for the value of this map? 145 pub with: HashMap<String, String>, 146 147 /// Additional derive attributes to add to generated types. If using in a CLI, this flag can be 148 /// specified multiple times to add multiple attributes. 149 /// 150 /// These derive attributes will be added to any generated structs or enums 151 pub additional_derive_attributes: Vec<String>, 152 153 /// Evaluate to a string literal containing the generated code rather than the generated tokens 154 /// themselves. Mostly useful for Wasmtime internal debugging and development. 155 pub stringify: bool, 156 157 /// Temporary option to skip `impl<T: Trait> Trait for &mut T` for the 158 /// `wasmtime-wasi` crate while that's given a chance to update its b 159 /// indings. 160 pub skip_mut_forwarding_impls: bool, 161 162 /// Indicates that the `T` in `Store<T>` should be send even if async is not 163 /// enabled. 164 /// 165 /// This is helpful when sync bindings depend on generated functions from 166 /// async bindings as is the case with WASI in-tree. 167 pub require_store_data_send: bool, 168 169 /// Path to the `wasmtime` crate if it's not the default path. 170 pub wasmtime_crate: Option<String>, 171 } 172 173 #[derive(Debug, Clone)] 174 pub struct TrappableError { 175 /// Full path to the error, such as `wasi:io/streams/error`. 176 pub wit_path: String, 177 178 /// The name, in Rust, of the error type to generate. 179 pub rust_type_name: String, 180 } 181 182 /// Which imports should be generated as async functions. 183 /// 184 /// The imports should be declared in the following format: 185 /// - Regular functions: `"{function-name}"` 186 /// - Resource methods: `"[method]{resource-name}.{method-name}"` 187 /// - Resource destructors: `"[drop]{resource-name}"` 188 /// 189 /// Examples: 190 /// - Regular function: `"get-environment"` 191 /// - Resource method: `"[method]input-stream.read"` 192 /// - Resource destructor: `"[drop]input-stream"` 193 #[derive(Default, Debug, Clone)] 194 pub enum AsyncConfig { 195 /// No functions are `async`. 196 #[default] 197 None, 198 /// All generated functions should be `async`. 199 All, 200 /// These imported functions should not be async, but everything else is. 201 AllExceptImports(HashSet<String>), 202 /// These functions are the only imports that are async, all other imports 203 /// are sync. 204 /// 205 /// Note that all exports are still async in this situation. 206 OnlyImports(HashSet<String>), 207 } 208 209 impl AsyncConfig { 210 pub fn is_import_async(&self, f: &str) -> bool { 211 match self { 212 AsyncConfig::None => false, 213 AsyncConfig::All => true, 214 AsyncConfig::AllExceptImports(set) => !set.contains(f), 215 AsyncConfig::OnlyImports(set) => set.contains(f), 216 } 217 } 218 219 pub fn is_drop_async(&self, r: &str) -> bool { 220 self.is_import_async(&format!("[drop]{r}")) 221 } 222 223 pub fn maybe_async(&self) -> bool { 224 match self { 225 AsyncConfig::None => false, 226 AsyncConfig::All | AsyncConfig::AllExceptImports(_) | AsyncConfig::OnlyImports(_) => { 227 true 228 } 229 } 230 } 231 } 232 233 #[derive(Default, Debug, Clone)] 234 pub enum TrappableImports { 235 /// No imports are allowed to trap. 236 #[default] 237 None, 238 /// All imports may trap. 239 All, 240 /// Only the specified set of functions may trap. 241 Only(HashSet<String>), 242 } 243 244 impl TrappableImports { 245 fn can_trap(&self, f: &Function) -> bool { 246 match self { 247 TrappableImports::None => false, 248 TrappableImports::All => true, 249 TrappableImports::Only(set) => set.contains(&f.name), 250 } 251 } 252 } 253 254 impl Opts { 255 pub fn generate(&self, resolve: &Resolve, world: WorldId) -> anyhow::Result<String> { 256 let mut r = Wasmtime::default(); 257 r.sizes.fill(resolve); 258 r.opts = self.clone(); 259 r.generate(resolve, world) 260 } 261 262 fn is_store_data_send(&self) -> bool { 263 self.async_.maybe_async() || self.require_store_data_send 264 } 265 } 266 267 impl Wasmtime { 268 fn name_interface( 269 &mut self, 270 resolve: &Resolve, 271 id: InterfaceId, 272 name: &WorldKey, 273 is_export: bool, 274 ) -> bool { 275 let mut path = Vec::new(); 276 if is_export { 277 path.push("exports".to_string()); 278 } 279 match name { 280 WorldKey::Name(name) => { 281 path.push(name.to_snake_case()); 282 } 283 WorldKey::Interface(_) => { 284 let iface = &resolve.interfaces[id]; 285 let pkgname = &resolve.packages[iface.package.unwrap()].name; 286 path.push(pkgname.namespace.to_snake_case()); 287 path.push(self.name_package_module(resolve, iface.package.unwrap())); 288 path.push(to_rust_ident(iface.name.as_ref().unwrap())); 289 } 290 } 291 let entry = if let Some(name_at_root) = self.lookup_replacement(resolve, name, None) { 292 InterfaceName::Remapped { 293 name_at_root, 294 local_path: path, 295 } 296 } else { 297 InterfaceName::Path(path) 298 }; 299 300 let remapped = matches!(entry, InterfaceName::Remapped { .. }); 301 self.interface_names.insert(id, entry); 302 remapped 303 } 304 305 /// If the package `id` is the only package with its namespace/name combo 306 /// then pass through the name unmodified. If, however, there are multiple 307 /// versions of this package then the package module is going to get version 308 /// information. 309 fn name_package_module(&self, resolve: &Resolve, id: PackageId) -> String { 310 let pkg = &resolve.packages[id]; 311 let versions_with_same_name = resolve 312 .packages 313 .iter() 314 .filter_map(|(_, p)| { 315 if p.name.namespace == pkg.name.namespace && p.name.name == pkg.name.name { 316 Some(&p.name.version) 317 } else { 318 None 319 } 320 }) 321 .collect::<Vec<_>>(); 322 let base = pkg.name.name.to_snake_case(); 323 if versions_with_same_name.len() == 1 { 324 return base; 325 } 326 327 let version = match &pkg.name.version { 328 Some(version) => version, 329 // If this package didn't have a version then don't mangle its name 330 // and other packages with the same name but with versions present 331 // will have their names mangled. 332 None => return base, 333 }; 334 335 // Here there's multiple packages with the same name that differ only in 336 // version, so the version needs to be mangled into the Rust module name 337 // that we're generating. This in theory could look at all of 338 // `versions_with_same_name` and produce a minimal diff, e.g. for 0.1.0 339 // and 0.2.0 this could generate "foo1" and "foo2", but for now 340 // a simpler path is chosen to generate "foo0_1_0" and "foo0_2_0". 341 let version = version 342 .to_string() 343 .replace('.', "_") 344 .replace('-', "_") 345 .replace('+', "_") 346 .to_snake_case(); 347 format!("{base}{version}") 348 } 349 350 fn generate(&mut self, resolve: &Resolve, id: WorldId) -> anyhow::Result<String> { 351 self.types.analyze(resolve, id); 352 353 // Resolve the `trappable_error_type` configuration values to `TypeId` 354 // values. This is done by iterating over each `trappable_error_type` 355 // and then locating the interface that it corresponds to as well as the 356 // type within that interface. 357 // 358 // Note that `LookupItem::InterfaceNoPop` is used here as the full 359 // hierarchical behavior of `lookup_keys` isn't used as the interface 360 // must be named here. 361 'outer: for (i, te) in self.opts.trappable_error_type.iter().enumerate() { 362 let error_name = format!("_TrappableError{i}"); 363 for (id, iface) in resolve.interfaces.iter() { 364 for (key, projection) in lookup_keys( 365 resolve, 366 &WorldKey::Interface(id), 367 LookupItem::InterfaceNoPop, 368 ) { 369 assert!(projection.is_empty()); 370 371 // If `wit_path` looks like `{key}/{type_name}` where 372 // `type_name` is a type within `iface` then we've found a 373 // match. Otherwise continue to the next lookup key if there 374 // is one, and failing that continue to the next interface. 375 let suffix = match te.wit_path.strip_prefix(&key) { 376 Some(s) => s, 377 None => continue, 378 }; 379 let suffix = match suffix.strip_prefix('/') { 380 Some(s) => s, 381 None => continue, 382 }; 383 if let Some(id) = iface.types.get(suffix) { 384 uwriteln!(self.src, "type {error_name} = {};", te.rust_type_name); 385 let prev = self.trappable_errors.insert(*id, error_name); 386 assert!(prev.is_none()); 387 continue 'outer; 388 } 389 } 390 } 391 392 bail!( 393 "failed to locate a WIT error type corresponding to the \ 394 `trappable_error_type` name `{}` provided", 395 te.wit_path 396 ) 397 } 398 399 // Convert all entries in `with` as relative to the root of where the 400 // macro itself is invoked. This emits a `pub use` to bring the name 401 // into scope under an "anonymous name" which then replaces the `with` 402 // map entry. 403 let mut with = self.opts.with.iter_mut().collect::<Vec<_>>(); 404 with.sort(); 405 for (i, (_k, v)) in with.into_iter().enumerate() { 406 let name = format!("__with_name{i}"); 407 uwriteln!(self.src, "#[doc(hidden)]\npub use {v} as {name};"); 408 *v = name; 409 } 410 411 let world = &resolve.worlds[id]; 412 for (name, import) in world.imports.iter() { 413 if !self.opts.only_interfaces || matches!(import, WorldItem::Interface { .. }) { 414 self.import(resolve, id, name, import); 415 } 416 } 417 418 for (name, export) in world.exports.iter() { 419 if !self.opts.only_interfaces || matches!(export, WorldItem::Interface { .. }) { 420 self.export(resolve, name, export); 421 } 422 } 423 self.finish(resolve, id) 424 } 425 426 fn import(&mut self, resolve: &Resolve, world: WorldId, name: &WorldKey, item: &WorldItem) { 427 let mut gen = InterfaceGenerator::new(self, resolve); 428 match item { 429 WorldItem::Function(func) => { 430 // Only generate a trait signature for free functions since 431 // resource-related functions get their trait signatures 432 // during `type_resource`. 433 let sig = if let FunctionKind::Freestanding = func.kind { 434 gen.generate_function_trait_sig(func); 435 Some(mem::take(&mut gen.src).into()) 436 } else { 437 None 438 }; 439 gen.generate_add_function_to_linker(TypeOwner::World(world), func, "linker"); 440 let add_to_linker = gen.src.into(); 441 self.import_functions.push(ImportFunction { 442 func: func.clone(), 443 sig, 444 add_to_linker, 445 }); 446 } 447 WorldItem::Interface { id, .. } => { 448 gen.gen.interface_last_seen_as_import.insert(*id, true); 449 gen.current_interface = Some((*id, name, false)); 450 let snake = match name { 451 WorldKey::Name(s) => s.to_snake_case(), 452 WorldKey::Interface(id) => resolve.interfaces[*id] 453 .name 454 .as_ref() 455 .unwrap() 456 .to_snake_case(), 457 }; 458 let module = if gen.gen.name_interface(resolve, *id, name, false) { 459 // If this interface is remapped then that means that it was 460 // provided via the `with` key in the bindgen configuration. 461 // That means that bindings generation is skipped here. To 462 // accommodate future bindgens depending on this bindgen 463 // though we still generate a module which reexports the 464 // original module. This helps maintain the same output 465 // structure regardless of whether `with` is used. 466 let name_at_root = match &gen.gen.interface_names[id] { 467 InterfaceName::Remapped { name_at_root, .. } => name_at_root, 468 InterfaceName::Path(_) => unreachable!(), 469 }; 470 let path_to_root = gen.path_to_root(); 471 format!( 472 " 473 pub mod {snake} {{ 474 #[allow(unused_imports)] 475 pub use {path_to_root}{name_at_root}::*; 476 }} 477 " 478 ) 479 } else { 480 // If this interface is not remapped then it's time to 481 // actually generate bindings here. 482 gen.types(*id); 483 let key_name = resolve.name_world_key(name); 484 gen.generate_add_to_linker(*id, &key_name); 485 486 let module = &gen.src[..]; 487 let wt = gen.gen.wasmtime_path(); 488 489 format!( 490 " 491 #[allow(clippy::all)] 492 pub mod {snake} {{ 493 #[allow(unused_imports)] 494 use {wt}::component::__internal::anyhow; 495 496 {module} 497 }} 498 " 499 ) 500 }; 501 self.import_interfaces 502 .push((module, self.interface_names[id].clone())); 503 } 504 WorldItem::Type(ty) => { 505 let name = match name { 506 WorldKey::Name(name) => name, 507 WorldKey::Interface(_) => unreachable!(), 508 }; 509 gen.define_type(name, *ty); 510 let body = mem::take(&mut gen.src); 511 self.src.push_str(&body); 512 } 513 }; 514 } 515 516 fn export(&mut self, resolve: &Resolve, name: &WorldKey, item: &WorldItem) { 517 let wt = self.wasmtime_path(); 518 let mut gen = InterfaceGenerator::new(self, resolve); 519 let field; 520 let ty; 521 let ty_pre; 522 let getter; 523 let getter_pre; 524 match item { 525 WorldItem::Function(func) => { 526 gen.define_rust_guest_export(resolve, None, func); 527 let body = mem::take(&mut gen.src).into(); 528 getter = gen.extract_typed_function(func).1; 529 assert!(gen.src.is_empty()); 530 self.exports.funcs.push(body); 531 ty_pre = format!("{wt}::component::ComponentExportIndex"); 532 field = func_field_name(resolve, func); 533 ty = format!("{wt}::component::Func"); 534 getter_pre = format!( 535 "_component.export_index(None, \"{}\") 536 .ok_or_else(|| anyhow::anyhow!(\"no function export `{0}` found\"))?.1", 537 func.name 538 ); 539 } 540 WorldItem::Type(_) => unreachable!(), 541 WorldItem::Interface { id, .. } => { 542 gen.gen.interface_last_seen_as_import.insert(*id, false); 543 gen.gen.name_interface(resolve, *id, name, true); 544 gen.current_interface = Some((*id, name, true)); 545 gen.types(*id); 546 let struct_name = "Guest"; 547 let iface = &resolve.interfaces[*id]; 548 let iface_name = match name { 549 WorldKey::Name(name) => name, 550 WorldKey::Interface(_) => iface.name.as_ref().unwrap(), 551 }; 552 uwriteln!(gen.src, "pub struct {struct_name} {{"); 553 for (_, func) in iface.functions.iter() { 554 uwriteln!( 555 gen.src, 556 "{}: {wt}::component::Func,", 557 func_field_name(resolve, func) 558 ); 559 } 560 uwriteln!(gen.src, "}}"); 561 562 uwriteln!(gen.src, "#[derive(Clone)]"); 563 uwriteln!(gen.src, "pub struct {struct_name}Pre {{"); 564 for (_, func) in iface.functions.iter() { 565 uwriteln!( 566 gen.src, 567 "{}: {wt}::component::ComponentExportIndex,", 568 func_field_name(resolve, func) 569 ); 570 } 571 uwriteln!(gen.src, "}}"); 572 573 uwriteln!(gen.src, "impl {struct_name}Pre {{"); 574 let instance_name = resolve.name_world_key(name); 575 uwrite!( 576 gen.src, 577 " 578 pub fn new( 579 component: &{wt}::component::Component, 580 ) -> {wt}::Result<{struct_name}Pre> {{ 581 let _component = component; 582 let (_, instance) = component.export_index(None, \"{instance_name}\") 583 .ok_or_else(|| anyhow::anyhow!(\"no exported instance named `{instance_name}`\"))?; 584 let _lookup = |name: &str| {{ 585 _component.export_index(Some(&instance), name) 586 .map(|p| p.1) 587 .ok_or_else(|| {{ 588 anyhow::anyhow!( 589 \"instance export `{instance_name}` does \\ 590 not have export `{{name}}`\" 591 ) 592 }}) 593 }}; 594 " 595 ); 596 let mut fields = Vec::new(); 597 for (_, func) in iface.functions.iter() { 598 let name = func_field_name(resolve, func); 599 uwriteln!(gen.src, "let {name} = _lookup(\"{}\")?;", func.name); 600 fields.push(name); 601 } 602 uwriteln!(gen.src, "Ok({struct_name}Pre {{"); 603 for name in fields { 604 uwriteln!(gen.src, "{name},"); 605 } 606 uwriteln!(gen.src, "}})"); 607 uwriteln!(gen.src, "}}"); 608 609 uwrite!( 610 gen.src, 611 " 612 pub fn load( 613 &self, 614 mut store: impl {wt}::AsContextMut, 615 instance: &{wt}::component::Instance, 616 ) -> {wt}::Result<{struct_name}> {{ 617 let mut store = store.as_context_mut(); 618 let _ = &mut store; 619 let _instance = instance; 620 " 621 ); 622 let mut fields = Vec::new(); 623 for (_, func) in iface.functions.iter() { 624 let (name, getter) = gen.extract_typed_function(func); 625 uwriteln!(gen.src, "let {name} = {getter};"); 626 fields.push(name); 627 } 628 uwriteln!(gen.src, "Ok({struct_name} {{"); 629 for name in fields { 630 uwriteln!(gen.src, "{name},"); 631 } 632 uwriteln!(gen.src, "}})"); 633 uwriteln!(gen.src, "}}"); // end `fn new` 634 uwriteln!(gen.src, "}}"); // end `impl {struct_name}Pre` 635 636 uwriteln!(gen.src, "impl {struct_name} {{"); 637 let mut resource_methods = IndexMap::new(); 638 639 for (_, func) in iface.functions.iter() { 640 match func.kind { 641 FunctionKind::Freestanding => { 642 gen.define_rust_guest_export(resolve, Some(name), func); 643 } 644 FunctionKind::Method(id) 645 | FunctionKind::Constructor(id) 646 | FunctionKind::Static(id) => { 647 resource_methods.entry(id).or_insert(Vec::new()).push(func); 648 } 649 } 650 } 651 652 for (id, _) in resource_methods.iter() { 653 let name = resolve.types[*id].name.as_ref().unwrap(); 654 let snake = name.to_snake_case(); 655 let camel = name.to_upper_camel_case(); 656 uwriteln!( 657 gen.src, 658 "pub fn {snake}(&self) -> Guest{camel}<'_> {{ 659 Guest{camel} {{ funcs: self }} 660 }}" 661 ); 662 } 663 664 uwriteln!(gen.src, "}}"); 665 666 for (id, methods) in resource_methods { 667 let resource_name = resolve.types[id].name.as_ref().unwrap(); 668 let camel = resource_name.to_upper_camel_case(); 669 uwriteln!(gen.src, "impl Guest{camel}<'_> {{"); 670 for method in methods { 671 gen.define_rust_guest_export(resolve, Some(name), method); 672 } 673 uwriteln!(gen.src, "}}"); 674 } 675 676 let module = &gen.src[..]; 677 let snake = to_rust_ident(iface_name); 678 679 let module = format!( 680 " 681 #[allow(clippy::all)] 682 pub mod {snake} {{ 683 #[allow(unused_imports)] 684 use {wt}::component::__internal::anyhow; 685 686 {module} 687 }} 688 " 689 ); 690 let pkgname = match name { 691 WorldKey::Name(_) => None, 692 WorldKey::Interface(_) => { 693 Some(resolve.packages[iface.package.unwrap()].name.clone()) 694 } 695 }; 696 self.exports 697 .modules 698 .push((module, self.interface_names[id].clone())); 699 700 let (path, method_name) = match pkgname { 701 Some(pkgname) => ( 702 format!( 703 "exports::{}::{}::{snake}::{struct_name}", 704 pkgname.namespace.to_snake_case(), 705 self.name_package_module(resolve, iface.package.unwrap()), 706 ), 707 format!( 708 "{}_{}_{snake}", 709 pkgname.namespace.to_snake_case(), 710 self.name_package_module(resolve, iface.package.unwrap()) 711 ), 712 ), 713 None => (format!("exports::{snake}::{struct_name}"), snake.clone()), 714 }; 715 field = format!("interface{}", self.exports.fields.len()); 716 getter = format!("self.{field}.load(&mut store, &_instance)?"); 717 self.exports.funcs.push(format!( 718 " 719 pub fn {method_name}(&self) -> &{path} {{ 720 &self.{field} 721 }} 722 ", 723 )); 724 ty_pre = format!("{path}Pre"); 725 ty = path; 726 getter_pre = format!("{ty_pre}::new(_component)?"); 727 } 728 } 729 let prev = self.exports.fields.insert( 730 field, 731 ExportField { 732 ty, 733 ty_pre, 734 getter, 735 getter_pre, 736 }, 737 ); 738 assert!(prev.is_none()); 739 } 740 741 fn build_world_struct(&mut self, resolve: &Resolve, world: WorldId) { 742 let wt = self.wasmtime_path(); 743 let world_name = &resolve.worlds[world].name; 744 let camel = to_rust_upper_camel_case(&world_name); 745 let (async_, async__, where_clause, await_) = if self.opts.async_.maybe_async() { 746 ("async", "_async", "where _T: Send", ".await") 747 } else { 748 ("", "", "", "") 749 }; 750 uwriteln!( 751 self.src, 752 " 753 /// Auto-generated bindings for a pre-instantiated version of a 754 /// component which implements the world `{world_name}`. 755 /// 756 /// This structure is created through [`{camel}Pre::new`] which 757 /// takes a [`InstancePre`]({wt}::component::InstancePre) that 758 /// has been created through a [`Linker`]({wt}::component::Linker). 759 pub struct {camel}Pre<T> {{" 760 ); 761 uwriteln!(self.src, "instance_pre: {wt}::component::InstancePre<T>,"); 762 for (name, field) in self.exports.fields.iter() { 763 uwriteln!(self.src, "{name}: {},", field.ty_pre); 764 } 765 self.src.push_str("}\n"); 766 767 uwriteln!(self.src, "impl<T> Clone for {camel}Pre<T> {{"); 768 uwriteln!(self.src, "fn clone(&self) -> Self {{"); 769 uwriteln!(self.src, "Self {{ instance_pre: self.instance_pre.clone(),"); 770 for (name, _field) in self.exports.fields.iter() { 771 uwriteln!(self.src, "{name}: self.{name}.clone(),"); 772 } 773 uwriteln!(self.src, "}}"); // `Self ... 774 uwriteln!(self.src, "}}"); // `fn clone` 775 uwriteln!(self.src, "}}"); // `impl Clone` 776 777 uwriteln!( 778 self.src, 779 " 780 /// Auto-generated bindings for an instance a component which 781 /// implements the world `{world_name}`. 782 /// 783 /// This structure is created through either 784 /// [`{camel}::instantiate{async__}`] or by first creating 785 /// a [`{camel}Pre`] followed by using 786 /// [`{camel}Pre::instantiate{async__}`]. 787 pub struct {camel} {{" 788 ); 789 for (name, field) in self.exports.fields.iter() { 790 uwriteln!(self.src, "{name}: {},", field.ty); 791 } 792 self.src.push_str("}\n"); 793 794 self.world_imports_trait(resolve, world); 795 796 uwriteln!(self.src, "const _: () = {{"); 797 uwriteln!( 798 self.src, 799 " 800 #[allow(unused_imports)] 801 use {wt}::component::__internal::anyhow; 802 " 803 ); 804 805 uwriteln!( 806 self.src, 807 "impl<_T> {camel}Pre<_T> {{ 808 /// Creates a new copy of `{camel}Pre` bindings which can then 809 /// be used to instantiate into a particular store. 810 /// 811 /// This method may fail if the component behind `instance_pre` 812 /// does not have the required exports. 813 pub fn new( 814 instance_pre: {wt}::component::InstancePre<_T>, 815 ) -> {wt}::Result<Self> {{ 816 let _component = instance_pre.component(); 817 ", 818 ); 819 for (name, field) in self.exports.fields.iter() { 820 uwriteln!(self.src, "let {name} = {};", field.getter_pre); 821 } 822 uwriteln!(self.src, "Ok({camel}Pre {{"); 823 uwriteln!(self.src, "instance_pre,"); 824 for (name, _) in self.exports.fields.iter() { 825 uwriteln!(self.src, "{name},"); 826 } 827 uwriteln!(self.src, "}})"); 828 uwriteln!(self.src, "}}"); // close `fn new` 829 830 uwriteln!( 831 self.src, 832 " 833 /// Instantiates a new instance of [`{camel}`] within the 834 /// `store` provided. 835 /// 836 /// This function will use `self` as the pre-instantiated 837 /// instance to perform instantiation. Afterwards the preloaded 838 /// indices in `self` are used to lookup all exports on the 839 /// resulting instance. 840 pub {async_} fn instantiate{async__}( 841 &self, 842 mut store: impl {wt}::AsContextMut<Data = _T>, 843 ) -> {wt}::Result<{camel}> 844 {where_clause} 845 {{ 846 let mut store = store.as_context_mut(); 847 let _instance = self.instance_pre.instantiate{async__}(&mut store){await_}?; 848 ", 849 ); 850 for (name, field) in self.exports.fields.iter() { 851 uwriteln!(self.src, "let {name} = {};", field.getter); 852 } 853 uwriteln!(self.src, "Ok({camel} {{"); 854 for (name, _) in self.exports.fields.iter() { 855 uwriteln!(self.src, "{name},"); 856 } 857 uwriteln!(self.src, "}})"); 858 uwriteln!(self.src, "}}"); // close `fn new` 859 uwriteln!( 860 self.src, 861 " 862 pub fn engine(&self) -> &{wt}::Engine {{ 863 self.instance_pre.engine() 864 }} 865 866 pub fn instance_pre(&self) -> &{wt}::component::InstancePre<_T> {{ 867 &self.instance_pre 868 }} 869 ", 870 ); 871 872 uwriteln!(self.src, "}}"); 873 874 uwriteln!( 875 self.src, 876 "impl {camel} {{ 877 /// Convenience wrapper around [`{camel}Pre::new`] and 878 /// [`{camel}Pre::instantiate{async__}`]. 879 pub {async_} fn instantiate{async__}<_T>( 880 mut store: impl {wt}::AsContextMut<Data = _T>, 881 component: &{wt}::component::Component, 882 linker: &{wt}::component::Linker<_T>, 883 ) -> {wt}::Result<{camel}> 884 {where_clause} 885 {{ 886 let pre = linker.instantiate_pre(component)?; 887 {camel}Pre::new(pre)?.instantiate{async__}(store){await_} 888 }} 889 ", 890 ); 891 self.world_add_to_linker(resolve, world); 892 893 for func in self.exports.funcs.iter() { 894 self.src.push_str(func); 895 } 896 897 uwriteln!(self.src, "}}"); // close `impl {camel}` 898 899 uwriteln!(self.src, "}};"); // close `const _: () = ... 900 } 901 902 fn finish(&mut self, resolve: &Resolve, world: WorldId) -> anyhow::Result<String> { 903 let remapping_keys = self.opts.with.keys().cloned().collect::<HashSet<String>>(); 904 905 let mut unused_keys = remapping_keys 906 .difference(&self.used_with_opts) 907 .map(|s| s.as_str()) 908 .collect::<Vec<&str>>(); 909 910 unused_keys.sort(); 911 912 if !unused_keys.is_empty() { 913 anyhow::bail!("interfaces were specified in the `with` config option but are not referenced in the target world: {unused_keys:?}"); 914 } 915 916 if let TrappableImports::Only(only) = &self.opts.trappable_imports { 917 let mut unused_imports = Vec::from_iter( 918 only.difference(&self.used_trappable_imports_opts) 919 .map(|s| s.as_str()), 920 ); 921 922 if !unused_imports.is_empty() { 923 unused_imports.sort(); 924 anyhow::bail!("names specified in the `trappable_imports` config option but are not referenced in the target world: {unused_imports:?}"); 925 } 926 } 927 928 if !self.opts.only_interfaces { 929 self.build_world_struct(resolve, world) 930 } 931 932 let imports = mem::take(&mut self.import_interfaces); 933 self.emit_modules(imports); 934 935 let exports = mem::take(&mut self.exports.modules); 936 self.emit_modules(exports); 937 938 let mut src = mem::take(&mut self.src); 939 if self.opts.rustfmt { 940 let mut child = Command::new("rustfmt") 941 .arg("--edition=2018") 942 .stdin(Stdio::piped()) 943 .stdout(Stdio::piped()) 944 .spawn() 945 .expect("failed to spawn `rustfmt`"); 946 child 947 .stdin 948 .take() 949 .unwrap() 950 .write_all(src.as_bytes()) 951 .unwrap(); 952 src.as_mut_string().truncate(0); 953 child 954 .stdout 955 .take() 956 .unwrap() 957 .read_to_string(src.as_mut_string()) 958 .unwrap(); 959 let status = child.wait().unwrap(); 960 assert!(status.success()); 961 } 962 963 Ok(src.into()) 964 } 965 966 fn emit_modules(&mut self, modules: Vec<(String, InterfaceName)>) { 967 #[derive(Default)] 968 struct Module { 969 submodules: BTreeMap<String, Module>, 970 contents: Vec<String>, 971 } 972 let mut map = Module::default(); 973 for (module, name) in modules { 974 let path = match name { 975 InterfaceName::Remapped { local_path, .. } => local_path, 976 InterfaceName::Path(path) => path, 977 }; 978 let mut cur = &mut map; 979 for name in path[..path.len() - 1].iter() { 980 cur = cur 981 .submodules 982 .entry(name.clone()) 983 .or_insert(Module::default()); 984 } 985 cur.contents.push(module); 986 } 987 988 emit(&mut self.src, map); 989 990 fn emit(me: &mut Source, module: Module) { 991 for (name, submodule) in module.submodules { 992 uwriteln!(me, "pub mod {name} {{"); 993 emit(me, submodule); 994 uwriteln!(me, "}}"); 995 } 996 for submodule in module.contents { 997 uwriteln!(me, "{submodule}"); 998 } 999 } 1000 } 1001 1002 /// Attempts to find the `key`, possibly with the resource projection 1003 /// `item`, within the `with` map provided to bindings configuration. 1004 fn lookup_replacement( 1005 &mut self, 1006 resolve: &Resolve, 1007 key: &WorldKey, 1008 item: Option<&str>, 1009 ) -> Option<String> { 1010 let item = match item { 1011 Some(item) => LookupItem::Name(item), 1012 None => LookupItem::None, 1013 }; 1014 1015 for (lookup, mut projection) in lookup_keys(resolve, key, item) { 1016 if let Some(renamed) = self.opts.with.get(&lookup) { 1017 projection.push(renamed.clone()); 1018 projection.reverse(); 1019 self.used_with_opts.insert(lookup); 1020 return Some(projection.join("::")); 1021 } 1022 } 1023 1024 None 1025 } 1026 1027 fn wasmtime_path(&self) -> String { 1028 self.opts 1029 .wasmtime_crate 1030 .clone() 1031 .unwrap_or("wasmtime".to_string()) 1032 } 1033 } 1034 1035 enum LookupItem<'a> { 1036 None, 1037 Name(&'a str), 1038 InterfaceNoPop, 1039 } 1040 1041 fn lookup_keys( 1042 resolve: &Resolve, 1043 key: &WorldKey, 1044 item: LookupItem<'_>, 1045 ) -> Vec<(String, Vec<String>)> { 1046 struct Name<'a> { 1047 prefix: Prefix, 1048 item: Option<&'a str>, 1049 } 1050 1051 #[derive(Copy, Clone)] 1052 enum Prefix { 1053 Namespace(PackageId), 1054 UnversionedPackage(PackageId), 1055 VersionedPackage(PackageId), 1056 UnversionedInterface(InterfaceId), 1057 VersionedInterface(InterfaceId), 1058 } 1059 1060 let prefix = match key { 1061 WorldKey::Interface(id) => Prefix::VersionedInterface(*id), 1062 1063 // Non-interface-keyed names don't get the lookup logic below, 1064 // they're relatively uncommon so only lookup the precise key here. 1065 WorldKey::Name(key) => { 1066 let to_lookup = match item { 1067 LookupItem::Name(item) => format!("{key}/{item}"), 1068 LookupItem::None | LookupItem::InterfaceNoPop => key.to_string(), 1069 }; 1070 return vec![(to_lookup, Vec::new())]; 1071 } 1072 }; 1073 1074 // Here names are iteratively attempted as `key` + `item` is "walked to 1075 // its root" and each attempt is consulted in `self.opts.with`. This 1076 // loop will start at the leaf, the most specific path, and then walk to 1077 // the root, popping items, trying to find a result. 1078 // 1079 // Each time a name is "popped" the projection from the next path is 1080 // pushed onto `projection`. This means that if we actually find a match 1081 // then `projection` is a collection of namespaces that results in the 1082 // final replacement name. 1083 let (interface_required, item) = match item { 1084 LookupItem::None => (false, None), 1085 LookupItem::Name(s) => (false, Some(s)), 1086 LookupItem::InterfaceNoPop => (true, None), 1087 }; 1088 let mut name = Name { prefix, item }; 1089 let mut projection = Vec::new(); 1090 let mut ret = Vec::new(); 1091 loop { 1092 let lookup = name.lookup_key(resolve); 1093 ret.push((lookup, projection.clone())); 1094 if !name.pop(resolve, &mut projection) { 1095 break; 1096 } 1097 if interface_required { 1098 match name.prefix { 1099 Prefix::VersionedInterface(_) | Prefix::UnversionedInterface(_) => {} 1100 _ => break, 1101 } 1102 } 1103 } 1104 1105 return ret; 1106 1107 impl<'a> Name<'a> { 1108 fn lookup_key(&self, resolve: &Resolve) -> String { 1109 let mut s = self.prefix.lookup_key(resolve); 1110 if let Some(item) = self.item { 1111 s.push_str("/"); 1112 s.push_str(item); 1113 } 1114 s 1115 } 1116 1117 fn pop(&mut self, resolve: &'a Resolve, projection: &mut Vec<String>) -> bool { 1118 match (self.item, self.prefix) { 1119 // If this is a versioned resource name, try the unversioned 1120 // resource name next. 1121 (Some(_), Prefix::VersionedInterface(id)) => { 1122 self.prefix = Prefix::UnversionedInterface(id); 1123 true 1124 } 1125 // If this is an unversioned resource name then time to 1126 // ignore the resource itself and move on to the next most 1127 // specific item, versioned interface names. 1128 (Some(item), Prefix::UnversionedInterface(id)) => { 1129 self.prefix = Prefix::VersionedInterface(id); 1130 self.item = None; 1131 projection.push(item.to_upper_camel_case()); 1132 true 1133 } 1134 (Some(_), _) => unreachable!(), 1135 (None, _) => self.prefix.pop(resolve, projection), 1136 } 1137 } 1138 } 1139 1140 impl Prefix { 1141 fn lookup_key(&self, resolve: &Resolve) -> String { 1142 match *self { 1143 Prefix::Namespace(id) => resolve.packages[id].name.namespace.clone(), 1144 Prefix::UnversionedPackage(id) => { 1145 let mut name = resolve.packages[id].name.clone(); 1146 name.version = None; 1147 name.to_string() 1148 } 1149 Prefix::VersionedPackage(id) => resolve.packages[id].name.to_string(), 1150 Prefix::UnversionedInterface(id) => { 1151 let id = resolve.id_of(id).unwrap(); 1152 match id.find('@') { 1153 Some(i) => id[..i].to_string(), 1154 None => id, 1155 } 1156 } 1157 Prefix::VersionedInterface(id) => resolve.id_of(id).unwrap(), 1158 } 1159 } 1160 1161 fn pop(&mut self, resolve: &Resolve, projection: &mut Vec<String>) -> bool { 1162 *self = match *self { 1163 // try the unversioned interface next 1164 Prefix::VersionedInterface(id) => Prefix::UnversionedInterface(id), 1165 // try this interface's versioned package next 1166 Prefix::UnversionedInterface(id) => { 1167 let iface = &resolve.interfaces[id]; 1168 let name = iface.name.as_ref().unwrap(); 1169 projection.push(to_rust_ident(name)); 1170 Prefix::VersionedPackage(iface.package.unwrap()) 1171 } 1172 // try the unversioned package next 1173 Prefix::VersionedPackage(id) => Prefix::UnversionedPackage(id), 1174 // try this package's namespace next 1175 Prefix::UnversionedPackage(id) => { 1176 let name = &resolve.packages[id].name; 1177 projection.push(to_rust_ident(&name.name)); 1178 Prefix::Namespace(id) 1179 } 1180 // nothing left to try any more 1181 Prefix::Namespace(_) => return false, 1182 }; 1183 true 1184 } 1185 } 1186 } 1187 1188 impl Wasmtime { 1189 fn has_world_imports_trait(&self, resolve: &Resolve, world: WorldId) -> bool { 1190 !self.import_functions.is_empty() || get_world_resources(resolve, world).count() > 0 1191 } 1192 1193 fn world_imports_trait(&mut self, resolve: &Resolve, world: WorldId) { 1194 if !self.has_world_imports_trait(resolve, world) { 1195 return; 1196 } 1197 1198 let wt = self.wasmtime_path(); 1199 let world_camel = to_rust_upper_camel_case(&resolve.worlds[world].name); 1200 if self.opts.async_.maybe_async() { 1201 uwriteln!(self.src, "#[{wt}::component::__internal::async_trait]") 1202 } 1203 uwrite!(self.src, "pub trait {world_camel}Imports"); 1204 let mut supertraits = vec![]; 1205 if self.opts.async_.maybe_async() { 1206 supertraits.push("Send".to_string()); 1207 } 1208 for resource in get_world_resources(resolve, world) { 1209 supertraits.push(format!("Host{}", resource.to_upper_camel_case())); 1210 } 1211 if !supertraits.is_empty() { 1212 uwrite!(self.src, ": {}", supertraits.join(" + ")); 1213 } 1214 uwriteln!(self.src, " {{"); 1215 for f in self.import_functions.iter() { 1216 if let Some(sig) = &f.sig { 1217 self.src.push_str(sig); 1218 self.src.push_str(";\n"); 1219 } 1220 } 1221 uwriteln!(self.src, "}}"); 1222 1223 uwriteln!( 1224 self.src, 1225 " 1226 pub trait {world_camel}ImportsGetHost<T>: 1227 Fn(T) -> <Self as {world_camel}ImportsGetHost<T>>::Host 1228 + Send 1229 + Sync 1230 + Copy 1231 + 'static 1232 {{ 1233 type Host: {world_camel}Imports; 1234 }} 1235 1236 impl<F, T, O> {world_camel}ImportsGetHost<T> for F 1237 where 1238 F: Fn(T) -> O + Send + Sync + Copy + 'static, 1239 O: {world_camel}Imports 1240 {{ 1241 type Host = O; 1242 }} 1243 " 1244 ); 1245 1246 // Generate impl WorldImports for &mut WorldImports 1247 let (async_trait, maybe_send) = if self.opts.async_.maybe_async() { 1248 ( 1249 format!("#[{wt}::component::__internal::async_trait]\n"), 1250 "+ Send", 1251 ) 1252 } else { 1253 (String::new(), "") 1254 }; 1255 if !self.opts.skip_mut_forwarding_impls { 1256 uwriteln!( 1257 self.src, 1258 "{async_trait}impl<_T: {world_camel}Imports + ?Sized {maybe_send}> {world_camel}Imports for &mut _T {{" 1259 ); 1260 // Forward each method call to &mut T 1261 for f in self.import_functions.iter() { 1262 if let Some(sig) = &f.sig { 1263 self.src.push_str(sig); 1264 uwrite!( 1265 self.src, 1266 "{{ {world_camel}Imports::{}(*self,", 1267 rust_function_name(&f.func) 1268 ); 1269 for (name, _) in f.func.params.iter() { 1270 uwrite!(self.src, "{},", to_rust_ident(name)); 1271 } 1272 uwrite!(self.src, ")"); 1273 if self.opts.async_.is_import_async(&f.func.name) { 1274 uwrite!(self.src, ".await"); 1275 } 1276 uwriteln!(self.src, "}}"); 1277 } 1278 } 1279 uwriteln!(self.src, "}}"); 1280 } 1281 } 1282 1283 fn import_interface_paths(&self) -> Vec<String> { 1284 self.import_interfaces 1285 .iter() 1286 .map(|(_, name)| match name { 1287 InterfaceName::Path(path) => path.join("::"), 1288 InterfaceName::Remapped { name_at_root, .. } => name_at_root.clone(), 1289 }) 1290 .collect() 1291 } 1292 1293 fn world_host_traits(&self, resolve: &Resolve, world: WorldId) -> Vec<String> { 1294 let mut traits = self 1295 .import_interface_paths() 1296 .iter() 1297 .map(|path| format!("{path}::Host")) 1298 .collect::<Vec<_>>(); 1299 if self.has_world_imports_trait(resolve, world) { 1300 let world_camel = to_rust_upper_camel_case(&resolve.worlds[world].name); 1301 traits.push(format!("{world_camel}Imports")); 1302 } 1303 if self.opts.async_.maybe_async() { 1304 traits.push("Send".to_string()); 1305 } 1306 traits 1307 } 1308 1309 fn world_add_to_linker(&mut self, resolve: &Resolve, world: WorldId) { 1310 let has_world_imports_trait = self.has_world_imports_trait(resolve, world); 1311 if self.import_interfaces.is_empty() && !has_world_imports_trait { 1312 return; 1313 } 1314 1315 let camel = to_rust_upper_camel_case(&resolve.worlds[world].name); 1316 let data_bounds = if self.opts.is_store_data_send() { 1317 "T: Send," 1318 } else { 1319 "" 1320 }; 1321 let wt = self.wasmtime_path(); 1322 if has_world_imports_trait { 1323 uwrite!( 1324 self.src, 1325 " 1326 pub fn add_to_linker_imports_get_host<T>( 1327 linker: &mut {wt}::component::Linker<T>, 1328 host_getter: impl for<'a> {camel}ImportsGetHost<&'a mut T>, 1329 ) -> {wt}::Result<()> 1330 where {data_bounds} 1331 {{ 1332 let mut linker = linker.root(); 1333 " 1334 ); 1335 for name in get_world_resources(resolve, world) { 1336 Self::generate_add_resource_to_linker( 1337 &mut self.src, 1338 &self.opts, 1339 &wt, 1340 "linker", 1341 name, 1342 ); 1343 } 1344 for f in self.import_functions.iter() { 1345 self.src.push_str(&f.add_to_linker); 1346 self.src.push_str("\n"); 1347 } 1348 uwriteln!(self.src, "Ok(())\n}}"); 1349 } 1350 1351 let host_bounds = format!("U: {}", self.world_host_traits(resolve, world).join(" + ")); 1352 1353 if !self.opts.skip_mut_forwarding_impls { 1354 uwriteln!( 1355 self.src, 1356 " 1357 pub fn add_to_linker<T, U>( 1358 linker: &mut {wt}::component::Linker<T>, 1359 get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, 1360 ) -> {wt}::Result<()> 1361 where 1362 {data_bounds} 1363 {host_bounds} 1364 {{ 1365 " 1366 ); 1367 if has_world_imports_trait { 1368 uwriteln!( 1369 self.src, 1370 "Self::add_to_linker_imports_get_host(linker, get)?;" 1371 ); 1372 } 1373 for path in self.import_interface_paths() { 1374 uwriteln!(self.src, "{path}::add_to_linker(linker, get)?;"); 1375 } 1376 uwriteln!(self.src, "Ok(())\n}}"); 1377 } 1378 } 1379 1380 fn generate_add_resource_to_linker( 1381 src: &mut Source, 1382 opts: &Opts, 1383 wt: &str, 1384 inst: &str, 1385 name: &str, 1386 ) { 1387 let camel = name.to_upper_camel_case(); 1388 if opts.async_.is_drop_async(name) { 1389 uwriteln!( 1390 src, 1391 "{inst}.resource_async( 1392 \"{name}\", 1393 {wt}::component::ResourceType::host::<{camel}>(), 1394 move |mut store, rep| {{ 1395 std::boxed::Box::new(async move {{ 1396 Host{camel}::drop(&mut host_getter(store.data_mut()), {wt}::component::Resource::new_own(rep)).await 1397 }}) 1398 }}, 1399 )?;" 1400 ) 1401 } else { 1402 uwriteln!( 1403 src, 1404 "{inst}.resource( 1405 \"{name}\", 1406 {wt}::component::ResourceType::host::<{camel}>(), 1407 move |mut store, rep| -> {wt}::Result<()> {{ 1408 Host{camel}::drop(&mut host_getter(store.data_mut()), {wt}::component::Resource::new_own(rep)) 1409 }}, 1410 )?;" 1411 ) 1412 } 1413 } 1414 } 1415 1416 struct InterfaceGenerator<'a> { 1417 src: Source, 1418 gen: &'a mut Wasmtime, 1419 resolve: &'a Resolve, 1420 current_interface: Option<(InterfaceId, &'a WorldKey, bool)>, 1421 } 1422 1423 impl<'a> InterfaceGenerator<'a> { 1424 fn new(gen: &'a mut Wasmtime, resolve: &'a Resolve) -> InterfaceGenerator<'a> { 1425 InterfaceGenerator { 1426 src: Source::default(), 1427 gen, 1428 resolve, 1429 current_interface: None, 1430 } 1431 } 1432 1433 fn types_imported(&self) -> bool { 1434 match self.current_interface { 1435 Some((_, _, is_export)) => !is_export, 1436 None => true, 1437 } 1438 } 1439 1440 fn types(&mut self, id: InterfaceId) { 1441 for (name, id) in self.resolve.interfaces[id].types.iter() { 1442 self.define_type(name, *id); 1443 } 1444 } 1445 1446 fn define_type(&mut self, name: &str, id: TypeId) { 1447 let ty = &self.resolve.types[id]; 1448 match &ty.kind { 1449 TypeDefKind::Record(record) => self.type_record(id, name, record, &ty.docs), 1450 TypeDefKind::Flags(flags) => self.type_flags(id, name, flags, &ty.docs), 1451 TypeDefKind::Tuple(tuple) => self.type_tuple(id, name, tuple, &ty.docs), 1452 TypeDefKind::Enum(enum_) => self.type_enum(id, name, enum_, &ty.docs), 1453 TypeDefKind::Variant(variant) => self.type_variant(id, name, variant, &ty.docs), 1454 TypeDefKind::Option(t) => self.type_option(id, name, t, &ty.docs), 1455 TypeDefKind::Result(r) => self.type_result(id, name, r, &ty.docs), 1456 TypeDefKind::List(t) => self.type_list(id, name, t, &ty.docs), 1457 TypeDefKind::Type(t) => self.type_alias(id, name, t, &ty.docs), 1458 TypeDefKind::Future(_) => todo!("generate for future"), 1459 TypeDefKind::Stream(_) => todo!("generate for stream"), 1460 TypeDefKind::Handle(handle) => self.type_handle(id, name, handle, &ty.docs), 1461 TypeDefKind::Resource => self.type_resource(id, name, ty, &ty.docs), 1462 TypeDefKind::Unknown => unreachable!(), 1463 } 1464 } 1465 1466 fn type_handle(&mut self, id: TypeId, name: &str, handle: &Handle, docs: &Docs) { 1467 self.rustdoc(docs); 1468 let name = name.to_upper_camel_case(); 1469 uwriteln!(self.src, "pub type {name} = "); 1470 self.print_handle(handle); 1471 self.push_str(";\n"); 1472 self.assert_type(id, &name); 1473 } 1474 1475 fn type_resource(&mut self, id: TypeId, name: &str, resource: &TypeDef, docs: &Docs) { 1476 let camel = name.to_upper_camel_case(); 1477 let wt = self.gen.wasmtime_path(); 1478 1479 if self.types_imported() { 1480 self.rustdoc(docs); 1481 1482 let replacement = match self.current_interface { 1483 Some((_, key, _)) => self.gen.lookup_replacement(self.resolve, key, Some(name)), 1484 None => { 1485 self.gen.used_with_opts.insert(name.into()); 1486 self.gen.opts.with.get(name).cloned() 1487 } 1488 }; 1489 match replacement { 1490 Some(path) => { 1491 uwriteln!( 1492 self.src, 1493 "pub use {}{path} as {camel};", 1494 self.path_to_root() 1495 ); 1496 } 1497 None => { 1498 uwriteln!(self.src, "pub enum {camel} {{}}"); 1499 } 1500 } 1501 1502 // Generate resource trait 1503 if self.gen.opts.async_.maybe_async() { 1504 uwriteln!(self.src, "#[{wt}::component::__internal::async_trait]") 1505 } 1506 uwriteln!(self.src, "pub trait Host{camel} {{"); 1507 1508 let mut functions = match resource.owner { 1509 TypeOwner::World(id) => self.resolve.worlds[id] 1510 .imports 1511 .values() 1512 .filter_map(|item| match item { 1513 WorldItem::Function(f) => Some(f), 1514 _ => None, 1515 }) 1516 .collect(), 1517 TypeOwner::Interface(id) => self.resolve.interfaces[id] 1518 .functions 1519 .values() 1520 .collect::<Vec<_>>(), 1521 TypeOwner::None => { 1522 panic!("A resource must be owned by a world or interface"); 1523 } 1524 }; 1525 1526 functions.retain(|func| match func.kind { 1527 FunctionKind::Freestanding => false, 1528 FunctionKind::Method(resource) 1529 | FunctionKind::Static(resource) 1530 | FunctionKind::Constructor(resource) => id == resource, 1531 }); 1532 1533 for func in &functions { 1534 self.generate_function_trait_sig(func); 1535 self.push_str(";\n"); 1536 } 1537 1538 if self.gen.opts.async_.is_drop_async(name) { 1539 uwrite!(self.src, "async "); 1540 } 1541 uwrite!( 1542 self.src, 1543 "fn drop(&mut self, rep: {wt}::component::Resource<{camel}>) -> {wt}::Result<()>;" 1544 ); 1545 1546 uwriteln!(self.src, "}}"); 1547 1548 // Generate impl HostResource for &mut HostResource 1549 if !self.gen.opts.skip_mut_forwarding_impls { 1550 let (async_trait, maybe_send) = if self.gen.opts.async_.maybe_async() { 1551 ( 1552 format!("#[{wt}::component::__internal::async_trait]\n"), 1553 "+ Send", 1554 ) 1555 } else { 1556 (String::new(), "") 1557 }; 1558 uwriteln!( 1559 self.src, 1560 "{async_trait}impl <_T: Host{camel} + ?Sized {maybe_send}> Host{camel} for &mut _T {{" 1561 ); 1562 for func in &functions { 1563 self.generate_function_trait_sig(func); 1564 uwrite!( 1565 self.src, 1566 "{{ Host{camel}::{}(*self,", 1567 rust_function_name(func) 1568 ); 1569 for (name, _) in func.params.iter() { 1570 uwrite!(self.src, "{},", to_rust_ident(name)); 1571 } 1572 uwrite!(self.src, ")"); 1573 if self.gen.opts.async_.is_import_async(&func.name) { 1574 uwrite!(self.src, ".await"); 1575 } 1576 uwriteln!(self.src, "}}"); 1577 } 1578 if self.gen.opts.async_.is_drop_async(name) { 1579 uwriteln!(self.src, " 1580 async fn drop(&mut self, rep: {wt}::component::Resource<{camel}>) -> {wt}::Result<()> {{ 1581 Host{camel}::drop(*self, rep).await 1582 }}", 1583 ); 1584 } else { 1585 uwriteln!(self.src, " 1586 fn drop(&mut self, rep: {wt}::component::Resource<{camel}>) -> {wt}::Result<()> {{ 1587 Host{camel}::drop(*self, rep) 1588 }}", 1589 ); 1590 } 1591 uwriteln!(self.src, "}}"); 1592 } 1593 } else { 1594 self.rustdoc(docs); 1595 uwriteln!( 1596 self.src, 1597 " 1598 pub type {camel} = {wt}::component::ResourceAny; 1599 1600 pub struct Guest{camel}<'a> {{ 1601 funcs: &'a Guest, 1602 }} 1603 " 1604 ); 1605 } 1606 } 1607 1608 fn type_record(&mut self, id: TypeId, _name: &str, record: &Record, docs: &Docs) { 1609 let info = self.info(id); 1610 let wt = self.gen.wasmtime_path(); 1611 1612 // We use a BTree set to make sure we don't have any duplicates and we have a stable order 1613 let additional_derives: BTreeSet<String> = self 1614 .gen 1615 .opts 1616 .additional_derive_attributes 1617 .iter() 1618 .cloned() 1619 .collect(); 1620 1621 for (name, mode) in self.modes_of(id) { 1622 let lt = self.lifetime_for(&info, mode); 1623 self.rustdoc(docs); 1624 1625 let mut derives = additional_derives.clone(); 1626 1627 uwriteln!(self.src, "#[derive({wt}::component::ComponentType)]"); 1628 if lt.is_none() { 1629 uwriteln!(self.src, "#[derive({wt}::component::Lift)]"); 1630 } 1631 uwriteln!(self.src, "#[derive({wt}::component::Lower)]"); 1632 self.push_str("#[component(record)]\n"); 1633 if let Some(path) = &self.gen.opts.wasmtime_crate { 1634 uwriteln!(self.src, "#[component(wasmtime_crate = {path})]\n"); 1635 } 1636 1637 if info.is_copy() { 1638 derives.extend(["Copy", "Clone"].into_iter().map(|s| s.to_string())); 1639 } else if info.is_clone() { 1640 derives.insert("Clone".to_string()); 1641 } 1642 1643 if !derives.is_empty() { 1644 self.push_str("#[derive("); 1645 self.push_str(&derives.into_iter().collect::<Vec<_>>().join(", ")); 1646 self.push_str(")]\n") 1647 } 1648 1649 self.push_str(&format!("pub struct {name}")); 1650 self.print_generics(lt); 1651 self.push_str(" {\n"); 1652 for field in record.fields.iter() { 1653 self.rustdoc(&field.docs); 1654 self.push_str(&format!("#[component(name = \"{}\")]\n", field.name)); 1655 self.push_str("pub "); 1656 self.push_str(&to_rust_ident(&field.name)); 1657 self.push_str(": "); 1658 self.print_ty(&field.ty, mode); 1659 self.push_str(",\n"); 1660 } 1661 self.push_str("}\n"); 1662 1663 self.push_str("impl"); 1664 self.print_generics(lt); 1665 self.push_str(" core::fmt::Debug for "); 1666 self.push_str(&name); 1667 self.print_generics(lt); 1668 self.push_str(" {\n"); 1669 self.push_str( 1670 "fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n", 1671 ); 1672 self.push_str(&format!("f.debug_struct(\"{name}\")")); 1673 for field in record.fields.iter() { 1674 self.push_str(&format!( 1675 ".field(\"{}\", &self.{})", 1676 field.name, 1677 to_rust_ident(&field.name) 1678 )); 1679 } 1680 self.push_str(".finish()\n"); 1681 self.push_str("}\n"); 1682 self.push_str("}\n"); 1683 1684 if info.error { 1685 self.push_str("impl"); 1686 self.print_generics(lt); 1687 self.push_str(" core::fmt::Display for "); 1688 self.push_str(&name); 1689 self.print_generics(lt); 1690 self.push_str(" {\n"); 1691 self.push_str( 1692 "fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n", 1693 ); 1694 self.push_str("write!(f, \"{:?}\", self)\n"); 1695 self.push_str("}\n"); 1696 self.push_str("}\n"); 1697 1698 if cfg!(feature = "std") { 1699 self.push_str("impl std::error::Error for "); 1700 self.push_str(&name); 1701 self.push_str("{}\n"); 1702 } 1703 } 1704 self.assert_type(id, &name); 1705 } 1706 } 1707 1708 fn type_tuple(&mut self, id: TypeId, _name: &str, tuple: &Tuple, docs: &Docs) { 1709 let info = self.info(id); 1710 for (name, mode) in self.modes_of(id) { 1711 let lt = self.lifetime_for(&info, mode); 1712 self.rustdoc(docs); 1713 self.push_str(&format!("pub type {name}")); 1714 self.print_generics(lt); 1715 self.push_str(" = ("); 1716 for ty in tuple.types.iter() { 1717 self.print_ty(ty, mode); 1718 self.push_str(","); 1719 } 1720 self.push_str(");\n"); 1721 self.assert_type(id, &name); 1722 } 1723 } 1724 1725 fn type_flags(&mut self, id: TypeId, name: &str, flags: &Flags, docs: &Docs) { 1726 self.rustdoc(docs); 1727 let wt = self.gen.wasmtime_path(); 1728 let rust_name = to_rust_upper_camel_case(name); 1729 uwriteln!(self.src, "{wt}::component::flags!(\n"); 1730 self.src.push_str(&format!("{rust_name} {{\n")); 1731 for flag in flags.flags.iter() { 1732 // TODO wasmtime-component-macro doesn't support docs for flags rn 1733 uwrite!( 1734 self.src, 1735 "#[component(name=\"{}\")] const {};\n", 1736 flag.name, 1737 flag.name.to_shouty_snake_case() 1738 ); 1739 } 1740 self.src.push_str("}\n"); 1741 self.src.push_str(");\n\n"); 1742 self.assert_type(id, &rust_name); 1743 } 1744 1745 fn type_variant(&mut self, id: TypeId, _name: &str, variant: &Variant, docs: &Docs) { 1746 self.print_rust_enum( 1747 id, 1748 variant.cases.iter().map(|c| { 1749 ( 1750 c.name.to_upper_camel_case(), 1751 Some(c.name.clone()), 1752 &c.docs, 1753 c.ty.as_ref(), 1754 ) 1755 }), 1756 docs, 1757 "variant", 1758 ); 1759 } 1760 1761 fn type_option(&mut self, id: TypeId, _name: &str, payload: &Type, docs: &Docs) { 1762 let info = self.info(id); 1763 1764 for (name, mode) in self.modes_of(id) { 1765 self.rustdoc(docs); 1766 let lt = self.lifetime_for(&info, mode); 1767 self.push_str(&format!("pub type {name}")); 1768 self.print_generics(lt); 1769 self.push_str("= Option<"); 1770 self.print_ty(payload, mode); 1771 self.push_str(">;\n"); 1772 self.assert_type(id, &name); 1773 } 1774 } 1775 1776 // Emit a double-check that the wit-parser-understood size of a type agrees 1777 // with the Wasmtime-understood size of a type. 1778 fn assert_type(&mut self, id: TypeId, name: &str) { 1779 self.push_str("const _: () = {\n"); 1780 let wt = self.gen.wasmtime_path(); 1781 uwriteln!( 1782 self.src, 1783 "assert!({} == <{name} as {wt}::component::ComponentType>::SIZE32);", 1784 self.gen.sizes.size(&Type::Id(id)).size_wasm32(), 1785 ); 1786 uwriteln!( 1787 self.src, 1788 "assert!({} == <{name} as {wt}::component::ComponentType>::ALIGN32);", 1789 self.gen.sizes.align(&Type::Id(id)).align_wasm32(), 1790 ); 1791 self.push_str("};\n"); 1792 } 1793 1794 fn print_rust_enum<'b>( 1795 &mut self, 1796 id: TypeId, 1797 cases: impl IntoIterator<Item = (String, Option<String>, &'b Docs, Option<&'b Type>)> + Clone, 1798 docs: &Docs, 1799 derive_component: &str, 1800 ) where 1801 Self: Sized, 1802 { 1803 let info = self.info(id); 1804 let wt = self.gen.wasmtime_path(); 1805 1806 // We use a BTree set to make sure we don't have any duplicates and we have a stable order 1807 let additional_derives: BTreeSet<String> = self 1808 .gen 1809 .opts 1810 .additional_derive_attributes 1811 .iter() 1812 .cloned() 1813 .collect(); 1814 1815 for (name, mode) in self.modes_of(id) { 1816 let name = to_rust_upper_camel_case(&name); 1817 1818 let mut derives = additional_derives.clone(); 1819 1820 self.rustdoc(docs); 1821 let lt = self.lifetime_for(&info, mode); 1822 uwriteln!(self.src, "#[derive({wt}::component::ComponentType)]"); 1823 if lt.is_none() { 1824 uwriteln!(self.src, "#[derive({wt}::component::Lift)]"); 1825 } 1826 uwriteln!(self.src, "#[derive({wt}::component::Lower)]"); 1827 self.push_str(&format!("#[component({derive_component})]\n")); 1828 if let Some(path) = &self.gen.opts.wasmtime_crate { 1829 uwriteln!(self.src, "#[component(wasmtime_crate = {path})]\n"); 1830 } 1831 if info.is_copy() { 1832 derives.extend(["Copy", "Clone"].into_iter().map(|s| s.to_string())); 1833 } else if info.is_clone() { 1834 derives.insert("Clone".to_string()); 1835 } 1836 1837 if !derives.is_empty() { 1838 self.push_str("#[derive("); 1839 self.push_str(&derives.into_iter().collect::<Vec<_>>().join(", ")); 1840 self.push_str(")]\n") 1841 } 1842 1843 self.push_str(&format!("pub enum {name}")); 1844 self.print_generics(lt); 1845 self.push_str("{\n"); 1846 for (case_name, component_name, docs, payload) in cases.clone() { 1847 self.rustdoc(docs); 1848 if let Some(n) = component_name { 1849 self.push_str(&format!("#[component(name = \"{n}\")] ")); 1850 } 1851 self.push_str(&case_name); 1852 if let Some(ty) = payload { 1853 self.push_str("("); 1854 self.print_ty(ty, mode); 1855 self.push_str(")") 1856 } 1857 self.push_str(",\n"); 1858 } 1859 self.push_str("}\n"); 1860 1861 self.print_rust_enum_debug( 1862 id, 1863 mode, 1864 &name, 1865 cases 1866 .clone() 1867 .into_iter() 1868 .map(|(name, _attr, _docs, ty)| (name, ty)), 1869 ); 1870 1871 if info.error { 1872 self.push_str("impl"); 1873 self.print_generics(lt); 1874 self.push_str(" core::fmt::Display for "); 1875 self.push_str(&name); 1876 self.print_generics(lt); 1877 self.push_str(" {\n"); 1878 self.push_str( 1879 "fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n", 1880 ); 1881 self.push_str("write!(f, \"{:?}\", self)"); 1882 self.push_str("}\n"); 1883 self.push_str("}\n"); 1884 self.push_str("\n"); 1885 1886 if cfg!(feature = "std") { 1887 self.push_str("impl"); 1888 self.print_generics(lt); 1889 self.push_str(" std::error::Error for "); 1890 self.push_str(&name); 1891 self.print_generics(lt); 1892 self.push_str(" {}\n"); 1893 } 1894 } 1895 1896 self.assert_type(id, &name); 1897 } 1898 } 1899 1900 fn print_rust_enum_debug<'b>( 1901 &mut self, 1902 id: TypeId, 1903 mode: TypeMode, 1904 name: &str, 1905 cases: impl IntoIterator<Item = (String, Option<&'b Type>)>, 1906 ) where 1907 Self: Sized, 1908 { 1909 let info = self.info(id); 1910 let lt = self.lifetime_for(&info, mode); 1911 self.push_str("impl"); 1912 self.print_generics(lt); 1913 self.push_str(" core::fmt::Debug for "); 1914 self.push_str(name); 1915 self.print_generics(lt); 1916 self.push_str(" {\n"); 1917 self.push_str("fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n"); 1918 self.push_str("match self {\n"); 1919 for (case_name, payload) in cases { 1920 self.push_str(name); 1921 self.push_str("::"); 1922 self.push_str(&case_name); 1923 if payload.is_some() { 1924 self.push_str("(e)"); 1925 } 1926 self.push_str(" => {\n"); 1927 self.push_str(&format!("f.debug_tuple(\"{name}::{case_name}\")")); 1928 if payload.is_some() { 1929 self.push_str(".field(e)"); 1930 } 1931 self.push_str(".finish()\n"); 1932 self.push_str("}\n"); 1933 } 1934 self.push_str("}\n"); 1935 self.push_str("}\n"); 1936 self.push_str("}\n"); 1937 } 1938 1939 fn type_result(&mut self, id: TypeId, _name: &str, result: &Result_, docs: &Docs) { 1940 let info = self.info(id); 1941 1942 for (name, mode) in self.modes_of(id) { 1943 self.rustdoc(docs); 1944 let lt = self.lifetime_for(&info, mode); 1945 self.push_str(&format!("pub type {name}")); 1946 self.print_generics(lt); 1947 self.push_str("= Result<"); 1948 self.print_optional_ty(result.ok.as_ref(), mode); 1949 self.push_str(","); 1950 self.print_optional_ty(result.err.as_ref(), mode); 1951 self.push_str(">;\n"); 1952 self.assert_type(id, &name); 1953 } 1954 } 1955 1956 fn type_enum(&mut self, id: TypeId, name: &str, enum_: &Enum, docs: &Docs) { 1957 let info = self.info(id); 1958 let wt = self.gen.wasmtime_path(); 1959 1960 // We use a BTree set to make sure we don't have any duplicates and have a stable order 1961 let mut derives: BTreeSet<String> = self 1962 .gen 1963 .opts 1964 .additional_derive_attributes 1965 .iter() 1966 .cloned() 1967 .collect(); 1968 1969 derives.extend( 1970 ["Clone", "Copy", "PartialEq", "Eq"] 1971 .into_iter() 1972 .map(|s| s.to_string()), 1973 ); 1974 1975 let name = to_rust_upper_camel_case(name); 1976 self.rustdoc(docs); 1977 uwriteln!(self.src, "#[derive({wt}::component::ComponentType)]"); 1978 uwriteln!(self.src, "#[derive({wt}::component::Lift)]"); 1979 uwriteln!(self.src, "#[derive({wt}::component::Lower)]"); 1980 self.push_str("#[component(enum)]\n"); 1981 if let Some(path) = &self.gen.opts.wasmtime_crate { 1982 uwriteln!(self.src, "#[component(wasmtime_crate = {path})]\n"); 1983 } 1984 1985 self.push_str("#[derive("); 1986 self.push_str(&derives.into_iter().collect::<Vec<_>>().join(", ")); 1987 self.push_str(")]\n"); 1988 1989 let repr = match enum_.cases.len().ilog2() { 1990 0..=7 => "u8", 1991 8..=15 => "u16", 1992 _ => "u32", 1993 }; 1994 uwriteln!(self.src, "#[repr({repr})]"); 1995 1996 self.push_str(&format!("pub enum {name} {{\n")); 1997 for case in enum_.cases.iter() { 1998 self.rustdoc(&case.docs); 1999 self.push_str(&format!("#[component(name = \"{}\")]", case.name)); 2000 self.push_str(&case.name.to_upper_camel_case()); 2001 self.push_str(",\n"); 2002 } 2003 self.push_str("}\n"); 2004 2005 // Auto-synthesize an implementation of the standard `Error` trait for 2006 // error-looking types based on their name. 2007 if info.error { 2008 self.push_str("impl "); 2009 self.push_str(&name); 2010 self.push_str("{\n"); 2011 2012 self.push_str("pub fn name(&self) -> &'static str {\n"); 2013 self.push_str("match self {\n"); 2014 for case in enum_.cases.iter() { 2015 self.push_str(&name); 2016 self.push_str("::"); 2017 self.push_str(&case.name.to_upper_camel_case()); 2018 self.push_str(" => \""); 2019 self.push_str(case.name.as_str()); 2020 self.push_str("\",\n"); 2021 } 2022 self.push_str("}\n"); 2023 self.push_str("}\n"); 2024 2025 self.push_str("pub fn message(&self) -> &'static str {\n"); 2026 self.push_str("match self {\n"); 2027 for case in enum_.cases.iter() { 2028 self.push_str(&name); 2029 self.push_str("::"); 2030 self.push_str(&case.name.to_upper_camel_case()); 2031 self.push_str(" => \""); 2032 if let Some(contents) = &case.docs.contents { 2033 self.push_str(contents.trim()); 2034 } 2035 self.push_str("\",\n"); 2036 } 2037 self.push_str("}\n"); 2038 self.push_str("}\n"); 2039 2040 self.push_str("}\n"); 2041 2042 self.push_str("impl core::fmt::Debug for "); 2043 self.push_str(&name); 2044 self.push_str( 2045 "{\nfn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n", 2046 ); 2047 self.push_str("f.debug_struct(\""); 2048 self.push_str(&name); 2049 self.push_str("\")\n"); 2050 self.push_str(".field(\"code\", &(*self as i32))\n"); 2051 self.push_str(".field(\"name\", &self.name())\n"); 2052 self.push_str(".field(\"message\", &self.message())\n"); 2053 self.push_str(".finish()\n"); 2054 self.push_str("}\n"); 2055 self.push_str("}\n"); 2056 2057 self.push_str("impl core::fmt::Display for "); 2058 self.push_str(&name); 2059 self.push_str( 2060 "{\nfn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n", 2061 ); 2062 self.push_str("write!(f, \"{} (error {})\", self.name(), *self as i32)"); 2063 self.push_str("}\n"); 2064 self.push_str("}\n"); 2065 self.push_str("\n"); 2066 if cfg!(feature = "std") { 2067 self.push_str("impl std::error::Error for "); 2068 self.push_str(&name); 2069 self.push_str("{}\n"); 2070 } 2071 } else { 2072 self.print_rust_enum_debug( 2073 id, 2074 TypeMode::Owned, 2075 &name, 2076 enum_ 2077 .cases 2078 .iter() 2079 .map(|c| (c.name.to_upper_camel_case(), None)), 2080 ) 2081 } 2082 self.assert_type(id, &name); 2083 } 2084 2085 fn type_alias(&mut self, id: TypeId, _name: &str, ty: &Type, docs: &Docs) { 2086 let info = self.info(id); 2087 for (name, mode) in self.modes_of(id) { 2088 self.rustdoc(docs); 2089 self.push_str(&format!("pub type {name}")); 2090 let lt = self.lifetime_for(&info, mode); 2091 self.print_generics(lt); 2092 self.push_str(" = "); 2093 self.print_ty(ty, mode); 2094 self.push_str(";\n"); 2095 let def_id = resolve_type_definition_id(self.resolve, id); 2096 if !matches!(self.resolve().types[def_id].kind, TypeDefKind::Resource) { 2097 self.assert_type(id, &name); 2098 } 2099 } 2100 } 2101 2102 fn type_list(&mut self, id: TypeId, _name: &str, ty: &Type, docs: &Docs) { 2103 let info = self.info(id); 2104 for (name, mode) in self.modes_of(id) { 2105 let lt = self.lifetime_for(&info, mode); 2106 self.rustdoc(docs); 2107 self.push_str(&format!("pub type {name}")); 2108 self.print_generics(lt); 2109 self.push_str(" = "); 2110 self.print_list(ty, mode); 2111 self.push_str(";\n"); 2112 self.assert_type(id, &name); 2113 } 2114 } 2115 2116 fn print_result_ty(&mut self, results: &Results, mode: TypeMode) { 2117 match results { 2118 Results::Named(rs) => match rs.len() { 2119 0 => self.push_str("()"), 2120 1 => self.print_ty(&rs[0].1, mode), 2121 _ => { 2122 self.push_str("("); 2123 for (i, (_, ty)) in rs.iter().enumerate() { 2124 if i > 0 { 2125 self.push_str(", ") 2126 } 2127 self.print_ty(ty, mode) 2128 } 2129 self.push_str(")"); 2130 } 2131 }, 2132 Results::Anon(ty) => self.print_ty(ty, mode), 2133 } 2134 } 2135 2136 fn special_case_trappable_error( 2137 &mut self, 2138 func: &Function, 2139 ) -> Option<(&'a Result_, TypeId, String)> { 2140 let results = &func.results; 2141 2142 self.gen 2143 .used_trappable_imports_opts 2144 .insert(func.name.clone()); 2145 2146 // We fillin a special trappable error type in the case when a function has just one 2147 // result, which is itself a `result<a, e>`, and the `e` is *not* a primitive 2148 // (i.e. defined in std) type, and matches the typename given by the user. 2149 let mut i = results.iter_types(); 2150 let id = match i.next()? { 2151 Type::Id(id) => id, 2152 _ => return None, 2153 }; 2154 if i.next().is_some() { 2155 return None; 2156 } 2157 let result = match &self.resolve.types[*id].kind { 2158 TypeDefKind::Result(r) => r, 2159 _ => return None, 2160 }; 2161 let error_typeid = match result.err? { 2162 Type::Id(id) => resolve_type_definition_id(&self.resolve, id), 2163 _ => return None, 2164 }; 2165 2166 let name = self.gen.trappable_errors.get(&error_typeid)?; 2167 2168 let mut path = self.path_to_root(); 2169 uwrite!(path, "{name}"); 2170 Some((result, error_typeid, path)) 2171 } 2172 2173 fn generate_add_to_linker(&mut self, id: InterfaceId, name: &str) { 2174 let iface = &self.resolve.interfaces[id]; 2175 let owner = TypeOwner::Interface(id); 2176 let wt = self.gen.wasmtime_path(); 2177 2178 let is_maybe_async = self.gen.opts.async_.maybe_async(); 2179 if is_maybe_async { 2180 uwriteln!(self.src, "#[{wt}::component::__internal::async_trait]") 2181 } 2182 // Generate the `pub trait` which represents the host functionality for 2183 // this import which additionally inherits from all resource traits 2184 // for this interface defined by `type_resource`. 2185 uwrite!(self.src, "pub trait Host"); 2186 let mut host_supertraits = vec![]; 2187 if is_maybe_async { 2188 host_supertraits.push("Send".to_string()); 2189 } 2190 for resource in get_resources(self.resolve, id) { 2191 host_supertraits.push(format!("Host{}", resource.to_upper_camel_case())); 2192 } 2193 if !host_supertraits.is_empty() { 2194 uwrite!(self.src, ": {}", host_supertraits.join(" + ")); 2195 } 2196 uwriteln!(self.src, " {{"); 2197 for (_, func) in iface.functions.iter() { 2198 match func.kind { 2199 FunctionKind::Freestanding => {} 2200 _ => continue, 2201 } 2202 self.generate_function_trait_sig(func); 2203 self.push_str(";\n"); 2204 } 2205 2206 // Generate `convert_*` functions to convert custom trappable errors 2207 // into the representation required by Wasmtime's component API. 2208 let mut required_conversion_traits = IndexSet::new(); 2209 let mut errors_converted = IndexMap::new(); 2210 let mut my_error_types = iface 2211 .types 2212 .iter() 2213 .filter(|(_, id)| self.gen.trappable_errors.contains_key(*id)) 2214 .map(|(_, id)| *id) 2215 .collect::<Vec<_>>(); 2216 my_error_types.extend( 2217 iface 2218 .functions 2219 .iter() 2220 .filter_map(|(_, func)| self.special_case_trappable_error(func)) 2221 .map(|(_, id, _)| id), 2222 ); 2223 let root = self.path_to_root(); 2224 for err_id in my_error_types { 2225 let custom_name = &self.gen.trappable_errors[&err_id]; 2226 let err = &self.resolve.types[resolve_type_definition_id(self.resolve, err_id)]; 2227 let err_name = err.name.as_ref().unwrap(); 2228 let err_snake = err_name.to_snake_case(); 2229 let err_camel = err_name.to_upper_camel_case(); 2230 let owner = match err.owner { 2231 TypeOwner::Interface(i) => i, 2232 _ => unimplemented!(), 2233 }; 2234 match self.path_to_interface(owner) { 2235 Some(path) => { 2236 required_conversion_traits.insert(format!("{path}::Host")); 2237 } 2238 None => { 2239 if errors_converted.insert(err_name, err_id).is_none() { 2240 uwriteln!( 2241 self.src, 2242 "fn convert_{err_snake}(&mut self, err: {root}{custom_name}) -> {wt}::Result<{err_camel}>;" 2243 ); 2244 } 2245 } 2246 } 2247 } 2248 uwriteln!(self.src, "}}"); 2249 2250 let (data_bounds, mut host_bounds) = if self.gen.opts.is_store_data_send() { 2251 ("T: Send,", "Host + Send".to_string()) 2252 } else { 2253 ("", "Host".to_string()) 2254 }; 2255 for ty in required_conversion_traits { 2256 uwrite!(host_bounds, " + {ty}"); 2257 } 2258 2259 uwriteln!( 2260 self.src, 2261 " 2262 pub trait GetHost<T>: 2263 Fn(T) -> <Self as GetHost<T>>::Host 2264 + Send 2265 + Sync 2266 + Copy 2267 + 'static 2268 {{ 2269 type Host: {host_bounds}; 2270 }} 2271 2272 impl<F, T, O> GetHost<T> for F 2273 where 2274 F: Fn(T) -> O + Send + Sync + Copy + 'static, 2275 O: {host_bounds}, 2276 {{ 2277 type Host = O; 2278 }} 2279 2280 pub fn add_to_linker_get_host<T>( 2281 linker: &mut {wt}::component::Linker<T>, 2282 host_getter: impl for<'a> GetHost<&'a mut T>, 2283 ) -> {wt}::Result<()> 2284 where {data_bounds} 2285 {{ 2286 " 2287 ); 2288 uwriteln!(self.src, "let mut inst = linker.instance(\"{name}\")?;"); 2289 2290 for name in get_resources(self.resolve, id) { 2291 Wasmtime::generate_add_resource_to_linker( 2292 &mut self.src, 2293 &self.gen.opts, 2294 &wt, 2295 "inst", 2296 name, 2297 ); 2298 } 2299 2300 for (_, func) in iface.functions.iter() { 2301 self.generate_add_function_to_linker(owner, func, "inst"); 2302 } 2303 uwriteln!(self.src, "Ok(())"); 2304 uwriteln!(self.src, "}}"); 2305 2306 if !self.gen.opts.skip_mut_forwarding_impls { 2307 // Generate add_to_linker (with closure) 2308 uwriteln!( 2309 self.src, 2310 " 2311 pub fn add_to_linker<T, U>( 2312 linker: &mut {wt}::component::Linker<T>, 2313 get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static, 2314 ) -> {wt}::Result<()> 2315 where 2316 U: {host_bounds}, {data_bounds} 2317 {{ 2318 add_to_linker_get_host(linker, get) 2319 }} 2320 " 2321 ); 2322 2323 // Generate impl Host for &mut Host 2324 let (async_trait, maybe_send) = if is_maybe_async { 2325 ( 2326 format!("#[{wt}::component::__internal::async_trait]"), 2327 "+ Send", 2328 ) 2329 } else { 2330 (String::new(), "") 2331 }; 2332 2333 uwriteln!( 2334 self.src, 2335 "{async_trait}impl<_T: Host + ?Sized {maybe_send}> Host for &mut _T {{" 2336 ); 2337 // Forward each method call to &mut T 2338 for (_, func) in iface.functions.iter() { 2339 match func.kind { 2340 FunctionKind::Freestanding => {} 2341 _ => continue, 2342 } 2343 self.generate_function_trait_sig(func); 2344 uwrite!(self.src, "{{ Host::{}(*self,", rust_function_name(func)); 2345 for (name, _) in func.params.iter() { 2346 uwrite!(self.src, "{},", to_rust_ident(name)); 2347 } 2348 uwrite!(self.src, ")"); 2349 if self.gen.opts.async_.is_import_async(&func.name) { 2350 uwrite!(self.src, ".await"); 2351 } 2352 uwriteln!(self.src, "}}"); 2353 } 2354 for (err_name, err_id) in errors_converted { 2355 uwriteln!( 2356 self.src, 2357 "fn convert_{err_snake}(&mut self, err: {root}{custom_name}) -> {wt}::Result<{err_camel}> {{ 2358 Host::convert_{err_snake}(*self, err) 2359 }}", 2360 custom_name = self.gen.trappable_errors[&err_id], 2361 err_snake = err_name.to_snake_case(), 2362 err_camel = err_name.to_upper_camel_case(), 2363 ); 2364 } 2365 uwriteln!(self.src, "}}"); 2366 } 2367 } 2368 2369 fn generate_add_function_to_linker(&mut self, owner: TypeOwner, func: &Function, linker: &str) { 2370 uwrite!( 2371 self.src, 2372 "{linker}.{}(\"{}\", ", 2373 if self.gen.opts.async_.is_import_async(&func.name) { 2374 "func_wrap_async" 2375 } else { 2376 "func_wrap" 2377 }, 2378 func.name 2379 ); 2380 self.generate_guest_import_closure(owner, func); 2381 uwriteln!(self.src, ")?;") 2382 } 2383 2384 fn generate_guest_import_closure(&mut self, owner: TypeOwner, func: &Function) { 2385 // Generate the closure that's passed to a `Linker`, the final piece of 2386 // codegen here. 2387 2388 let wt = self.gen.wasmtime_path(); 2389 uwrite!( 2390 self.src, 2391 "move |mut caller: {wt}::StoreContextMut<'_, T>, (" 2392 ); 2393 for (i, _param) in func.params.iter().enumerate() { 2394 uwrite!(self.src, "arg{},", i); 2395 } 2396 self.src.push_str(") : ("); 2397 2398 for (_, ty) in func.params.iter() { 2399 // Lift is required to be impled for this type, so we can't use 2400 // a borrowed type: 2401 self.print_ty(ty, TypeMode::Owned); 2402 self.src.push_str(", "); 2403 } 2404 self.src.push_str(") |"); 2405 if self.gen.opts.async_.is_import_async(&func.name) { 2406 uwriteln!( 2407 self.src, 2408 " {wt}::component::__internal::Box::new(async move {{ " 2409 ); 2410 } else { 2411 self.src.push_str(" { \n"); 2412 } 2413 2414 if self.gen.opts.tracing { 2415 uwrite!( 2416 self.src, 2417 " 2418 let span = tracing::span!( 2419 tracing::Level::TRACE, 2420 \"wit-bindgen import\", 2421 module = \"{}\", 2422 function = \"{}\", 2423 ); 2424 let _enter = span.enter(); 2425 ", 2426 match owner { 2427 TypeOwner::Interface(id) => self.resolve.interfaces[id] 2428 .name 2429 .as_deref() 2430 .unwrap_or("<no module>"), 2431 TypeOwner::World(id) => &self.resolve.worlds[id].name, 2432 TypeOwner::None => "<no owner>", 2433 }, 2434 func.name, 2435 ); 2436 let mut event_fields = func 2437 .params 2438 .iter() 2439 .enumerate() 2440 .map(|(i, (name, _ty))| { 2441 let name = to_rust_ident(&name); 2442 format!("{name} = tracing::field::debug(&arg{i})") 2443 }) 2444 .collect::<Vec<String>>(); 2445 event_fields.push(format!("\"call\"")); 2446 uwrite!( 2447 self.src, 2448 "tracing::event!(tracing::Level::TRACE, {});\n", 2449 event_fields.join(", ") 2450 ); 2451 } 2452 2453 self.src 2454 .push_str("let host = &mut host_getter(caller.data_mut());\n"); 2455 let func_name = rust_function_name(func); 2456 let host_trait = match func.kind { 2457 FunctionKind::Freestanding => match owner { 2458 TypeOwner::World(id) => format!( 2459 "{}Imports", 2460 self.resolve.worlds[id].name.to_upper_camel_case() 2461 ), 2462 _ => "Host".to_string(), 2463 }, 2464 FunctionKind::Method(id) | FunctionKind::Static(id) | FunctionKind::Constructor(id) => { 2465 let resource = self.resolve.types[id] 2466 .name 2467 .as_ref() 2468 .unwrap() 2469 .to_upper_camel_case(); 2470 format!("Host{resource}") 2471 } 2472 }; 2473 uwrite!(self.src, "let r = {host_trait}::{func_name}(host, "); 2474 2475 for (i, _) in func.params.iter().enumerate() { 2476 uwrite!(self.src, "arg{},", i); 2477 } 2478 if self.gen.opts.async_.is_import_async(&func.name) { 2479 uwrite!(self.src, ").await;\n"); 2480 } else { 2481 uwrite!(self.src, ");\n"); 2482 } 2483 2484 if self.gen.opts.tracing { 2485 uwrite!( 2486 self.src, 2487 "tracing::event!(tracing::Level::TRACE, result = tracing::field::debug(&r), \"return\");" 2488 ); 2489 } 2490 2491 if !self.gen.opts.trappable_imports.can_trap(&func) { 2492 if func.results.iter_types().len() == 1 { 2493 uwrite!(self.src, "Ok((r,))\n"); 2494 } else { 2495 uwrite!(self.src, "Ok(r)\n"); 2496 } 2497 } else if let Some((_, err, _)) = self.special_case_trappable_error(func) { 2498 let err = &self.resolve.types[resolve_type_definition_id(self.resolve, err)]; 2499 let err_name = err.name.as_ref().unwrap(); 2500 let owner = match err.owner { 2501 TypeOwner::Interface(i) => i, 2502 _ => unimplemented!(), 2503 }; 2504 let convert_trait = match self.path_to_interface(owner) { 2505 Some(path) => format!("{path}::Host"), 2506 None => format!("Host"), 2507 }; 2508 let convert = format!("{}::convert_{}", convert_trait, err_name.to_snake_case()); 2509 uwrite!( 2510 self.src, 2511 "Ok((match r {{ 2512 Ok(a) => Ok(a), 2513 Err(e) => Err({convert}(host, e)?), 2514 }},))" 2515 ); 2516 } else if func.results.iter_types().len() == 1 { 2517 uwrite!(self.src, "Ok((r?,))\n"); 2518 } else { 2519 uwrite!(self.src, "r\n"); 2520 } 2521 2522 if self.gen.opts.async_.is_import_async(&func.name) { 2523 // Need to close Box::new and async block 2524 self.src.push_str("})"); 2525 } else { 2526 self.src.push_str("}"); 2527 } 2528 } 2529 2530 fn generate_function_trait_sig(&mut self, func: &Function) { 2531 let wt = self.gen.wasmtime_path(); 2532 self.rustdoc(&func.docs); 2533 2534 if self.gen.opts.async_.is_import_async(&func.name) { 2535 self.push_str("async "); 2536 } 2537 self.push_str("fn "); 2538 self.push_str(&rust_function_name(func)); 2539 self.push_str("(&mut self, "); 2540 for (name, param) in func.params.iter() { 2541 let name = to_rust_ident(name); 2542 self.push_str(&name); 2543 self.push_str(": "); 2544 self.print_ty(param, TypeMode::Owned); 2545 self.push_str(","); 2546 } 2547 self.push_str(")"); 2548 self.push_str(" -> "); 2549 2550 if !self.gen.opts.trappable_imports.can_trap(func) { 2551 self.print_result_ty(&func.results, TypeMode::Owned); 2552 } else if let Some((r, _id, error_typename)) = self.special_case_trappable_error(func) { 2553 // Functions which have a single result `result<ok,err>` get special 2554 // cased to use the host_wasmtime_rust::Error<err>, making it possible 2555 // for them to trap or use `?` to propagate their errors 2556 self.push_str("Result<"); 2557 if let Some(ok) = r.ok { 2558 self.print_ty(&ok, TypeMode::Owned); 2559 } else { 2560 self.push_str("()"); 2561 } 2562 self.push_str(","); 2563 self.push_str(&error_typename); 2564 self.push_str(">"); 2565 } else { 2566 // All other functions get their return values wrapped in an wasmtime::Result. 2567 // Returning the anyhow::Error case can be used to trap. 2568 uwrite!(self.src, "{wt}::Result<"); 2569 self.print_result_ty(&func.results, TypeMode::Owned); 2570 self.push_str(">"); 2571 } 2572 } 2573 2574 fn extract_typed_function(&mut self, func: &Function) -> (String, String) { 2575 let prev = mem::take(&mut self.src); 2576 let snake = func_field_name(self.resolve, func); 2577 uwrite!(self.src, "*_instance.get_typed_func::<("); 2578 for (_, ty) in func.params.iter() { 2579 self.print_ty(ty, TypeMode::AllBorrowed("'_")); 2580 self.push_str(", "); 2581 } 2582 self.src.push_str("), ("); 2583 for ty in func.results.iter_types() { 2584 self.print_ty(ty, TypeMode::Owned); 2585 self.push_str(", "); 2586 } 2587 uwriteln!(self.src, ")>(&mut store, &self.{snake})?.func()"); 2588 2589 let ret = (snake, mem::take(&mut self.src).to_string()); 2590 self.src = prev; 2591 ret 2592 } 2593 2594 fn define_rust_guest_export( 2595 &mut self, 2596 resolve: &Resolve, 2597 ns: Option<&WorldKey>, 2598 func: &Function, 2599 ) { 2600 // Exports must be async if anything could be async, it's just imports 2601 // that get to be optionally async/sync. 2602 let is_async = self.gen.opts.async_.maybe_async(); 2603 2604 let (async_, async__, await_) = if is_async { 2605 ("async", "_async", ".await") 2606 } else { 2607 ("", "", "") 2608 }; 2609 2610 self.rustdoc(&func.docs); 2611 let wt = self.gen.wasmtime_path(); 2612 2613 uwrite!( 2614 self.src, 2615 "pub {async_} fn call_{}<S: {wt}::AsContextMut>(&self, mut store: S, ", 2616 func.item_name().to_snake_case(), 2617 ); 2618 2619 for (i, param) in func.params.iter().enumerate() { 2620 uwrite!(self.src, "arg{}: ", i); 2621 self.print_ty(¶m.1, TypeMode::AllBorrowed("'_")); 2622 self.push_str(","); 2623 } 2624 2625 uwrite!(self.src, ") -> {wt}::Result<"); 2626 self.print_result_ty(&func.results, TypeMode::Owned); 2627 2628 if is_async { 2629 uwriteln!(self.src, "> where <S as {wt}::AsContext>::Data: Send {{"); 2630 } else { 2631 self.src.push_str("> {\n"); 2632 } 2633 2634 if self.gen.opts.tracing { 2635 let ns = match ns { 2636 Some(key) => resolve.name_world_key(key), 2637 None => "default".to_string(), 2638 }; 2639 self.src.push_str(&format!( 2640 " 2641 let span = tracing::span!( 2642 tracing::Level::TRACE, 2643 \"wit-bindgen export\", 2644 module = \"{ns}\", 2645 function = \"{}\", 2646 ); 2647 let _enter = span.enter(); 2648 ", 2649 func.name, 2650 )); 2651 } 2652 2653 self.src.push_str("let callee = unsafe {\n"); 2654 uwrite!(self.src, "{wt}::component::TypedFunc::<("); 2655 for (_, ty) in func.params.iter() { 2656 self.print_ty(ty, TypeMode::AllBorrowed("'_")); 2657 self.push_str(", "); 2658 } 2659 self.src.push_str("), ("); 2660 for ty in func.results.iter_types() { 2661 self.print_ty(ty, TypeMode::Owned); 2662 self.push_str(", "); 2663 } 2664 let projection_to_func = match &func.kind { 2665 FunctionKind::Freestanding => "", 2666 _ => ".funcs", 2667 }; 2668 uwriteln!( 2669 self.src, 2670 ")>::new_unchecked(self{projection_to_func}.{})", 2671 func_field_name(self.resolve, func), 2672 ); 2673 self.src.push_str("};\n"); 2674 self.src.push_str("let ("); 2675 for (i, _) in func.results.iter_types().enumerate() { 2676 uwrite!(self.src, "ret{},", i); 2677 } 2678 uwrite!( 2679 self.src, 2680 ") = callee.call{async__}(store.as_context_mut(), (" 2681 ); 2682 for (i, _) in func.params.iter().enumerate() { 2683 uwrite!(self.src, "arg{}, ", i); 2684 } 2685 uwriteln!(self.src, ")){await_}?;"); 2686 2687 uwriteln!( 2688 self.src, 2689 "callee.post_return{async__}(store.as_context_mut()){await_}?;" 2690 ); 2691 2692 self.src.push_str("Ok("); 2693 if func.results.iter_types().len() == 1 { 2694 self.src.push_str("ret0"); 2695 } else { 2696 self.src.push_str("("); 2697 for (i, _) in func.results.iter_types().enumerate() { 2698 uwrite!(self.src, "ret{},", i); 2699 } 2700 self.src.push_str(")"); 2701 } 2702 self.src.push_str(")\n"); 2703 2704 // End function body 2705 self.src.push_str("}\n"); 2706 } 2707 2708 fn rustdoc(&mut self, docs: &Docs) { 2709 let docs = match &docs.contents { 2710 Some(docs) => docs, 2711 None => return, 2712 }; 2713 for line in docs.trim().lines() { 2714 self.push_str("/// "); 2715 self.push_str(line); 2716 self.push_str("\n"); 2717 } 2718 } 2719 2720 fn path_to_root(&self) -> String { 2721 let mut path_to_root = String::new(); 2722 if let Some((_, key, is_export)) = self.current_interface { 2723 match key { 2724 WorldKey::Name(_) => { 2725 path_to_root.push_str("super::"); 2726 } 2727 WorldKey::Interface(_) => { 2728 path_to_root.push_str("super::super::super::"); 2729 } 2730 } 2731 if is_export { 2732 path_to_root.push_str("super::"); 2733 } 2734 } 2735 path_to_root 2736 } 2737 } 2738 2739 impl<'a> RustGenerator<'a> for InterfaceGenerator<'a> { 2740 fn resolve(&self) -> &'a Resolve { 2741 self.resolve 2742 } 2743 2744 fn ownership(&self) -> Ownership { 2745 self.gen.opts.ownership 2746 } 2747 2748 fn path_to_interface(&self, interface: InterfaceId) -> Option<String> { 2749 if let Some((cur, _, _)) = self.current_interface { 2750 if cur == interface { 2751 return None; 2752 } 2753 } 2754 let mut path_to_root = self.path_to_root(); 2755 match &self.gen.interface_names[&interface] { 2756 InterfaceName::Remapped { name_at_root, .. } => path_to_root.push_str(name_at_root), 2757 InterfaceName::Path(path) => { 2758 for (i, name) in path.iter().enumerate() { 2759 if i > 0 { 2760 path_to_root.push_str("::"); 2761 } 2762 path_to_root.push_str(name); 2763 } 2764 } 2765 } 2766 Some(path_to_root) 2767 } 2768 2769 fn push_str(&mut self, s: &str) { 2770 self.src.push_str(s); 2771 } 2772 2773 fn info(&self, ty: TypeId) -> TypeInfo { 2774 self.gen.types.get(ty) 2775 } 2776 2777 fn is_imported_interface(&self, interface: InterfaceId) -> bool { 2778 self.gen.interface_last_seen_as_import[&interface] 2779 } 2780 2781 fn wasmtime_path(&self) -> String { 2782 self.gen.wasmtime_path() 2783 } 2784 } 2785 2786 /// When an interface `use`s a type from another interface, it creates a new TypeId 2787 /// referring to the definition TypeId. Chase this chain of references down to 2788 /// a TypeId for type's definition. 2789 fn resolve_type_definition_id(resolve: &Resolve, mut id: TypeId) -> TypeId { 2790 loop { 2791 match resolve.types[id].kind { 2792 TypeDefKind::Type(Type::Id(def_id)) => id = def_id, 2793 _ => return id, 2794 } 2795 } 2796 } 2797 2798 fn rust_function_name(func: &Function) -> String { 2799 match func.kind { 2800 FunctionKind::Method(_) | FunctionKind::Static(_) => to_rust_ident(func.item_name()), 2801 FunctionKind::Constructor(_) => "new".to_string(), 2802 FunctionKind::Freestanding => to_rust_ident(&func.name), 2803 } 2804 } 2805 2806 fn func_field_name(resolve: &Resolve, func: &Function) -> String { 2807 let mut name = String::new(); 2808 match func.kind { 2809 FunctionKind::Method(id) => { 2810 name.push_str("method-"); 2811 name.push_str(resolve.types[id].name.as_ref().unwrap()); 2812 name.push_str("-"); 2813 } 2814 FunctionKind::Static(id) => { 2815 name.push_str("static-"); 2816 name.push_str(resolve.types[id].name.as_ref().unwrap()); 2817 name.push_str("-"); 2818 } 2819 FunctionKind::Constructor(id) => { 2820 name.push_str("constructor-"); 2821 name.push_str(resolve.types[id].name.as_ref().unwrap()); 2822 name.push_str("-"); 2823 } 2824 FunctionKind::Freestanding => {} 2825 } 2826 name.push_str(func.item_name()); 2827 name.to_snake_case() 2828 } 2829 2830 fn get_resources<'a>(resolve: &'a Resolve, id: InterfaceId) -> impl Iterator<Item = &'a str> + 'a { 2831 resolve.interfaces[id] 2832 .types 2833 .iter() 2834 .filter_map(move |(name, ty)| match resolve.types[*ty].kind { 2835 TypeDefKind::Resource => Some(name.as_str()), 2836 _ => None, 2837 }) 2838 } 2839 2840 fn get_world_resources<'a>( 2841 resolve: &'a Resolve, 2842 id: WorldId, 2843 ) -> impl Iterator<Item = &'a str> + 'a { 2844 resolve.worlds[id] 2845 .imports 2846 .iter() 2847 .filter_map(move |(name, item)| match item { 2848 WorldItem::Type(id) => match resolve.types[*id].kind { 2849 TypeDefKind::Resource => Some(match name { 2850 WorldKey::Name(s) => s.as_str(), 2851 WorldKey::Interface(_) => unreachable!(), 2852 }), 2853 _ => None, 2854 }, 2855 _ => None, 2856 }) 2857 } 2858