#![allow(clippy::missing_safety_doc)]
use alloc::boxed::Box;
use core::mem::ManuallyDrop;
#[cfg(doc)]
use crate::interfaces::IUnknown;
pub unsafe trait Class {
type Factory;
unsafe fn dec_ref_count(&self) -> u32;
unsafe fn add_ref(&self) -> u32;
}
#[repr(transparent)]
pub struct ClassAllocation<T: Class> {
inner: core::mem::ManuallyDrop<core::pin::Pin<Box<T>>>,
}
impl<T: Class> ClassAllocation<T> {
pub fn new(inner: core::pin::Pin<Box<T>>) -> Self {
Self {
inner: core::mem::ManuallyDrop::new(inner),
}
}
#[inline(always)]
pub unsafe fn from_raw(raw: *mut T) -> Self {
let inner = core::mem::ManuallyDrop::new(Box::from_raw(raw).into());
Self { inner }
}
#[doc(hidden)]
#[inline(never)]
pub unsafe fn drop_inner(&mut self) {
ManuallyDrop::drop(&mut self.inner);
}
}
unsafe impl<T: Class> Send for ClassAllocation<T> {}
unsafe impl<T: Class> Sync for ClassAllocation<T> {}
impl<T: Class> core::ops::Deref for ClassAllocation<T> {
type Target = core::pin::Pin<Box<T>>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T: Class> Drop for ClassAllocation<T> {
fn drop(&mut self) {
unsafe {
if self.inner.dec_ref_count() == 0 {
core::mem::ManuallyDrop::drop(&mut self.inner);
}
}
}
}
impl<T: Class + core::fmt::Debug> core::fmt::Debug for ClassAllocation<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let inner = self.inner.as_ref().get_ref();
write!(f, "{:?}", inner)
}
}
impl<T: Class> Clone for ClassAllocation<T> {
fn clone(&self) -> Self {
unsafe {
self.inner.add_ref();
core::mem::transmute_copy(self)
}
}
}