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