use core::marker::PhantomData;
use core::ptr::NonNull;
use objc2::msg_send;
use objc2::rc::{Id, Owned, Shared};
use objc2::runtime::{Bool, Class, Object};
use objc2::Message;
use super::NSString;
pub unsafe trait INSObject: Message {
fn class() -> &'static Class;
fn hash_code(&self) -> usize {
unsafe { msg_send![self, hash] }
}
fn is_equal<T: INSObject>(&self, other: &T) -> bool {
let result: Bool = unsafe { msg_send![self, isEqual: other] };
result.is_true()
}
fn description(&self) -> Id<NSString, Shared> {
unsafe {
let result: *mut NSString = msg_send![self, description];
Id::retain(NonNull::new_unchecked(result))
}
}
fn is_kind_of(&self, cls: &Class) -> bool {
let result: Bool = unsafe { msg_send![self, isKindOfClass: cls] };
result.is_true()
}
}
object!(unsafe pub struct NSObject<> {
p: PhantomData<Object>, });
#[cfg(doctest)]
pub struct NSObjectNotSendNorSync;
impl NSObject {
unsafe_def_fn!(pub fn new -> Owned);
}
#[cfg(test)]
mod tests {
use super::{INSObject, NSObject};
use crate::NSString;
use alloc::format;
#[test]
fn test_equality() {
let obj1 = NSObject::new();
assert_eq!(obj1, obj1);
let obj2 = NSObject::new();
assert_ne!(obj1, obj2);
}
#[test]
fn test_hash_code() {
let obj = NSObject::new();
assert_eq!(obj.hash_code(), obj.hash_code());
}
#[test]
fn test_debug() {
let obj = NSObject::new();
let expected = format!("<NSObject: {:p}>", &*obj);
assert_eq!(format!("{:?}", obj), format!("{:?}", expected));
}
#[test]
fn test_is_kind_of() {
let obj = NSObject::new();
assert!(obj.is_kind_of(NSObject::class()));
assert!(!obj.is_kind_of(NSString::class()));
}
}