use core::mem::ManuallyDrop;
use crate::encode::EncodeReturn;
use crate::rc::{Allocated, PartialInit, Retained};
use crate::runtime::{AnyClass, AnyObject, MessageReceiver, Sel};
use crate::{sel, DefinedClass, Message};
use super::defined_ivars::set_finalized;
use super::{
AllocFamily, ConvertReturn, CopyFamily, InitFamily, MutableCopyFamily, NewFamily, NoneFamily,
};
#[derive(Debug, Copy, Clone)]
pub struct KindSendMessageSuper;
#[derive(Debug, Copy, Clone)]
pub struct KindSendMessage;
#[derive(Debug, Copy, Clone)]
pub struct KindDefined;
trait SendMessage {}
impl SendMessage for KindSendMessage {}
impl SendMessage for KindSendMessageSuper {}
trait NotSuper {}
impl NotSuper for KindSendMessage {}
impl NotSuper for KindDefined {}
trait IsSuper {}
impl IsSuper for KindSendMessageSuper {}
pub trait RetainSemantics<Receiver, Return, Kind>: Sized {
type ReceiverInner: MessageReceiver;
fn prepare_message_send(receiver: Receiver) -> Self::ReceiverInner;
unsafe fn prepare_defined_method(receiver: Self::ReceiverInner) -> Receiver;
type ReturnInner: EncodeReturn;
#[track_caller]
unsafe fn convert_message_return(
ret: Self::ReturnInner,
receiver_ptr: *mut AnyObject,
sel: Sel,
) -> Return;
fn convert_defined_return(ret: Return) -> Self::ReturnInner;
}
impl<Receiver, Return, Kind, MethodFamily> RetainSemantics<Receiver, Return, Kind> for MethodFamily
where
Receiver: MessageReceiver,
Return: ConvertReturn<MethodFamily>,
{
type ReceiverInner = Receiver;
#[inline]
fn prepare_message_send(receiver: Receiver) -> Receiver {
receiver
}
#[inline]
unsafe fn prepare_defined_method(receiver: Receiver) -> Receiver {
receiver
}
type ReturnInner = Return::Inner;
#[inline]
unsafe fn convert_message_return(
ret: Return::Inner,
receiver_ptr: *mut AnyObject,
sel: Sel,
) -> Return {
unsafe { Return::convert_message_return(ret, receiver_ptr, sel) }
}
#[inline]
fn convert_defined_return(ret: Return) -> Return::Inner {
Return::convert_defined_return(ret)
}
}
impl<'a, T, Return, Kind, MethodFamily> RetainSemantics<&'a Retained<T>, Return, Kind>
for MethodFamily
where
T: Message,
Kind: SendMessage,
MethodFamily: RetainSemantics<*const T, Return, Kind>,
{
type ReceiverInner = *const T;
#[inline]
fn prepare_message_send(receiver: &'a Retained<T>) -> *const T {
&**receiver
}
#[inline]
unsafe fn prepare_defined_method(_receiver: *const T) -> &'a Retained<T> {
unreachable!()
}
type ReturnInner = <Self as RetainSemantics<*const T, Return, Kind>>::ReturnInner;
#[inline]
unsafe fn convert_message_return(
ret: Self::ReturnInner,
receiver_ptr: *mut AnyObject,
sel: Sel,
) -> Return {
unsafe {
<Self as RetainSemantics<*const T, Return, Kind>>::convert_message_return(
ret,
receiver_ptr,
sel,
)
}
}
#[inline]
fn convert_defined_return(ret: Return) -> Self::ReturnInner {
<Self as RetainSemantics<*const T, Return, Kind>>::convert_defined_return(ret)
}
}
impl<T, Return, Kind, MethodFamily> RetainSemantics<ManuallyDrop<Retained<T>>, Return, Kind>
for MethodFamily
where
T: Message,
Kind: SendMessage,
MethodFamily: RetainSemantics<*mut T, Return, Kind>,
{
type ReceiverInner = *mut T;
#[inline]
fn prepare_message_send(receiver: ManuallyDrop<Retained<T>>) -> *mut T {
Retained::into_raw(ManuallyDrop::into_inner(receiver))
}
#[inline]
unsafe fn prepare_defined_method(_receiver: *mut T) -> ManuallyDrop<Retained<T>> {
unreachable!()
}
type ReturnInner = <Self as RetainSemantics<*mut T, Return, Kind>>::ReturnInner;
#[inline]
unsafe fn convert_message_return(
ret: Self::ReturnInner,
receiver_ptr: *mut AnyObject,
sel: Sel,
) -> Return {
unsafe {
<Self as RetainSemantics<*mut T, Return, Kind>>::convert_message_return(
ret,
receiver_ptr,
sel,
)
}
}
#[inline]
fn convert_defined_return(ret: Return) -> Self::ReturnInner {
<Self as RetainSemantics<*mut T, Return, Kind>>::convert_defined_return(ret)
}
}
impl<T: Message> ConvertReturn<NewFamily> for Option<Retained<T>> {
type Inner = *mut T;
#[inline]
unsafe fn convert_message_return(
inner: Self::Inner,
_receiver_ptr: *mut AnyObject,
_sel: Sel,
) -> Self {
unsafe { Retained::from_raw(inner) }
}
#[inline]
fn convert_defined_return(self) -> Self::Inner {
Retained::consume_as_ptr_option(self)
}
}
impl<T: Message> ConvertReturn<NewFamily> for Retained<T> {
type Inner = *mut T;
#[inline]
unsafe fn convert_message_return(
inner: Self::Inner,
receiver_ptr: *mut AnyObject,
sel: Sel,
) -> Self {
let ret = unsafe { Retained::from_raw(inner) };
if let Some(ret) = ret {
ret
} else {
let receiver = unsafe { receiver_ptr.as_ref() };
new_fail(receiver, sel)
}
}
#[inline]
fn convert_defined_return(self) -> Self::Inner {
Retained::into_raw(self)
}
}
#[cold]
#[track_caller]
fn new_fail(receiver: Option<&AnyObject>, sel: Sel) -> ! {
if let Some(receiver) = receiver {
let cls = receiver.class();
if cls.is_metaclass() {
if sel == sel!(new) {
panic!("failed creating new instance of {cls}")
} else {
panic!("failed creating new instance using +[{cls} {sel}]")
}
} else {
panic!("unexpected NULL returned from -[{cls} {sel}]")
}
} else {
panic!("unexpected NULL {sel}; receiver was NULL");
}
}
impl<'a, Return, Kind> RetainSemantics<&'a AnyClass, Allocated<Return>, Kind> for AllocFamily
where
Return: Message,
{
type ReceiverInner = &'a AnyClass;
#[inline]
fn prepare_message_send(receiver: &'a AnyClass) -> &'a AnyClass {
receiver
}
#[inline]
unsafe fn prepare_defined_method(receiver: &'a AnyClass) -> &'a AnyClass {
receiver
}
type ReturnInner = *mut Return;
#[inline]
unsafe fn convert_message_return(
ret: *mut Return,
_receiver_ptr: *mut AnyObject,
_sel: Sel,
) -> Allocated<Return> {
unsafe { Allocated::new(ret) }
}
#[inline]
fn convert_defined_return(ret: Allocated<Return>) -> *mut Return {
Allocated::into_ptr(ret)
}
}
impl<T, Kind> RetainSemantics<Allocated<T>, Option<Retained<T>>, Kind> for InitFamily
where
T: Message,
Kind: NotSuper,
{
type ReceiverInner = *mut T;
#[inline]
fn prepare_message_send(receiver: Allocated<T>) -> *mut T {
Allocated::into_ptr(receiver)
}
#[inline]
unsafe fn prepare_defined_method(receiver: *mut T) -> Allocated<T> {
unsafe { Allocated::new(receiver) }
}
type ReturnInner = *mut T;
#[inline]
unsafe fn convert_message_return(
ret: *mut T,
_receiver_ptr: *mut AnyObject,
_sel: Sel,
) -> Option<Retained<T>> {
unsafe { Retained::from_raw(ret) }
}
#[inline]
fn convert_defined_return(ret: Option<Retained<T>>) -> *mut T {
Retained::consume_as_ptr_option(ret)
}
}
impl<T, Kind> RetainSemantics<Allocated<T>, Retained<T>, Kind> for InitFamily
where
T: Message,
Kind: NotSuper,
{
type ReceiverInner = *mut T;
#[inline]
fn prepare_message_send(receiver: Allocated<T>) -> *mut T {
Allocated::into_ptr(receiver)
}
#[inline]
unsafe fn prepare_defined_method(receiver: *mut T) -> Allocated<T> {
unsafe { Allocated::new(receiver) }
}
type ReturnInner = *mut T;
#[inline]
unsafe fn convert_message_return(
ret: *mut T,
receiver_ptr: *mut AnyObject,
sel: Sel,
) -> Retained<T> {
let ret = unsafe { Retained::from_raw(ret) };
if let Some(ret) = ret {
ret
} else {
init_fail(receiver_ptr, sel)
}
}
#[inline]
fn convert_defined_return(ret: Retained<T>) -> *mut T {
Retained::into_raw(ret)
}
}
impl<T, Kind> RetainSemantics<PartialInit<T>, Option<Retained<T>>, Kind> for InitFamily
where
T: DefinedClass,
Kind: IsSuper,
{
type ReceiverInner = *mut T;
#[inline]
fn prepare_message_send(receiver: PartialInit<T>) -> *mut T {
PartialInit::into_ptr(receiver)
}
#[inline]
unsafe fn prepare_defined_method(receiver: *mut T) -> PartialInit<T> {
unsafe { PartialInit::new(receiver) }
}
type ReturnInner = *mut T;
#[inline]
unsafe fn convert_message_return(
ret: *mut T,
_receiver_ptr: *mut AnyObject,
_sel: Sel,
) -> Option<Retained<T>> {
let ret = unsafe { Retained::from_raw(ret) };
if let Some(ret) = ret {
unsafe { set_finalized(ret.as_nonnull_ptr()) };
Some(ret)
} else {
None
}
}
#[inline]
fn convert_defined_return(ret: Option<Retained<T>>) -> *mut T {
Retained::consume_as_ptr_option(ret)
}
}
impl<T, Kind> RetainSemantics<PartialInit<T>, Retained<T>, Kind> for InitFamily
where
T: DefinedClass,
Kind: IsSuper,
{
type ReceiverInner = *mut T;
#[inline]
fn prepare_message_send(receiver: PartialInit<T>) -> *mut T {
PartialInit::into_ptr(receiver)
}
#[inline]
unsafe fn prepare_defined_method(receiver: *mut T) -> PartialInit<T> {
unsafe { PartialInit::new(receiver) }
}
type ReturnInner = *mut T;
#[inline]
unsafe fn convert_message_return(
ret: *mut T,
receiver_ptr: *mut AnyObject,
sel: Sel,
) -> Retained<T> {
let ret = unsafe { Retained::from_raw(ret) };
if let Some(ret) = ret {
unsafe { set_finalized(ret.as_nonnull_ptr()) };
ret
} else {
init_fail(receiver_ptr, sel)
}
}
#[inline]
fn convert_defined_return(ret: Retained<T>) -> *mut T {
Retained::into_raw(ret)
}
}
#[cold]
#[track_caller]
fn init_fail(receiver: *mut AnyObject, sel: Sel) -> ! {
if receiver.is_null() {
panic!("failed allocating object")
} else {
if sel == sel!(init) {
panic!("failed initializing object")
} else {
panic!("failed initializing object with -{sel}")
}
}
}
impl<T: Message> ConvertReturn<CopyFamily> for Option<Retained<T>> {
type Inner = *mut T;
#[inline]
unsafe fn convert_message_return(
inner: Self::Inner,
_receiver_ptr: *mut AnyObject,
_sel: Sel,
) -> Self {
unsafe { Retained::from_raw(inner) }
}
#[inline]
fn convert_defined_return(self) -> Self::Inner {
Retained::consume_as_ptr_option(self)
}
}
impl<T: Message> ConvertReturn<CopyFamily> for Retained<T> {
type Inner = *mut T;
#[inline]
unsafe fn convert_message_return(
inner: Self::Inner,
_receiver_ptr: *mut AnyObject,
_sel: Sel,
) -> Self {
let ret = unsafe { Retained::from_raw(inner) };
if let Some(ret) = ret {
ret
} else {
copy_fail()
}
}
#[inline]
fn convert_defined_return(self) -> Self::Inner {
Retained::into_raw(self)
}
}
#[cold]
#[track_caller]
fn copy_fail() -> ! {
panic!("failed copying object")
}
impl<T: Message> ConvertReturn<MutableCopyFamily> for Option<Retained<T>> {
type Inner = *mut T;
#[inline]
unsafe fn convert_message_return(
inner: Self::Inner,
_receiver_ptr: *mut AnyObject,
_sel: Sel,
) -> Self {
unsafe { Retained::from_raw(inner) }
}
#[inline]
fn convert_defined_return(self) -> Self::Inner {
Retained::consume_as_ptr_option(self)
}
}
impl<T: Message> ConvertReturn<MutableCopyFamily> for Retained<T> {
type Inner = *mut T;
#[inline]
unsafe fn convert_message_return(
inner: Self::Inner,
_receiver_ptr: *mut AnyObject,
_sel: Sel,
) -> Self {
let ret = unsafe { Retained::from_raw(inner) };
if let Some(ret) = ret {
ret
} else {
mutable_copy_fail()
}
}
#[inline]
fn convert_defined_return(self) -> Self::Inner {
Retained::into_raw(self)
}
}
#[cold]
#[track_caller]
fn mutable_copy_fail() -> ! {
panic!("failed copying object")
}
impl<T: Message> ConvertReturn<NoneFamily> for Option<Retained<T>> {
type Inner = *mut T;
#[inline]
unsafe fn convert_message_return(
inner: Self::Inner,
_receiver_ptr: *mut AnyObject,
_sel: Sel,
) -> Self {
unsafe { Retained::retain_autoreleased(inner) }
}
#[inline]
fn convert_defined_return(self) -> Self::Inner {
Retained::autorelease_return_option(self)
}
}
impl<T: Message> ConvertReturn<NoneFamily> for Retained<T> {
type Inner = *mut T;
#[inline]
unsafe fn convert_message_return(
inner: Self::Inner,
receiver_ptr: *mut AnyObject,
sel: Sel,
) -> Self {
let ret = unsafe { Retained::retain_autoreleased(inner) };
if let Some(ret) = ret {
ret
} else {
let receiver = unsafe { receiver_ptr.as_ref() };
none_fail(receiver, sel)
}
}
#[inline]
fn convert_defined_return(self) -> Self::Inner {
Retained::autorelease_return(self)
}
}
#[cold]
#[track_caller]
fn none_fail(receiver: Option<&AnyObject>, sel: Sel) -> ! {
if let Some(receiver) = receiver {
let cls = receiver.class();
panic!(
"unexpected NULL returned from {}[{cls} {sel}]",
if cls.is_metaclass() { "+" } else { "-" },
)
} else {
panic!("unexpected NULL {sel}; receiver was NULL");
}
}