use super::*; #[doc(hidden)] pub trait TypeKind { type TypeKind; } #[doc(hidden)] pub struct ReferenceType; #[doc(hidden)] pub struct ValueType; #[doc(hidden)] pub struct CopyType; #[doc(hidden)] pub trait Type::TypeKind>: TypeKind + Sized + Clone { type Abi; type Default; fn abi(&self) -> Self::Abi { unsafe { std::mem::transmute_copy(self) } } /// # Safety unsafe fn from_abi(abi: Self::Abi) -> Result; fn from_default(default: &Self::Default) -> Result; } impl Type for T where T: TypeKind + Clone, { type Abi = *mut std::ffi::c_void; type Default = Option; unsafe fn from_abi(abi: Self::Abi) -> Result { if !abi.is_null() { Ok(std::mem::transmute_copy(&abi)) } else { Err(Error::OK) } } fn from_default(default: &Self::Default) -> Result { default.as_ref().cloned().ok_or(Error::OK) } } impl Type for T where T: TypeKind + Clone, { type Abi = std::mem::MaybeUninit; type Default = Self; unsafe fn from_abi(abi: std::mem::MaybeUninit) -> Result { Ok(abi.assume_init()) } fn from_default(default: &Self::Default) -> Result { Ok(default.clone()) } } impl Type for T where T: TypeKind + Clone, { type Abi = Self; type Default = Self; unsafe fn from_abi(abi: Self) -> Result { Ok(abi) } fn from_default(default: &Self) -> Result { Ok(default.clone()) } } impl TypeKind for T { type TypeKind = ReferenceType; } impl TypeKind for *mut T { type TypeKind = CopyType; } macro_rules! primitives { ($($t:ty),+) => { $( impl TypeKind for $t { type TypeKind = CopyType; } )* }; } primitives!(bool, i8, u8, i16, u16, i32, u32, i64, u64, f32, f64, usize, isize); #[doc(hidden)] pub type AbiType = >::Abi; /// # Safety #[doc(hidden)] pub unsafe fn from_abi>(abi: T::Abi) -> Result { T::from_abi(abi) }