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