use core::fmt;
use core::marker::PhantomData;
use core::mem::ManuallyDrop;
use core::ops::Deref;
use core::panic::{RefUnwindSafe, UnwindSafe};
use core::ptr::NonNull;
use crate::generated::{dispatch_release, dispatch_retain};
use crate::DispatchObject;
mod forwarding_impls;
use DispatchRetained as Retained;
#[cfg_attr(
not(feature = "objc2"),
doc = "[`objc2::rc::Retained`]: #objc2-not-available"
)]
#[cfg_attr(not(feature = "std"), doc = "[`std::sync::Arc`]: #std-not-enabled")]
#[repr(transparent)]
#[doc(alias = "Retained")]
#[doc(alias = "objc2::rc::Retained")]
pub struct DispatchRetained<T: ?Sized> {
ptr: NonNull<T>,
item: PhantomData<T>,
notunwindsafe: PhantomData<&'static mut ()>,
}
impl<T: ?Sized> Drop for DispatchRetained<T> {
#[doc(alias = "dispatch_release")]
#[doc(alias = "release")]
#[inline]
fn drop(&mut self) {
unsafe { dispatch_release(self.ptr.cast()) };
}
}
impl<T: ?Sized + DispatchObject> DispatchRetained<T> {
#[inline]
pub unsafe fn from_raw(ptr: NonNull<T>) -> Self {
Self {
ptr,
item: PhantomData,
notunwindsafe: PhantomData,
}
}
#[doc(alias = "dispatch_retain")]
#[inline]
pub unsafe fn retain(ptr: NonNull<T>) -> Self {
unsafe { dispatch_retain(ptr.cast()) };
unsafe { Self::from_raw(ptr) }
}
#[inline]
pub fn into_raw(this: Self) -> NonNull<T> {
ManuallyDrop::new(this).ptr
}
#[inline]
pub fn as_ptr(this: &Self) -> NonNull<T> {
this.ptr
}
#[inline]
pub unsafe fn cast_unchecked<U: DispatchObject>(this: Self) -> DispatchRetained<U> {
unsafe { DispatchRetained::from_raw(Self::into_raw(this).cast()) }
}
}
impl<T: ?Sized + DispatchObject> Clone for DispatchRetained<T> {
#[doc(alias = "dispatch_retain")]
#[doc(alias = "retain")]
#[inline]
fn clone(&self) -> Self {
self.retain()
}
}
impl<T: ?Sized> Deref for DispatchRetained<T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
unsafe { self.ptr.as_ref() }
}
}
impl<T: ?Sized> fmt::Pointer for DispatchRetained<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Pointer::fmt(&self.ptr.as_ptr(), f)
}
}
impl<T: ?Sized + AsRef<U>, U: DispatchObject> From<&T> for DispatchRetained<U> {
#[inline]
fn from(obj: &T) -> Self {
obj.as_ref().retain()
}
}
#[cfg(feature = "objc2")]
impl<T: ?Sized + DispatchObject + objc2::Message> From<objc2::rc::Retained<T>>
for DispatchRetained<T>
{
#[inline]
fn from(obj: objc2::rc::Retained<T>) -> Self {
let ptr = objc2::rc::Retained::into_raw(obj);
let ptr = NonNull::new(ptr).unwrap();
unsafe { Self::from_raw(ptr) }
}
}
#[cfg(feature = "objc2")]
impl<T: ?Sized + DispatchObject + objc2::Message> From<DispatchRetained<T>>
for objc2::rc::Retained<T>
{
#[inline]
fn from(obj: DispatchRetained<T>) -> Self {
let ptr = DispatchRetained::into_raw(obj);
unsafe { Self::from_raw(ptr.as_ptr()) }.unwrap()
}
}
unsafe impl<T: ?Sized + Sync + Send> Send for DispatchRetained<T> {}
unsafe impl<T: ?Sized + Sync + Send> Sync for DispatchRetained<T> {}
impl<T: ?Sized> Unpin for DispatchRetained<T> {}
impl<T: ?Sized + RefUnwindSafe> RefUnwindSafe for DispatchRetained<T> {}
impl<T: ?Sized + RefUnwindSafe> UnwindSafe for DispatchRetained<T> {}