wasmtime_c_api/component/
val.rs

1use crate::{WasmtimeStoreContextMut, handle_result, wasm_name_t, wasmtime_error_t};
2use std::mem;
3use std::mem::{ManuallyDrop, MaybeUninit};
4use std::ptr;
5use std::slice;
6use wasmtime::component::{ResourceAny, ResourceDynamic, ResourceType, Val};
7
8crate::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
47impl 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
53impl 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)]
65pub struct wasmtime_component_valrecord_entry_t {
66    name: wasm_name_t,
67    val: wasmtime_component_val_t,
68}
69
70impl 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
79impl 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
88impl 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
97impl 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
103impl 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
113impl 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
119impl 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
129impl 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
141impl 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)]
153pub struct wasmtime_component_valvariant_t {
154    discriminant: wasm_name_t,
155    val: Option<Box<wasmtime_component_val_t>>,
156}
157
158impl 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
169impl 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)]
180pub struct wasmtime_component_valresult_t {
181    is_ok: bool,
182    val: Option<Box<wasmtime_component_val_t>>,
183}
184
185impl 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
196impl 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)]
211pub 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
236impl Default for wasmtime_component_val_t {
237    fn default() -> Self {
238        Self::Bool(false)
239    }
240}
241
242impl 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
280impl 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)]
322pub 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)]
329pub extern "C" fn wasmtime_component_val_free(_dst: Option<Box<wasmtime_component_val_t>>) {}
330
331#[unsafe(no_mangle)]
332pub 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)]
340pub 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)]
349pub struct wasmtime_component_resource_type_t {
350    pub(crate) ty: ResourceType,
351}
352
353#[unsafe(no_mangle)]
354pub 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)]
363pub 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)]
370pub 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)]
378pub 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)]
385pub struct wasmtime_component_resource_any_t {
386    resource: ResourceAny,
387}
388
389#[unsafe(no_mangle)]
390pub 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)]
399pub 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)]
408pub 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)]
415pub 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)]
423pub extern "C" fn wasmtime_component_resource_any_delete(
424    _resource: Option<Box<wasmtime_component_resource_any_t>>,
425) {
426}
427
428#[repr(C)]
429pub struct wasmtime_component_resource_host_t {
430    resource: ResourceDynamic,
431}
432
433impl 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)]
447pub 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)]
462pub 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)]
471pub 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)]
478pub 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)]
485pub 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)]
492pub extern "C" fn wasmtime_component_resource_host_delete(
493    _resource: Option<Box<wasmtime_component_resource_host_t>>,
494) {
495}
496
497#[unsafe(no_mangle)]
498pub 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)]
512pub 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}