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