use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use std::os::raw::c_char;
use std::{fmt, slice, str};
use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl};
use objc_id::Id;
use crate::foundation::{id, to_bool, BOOL, NO, YES};
const UTF8_ENCODING: usize = 4;
#[derive(Debug)]
pub struct NSString<'a> {
pub objc: Id<Object>,
phantom: PhantomData<&'a ()>
}
impl<'a> NSString<'a> {
pub fn new(s: &str) -> Self {
NSString {
objc: unsafe {
let nsstring: *mut Object = msg_send![class!(NSString), alloc];
Id::from_ptr(msg_send![nsstring, initWithBytes:s.as_ptr()
length:s.len()
encoding:UTF8_ENCODING
])
},
phantom: PhantomData
}
}
pub fn no_copy(s: &'a str) -> Self {
NSString {
objc: unsafe {
let nsstring: id = msg_send![class!(NSString), alloc];
Id::from_ptr(msg_send![nsstring, initWithBytesNoCopy:s.as_ptr()
length:s.len()
encoding:UTF8_ENCODING
freeWhenDone:NO
])
},
phantom: PhantomData
}
}
pub fn retain(object: id) -> Self {
NSString {
objc: unsafe { Id::from_ptr(object) },
phantom: PhantomData
}
}
pub fn from_retained(object: id) -> Self {
NSString {
objc: unsafe { Id::from_retained_ptr(object) },
phantom: PhantomData
}
}
pub fn is(obj: id) -> bool {
let result: BOOL = unsafe { msg_send![obj, isKindOfClass: class!(NSString)] };
to_bool(result)
}
fn bytes(&self) -> *const u8 {
unsafe {
let bytes: *const c_char = msg_send![&*self.objc, UTF8String];
bytes as *const u8
}
}
fn bytes_len(&self) -> usize {
unsafe { msg_send![&*self.objc, lengthOfBytesUsingEncoding: UTF8_ENCODING] }
}
pub fn to_str(&self) -> &str {
let bytes = self.bytes();
let len = self.bytes_len();
unsafe {
let bytes = slice::from_raw_parts(bytes, len);
str::from_utf8(bytes).unwrap()
}
}
pub fn to_string(&self) -> String {
self.to_str().to_string()
}
}
impl fmt::Display for NSString<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.to_str())
}
}
impl From<NSString<'_>> for id {
fn from(mut string: NSString) -> Self {
&mut *string.objc
}
}
impl Deref for NSString<'_> {
type Target = Object;
fn deref(&self) -> &Object {
&*self.objc
}
}
impl DerefMut for NSString<'_> {
fn deref_mut(&mut self) -> &mut Object {
&mut *self.objc
}
}