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