2018-07-19 14:44:23 -05:00
|
|
|
use core::char;
|
|
|
|
use core::mem::{self, ManuallyDrop};
|
|
|
|
|
2018-08-03 16:28:35 +03:00
|
|
|
use convert::traits::WasmAbi;
|
2018-09-26 08:26:00 -07:00
|
|
|
use convert::{FromWasmAbi, IntoWasmAbi, RefFromWasmAbi, Stack};
|
|
|
|
use convert::{OptionFromWasmAbi, OptionIntoWasmAbi, ReturnWasmAbi};
|
|
|
|
use {Clamped, JsValue};
|
2018-07-19 14:44:23 -05:00
|
|
|
|
2018-09-17 18:26:45 -07:00
|
|
|
unsafe impl WasmAbi for () {}
|
|
|
|
|
2018-08-03 16:28:35 +03:00
|
|
|
#[repr(C)]
|
|
|
|
pub struct WasmOptionalI32 {
|
|
|
|
pub present: u32,
|
|
|
|
pub value: i32,
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe impl WasmAbi for WasmOptionalI32 {}
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
pub struct WasmOptionalU32 {
|
|
|
|
pub present: u32,
|
|
|
|
pub value: u32,
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe impl WasmAbi for WasmOptionalU32 {}
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
pub struct WasmOptionalF32 {
|
|
|
|
pub present: u32,
|
|
|
|
pub value: f32,
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe impl WasmAbi for WasmOptionalF32 {}
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
pub struct WasmOptionalF64 {
|
|
|
|
pub present: u32,
|
|
|
|
pub value: f64,
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe impl WasmAbi for WasmOptionalF64 {}
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
pub struct Wasm64 {
|
|
|
|
pub low: u32,
|
|
|
|
pub high: u32,
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe impl WasmAbi for Wasm64 {}
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
pub struct WasmOptional64 {
|
|
|
|
pub present: u32,
|
|
|
|
pub padding: u32,
|
|
|
|
pub low: u32,
|
|
|
|
pub high: u32,
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe impl WasmAbi for WasmOptional64 {}
|
|
|
|
|
2018-08-03 18:40:55 +03:00
|
|
|
macro_rules! type_wasm_native {
|
2018-08-03 16:28:35 +03:00
|
|
|
($($t:tt as $c:tt => $r:tt)*) => ($(
|
2018-07-19 14:44:23 -05:00
|
|
|
impl IntoWasmAbi for $t {
|
2018-08-03 16:28:35 +03:00
|
|
|
type Abi = $c;
|
2018-07-19 14:44:23 -05:00
|
|
|
|
|
|
|
#[inline]
|
2018-08-03 16:28:35 +03:00
|
|
|
fn into_abi(self, _extra: &mut Stack) -> $c { self as $c }
|
2018-07-19 14:44:23 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
impl FromWasmAbi for $t {
|
2018-08-03 16:28:35 +03:00
|
|
|
type Abi = $c;
|
2018-07-19 14:44:23 -05:00
|
|
|
|
|
|
|
#[inline]
|
2018-08-03 16:28:35 +03:00
|
|
|
unsafe fn from_abi(js: $c, _extra: &mut Stack) -> Self { js as $t }
|
|
|
|
}
|
|
|
|
|
|
|
|
impl IntoWasmAbi for Option<$t> {
|
|
|
|
type Abi = $r;
|
|
|
|
|
2018-10-01 15:27:34 -07:00
|
|
|
#[inline]
|
2018-08-03 16:28:35 +03:00
|
|
|
fn into_abi(self, _extra: &mut Stack) -> $r {
|
|
|
|
match self {
|
|
|
|
None => $r {
|
|
|
|
present: 0,
|
|
|
|
value: 0 as $c,
|
|
|
|
},
|
|
|
|
Some(me) => $r {
|
|
|
|
present: 1,
|
|
|
|
value: me as $c,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FromWasmAbi for Option<$t> {
|
|
|
|
type Abi = $r;
|
|
|
|
|
2018-10-01 15:27:34 -07:00
|
|
|
#[inline]
|
2018-08-03 16:28:35 +03:00
|
|
|
unsafe fn from_abi(js: $r, _extra: &mut Stack) -> Self {
|
|
|
|
if js.present == 0 {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(js.value as $t)
|
|
|
|
}
|
|
|
|
}
|
2018-07-19 14:44:23 -05:00
|
|
|
}
|
|
|
|
)*)
|
|
|
|
}
|
|
|
|
|
2018-08-03 18:40:55 +03:00
|
|
|
type_wasm_native!(
|
2018-08-03 16:28:35 +03:00
|
|
|
i32 as i32 => WasmOptionalI32
|
|
|
|
isize as i32 => WasmOptionalI32
|
|
|
|
u32 as u32 => WasmOptionalU32
|
|
|
|
usize as u32 => WasmOptionalU32
|
|
|
|
f32 as f32 => WasmOptionalF32
|
|
|
|
f64 as f64 => WasmOptionalF64
|
|
|
|
);
|
2018-07-19 14:44:23 -05:00
|
|
|
|
2018-08-03 18:40:55 +03:00
|
|
|
macro_rules! type_abi_as_u32 {
|
2018-07-19 14:44:23 -05:00
|
|
|
($($t:tt)*) => ($(
|
|
|
|
impl IntoWasmAbi for $t {
|
2018-08-03 16:28:35 +03:00
|
|
|
type Abi = u32;
|
2018-07-19 14:44:23 -05:00
|
|
|
|
|
|
|
#[inline]
|
2018-08-03 16:28:35 +03:00
|
|
|
fn into_abi(self, _extra: &mut Stack) -> u32 { self as u32 }
|
2018-07-19 14:44:23 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
impl FromWasmAbi for $t {
|
2018-08-03 16:28:35 +03:00
|
|
|
type Abi = u32;
|
2018-07-19 14:44:23 -05:00
|
|
|
|
|
|
|
#[inline]
|
2018-08-03 16:28:35 +03:00
|
|
|
unsafe fn from_abi(js: u32, _extra: &mut Stack) -> Self { js as $t }
|
|
|
|
}
|
|
|
|
|
|
|
|
impl OptionIntoWasmAbi for $t {
|
|
|
|
#[inline]
|
|
|
|
fn none() -> u32 { 0xFFFFFFu32 }
|
|
|
|
}
|
|
|
|
|
|
|
|
impl OptionFromWasmAbi for $t {
|
|
|
|
#[inline]
|
|
|
|
fn is_none(js: &u32) -> bool { *js == 0xFFFFFFu32 }
|
2018-07-19 14:44:23 -05:00
|
|
|
}
|
|
|
|
)*)
|
|
|
|
}
|
|
|
|
|
2018-08-03 18:40:55 +03:00
|
|
|
type_abi_as_u32!(i8 u8 i16 u16);
|
2018-07-19 14:44:23 -05:00
|
|
|
|
2018-08-03 16:28:35 +03:00
|
|
|
macro_rules! type_64 {
|
2018-07-19 14:44:23 -05:00
|
|
|
($($t:tt)*) => ($(
|
|
|
|
impl IntoWasmAbi for $t {
|
2018-08-03 16:28:35 +03:00
|
|
|
type Abi = Wasm64;
|
2018-07-19 14:44:23 -05:00
|
|
|
|
|
|
|
#[inline]
|
2018-08-03 16:28:35 +03:00
|
|
|
fn into_abi(self, _extra: &mut Stack) -> Wasm64 {
|
|
|
|
Wasm64 {
|
|
|
|
low: self as u32,
|
|
|
|
high: (self >> 32) as u32,
|
|
|
|
}
|
|
|
|
}
|
2018-07-19 14:44:23 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
impl FromWasmAbi for $t {
|
2018-08-03 16:28:35 +03:00
|
|
|
type Abi = Wasm64;
|
2018-07-19 14:44:23 -05:00
|
|
|
|
|
|
|
#[inline]
|
2018-08-03 16:28:35 +03:00
|
|
|
unsafe fn from_abi(js: Wasm64, _extra: &mut Stack) -> $t {
|
|
|
|
(js.low as $t) | ((js.high as $t) << 32)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl IntoWasmAbi for Option<$t> {
|
|
|
|
type Abi = WasmOptional64;
|
|
|
|
|
2018-10-01 15:27:34 -07:00
|
|
|
#[inline]
|
2018-08-03 16:28:35 +03:00
|
|
|
fn into_abi(self, _extra: &mut Stack) -> WasmOptional64 {
|
|
|
|
match self {
|
|
|
|
None => WasmOptional64 {
|
|
|
|
present: 0,
|
|
|
|
padding: 0,
|
|
|
|
low: 0 as u32,
|
|
|
|
high: 0 as u32,
|
|
|
|
},
|
|
|
|
Some(me) => WasmOptional64 {
|
|
|
|
present: 1,
|
|
|
|
padding: 0,
|
|
|
|
low: me as u32,
|
|
|
|
high: (me >> 32) as u32,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FromWasmAbi for Option<$t> {
|
|
|
|
type Abi = WasmOptional64;
|
|
|
|
|
2018-10-01 15:27:34 -07:00
|
|
|
#[inline]
|
2018-08-03 16:28:35 +03:00
|
|
|
unsafe fn from_abi(js: WasmOptional64, _extra: &mut Stack) -> Self {
|
|
|
|
if js.present == 0 {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some((js.low as $t) | ((js.high as $t) << 32))
|
|
|
|
}
|
|
|
|
}
|
2018-07-19 14:44:23 -05:00
|
|
|
}
|
|
|
|
)*)
|
|
|
|
}
|
|
|
|
|
2018-08-03 16:28:35 +03:00
|
|
|
type_64!(i64 u64);
|
2018-07-19 14:44:23 -05:00
|
|
|
|
|
|
|
impl IntoWasmAbi for bool {
|
|
|
|
type Abi = u32;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn into_abi(self, _extra: &mut Stack) -> u32 {
|
|
|
|
self as u32
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FromWasmAbi for bool {
|
|
|
|
type Abi = u32;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
unsafe fn from_abi(js: u32, _extra: &mut Stack) -> bool {
|
|
|
|
js != 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-03 19:07:12 +03:00
|
|
|
impl OptionIntoWasmAbi for bool {
|
|
|
|
#[inline]
|
2018-09-26 08:26:00 -07:00
|
|
|
fn none() -> u32 {
|
|
|
|
0xFFFFFFu32
|
|
|
|
}
|
2018-08-03 19:07:12 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
impl OptionFromWasmAbi for bool {
|
|
|
|
#[inline]
|
2018-09-26 08:26:00 -07:00
|
|
|
fn is_none(js: &u32) -> bool {
|
|
|
|
*js == 0xFFFFFFu32
|
|
|
|
}
|
2018-08-03 19:07:12 +03:00
|
|
|
}
|
|
|
|
|
2018-07-19 14:44:23 -05:00
|
|
|
impl IntoWasmAbi for char {
|
|
|
|
type Abi = u32;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn into_abi(self, _extra: &mut Stack) -> u32 {
|
|
|
|
self as u32
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FromWasmAbi for char {
|
|
|
|
type Abi = u32;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
unsafe fn from_abi(js: u32, _extra: &mut Stack) -> char {
|
|
|
|
char::from_u32_unchecked(js)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-03 20:45:57 +03:00
|
|
|
impl IntoWasmAbi for Option<char> {
|
|
|
|
type Abi = WasmOptionalU32;
|
|
|
|
|
2018-10-01 15:27:34 -07:00
|
|
|
#[inline]
|
2018-08-03 20:45:57 +03:00
|
|
|
fn into_abi(self, _extra: &mut Stack) -> WasmOptionalU32 {
|
|
|
|
match self {
|
|
|
|
None => WasmOptionalU32 {
|
|
|
|
present: 0,
|
|
|
|
value: 0,
|
|
|
|
},
|
|
|
|
Some(me) => WasmOptionalU32 {
|
|
|
|
present: 1,
|
|
|
|
value: me as u32,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FromWasmAbi for Option<char> {
|
|
|
|
type Abi = WasmOptionalU32;
|
|
|
|
|
2018-10-01 15:27:34 -07:00
|
|
|
#[inline]
|
2018-08-03 20:45:57 +03:00
|
|
|
unsafe fn from_abi(js: WasmOptionalU32, _extra: &mut Stack) -> Self {
|
|
|
|
if js.present == 0 {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(char::from_u32_unchecked(js.value))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-19 14:44:23 -05:00
|
|
|
impl<T> IntoWasmAbi for *const T {
|
|
|
|
type Abi = u32;
|
|
|
|
|
|
|
|
fn into_abi(self, _extra: &mut Stack) -> u32 {
|
|
|
|
self as u32
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> FromWasmAbi for *const T {
|
|
|
|
type Abi = u32;
|
|
|
|
|
|
|
|
unsafe fn from_abi(js: u32, _extra: &mut Stack) -> *const T {
|
|
|
|
js as *const T
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> IntoWasmAbi for *mut T {
|
|
|
|
type Abi = u32;
|
|
|
|
|
|
|
|
fn into_abi(self, _extra: &mut Stack) -> u32 {
|
|
|
|
self as u32
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> FromWasmAbi for *mut T {
|
|
|
|
type Abi = u32;
|
|
|
|
|
|
|
|
unsafe fn from_abi(js: u32, _extra: &mut Stack) -> *mut T {
|
|
|
|
js as *mut T
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl IntoWasmAbi for JsValue {
|
|
|
|
type Abi = u32;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn into_abi(self, _extra: &mut Stack) -> u32 {
|
|
|
|
let ret = self.idx;
|
|
|
|
mem::forget(self);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FromWasmAbi for JsValue {
|
|
|
|
type Abi = u32;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
unsafe fn from_abi(js: u32, _extra: &mut Stack) -> JsValue {
|
|
|
|
JsValue { idx: js }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> IntoWasmAbi for &'a JsValue {
|
|
|
|
type Abi = u32;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn into_abi(self, _extra: &mut Stack) -> u32 {
|
|
|
|
self.idx
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl RefFromWasmAbi for JsValue {
|
|
|
|
type Abi = u32;
|
|
|
|
type Anchor = ManuallyDrop<JsValue>;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
unsafe fn ref_from_abi(js: u32, _extra: &mut Stack) -> Self::Anchor {
|
|
|
|
ManuallyDrop::new(JsValue { idx: js })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: OptionIntoWasmAbi> IntoWasmAbi for Option<T> {
|
|
|
|
type Abi = T::Abi;
|
|
|
|
|
|
|
|
fn into_abi(self, extra: &mut Stack) -> T::Abi {
|
|
|
|
match self {
|
|
|
|
None => T::none(),
|
2018-08-03 16:28:35 +03:00
|
|
|
Some(me) => me.into_abi(extra),
|
2018-07-19 14:44:23 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: OptionFromWasmAbi> FromWasmAbi for Option<T> {
|
|
|
|
type Abi = T::Abi;
|
|
|
|
|
|
|
|
unsafe fn from_abi(js: T::Abi, extra: &mut Stack) -> Self {
|
|
|
|
if T::is_none(&js) {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(T::from_abi(js, extra))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-09-17 18:26:45 -07:00
|
|
|
|
2018-09-24 13:49:12 -07:00
|
|
|
impl<T: IntoWasmAbi> IntoWasmAbi for Clamped<T> {
|
|
|
|
type Abi = T::Abi;
|
|
|
|
|
|
|
|
fn into_abi(self, extra: &mut Stack) -> Self::Abi {
|
|
|
|
self.0.into_abi(extra)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: FromWasmAbi> FromWasmAbi for Clamped<T> {
|
|
|
|
type Abi = T::Abi;
|
|
|
|
|
|
|
|
unsafe fn from_abi(js: T::Abi, extra: &mut Stack) -> Self {
|
|
|
|
Clamped(T::from_abi(js, extra))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-17 18:26:45 -07:00
|
|
|
impl IntoWasmAbi for () {
|
|
|
|
type Abi = ();
|
|
|
|
|
2018-09-26 09:21:31 -07:00
|
|
|
#[inline]
|
2018-09-17 18:26:45 -07:00
|
|
|
fn into_abi(self, _extra: &mut Stack) -> () {
|
|
|
|
self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: IntoWasmAbi> ReturnWasmAbi for Result<T, JsValue> {
|
|
|
|
type Abi = T::Abi;
|
|
|
|
|
|
|
|
fn return_abi(self, extra: &mut Stack) -> Self::Abi {
|
|
|
|
match self {
|
|
|
|
Ok(v) => v.into_abi(extra),
|
|
|
|
Err(e) => ::throw_val(e),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|