1 use crate::{WasmtimeStoreContextMut, abort}; 2 use std::mem::{ManuallyDrop, MaybeUninit}; 3 use std::{num::NonZeroU64, os::raw::c_void, ptr}; 4 use wasmtime::{ 5 AnyRef, ArrayRef, ArrayRefPre, ArrayType, EqRef, ExnRef, ExternRef, FieldType, I31, Mutability, 6 OwnedRooted, Ref, RootScope, StorageType, StructRef, StructRefPre, StructType, Val, ValType, 7 }; 8 9 /// `*mut wasm_ref_t` is a reference type (`externref` or `funcref`), as seen by 10 /// the C API. Because we do not have a uniform representation for `funcref`s 11 /// and `externref`s, a `*mut wasm_ref_t` is morally a 12 /// `Option<Box<Either<ExternRef, Func>>>`. 13 /// 14 /// A null `*mut wasm_ref_t` is either a null `funcref` or a null `externref` 15 /// depending on context (e.g. the table's element type that it is going into or 16 /// coming out of). 17 /// 18 /// Note: this is not `#[repr(C)]` because it is an opaque type in the header, 19 /// and only ever referenced as `*mut wasm_ref_t`. This also lets us use a 20 /// regular, non-`repr(C)` `enum` to define `WasmRefInner`. 21 #[derive(Clone)] 22 pub struct wasm_ref_t { 23 pub(crate) r: Ref, 24 } 25 26 wasmtime_c_api_macros::declare_own!(wasm_ref_t); 27 28 impl wasm_ref_t { 29 pub(crate) fn new(r: Ref) -> Option<Box<wasm_ref_t>> { 30 if r.is_null() || !r.is_func() { 31 None 32 } else { 33 Some(Box::new(wasm_ref_t { r })) 34 } 35 } 36 } 37 38 pub(crate) fn ref_to_val(r: &wasm_ref_t) -> Val { 39 Val::from(r.r.clone()) 40 } 41 42 #[unsafe(no_mangle)] 43 pub extern "C" fn wasm_ref_copy(r: Option<&wasm_ref_t>) -> Option<Box<wasm_ref_t>> { 44 r.map(|r| Box::new(r.clone())) 45 } 46 47 #[unsafe(no_mangle)] 48 pub extern "C" fn wasm_ref_same(_a: Option<&wasm_ref_t>, _b: Option<&wasm_ref_t>) -> bool { 49 // We need a store to determine whether these are the same reference or not. 50 abort("wasm_ref_same") 51 } 52 53 #[unsafe(no_mangle)] 54 pub extern "C" fn wasm_ref_get_host_info(_ref: Option<&wasm_ref_t>) -> *mut c_void { 55 std::ptr::null_mut() 56 } 57 58 #[unsafe(no_mangle)] 59 pub extern "C" fn wasm_ref_set_host_info(_ref: Option<&wasm_ref_t>, _info: *mut c_void) { 60 abort("wasm_ref_set_host_info") 61 } 62 63 #[unsafe(no_mangle)] 64 pub extern "C" fn wasm_ref_set_host_info_with_finalizer( 65 _ref: Option<&wasm_ref_t>, 66 _info: *mut c_void, 67 _finalizer: Option<extern "C" fn(*mut c_void)>, 68 ) { 69 abort("wasm_ref_set_host_info_with_finalizer") 70 } 71 72 #[unsafe(no_mangle)] 73 pub extern "C" fn wasm_ref_as_extern(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_extern_t> { 74 abort("wasm_ref_as_extern") 75 } 76 77 #[unsafe(no_mangle)] 78 pub extern "C" fn wasm_ref_as_extern_const( 79 _ref: Option<&wasm_ref_t>, 80 ) -> Option<&crate::wasm_extern_t> { 81 abort("wasm_ref_as_extern_const") 82 } 83 84 #[unsafe(no_mangle)] 85 pub extern "C" fn wasm_ref_as_foreign(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_foreign_t> { 86 abort("wasm_ref_as_foreign") 87 } 88 89 #[unsafe(no_mangle)] 90 pub extern "C" fn wasm_ref_as_foreign_const( 91 _ref: Option<&wasm_ref_t>, 92 ) -> Option<&crate::wasm_foreign_t> { 93 abort("wasm_ref_as_foreign_const") 94 } 95 96 #[unsafe(no_mangle)] 97 pub extern "C" fn wasm_ref_as_func(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_func_t> { 98 abort("wasm_ref_as_func") 99 } 100 101 #[unsafe(no_mangle)] 102 pub extern "C" fn wasm_ref_as_func_const(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_func_t> { 103 abort("wasm_ref_as_func_const") 104 } 105 106 #[unsafe(no_mangle)] 107 pub extern "C" fn wasm_ref_as_global(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_global_t> { 108 abort("wasm_ref_as_global") 109 } 110 111 #[unsafe(no_mangle)] 112 pub extern "C" fn wasm_ref_as_global_const( 113 _ref: Option<&wasm_ref_t>, 114 ) -> Option<&crate::wasm_global_t> { 115 abort("wasm_ref_as_global_const") 116 } 117 118 #[unsafe(no_mangle)] 119 pub extern "C" fn wasm_ref_as_instance( 120 _ref: Option<&wasm_ref_t>, 121 ) -> Option<&crate::wasm_instance_t> { 122 abort("wasm_ref_as_instance") 123 } 124 125 #[unsafe(no_mangle)] 126 pub extern "C" fn wasm_ref_as_instance_const( 127 _ref: Option<&wasm_ref_t>, 128 ) -> Option<&crate::wasm_instance_t> { 129 abort("wasm_ref_as_instance_const") 130 } 131 132 #[unsafe(no_mangle)] 133 pub extern "C" fn wasm_ref_as_memory(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_memory_t> { 134 abort("wasm_ref_as_memory") 135 } 136 137 #[unsafe(no_mangle)] 138 pub extern "C" fn wasm_ref_as_memory_const( 139 _ref: Option<&wasm_ref_t>, 140 ) -> Option<&crate::wasm_memory_t> { 141 abort("wasm_ref_as_memory_const") 142 } 143 144 #[unsafe(no_mangle)] 145 pub extern "C" fn wasm_ref_as_module(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_module_t> { 146 abort("wasm_ref_as_module") 147 } 148 149 #[unsafe(no_mangle)] 150 pub extern "C" fn wasm_ref_as_module_const( 151 _ref: Option<&wasm_ref_t>, 152 ) -> Option<&crate::wasm_module_t> { 153 abort("wasm_ref_as_module_const") 154 } 155 156 #[unsafe(no_mangle)] 157 pub extern "C" fn wasm_ref_as_table(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_table_t> { 158 abort("wasm_ref_as_table") 159 } 160 161 #[unsafe(no_mangle)] 162 pub extern "C" fn wasm_ref_as_table_const( 163 _ref: Option<&wasm_ref_t>, 164 ) -> Option<&crate::wasm_table_t> { 165 abort("wasm_ref_as_table_const") 166 } 167 168 #[unsafe(no_mangle)] 169 pub extern "C" fn wasm_ref_as_trap(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_trap_t> { 170 abort("wasm_ref_as_trap") 171 } 172 173 #[unsafe(no_mangle)] 174 pub extern "C" fn wasm_ref_as_trap_const(_ref: Option<&wasm_ref_t>) -> Option<&crate::wasm_trap_t> { 175 abort("wasm_ref_as_trap_const") 176 } 177 178 #[derive(Clone)] 179 #[repr(C)] 180 pub struct wasm_foreign_t {} 181 182 wasmtime_c_api_macros::declare_ref!(wasm_foreign_t); 183 184 #[unsafe(no_mangle)] 185 pub extern "C" fn wasm_foreign_new(_store: &crate::wasm_store_t) -> Box<wasm_foreign_t> { 186 abort("wasm_foreign_new") 187 } 188 189 /// C-API representation of `anyref`. 190 /// 191 /// This represented differently in the C API from the header to handle how 192 /// this is dispatched internally. Null anyref values are represented with a 193 /// `store_id` of zero, and otherwise the `rooted` field is valid. 194 /// 195 /// Note that this relies on the Wasmtime definition of `OwnedRooted` to have 196 /// a 64-bit store_id first. 197 macro_rules! ref_wrapper { 198 ($wasmtime:ident => $c:ident) => { 199 pub struct $c { 200 store_id: u64, 201 a: u32, 202 b: u32, 203 c: *const (), 204 } 205 206 impl $c { 207 pub unsafe fn as_wasmtime(&self) -> Option<OwnedRooted<$wasmtime>> { 208 let store_id = NonZeroU64::new(self.store_id)?; 209 Some(OwnedRooted::from_borrowed_raw_parts_for_c_api( 210 store_id, self.a, self.b, self.c, 211 )) 212 } 213 214 pub unsafe fn into_wasmtime(self) -> Option<OwnedRooted<$wasmtime>> { 215 ManuallyDrop::new(self).to_owned() 216 } 217 218 unsafe fn to_owned(&self) -> Option<OwnedRooted<$wasmtime>> { 219 let store_id = NonZeroU64::new(self.store_id)?; 220 Some(OwnedRooted::from_owned_raw_parts_for_c_api( 221 store_id, self.a, self.b, self.c, 222 )) 223 } 224 } 225 226 impl Drop for $c { 227 fn drop(&mut self) { 228 unsafe { 229 let _ = self.to_owned(); 230 } 231 } 232 } 233 234 impl From<Option<OwnedRooted<$wasmtime>>> for $c { 235 fn from(rooted: Option<OwnedRooted<$wasmtime>>) -> $c { 236 let mut ret = $c { 237 store_id: 0, 238 a: 0, 239 b: 0, 240 c: core::ptr::null(), 241 }; 242 if let Some(rooted) = rooted { 243 let (store_id, a, b, c) = rooted.into_parts_for_c_api(); 244 ret.store_id = store_id.get(); 245 ret.a = a; 246 ret.b = b; 247 ret.c = c; 248 } 249 ret 250 } 251 } 252 253 impl From<OwnedRooted<$wasmtime>> for $c { 254 fn from(rooted: OwnedRooted<$wasmtime>) -> $c { 255 Self::from(Some(rooted)) 256 } 257 } 258 259 // SAFETY: The `*const ()` comes from (and is converted back 260 // into) an `Arc<()>`, and is only accessed as such, so this 261 // type is both Send and Sync. These constraints are necessary 262 // in the async machinery in this crate. 263 unsafe impl Send for $c {} 264 unsafe impl Sync for $c {} 265 }; 266 } 267 268 ref_wrapper!(AnyRef => wasmtime_anyref_t); 269 ref_wrapper!(ExternRef => wasmtime_externref_t); 270 ref_wrapper!(EqRef => wasmtime_eqref_t); 271 ref_wrapper!(StructRef => wasmtime_structref_t); 272 ref_wrapper!(ExnRef => wasmtime_exnref_t); 273 274 // Opaque types for struct type and struct ref pre-allocator 275 pub struct wasmtime_struct_type_t { 276 ty: StructType, 277 } 278 wasmtime_c_api_macros::declare_own!(wasmtime_struct_type_t); 279 280 pub struct wasmtime_struct_ref_pre_t { 281 pre: StructRefPre, 282 } 283 wasmtime_c_api_macros::declare_own!(wasmtime_struct_ref_pre_t); 284 285 ref_wrapper!(ArrayRef => wasmtime_arrayref_t); 286 287 pub struct wasmtime_array_type_t { 288 ty: ArrayType, 289 } 290 wasmtime_c_api_macros::declare_own!(wasmtime_array_type_t); 291 292 pub struct wasmtime_array_ref_pre_t { 293 pre: ArrayRefPre, 294 } 295 wasmtime_c_api_macros::declare_own!(wasmtime_array_ref_pre_t); 296 297 #[unsafe(no_mangle)] 298 pub unsafe extern "C" fn wasmtime_anyref_clone( 299 anyref: Option<&wasmtime_anyref_t>, 300 out: &mut MaybeUninit<wasmtime_anyref_t>, 301 ) { 302 let anyref = anyref.and_then(|a| a.as_wasmtime()); 303 crate::initialize(out, anyref.into()); 304 } 305 306 #[unsafe(no_mangle)] 307 pub unsafe extern "C" fn wasmtime_anyref_unroot(val: Option<&mut ManuallyDrop<wasmtime_anyref_t>>) { 308 if let Some(val) = val { 309 unsafe { 310 ManuallyDrop::drop(val); 311 } 312 } 313 } 314 315 #[unsafe(no_mangle)] 316 pub unsafe extern "C" fn wasmtime_anyref_to_raw( 317 cx: WasmtimeStoreContextMut<'_>, 318 val: Option<&wasmtime_anyref_t>, 319 ) -> u32 { 320 val.and_then(|v| v.as_wasmtime()) 321 .and_then(|e| e.to_raw(cx).ok()) 322 .unwrap_or_default() 323 } 324 325 #[unsafe(no_mangle)] 326 pub unsafe extern "C" fn wasmtime_anyref_from_raw( 327 cx: WasmtimeStoreContextMut<'_>, 328 raw: u32, 329 val: &mut MaybeUninit<wasmtime_anyref_t>, 330 ) { 331 let mut scope = RootScope::new(cx); 332 let anyref = 333 AnyRef::from_raw(&mut scope, raw).map(|a| a.to_owned_rooted(&mut scope).expect("in scope")); 334 crate::initialize(val, anyref.into()); 335 } 336 337 #[unsafe(no_mangle)] 338 pub extern "C" fn wasmtime_anyref_from_i31( 339 cx: WasmtimeStoreContextMut<'_>, 340 val: u32, 341 out: &mut MaybeUninit<wasmtime_anyref_t>, 342 ) { 343 let mut scope = RootScope::new(cx); 344 let anyref = AnyRef::from_i31(&mut scope, I31::wrapping_u32(val)); 345 let anyref = anyref.to_owned_rooted(&mut scope).expect("in scope"); 346 crate::initialize(out, Some(anyref).into()) 347 } 348 349 #[unsafe(no_mangle)] 350 pub unsafe extern "C" fn wasmtime_anyref_is_i31( 351 cx: WasmtimeStoreContextMut<'_>, 352 anyref: Option<&wasmtime_anyref_t>, 353 ) -> bool { 354 match anyref.and_then(|a| a.as_wasmtime()) { 355 Some(anyref) => anyref.is_i31(&cx).expect("OwnedRooted always in scope"), 356 None => false, 357 } 358 } 359 360 #[unsafe(no_mangle)] 361 pub unsafe extern "C" fn wasmtime_anyref_i31_get_u( 362 cx: WasmtimeStoreContextMut<'_>, 363 anyref: Option<&wasmtime_anyref_t>, 364 dst: &mut MaybeUninit<u32>, 365 ) -> bool { 366 match anyref.and_then(|a| a.as_wasmtime()) { 367 Some(anyref) if anyref.is_i31(&cx).expect("OwnedRooted always in scope") => { 368 let val = anyref 369 .unwrap_i31(&cx) 370 .expect("OwnedRooted always in scope") 371 .get_u32(); 372 crate::initialize(dst, val); 373 true 374 } 375 _ => false, 376 } 377 } 378 379 #[unsafe(no_mangle)] 380 pub unsafe extern "C" fn wasmtime_anyref_i31_get_s( 381 cx: WasmtimeStoreContextMut<'_>, 382 anyref: Option<&wasmtime_anyref_t>, 383 dst: &mut MaybeUninit<i32>, 384 ) -> bool { 385 match anyref.and_then(|a| a.as_wasmtime()) { 386 Some(anyref) if anyref.is_i31(&cx).expect("OwnedRooted always in scope") => { 387 let val = anyref 388 .unwrap_i31(&cx) 389 .expect("OwnedRooted always in scope") 390 .get_i32(); 391 crate::initialize(dst, val); 392 true 393 } 394 _ => false, 395 } 396 } 397 398 #[unsafe(no_mangle)] 399 pub extern "C" fn wasmtime_externref_new( 400 cx: WasmtimeStoreContextMut<'_>, 401 data: *mut c_void, 402 finalizer: Option<extern "C" fn(*mut c_void)>, 403 out: &mut MaybeUninit<wasmtime_externref_t>, 404 ) -> bool { 405 let mut scope = RootScope::new(cx); 406 let e = match ExternRef::new(&mut scope, crate::ForeignData { data, finalizer }) { 407 Ok(e) => e, 408 Err(_) => return false, 409 }; 410 let e = e.to_owned_rooted(&mut scope).expect("in scope"); 411 crate::initialize(out, Some(e).into()); 412 true 413 } 414 415 #[unsafe(no_mangle)] 416 pub unsafe extern "C" fn wasmtime_externref_data( 417 cx: WasmtimeStoreContextMut<'_>, 418 externref: Option<&wasmtime_externref_t>, 419 ) -> *mut c_void { 420 externref 421 .and_then(|e| e.as_wasmtime()) 422 .and_then(|e| { 423 let data = e.data(cx).ok()??; 424 Some(data.downcast_ref::<crate::ForeignData>().unwrap().data) 425 }) 426 .unwrap_or(ptr::null_mut()) 427 } 428 429 #[unsafe(no_mangle)] 430 pub unsafe extern "C" fn wasmtime_externref_clone( 431 externref: Option<&wasmtime_externref_t>, 432 out: &mut MaybeUninit<wasmtime_externref_t>, 433 ) { 434 let externref = externref.and_then(|e| e.as_wasmtime()); 435 crate::initialize(out, externref.into()); 436 } 437 438 #[unsafe(no_mangle)] 439 pub unsafe extern "C" fn wasmtime_externref_unroot( 440 val: Option<&mut ManuallyDrop<wasmtime_externref_t>>, 441 ) { 442 if let Some(val) = val { 443 unsafe { 444 ManuallyDrop::drop(val); 445 } 446 } 447 } 448 449 #[unsafe(no_mangle)] 450 pub unsafe extern "C" fn wasmtime_externref_to_raw( 451 cx: WasmtimeStoreContextMut<'_>, 452 val: Option<&wasmtime_externref_t>, 453 ) -> u32 { 454 val.and_then(|e| e.as_wasmtime()) 455 .and_then(|e| e.to_raw(cx).ok()) 456 .unwrap_or_default() 457 } 458 459 #[unsafe(no_mangle)] 460 pub unsafe extern "C" fn wasmtime_externref_from_raw( 461 cx: WasmtimeStoreContextMut<'_>, 462 raw: u32, 463 val: &mut MaybeUninit<wasmtime_externref_t>, 464 ) { 465 let mut scope = RootScope::new(cx); 466 let rooted = ExternRef::from_raw(&mut scope, raw) 467 .map(|e| e.to_owned_rooted(&mut scope).expect("in scope")); 468 crate::initialize(val, rooted.into()); 469 } 470 471 #[unsafe(no_mangle)] 472 pub unsafe extern "C" fn wasmtime_exnref_clone( 473 exnref: Option<&wasmtime_exnref_t>, 474 out: &mut MaybeUninit<wasmtime_exnref_t>, 475 ) { 476 let exnref = exnref.and_then(|e| e.as_wasmtime()); 477 crate::initialize(out, exnref.into()); 478 } 479 480 #[unsafe(no_mangle)] 481 pub unsafe extern "C" fn wasmtime_exnref_unroot(val: Option<&mut ManuallyDrop<wasmtime_exnref_t>>) { 482 if let Some(val) = val { 483 unsafe { 484 ManuallyDrop::drop(val); 485 } 486 } 487 } 488 489 #[unsafe(no_mangle)] 490 pub unsafe extern "C" fn wasmtime_eqref_clone( 491 eqref: Option<&wasmtime_eqref_t>, 492 out: &mut MaybeUninit<wasmtime_eqref_t>, 493 ) { 494 let eqref = eqref.and_then(|e| e.as_wasmtime()); 495 crate::initialize(out, eqref.into()); 496 } 497 498 #[unsafe(no_mangle)] 499 pub unsafe extern "C" fn wasmtime_eqref_unroot(val: Option<&mut ManuallyDrop<wasmtime_eqref_t>>) { 500 if let Some(val) = val { 501 unsafe { 502 ManuallyDrop::drop(val); 503 } 504 } 505 } 506 507 #[unsafe(no_mangle)] 508 pub unsafe extern "C" fn wasmtime_eqref_to_anyref( 509 eqref: Option<&wasmtime_eqref_t>, 510 out: &mut MaybeUninit<wasmtime_anyref_t>, 511 ) { 512 let anyref = eqref.and_then(|e| e.as_wasmtime()).map(|e| e.to_anyref()); 513 crate::initialize(out, anyref.into()); 514 } 515 516 #[unsafe(no_mangle)] 517 pub extern "C" fn wasmtime_eqref_from_i31( 518 cx: WasmtimeStoreContextMut<'_>, 519 val: u32, 520 out: &mut MaybeUninit<wasmtime_eqref_t>, 521 ) { 522 let mut scope = RootScope::new(cx); 523 let eqref = EqRef::from_i31(&mut scope, I31::wrapping_u32(val)); 524 let eqref = eqref.to_owned_rooted(&mut scope).expect("in scope"); 525 crate::initialize(out, Some(eqref).into()) 526 } 527 528 #[unsafe(no_mangle)] 529 pub unsafe extern "C" fn wasmtime_eqref_is_i31( 530 cx: WasmtimeStoreContextMut<'_>, 531 eqref: Option<&wasmtime_eqref_t>, 532 ) -> bool { 533 match eqref.and_then(|e| e.as_wasmtime()) { 534 Some(eqref) => eqref.is_i31(&cx).expect("OwnedRooted always in scope"), 535 None => false, 536 } 537 } 538 539 #[unsafe(no_mangle)] 540 pub unsafe extern "C" fn wasmtime_eqref_i31_get_u( 541 cx: WasmtimeStoreContextMut<'_>, 542 eqref: Option<&wasmtime_eqref_t>, 543 dst: &mut MaybeUninit<u32>, 544 ) -> bool { 545 let mut scope = RootScope::new(cx); 546 if let Some(eqref) = eqref.and_then(|e| e.as_wasmtime()) { 547 if let Some(val) = eqref.as_i31(&mut scope).expect("in scope") { 548 crate::initialize(dst, val.get_u32()); 549 return true; 550 } 551 } 552 false 553 } 554 555 #[unsafe(no_mangle)] 556 pub unsafe extern "C" fn wasmtime_eqref_i31_get_s( 557 cx: WasmtimeStoreContextMut<'_>, 558 eqref: Option<&wasmtime_eqref_t>, 559 dst: &mut MaybeUninit<i32>, 560 ) -> bool { 561 let mut scope = RootScope::new(cx); 562 if let Some(eqref) = eqref.and_then(|e| e.as_wasmtime()) { 563 if let Some(val) = eqref.as_i31(&mut scope).expect("in scope") { 564 crate::initialize(dst, val.get_i32()); 565 return true; 566 } 567 } 568 false 569 } 570 571 pub type wasmtime_storage_kind_t = u8; 572 pub const WASMTIME_STORAGE_KIND_I8: wasmtime_storage_kind_t = 9; 573 pub const WASMTIME_STORAGE_KIND_I16: wasmtime_storage_kind_t = 10; 574 575 #[repr(C)] 576 pub struct wasmtime_field_type_t { 577 pub kind: wasmtime_storage_kind_t, 578 pub mutable_: bool, 579 } 580 581 fn field_type_from_c(ft: &wasmtime_field_type_t) -> FieldType { 582 let mutability = if ft.mutable_ { 583 Mutability::Var 584 } else { 585 Mutability::Const 586 }; 587 let storage = match ft.kind { 588 WASMTIME_STORAGE_KIND_I8 => StorageType::I8, 589 WASMTIME_STORAGE_KIND_I16 => StorageType::I16, 590 crate::WASMTIME_I32 => StorageType::ValType(ValType::I32), 591 crate::WASMTIME_I64 => StorageType::ValType(ValType::I64), 592 crate::WASMTIME_F32 => StorageType::ValType(ValType::F32), 593 crate::WASMTIME_F64 => StorageType::ValType(ValType::F64), 594 crate::WASMTIME_V128 => StorageType::ValType(ValType::V128), 595 crate::WASMTIME_FUNCREF => StorageType::ValType(ValType::FUNCREF), 596 crate::WASMTIME_EXTERNREF => StorageType::ValType(ValType::EXTERNREF), 597 crate::WASMTIME_ANYREF => StorageType::ValType(ValType::ANYREF), 598 crate::WASMTIME_EXNREF => StorageType::ValType(ValType::EXNREF), 599 other => panic!("unknown wasmtime_storage_kind_t: {other}"), 600 }; 601 FieldType::new(mutability, storage) 602 } 603 604 #[unsafe(no_mangle)] 605 pub extern "C" fn wasmtime_struct_type_new( 606 engine: &crate::wasm_engine_t, 607 fields: *const wasmtime_field_type_t, 608 nfields: usize, 609 ) -> Box<wasmtime_struct_type_t> { 610 let fields = if nfields == 0 { 611 &[] 612 } else { 613 unsafe { std::slice::from_raw_parts(fields, nfields) } 614 }; 615 let field_types: Vec<FieldType> = fields.iter().map(field_type_from_c).collect(); 616 let ty = StructType::new(&engine.engine, field_types).expect("failed to create struct type"); 617 Box::new(wasmtime_struct_type_t { ty }) 618 } 619 620 #[unsafe(no_mangle)] 621 pub extern "C" fn wasmtime_struct_ref_pre_new( 622 cx: WasmtimeStoreContextMut<'_>, 623 ty: &wasmtime_struct_type_t, 624 ) -> Box<wasmtime_struct_ref_pre_t> { 625 let pre = StructRefPre::new(cx, ty.ty.clone()); 626 Box::new(wasmtime_struct_ref_pre_t { pre }) 627 } 628 629 #[unsafe(no_mangle)] 630 pub unsafe extern "C" fn wasmtime_structref_new( 631 mut cx: WasmtimeStoreContextMut<'_>, 632 pre: &wasmtime_struct_ref_pre_t, 633 fields: *const crate::wasmtime_val_t, 634 nfields: usize, 635 out: &mut MaybeUninit<wasmtime_structref_t>, 636 ) -> Option<Box<crate::wasmtime_error_t>> { 637 let c_fields = if nfields == 0 { 638 &[] 639 } else { 640 std::slice::from_raw_parts(fields, nfields) 641 }; 642 let mut scope = RootScope::new(&mut cx); 643 let vals: Vec<Val> = c_fields.iter().map(|v| v.to_val(&mut scope)).collect(); 644 match StructRef::new(&mut scope, &pre.pre, &vals) { 645 Ok(structref) => { 646 let owned = structref 647 .to_owned_rooted(&mut scope) 648 .expect("just allocated"); 649 crate::initialize(out, Some(owned).into()); 650 None 651 } 652 Err(e) => { 653 crate::initialize(out, None::<OwnedRooted<StructRef>>.into()); 654 Some(Box::new(e.into())) 655 } 656 } 657 } 658 659 #[unsafe(no_mangle)] 660 pub unsafe extern "C" fn wasmtime_structref_clone( 661 structref: Option<&wasmtime_structref_t>, 662 out: &mut MaybeUninit<wasmtime_structref_t>, 663 ) { 664 let structref = structref.and_then(|s| s.as_wasmtime()); 665 crate::initialize(out, structref.into()); 666 } 667 668 #[unsafe(no_mangle)] 669 pub unsafe extern "C" fn wasmtime_structref_unroot( 670 structref: Option<&mut ManuallyDrop<wasmtime_structref_t>>, 671 ) { 672 if let Some(structref) = structref { 673 ManuallyDrop::drop(structref); 674 } 675 } 676 677 #[unsafe(no_mangle)] 678 pub unsafe extern "C" fn wasmtime_structref_to_anyref( 679 structref: Option<&wasmtime_structref_t>, 680 out: &mut MaybeUninit<wasmtime_anyref_t>, 681 ) { 682 let anyref = structref 683 .and_then(|s| s.as_wasmtime()) 684 .map(|s| s.to_anyref()); 685 crate::initialize(out, anyref.into()); 686 } 687 688 #[unsafe(no_mangle)] 689 pub unsafe extern "C" fn wasmtime_structref_to_eqref( 690 structref: Option<&wasmtime_structref_t>, 691 out: &mut MaybeUninit<wasmtime_eqref_t>, 692 ) { 693 let eqref = structref 694 .and_then(|s| s.as_wasmtime()) 695 .map(|s| s.to_eqref()); 696 crate::initialize(out, eqref.into()); 697 } 698 699 #[unsafe(no_mangle)] 700 pub unsafe extern "C" fn wasmtime_structref_field( 701 mut cx: WasmtimeStoreContextMut<'_>, 702 structref: Option<&wasmtime_structref_t>, 703 index: usize, 704 out: &mut MaybeUninit<crate::wasmtime_val_t>, 705 ) -> Option<Box<crate::wasmtime_error_t>> { 706 let structref = structref 707 .and_then(|s| s.as_wasmtime()) 708 .expect("non-null structref required"); 709 let mut scope = RootScope::new(&mut cx); 710 let rooted = structref.to_rooted(&mut scope); 711 match rooted.field(&mut scope, index) { 712 Ok(val) => { 713 let c_val = crate::wasmtime_val_t::from_val(&mut scope, val); 714 crate::initialize(out, c_val); 715 None 716 } 717 Err(e) => Some(Box::new(e.into())), 718 } 719 } 720 721 #[unsafe(no_mangle)] 722 pub unsafe extern "C" fn wasmtime_structref_set_field( 723 mut cx: WasmtimeStoreContextMut<'_>, 724 structref: Option<&wasmtime_structref_t>, 725 index: usize, 726 val: &crate::wasmtime_val_t, 727 ) -> Option<Box<crate::wasmtime_error_t>> { 728 let structref = structref 729 .and_then(|s| s.as_wasmtime()) 730 .expect("non-null structref required"); 731 let mut scope = RootScope::new(&mut cx); 732 let rooted = structref.to_rooted(&mut scope); 733 let rust_val = val.to_val(&mut scope); 734 match rooted.set_field(&mut scope, index, rust_val) { 735 Ok(()) => None, 736 Err(e) => Some(Box::new(e.into())), 737 } 738 } 739 740 #[unsafe(no_mangle)] 741 pub unsafe extern "C" fn wasmtime_eqref_is_struct( 742 cx: WasmtimeStoreContextMut<'_>, 743 eqref: Option<&wasmtime_eqref_t>, 744 ) -> bool { 745 match eqref.and_then(|e| e.as_wasmtime()) { 746 Some(eqref) => eqref.is_struct(&cx).expect("OwnedRooted always in scope"), 747 None => false, 748 } 749 } 750 751 #[unsafe(no_mangle)] 752 pub unsafe extern "C" fn wasmtime_eqref_as_struct( 753 mut cx: WasmtimeStoreContextMut<'_>, 754 eqref: Option<&wasmtime_eqref_t>, 755 out: &mut MaybeUninit<wasmtime_structref_t>, 756 ) -> bool { 757 if let Some(eqref) = eqref.and_then(|e| e.as_wasmtime()) { 758 let mut scope = RootScope::new(&mut cx); 759 let rooted = eqref.to_rooted(&mut scope); 760 if let Ok(Some(structref)) = rooted.as_struct(&scope) { 761 let owned = structref.to_owned_rooted(&mut scope).expect("in scope"); 762 crate::initialize(out, Some(owned).into()); 763 return true; 764 } 765 } 766 crate::initialize(out, None::<OwnedRooted<StructRef>>.into()); 767 false 768 } 769 770 #[unsafe(no_mangle)] 771 pub extern "C" fn wasmtime_array_type_new( 772 engine: &crate::wasm_engine_t, 773 field: &wasmtime_field_type_t, 774 ) -> Box<wasmtime_array_type_t> { 775 let ft = field_type_from_c(field); 776 let ty = ArrayType::new(&engine.engine, ft); 777 Box::new(wasmtime_array_type_t { ty }) 778 } 779 780 #[unsafe(no_mangle)] 781 pub extern "C" fn wasmtime_array_ref_pre_new( 782 cx: WasmtimeStoreContextMut<'_>, 783 ty: &wasmtime_array_type_t, 784 ) -> Box<wasmtime_array_ref_pre_t> { 785 let pre = ArrayRefPre::new(cx, ty.ty.clone()); 786 Box::new(wasmtime_array_ref_pre_t { pre }) 787 } 788 789 #[unsafe(no_mangle)] 790 pub unsafe extern "C" fn wasmtime_arrayref_new( 791 mut cx: WasmtimeStoreContextMut<'_>, 792 pre: &wasmtime_array_ref_pre_t, 793 elem: &crate::wasmtime_val_t, 794 len: u32, 795 out: &mut MaybeUninit<wasmtime_arrayref_t>, 796 ) -> Option<Box<crate::wasmtime_error_t>> { 797 let mut scope = RootScope::new(&mut cx); 798 let val = elem.to_val(&mut scope); 799 match ArrayRef::new(&mut scope, &pre.pre, &val, len) { 800 Ok(arrayref) => { 801 let owned = arrayref 802 .to_owned_rooted(&mut scope) 803 .expect("just allocated"); 804 crate::initialize(out, Some(owned).into()); 805 None 806 } 807 Err(e) => { 808 crate::initialize(out, None::<OwnedRooted<ArrayRef>>.into()); 809 Some(Box::new(e.into())) 810 } 811 } 812 } 813 814 #[unsafe(no_mangle)] 815 pub unsafe extern "C" fn wasmtime_arrayref_clone( 816 arrayref: Option<&wasmtime_arrayref_t>, 817 out: &mut MaybeUninit<wasmtime_arrayref_t>, 818 ) { 819 let arrayref = arrayref.and_then(|a| a.as_wasmtime()); 820 crate::initialize(out, arrayref.into()); 821 } 822 823 #[unsafe(no_mangle)] 824 pub unsafe extern "C" fn wasmtime_arrayref_unroot( 825 arrayref: Option<&mut ManuallyDrop<wasmtime_arrayref_t>>, 826 ) { 827 if let Some(arrayref) = arrayref { 828 ManuallyDrop::drop(arrayref); 829 } 830 } 831 832 #[unsafe(no_mangle)] 833 pub unsafe extern "C" fn wasmtime_arrayref_to_anyref( 834 arrayref: Option<&wasmtime_arrayref_t>, 835 out: &mut MaybeUninit<wasmtime_anyref_t>, 836 ) { 837 let anyref = arrayref 838 .and_then(|a| a.as_wasmtime()) 839 .map(|a| a.to_anyref()); 840 crate::initialize(out, anyref.into()); 841 } 842 843 #[unsafe(no_mangle)] 844 pub unsafe extern "C" fn wasmtime_arrayref_to_eqref( 845 arrayref: Option<&wasmtime_arrayref_t>, 846 out: &mut MaybeUninit<wasmtime_eqref_t>, 847 ) { 848 let eqref = arrayref.and_then(|a| a.as_wasmtime()).map(|a| a.to_eqref()); 849 crate::initialize(out, eqref.into()); 850 } 851 852 #[unsafe(no_mangle)] 853 pub unsafe extern "C" fn wasmtime_arrayref_len( 854 cx: WasmtimeStoreContextMut<'_>, 855 arrayref: Option<&wasmtime_arrayref_t>, 856 out: &mut MaybeUninit<u32>, 857 ) -> Option<Box<crate::wasmtime_error_t>> { 858 let arrayref = arrayref 859 .and_then(|a| a.as_wasmtime()) 860 .expect("non-null arrayref required"); 861 match arrayref.len(&cx) { 862 Ok(len) => { 863 crate::initialize(out, len); 864 None 865 } 866 Err(e) => Some(Box::new(e.into())), 867 } 868 } 869 870 #[unsafe(no_mangle)] 871 pub unsafe extern "C" fn wasmtime_arrayref_get( 872 mut cx: WasmtimeStoreContextMut<'_>, 873 arrayref: Option<&wasmtime_arrayref_t>, 874 index: u32, 875 out: &mut MaybeUninit<crate::wasmtime_val_t>, 876 ) -> Option<Box<crate::wasmtime_error_t>> { 877 let arrayref = arrayref 878 .and_then(|a| a.as_wasmtime()) 879 .expect("non-null arrayref required"); 880 let mut scope = RootScope::new(&mut cx); 881 let rooted = arrayref.to_rooted(&mut scope); 882 match rooted.get(&mut scope, index) { 883 Ok(val) => { 884 let c_val = crate::wasmtime_val_t::from_val(&mut scope, val); 885 crate::initialize(out, c_val); 886 None 887 } 888 Err(e) => Some(Box::new(e.into())), 889 } 890 } 891 892 #[unsafe(no_mangle)] 893 pub unsafe extern "C" fn wasmtime_arrayref_set( 894 mut cx: WasmtimeStoreContextMut<'_>, 895 arrayref: Option<&wasmtime_arrayref_t>, 896 index: u32, 897 val: &crate::wasmtime_val_t, 898 ) -> Option<Box<crate::wasmtime_error_t>> { 899 let arrayref = arrayref 900 .and_then(|a| a.as_wasmtime()) 901 .expect("non-null arrayref required"); 902 let mut scope = RootScope::new(&mut cx); 903 let rooted = arrayref.to_rooted(&mut scope); 904 let rust_val = val.to_val(&mut scope); 905 match rooted.set(&mut scope, index, rust_val) { 906 Ok(()) => None, 907 Err(e) => Some(Box::new(e.into())), 908 } 909 } 910 911 #[unsafe(no_mangle)] 912 pub unsafe extern "C" fn wasmtime_eqref_is_array( 913 cx: WasmtimeStoreContextMut<'_>, 914 eqref: Option<&wasmtime_eqref_t>, 915 ) -> bool { 916 match eqref.and_then(|e| e.as_wasmtime()) { 917 Some(eqref) => eqref.is_array(&cx).expect("OwnedRooted always in scope"), 918 None => false, 919 } 920 } 921 922 #[unsafe(no_mangle)] 923 pub unsafe extern "C" fn wasmtime_eqref_as_array( 924 mut cx: WasmtimeStoreContextMut<'_>, 925 eqref: Option<&wasmtime_eqref_t>, 926 out: &mut MaybeUninit<wasmtime_arrayref_t>, 927 ) -> bool { 928 if let Some(eqref) = eqref.and_then(|e| e.as_wasmtime()) { 929 let mut scope = RootScope::new(&mut cx); 930 let rooted = eqref.to_rooted(&mut scope); 931 if let Ok(Some(arrayref)) = rooted.as_array(&scope) { 932 let owned = arrayref.to_owned_rooted(&mut scope).expect("just created"); 933 crate::initialize(out, Some(owned).into()); 934 return true; 935 } 936 } 937 crate::initialize(out, None::<OwnedRooted<ArrayRef>>.into()); 938 false 939 } 940