use crate::encode::{
Anchored, BinaryDecode, BinaryEncode, BorrowScope, CallScoped, EncodeTypeDef, JsRef,
ThrowingResult,
};
use crate::ipc::EncodedData;
use crate::{JsCast, JsValue};
use core::mem::ManuallyDrop;
use core::ops::Deref;
pub trait IntoWasmAbi: BinaryEncode + EncodeTypeDef {
#[inline]
fn into_abi(self) -> u32
where
Self: Sized + IntoAbiId,
{
self.into_abi_id()
}
}
pub trait FromWasmAbi: BinaryDecode + EncodeTypeDef {
#[inline]
unsafe fn from_abi(js: u32) -> Self
where
Self: Sized + FromAbiId,
{
unsafe { Self::from_abi_id(js) }
}
}
pub trait OptionIntoWasmAbi: IntoWasmAbi {}
pub trait OptionFromWasmAbi: FromWasmAbi {}
pub trait WasmAbi {}
pub trait RefFromWasmAbi {
#[inline]
unsafe fn ref_from_abi(js: u32) -> AbiRef<Self>
where
Self: Sized + FromAbiId,
{
AbiRef(ManuallyDrop::new(unsafe { Self::from_abi_id(js) }))
}
}
pub struct AbiRef<T>(ManuallyDrop<T>);
impl<T> Deref for AbiRef<T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> AsRef<T> for AbiRef<T> {
#[inline]
fn as_ref(&self) -> &T {
self
}
}
#[doc(hidden)]
pub trait IntoAbiId {
fn into_abi_id(self) -> u32;
}
#[doc(hidden)]
pub trait FromAbiId {
unsafe fn from_abi_id(js: u32) -> Self;
}
impl<T> IntoAbiId for T
where
T: AsRef<JsValue>,
{
#[inline]
fn into_abi_id(self) -> u32 {
let id = self.as_ref().js_ref().into_abi();
core::mem::forget(self);
id
}
}
impl<T> FromAbiId for T
where
T: JsCast,
{
#[inline]
unsafe fn from_abi_id(js: u32) -> Self {
T::unchecked_from_js(JsValue::from_ref(JsRef::from_abi(js)))
}
}
pub trait ReturnAbi<S: BorrowScope> {
type Wire: EncodeTypeDef;
}
pub trait ReturnSync: ReturnAbi<CallScoped> {
fn return_abi(self, encoder: &mut EncodedData);
}
impl<T: IntoWasmAbi> ReturnAbi<CallScoped> for T {
type Wire = T;
}
impl<T: IntoWasmAbi> ReturnSync for T {
#[inline]
fn return_abi(self, encoder: &mut EncodedData) {
self.encode(encoder);
}
}
impl<T, E> ReturnAbi<CallScoped> for Result<T, E>
where
T: BinaryEncode + EncodeTypeDef,
E: Into<JsValue>,
{
type Wire = ThrowingResult<T, JsValue>;
}
impl<T, E> ReturnSync for Result<T, E>
where
T: BinaryEncode + EncodeTypeDef,
E: Into<JsValue>,
{
#[inline]
fn return_abi(self, encoder: &mut EncodedData) {
ThrowingResult(self.map_err(Into::into)).encode(encoder);
}
}
impl ReturnAbi<CallScoped> for crate::__rt::object_store::ObjectHandle {
type Wire = Self;
}
impl ReturnSync for crate::__rt::object_store::ObjectHandle {
#[inline]
fn return_abi(self, encoder: &mut EncodedData) {
self.encode(encoder);
}
}
pub trait TryFromJsValue: Sized {
fn try_from_js_value(value: JsValue) -> Result<Self, JsValue> {
Self::try_from_js_value_ref(&value).ok_or(value)
}
fn try_from_js_value_ref(value: &JsValue) -> Option<Self>;
}
pub trait ReturnAsync: ReturnAbi<Anchored> {
fn into_js_result(self) -> Result<JsValue, JsValue>;
}
impl<T> ReturnAbi<Anchored> for T
where
T: Into<JsValue> + crate::sys::Promising,
<T as crate::sys::Promising>::Resolution: EncodeTypeDef,
{
type Wire = <T as crate::sys::Promising>::Resolution;
}
impl<T> ReturnAsync for T
where
T: Into<JsValue> + crate::sys::Promising,
<T as crate::sys::Promising>::Resolution: EncodeTypeDef,
{
#[inline]
fn into_js_result(self) -> Result<JsValue, JsValue> {
Ok(self.into())
}
}
impl<T, E> ReturnAbi<Anchored> for Result<T, E>
where
T: Into<JsValue> + crate::sys::Promising,
<T as crate::sys::Promising>::Resolution: EncodeTypeDef,
E: Into<JsValue>,
{
type Wire = <T as crate::sys::Promising>::Resolution;
}
impl<T, E> ReturnAsync for Result<T, E>
where
T: Into<JsValue> + crate::sys::Promising,
<T as crate::sys::Promising>::Resolution: EncodeTypeDef,
E: Into<JsValue>,
{
#[inline]
fn into_js_result(self) -> Result<JsValue, JsValue> {
match self {
Ok(value) => Ok(value.into()),
Err(error) => Err(error.into()),
}
}
}
pub trait FromJsFuture: Sized {
fn from_js_future(result: Result<JsValue, JsValue>) -> Self;
}
impl<T: TryFromJsValue> FromJsFuture for T {
#[inline]
fn from_js_future(result: Result<JsValue, JsValue>) -> Self {
let value = result.expect("async function failed");
T::try_from_js_value(value).expect("async function returned incompatible value")
}
}
impl<T: TryFromJsValue, E: From<JsValue>> FromJsFuture for Result<T, E> {
#[inline]
fn from_js_future(result: Result<JsValue, JsValue>) -> Self {
match result {
Ok(value) => Ok(
T::try_from_js_value(value).expect("async function returned incompatible value")
),
Err(error) => Err(E::from(error)),
}
}
}
pub trait UpcastFrom<S: ?Sized> {}
pub trait Upcast<T: ?Sized> {
#[inline]
fn upcast(&self) -> &T
where
Self: crate::__rt::marker::ErasableGeneric,
T: Sized
+ crate::__rt::marker::ErasableGeneric<
Repr = <Self as crate::__rt::marker::ErasableGeneric>::Repr,
>,
{
unsafe { &*(self as *const Self as *const T) }
}
#[inline]
fn upcast_into(self) -> T
where
Self: Sized + crate::__rt::marker::ErasableGeneric,
T: Sized
+ crate::__rt::marker::ErasableGeneric<
Repr = <Self as crate::__rt::marker::ErasableGeneric>::Repr,
>,
{
unsafe { core::mem::transmute_copy(&core::mem::ManuallyDrop::new(self)) }
}
}
impl<S, T> Upcast<T> for S
where
T: UpcastFrom<S> + ?Sized,
S: ?Sized,
{
}
impl<'a, T, Target> UpcastFrom<&'a T> for &'a Target where Target: UpcastFrom<T> {}
impl<'a, T, Target> UpcastFrom<&'a mut T> for &'a mut Target where Target: UpcastFrom<T> {}
macro_rules! impl_tuple_upcast {
([$($ty:ident)+] [$($target:ident)+]) => {
impl<$($ty,)+ $($target,)+> UpcastFrom<($($ty,)+)> for ($($target,)+)
where
$($ty: JsGeneric,)+
$($target: JsGeneric + UpcastFrom<$ty>,)+
{
}
impl<$($ty,)+ $($target,)+> UpcastFrom<($($ty,)+)> for crate::sys::JsOption<($($target,)+)>
where
$($ty: JsGeneric,)+
$($target: JsGeneric + UpcastFrom<$ty>,)+
{
}
};
}
impl_tuple_upcast!([T1][Target1]);
impl_tuple_upcast!([T1 T2] [Target1 Target2]);
impl_tuple_upcast!([T1 T2 T3] [Target1 Target2 Target3]);
impl_tuple_upcast!([T1 T2 T3 T4] [Target1 Target2 Target3 Target4]);
impl_tuple_upcast!([T1 T2 T3 T4 T5] [Target1 Target2 Target3 Target4 Target5]);
impl_tuple_upcast!([T1 T2 T3 T4 T5 T6] [Target1 Target2 Target3 Target4 Target5 Target6]);
impl_tuple_upcast!([T1 T2 T3 T4 T5 T6 T7] [Target1 Target2 Target3 Target4 Target5 Target6 Target7]);
impl_tuple_upcast!([T1 T2 T3 T4 T5 T6 T7 T8] [Target1 Target2 Target3 Target4 Target5 Target6 Target7 Target8]);
pub trait JsGeneric:
crate::__rt::marker::ErasableGeneric<Repr = JsValue>
+ UpcastFrom<Self>
+ Upcast<Self>
+ Upcast<JsValue>
+ JsCast
+ crate::__rt::JsRefEncode
+ crate::__rt::EncodeTypeDef
+ crate::__rt::BinaryEncode
+ crate::__rt::BinaryDecode
+ crate::__rt::BatchableResult
+ 'static
{
}
impl<T> JsGeneric for T where
T: crate::__rt::marker::ErasableGeneric<Repr = JsValue>
+ UpcastFrom<T>
+ Upcast<JsValue>
+ JsCast
+ crate::__rt::JsRefEncode
+ crate::__rt::EncodeTypeDef
+ crate::__rt::BinaryEncode
+ crate::__rt::BinaryDecode
+ crate::__rt::BatchableResult
+ 'static
{
}
pub trait IntoJsGeneric {
type JsCanon: JsGeneric;
fn to_js(self) -> Self::JsCanon;
}
impl IntoJsGeneric for JsValue {
type JsCanon = JsValue;
#[inline]
fn to_js(self) -> JsValue {
self
}
}
impl<T: IntoJsGeneric + Clone> IntoJsGeneric for &T {
type JsCanon = T::JsCanon;
#[inline]
fn to_js(self) -> T::JsCanon {
self.clone().to_js()
}
}