use core::cell::UnsafeCell;
use core::cmp::Ordering;
use core::convert::AsRef;
use core::fmt;
use core::hash;
use core::marker::{PhantomData, PhantomPinned};
use crate::{
CFComparisonResult, CFEqual, CFGetRetainCount, CFGetTypeID, CFHash, CFRange, ConcreteType, Type,
};
pub type CFTypeID = usize;
pub type CFOptionFlags = usize;
pub type CFHashCode = usize;
pub type CFIndex = isize;
#[repr(C)]
pub struct CFType {
inner: [u8; 0],
_p: UnsafeCell<PhantomData<(*const UnsafeCell<()>, PhantomPinned)>>,
}
impl CFType {
#[doc(alias = "CFGetTypeID")]
pub fn downcast_ref<T: ConcreteType>(&self) -> Option<&T> {
if CFGetTypeID(Some(self)) == T::type_id() {
let ptr: *const Self = self;
let ptr: *const T = ptr.cast();
let this: &T = unsafe { &*ptr };
Some(this)
} else {
None
}
}
#[doc(alias = "CFGetRetainCount")]
pub fn retain_count(&self) -> usize {
CFGetRetainCount(Some(self)) as _
}
}
impl AsRef<Self> for CFType {
#[inline]
fn as_ref(&self) -> &Self {
self
}
}
unsafe impl Type for CFType {}
impl fmt::Debug for CFType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
#[cfg(feature = "CFString")]
{
let desc = crate::CFCopyDescription(Some(self)).expect("must have description");
write!(f, "{desc}")
}
#[cfg(not(feature = "CFString"))]
{
f.debug_struct("<CoreFoundation type (enable CFString feature for more info)>")
.finish_non_exhaustive()
}
}
}
impl PartialEq for CFType {
#[inline]
#[doc(alias = "CFEqual")]
fn eq(&self, other: &Self) -> bool {
CFEqual(Some(self), Some(other))
}
}
impl Eq for CFType {}
impl hash::Hash for CFType {
#[doc(alias = "CFHash")]
fn hash<H: hash::Hasher>(&self, state: &mut H) {
CFHash(Some(self)).hash(state);
}
}
#[cfg(feature = "objc2")]
unsafe impl objc2::encode::RefEncode for CFType {
const ENCODING_REF: objc2::encode::Encoding =
objc2::encode::Encoding::Pointer(&objc2::encode::Encoding::Void);
}
#[cfg(feature = "objc2")]
unsafe impl objc2::Message for CFType {}
#[cfg(feature = "objc2")]
impl AsRef<objc2::runtime::AnyObject> for CFType {
fn as_ref(&self) -> &objc2::runtime::AnyObject {
unsafe { core::mem::transmute(self) }
}
}
#[cfg(feature = "objc2")]
impl core::borrow::Borrow<objc2::runtime::AnyObject> for CFType {
fn borrow(&self) -> &objc2::runtime::AnyObject {
<Self as AsRef<objc2::runtime::AnyObject>>::as_ref(self)
}
}
impl Default for CFComparisonResult {
#[inline]
fn default() -> Self {
Self::CompareEqualTo
}
}
impl From<Ordering> for CFComparisonResult {
#[inline]
fn from(order: Ordering) -> Self {
match order {
Ordering::Less => Self::CompareLessThan,
Ordering::Equal => Self::CompareEqualTo,
Ordering::Greater => Self::CompareGreaterThan,
}
}
}
impl From<CFComparisonResult> for Ordering {
#[inline]
fn from(comparison_result: CFComparisonResult) -> Self {
match comparison_result.0 {
..=-1 => Self::Less, 0 => Self::Equal, 1.. => Self::Greater, #[allow(unreachable_patterns)] _ => Self::Equal,
}
}
}
impl CFRange {
#[doc(alias = "CFRangeMake")]
pub fn new(location: CFIndex, length: CFIndex) -> Self {
Self { location, length }
}
}