mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-12 05:18:43 +00:00
feat(c-api) Move all types into their own modules.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
use super::super::store::wasm_store_t;
|
||||
use super::super::trap::wasm_trap_t;
|
||||
use super::super::types::{wasm_functype_t, wasm_valkind_enum};
|
||||
use super::super::value::{wasm_val_inner, wasm_val_t};
|
||||
use super::super::{wasm_functype_t, wasm_trap_t, wasm_valkind_enum};
|
||||
use std::convert::TryInto;
|
||||
use std::ffi::c_void;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
2
lib/c-api/src/wasm_c_api/externals/global.rs
vendored
2
lib/c-api/src/wasm_c_api/externals/global.rs
vendored
@@ -1,6 +1,6 @@
|
||||
use super::super::store::wasm_store_t;
|
||||
use super::super::types::wasm_globaltype_t;
|
||||
use super::super::value::wasm_val_t;
|
||||
use super::super::wasm_globaltype_t;
|
||||
use std::convert::TryInto;
|
||||
use std::ptr::NonNull;
|
||||
use wasmer::{Global, Store, Val};
|
||||
|
||||
3
lib/c-api/src/wasm_c_api/externals/memory.rs
vendored
3
lib/c-api/src/wasm_c_api/externals/memory.rs
vendored
@@ -1,6 +1,5 @@
|
||||
use super::super::store::wasm_store_t;
|
||||
use super::super::wasm_memorytype_t;
|
||||
use crate::c_try;
|
||||
use super::super::types::wasm_memorytype_t;
|
||||
use std::mem;
|
||||
use std::ptr::NonNull;
|
||||
use wasmer::{Memory, Pages, Store};
|
||||
|
||||
3
lib/c-api/src/wasm_c_api/externals/table.rs
vendored
3
lib/c-api/src/wasm_c_api/externals/table.rs
vendored
@@ -1,6 +1,5 @@
|
||||
use super::super::store::wasm_store_t;
|
||||
use super::super::{wasm_ref_t, wasm_table_size_t, wasm_tabletype_t};
|
||||
use crate::c_try;
|
||||
use super::super::types::{wasm_ref_t, wasm_table_size_t, wasm_tabletype_t};
|
||||
use std::ptr::NonNull;
|
||||
use wasmer::{Store, Table};
|
||||
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
use super::{
|
||||
externals::{wasm_extern_t, wasm_extern_vec_t},
|
||||
module::wasm_module_t,
|
||||
store::wasm_store_t,
|
||||
wasm_trap_t,
|
||||
};
|
||||
use crate::c_try;
|
||||
use super::externals::{wasm_extern_t, wasm_extern_vec_t};
|
||||
use super::module::wasm_module_t;
|
||||
use super::store::wasm_store_t;
|
||||
use super::trap::wasm_trap_t;
|
||||
use crate::ordered_resolver::OrderedResolver;
|
||||
use std::mem;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
@@ -155,3 +155,21 @@ macro_rules! wasm_declare_own {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! c_try {
|
||||
($expr:expr) => {{
|
||||
let res: Result<_, _> = $expr;
|
||||
match res {
|
||||
Ok(val) => val,
|
||||
Err(err) => {
|
||||
crate::error::update_last_error(err);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}};
|
||||
($expr:expr, $e:expr) => {{
|
||||
let opt: Option<_> = $expr;
|
||||
c_try!(opt.ok_or_else(|| $e))
|
||||
}};
|
||||
}
|
||||
|
||||
@@ -8,905 +8,8 @@ pub mod externals;
|
||||
pub mod instance;
|
||||
pub mod module;
|
||||
pub mod store;
|
||||
pub(crate) mod utils;
|
||||
pub mod trap;
|
||||
pub mod types;
|
||||
pub mod value;
|
||||
#[cfg(feature = "wasi")]
|
||||
pub mod wasi;
|
||||
|
||||
// required due to really weird Rust resolution rules
|
||||
// https://github.com/rust-lang/rust/issues/57966
|
||||
use crate::c_try;
|
||||
use externals::wasm_extern_t;
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::mem;
|
||||
use std::ptr::NonNull;
|
||||
use thiserror::Error;
|
||||
use value::wasm_valkind_t;
|
||||
use wasmer::{
|
||||
ExportType, ExternType, FunctionType, GlobalType, ImportType, MemoryType, Mutability, Pages,
|
||||
RuntimeError, TableType, ValType,
|
||||
};
|
||||
#[cfg(feature = "jit")]
|
||||
use wasmer_engine_jit::JIT;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type wasm_table_size_t = u32;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type wasm_mutability_t = u8;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[repr(u8)]
|
||||
enum wasm_mutability_enum {
|
||||
WASM_CONST = 0,
|
||||
WASM_VAR,
|
||||
}
|
||||
|
||||
impl wasm_mutability_enum {
|
||||
#[allow(dead_code)]
|
||||
fn is_mutable(self) -> bool {
|
||||
self == Self::WASM_VAR
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<wasm_mutability_t> for wasm_mutability_enum {
|
||||
type Error = &'static str;
|
||||
|
||||
fn try_from(item: wasm_mutability_t) -> Result<Self, Self::Error> {
|
||||
Ok(match item {
|
||||
0 => wasm_mutability_enum::WASM_CONST,
|
||||
1 => wasm_mutability_enum::WASM_VAR,
|
||||
_ => return Err("wasm_mutability_t value out of bounds"),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl From<wasm_mutability_enum> for wasm_mutability_t {
|
||||
fn from(other: wasm_mutability_enum) -> Self {
|
||||
other as wasm_mutability_t
|
||||
}
|
||||
}
|
||||
|
||||
impl From<wasm_mutability_enum> for Mutability {
|
||||
fn from(other: wasm_mutability_enum) -> Self {
|
||||
match other {
|
||||
wasm_mutability_enum::WASM_CONST => Mutability::Const,
|
||||
wasm_mutability_enum::WASM_VAR => Mutability::Var,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Mutability> for wasm_mutability_enum {
|
||||
fn from(other: Mutability) -> Self {
|
||||
match other {
|
||||
Mutability::Const => wasm_mutability_enum::WASM_CONST,
|
||||
Mutability::Var => wasm_mutability_enum::WASM_VAR,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<wasm_valkind_enum> for ValType {
|
||||
fn from(other: wasm_valkind_enum) -> Self {
|
||||
use wasm_valkind_enum::*;
|
||||
match other {
|
||||
WASM_I32 => ValType::I32,
|
||||
WASM_I64 => ValType::I64,
|
||||
WASM_F32 => ValType::F32,
|
||||
WASM_F64 => ValType::F64,
|
||||
WASM_ANYREF => ValType::ExternRef,
|
||||
WASM_FUNCREF => ValType::FuncRef,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<wasm_valtype_t> for ValType {
|
||||
fn from(other: wasm_valtype_t) -> Self {
|
||||
other.valkind.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ValType> for wasm_valtype_t {
|
||||
fn from(other: ValType) -> Self {
|
||||
Self {
|
||||
valkind: other.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[repr(u8)]
|
||||
pub enum wasm_valkind_enum {
|
||||
WASM_I32 = 0,
|
||||
WASM_I64 = 1,
|
||||
WASM_F32 = 2,
|
||||
WASM_F64 = 3,
|
||||
WASM_ANYREF = 128,
|
||||
WASM_FUNCREF = 129,
|
||||
}
|
||||
|
||||
impl From<ValType> for wasm_valkind_enum {
|
||||
fn from(other: ValType) -> Self {
|
||||
match other {
|
||||
ValType::I32 => Self::WASM_I32,
|
||||
ValType::I64 => Self::WASM_I64,
|
||||
ValType::F32 => Self::WASM_F32,
|
||||
ValType::F64 => Self::WASM_F64,
|
||||
ValType::V128 => todo!("no v128 type in Wasm C API yet!"),
|
||||
ValType::ExternRef => Self::WASM_ANYREF,
|
||||
ValType::FuncRef => Self::WASM_FUNCREF,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type wasm_byte_t = u8;
|
||||
wasm_declare_vec!(byte);
|
||||
|
||||
// opaque type over `ExternRef`?
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct wasm_ref_t;
|
||||
|
||||
// opaque type which is a `RuntimeError`
|
||||
#[repr(C)]
|
||||
pub struct wasm_trap_t {}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_trap_delete(trap: Option<NonNull<wasm_trap_t>>) {
|
||||
if let Some(t_inner) = trap {
|
||||
let _ = Box::from_raw(t_inner.cast::<RuntimeError>().as_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_trap_message(
|
||||
trap: *const wasm_trap_t,
|
||||
out_ptr: *mut wasm_byte_vec_t,
|
||||
) {
|
||||
let re = &*(trap as *const RuntimeError);
|
||||
// this code assumes no nul bytes appear in the message
|
||||
let mut message = format!("{}\0", re);
|
||||
message.shrink_to_fit();
|
||||
|
||||
// TODO use `String::into_raw_parts` when it gets stabilized
|
||||
(*out_ptr).size = message.as_bytes().len();
|
||||
(*out_ptr).data = message.as_mut_ptr();
|
||||
mem::forget(message);
|
||||
}
|
||||
|
||||
// in trap/RuntimeError we need to store
|
||||
// 1. message
|
||||
// 2. origin (frame); frame contains:
|
||||
// 1. func index
|
||||
// 2. func offset
|
||||
// 3. module offset
|
||||
// 4. which instance this was apart of
|
||||
|
||||
/*#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_trap_trace(trap: *const wasm_trap_t, out_ptr: *mut wasm_frame_vec_t) {
|
||||
let re = &*(trap as *const RuntimeError);
|
||||
todo!()
|
||||
}*/
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct wasm_valtype_t {
|
||||
valkind: wasm_valkind_enum,
|
||||
}
|
||||
|
||||
impl Default for wasm_valtype_t {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
valkind: wasm_valkind_enum::WASM_I32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wasm_declare_boxed_vec!(valtype);
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_valtype_new(kind: wasm_valkind_t) -> Option<Box<wasm_valtype_t>> {
|
||||
let kind_enum = kind.try_into().ok()?;
|
||||
let valtype = wasm_valtype_t { valkind: kind_enum };
|
||||
Some(Box::new(valtype))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_valtype_delete(_valtype: Option<Box<wasm_valtype_t>>) {}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_valtype_kind(valtype: *const wasm_valtype_t) -> wasm_valkind_t {
|
||||
if valtype.is_null() {
|
||||
// TODO: handle error
|
||||
panic!("wasm_valtype_kind: argument is null pointer");
|
||||
}
|
||||
return (*valtype).valkind as wasm_valkind_t;
|
||||
}
|
||||
|
||||
//wasm_declare_ref!(trap);
|
||||
//wasm_declare_ref!(foreign);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[repr(transparent)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct wasm_globaltype_t {
|
||||
extern_: wasm_externtype_t,
|
||||
}
|
||||
|
||||
impl wasm_globaltype_t {
|
||||
fn as_globaltype(&self) -> &GlobalType {
|
||||
if let ExternType::Global(ref g) = self.extern_.inner {
|
||||
g
|
||||
} else {
|
||||
unreachable!(
|
||||
"Data corruption detected: `wasm_globaltype_t` does not contain a `GlobalType`"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wasm_declare_vec!(globaltype);
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_globaltype_new(
|
||||
// own
|
||||
valtype: Option<Box<wasm_valtype_t>>,
|
||||
mutability: wasm_mutability_t,
|
||||
) -> Option<Box<wasm_globaltype_t>> {
|
||||
wasm_globaltype_new_inner(valtype?, mutability)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_globaltype_delete(_globaltype: Option<Box<wasm_globaltype_t>>) {}
|
||||
|
||||
unsafe fn wasm_globaltype_new_inner(
|
||||
// own
|
||||
valtype: Box<wasm_valtype_t>,
|
||||
mutability: wasm_mutability_t,
|
||||
) -> Option<Box<wasm_globaltype_t>> {
|
||||
let me: wasm_mutability_enum = mutability.try_into().ok()?;
|
||||
let gd = Box::new(wasm_globaltype_t {
|
||||
extern_: wasm_externtype_t {
|
||||
inner: ExternType::Global(GlobalType::new((*valtype).into(), me.into())),
|
||||
},
|
||||
});
|
||||
wasm_valtype_delete(Some(valtype));
|
||||
|
||||
Some(gd)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_globaltype_mutability(
|
||||
globaltype: &wasm_globaltype_t,
|
||||
) -> wasm_mutability_t {
|
||||
let gt = globaltype.as_globaltype();
|
||||
wasm_mutability_enum::from(gt.mutability).into()
|
||||
}
|
||||
|
||||
// TODO: fix memory leak
|
||||
// this function leaks memory because the returned limits pointer is not owned
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_globaltype_content(
|
||||
globaltype: &wasm_globaltype_t,
|
||||
) -> *const wasm_valtype_t {
|
||||
let gt = globaltype.as_globaltype();
|
||||
Box::into_raw(Box::new(gt.ty.into()))
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[repr(C)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct wasm_tabletype_t {
|
||||
extern_: wasm_externtype_t,
|
||||
}
|
||||
|
||||
wasm_declare_vec!(tabletype);
|
||||
|
||||
impl wasm_tabletype_t {
|
||||
fn as_tabletype(&self) -> &TableType {
|
||||
if let ExternType::Table(ref t) = self.extern_.inner {
|
||||
t
|
||||
} else {
|
||||
unreachable!(
|
||||
"Data corruption detected: `wasm_tabletype_t` does not contain a `TableType`"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_tabletype_new(
|
||||
// own
|
||||
valtype: Box<wasm_valtype_t>,
|
||||
limits: &wasm_limits_t,
|
||||
) -> Box<wasm_tabletype_t> {
|
||||
// TODO: investigate if `0` is in fact a sentinel value here
|
||||
let max_elements = if limits.max == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(limits.max as _)
|
||||
};
|
||||
let out = Box::new(wasm_tabletype_t {
|
||||
extern_: wasm_externtype_t {
|
||||
inner: ExternType::Table(TableType::new(
|
||||
(*valtype).into(),
|
||||
limits.min as _,
|
||||
max_elements,
|
||||
)),
|
||||
},
|
||||
});
|
||||
wasm_valtype_delete(Some(valtype));
|
||||
|
||||
out
|
||||
}
|
||||
|
||||
// TODO: fix memory leak
|
||||
// this function leaks memory because the returned limits pointer is not owned
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_tabletype_limits(
|
||||
tabletype: &wasm_tabletype_t,
|
||||
) -> *const wasm_limits_t {
|
||||
let tt = tabletype.as_tabletype();
|
||||
Box::into_raw(Box::new(wasm_limits_t {
|
||||
min: tt.minimum as _,
|
||||
max: tt.maximum.unwrap_or(0),
|
||||
}))
|
||||
}
|
||||
|
||||
// TODO: fix memory leak
|
||||
// this function leaks memory because the returned limits pointer is not owned
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_tabletype_element(
|
||||
tabletype: &wasm_tabletype_t,
|
||||
) -> *const wasm_valtype_t {
|
||||
let tt = tabletype.as_tabletype();
|
||||
|
||||
Box::into_raw(Box::new(tt.ty.into()))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_tabletype_delete(_tabletype: Option<Box<wasm_tabletype_t>>) {}
|
||||
|
||||
// opaque type wrapping `MemoryType`
|
||||
#[derive(Clone, Debug)]
|
||||
#[repr(transparent)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct wasm_memorytype_t {
|
||||
extern_: wasm_externtype_t,
|
||||
}
|
||||
|
||||
impl wasm_memorytype_t {
|
||||
pub(crate) fn as_memorytype(&self) -> &MemoryType {
|
||||
if let ExternType::Memory(ref mt) = self.extern_.inner {
|
||||
mt
|
||||
} else {
|
||||
unreachable!(
|
||||
"Data corruption detected: `wasm_memorytype_t` does not contain a `MemoryType`"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wasm_declare_vec!(memorytype);
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct wasm_limits_t {
|
||||
min: u32,
|
||||
max: u32,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_memorytype_new(limits: &wasm_limits_t) -> Box<wasm_memorytype_t> {
|
||||
let min_pages = Pages(limits.min as _);
|
||||
// TODO: investigate if `0` is in fact a sentinel value here
|
||||
let max_pages = if limits.max == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(Pages(limits.max as _))
|
||||
};
|
||||
Box::new(wasm_memorytype_t {
|
||||
extern_: wasm_externtype_t {
|
||||
inner: ExternType::Memory(MemoryType::new(min_pages, max_pages, false)),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_memorytype_delete(_memorytype: Option<Box<wasm_memorytype_t>>) {}
|
||||
|
||||
// TODO: fix memory leak
|
||||
// this function leaks memory because the returned limits pointer is not owned
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_memorytype_limits(mt: &wasm_memorytype_t) -> *const wasm_limits_t {
|
||||
let md = mt.as_memorytype();
|
||||
Box::into_raw(Box::new(wasm_limits_t {
|
||||
min: md.minimum.bytes().0 as _,
|
||||
max: md.maximum.map(|max| max.bytes().0 as _).unwrap_or(0),
|
||||
}))
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[repr(transparent)]
|
||||
pub struct wasm_functype_t {
|
||||
extern_: wasm_externtype_t,
|
||||
}
|
||||
|
||||
impl wasm_functype_t {
|
||||
pub(crate) fn sig(&self) -> &FunctionType {
|
||||
if let ExternType::Function(ref f) = self.extern_.inner {
|
||||
f
|
||||
} else {
|
||||
unreachable!("data corruption: `wasm_functype_t` does not contain a function")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wasm_declare_vec!(functype);
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_functype_new(
|
||||
// own
|
||||
params: Option<NonNull<wasm_valtype_vec_t>>,
|
||||
// own
|
||||
results: Option<NonNull<wasm_valtype_vec_t>>,
|
||||
) -> Option<Box<wasm_functype_t>> {
|
||||
wasm_functype_new_inner(params?, results?)
|
||||
}
|
||||
|
||||
unsafe fn wasm_functype_new_inner(
|
||||
// own
|
||||
params: NonNull<wasm_valtype_vec_t>,
|
||||
// own
|
||||
results: NonNull<wasm_valtype_vec_t>,
|
||||
) -> Option<Box<wasm_functype_t>> {
|
||||
let params = params.as_ref();
|
||||
let results = results.as_ref();
|
||||
let params: Vec<ValType> = params
|
||||
.into_slice()?
|
||||
.iter()
|
||||
.map(|&ptr| *ptr)
|
||||
.map(Into::into)
|
||||
.collect::<Vec<_>>();
|
||||
let results: Vec<ValType> = results
|
||||
.into_slice()?
|
||||
.iter()
|
||||
.map(|&ptr| *ptr)
|
||||
.map(Into::into)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let extern_ = wasm_externtype_t {
|
||||
inner: ExternType::Function(FunctionType::new(params, results)),
|
||||
};
|
||||
Some(Box::new(wasm_functype_t { extern_ }))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_functype_delete(_ft: Option<Box<wasm_functype_t>>) {}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_functype_copy(
|
||||
arg: Option<NonNull<wasm_functype_t>>,
|
||||
) -> Option<Box<wasm_functype_t>> {
|
||||
let arg = arg?;
|
||||
let funcsig = arg.as_ref();
|
||||
Some(Box::new(funcsig.clone()))
|
||||
}
|
||||
|
||||
// TODO: fix memory leak
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_functype_params(ft: &wasm_functype_t) -> *const wasm_valtype_vec_t {
|
||||
let mut valtypes = ft
|
||||
.sig()
|
||||
.params()
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(Into::into)
|
||||
.map(Box::new)
|
||||
.map(Box::into_raw)
|
||||
.collect::<Vec<*mut wasm_valtype_t>>();
|
||||
let out = Box::into_raw(Box::new(wasm_valtype_vec_t {
|
||||
size: valtypes.len(),
|
||||
data: valtypes.as_mut_ptr(),
|
||||
}));
|
||||
mem::forget(valtypes);
|
||||
out as *const _
|
||||
}
|
||||
|
||||
// TODO: fix memory leak
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_functype_results(ft: &wasm_functype_t) -> *const wasm_valtype_vec_t {
|
||||
let mut valtypes = ft
|
||||
.sig()
|
||||
.results()
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(Into::into)
|
||||
.map(Box::new)
|
||||
.map(Box::into_raw)
|
||||
.collect::<Vec<*mut wasm_valtype_t>>();
|
||||
let out = Box::into_raw(Box::new(wasm_valtype_vec_t {
|
||||
size: valtypes.len(),
|
||||
data: valtypes.as_mut_ptr(),
|
||||
}));
|
||||
mem::forget(valtypes);
|
||||
out as *const _
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub struct wasm_frame_t {}
|
||||
|
||||
wasm_declare_vec!(frame);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[repr(transparent)]
|
||||
pub struct wasm_externtype_t {
|
||||
inner: ExternType,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_extern_type(e: &wasm_extern_t) -> Box<wasm_externtype_t> {
|
||||
Box::new(wasm_externtype_t {
|
||||
inner: e.inner.ty(),
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_externtype_delete(_et: Option<Box<wasm_externtype_t>>) {}
|
||||
|
||||
impl From<ExternType> for wasm_externtype_t {
|
||||
fn from(other: ExternType) -> Self {
|
||||
Self { inner: other }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&ExternType> for wasm_externtype_t {
|
||||
fn from(other: &ExternType) -> Self {
|
||||
other.clone().into()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
type wasm_externkind_t = u8;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[repr(u8)]
|
||||
pub enum wasm_externkind_enum {
|
||||
WASM_EXTERN_FUNC = 0,
|
||||
WASM_EXTERN_GLOBAL = 1,
|
||||
WASM_EXTERN_TABLE = 2,
|
||||
WASM_EXTERN_MEMORY = 3,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_extern_kind(e: &wasm_extern_t) -> wasm_externkind_t {
|
||||
wasm_externkind_enum::from(e.inner.ty()) as wasm_externkind_t
|
||||
}
|
||||
|
||||
impl From<ExternType> for wasm_externkind_enum {
|
||||
fn from(other: ExternType) -> Self {
|
||||
(&other).into()
|
||||
}
|
||||
}
|
||||
impl From<&ExternType> for wasm_externkind_enum {
|
||||
fn from(other: &ExternType) -> Self {
|
||||
match other {
|
||||
ExternType::Function(_) => Self::WASM_EXTERN_FUNC,
|
||||
ExternType::Global(_) => Self::WASM_EXTERN_GLOBAL,
|
||||
ExternType::Table(_) => Self::WASM_EXTERN_TABLE,
|
||||
ExternType::Memory(_) => Self::WASM_EXTERN_MEMORY,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_externtype_kind(et: &wasm_externtype_t) -> wasm_externkind_t {
|
||||
wasm_externkind_enum::from(&et.inner) as wasm_externkind_t
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Error)]
|
||||
#[error("failed to convert from `wasm_externtype_t`: {0}")]
|
||||
pub struct ExternTypeConversionError(&'static str);
|
||||
impl From<&'static str> for ExternTypeConversionError {
|
||||
fn from(other: &'static str) -> Self {
|
||||
Self(other)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&'static wasm_externtype_t> for &'static wasm_functype_t {
|
||||
type Error = ExternTypeConversionError;
|
||||
fn try_from(other: &'static wasm_externtype_t) -> Result<Self, Self::Error> {
|
||||
if let ExternType::Function(_) = other.inner {
|
||||
Ok(unsafe { mem::transmute::<&'static wasm_externtype_t, Self>(other) })
|
||||
} else {
|
||||
Err(ExternTypeConversionError("Wrong type: expected function"))
|
||||
}
|
||||
}
|
||||
}
|
||||
impl TryFrom<&'static wasm_externtype_t> for &'static wasm_globaltype_t {
|
||||
type Error = ExternTypeConversionError;
|
||||
fn try_from(other: &'static wasm_externtype_t) -> Result<Self, Self::Error> {
|
||||
if let ExternType::Global(_) = other.inner {
|
||||
Ok(unsafe { mem::transmute::<&'static wasm_externtype_t, Self>(other) })
|
||||
} else {
|
||||
Err(ExternTypeConversionError("Wrong type: expected global"))
|
||||
}
|
||||
}
|
||||
}
|
||||
impl TryFrom<&'static wasm_externtype_t> for &'static wasm_memorytype_t {
|
||||
type Error = ExternTypeConversionError;
|
||||
fn try_from(other: &'static wasm_externtype_t) -> Result<Self, Self::Error> {
|
||||
if let ExternType::Memory(_) = other.inner {
|
||||
Ok(unsafe { mem::transmute::<&'static wasm_externtype_t, Self>(other) })
|
||||
} else {
|
||||
Err(ExternTypeConversionError("Wrong type: expected memory"))
|
||||
}
|
||||
}
|
||||
}
|
||||
impl TryFrom<&'static wasm_externtype_t> for &'static wasm_tabletype_t {
|
||||
type Error = ExternTypeConversionError;
|
||||
fn try_from(other: &'static wasm_externtype_t) -> Result<Self, Self::Error> {
|
||||
if let ExternType::Table(_) = other.inner {
|
||||
Ok(unsafe { mem::transmute::<&'static wasm_externtype_t, Self>(other) })
|
||||
} else {
|
||||
Err(ExternTypeConversionError("Wrong type: expected table"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_externtype_as_functype_const(
|
||||
et: &'static wasm_externtype_t,
|
||||
) -> Option<&'static wasm_functype_t> {
|
||||
Some(c_try!(et.try_into()))
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_externtype_as_functype(
|
||||
et: &'static wasm_externtype_t,
|
||||
) -> Option<&'static wasm_functype_t> {
|
||||
Some(c_try!(et.try_into()))
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_functype_as_externtype_const(
|
||||
ft: &'static wasm_functype_t,
|
||||
) -> &'static wasm_externtype_t {
|
||||
&ft.extern_
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_functype_as_externtype(
|
||||
ft: &'static wasm_functype_t,
|
||||
) -> &'static wasm_externtype_t {
|
||||
&ft.extern_
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_externtype_as_memorytype_const(
|
||||
et: &'static wasm_externtype_t,
|
||||
) -> Option<&'static wasm_memorytype_t> {
|
||||
Some(c_try!(et.try_into()))
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_externtype_as_memorytype(
|
||||
et: &'static wasm_externtype_t,
|
||||
) -> Option<&'static wasm_memorytype_t> {
|
||||
Some(c_try!(et.try_into()))
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_memorytype_as_externtype_const(
|
||||
mt: &'static wasm_memorytype_t,
|
||||
) -> &'static wasm_externtype_t {
|
||||
&mt.extern_
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_memorytype_as_externtype(
|
||||
mt: &'static wasm_memorytype_t,
|
||||
) -> &'static wasm_externtype_t {
|
||||
&mt.extern_
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_externtype_as_globaltype_const(
|
||||
et: &'static wasm_externtype_t,
|
||||
) -> Option<&'static wasm_globaltype_t> {
|
||||
Some(c_try!(et.try_into()))
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_externtype_as_globaltype(
|
||||
et: &'static wasm_externtype_t,
|
||||
) -> Option<&'static wasm_globaltype_t> {
|
||||
Some(c_try!(et.try_into()))
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_globaltype_as_externtype_const(
|
||||
gt: &'static wasm_globaltype_t,
|
||||
) -> &'static wasm_externtype_t {
|
||||
>.extern_
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_globaltype_as_externtype(
|
||||
gt: &'static wasm_globaltype_t,
|
||||
) -> &'static wasm_externtype_t {
|
||||
>.extern_
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_externtype_as_tabletype_const(
|
||||
et: &'static wasm_externtype_t,
|
||||
) -> Option<&'static wasm_tabletype_t> {
|
||||
Some(c_try!(et.try_into()))
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_externtype_as_tabletype(
|
||||
et: &'static wasm_externtype_t,
|
||||
) -> Option<&'static wasm_tabletype_t> {
|
||||
Some(c_try!(et.try_into()))
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_tabletype_as_externtype_const(
|
||||
tt: &'static wasm_tabletype_t,
|
||||
) -> &'static wasm_externtype_t {
|
||||
&tt.extern_
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_tabletype_as_externtype(
|
||||
tt: &'static wasm_tabletype_t,
|
||||
) -> &'static wasm_externtype_t {
|
||||
&tt.extern_
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
type wasm_name_t = wasm_byte_vec_t;
|
||||
|
||||
#[repr(C)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct wasm_exporttype_t {
|
||||
name: NonNull<wasm_name_t>,
|
||||
extern_type: NonNull<wasm_externtype_t>,
|
||||
}
|
||||
|
||||
wasm_declare_boxed_vec!(exporttype);
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_exporttype_new(
|
||||
name: NonNull<wasm_name_t>,
|
||||
extern_type: NonNull<wasm_externtype_t>,
|
||||
) -> Box<wasm_exporttype_t> {
|
||||
Box::new(wasm_exporttype_t { name, extern_type })
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_exporttype_name(et: &'static wasm_exporttype_t) -> &'static wasm_name_t {
|
||||
unsafe { et.name.as_ref() }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_exporttype_type(
|
||||
et: &'static wasm_exporttype_t,
|
||||
) -> &'static wasm_externtype_t {
|
||||
unsafe { et.extern_type.as_ref() }
|
||||
}
|
||||
|
||||
impl From<ExportType> for wasm_exporttype_t {
|
||||
fn from(other: ExportType) -> Self {
|
||||
(&other).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&ExportType> for wasm_exporttype_t {
|
||||
fn from(other: &ExportType) -> Self {
|
||||
// TODO: double check that freeing String as `Vec<u8>` is valid
|
||||
let name = {
|
||||
let mut heap_str: Box<str> = other.name().to_string().into_boxed_str();
|
||||
let char_ptr = heap_str.as_mut_ptr();
|
||||
let str_len = heap_str.bytes().len();
|
||||
let name_inner = wasm_name_t {
|
||||
size: str_len,
|
||||
data: char_ptr,
|
||||
};
|
||||
Box::leak(heap_str);
|
||||
unsafe { NonNull::new_unchecked(Box::into_raw(Box::new(name_inner))) }
|
||||
};
|
||||
|
||||
let extern_type = {
|
||||
let extern_type: wasm_externtype_t = other.ty().into();
|
||||
unsafe { NonNull::new_unchecked(Box::into_raw(Box::new(extern_type))) }
|
||||
};
|
||||
|
||||
wasm_exporttype_t { name, extern_type }
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: improve ownership in `importtype_t` (can we safely use `Box<wasm_name_t>` here?)
|
||||
#[repr(C)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct wasm_importtype_t {
|
||||
module: NonNull<wasm_name_t>,
|
||||
name: NonNull<wasm_name_t>,
|
||||
extern_type: NonNull<wasm_externtype_t>,
|
||||
}
|
||||
|
||||
wasm_declare_boxed_vec!(importtype);
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_importtype_new(
|
||||
module: NonNull<wasm_name_t>,
|
||||
name: NonNull<wasm_name_t>,
|
||||
extern_type: NonNull<wasm_externtype_t>,
|
||||
) -> Box<wasm_importtype_t> {
|
||||
Box::new(wasm_importtype_t {
|
||||
name,
|
||||
module,
|
||||
extern_type,
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_importtype_module(et: &'static wasm_importtype_t) -> &'static wasm_name_t {
|
||||
unsafe { et.module.as_ref() }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_importtype_name(et: &'static wasm_importtype_t) -> &'static wasm_name_t {
|
||||
unsafe { et.name.as_ref() }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_importtype_type(
|
||||
et: &'static wasm_importtype_t,
|
||||
) -> &'static wasm_externtype_t {
|
||||
unsafe { et.extern_type.as_ref() }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_importtype_delete(_importtype: Option<Box<wasm_importtype_t>>) {}
|
||||
|
||||
impl From<ImportType> for wasm_importtype_t {
|
||||
fn from(other: ImportType) -> Self {
|
||||
(&other).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&ImportType> for wasm_importtype_t {
|
||||
fn from(other: &ImportType) -> Self {
|
||||
// TODO: double check that freeing String as `Vec<u8>` is valid
|
||||
let name = {
|
||||
let mut heap_str: Box<str> = other.name().to_string().into_boxed_str();
|
||||
let char_ptr = heap_str.as_mut_ptr();
|
||||
let str_len = heap_str.bytes().len();
|
||||
let name_inner = wasm_name_t {
|
||||
size: str_len,
|
||||
data: char_ptr,
|
||||
};
|
||||
Box::leak(heap_str);
|
||||
unsafe { NonNull::new_unchecked(Box::into_raw(Box::new(name_inner))) }
|
||||
};
|
||||
|
||||
// TODO: double check that freeing String as `Vec<u8>` is valid
|
||||
let module = {
|
||||
let mut heap_str: Box<str> = other.module().to_string().into_boxed_str();
|
||||
let char_ptr = heap_str.as_mut_ptr();
|
||||
let str_len = heap_str.bytes().len();
|
||||
let name_inner = wasm_name_t {
|
||||
size: str_len,
|
||||
data: char_ptr,
|
||||
};
|
||||
Box::leak(heap_str);
|
||||
unsafe { NonNull::new_unchecked(Box::into_raw(Box::new(name_inner))) }
|
||||
};
|
||||
|
||||
let extern_type = {
|
||||
let extern_type: wasm_externtype_t = other.ty().into();
|
||||
unsafe { NonNull::new_unchecked(Box::into_raw(Box::new(extern_type))) }
|
||||
};
|
||||
|
||||
wasm_importtype_t {
|
||||
name,
|
||||
module,
|
||||
extern_type,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
use super::store::wasm_store_t;
|
||||
use super::{
|
||||
use super::types::{
|
||||
wasm_byte_vec_t, wasm_exporttype_t, wasm_exporttype_vec_t, wasm_importtype_t,
|
||||
wasm_importtype_vec_t,
|
||||
};
|
||||
use crate::c_try;
|
||||
use std::mem;
|
||||
use std::ptr::NonNull;
|
||||
use std::slice;
|
||||
|
||||
48
lib/c-api/src/wasm_c_api/trap.rs
Normal file
48
lib/c-api/src/wasm_c_api/trap.rs
Normal file
@@ -0,0 +1,48 @@
|
||||
use super::types::wasm_byte_vec_t;
|
||||
use std::mem;
|
||||
use std::ptr::NonNull;
|
||||
use wasmer::RuntimeError;
|
||||
|
||||
// opaque type which is a `RuntimeError`
|
||||
#[repr(C)]
|
||||
pub struct wasm_trap_t {}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_trap_delete(trap: Option<NonNull<wasm_trap_t>>) {
|
||||
if let Some(t_inner) = trap {
|
||||
let _ = Box::from_raw(t_inner.cast::<RuntimeError>().as_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_trap_message(
|
||||
trap: *const wasm_trap_t,
|
||||
out_ptr: *mut wasm_byte_vec_t,
|
||||
) {
|
||||
let re = &*(trap as *const RuntimeError);
|
||||
// this code assumes no nul bytes appear in the message
|
||||
let mut message = format!("{}\0", re);
|
||||
message.shrink_to_fit();
|
||||
|
||||
// TODO use `String::into_raw_parts` when it gets stabilized
|
||||
(*out_ptr).size = message.as_bytes().len();
|
||||
(*out_ptr).data = message.as_mut_ptr();
|
||||
mem::forget(message);
|
||||
}
|
||||
|
||||
// in trap/RuntimeError we need to store
|
||||
// 1. message
|
||||
// 2. origin (frame); frame contains:
|
||||
// 1. func index
|
||||
// 2. func offset
|
||||
// 3. module offset
|
||||
// 4. which instance this was apart of
|
||||
|
||||
/*#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_trap_trace(trap: *const wasm_trap_t, out_ptr: *mut wasm_frame_vec_t) {
|
||||
let re = &*(trap as *const RuntimeError);
|
||||
todo!()
|
||||
}*/
|
||||
|
||||
//wasm_declare_ref!(trap);
|
||||
//wasm_declare_ref!(foreign);
|
||||
4
lib/c-api/src/wasm_c_api/types/byte.rs
Normal file
4
lib/c-api/src/wasm_c_api/types/byte.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type wasm_byte_t = u8;
|
||||
|
||||
wasm_declare_vec!(byte);
|
||||
62
lib/c-api/src/wasm_c_api/types/export.rs
Normal file
62
lib/c-api/src/wasm_c_api/types/export.rs
Normal file
@@ -0,0 +1,62 @@
|
||||
use super::{wasm_externtype_t, wasm_name_t};
|
||||
use std::ptr::NonNull;
|
||||
use wasmer::ExportType;
|
||||
|
||||
#[repr(C)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct wasm_exporttype_t {
|
||||
name: NonNull<wasm_name_t>,
|
||||
extern_type: NonNull<wasm_externtype_t>,
|
||||
}
|
||||
|
||||
wasm_declare_boxed_vec!(exporttype);
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_exporttype_new(
|
||||
name: NonNull<wasm_name_t>,
|
||||
extern_type: NonNull<wasm_externtype_t>,
|
||||
) -> Box<wasm_exporttype_t> {
|
||||
Box::new(wasm_exporttype_t { name, extern_type })
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_exporttype_name(et: &'static wasm_exporttype_t) -> &'static wasm_name_t {
|
||||
unsafe { et.name.as_ref() }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_exporttype_type(
|
||||
et: &'static wasm_exporttype_t,
|
||||
) -> &'static wasm_externtype_t {
|
||||
unsafe { et.extern_type.as_ref() }
|
||||
}
|
||||
|
||||
impl From<ExportType> for wasm_exporttype_t {
|
||||
fn from(other: ExportType) -> Self {
|
||||
(&other).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&ExportType> for wasm_exporttype_t {
|
||||
fn from(other: &ExportType) -> Self {
|
||||
// TODO: double check that freeing String as `Vec<u8>` is valid
|
||||
let name = {
|
||||
let mut heap_str: Box<str> = other.name().to_string().into_boxed_str();
|
||||
let char_ptr = heap_str.as_mut_ptr();
|
||||
let str_len = heap_str.bytes().len();
|
||||
let name_inner = wasm_name_t {
|
||||
size: str_len,
|
||||
data: char_ptr,
|
||||
};
|
||||
Box::leak(heap_str);
|
||||
unsafe { NonNull::new_unchecked(Box::into_raw(Box::new(name_inner))) }
|
||||
};
|
||||
|
||||
let extern_type = {
|
||||
let extern_type: wasm_externtype_t = other.ty().into();
|
||||
unsafe { NonNull::new_unchecked(Box::into_raw(Box::new(extern_type))) }
|
||||
};
|
||||
|
||||
wasm_exporttype_t { name, extern_type }
|
||||
}
|
||||
}
|
||||
243
lib/c-api/src/wasm_c_api/types/extern_.rs
Normal file
243
lib/c-api/src/wasm_c_api/types/extern_.rs
Normal file
@@ -0,0 +1,243 @@
|
||||
use super::super::externals::wasm_extern_t;
|
||||
use super::{wasm_functype_t, wasm_globaltype_t, wasm_memorytype_t, wasm_tabletype_t};
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::mem;
|
||||
use thiserror::Error;
|
||||
use wasmer::ExternType;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[repr(transparent)]
|
||||
pub struct wasm_externtype_t {
|
||||
pub(crate) inner: ExternType,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_extern_type(e: &wasm_extern_t) -> Box<wasm_externtype_t> {
|
||||
Box::new(wasm_externtype_t {
|
||||
inner: e.inner.ty(),
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_externtype_delete(_et: Option<Box<wasm_externtype_t>>) {}
|
||||
|
||||
impl From<ExternType> for wasm_externtype_t {
|
||||
fn from(other: ExternType) -> Self {
|
||||
Self { inner: other }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&ExternType> for wasm_externtype_t {
|
||||
fn from(other: &ExternType) -> Self {
|
||||
other.clone().into()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
type wasm_externkind_t = u8;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[repr(u8)]
|
||||
pub enum wasm_externkind_enum {
|
||||
WASM_EXTERN_FUNC = 0,
|
||||
WASM_EXTERN_GLOBAL = 1,
|
||||
WASM_EXTERN_TABLE = 2,
|
||||
WASM_EXTERN_MEMORY = 3,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_extern_kind(e: &wasm_extern_t) -> wasm_externkind_t {
|
||||
wasm_externkind_enum::from(e.inner.ty()) as wasm_externkind_t
|
||||
}
|
||||
|
||||
impl From<ExternType> for wasm_externkind_enum {
|
||||
fn from(other: ExternType) -> Self {
|
||||
(&other).into()
|
||||
}
|
||||
}
|
||||
impl From<&ExternType> for wasm_externkind_enum {
|
||||
fn from(other: &ExternType) -> Self {
|
||||
match other {
|
||||
ExternType::Function(_) => Self::WASM_EXTERN_FUNC,
|
||||
ExternType::Global(_) => Self::WASM_EXTERN_GLOBAL,
|
||||
ExternType::Table(_) => Self::WASM_EXTERN_TABLE,
|
||||
ExternType::Memory(_) => Self::WASM_EXTERN_MEMORY,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_externtype_kind(et: &wasm_externtype_t) -> wasm_externkind_t {
|
||||
wasm_externkind_enum::from(&et.inner) as wasm_externkind_t
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Error)]
|
||||
#[error("failed to convert from `wasm_externtype_t`: {0}")]
|
||||
pub struct ExternTypeConversionError(&'static str);
|
||||
|
||||
impl From<&'static str> for ExternTypeConversionError {
|
||||
fn from(other: &'static str) -> Self {
|
||||
Self(other)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&'static wasm_externtype_t> for &'static wasm_functype_t {
|
||||
type Error = ExternTypeConversionError;
|
||||
|
||||
fn try_from(other: &'static wasm_externtype_t) -> Result<Self, Self::Error> {
|
||||
if let ExternType::Function(_) = other.inner {
|
||||
Ok(unsafe { mem::transmute::<&'static wasm_externtype_t, Self>(other) })
|
||||
} else {
|
||||
Err(ExternTypeConversionError("Wrong type: expected function"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&'static wasm_externtype_t> for &'static wasm_globaltype_t {
|
||||
type Error = ExternTypeConversionError;
|
||||
|
||||
fn try_from(other: &'static wasm_externtype_t) -> Result<Self, Self::Error> {
|
||||
if let ExternType::Global(_) = other.inner {
|
||||
Ok(unsafe { mem::transmute::<&'static wasm_externtype_t, Self>(other) })
|
||||
} else {
|
||||
Err(ExternTypeConversionError("Wrong type: expected global"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&'static wasm_externtype_t> for &'static wasm_memorytype_t {
|
||||
type Error = ExternTypeConversionError;
|
||||
|
||||
fn try_from(other: &'static wasm_externtype_t) -> Result<Self, Self::Error> {
|
||||
if let ExternType::Memory(_) = other.inner {
|
||||
Ok(unsafe { mem::transmute::<&'static wasm_externtype_t, Self>(other) })
|
||||
} else {
|
||||
Err(ExternTypeConversionError("Wrong type: expected memory"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&'static wasm_externtype_t> for &'static wasm_tabletype_t {
|
||||
type Error = ExternTypeConversionError;
|
||||
|
||||
fn try_from(other: &'static wasm_externtype_t) -> Result<Self, Self::Error> {
|
||||
if let ExternType::Table(_) = other.inner {
|
||||
Ok(unsafe { mem::transmute::<&'static wasm_externtype_t, Self>(other) })
|
||||
} else {
|
||||
Err(ExternTypeConversionError("Wrong type: expected table"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_externtype_as_functype_const(
|
||||
et: &'static wasm_externtype_t,
|
||||
) -> Option<&'static wasm_functype_t> {
|
||||
Some(c_try!(et.try_into()))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_externtype_as_functype(
|
||||
et: &'static wasm_externtype_t,
|
||||
) -> Option<&'static wasm_functype_t> {
|
||||
Some(c_try!(et.try_into()))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_functype_as_externtype_const(
|
||||
ft: &'static wasm_functype_t,
|
||||
) -> &'static wasm_externtype_t {
|
||||
&ft.extern_
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_functype_as_externtype(
|
||||
ft: &'static wasm_functype_t,
|
||||
) -> &'static wasm_externtype_t {
|
||||
&ft.extern_
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_externtype_as_memorytype_const(
|
||||
et: &'static wasm_externtype_t,
|
||||
) -> Option<&'static wasm_memorytype_t> {
|
||||
Some(c_try!(et.try_into()))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_externtype_as_memorytype(
|
||||
et: &'static wasm_externtype_t,
|
||||
) -> Option<&'static wasm_memorytype_t> {
|
||||
Some(c_try!(et.try_into()))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_memorytype_as_externtype_const(
|
||||
mt: &'static wasm_memorytype_t,
|
||||
) -> &'static wasm_externtype_t {
|
||||
&mt.extern_
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_memorytype_as_externtype(
|
||||
mt: &'static wasm_memorytype_t,
|
||||
) -> &'static wasm_externtype_t {
|
||||
&mt.extern_
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_externtype_as_globaltype_const(
|
||||
et: &'static wasm_externtype_t,
|
||||
) -> Option<&'static wasm_globaltype_t> {
|
||||
Some(c_try!(et.try_into()))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_externtype_as_globaltype(
|
||||
et: &'static wasm_externtype_t,
|
||||
) -> Option<&'static wasm_globaltype_t> {
|
||||
Some(c_try!(et.try_into()))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_globaltype_as_externtype_const(
|
||||
gt: &'static wasm_globaltype_t,
|
||||
) -> &'static wasm_externtype_t {
|
||||
>.extern_
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_globaltype_as_externtype(
|
||||
gt: &'static wasm_globaltype_t,
|
||||
) -> &'static wasm_externtype_t {
|
||||
>.extern_
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_externtype_as_tabletype_const(
|
||||
et: &'static wasm_externtype_t,
|
||||
) -> Option<&'static wasm_tabletype_t> {
|
||||
Some(c_try!(et.try_into()))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_externtype_as_tabletype(
|
||||
et: &'static wasm_externtype_t,
|
||||
) -> Option<&'static wasm_tabletype_t> {
|
||||
Some(c_try!(et.try_into()))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_tabletype_as_externtype_const(
|
||||
tt: &'static wasm_tabletype_t,
|
||||
) -> &'static wasm_externtype_t {
|
||||
&tt.extern_
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_tabletype_as_externtype(
|
||||
tt: &'static wasm_tabletype_t,
|
||||
) -> &'static wasm_externtype_t {
|
||||
&tt.extern_
|
||||
}
|
||||
5
lib/c-api/src/wasm_c_api/types/frame.rs
Normal file
5
lib/c-api/src/wasm_c_api/types/frame.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub struct wasm_frame_t {}
|
||||
|
||||
wasm_declare_vec!(frame);
|
||||
112
lib/c-api/src/wasm_c_api/types/function.rs
Normal file
112
lib/c-api/src/wasm_c_api/types/function.rs
Normal file
@@ -0,0 +1,112 @@
|
||||
use super::{wasm_externtype_t, wasm_valtype_t, wasm_valtype_vec_t};
|
||||
use std::mem;
|
||||
use std::ptr::NonNull;
|
||||
use wasmer::{ExternType, FunctionType, ValType};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[repr(transparent)]
|
||||
pub struct wasm_functype_t {
|
||||
pub(crate) extern_: wasm_externtype_t,
|
||||
}
|
||||
|
||||
impl wasm_functype_t {
|
||||
pub(crate) fn sig(&self) -> &FunctionType {
|
||||
if let ExternType::Function(ref f) = self.extern_.inner {
|
||||
f
|
||||
} else {
|
||||
unreachable!("data corruption: `wasm_functype_t` does not contain a function")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wasm_declare_vec!(functype);
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_functype_new(
|
||||
// own
|
||||
params: Option<NonNull<wasm_valtype_vec_t>>,
|
||||
// own
|
||||
results: Option<NonNull<wasm_valtype_vec_t>>,
|
||||
) -> Option<Box<wasm_functype_t>> {
|
||||
wasm_functype_new_inner(params?, results?)
|
||||
}
|
||||
|
||||
unsafe fn wasm_functype_new_inner(
|
||||
// own
|
||||
params: NonNull<wasm_valtype_vec_t>,
|
||||
// own
|
||||
results: NonNull<wasm_valtype_vec_t>,
|
||||
) -> Option<Box<wasm_functype_t>> {
|
||||
let params = params.as_ref();
|
||||
let results = results.as_ref();
|
||||
let params: Vec<ValType> = params
|
||||
.into_slice()?
|
||||
.iter()
|
||||
.map(|&ptr| *ptr)
|
||||
.map(Into::into)
|
||||
.collect::<Vec<_>>();
|
||||
let results: Vec<ValType> = results
|
||||
.into_slice()?
|
||||
.iter()
|
||||
.map(|&ptr| *ptr)
|
||||
.map(Into::into)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let extern_ = wasm_externtype_t {
|
||||
inner: ExternType::Function(FunctionType::new(params, results)),
|
||||
};
|
||||
Some(Box::new(wasm_functype_t { extern_ }))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_functype_delete(_ft: Option<Box<wasm_functype_t>>) {}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_functype_copy(
|
||||
arg: Option<NonNull<wasm_functype_t>>,
|
||||
) -> Option<Box<wasm_functype_t>> {
|
||||
let arg = arg?;
|
||||
let funcsig = arg.as_ref();
|
||||
Some(Box::new(funcsig.clone()))
|
||||
}
|
||||
|
||||
// TODO: fix memory leak
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_functype_params(ft: &wasm_functype_t) -> *const wasm_valtype_vec_t {
|
||||
let mut valtypes = ft
|
||||
.sig()
|
||||
.params()
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(Into::into)
|
||||
.map(Box::new)
|
||||
.map(Box::into_raw)
|
||||
.collect::<Vec<*mut wasm_valtype_t>>();
|
||||
let out = Box::into_raw(Box::new(wasm_valtype_vec_t {
|
||||
size: valtypes.len(),
|
||||
data: valtypes.as_mut_ptr(),
|
||||
}));
|
||||
mem::forget(valtypes);
|
||||
out as *const _
|
||||
}
|
||||
|
||||
// TODO: fix memory leak
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_functype_results(ft: &wasm_functype_t) -> *const wasm_valtype_vec_t {
|
||||
let mut valtypes = ft
|
||||
.sig()
|
||||
.results()
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(Into::into)
|
||||
.map(Box::new)
|
||||
.map(Box::into_raw)
|
||||
.collect::<Vec<*mut wasm_valtype_t>>();
|
||||
let out = Box::into_raw(Box::new(wasm_valtype_vec_t {
|
||||
size: valtypes.len(),
|
||||
data: valtypes.as_mut_ptr(),
|
||||
}));
|
||||
mem::forget(valtypes);
|
||||
out as *const _
|
||||
}
|
||||
72
lib/c-api/src/wasm_c_api/types/global.rs
Normal file
72
lib/c-api/src/wasm_c_api/types/global.rs
Normal file
@@ -0,0 +1,72 @@
|
||||
use super::{
|
||||
wasm_externtype_t, wasm_mutability_enum, wasm_mutability_t, wasm_valtype_delete, wasm_valtype_t,
|
||||
};
|
||||
use std::convert::TryInto;
|
||||
use wasmer::{ExternType, GlobalType};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[repr(transparent)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct wasm_globaltype_t {
|
||||
pub(crate) extern_: wasm_externtype_t,
|
||||
}
|
||||
|
||||
impl wasm_globaltype_t {
|
||||
pub(crate) fn as_globaltype(&self) -> &GlobalType {
|
||||
if let ExternType::Global(ref g) = self.extern_.inner {
|
||||
g
|
||||
} else {
|
||||
unreachable!(
|
||||
"Data corruption detected: `wasm_globaltype_t` does not contain a `GlobalType`"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wasm_declare_vec!(globaltype);
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_globaltype_new(
|
||||
// own
|
||||
valtype: Option<Box<wasm_valtype_t>>,
|
||||
mutability: wasm_mutability_t,
|
||||
) -> Option<Box<wasm_globaltype_t>> {
|
||||
wasm_globaltype_new_inner(valtype?, mutability)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_globaltype_delete(_globaltype: Option<Box<wasm_globaltype_t>>) {}
|
||||
|
||||
unsafe fn wasm_globaltype_new_inner(
|
||||
// own
|
||||
valtype: Box<wasm_valtype_t>,
|
||||
mutability: wasm_mutability_t,
|
||||
) -> Option<Box<wasm_globaltype_t>> {
|
||||
let me: wasm_mutability_enum = mutability.try_into().ok()?;
|
||||
let gd = Box::new(wasm_globaltype_t {
|
||||
extern_: wasm_externtype_t {
|
||||
inner: ExternType::Global(GlobalType::new((*valtype).into(), me.into())),
|
||||
},
|
||||
});
|
||||
wasm_valtype_delete(Some(valtype));
|
||||
|
||||
Some(gd)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_globaltype_mutability(
|
||||
globaltype: &wasm_globaltype_t,
|
||||
) -> wasm_mutability_t {
|
||||
let gt = globaltype.as_globaltype();
|
||||
wasm_mutability_enum::from(gt.mutability).into()
|
||||
}
|
||||
|
||||
// TODO: fix memory leak
|
||||
// this function leaks memory because the returned limits pointer is not owned
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_globaltype_content(
|
||||
globaltype: &wasm_globaltype_t,
|
||||
) -> *const wasm_valtype_t {
|
||||
let gt = globaltype.as_globaltype();
|
||||
Box::into_raw(Box::new(gt.ty.into()))
|
||||
}
|
||||
94
lib/c-api/src/wasm_c_api/types/import.rs
Normal file
94
lib/c-api/src/wasm_c_api/types/import.rs
Normal file
@@ -0,0 +1,94 @@
|
||||
use super::{wasm_externtype_t, wasm_name_t};
|
||||
use std::ptr::NonNull;
|
||||
use wasmer::ImportType;
|
||||
|
||||
// TODO: improve ownership in `importtype_t` (can we safely use `Box<wasm_name_t>` here?)
|
||||
#[repr(C)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct wasm_importtype_t {
|
||||
pub(crate) module: NonNull<wasm_name_t>,
|
||||
pub(crate) name: NonNull<wasm_name_t>,
|
||||
pub(crate) extern_type: NonNull<wasm_externtype_t>,
|
||||
}
|
||||
|
||||
wasm_declare_boxed_vec!(importtype);
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_importtype_new(
|
||||
module: NonNull<wasm_name_t>,
|
||||
name: NonNull<wasm_name_t>,
|
||||
extern_type: NonNull<wasm_externtype_t>,
|
||||
) -> Box<wasm_importtype_t> {
|
||||
Box::new(wasm_importtype_t {
|
||||
name,
|
||||
module,
|
||||
extern_type,
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_importtype_module(et: &'static wasm_importtype_t) -> &'static wasm_name_t {
|
||||
unsafe { et.module.as_ref() }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_importtype_name(et: &'static wasm_importtype_t) -> &'static wasm_name_t {
|
||||
unsafe { et.name.as_ref() }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_importtype_type(
|
||||
et: &'static wasm_importtype_t,
|
||||
) -> &'static wasm_externtype_t {
|
||||
unsafe { et.extern_type.as_ref() }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_importtype_delete(_importtype: Option<Box<wasm_importtype_t>>) {}
|
||||
|
||||
impl From<ImportType> for wasm_importtype_t {
|
||||
fn from(other: ImportType) -> Self {
|
||||
(&other).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&ImportType> for wasm_importtype_t {
|
||||
fn from(other: &ImportType) -> Self {
|
||||
// TODO: double check that freeing String as `Vec<u8>` is valid
|
||||
let name = {
|
||||
let mut heap_str: Box<str> = other.name().to_string().into_boxed_str();
|
||||
let char_ptr = heap_str.as_mut_ptr();
|
||||
let str_len = heap_str.bytes().len();
|
||||
let name_inner = wasm_name_t {
|
||||
size: str_len,
|
||||
data: char_ptr,
|
||||
};
|
||||
Box::leak(heap_str);
|
||||
unsafe { NonNull::new_unchecked(Box::into_raw(Box::new(name_inner))) }
|
||||
};
|
||||
|
||||
// TODO: double check that freeing String as `Vec<u8>` is valid
|
||||
let module = {
|
||||
let mut heap_str: Box<str> = other.module().to_string().into_boxed_str();
|
||||
let char_ptr = heap_str.as_mut_ptr();
|
||||
let str_len = heap_str.bytes().len();
|
||||
let name_inner = wasm_name_t {
|
||||
size: str_len,
|
||||
data: char_ptr,
|
||||
};
|
||||
Box::leak(heap_str);
|
||||
unsafe { NonNull::new_unchecked(Box::into_raw(Box::new(name_inner))) }
|
||||
};
|
||||
|
||||
let extern_type = {
|
||||
let extern_type: wasm_externtype_t = other.ty().into();
|
||||
unsafe { NonNull::new_unchecked(Box::into_raw(Box::new(extern_type))) }
|
||||
};
|
||||
|
||||
wasm_importtype_t {
|
||||
name,
|
||||
module,
|
||||
extern_type,
|
||||
}
|
||||
}
|
||||
}
|
||||
61
lib/c-api/src/wasm_c_api/types/memory.rs
Normal file
61
lib/c-api/src/wasm_c_api/types/memory.rs
Normal file
@@ -0,0 +1,61 @@
|
||||
use super::wasm_externtype_t;
|
||||
use wasmer::{ExternType, MemoryType, Pages};
|
||||
|
||||
// opaque type wrapping `MemoryType`
|
||||
#[derive(Clone, Debug)]
|
||||
#[repr(transparent)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct wasm_memorytype_t {
|
||||
pub(crate) extern_: wasm_externtype_t,
|
||||
}
|
||||
|
||||
impl wasm_memorytype_t {
|
||||
pub(crate) fn as_memorytype(&self) -> &MemoryType {
|
||||
if let ExternType::Memory(ref mt) = self.extern_.inner {
|
||||
mt
|
||||
} else {
|
||||
unreachable!(
|
||||
"Data corruption detected: `wasm_memorytype_t` does not contain a `MemoryType`"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wasm_declare_vec!(memorytype);
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct wasm_limits_t {
|
||||
pub(crate) min: u32,
|
||||
pub(crate) max: u32,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_memorytype_new(limits: &wasm_limits_t) -> Box<wasm_memorytype_t> {
|
||||
let min_pages = Pages(limits.min as _);
|
||||
// TODO: investigate if `0` is in fact a sentinel value here
|
||||
let max_pages = if limits.max == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(Pages(limits.max as _))
|
||||
};
|
||||
Box::new(wasm_memorytype_t {
|
||||
extern_: wasm_externtype_t {
|
||||
inner: ExternType::Memory(MemoryType::new(min_pages, max_pages, false)),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_memorytype_delete(_memorytype: Option<Box<wasm_memorytype_t>>) {}
|
||||
|
||||
// TODO: fix memory leak
|
||||
// this function leaks memory because the returned limits pointer is not owned
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_memorytype_limits(mt: &wasm_memorytype_t) -> *const wasm_limits_t {
|
||||
let md = mt.as_memorytype();
|
||||
Box::into_raw(Box::new(wasm_limits_t {
|
||||
min: md.minimum.bytes().0 as _,
|
||||
max: md.maximum.map(|max| max.bytes().0 as _).unwrap_or(0),
|
||||
}))
|
||||
}
|
||||
27
lib/c-api/src/wasm_c_api/types/mod.rs
Normal file
27
lib/c-api/src/wasm_c_api/types/mod.rs
Normal file
@@ -0,0 +1,27 @@
|
||||
mod byte;
|
||||
mod export;
|
||||
mod extern_;
|
||||
mod frame;
|
||||
mod function;
|
||||
mod global;
|
||||
mod import;
|
||||
mod memory;
|
||||
mod mutability;
|
||||
mod name;
|
||||
mod reference;
|
||||
mod table;
|
||||
mod value;
|
||||
|
||||
pub use byte::*;
|
||||
pub use export::*;
|
||||
pub use extern_::*;
|
||||
pub use frame::*;
|
||||
pub use function::*;
|
||||
pub use global::*;
|
||||
pub use import::*;
|
||||
pub use memory::*;
|
||||
pub use mutability::*;
|
||||
pub use name::*;
|
||||
pub use reference::*;
|
||||
pub use table::*;
|
||||
pub use value::*;
|
||||
56
lib/c-api/src/wasm_c_api/types/mutability.rs
Normal file
56
lib/c-api/src/wasm_c_api/types/mutability.rs
Normal file
@@ -0,0 +1,56 @@
|
||||
use std::convert::TryFrom;
|
||||
use wasmer::Mutability;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type wasm_mutability_t = u8;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[repr(u8)]
|
||||
pub enum wasm_mutability_enum {
|
||||
WASM_CONST = 0,
|
||||
WASM_VAR,
|
||||
}
|
||||
|
||||
impl wasm_mutability_enum {
|
||||
#[allow(dead_code)]
|
||||
fn is_mutable(self) -> bool {
|
||||
self == Self::WASM_VAR
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<wasm_mutability_t> for wasm_mutability_enum {
|
||||
type Error = &'static str;
|
||||
|
||||
fn try_from(item: wasm_mutability_t) -> Result<Self, Self::Error> {
|
||||
Ok(match item {
|
||||
0 => wasm_mutability_enum::WASM_CONST,
|
||||
1 => wasm_mutability_enum::WASM_VAR,
|
||||
_ => return Err("wasm_mutability_t value out of bounds"),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl From<wasm_mutability_enum> for wasm_mutability_t {
|
||||
fn from(other: wasm_mutability_enum) -> Self {
|
||||
other as wasm_mutability_t
|
||||
}
|
||||
}
|
||||
|
||||
impl From<wasm_mutability_enum> for Mutability {
|
||||
fn from(other: wasm_mutability_enum) -> Self {
|
||||
match other {
|
||||
wasm_mutability_enum::WASM_CONST => Mutability::Const,
|
||||
wasm_mutability_enum::WASM_VAR => Mutability::Var,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Mutability> for wasm_mutability_enum {
|
||||
fn from(other: Mutability) -> Self {
|
||||
match other {
|
||||
Mutability::Const => wasm_mutability_enum::WASM_CONST,
|
||||
Mutability::Var => wasm_mutability_enum::WASM_VAR,
|
||||
}
|
||||
}
|
||||
}
|
||||
4
lib/c-api/src/wasm_c_api/types/name.rs
Normal file
4
lib/c-api/src/wasm_c_api/types/name.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
use super::wasm_byte_vec_t;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type wasm_name_t = wasm_byte_vec_t;
|
||||
3
lib/c-api/src/wasm_c_api/types/reference.rs
Normal file
3
lib/c-api/src/wasm_c_api/types/reference.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
// opaque type over `ExternRef`?
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct wasm_ref_t;
|
||||
79
lib/c-api/src/wasm_c_api/types/table.rs
Normal file
79
lib/c-api/src/wasm_c_api/types/table.rs
Normal file
@@ -0,0 +1,79 @@
|
||||
use super::{wasm_externtype_t, wasm_limits_t, wasm_valtype_delete, wasm_valtype_t};
|
||||
use wasmer::{ExternType, TableType};
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type wasm_table_size_t = u32;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[repr(C)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct wasm_tabletype_t {
|
||||
pub(crate) extern_: wasm_externtype_t,
|
||||
}
|
||||
|
||||
wasm_declare_vec!(tabletype);
|
||||
|
||||
impl wasm_tabletype_t {
|
||||
pub(crate) fn as_tabletype(&self) -> &TableType {
|
||||
if let ExternType::Table(ref t) = self.extern_.inner {
|
||||
t
|
||||
} else {
|
||||
unreachable!(
|
||||
"Data corruption detected: `wasm_tabletype_t` does not contain a `TableType`"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_tabletype_new(
|
||||
// own
|
||||
valtype: Box<wasm_valtype_t>,
|
||||
limits: &wasm_limits_t,
|
||||
) -> Box<wasm_tabletype_t> {
|
||||
// TODO: investigate if `0` is in fact a sentinel value here
|
||||
let max_elements = if limits.max == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(limits.max as _)
|
||||
};
|
||||
let out = Box::new(wasm_tabletype_t {
|
||||
extern_: wasm_externtype_t {
|
||||
inner: ExternType::Table(TableType::new(
|
||||
(*valtype).into(),
|
||||
limits.min as _,
|
||||
max_elements,
|
||||
)),
|
||||
},
|
||||
});
|
||||
wasm_valtype_delete(Some(valtype));
|
||||
|
||||
out
|
||||
}
|
||||
|
||||
// TODO: fix memory leak
|
||||
// this function leaks memory because the returned limits pointer is not owned
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_tabletype_limits(
|
||||
tabletype: &wasm_tabletype_t,
|
||||
) -> *const wasm_limits_t {
|
||||
let tt = tabletype.as_tabletype();
|
||||
Box::into_raw(Box::new(wasm_limits_t {
|
||||
min: tt.minimum as _,
|
||||
max: tt.maximum.unwrap_or(0),
|
||||
}))
|
||||
}
|
||||
|
||||
// TODO: fix memory leak
|
||||
// this function leaks memory because the returned limits pointer is not owned
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_tabletype_element(
|
||||
tabletype: &wasm_tabletype_t,
|
||||
) -> *const wasm_valtype_t {
|
||||
let tt = tabletype.as_tabletype();
|
||||
|
||||
Box::into_raw(Box::new(tt.ty.into()))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_tabletype_delete(_tabletype: Option<Box<wasm_tabletype_t>>) {}
|
||||
92
lib/c-api/src/wasm_c_api/types/value.rs
Normal file
92
lib/c-api/src/wasm_c_api/types/value.rs
Normal file
@@ -0,0 +1,92 @@
|
||||
use super::super::value::wasm_valkind_t;
|
||||
use std::convert::TryInto;
|
||||
use wasmer::ValType;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[repr(u8)]
|
||||
pub enum wasm_valkind_enum {
|
||||
WASM_I32 = 0,
|
||||
WASM_I64 = 1,
|
||||
WASM_F32 = 2,
|
||||
WASM_F64 = 3,
|
||||
WASM_ANYREF = 128,
|
||||
WASM_FUNCREF = 129,
|
||||
}
|
||||
|
||||
impl From<ValType> for wasm_valkind_enum {
|
||||
fn from(other: ValType) -> Self {
|
||||
match other {
|
||||
ValType::I32 => Self::WASM_I32,
|
||||
ValType::I64 => Self::WASM_I64,
|
||||
ValType::F32 => Self::WASM_F32,
|
||||
ValType::F64 => Self::WASM_F64,
|
||||
ValType::V128 => todo!("no v128 type in Wasm C API yet!"),
|
||||
ValType::ExternRef => Self::WASM_ANYREF,
|
||||
ValType::FuncRef => Self::WASM_FUNCREF,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<wasm_valkind_enum> for ValType {
|
||||
fn from(other: wasm_valkind_enum) -> Self {
|
||||
use wasm_valkind_enum::*;
|
||||
match other {
|
||||
WASM_I32 => ValType::I32,
|
||||
WASM_I64 => ValType::I64,
|
||||
WASM_F32 => ValType::F32,
|
||||
WASM_F64 => ValType::F64,
|
||||
WASM_ANYREF => ValType::ExternRef,
|
||||
WASM_FUNCREF => ValType::FuncRef,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct wasm_valtype_t {
|
||||
valkind: wasm_valkind_enum,
|
||||
}
|
||||
|
||||
impl Default for wasm_valtype_t {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
valkind: wasm_valkind_enum::WASM_I32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wasm_declare_boxed_vec!(valtype);
|
||||
|
||||
impl From<wasm_valtype_t> for ValType {
|
||||
fn from(other: wasm_valtype_t) -> Self {
|
||||
other.valkind.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ValType> for wasm_valtype_t {
|
||||
fn from(other: ValType) -> Self {
|
||||
Self {
|
||||
valkind: other.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_valtype_new(kind: wasm_valkind_t) -> Option<Box<wasm_valtype_t>> {
|
||||
let kind_enum = kind.try_into().ok()?;
|
||||
let valtype = wasm_valtype_t { valkind: kind_enum };
|
||||
Some(Box::new(valtype))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_valtype_delete(_valtype: Option<Box<wasm_valtype_t>>) {}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_valtype_kind(valtype: *const wasm_valtype_t) -> wasm_valkind_t {
|
||||
if valtype.is_null() {
|
||||
// TODO: handle error
|
||||
panic!("wasm_valtype_kind: argument is null pointer");
|
||||
}
|
||||
return (*valtype).valkind as wasm_valkind_t;
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#[macro_export]
|
||||
macro_rules! c_try {
|
||||
($expr:expr) => {{
|
||||
let res: Result<_, _> = $expr;
|
||||
match res {
|
||||
Ok(val) => val,
|
||||
Err(err) => {
|
||||
crate::error::update_last_error(err);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}};
|
||||
($expr:expr, $e:expr) => {{
|
||||
let opt: Option<_> = $expr;
|
||||
c_try!(opt.ok_or_else(|| $e))
|
||||
}};
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
use super::{wasm_ref_t, wasm_valkind_enum};
|
||||
use super::types::{wasm_ref_t, wasm_valkind_enum};
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::ptr::NonNull;
|
||||
use wasmer::Val;
|
||||
|
||||
@@ -12,7 +12,6 @@ use super::{
|
||||
};
|
||||
// required due to really weird Rust resolution rules for macros
|
||||
// https://github.com/rust-lang/rust/issues/57966
|
||||
use crate::c_try;
|
||||
use crate::error::{update_last_error, CApiError};
|
||||
use std::convert::TryFrom;
|
||||
use std::ffi::CStr;
|
||||
|
||||
Reference in New Issue
Block a user