wasmtime_c_api/component/
val.rs

1use crate::{
2    WasmtimeStoreContextMut, handle_result, wasm_name_t, wasmtime_component_resource_type_t,
3    wasmtime_error_t,
4};
5use std::mem;
6use std::mem::{ManuallyDrop, MaybeUninit};
7use std::ptr;
8use std::slice;
9use wasmtime::component::{ResourceAny, ResourceDynamic, Val};
10
11crate::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
50impl 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
56impl 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)]
68pub struct wasmtime_component_valrecord_entry_t {
69    name: wasm_name_t,
70    val: wasmtime_component_val_t,
71}
72
73impl 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
82impl 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
91impl 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
100impl 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
106impl 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
116impl 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
122impl 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
132impl 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
144impl 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)]
156pub struct wasmtime_component_valvariant_t {
157    discriminant: wasm_name_t,
158    val: Option<Box<wasmtime_component_val_t>>,
159}
160
161impl 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
172impl 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)]
183pub struct wasmtime_component_valresult_t {
184    is_ok: bool,
185    val: Option<Box<wasmtime_component_val_t>>,
186}
187
188impl 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
199impl 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)]
214pub 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
239impl Default for wasmtime_component_val_t {
240    fn default() -> Self {
241        Self::Bool(false)
242    }
243}
244
245impl 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
283impl 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)]
325pub 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)]
332pub extern "C" fn wasmtime_component_val_free(_dst: Option<Box<wasmtime_component_val_t>>) {}
333
334#[unsafe(no_mangle)]
335pub 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)]
343pub 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)]
353pub struct wasmtime_component_resource_any_t {
354    resource: ResourceAny,
355}
356
357#[unsafe(no_mangle)]
358pub 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)]
367pub 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)]
376pub 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)]
383pub 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)]
391pub extern "C" fn wasmtime_component_resource_any_delete(
392    _resource: Option<Box<wasmtime_component_resource_any_t>>,
393) {
394}
395
396#[repr(C)]
397pub struct wasmtime_component_resource_host_t {
398    resource: ResourceDynamic,
399}
400
401impl 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)]
415pub 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)]
430pub 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)]
439pub 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)]
446pub 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)]
453pub 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)]
460pub extern "C" fn wasmtime_component_resource_host_delete(
461    _resource: Option<Box<wasmtime_component_resource_host_t>>,
462) {
463}
464
465#[unsafe(no_mangle)]
466pub 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)]
480pub 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}