objc_foundation/
string.rs1use std::os::raw::c_char;
2use std::slice;
3use std::str;
4
5use objc_id::{Id, ShareId};
6
7use INSObject;
8
9pub trait INSCopying : INSObject {
10 type Output: INSObject;
11
12 fn copy(&self) -> ShareId<Self::Output> {
13 unsafe {
14 let obj: *mut Self::Output = msg_send![self, copy];
15 Id::from_retained_ptr(obj)
16 }
17 }
18}
19
20pub trait INSMutableCopying : INSObject {
21 type Output: INSObject;
22
23 fn mutable_copy(&self) -> Id<Self::Output> {
24 unsafe {
25 let obj: *mut Self::Output = msg_send![self, mutableCopy];
26 Id::from_retained_ptr(obj)
27 }
28 }
29}
30
31const UTF8_ENCODING: usize = 4;
32
33pub trait INSString : INSObject {
34 fn len(&self) -> usize {
35 unsafe {
36 msg_send![self, lengthOfBytesUsingEncoding:UTF8_ENCODING]
37 }
38 }
39
40 fn as_str(&self) -> &str {
41 let bytes = unsafe {
42 let bytes: *const c_char = msg_send![self, UTF8String];
43 bytes as *const u8
44 };
45 let len = self.len();
46 unsafe {
47 let bytes = slice::from_raw_parts(bytes, len);
48 str::from_utf8(bytes).unwrap()
49 }
50 }
51
52 fn from_str(string: &str) -> Id<Self> {
53 let cls = Self::class();
54 unsafe {
55 let obj: *mut Self = msg_send![cls, alloc];
56 let obj: *mut Self = msg_send![obj, initWithBytes:string.as_ptr()
57 length:string.len()
58 encoding:UTF8_ENCODING];
59 Id::from_retained_ptr(obj)
60 }
61 }
62}
63
64object_struct!(NSString);
65
66impl INSString for NSString { }
67
68impl INSCopying for NSString {
69 type Output = NSString;
70}
71
72#[cfg(test)]
73mod tests {
74 use super::{INSCopying, INSString, NSString};
75
76 #[test]
77 fn test_utf8() {
78 let expected = "ประเทศไทย中华Việt Nam";
79 let s = NSString::from_str(expected);
80 assert!(s.len() == expected.len());
81 assert!(s.as_str() == expected);
82 }
83
84 #[test]
85 fn test_interior_nul() {
86 let expected = "Hello\0World";
87 let s = NSString::from_str(expected);
88 assert!(s.len() == expected.len());
89 assert!(s.as_str() == expected);
90 }
91
92 #[test]
93 fn test_copy() {
94 let s = NSString::from_str("Hello!");
95 let copied = s.copy();
96 assert!(copied.as_str() == s.as_str());
97 }
98}