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