use super::{Class, SEL};
use std::{cell::UnsafeCell, fmt, ops::Deref, ptr::NonNull};
#[repr(C)]
pub struct Object {
_data: UnsafeCell<[u8; 0]>,
}
unsafe impl Sync for Object {}
impl fmt::Debug for Object {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.as_ptr().fmt(f)
}
}
impl Object {
#[inline]
pub fn as_ptr(&self) -> *mut Object {
self._data.get().cast()
}
#[inline]
pub fn as_non_null_ptr(&self) -> NonNull<Object> {
NonNull::from(self).cast()
}
#[inline]
pub fn get_class(&self) -> &'static Class {
extern "C" {
fn objc_msgSend(obj: &Object, sel: SEL) -> &'static Class;
}
let sel = selector!(class);
unsafe { objc_msgSend(self, sel) }
}
}
#[repr(transparent)]
#[allow(non_camel_case_types)]
pub struct id(NonNull<Object>);
unsafe impl Send for id {}
unsafe impl Sync for id {}
impl Deref for id {
type Target = Object;
#[inline]
fn deref(&self) -> &Self::Target {
unsafe { self.0.as_ref() }
}
}
impl Drop for id {
#[inline]
fn drop(&mut self) {
extern "C" {
fn objc_release(obj: &Object);
}
unsafe { objc_release(self) };
}
}
impl Clone for id {
#[inline]
fn clone(&self) -> Self {
extern "C" {
fn objc_retain(obj: &Object) -> NonNull<Object>;
}
Self(unsafe { objc_retain(self) })
}
}
impl fmt::Debug for id {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.as_ptr().fmt(f)
}
}
impl fmt::Pointer for id {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.as_ptr().fmt(f)
}
}
impl id {
#[inline]
pub const unsafe fn from_ptr(ptr: *mut Object) -> Self {
Self(NonNull::new_unchecked(ptr.cast()))
}
#[inline]
pub const unsafe fn from_non_null_ptr(ptr: NonNull<Object>) -> Self {
Self(ptr.cast())
}
#[inline]
pub fn as_ptr(&self) -> *mut Object {
self.0.as_ptr()
}
#[inline]
pub fn as_non_null_ptr(&self) -> NonNull<Object> {
self.0
}
}