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 { drop<T>( accessor: &wasmtime::component::Accessor<T, Self>, rep: wasmtime::component::Resource<Baz>, ) -> impl ::core::future::Future<Output = wasmtime::Result<()>> + Send where Self: Sized83 fn drop<T>( 84 accessor: &wasmtime::component::Accessor<T, Self>, 85 rep: wasmtime::component::Resource<Baz>, 86 ) -> impl ::core::future::Future<Output = wasmtime::Result<()>> + Send 87 where 88 Self: Sized; foo<T: Send>( accessor: &wasmtime::component::Accessor<T, Self>, self_: wasmtime::component::Resource<Baz>, ) -> impl ::core::future::Future<Output = ()> + Send89 fn foo<T: Send>( 90 accessor: &wasmtime::component::Accessor<T, Self>, 91 self_: wasmtime::component::Resource<Baz>, 92 ) -> impl ::core::future::Future<Output = ()> + Send; 93 } 94 pub trait HostBaz: Send {} 95 impl<_T: HostBaz + ?Sized + Send> HostBaz for &mut _T {} 96 /// Auto-generated bindings for a pre-instantiated version of a 97 /// component which implements the world `the-world`. 98 /// 99 /// This structure is created through [`TheWorldPre::new`] which 100 /// takes a [`InstancePre`](wasmtime::component::InstancePre) that 101 /// has been created through a [`Linker`](wasmtime::component::Linker). 102 /// 103 /// For more information see [`TheWorld`] as well. 104 pub struct TheWorldPre<T: 'static> { 105 instance_pre: wasmtime::component::InstancePre<T>, 106 indices: TheWorldIndices, 107 } 108 impl<T: 'static> Clone for TheWorldPre<T> { clone(&self) -> Self109 fn clone(&self) -> Self { 110 Self { 111 instance_pre: self.instance_pre.clone(), 112 indices: self.indices.clone(), 113 } 114 } 115 } 116 impl<_T: 'static> TheWorldPre<_T> { 117 /// Creates a new copy of `TheWorldPre` bindings which can then 118 /// be used to instantiate into a particular store. 119 /// 120 /// This method may fail if the component behind `instance_pre` 121 /// does not have the required exports. new( instance_pre: wasmtime::component::InstancePre<_T>, ) -> wasmtime::Result<Self>122 pub fn new( 123 instance_pre: wasmtime::component::InstancePre<_T>, 124 ) -> wasmtime::Result<Self> { 125 let indices = TheWorldIndices::new(&instance_pre)?; 126 Ok(Self { instance_pre, indices }) 127 } engine(&self) -> &wasmtime::Engine128 pub fn engine(&self) -> &wasmtime::Engine { 129 self.instance_pre.engine() 130 } instance_pre(&self) -> &wasmtime::component::InstancePre<_T>131 pub fn instance_pre(&self) -> &wasmtime::component::InstancePre<_T> { 132 &self.instance_pre 133 } 134 /// Instantiates a new instance of [`TheWorld`] within the 135 /// `store` provided. 136 /// 137 /// This function will use `self` as the pre-instantiated 138 /// instance to perform instantiation. Afterwards the preloaded 139 /// indices in `self` are used to lookup all exports on the 140 /// resulting instance. instantiate( &self, mut store: impl wasmtime::AsContextMut<Data = _T>, ) -> wasmtime::Result<TheWorld>141 pub fn instantiate( 142 &self, 143 mut store: impl wasmtime::AsContextMut<Data = _T>, 144 ) -> wasmtime::Result<TheWorld> { 145 let mut store = store.as_context_mut(); 146 let instance = self.instance_pre.instantiate(&mut store)?; 147 self.indices.load(&mut store, &instance) 148 } 149 } 150 impl<_T: Send + 'static> TheWorldPre<_T> { 151 /// Same as [`Self::instantiate`], except with `async`. instantiate_async( &self, mut store: impl wasmtime::AsContextMut<Data = _T>, ) -> wasmtime::Result<TheWorld>152 pub async fn instantiate_async( 153 &self, 154 mut store: impl wasmtime::AsContextMut<Data = _T>, 155 ) -> wasmtime::Result<TheWorld> { 156 let mut store = store.as_context_mut(); 157 let instance = self.instance_pre.instantiate_async(&mut store).await?; 158 self.indices.load(&mut store, &instance) 159 } 160 } 161 /// Auto-generated bindings for index of the exports of 162 /// `the-world`. 163 /// 164 /// This is an implementation detail of [`TheWorldPre`] and can 165 /// be constructed if needed as well. 166 /// 167 /// For more information see [`TheWorld`] as well. 168 #[derive(Clone)] 169 pub struct TheWorldIndices {} 170 /// Auto-generated bindings for an instance a component which 171 /// implements the world `the-world`. 172 /// 173 /// This structure can be created through a number of means 174 /// depending on your requirements and what you have on hand: 175 /// 176 /// * The most convenient way is to use 177 /// [`TheWorld::instantiate`] which only needs a 178 /// [`Store`], [`Component`], and [`Linker`]. 179 /// 180 /// * Alternatively you can create a [`TheWorldPre`] ahead of 181 /// time with a [`Component`] to front-load string lookups 182 /// of exports once instead of per-instantiation. This 183 /// method then uses [`TheWorldPre::instantiate`] to 184 /// create a [`TheWorld`]. 185 /// 186 /// * If you've instantiated the instance yourself already 187 /// then you can use [`TheWorld::new`]. 188 /// 189 /// These methods are all equivalent to one another and move 190 /// around the tradeoff of what work is performed when. 191 /// 192 /// [`Store`]: wasmtime::Store 193 /// [`Component`]: wasmtime::component::Component 194 /// [`Linker`]: wasmtime::component::Linker 195 pub struct TheWorld {} 196 pub trait TheWorldImportsWithStore: wasmtime::component::HasData + HostBazWithStore + Send { foo<T: Send>( accessor: &wasmtime::component::Accessor<T, Self>, ) -> impl ::core::future::Future<Output = ()> + Send197 fn foo<T: Send>( 198 accessor: &wasmtime::component::Accessor<T, Self>, 199 ) -> impl ::core::future::Future<Output = ()> + Send; 200 } 201 pub trait TheWorldImports: HostBaz + Send {} 202 impl<_T: TheWorldImports + ?Sized + Send> TheWorldImports for &mut _T {} 203 const _: () = { 204 impl TheWorldIndices { 205 /// Creates a new copy of `TheWorldIndices` bindings which can then 206 /// be used to instantiate into a particular store. 207 /// 208 /// This method may fail if the component does not have the 209 /// required exports. new<_T>( _instance_pre: &wasmtime::component::InstancePre<_T>, ) -> wasmtime::Result<Self>210 pub fn new<_T>( 211 _instance_pre: &wasmtime::component::InstancePre<_T>, 212 ) -> wasmtime::Result<Self> { 213 let _component = _instance_pre.component(); 214 let _instance_type = _instance_pre.instance_type(); 215 Ok(TheWorldIndices {}) 216 } 217 /// Uses the indices stored in `self` to load an instance 218 /// of [`TheWorld`] from the instance provided. 219 /// 220 /// Note that at this time this method will additionally 221 /// perform type-checks of all exports. load( &self, mut store: impl wasmtime::AsContextMut, instance: &wasmtime::component::Instance, ) -> wasmtime::Result<TheWorld>222 pub fn load( 223 &self, 224 mut store: impl wasmtime::AsContextMut, 225 instance: &wasmtime::component::Instance, 226 ) -> wasmtime::Result<TheWorld> { 227 let _ = &mut store; 228 let _instance = instance; 229 Ok(TheWorld {}) 230 } 231 } 232 impl TheWorld { 233 /// Convenience wrapper around [`TheWorldPre::new`] and 234 /// [`TheWorldPre::instantiate`]. instantiate<_T>( store: impl wasmtime::AsContextMut<Data = _T>, component: &wasmtime::component::Component, linker: &wasmtime::component::Linker<_T>, ) -> wasmtime::Result<TheWorld>235 pub fn instantiate<_T>( 236 store: impl wasmtime::AsContextMut<Data = _T>, 237 component: &wasmtime::component::Component, 238 linker: &wasmtime::component::Linker<_T>, 239 ) -> wasmtime::Result<TheWorld> { 240 let pre = linker.instantiate_pre(component)?; 241 TheWorldPre::new(pre)?.instantiate(store) 242 } 243 /// Convenience wrapper around [`TheWorldIndices::new`] and 244 /// [`TheWorldIndices::load`]. new( mut store: impl wasmtime::AsContextMut, instance: &wasmtime::component::Instance, ) -> wasmtime::Result<TheWorld>245 pub fn new( 246 mut store: impl wasmtime::AsContextMut, 247 instance: &wasmtime::component::Instance, 248 ) -> wasmtime::Result<TheWorld> { 249 let indices = TheWorldIndices::new(&instance.instance_pre(&store))?; 250 indices.load(&mut store, instance) 251 } 252 /// Convenience wrapper around [`TheWorldPre::new`] and 253 /// [`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,254 pub async fn instantiate_async<_T>( 255 store: impl wasmtime::AsContextMut<Data = _T>, 256 component: &wasmtime::component::Component, 257 linker: &wasmtime::component::Linker<_T>, 258 ) -> wasmtime::Result<TheWorld> 259 where 260 _T: Send, 261 { 262 let pre = linker.instantiate_pre(component)?; 263 TheWorldPre::new(pre)?.instantiate_async(store).await 264 } 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,265 pub fn add_to_linker_imports<T, D>( 266 linker: &mut wasmtime::component::Linker<T>, 267 options: &LinkOptions, 268 host_getter: fn(&mut T) -> D::Data<'_>, 269 ) -> wasmtime::Result<()> 270 where 271 D: TheWorldImportsWithStore, 272 for<'a> D::Data<'a>: TheWorldImports, 273 T: 'static + Send, 274 { 275 let mut linker = linker.root(); 276 if options.experimental_world { 277 if options.experimental_world_resource { 278 linker 279 .resource_concurrent( 280 "baz", 281 wasmtime::component::ResourceType::host::<Baz>(), 282 move |caller: &wasmtime::component::Accessor<T>, rep| { 283 wasmtime::component::__internal::Box::pin(async move { 284 let accessor = &caller.with_getter(host_getter); 285 wasmtime::ToWasmtimeResult::to_wasmtime_result( 286 HostBazWithStore::drop( 287 accessor, 288 wasmtime::component::Resource::new_own(rep), 289 ) 290 .await, 291 ) 292 }) 293 }, 294 )?; 295 } 296 if options.experimental_world_function_import { 297 linker 298 .func_wrap_concurrent( 299 "foo", 300 move |caller: &wasmtime::component::Accessor<T>, (): ()| { 301 wasmtime::component::__internal::Box::pin(async move { 302 let host = &caller.with_getter(host_getter); 303 let r = <D as TheWorldImportsWithStore>::foo(host).await; 304 Ok(r) 305 }) 306 }, 307 )?; 308 } 309 if options.experimental_world_resource_method { 310 linker 311 .func_wrap_concurrent( 312 "[method]baz.foo", 313 move | 314 caller: &wasmtime::component::Accessor<T>, 315 (arg0,): (wasmtime::component::Resource<Baz>,)| 316 { 317 wasmtime::component::__internal::Box::pin(async move { 318 let host = &caller.with_getter(host_getter); 319 let r = <D as HostBazWithStore>::foo(host, arg0).await; 320 Ok(r) 321 }) 322 }, 323 )?; 324 } 325 } 326 Ok(()) 327 } 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,328 pub fn add_to_linker<T, D>( 329 linker: &mut wasmtime::component::Linker<T>, 330 options: &LinkOptions, 331 host_getter: fn(&mut T) -> D::Data<'_>, 332 ) -> wasmtime::Result<()> 333 where 334 D: foo::foo::the_interface::HostWithStore + TheWorldImportsWithStore + Send, 335 for<'a> D::Data<'a>: foo::foo::the_interface::Host + TheWorldImports + Send, 336 T: 'static + Send, 337 { 338 if options.experimental_world { 339 Self::add_to_linker_imports::<T, D>(linker, options, host_getter)?; 340 if options.experimental_world_interface_import { 341 foo::foo::the_interface::add_to_linker::< 342 T, 343 D, 344 >(linker, &options.into(), host_getter)?; 345 } 346 } 347 Ok(()) 348 } 349 } 350 }; 351 pub mod foo { 352 pub mod foo { 353 #[allow(clippy::all)] 354 pub mod the_interface { 355 #[allow(unused_imports)] 356 use wasmtime::component::__internal::Box; 357 /// Link-time configurations. 358 #[derive(Clone, Debug, Default)] 359 pub struct LinkOptions { 360 experimental_interface: bool, 361 experimental_interface_function: bool, 362 experimental_interface_resource: bool, 363 experimental_interface_resource_method: bool, 364 } 365 impl LinkOptions { 366 /// Enable members marked as `@unstable(feature = experimental-interface)` experimental_interface(&mut self, enabled: bool) -> &mut Self367 pub fn experimental_interface(&mut self, enabled: bool) -> &mut Self { 368 self.experimental_interface = enabled; 369 self 370 } 371 /// Enable members marked as `@unstable(feature = experimental-interface-function)` experimental_interface_function( &mut self, enabled: bool, ) -> &mut Self372 pub fn experimental_interface_function( 373 &mut self, 374 enabled: bool, 375 ) -> &mut Self { 376 self.experimental_interface_function = enabled; 377 self 378 } 379 /// Enable members marked as `@unstable(feature = experimental-interface-resource)` experimental_interface_resource( &mut self, enabled: bool, ) -> &mut Self380 pub fn experimental_interface_resource( 381 &mut self, 382 enabled: bool, 383 ) -> &mut Self { 384 self.experimental_interface_resource = enabled; 385 self 386 } 387 /// Enable members marked as `@unstable(feature = experimental-interface-resource-method)` experimental_interface_resource_method( &mut self, enabled: bool, ) -> &mut Self388 pub fn experimental_interface_resource_method( 389 &mut self, 390 enabled: bool, 391 ) -> &mut Self { 392 self.experimental_interface_resource_method = enabled; 393 self 394 } 395 } 396 pub enum Bar {} 397 pub trait HostBarWithStore: wasmtime::component::HasData + Send { drop<T>( accessor: &wasmtime::component::Accessor<T, Self>, rep: wasmtime::component::Resource<Bar>, ) -> impl ::core::future::Future<Output = wasmtime::Result<()>> + Send where Self: Sized398 fn drop<T>( 399 accessor: &wasmtime::component::Accessor<T, Self>, 400 rep: wasmtime::component::Resource<Bar>, 401 ) -> impl ::core::future::Future<Output = wasmtime::Result<()>> + Send 402 where 403 Self: Sized; foo<T: Send>( accessor: &wasmtime::component::Accessor<T, Self>, self_: wasmtime::component::Resource<Bar>, ) -> impl ::core::future::Future<Output = ()> + Send404 fn foo<T: Send>( 405 accessor: &wasmtime::component::Accessor<T, Self>, 406 self_: wasmtime::component::Resource<Bar>, 407 ) -> impl ::core::future::Future<Output = ()> + Send; 408 } 409 pub trait HostBar: Send {} 410 impl<_T: HostBar + ?Sized + Send> HostBar for &mut _T {} 411 pub trait HostWithStore: wasmtime::component::HasData + HostBarWithStore + Send { foo<T: Send>( accessor: &wasmtime::component::Accessor<T, Self>, ) -> impl ::core::future::Future<Output = ()> + Send412 fn foo<T: Send>( 413 accessor: &wasmtime::component::Accessor<T, Self>, 414 ) -> impl ::core::future::Future<Output = ()> + Send; 415 } 416 pub trait Host: HostBar + Send {} 417 impl<_T: Host + ?Sized + Send> Host for &mut _T {} 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,418 pub fn add_to_linker<T, D>( 419 linker: &mut wasmtime::component::Linker<T>, 420 options: &LinkOptions, 421 host_getter: fn(&mut T) -> D::Data<'_>, 422 ) -> wasmtime::Result<()> 423 where 424 D: HostWithStore, 425 for<'a> D::Data<'a>: Host, 426 T: 'static + Send, 427 { 428 if options.experimental_interface { 429 let mut inst = linker.instance("foo:foo/the-interface")?; 430 if options.experimental_interface_resource { 431 inst.resource_concurrent( 432 "bar", 433 wasmtime::component::ResourceType::host::<Bar>(), 434 move |caller: &wasmtime::component::Accessor<T>, rep| { 435 wasmtime::component::__internal::Box::pin(async move { 436 let accessor = &caller.with_getter(host_getter); 437 wasmtime::ToWasmtimeResult::to_wasmtime_result( 438 HostBarWithStore::drop( 439 accessor, 440 wasmtime::component::Resource::new_own(rep), 441 ) 442 .await, 443 ) 444 }) 445 }, 446 )?; 447 } 448 if options.experimental_interface_function { 449 inst.func_wrap_concurrent( 450 "foo", 451 move |caller: &wasmtime::component::Accessor<T>, (): ()| { 452 wasmtime::component::__internal::Box::pin(async move { 453 let host = &caller.with_getter(host_getter); 454 let r = <D as HostWithStore>::foo(host).await; 455 Ok(r) 456 }) 457 }, 458 )?; 459 } 460 if options.experimental_interface_resource_method { 461 inst.func_wrap_concurrent( 462 "[method]bar.foo", 463 move | 464 caller: &wasmtime::component::Accessor<T>, 465 (arg0,): (wasmtime::component::Resource<Bar>,)| 466 { 467 wasmtime::component::__internal::Box::pin(async move { 468 let host = &caller.with_getter(host_getter); 469 let r = <D as HostBarWithStore>::foo(host, arg0).await; 470 Ok(r) 471 }) 472 }, 473 )?; 474 } 475 } 476 Ok(()) 477 } 478 } 479 } 480 } 481