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