objc_foundation/
string.rs

1use 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}