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