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