diff --git a/src/foundation.rs b/src/foundation.rs index babc187..1840f26 100644 --- a/src/foundation.rs +++ b/src/foundation.rs @@ -9,7 +9,6 @@ use base::{id, class}; use libc; -use std::ffi::CString; #[cfg(target_pointer_width = "32")] pub type NSInteger = libc::c_int; @@ -21,6 +20,8 @@ pub type NSInteger = libc::c_long; #[cfg(target_pointer_width = "64")] pub type NSUInteger = libc::c_ulong; +const UTF8_ENCODING: usize = 4; + #[repr(C)] pub struct NSPoint { pub x: f64, @@ -123,24 +124,26 @@ pub trait NSString { msg_send![class("NSString"), alloc] } - unsafe fn initWithUTF8String_(self, c_string: *const i8) -> id; unsafe fn stringByAppendingString_(self, other: id) -> id; unsafe fn init_str(self, string: &str) -> Self; unsafe fn UTF8String(self) -> *const libc::c_char; + unsafe fn len(self) -> usize; } impl NSString for id { - unsafe fn initWithUTF8String_(self, c_string: *const i8) -> id { - msg_send![self, initWithUTF8String:c_string as id] - } - unsafe fn stringByAppendingString_(self, other: id) -> id { msg_send![self, stringByAppendingString:other] } unsafe fn init_str(self, string: &str) -> id { - let cstring = CString::new(string).unwrap(); - self.initWithUTF8String_(cstring.as_ptr()) + return msg_send![self, + initWithBytes:string.as_ptr() + length:string.len() + encoding:UTF8_ENCODING as id]; + } + + unsafe fn len(self) -> usize { + msg_send![self, lengthOfBytesUsingEncoding:UTF8_ENCODING] } unsafe fn UTF8String(self) -> *const libc::c_char { diff --git a/tests/foundation.rs b/tests/foundation.rs new file mode 100644 index 0000000..c4f9130 --- /dev/null +++ b/tests/foundation.rs @@ -0,0 +1,59 @@ +extern crate cocoa; + +#[cfg(test)] +mod foundation { + mod nsstring { + use cocoa::foundation::{NSString}; + use cocoa::base::{nil}; + use std::slice; + use std::str; + + #[test] + fn test_utf8() { + let expected = "Iñtërnâtiônàlizætiøn"; + unsafe { + let built = NSString::alloc(nil).init_str(expected); + let bytes = built.UTF8String() as *const u8; + let objc_string = str::from_utf8(slice::from_raw_parts(bytes, built.len())).unwrap(); + assert!(objc_string.len() == expected.len()); + assert!(objc_string == expected); + } + } + + #[test] + fn test_string() { + let expected = "Hello World!"; + unsafe { + let built = NSString::alloc(nil).init_str(expected); + let bytes = built.UTF8String() as *const u8; + let objc_string = str::from_utf8(slice::from_raw_parts(bytes, built.len())).unwrap(); + assert!(objc_string.len() == expected.len()); + assert!(objc_string == expected); + } + } + + #[test] + fn test_length() { + let expected = "Hello!"; + unsafe { + let built = NSString::alloc(nil).init_str(expected); + assert!(built.len() == expected.len()); + } + } + + #[test] + fn test_append_by_appending_string() { + let initial_str = "Iñtërnâtiônàlizætiøn"; + let to_append = "_more_strings"; + let expected = concat!("Iñtërnâtiônàlizætiøn", "_more_strings"); + unsafe { + let built = NSString::alloc(nil).init_str(initial_str); + let built_to_append = NSString::alloc(nil).init_str(to_append); + let append_string = built.stringByAppendingString_(built_to_append); + let bytes = append_string.UTF8String() as *const u8; + let objc_string = str::from_utf8(slice::from_raw_parts(bytes, append_string.len())).unwrap(); + assert!(objc_string == expected); + } + } + } +}