use crate::idl::iunknown::IUnknownUnsafeExt;
use crate::IUnknown;
use std::cell::Cell;
use std::marker::PhantomData;
use std::ptr::NonNull;
#[cfg(doc)]
use crate::idl::iunknown::IUnknownVtbl;
mod private {
pub trait MtKind {}
pub trait SafetyKind {}
}
pub trait MtKind: private::MtKind {}
impl<T> MtKind for T where T: private::MtKind {}
pub struct Apartment {
_v: *const (),
}
impl private::MtKind for Apartment {}
pub struct Multi {
_v: (),
}
impl private::MtKind for Multi {}
pub trait SafetyKind: private::SafetyKind {}
impl<T> SafetyKind for T where T: private::SafetyKind {}
pub struct Safe {
_v: (),
}
impl private::SafetyKind for Safe {}
pub struct Unsafe {
_v: (),
}
impl private::SafetyKind for Unsafe {}
pub trait ComInterface {
type Vtbl;
type Mt: MtKind;
}
pub unsafe trait ComHierarchy<T>: ComInterface {}
pub unsafe trait ComDeref {
type Target: ComInterface;
type Mt: MtKind;
type Safety: SafetyKind;
fn com_deref(&self) -> ComRef<Self::Target, Self::Mt, Self::Safety>;
}
unsafe impl<T: ComInterface> ComDeref for NonNull<T> {
type Target = T;
type Mt = Apartment;
type Safety = Unsafe;
fn com_deref(&self) -> ComRef<Self::Target, Self::Mt, Self::Safety> {
ComRef::new(*self)
}
}
#[repr(transparent)]
pub struct ComRef<T, M: MtKind = Apartment, S: SafetyKind = Unsafe> {
ptr: NonNull<T>,
_marker: PhantomData<(Cell<T>, M, S)>,
}
impl<T: ComInterface> ComRef<T, Apartment, Unsafe> {
#[inline]
pub const fn new(ptr: NonNull<T>) -> Self {
unsafe { ComRef::new_with_characteristics(ptr) }
}
#[inline]
pub const fn new_with_default_threading(ptr: NonNull<T>) -> ComRef<T, T::Mt, Unsafe> {
unsafe { ComRef::new_with_characteristics(ptr) }
}
}
impl<T: ComInterface, M: MtKind, S: SafetyKind> ComRef<T, M, S> {
#[inline]
const unsafe fn new_with_characteristics(ptr: NonNull<T>) -> Self {
ComRef {
ptr,
_marker: PhantomData,
}
}
#[inline]
pub const fn into_apartment_threaded(self) -> ComRef<T, Apartment, S> {
unsafe { ComRef::new_with_characteristics(self.ptr) }
}
#[inline]
pub const unsafe fn into_multi_threaded(self) -> ComRef<T, Multi, S> {
unsafe { ComRef::new_with_characteristics(self.ptr) }
}
#[inline]
pub const fn into_unsafe(self) -> ComRef<T, M, Unsafe> {
unsafe { ComRef::new_with_characteristics(self.ptr) }
}
#[inline]
pub const unsafe fn into_safe(self) -> ComRef<T, M, Safe> {
ComRef::new_with_characteristics(self.ptr)
}
#[inline]
pub const fn upcast<U>(&self) -> ComRef<U, M, S>
where
T: ComHierarchy<U>,
U: ComInterface,
{
unsafe { ComRef::new_with_characteristics(self.ptr.cast::<U>()) }
}
#[inline]
pub const fn into_raw(self) -> NonNull<T> {
self.ptr
}
#[inline]
pub const fn as_ptr(self) -> *mut T {
self.ptr.as_ptr()
}
}
unsafe impl<T: ComInterface, M: MtKind, S: SafetyKind> ComDeref for ComRef<T, M, S> {
type Target = T;
type Mt = M;
type Safety = S;
#[inline]
fn com_deref(&self) -> Self {
*self
}
}
unsafe impl<T, M: MtKind, S: SafetyKind> Send for ComRef<T, M, S> where M: Send {}
unsafe impl<T, M: MtKind, S: SafetyKind> Sync for ComRef<T, M, S> where M: Sync {}
impl<T, M: MtKind, S: SafetyKind> Clone for ComRef<T, M, S> {
#[inline]
fn clone(&self) -> Self {
Self {
ptr: self.ptr,
_marker: self._marker,
}
}
}
impl<T, M: MtKind, S: SafetyKind> Copy for ComRef<T, M, S> {}
#[repr(transparent)]
pub struct ComPtr<T: ComHierarchy<IUnknown>, M: MtKind = Apartment, S: SafetyKind = Unsafe> {
ptr: ComRef<T, M, S>,
}
impl<T: ComHierarchy<IUnknown>, M: MtKind, S: SafetyKind> ComPtr<T, M, S> {
pub unsafe fn new(ptr: ComRef<T, M, S>) -> Self {
Self { ptr }
}
pub unsafe fn adopt(ptr: ComRef<T, M, S>) -> Self {
ptr.into_unsafe().AddRef();
Self { ptr }
}
pub fn into_inner(self) -> ComRef<T, M, S> {
let p = self.ptr;
std::mem::forget(self);
p
}
pub fn as_ref(&self) -> ComRef<T, M, S> {
self.ptr
}
pub fn as_unsafe(&self) -> ComRef<T, M, Unsafe> {
self.ptr.into_unsafe()
}
#[inline]
pub fn upcast<U>(&self) -> ComRef<U, M, S>
where
T: ComHierarchy<U>,
U: ComInterface,
{
self.ptr.upcast()
}
}
unsafe impl<T: ComHierarchy<IUnknown>, M: MtKind, S: SafetyKind> ComDeref for ComPtr<T, M, S> {
type Target = T;
type Mt = M;
type Safety = S;
#[inline]
fn com_deref(&self) -> ComRef<T, M, S> {
self.ptr
}
}
impl<T: ComHierarchy<IUnknown>, M: MtKind, S: SafetyKind> Clone for ComPtr<T, M, S> {
fn clone(&self) -> Self {
unsafe {
self.as_unsafe().AddRef();
}
Self { ptr: self.ptr }
}
}
impl<T: ComHierarchy<IUnknown>, M: MtKind, S: SafetyKind> Drop for ComPtr<T, M, S> {
fn drop(&mut self) {
unsafe {
self.as_unsafe().Release();
}
}
}