<commit_before>use objc::runtime::{Class, Object};
use objc::{Id, Message};

use NSString;

pub trait INSObject : Message {
    fn class_name() -> &'static str;

    fn class(&self) -> &Class {
        let obj = unsafe { &*(self as *const _ as *const Object) };
        obj.class()
    }

    fn hash_code(&self) -> uint {
        unsafe {
            msg_send![self, hash]
        }
    }

    fn is_equal<T: INSObject>(&self, other: &T) -> bool {
        let result: i8 = unsafe {
            msg_send![self, isEqual:other]
        };
        result != 0
    }

    fn description(&self) -> Id<NSString> {
        unsafe {
            let result: *mut NSString = msg_send![self, description];
            Id::from_ptr(result)
        }
    }

    fn is_kind_of(&self, cls: &Class) -> bool {
        let result: i8 = unsafe {
            msg_send![self, isKindOfClass:cls]
        };
        result != 0
    }

    fn as_object<T: INSObject>(&self) -> Option<&T> {
        let cls = class::<T>();
        if self.is_kind_of(cls) {
            let ptr = self as *const _ as *const T;
            Some(unsafe { &*ptr })
        } else {
            None
        }
    }

    fn new() -> Id<Self> {
        let cls = class::<Self>();
        unsafe {
            let obj: *mut Self = msg_send![cls, alloc];
            let obj: *mut Self = msg_send![obj, init];
            Id::from_retained_ptr(obj)
        }
    }
}

object_struct!(NSObject);

pub fn class<T: INSObject>() -> &'static Class {
    let name = <T as INSObject>::class_name();
    match Class::get(name) {
        Some(cls) => cls,
        None => panic!("Class {} not found", name),
    }
}

#[cfg(test)]
mod tests {
    use objc::Id;
    use {INSString, NSString};
    use super::{class, INSObject, NSObject};

    #[test]
    fn test_class_name() {
        assert!(<NSObject as INSObject>::class_name() == "NSObject");
    }

    #[test]
    fn test_class() {
        let obj: Id<NSObject> = INSObject::new();
        let cls = obj.class();
        assert!(cls.name() == "NSObject");
    }

    #[test]
    fn test_is_equal() {
        let obj1: Id<NSObject> = INSObject::new();
        assert!(obj1.is_equal(&*obj1));

        let obj2: Id<NSObject> = INSObject::new();
        assert!(!obj1.is_equal(&*obj2));
    }

    #[test]
    fn test_hash_code() {
        let obj: Id<NSObject> = INSObject::new();
        assert!(obj.hash_code() == obj.hash_code());
    }

    #[test]
    fn test_description() {
        let obj: Id<NSObject> = INSObject::new();
        let description = obj.description();
        let expected = format!("<NSObject: {:?}>", &*obj as *const NSObject);
        assert!(description.as_str() == expected.as_slice());
    }

    #[test]
    fn test_is_kind_of() {
        let obj: Id<NSObject> = INSObject::new();
        assert!(obj.is_kind_of(class::<NSObject>()));
        assert!(!obj.is_kind_of(class::<NSString>()));
    }

    #[test]
    fn test_as_object() {
        let obj: Id<NSObject> = INSObject::new();
        let as_str: Option<&NSString> = obj.as_object();
        assert!(as_str.is_none());

        let string: Id<NSString> = INSObject::new();
        let as_obj: Option<&NSObject> = string.as_object();
        assert!(as_obj.is_some());
    }
}
<commit_msg>Removed class method from INSObject.<commit_after>use objc::runtime::Class;
use objc::{Id, Message};

use NSString;

pub trait INSObject : Message {
    fn class_name() -> &'static str;

    fn hash_code(&self) -> uint {
        unsafe {
            msg_send![self, hash]
        }
    }

    fn is_equal<T: INSObject>(&self, other: &T) -> bool {
        let result: i8 = unsafe {
            msg_send![self, isEqual:other]
        };
        result != 0
    }

    fn description(&self) -> Id<NSString> {
        unsafe {
            let result: *mut NSString = msg_send![self, description];
            Id::from_ptr(result)
        }
    }

    fn is_kind_of(&self, cls: &Class) -> bool {
        let result: i8 = unsafe {
            msg_send![self, isKindOfClass:cls]
        };
        result != 0
    }

    fn as_object<T: INSObject>(&self) -> Option<&T> {
        let cls = class::<T>();
        if self.is_kind_of(cls) {
            let ptr = self as *const _ as *const T;
            Some(unsafe { &*ptr })
        } else {
            None
        }
    }

    fn new() -> Id<Self> {
        let cls = class::<Self>();
        unsafe {
            let obj: *mut Self = msg_send![cls, alloc];
            let obj: *mut Self = msg_send![obj, init];
            Id::from_retained_ptr(obj)
        }
    }
}

object_struct!(NSObject);

pub fn class<T: INSObject>() -> &'static Class {
    let name = <T as INSObject>::class_name();
    match Class::get(name) {
        Some(cls) => cls,
        None => panic!("Class {} not found", name),
    }
}

#[cfg(test)]
mod tests {
    use objc::Id;
    use {INSString, NSString};
    use super::{class, INSObject, NSObject};

    #[test]
    fn test_class_name() {
        assert!(<NSObject as INSObject>::class_name() == "NSObject");
    }

    #[test]
    fn test_is_equal() {
        let obj1: Id<NSObject> = INSObject::new();
        assert!(obj1.is_equal(&*obj1));

        let obj2: Id<NSObject> = INSObject::new();
        assert!(!obj1.is_equal(&*obj2));
    }

    #[test]
    fn test_hash_code() {
        let obj: Id<NSObject> = INSObject::new();
        assert!(obj.hash_code() == obj.hash_code());
    }

    #[test]
    fn test_description() {
        let obj: Id<NSObject> = INSObject::new();
        let description = obj.description();
        let expected = format!("<NSObject: {:?}>", &*obj as *const NSObject);
        assert!(description.as_str() == expected.as_slice());
    }

    #[test]
    fn test_is_kind_of() {
        let obj: Id<NSObject> = INSObject::new();
        assert!(obj.is_kind_of(class::<NSObject>()));
        assert!(!obj.is_kind_of(class::<NSString>()));
    }

    #[test]
    fn test_as_object() {
        let obj: Id<NSObject> = INSObject::new();
        let as_str: Option<&NSString> = obj.as_object();
        assert!(as_str.is_none());

        let string: Id<NSString> = INSObject::new();
        let as_obj: Option<&NSObject> = string.as_object();
        assert!(as_obj.is_some());
    }
}

{'fraction_non_alphanumeric': 0.16690624500878454, 'fraction_numerical': 0.0031943778949049674, 'mean_word_length': 2.1754563894523327, 'pattern_counts': {'":': 0, '<': 48, '<?xml version=': 0, '>': 69, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5790548', 'n_tokens_mistral': 2123, 'n_tokens_neox': 2079, 'n_words': 452}