use super::*; #[doc(hidden)] pub enum Param> { Owned(T), Borrowed(T::Abi), } impl> Param { pub fn abi(&self) -> T::Abi { unsafe { match self { Self::Owned(item) => std::mem::transmute_copy(item), Self::Borrowed(borrowed) => std::mem::transmute_copy(borrowed), } } } } #[doc(hidden)] pub trait TryIntoParam> { fn try_into_param(self) -> Result>; } impl TryIntoParam for Option<&T> where T: ComInterface, { fn try_into_param(self) -> Result> { match self { Some(from) => Ok(Param::Borrowed(from.abi())), None => Ok(Param::Borrowed(unsafe { std::mem::zeroed() })), } } } impl TryIntoParam for &U where T: ComInterface, U: ComInterface, U: CanTryInto, { fn try_into_param(self) -> Result> { if U::CAN_INTO { Ok(Param::Borrowed(self.abi())) } else { Ok(Param::Owned(self.cast()?)) } } } #[doc(hidden)] pub trait CanTryInto: ComInterface where T: ComInterface, { const CAN_INTO: bool = false; } impl CanTryInto for U where T: ComInterface, U: ComInterface, U: CanInto, { const CAN_INTO: bool = true; } #[doc(hidden)] pub trait CanInto: Sized where T: Clone, { fn can_into(&self) -> &T { unsafe { std::mem::transmute(self) } } fn can_clone_into(&self) -> T { self.can_into().clone() } } impl CanInto for T where T: Clone {} #[doc(hidden)] pub trait IntoParam::TypeKind>: Sized where T: Type, { fn into_param(self) -> Param; } impl IntoParam for Option<&T> where T: Type, { fn into_param(self) -> Param { match self { Some(item) => Param::Borrowed(item.abi()), None => Param::Borrowed(unsafe { std::mem::zeroed() }), } } } impl IntoParam for &U where T: TypeKind + Clone, U: TypeKind + Clone, U: CanInto, { fn into_param(self) -> Param { Param::Borrowed(self.abi()) } } impl IntoParam for &T where T: TypeKind + Clone, { fn into_param(self) -> Param { Param::Borrowed(self.abi()) } } impl IntoParam for U where T: TypeKind + Clone, U: TypeKind + Clone, U: CanInto, { fn into_param(self) -> Param { unsafe { Param::Owned(std::mem::transmute_copy(&self)) } } }