1 /// Link-time configurations. 2 #[derive(Clone, Debug, Default)] 3 pub struct LinkOptions { 4 experimental_interface: bool, 5 experimental_interface_function: bool, 6 experimental_interface_resource: bool, 7 experimental_interface_resource_method: bool, 8 experimental_world: bool, 9 experimental_world_function_import: bool, 10 experimental_world_interface_import: bool, 11 experimental_world_resource: bool, 12 experimental_world_resource_method: bool, 13 } 14 impl LinkOptions { 15 /// Enable members marked as `@unstable(feature = experimental-interface)` experimental_interface(&mut self, enabled: bool) -> &mut Self16 pub fn experimental_interface(&mut self, enabled: bool) -> &mut Self { 17 self.experimental_interface = enabled; 18 self 19 } 20 /// Enable members marked as `@unstable(feature = experimental-interface-function)` experimental_interface_function(&mut self, enabled: bool) -> &mut Self21 pub fn experimental_interface_function(&mut self, enabled: bool) -> &mut Self { 22 self.experimental_interface_function = enabled; 23 self 24 } 25 /// Enable members marked as `@unstable(feature = experimental-interface-resource)` experimental_interface_resource(&mut self, enabled: bool) -> &mut Self26 pub fn experimental_interface_resource(&mut self, enabled: bool) -> &mut Self { 27 self.experimental_interface_resource = enabled; 28 self 29 } 30 /// Enable members marked as `@unstable(feature = experimental-interface-resource-method)` experimental_interface_resource_method( &mut self, enabled: bool, ) -> &mut Self31 pub fn experimental_interface_resource_method( 32 &mut self, 33 enabled: bool, 34 ) -> &mut Self { 35 self.experimental_interface_resource_method = enabled; 36 self 37 } 38 /// Enable members marked as `@unstable(feature = experimental-world)` experimental_world(&mut self, enabled: bool) -> &mut Self39 pub fn experimental_world(&mut self, enabled: bool) -> &mut Self { 40 self.experimental_world = enabled; 41 self 42 } 43 /// Enable members marked as `@unstable(feature = experimental-world-function-import)` experimental_world_function_import(&mut self, enabled: bool) -> &mut Self44 pub fn experimental_world_function_import(&mut self, enabled: bool) -> &mut Self { 45 self.experimental_world_function_import = enabled; 46 self 47 } 48 /// Enable members marked as `@unstable(feature = experimental-world-interface-import)` experimental_world_interface_import(&mut self, enabled: bool) -> &mut Self49 pub fn experimental_world_interface_import(&mut self, enabled: bool) -> &mut Self { 50 self.experimental_world_interface_import = enabled; 51 self 52 } 53 /// Enable members marked as `@unstable(feature = experimental-world-resource)` experimental_world_resource(&mut self, enabled: bool) -> &mut Self54 pub fn experimental_world_resource(&mut self, enabled: bool) -> &mut Self { 55 self.experimental_world_resource = enabled; 56 self 57 } 58 /// Enable members marked as `@unstable(feature = experimental-world-resource-method)` experimental_world_resource_method(&mut self, enabled: bool) -> &mut Self59 pub fn experimental_world_resource_method(&mut self, enabled: bool) -> &mut Self { 60 self.experimental_world_resource_method = enabled; 61 self 62 } 63 } 64 impl core::convert::From<LinkOptions> for foo::foo::the_interface::LinkOptions { from(src: LinkOptions) -> Self65 fn from(src: LinkOptions) -> Self { 66 (&src).into() 67 } 68 } 69 impl core::convert::From<&LinkOptions> for foo::foo::the_interface::LinkOptions { from(src: &LinkOptions) -> Self70 fn from(src: &LinkOptions) -> Self { 71 let mut dest = Self::default(); 72 dest.experimental_interface(src.experimental_interface); 73 dest.experimental_interface_function(src.experimental_interface_function); 74 dest.experimental_interface_resource(src.experimental_interface_resource); 75 dest.experimental_interface_resource_method( 76 src.experimental_interface_resource_method, 77 ); 78 dest 79 } 80 } 81 pub enum Baz {} 82 pub trait HostBazWithStore: wasmtime::component::HasData + Send {} 83 impl<_T: ?Sized> HostBazWithStore for _T 84 where 85 _T: wasmtime::component::HasData + Send, 86 {} 87 pub trait HostBaz: Send { foo( &mut self, self_: wasmtime::component::Resource<Baz>, ) -> impl ::core::future::Future<Output = ()> + Send88 fn foo( 89 &mut self, 90 self_: wasmtime::component::Resource<Baz>, 91 ) -> impl ::core::future::Future<Output = ()> + Send; drop( &mut self, rep: wasmtime::component::Resource<Baz>, ) -> impl ::core::future::Future<Output = wasmtime::Result<()>> + Send92 fn drop( 93 &mut self, 94 rep: wasmtime::component::Resource<Baz>, 95 ) -> impl ::core::future::Future<Output = wasmtime::Result<()>> + Send; 96 } 97 impl<_T: HostBaz + ?Sized + Send> HostBaz for &mut _T { foo( &mut self, self_: wasmtime::component::Resource<Baz>, ) -> impl ::core::future::Future<Output = ()> + Send98 fn foo( 99 &mut self, 100 self_: wasmtime::component::Resource<Baz>, 101 ) -> impl ::core::future::Future<Output = ()> + Send { 102 async move { HostBaz::foo(*self, self_).await } 103 } drop( &mut self, rep: wasmtime::component::Resource<Baz>, ) -> wasmtime::Result<()>104 async fn drop( 105 &mut self, 106 rep: wasmtime::component::Resource<Baz>, 107 ) -> wasmtime::Result<()> { 108 HostBaz::drop(*self, rep).await 109 } 110 } 111 /// Auto-generated bindings for a pre-instantiated version of a 112 /// component which implements the world `the-world`. 113 /// 114 /// This structure is created through [`TheWorldPre::new`] which 115 /// takes a [`InstancePre`](wasmtime::component::InstancePre) that 116 /// has been created through a [`Linker`](wasmtime::component::Linker). 117 /// 118 /// For more information see [`TheWorld`] as well. 119 pub struct TheWorldPre<T: 'static> { 120 instance_pre: wasmtime::component::InstancePre<T>, 121 indices: TheWorldIndices, 122 } 123 impl<T: 'static> Clone for TheWorldPre<T> { clone(&self) -> Self124 fn clone(&self) -> Self { 125 Self { 126 instance_pre: self.instance_pre.clone(), 127 indices: self.indices.clone(), 128 } 129 } 130 } 131 impl<_T: 'static> TheWorldPre<_T> { 132 /// Creates a new copy of `TheWorldPre` bindings which can then 133 /// be used to instantiate into a particular store. 134 /// 135 /// This method may fail if the component behind `instance_pre` 136 /// does not have the required exports. new( instance_pre: wasmtime::component::InstancePre<_T>, ) -> wasmtime::Result<Self>137 pub fn new( 138 instance_pre: wasmtime::component::InstancePre<_T>, 139 ) -> wasmtime::Result<Self> { 140 let indices = TheWorldIndices::new(&instance_pre)?; 141 Ok(Self { instance_pre, indices }) 142 } engine(&self) -> &wasmtime::Engine143 pub fn engine(&self) -> &wasmtime::Engine { 144 self.instance_pre.engine() 145 } instance_pre(&self) -> &wasmtime::component::InstancePre<_T>146 pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { 147 &self.instance_pre 148 } 149 /// Instantiates a new instance of [`TheWorld`] within the 150 /// `store` provided. 151 /// 152 /// This function will use `self` as the pre-instantiated 153 /// instance to perform instantiation. Afterwards the preloaded 154 /// indices in `self` are used to lookup all exports on the 155 /// resulting instance. instantiate( &self, mut store: impl wasmtime::AsContextMut<Data = _T>, ) -> wasmtime::Result<TheWorld>156 pub fn instantiate( 157 &self, 158 mut store: impl wasmtime::AsContextMut<Data = _T>, 159 ) -> wasmtime::Result<TheWorld> { 160 let mut store = store.as_context_mut(); 161 let instance = self.instance_pre.instantiate(&mut store)?; 162 self.indices.load(&mut store, &instance) 163 } 164 } 165 impl<_T: Send + 'static> TheWorldPre<_T> { 166 /// Same as [`Self::instantiate`], except with `async`. instantiate_async( &self, mut store: impl wasmtime::AsContextMut<Data = _T>, ) -> wasmtime::Result<TheWorld>167 pub async fn instantiate_async( 168 &self, 169 mut store: impl wasmtime::AsContextMut<Data = _T>, 170 ) -> wasmtime::Result<TheWorld> { 171 let mut store = store.as_context_mut(); 172 let instance = self.instance_pre.instantiate_async(&mut store).await?; 173 self.indices.load(&mut store, &instance) 174 } 175 } 176 /// Auto-generated bindings for index of the exports of 177 /// `the-world`. 178 /// 179 /// This is an implementation detail of [`TheWorldPre`] and can 180 /// be constructed if needed as well. 181 /// 182 /// For more information see [`TheWorld`] as well. 183 #[derive(Clone)] 184 pub struct TheWorldIndices {} 185 /// Auto-generated bindings for an instance a component which 186 /// implements the world `the-world`. 187 /// 188 /// This structure can be created through a number of means 189 /// depending on your requirements and what you have on hand: 190 /// 191 /// * The most convenient way is to use 192 /// [`TheWorld::instantiate`] which only needs a 193 /// [`Store`], [`Component`], and [`Linker`]. 194 /// 195 /// * Alternatively you can create a [`TheWorldPre`] ahead of 196 /// time with a [`Component`] to front-load string lookups 197 /// of exports once instead of per-instantiation. This 198 /// method then uses [`TheWorldPre::instantiate`] to 199 /// create a [`TheWorld`]. 200 /// 201 /// * If you've instantiated the instance yourself already 202 /// then you can use [`TheWorld::new`]. 203 /// 204 /// These methods are all equivalent to one another and move 205 /// around the tradeoff of what work is performed when. 206 /// 207 /// [`Store`]: wasmtime::Store 208 /// [`Component`]: wasmtime::component::Component 209 /// [`Linker`]: wasmtime::component::Linker 210 pub struct TheWorld {} 211 pub trait TheWorldImportsWithStore: wasmtime::component::HasData + HostBazWithStore + Send {} 212 impl<_T: ?Sized> TheWorldImportsWithStore for _T 213 where 214 _T: wasmtime::component::HasData + HostBazWithStore + Send, 215 {} 216 pub trait TheWorldImports: HostBaz + Send { foo(&mut self) -> impl ::core::future::Future<Output = ()> + Send217 fn foo(&mut self) -> impl ::core::future::Future<Output = ()> + Send; 218 } 219 impl<_T: TheWorldImports + ?Sized + Send> TheWorldImports for &mut _T { foo(&mut self) -> impl ::core::future::Future<Output = ()> + Send220 fn foo(&mut self) -> impl ::core::future::Future<Output = ()> + Send { 221 async move { TheWorldImports::foo(*self).await } 222 } 223 } 224 const _: () = { 225 impl TheWorldIndices { 226 /// Creates a new copy of `TheWorldIndices` bindings which can then 227 /// be used to instantiate into a particular store. 228 /// 229 /// This method may fail if the component does not have the 230 /// required exports. new<_T>( _instance_pre: &wasmtime::component::InstancePre<_T>, ) -> wasmtime::Result<Self>231 pub fn new<_T>( 232 _instance_pre: &wasmtime::component::InstancePre<_T>, 233 ) -> wasmtime::Result<Self> { 234 let _component = _instance_pre.component(); 235 let _instance_type = _instance_pre.instance_type(); 236 Ok(TheWorldIndices {}) 237 } 238 /// Uses the indices stored in `self` to load an instance 239 /// of [`TheWorld`] from the instance provided. 240 /// 241 /// Note that at this time this method will additionally 242 /// perform type-checks of all exports. load( &self, mut store: impl wasmtime::AsContextMut, instance: &wasmtime::component::Instance, ) -> wasmtime::Result<TheWorld>243 pub fn load( 244 &self, 245 mut store: impl wasmtime::AsContextMut, 246 instance: &wasmtime::component::Instance, 247 ) -> wasmtime::Result<TheWorld> { 248 let _ = &mut store; 249 let _instance = instance; 250 Ok(TheWorld {}) 251 } 252 } 253 impl TheWorld { 254 /// Convenience wrapper around [`TheWorldPre::new`] and 255 /// [`TheWorldPre::instantiate`]. instantiate<_T>( store: impl wasmtime::AsContextMut<Data = _T>, component: &wasmtime::component::Component, linker: &wasmtime::component::Linker<_T>, ) -> wasmtime::Result<TheWorld>256 pub fn instantiate<_T>( 257 store: impl wasmtime::AsContextMut<Data = _T>, 258 component: &wasmtime::component::Component, 259 linker: &wasmtime::component::Linker<_T>, 260 ) -> wasmtime::Result<TheWorld> { 261 let pre = linker.instantiate_pre(component)?; 262 TheWorldPre::new(pre)?.instantiate(store) 263 } 264 /// Convenience wrapper around [`TheWorldIndices::new`] and 265 /// [`TheWorldIndices::load`]. new( mut store: impl wasmtime::AsContextMut, instance: &wasmtime::component::Instance, ) -> wasmtime::Result<TheWorld>266 pub fn new( 267 mut store: impl wasmtime::AsContextMut, 268 instance: &wasmtime::component::Instance, 269 ) -> wasmtime::Result<TheWorld> { 270 let indices = TheWorldIndices::new(&instance.instance_pre(&store))?; 271 indices.load(&mut store, instance) 272 } 273 /// Convenience wrapper around [`TheWorldPre::new`] and 274 /// [`TheWorldPre::instantiate_async`]. instantiate_async<_T>( store: impl wasmtime::AsContextMut<Data = _T>, component: &wasmtime::component::Component, linker: &wasmtime::component::Linker<_T>, ) -> wasmtime::Result<TheWorld> where _T: Send,275 pub async fn instantiate_async<_T>( 276 store: impl wasmtime::AsContextMut<Data = _T>, 277 component: &wasmtime::component::Component, 278 linker: &wasmtime::component::Linker<_T>, 279 ) -> wasmtime::Result<TheWorld> 280 where 281 _T: Send, 282 { 283 let pre = linker.instantiate_pre(component)?; 284 TheWorldPre::new(pre)?.instantiate_async(store).await 285 } add_to_linker_imports<T, D>( linker: &mut wasmtime::component::Linker<T>, options: &LinkOptions, host_getter: fn(&mut T) -> D::Data<'_>, ) -> wasmtime::Result<()> where D: TheWorldImportsWithStore, for<'a> D::Data<'a>: TheWorldImports, T: 'static + Send,286 pub fn add_to_linker_imports<T, D>( 287 linker: &mut wasmtime::component::Linker<T>, 288 options: &LinkOptions, 289 host_getter: fn(&mut T) -> D::Data<'_>, 290 ) -> wasmtime::Result<()> 291 where 292 D: TheWorldImportsWithStore, 293 for<'a> D::Data<'a>: TheWorldImports, 294 T: 'static + Send, 295 { 296 let mut linker = linker.root(); 297 if options.experimental_world { 298 if options.experimental_world_resource { 299 linker 300 .resource_async( 301 "baz", 302 wasmtime::component::ResourceType::host::<Baz>(), 303 move |mut store, rep| { 304 wasmtime::component::__internal::Box::new(async move { 305 wasmtime::ToWasmtimeResult::to_wasmtime_result( 306 HostBaz::drop( 307 &mut host_getter(store.data_mut()), 308 wasmtime::component::Resource::new_own(rep), 309 ) 310 .await, 311 ) 312 }) 313 }, 314 )?; 315 } 316 if options.experimental_world_function_import { 317 linker 318 .func_wrap_async( 319 "foo", 320 move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { 321 wasmtime::component::__internal::Box::new(async move { 322 let host = &mut host_getter(caller.data_mut()); 323 let r = TheWorldImports::foo(host).await; 324 Ok(r) 325 }) 326 }, 327 )?; 328 } 329 if options.experimental_world_resource_method { 330 linker 331 .func_wrap_async( 332 "[method]baz.foo", 333 move | 334 mut caller: wasmtime::StoreContextMut<'_, T>, 335 (arg0,): (wasmtime::component::Resource<Baz>,)| 336 { 337 wasmtime::component::__internal::Box::new(async move { 338 let host = &mut host_getter(caller.data_mut()); 339 let r = HostBaz::foo(host, arg0).await; 340 Ok(r) 341 }) 342 }, 343 )?; 344 } 345 } 346 Ok(()) 347 } add_to_linker<T, D>( linker: &mut wasmtime::component::Linker<T>, options: &LinkOptions, host_getter: fn(&mut T) -> D::Data<'_>, ) -> wasmtime::Result<()> where D: foo::foo::the_interface::HostWithStore + TheWorldImportsWithStore + Send, for<'a> D::Data<'a>: foo::foo::the_interface::Host + TheWorldImports + Send, T: 'static + Send,348 pub fn add_to_linker<T, D>( 349 linker: &mut wasmtime::component::Linker<T>, 350 options: &LinkOptions, 351 host_getter: fn(&mut T) -> D::Data<'_>, 352 ) -> wasmtime::Result<()> 353 where 354 D: foo::foo::the_interface::HostWithStore + TheWorldImportsWithStore + Send, 355 for<'a> D::Data<'a>: foo::foo::the_interface::Host + TheWorldImports + Send, 356 T: 'static + Send, 357 { 358 if options.experimental_world { 359 Self::add_to_linker_imports::<T, D>(linker, options, host_getter)?; 360 if options.experimental_world_interface_import { 361 foo::foo::the_interface::add_to_linker::< 362 T, 363 D, 364 >(linker, &options.into(), host_getter)?; 365 } 366 } 367 Ok(()) 368 } 369 } 370 }; 371 pub mod foo { 372 pub mod foo { 373 #[allow(clippy::all)] 374 pub mod the_interface { 375 #[allow(unused_imports)] 376 use wasmtime::component::__internal::Box; 377 /// Link-time configurations. 378 #[derive(Clone, Debug, Default)] 379 pub struct LinkOptions { 380 experimental_interface: bool, 381 experimental_interface_function: bool, 382 experimental_interface_resource: bool, 383 experimental_interface_resource_method: bool, 384 } 385 impl LinkOptions { 386 /// Enable members marked as `@unstable(feature = experimental-interface)` experimental_interface(&mut self, enabled: bool) -> &mut Self387 pub fn experimental_interface(&mut self, enabled: bool) -> &mut Self { 388 self.experimental_interface = enabled; 389 self 390 } 391 /// Enable members marked as `@unstable(feature = experimental-interface-function)` experimental_interface_function( &mut self, enabled: bool, ) -> &mut Self392 pub fn experimental_interface_function( 393 &mut self, 394 enabled: bool, 395 ) -> &mut Self { 396 self.experimental_interface_function = enabled; 397 self 398 } 399 /// Enable members marked as `@unstable(feature = experimental-interface-resource)` experimental_interface_resource( &mut self, enabled: bool, ) -> &mut Self400 pub fn experimental_interface_resource( 401 &mut self, 402 enabled: bool, 403 ) -> &mut Self { 404 self.experimental_interface_resource = enabled; 405 self 406 } 407 /// Enable members marked as `@unstable(feature = experimental-interface-resource-method)` experimental_interface_resource_method( &mut self, enabled: bool, ) -> &mut Self408 pub fn experimental_interface_resource_method( 409 &mut self, 410 enabled: bool, 411 ) -> &mut Self { 412 self.experimental_interface_resource_method = enabled; 413 self 414 } 415 } 416 pub enum Bar {} 417 pub trait HostBarWithStore: wasmtime::component::HasData + Send {} 418 impl<_T: ?Sized> HostBarWithStore for _T 419 where 420 _T: wasmtime::component::HasData + Send, 421 {} 422 pub trait HostBar: Send { foo( &mut self, self_: wasmtime::component::Resource<Bar>, ) -> impl ::core::future::Future<Output = ()> + Send423 fn foo( 424 &mut self, 425 self_: wasmtime::component::Resource<Bar>, 426 ) -> impl ::core::future::Future<Output = ()> + Send; drop( &mut self, rep: wasmtime::component::Resource<Bar>, ) -> impl ::core::future::Future<Output = wasmtime::Result<()>> + Send427 fn drop( 428 &mut self, 429 rep: wasmtime::component::Resource<Bar>, 430 ) -> impl ::core::future::Future<Output = wasmtime::Result<()>> + Send; 431 } 432 impl<_T: HostBar + ?Sized + Send> HostBar for &mut _T { foo( &mut self, self_: wasmtime::component::Resource<Bar>, ) -> impl ::core::future::Future<Output = ()> + Send433 fn foo( 434 &mut self, 435 self_: wasmtime::component::Resource<Bar>, 436 ) -> impl ::core::future::Future<Output = ()> + Send { 437 async move { HostBar::foo(*self, self_).await } 438 } drop( &mut self, rep: wasmtime::component::Resource<Bar>, ) -> wasmtime::Result<()>439 async fn drop( 440 &mut self, 441 rep: wasmtime::component::Resource<Bar>, 442 ) -> wasmtime::Result<()> { 443 HostBar::drop(*self, rep).await 444 } 445 } 446 pub trait HostWithStore: wasmtime::component::HasData + HostBarWithStore + Send {} 447 impl<_T: ?Sized> HostWithStore for _T 448 where 449 _T: wasmtime::component::HasData + HostBarWithStore + Send, 450 {} 451 pub trait Host: HostBar + Send { foo(&mut self) -> impl ::core::future::Future<Output = ()> + Send452 fn foo(&mut self) -> impl ::core::future::Future<Output = ()> + Send; 453 } 454 impl<_T: Host + ?Sized + Send> Host for &mut _T { foo(&mut self) -> impl ::core::future::Future<Output = ()> + Send455 fn foo(&mut self) -> impl ::core::future::Future<Output = ()> + Send { 456 async move { Host::foo(*self).await } 457 } 458 } add_to_linker<T, D>( linker: &mut wasmtime::component::Linker<T>, options: &LinkOptions, host_getter: fn(&mut T) -> D::Data<'_>, ) -> wasmtime::Result<()> where D: HostWithStore, for<'a> D::Data<'a>: Host, T: 'static + Send,459 pub fn add_to_linker<T, D>( 460 linker: &mut wasmtime::component::Linker<T>, 461 options: &LinkOptions, 462 host_getter: fn(&mut T) -> D::Data<'_>, 463 ) -> wasmtime::Result<()> 464 where 465 D: HostWithStore, 466 for<'a> D::Data<'a>: Host, 467 T: 'static + Send, 468 { 469 if options.experimental_interface { 470 let mut inst = linker.instance("foo:foo/the-interface")?; 471 if options.experimental_interface_resource { 472 inst.resource_async( 473 "bar", 474 wasmtime::component::ResourceType::host::<Bar>(), 475 move |mut store, rep| { 476 wasmtime::component::__internal::Box::new(async move { 477 wasmtime::ToWasmtimeResult::to_wasmtime_result( 478 HostBar::drop( 479 &mut host_getter(store.data_mut()), 480 wasmtime::component::Resource::new_own(rep), 481 ) 482 .await, 483 ) 484 }) 485 }, 486 )?; 487 } 488 if options.experimental_interface_function { 489 inst.func_wrap_async( 490 "foo", 491 move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { 492 wasmtime::component::__internal::Box::new(async move { 493 let host = &mut host_getter(caller.data_mut()); 494 let r = Host::foo(host).await; 495 Ok(r) 496 }) 497 }, 498 )?; 499 } 500 if options.experimental_interface_resource_method { 501 inst.func_wrap_async( 502 "[method]bar.foo", 503 move | 504 mut caller: wasmtime::StoreContextMut<'_, T>, 505 (arg0,): (wasmtime::component::Resource<Bar>,)| 506 { 507 wasmtime::component::__internal::Box::new(async move { 508 let host = &mut host_getter(caller.data_mut()); 509 let r = HostBar::foo(host, arg0).await; 510 Ok(r) 511 }) 512 }, 513 )?; 514 } 515 } 516 Ok(()) 517 } 518 } 519 } 520 } 521