use super::*;
use crate::attributes::ComInterface;
use crate::type_system::{ExternInput, ExternOutput, ExternType, TypeSystem};
pub struct ComRc<T: ComInterface + ?Sized>
{
itf: ComItf<T>,
}
impl<T: ComInterface + ?Sized> std::fmt::Debug for ComRc<T>
{
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result
{
(**self).fmt(f)
}
}
impl<T: ComInterface + ?Sized> Clone for ComRc<T>
{
fn clone(&self) -> Self
{
ComRc::from(&self.itf)
}
}
impl<T: ComInterface + ?Sized> From<&ComItf<T>> for ComRc<T>
{
fn from(source: &ComItf<T>) -> Self
{
ComItf::as_rc(source)
}
}
impl<TS: TypeSystem, T: ComInterface + ?Sized> From<crate::raw::InterfacePtr<TS, T>> for ComRc<T>
{
fn from(source: crate::raw::InterfacePtr<TS, T>) -> Self
{
unsafe { ComItf::as_rc(&ComItf::wrap(source)) }
}
}
impl<T: ComInterface + ?Sized> ComRc<T>
{
pub unsafe fn attach(itf: ComItf<T>) -> ComRc<T>
{
ComRc { itf }
}
pub fn detach(rc: ComRc<T>) -> ComItf<T>
{
let itf = ComItf { ..rc.itf };
std::mem::forget(rc);
itf
}
pub unsafe fn wrap<TS: TypeSystem>(ptr: raw::InterfacePtr<TS, T>) -> ComRc<T>
{
ComRc::attach(ComItf::wrap(ptr))
}
}
#[cfg(windows)]
impl<T: ComInterface + ?Sized> ComRc<T>
{
pub fn create(clsid: GUID) -> crate::ComResult<ComRc<T>>
{
use crate::type_system::{AutomationTypeSystem, TypeSystemName};
let iid = match T::iid(TypeSystemName::Automation) {
Some(iid) => iid,
None => return Err(ComError::E_NOINTERFACE),
};
unsafe {
let mut out = ::std::ptr::null_mut();
match CoCreateInstance(
clsid,
std::ptr::null_mut(),
1, iid,
&mut out,
) {
crate::raw::S_OK => {
let ptr = raw::InterfacePtr::new(out).ok_or(ComError::E_POINTER)?;
let comitf = ComItf::wrap::<AutomationTypeSystem>(ptr);
Ok(ComRc::attach(comitf))
}
e => Err(e.into()),
}
}
}
}
impl<T: ComInterface + ?Sized> ::std::ops::Deref for ComRc<T>
{
type Target = ComItf<T>;
fn deref(&self) -> &Self::Target
{
&self.itf
}
}
impl<T: ComInterface + ?Sized> Drop for ComRc<T>
{
fn drop(&mut self)
{
self.itf.as_raw_iunknown().release();
}
}
impl<T: ComInterface + ?Sized> AsRef<ComItf<T>> for ComRc<T>
{
fn as_ref(&self) -> &ComItf<T>
{
&self.itf
}
}
impl<T: ComInterface + ?Sized> std::borrow::Borrow<ComItf<T>> for ComRc<T>
{
fn borrow(&self) -> &ComItf<T>
{
self.as_ref()
}
}
impl<TS: TypeSystem, I: ComInterface + ?Sized> ExternType<TS> for crate::ComRc<I>
where
I: ForeignType,
{
type ForeignType = Option<crate::raw::InterfacePtr<TS, I>>;
}
impl<TS: TypeSystem, I: ComInterface + ?Sized> ExternType<TS> for Option<crate::ComRc<I>>
where
I: ForeignType,
{
type ForeignType = Option<crate::raw::InterfacePtr<TS, I>>;
}
unsafe impl<TS: TypeSystem, I: ComInterface + ?Sized> ExternInput<TS> for crate::ComRc<I>
where
I: ForeignType,
{
type Lease = Self;
unsafe fn into_foreign_parameter(self) -> ComResult<(Self::ForeignType, Self::Lease)>
{
match ComItf::ptr::<TS>(&self) {
Some(ptr) => Ok((Some(ptr), self)),
None => Err(ComError::E_POINTER),
}
}
type Owned = Self;
unsafe fn from_foreign_parameter(source: Self::ForeignType) -> ComResult<Self>
{
match source {
Some(ptr) => Ok(ComRc::from(ptr)),
None => Err(ComError::E_POINTER),
}
}
}
unsafe impl<TS: TypeSystem, I: ComInterface + ?Sized> ExternOutput<TS> for crate::ComRc<I>
where
I: ForeignType,
{
fn into_foreign_output(self) -> ComResult<Self::ForeignType>
{
Ok(ComItf::ptr(&ComRc::detach(self)))
}
unsafe fn from_foreign_output(source: Self::ForeignType) -> ComResult<Self>
{
match source {
Some(ptr) => Ok(ComRc::wrap(ptr)),
None => Err(ComError::E_POINTER),
}
}
}
unsafe impl<TS: TypeSystem, I: ComInterface + ?Sized> ExternInput<TS> for Option<crate::ComRc<I>>
where
I: ForeignType,
{
type Lease = Self;
unsafe fn into_foreign_parameter(self) -> ComResult<(Self::ForeignType, Self::Lease)>
{
match &self {
None => Ok((None, self)),
Some(rc) => match ComItf::ptr::<TS>(rc) {
None => Err(ComError::E_POINTER),
Some(ptr) => Ok((Some(ptr), self)),
},
}
}
type Owned = Self;
unsafe fn from_foreign_parameter(source: Self::ForeignType) -> ComResult<Self>
{
Ok(source.map(ComRc::from))
}
}
unsafe impl<TS: TypeSystem, I: ComInterface + ?Sized> ExternOutput<TS> for Option<crate::ComRc<I>>
where
I: ForeignType,
{
fn into_foreign_output(self) -> ComResult<Self::ForeignType>
{
match self {
None => Ok(None),
Some(rc) => match ComItf::ptr::<TS>(&ComRc::detach(rc)) {
None => Err(ComError::E_POINTER),
Some(ptr) => Ok(Some(ptr)),
},
}
}
unsafe fn from_foreign_output(source: Self::ForeignType) -> ComResult<Self>
{
Ok(source.map(|ptr| ComRc::wrap(ptr)))
}
}