use std::ffi::c_void;
use jl_sys::{
jl_unbox_float32, jl_unbox_float64, jl_unbox_int8, jl_unbox_int16, jl_unbox_int32,
jl_unbox_int64, jl_unbox_uint8, jl_unbox_uint16, jl_unbox_uint32, jl_unbox_uint64,
jl_unbox_voidpointer,
};
use jlrs_sys::{jlrs_unbox_long, jlrs_unbox_ulong};
use super::into_julia::IntoJulia;
use crate::data::managed::value::Value;
#[diagnostic::on_unimplemented(
message = "the trait bound `{Self}: Unbox` is not satisfied",
label = "the trait `Unbox` is not implemented for `{Self}`",
note = "Custom types that implement `Unbox` should be generated with JlrsCore.reflect",
note = "Do not implement `ForeignType` or `OpaqueType` unless this type is exported to Julia with `julia_module!`"
)]
pub unsafe trait Unbox {
type Output: Sized + Clone;
#[inline]
unsafe fn unbox(value: Value) -> Self::Output {
let result = unsafe { value.data_ptr().cast::<Self::Output>().as_ref() };
result.clone()
}
}
macro_rules! impl_unboxer {
($type:ty, $unboxer:expr_2021) => {
unsafe impl Unbox for $type {
type Output = Self;
#[inline]
unsafe fn unbox(value: Value) -> $type {
unsafe {
$unboxer(
<Value as crate::data::managed::private::ManagedPriv>::unwrap(
value,
$crate::private::Private,
),
) as _
}
}
}
};
}
impl_unboxer!(u8, jl_unbox_uint8);
impl_unboxer!(u16, jl_unbox_uint16);
impl_unboxer!(u32, jl_unbox_uint32);
impl_unboxer!(u64, jl_unbox_uint64);
impl_unboxer!(i8, jl_unbox_int8);
impl_unboxer!(i16, jl_unbox_int16);
impl_unboxer!(i32, jl_unbox_int32);
impl_unboxer!(i64, jl_unbox_int64);
impl_unboxer!(f32, jl_unbox_float32);
impl_unboxer!(f64, jl_unbox_float64);
impl_unboxer!(*mut c_void, jl_unbox_voidpointer);
impl_unboxer!(usize, jlrs_unbox_ulong);
impl_unboxer!(isize, jlrs_unbox_long);
unsafe impl<T: IntoJulia> Unbox for *mut T {
type Output = Self;
}