use crate::{
call::Call,
data::{managed::value::ValueRet, types::construct_type::ConstructType},
prelude::{JlrsResult, LocalScope as _, Nothing},
weak_handle_unchecked,
};
#[cfg(feature = "ccall")]
use crate::{
data::managed::module::JlrsCore,
prelude::{JuliaString, Managed},
};
pub unsafe trait CCallArg {
type CCallArgType: ConstructType;
type FunctionArgType: ConstructType;
}
pub unsafe trait CCallReturn {
type FunctionReturnType: ConstructType;
type CCallReturnType: ConstructType;
type ReturnAs: CCallReturn;
unsafe fn return_or_throw(self) -> Self::ReturnAs;
}
macro_rules! impl_ccall_arg {
($type:ty) => {
unsafe impl CCallArg for $type {
type CCallArgType = Self;
type FunctionArgType = Self;
}
unsafe impl CCallReturn for $type {
type FunctionReturnType = Self;
type CCallReturnType = Self;
type ReturnAs = Self;
#[inline]
unsafe fn return_or_throw(self) -> Self::ReturnAs {
return self;
}
}
};
}
impl_ccall_arg!(u8);
impl_ccall_arg!(u16);
impl_ccall_arg!(u32);
impl_ccall_arg!(u64);
impl_ccall_arg!(usize);
impl_ccall_arg!(i8);
impl_ccall_arg!(i16);
impl_ccall_arg!(i32);
impl_ccall_arg!(i64);
impl_ccall_arg!(isize);
impl_ccall_arg!(f32);
impl_ccall_arg!(f64);
unsafe impl<T: CCallReturn> CCallReturn for Result<T, ValueRet> {
type FunctionReturnType = T::FunctionReturnType;
type CCallReturnType = T::CCallReturnType;
type ReturnAs = T;
#[inline]
unsafe fn return_or_throw(self) -> Self::ReturnAs {
unsafe {
#[cfg(feature = "ccall")]
{
match self {
Ok(t) => t,
Err(e) => crate::runtime::handle::ccall::throw_exception(e),
}
}
#[cfg(not(feature = "ccall"))]
unimplemented!(
"CCallReturn::return_or_throw can only be called if the `ccall` feature is enabled"
)
}
}
}
unsafe impl CCallReturn for () {
type FunctionReturnType = Nothing;
type CCallReturnType = Nothing;
type ReturnAs = ();
#[inline]
unsafe fn return_or_throw(self) -> Self::ReturnAs {
()
}
}
unsafe impl<T: CCallReturn> CCallReturn for JlrsResult<T> {
type FunctionReturnType = T::FunctionReturnType;
type CCallReturnType = T::CCallReturnType;
type ReturnAs = T;
#[inline]
unsafe fn return_or_throw(self) -> Self::ReturnAs {
unsafe {
#[cfg(feature = "ccall")]
{
match self {
Ok(t) => t,
Err(e) => {
let handle = weak_handle_unchecked!();
let e = handle.local_scope::<_, 1>(|mut frame| {
let msg = JuliaString::new(&mut frame, format!("{}", e)).as_value();
let err = JlrsCore::jlrs_error(&frame)
.as_value()
.call(&frame, [msg])
.unwrap();
err.leak()
});
crate::runtime::handle::ccall::throw_exception(e)
}
}
}
#[cfg(not(feature = "ccall"))]
unimplemented!(
"CCallReturn::return_or_throw can only be called if the `ccall` feature is enabled"
)
}
}
}