1 use crate::{
2     WasmtimeStoreContextMut, handle_result, wasm_name_t, wasmtime_component_resource_type_t,
3     wasmtime_error_t,
4 };
5 use std::mem;
6 use std::mem::{ManuallyDrop, MaybeUninit};
7 use std::ptr;
8 use std::slice;
9 use wasmtime::component::{ResourceAny, ResourceDynamic, Val};
10 
11 crate::declare_vecs! {
12     (
13         name: wasmtime_component_vallist_t,
14         ty: wasmtime_component_val_t,
15         new: wasmtime_component_vallist_new,
16         empty: wasmtime_component_vallist_new_empty,
17         uninit: wasmtime_component_vallist_new_uninit,
18         copy: wasmtime_component_vallist_copy,
19         delete: wasmtime_component_vallist_delete,
20     )
21     (
22         name: wasmtime_component_valrecord_t,
23         ty: wasmtime_component_valrecord_entry_t,
24         new: wasmtime_component_valrecord_new,
25         empty: wasmtime_component_valrecord_new_empty,
26         uninit: wasmtime_component_valrecord_new_uninit,
27         copy: wasmtime_component_valrecord_copy,
28         delete: wasmtime_component_valrecord_delete,
29     )
30     (
31         name: wasmtime_component_valtuple_t,
32         ty: wasmtime_component_val_t,
33         new: wasmtime_component_valtuple_new,
34         empty: wasmtime_component_valtuple_new_empty,
35         uninit: wasmtime_component_valtuple_new_uninit,
36         copy: wasmtime_component_valtuple_copy,
37         delete: wasmtime_component_valtuple_delete,
38     )
39     (
40         name: wasmtime_component_valflags_t,
41         ty: wasm_name_t,
42         new: wasmtime_component_valflags_new,
43         empty: wasmtime_component_valflags_new_empty,
44         uninit: wasmtime_component_valflags_new_uninit,
45         copy: wasmtime_component_valflags_copy,
46         delete: wasmtime_component_valflags_delete,
47     )
48 }
49 
50 impl From<&wasmtime_component_vallist_t> for Vec<Val> {
51     fn from(value: &wasmtime_component_vallist_t) -> Self {
52         value.as_slice().iter().map(Val::from).collect()
53     }
54 }
55 
56 impl From<&[Val]> for wasmtime_component_vallist_t {
57     fn from(value: &[Val]) -> Self {
58         value
59             .iter()
60             .map(wasmtime_component_val_t::from)
61             .collect::<Vec<_>>()
62             .into()
63     }
64 }
65 
66 #[derive(Clone)]
67 #[repr(C)]
68 pub struct wasmtime_component_valrecord_entry_t {
69     name: wasm_name_t,
70     val: wasmtime_component_val_t,
71 }
72 
73 impl Default for wasmtime_component_valrecord_entry_t {
74     fn default() -> Self {
75         Self {
76             name: wasm_name_t::from_name(String::new()),
77             val: Default::default(),
78         }
79     }
80 }
81 
82 impl From<&wasmtime_component_valrecord_entry_t> for (String, Val) {
83     fn from(value: &wasmtime_component_valrecord_entry_t) -> Self {
84         (
85             String::from_utf8(value.name.clone().take()).unwrap(),
86             Val::from(&value.val),
87         )
88     }
89 }
90 
91 impl From<&(String, Val)> for wasmtime_component_valrecord_entry_t {
92     fn from((name, val): &(String, Val)) -> Self {
93         Self {
94             name: wasm_name_t::from_name(name.clone()),
95             val: wasmtime_component_val_t::from(val),
96         }
97     }
98 }
99 
100 impl From<&wasmtime_component_valrecord_t> for Vec<(String, Val)> {
101     fn from(value: &wasmtime_component_valrecord_t) -> Self {
102         value.as_slice().iter().map(Into::into).collect()
103     }
104 }
105 
106 impl From<&[(String, Val)]> for wasmtime_component_valrecord_t {
107     fn from(value: &[(String, Val)]) -> Self {
108         value
109             .iter()
110             .map(wasmtime_component_valrecord_entry_t::from)
111             .collect::<Vec<_>>()
112             .into()
113     }
114 }
115 
116 impl From<&wasmtime_component_valtuple_t> for Vec<Val> {
117     fn from(value: &wasmtime_component_valtuple_t) -> Self {
118         value.as_slice().iter().map(Val::from).collect()
119     }
120 }
121 
122 impl From<&[Val]> for wasmtime_component_valtuple_t {
123     fn from(value: &[Val]) -> Self {
124         value
125             .iter()
126             .map(wasmtime_component_val_t::from)
127             .collect::<Vec<_>>()
128             .into()
129     }
130 }
131 
132 impl From<&wasmtime_component_valflags_t> for Vec<String> {
133     fn from(value: &wasmtime_component_valflags_t) -> Self {
134         value
135             .clone()
136             .take()
137             .into_iter()
138             .map(|mut x| String::from_utf8(x.take()))
139             .collect::<Result<Vec<_>, _>>()
140             .unwrap()
141     }
142 }
143 
144 impl From<&[String]> for wasmtime_component_valflags_t {
145     fn from(value: &[String]) -> Self {
146         value
147             .iter()
148             .map(|x| wasm_name_t::from_name(x.clone()))
149             .collect::<Vec<_>>()
150             .into()
151     }
152 }
153 
154 #[repr(C)]
155 #[derive(Clone)]
156 pub struct wasmtime_component_valvariant_t {
157     discriminant: wasm_name_t,
158     val: Option<Box<wasmtime_component_val_t>>,
159 }
160 
161 impl From<(&String, &Option<Box<Val>>)> for wasmtime_component_valvariant_t {
162     fn from((discriminant, value): (&String, &Option<Box<Val>>)) -> Self {
163         Self {
164             discriminant: wasm_name_t::from_name(discriminant.clone()),
165             val: value
166                 .as_ref()
167                 .map(|x| Box::new(wasmtime_component_val_t::from(x.as_ref()))),
168         }
169     }
170 }
171 
172 impl From<&wasmtime_component_valvariant_t> for (String, Option<Box<Val>>) {
173     fn from(value: &wasmtime_component_valvariant_t) -> Self {
174         (
175             String::from_utf8(value.discriminant.clone().take()).unwrap(),
176             value.val.as_ref().map(|x| Box::new(Val::from(x.as_ref()))),
177         )
178     }
179 }
180 
181 #[repr(C)]
182 #[derive(Clone)]
183 pub struct wasmtime_component_valresult_t {
184     is_ok: bool,
185     val: Option<Box<wasmtime_component_val_t>>,
186 }
187 
188 impl From<&wasmtime_component_valresult_t> for Result<Option<Box<Val>>, Option<Box<Val>>> {
189     fn from(value: &wasmtime_component_valresult_t) -> Self {
190         let val = value.val.as_ref().map(|x| Box::new(Val::from(x.as_ref())));
191 
192         match value.is_ok {
193             true => Ok(val),
194             false => Err(val),
195         }
196     }
197 }
198 
199 impl From<&Result<Option<Box<Val>>, Option<Box<Val>>>> for wasmtime_component_valresult_t {
200     fn from(value: &Result<Option<Box<Val>>, Option<Box<Val>>>) -> Self {
201         let (Ok(x) | Err(x)) = value;
202 
203         Self {
204             is_ok: value.is_ok(),
205             val: x
206                 .as_ref()
207                 .map(|x| Box::new(wasmtime_component_val_t::from(x.as_ref()))),
208         }
209     }
210 }
211 
212 #[repr(C, u8)]
213 #[derive(Clone)]
214 pub enum wasmtime_component_val_t {
215     Bool(bool),
216     S8(i8),
217     U8(u8),
218     S16(i16),
219     U16(u16),
220     S32(i32),
221     U32(u32),
222     S64(i64),
223     U64(u64),
224     F32(f32),
225     F64(f64),
226     Char(u32),
227     String(wasm_name_t),
228     List(wasmtime_component_vallist_t),
229     Record(wasmtime_component_valrecord_t),
230     Tuple(wasmtime_component_valtuple_t),
231     Variant(wasmtime_component_valvariant_t),
232     Enum(wasm_name_t),
233     Option(Option<Box<Self>>),
234     Result(wasmtime_component_valresult_t),
235     Flags(wasmtime_component_valflags_t),
236     Resource(Box<wasmtime_component_resource_any_t>),
237 }
238 
239 impl Default for wasmtime_component_val_t {
240     fn default() -> Self {
241         Self::Bool(false)
242     }
243 }
244 
245 impl From<&wasmtime_component_val_t> for Val {
246     fn from(value: &wasmtime_component_val_t) -> Self {
247         match value {
248             wasmtime_component_val_t::Bool(x) => Val::Bool(*x),
249             wasmtime_component_val_t::S8(x) => Val::S8(*x),
250             wasmtime_component_val_t::U8(x) => Val::U8(*x),
251             wasmtime_component_val_t::S16(x) => Val::S16(*x),
252             wasmtime_component_val_t::U16(x) => Val::U16(*x),
253             wasmtime_component_val_t::S32(x) => Val::S32(*x),
254             wasmtime_component_val_t::U32(x) => Val::U32(*x),
255             wasmtime_component_val_t::S64(x) => Val::S64(*x),
256             wasmtime_component_val_t::U64(x) => Val::U64(*x),
257             wasmtime_component_val_t::F32(x) => Val::Float32(*x),
258             wasmtime_component_val_t::F64(x) => Val::Float64(*x),
259             wasmtime_component_val_t::Char(x) => Val::Char(char::from_u32(*x).unwrap()),
260             wasmtime_component_val_t::String(x) => {
261                 Val::String(String::from_utf8(x.clone().take()).unwrap())
262             }
263             wasmtime_component_val_t::List(x) => Val::List(x.into()),
264             wasmtime_component_val_t::Record(x) => Val::Record(x.into()),
265             wasmtime_component_val_t::Tuple(x) => Val::Tuple(x.into()),
266             wasmtime_component_val_t::Variant(x) => {
267                 let (a, b) = x.into();
268                 Val::Variant(a, b)
269             }
270             wasmtime_component_val_t::Enum(x) => {
271                 Val::Enum(String::from_utf8(x.clone().take()).unwrap())
272             }
273             wasmtime_component_val_t::Option(x) => {
274                 Val::Option(x.as_ref().map(|x| Box::new(Val::from(x.as_ref()))))
275             }
276             wasmtime_component_val_t::Result(x) => Val::Result(x.into()),
277             wasmtime_component_val_t::Flags(x) => Val::Flags(x.into()),
278             wasmtime_component_val_t::Resource(x) => Val::Resource(x.resource),
279         }
280     }
281 }
282 
283 impl From<&Val> for wasmtime_component_val_t {
284     fn from(value: &Val) -> Self {
285         match value {
286             Val::Bool(x) => wasmtime_component_val_t::Bool(*x),
287             Val::S8(x) => wasmtime_component_val_t::S8(*x),
288             Val::U8(x) => wasmtime_component_val_t::U8(*x),
289             Val::S16(x) => wasmtime_component_val_t::S16(*x),
290             Val::U16(x) => wasmtime_component_val_t::U16(*x),
291             Val::S32(x) => wasmtime_component_val_t::S32(*x),
292             Val::U32(x) => wasmtime_component_val_t::U32(*x),
293             Val::S64(x) => wasmtime_component_val_t::S64(*x),
294             Val::U64(x) => wasmtime_component_val_t::U64(*x),
295             Val::Float32(x) => wasmtime_component_val_t::F32(*x),
296             Val::Float64(x) => wasmtime_component_val_t::F64(*x),
297             Val::Char(x) => wasmtime_component_val_t::Char(*x as _),
298             Val::String(x) => wasmtime_component_val_t::String(wasm_name_t::from_name(x.clone())),
299             Val::List(x) => wasmtime_component_val_t::List(x.as_slice().into()),
300             Val::Record(x) => wasmtime_component_val_t::Record(x.as_slice().into()),
301             Val::Tuple(x) => wasmtime_component_val_t::Tuple(x.as_slice().into()),
302             Val::Variant(discriminant, val) => {
303                 wasmtime_component_val_t::Variant((discriminant, val).into())
304             }
305             Val::Enum(x) => wasmtime_component_val_t::Enum(wasm_name_t::from_name(x.clone())),
306             Val::Option(x) => wasmtime_component_val_t::Option(
307                 x.as_ref()
308                     .map(|x| Box::new(wasmtime_component_val_t::from(x.as_ref()))),
309             ),
310             Val::Result(x) => wasmtime_component_val_t::Result(x.into()),
311             Val::Flags(x) => wasmtime_component_val_t::Flags(x.as_slice().into()),
312             Val::Resource(resource_any) => {
313                 wasmtime_component_val_t::Resource(Box::new(wasmtime_component_resource_any_t {
314                     resource: *resource_any,
315                 }))
316             }
317             Val::Future(_) => todo!(),
318             Val::Stream(_) => todo!(),
319             Val::ErrorContext(_) => todo!(),
320         }
321     }
322 }
323 
324 #[unsafe(no_mangle)]
325 pub extern "C" fn wasmtime_component_val_new(
326     src: &mut wasmtime_component_val_t,
327 ) -> Box<wasmtime_component_val_t> {
328     Box::new(mem::replace(src, wasmtime_component_val_t::default()))
329 }
330 
331 #[unsafe(no_mangle)]
332 pub extern "C" fn wasmtime_component_val_free(_dst: Option<Box<wasmtime_component_val_t>>) {}
333 
334 #[unsafe(no_mangle)]
335 pub extern "C" fn wasmtime_component_val_clone(
336     src: &wasmtime_component_val_t,
337     dst: &mut MaybeUninit<wasmtime_component_val_t>,
338 ) {
339     dst.write(src.clone());
340 }
341 
342 #[unsafe(no_mangle)]
343 pub unsafe extern "C" fn wasmtime_component_val_delete(
344     value: &mut ManuallyDrop<wasmtime_component_val_t>,
345 ) {
346     unsafe {
347         ManuallyDrop::drop(value);
348     }
349 }
350 
351 #[repr(C)]
352 #[derive(Clone)]
353 pub struct wasmtime_component_resource_any_t {
354     resource: ResourceAny,
355 }
356 
357 #[unsafe(no_mangle)]
358 pub extern "C" fn wasmtime_component_resource_any_type(
359     resource: &wasmtime_component_resource_any_t,
360 ) -> Box<wasmtime_component_resource_type_t> {
361     Box::new(wasmtime_component_resource_type_t {
362         ty: resource.resource.ty(),
363     })
364 }
365 
366 #[unsafe(no_mangle)]
367 pub extern "C" fn wasmtime_component_resource_any_clone(
368     resource: &wasmtime_component_resource_any_t,
369 ) -> Box<wasmtime_component_resource_any_t> {
370     Box::new(wasmtime_component_resource_any_t {
371         resource: resource.resource,
372     })
373 }
374 
375 #[unsafe(no_mangle)]
376 pub extern "C" fn wasmtime_component_resource_any_owned(
377     resource: &wasmtime_component_resource_any_t,
378 ) -> bool {
379     resource.resource.owned()
380 }
381 
382 #[unsafe(no_mangle)]
383 pub extern "C" fn wasmtime_component_resource_any_drop(
384     store: WasmtimeStoreContextMut<'_>,
385     resource: &wasmtime_component_resource_any_t,
386 ) -> Option<Box<wasmtime_error_t>> {
387     handle_result(resource.resource.resource_drop(store), |()| ())
388 }
389 
390 #[unsafe(no_mangle)]
391 pub extern "C" fn wasmtime_component_resource_any_delete(
392     _resource: Option<Box<wasmtime_component_resource_any_t>>,
393 ) {
394 }
395 
396 #[repr(C)]
397 pub struct wasmtime_component_resource_host_t {
398     resource: ResourceDynamic,
399 }
400 
401 impl wasmtime_component_resource_host_t {
402     // "poor man's clone"
403     fn resource(&self) -> ResourceDynamic {
404         let rep = self.resource.rep();
405         let ty = self.resource.ty();
406         if self.resource.owned() {
407             ResourceDynamic::new_own(rep, ty)
408         } else {
409             ResourceDynamic::new_borrow(rep, ty)
410         }
411     }
412 }
413 
414 #[unsafe(no_mangle)]
415 pub extern "C" fn wasmtime_component_resource_host_new(
416     owned: bool,
417     rep: u32,
418     ty: u32,
419 ) -> Box<wasmtime_component_resource_host_t> {
420     Box::new(wasmtime_component_resource_host_t {
421         resource: if owned {
422             ResourceDynamic::new_own(rep, ty)
423         } else {
424             ResourceDynamic::new_borrow(rep, ty)
425         },
426     })
427 }
428 
429 #[unsafe(no_mangle)]
430 pub extern "C" fn wasmtime_component_resource_host_clone(
431     resource: &wasmtime_component_resource_host_t,
432 ) -> Box<wasmtime_component_resource_host_t> {
433     Box::new(wasmtime_component_resource_host_t {
434         resource: resource.resource(),
435     })
436 }
437 
438 #[unsafe(no_mangle)]
439 pub extern "C" fn wasmtime_component_resource_host_rep(
440     resource: &wasmtime_component_resource_host_t,
441 ) -> u32 {
442     resource.resource.rep()
443 }
444 
445 #[unsafe(no_mangle)]
446 pub extern "C" fn wasmtime_component_resource_host_type(
447     resource: &wasmtime_component_resource_host_t,
448 ) -> u32 {
449     resource.resource.ty()
450 }
451 
452 #[unsafe(no_mangle)]
453 pub extern "C" fn wasmtime_component_resource_host_owned(
454     resource: &wasmtime_component_resource_host_t,
455 ) -> bool {
456     resource.resource.owned()
457 }
458 
459 #[unsafe(no_mangle)]
460 pub extern "C" fn wasmtime_component_resource_host_delete(
461     _resource: Option<Box<wasmtime_component_resource_host_t>>,
462 ) {
463 }
464 
465 #[unsafe(no_mangle)]
466 pub extern "C" fn wasmtime_component_resource_any_to_host(
467     store: WasmtimeStoreContextMut<'_>,
468     resource: &wasmtime_component_resource_any_t,
469     ret: &mut MaybeUninit<Box<wasmtime_component_resource_host_t>>,
470 ) -> Option<Box<wasmtime_error_t>> {
471     handle_result(
472         resource.resource.try_into_resource_dynamic(store),
473         |resource| {
474             ret.write(Box::new(wasmtime_component_resource_host_t { resource }));
475         },
476     )
477 }
478 
479 #[unsafe(no_mangle)]
480 pub extern "C" fn wasmtime_component_resource_host_to_any(
481     store: WasmtimeStoreContextMut<'_>,
482     resource: &wasmtime_component_resource_host_t,
483     ret: &mut MaybeUninit<Box<wasmtime_component_resource_any_t>>,
484 ) -> Option<Box<wasmtime_error_t>> {
485     handle_result(
486         resource.resource().try_into_resource_any(store),
487         |resource| {
488             ret.write(Box::new(wasmtime_component_resource_any_t { resource }));
489         },
490     )
491 }
492