use std::{borrow::Borrow, mem::ManuallyDrop, sync::Arc};
use anyhow::bail;
use bytes::Buf;
use crate::{
FfiDefault, Handle, LiftArgsError, MetadataBuffer, Result, RustBuffer, RustCallError,
RustCallStatus, RustCallStatusCode, UnexpectedUniFFICallbackError,
};
pub unsafe trait FfiConverter<UT>: Sized {
type FfiType: FfiDefault;
fn lower(obj: Self) -> Self::FfiType;
fn try_lift(v: Self::FfiType) -> Result<Self>;
fn write(obj: Self, buf: &mut Vec<u8>);
fn try_read(buf: &mut &[u8]) -> Result<Self>;
const TYPE_ID_META: MetadataBuffer;
}
#[cfg(not(all(target_arch = "wasm32", feature = "wasm-unstable-single-threaded")))]
pub unsafe trait FfiConverterArc<UT>: Send + Sync {
type FfiType: FfiDefault;
fn lower(obj: Arc<Self>) -> Self::FfiType;
fn try_lift(v: Self::FfiType) -> Result<Arc<Self>>;
fn write(obj: Arc<Self>, buf: &mut Vec<u8>);
fn try_read(buf: &mut &[u8]) -> Result<Arc<Self>>;
const TYPE_ID_META: MetadataBuffer;
}
#[cfg(all(target_arch = "wasm32", feature = "wasm-unstable-single-threaded"))]
pub unsafe trait FfiConverterArc<UT> {
type FfiType: FfiDefault;
fn lower(obj: Arc<Self>) -> Self::FfiType;
fn try_lift(v: Self::FfiType) -> Result<Arc<Self>>;
fn write(obj: Arc<Self>, buf: &mut Vec<u8>);
fn try_read(buf: &mut &[u8]) -> Result<Arc<Self>>;
const TYPE_ID_META: MetadataBuffer;
}
unsafe impl<T, UT> FfiConverter<UT> for Arc<T>
where
T: FfiConverterArc<UT> + ?Sized,
{
type FfiType = T::FfiType;
fn lower(obj: Self) -> Self::FfiType {
T::lower(obj)
}
fn try_lift(v: Self::FfiType) -> Result<Self> {
T::try_lift(v)
}
fn write(obj: Self, buf: &mut Vec<u8>) {
T::write(obj, buf)
}
fn try_read(buf: &mut &[u8]) -> Result<Self> {
T::try_read(buf)
}
const TYPE_ID_META: MetadataBuffer = T::TYPE_ID_META;
}
pub unsafe trait Lift<UT>: Sized {
type FfiType;
fn try_lift(v: Self::FfiType) -> Result<Self>;
fn try_read(buf: &mut &[u8]) -> Result<Self>;
fn try_lift_from_rust_buffer(v: RustBuffer) -> Result<Self> {
let vec = v.destroy_into_vec();
let mut buf = vec.as_slice();
let value = Self::try_read(&mut buf)?;
match Buf::remaining(&buf) {
0 => Ok(value),
n => bail!("junk data left in buffer after lifting (count: {n})",),
}
}
}
pub unsafe trait Lower<UT>: Sized {
type FfiType: FfiDefault;
fn lower(obj: Self) -> Self::FfiType;
fn write(obj: Self, buf: &mut Vec<u8>);
fn lower_into_rust_buffer(obj: Self) -> RustBuffer {
let mut buf = ::std::vec::Vec::new();
Self::write(obj, &mut buf);
RustBuffer::from_vec(buf)
}
}
pub unsafe trait LowerReturn<UT>: Sized {
type ReturnType: FfiDefault;
fn lower_return(v: Self) -> Result<Self::ReturnType, RustCallError>;
fn handle_failed_lift(error: LiftArgsError) -> Result<Self::ReturnType, RustCallError> {
Err(error.to_internal_error())
}
}
pub unsafe trait LowerError<UT>: Sized {
fn lower_error(obj: Self) -> RustBuffer;
}
pub unsafe trait LiftReturn<UT>: Sized {
type ReturnType;
fn try_lift_successful_return(v: Self::ReturnType) -> Result<Self>;
fn lift_foreign_return(ffi_return: Self::ReturnType, call_status: RustCallStatus) -> Self {
match call_status.code {
RustCallStatusCode::Success => Self::try_lift_successful_return(ffi_return)
.unwrap_or_else(|e| {
Self::handle_callback_unexpected_error(UnexpectedUniFFICallbackError::new(e))
}),
RustCallStatusCode::Error => {
Self::lift_error(ManuallyDrop::into_inner(call_status.error_buf))
}
_ => {
let e = <String as FfiConverter<crate::UniFfiTag>>::try_lift(
ManuallyDrop::into_inner(call_status.error_buf),
)
.unwrap_or_else(|e| format!("(Error lifting message: {e}"));
Self::handle_callback_unexpected_error(UnexpectedUniFFICallbackError::new(e))
}
}
}
fn lift_error(_buf: RustBuffer) -> Self {
panic!("Callback interface method returned unexpected error")
}
fn handle_callback_unexpected_error(e: UnexpectedUniFFICallbackError) -> Self {
panic!("Callback interface failure: {e}")
}
}
pub unsafe trait LiftRef<UT> {
type LiftType: Lift<UT> + Borrow<Self>;
}
pub trait TypeId<UT> {
const TYPE_ID_META: MetadataBuffer;
}
pub trait ConvertError<UT>: Sized {
fn try_convert_unexpected_callback_error(e: UnexpectedUniFFICallbackError) -> Result<Self>;
}
pub unsafe trait HandleAlloc<UT>: Send + Sync {
fn new_handle(value: Arc<Self>) -> Handle;
unsafe fn clone_handle(handle: Handle) -> Handle;
unsafe fn get_arc(handle: Handle) -> Arc<Self> {
Self::consume_handle(Self::clone_handle(handle))
}
unsafe fn consume_handle(handle: Handle) -> Arc<Self>;
}
#[macro_export]
#[allow(clippy::crate_in_macro_def)]
macro_rules! derive_ffi_traits {
(blanket $ty:ty) => {
$crate::derive_ffi_traits!(impl<UT> Lower<UT> for $ty);
$crate::derive_ffi_traits!(impl<UT> Lift<UT> for $ty);
$crate::derive_ffi_traits!(impl<UT> LowerReturn<UT> for $ty);
$crate::derive_ffi_traits!(impl<UT> LowerError<UT> for $ty);
$crate::derive_ffi_traits!(impl<UT> LiftReturn<UT> for $ty);
$crate::derive_ffi_traits!(impl<UT> LiftRef<UT> for $ty);
$crate::derive_ffi_traits!(impl<UT> ConvertError<UT> for $ty);
$crate::derive_ffi_traits!(impl<UT> TypeId<UT> for $ty);
};
(local $ty:ty) => {
$crate::derive_ffi_traits!(impl Lower<crate::UniFfiTag> for $ty);
$crate::derive_ffi_traits!(impl Lift<crate::UniFfiTag> for $ty);
$crate::derive_ffi_traits!(impl LowerReturn<crate::UniFfiTag> for $ty);
$crate::derive_ffi_traits!(impl LowerError<crate::UniFfiTag> for $ty);
$crate::derive_ffi_traits!(impl LiftReturn<crate::UniFfiTag> for $ty);
$crate::derive_ffi_traits!(impl LiftRef<crate::UniFfiTag> for $ty);
$crate::derive_ffi_traits!(impl ConvertError<crate::UniFfiTag> for $ty);
$crate::derive_ffi_traits!(impl TypeId<crate::UniFfiTag> for $ty);
};
(impl $(<$($generic:ident),*>)? $(::uniffi::)? Lower<$ut:path> for $ty:ty $(where $($where:tt)*)?) => {
unsafe impl $(<$($generic),*>)* $crate::Lower<$ut> for $ty $(where $($where)*)*
{
type FfiType = <Self as $crate::FfiConverter<$ut>>::FfiType;
fn lower(obj: Self) -> Self::FfiType {
<Self as $crate::FfiConverter<$ut>>::lower(obj)
}
fn write(obj: Self, buf: &mut ::std::vec::Vec<u8>) {
<Self as $crate::FfiConverter<$ut>>::write(obj, buf)
}
}
};
(impl $(<$($generic:ident),*>)? $(::uniffi::)? Lift<$ut:path> for $ty:ty $(where $($where:tt)*)?) => {
unsafe impl $(<$($generic),*>)* $crate::Lift<$ut> for $ty $(where $($where)*)*
{
type FfiType = <Self as $crate::FfiConverter<$ut>>::FfiType;
fn try_lift(v: Self::FfiType) -> $crate::deps::anyhow::Result<Self> {
<Self as $crate::FfiConverter<$ut>>::try_lift(v)
}
fn try_read(buf: &mut &[u8]) -> $crate::deps::anyhow::Result<Self> {
<Self as $crate::FfiConverter<$ut>>::try_read(buf)
}
}
};
(impl $(<$($generic:ident),*>)? $(::uniffi::)? LowerReturn<$ut:path> for $ty:ty $(where $($where:tt)*)?) => {
unsafe impl $(<$($generic),*>)* $crate::LowerReturn<$ut> for $ty $(where $($where)*)*
{
type ReturnType = <Self as $crate::Lower<$ut>>::FfiType;
fn lower_return(v: Self) -> $crate::deps::anyhow::Result<Self::ReturnType, $crate::RustCallError> {
::std::result::Result::Ok(<Self as $crate::Lower<$ut>>::lower(v))
}
}
};
(impl $(<$($generic:ident),*>)? $(::uniffi::)? LowerError<$ut:path> for $ty:ty $(where $($where:tt)*)?) => {
unsafe impl $(<$($generic),*>)* $crate::LowerError<$ut> for $ty $(where $($where)*)*
{
fn lower_error(obj: Self) -> $crate::RustBuffer {
<Self as $crate::Lower<$ut>>::lower_into_rust_buffer(obj)
}
}
};
(impl $(<$($generic:ident),*>)? $(::uniffi::)? LiftReturn<$ut:path> for $ty:ty $(where $($where:tt)*)?) => {
unsafe impl $(<$($generic),*>)* $crate::LiftReturn<$ut> for $ty $(where $($where)*)*
{
type ReturnType = <Self as $crate::Lift<$ut>>::FfiType;
fn try_lift_successful_return(v: Self::ReturnType) -> $crate::Result<Self> {
<Self as $crate::Lift<$ut>>::try_lift(v)
}
}
};
(impl $(<$($generic:ident),*>)? $(::uniffi::)? LiftRef<$ut:path> for $ty:ty $(where $($where:tt)*)?) => {
unsafe impl $(<$($generic),*>)* $crate::LiftRef<$ut> for $ty $(where $($where)*)*
{
type LiftType = Self;
}
};
(impl $(<$($generic:ident),*>)? $(::uniffi::)? ConvertError<$ut:path> for $ty:ty $(where $($where:tt)*)?) => {
impl $(<$($generic),*>)* $crate::ConvertError<$ut> for $ty $(where $($where)*)*
{
fn try_convert_unexpected_callback_error(e: $crate::UnexpectedUniFFICallbackError) -> $crate::deps::anyhow::Result<Self> {
$crate::convert_unexpected_error!(e, $ty)
}
}
};
(impl $(<$($generic:ident),*>)? $(::uniffi::)? HandleAlloc<$ut:path> for $ty:ty $(where $($where:tt)*)?) => {
unsafe impl $(<$($generic),*>)* $crate::HandleAlloc<$ut> for $ty $(where $($where)*)*
{
fn new_handle(value: ::std::sync::Arc<Self>) -> $crate::Handle {
$crate::Handle::from_pointer(::std::sync::Arc::into_raw(::std::sync::Arc::new(value)))
}
unsafe fn clone_handle(handle: $crate::Handle) -> $crate::Handle {
::std::sync::Arc::<::std::sync::Arc<Self>>::increment_strong_count(handle.as_pointer::<::std::sync::Arc<Self>>());
handle
}
unsafe fn consume_handle(handle: $crate::Handle) -> ::std::sync::Arc<Self> {
::std::sync::Arc::<Self>::clone(
&std::sync::Arc::<::std::sync::Arc::<Self>>::from_raw(handle.as_pointer::<::std::sync::Arc<Self>>())
)
}
}
};
(impl $(<$($generic:ident),*>)? $(::uniffi::)? TypeId<$ut:path> for $ty:ty $(where $($where:tt)*)?) => {
impl $(<$($generic),*>)* $crate::TypeId<$ut> for $ty $(where $($where)*)*
{
const TYPE_ID_META: $crate::MetadataBuffer = <Self as $crate::FfiConverter<$ut>>::TYPE_ID_META;
}
};
}
unsafe impl<T: Send + Sync, UT> HandleAlloc<UT> for T {
fn new_handle(value: Arc<Self>) -> Handle {
Handle::from_arc(value)
}
unsafe fn clone_handle(handle: Handle) -> Handle {
handle.clone_arc_handle::<T>()
}
unsafe fn consume_handle(handle: Handle) -> Arc<Self> {
handle.into_arc()
}
}