virtualization_rs/
base.rs

1//! base module
2
3use std::marker::PhantomData;
4use std::slice;
5use std::str;
6
7use block::Block;
8use libc::c_void;
9use objc::rc::StrongPtr;
10use objc::runtime::{Object, BOOL, NO, YES};
11use objc::{class, msg_send, sel, sel_impl};
12
13#[link(name = "Virtualization", kind = "framework")]
14extern "C" {}
15
16#[link(name = "Foundation", kind = "framework")]
17extern "C" {
18    pub fn dispatch_queue_create(label: *const libc::c_char, attr: Id) -> Id;
19    // pub fn dispatch_sync(queue: Id, block: &Block<(), ()>);
20    pub fn dispatch_sync(queue: Id, block: *mut c_void);
21    pub fn dispatch_async(queue: Id, block: &Block<(), ()>);
22// pub fn dispatch_async(queue: Id, block: *mut c_void);
23}
24
25pub type Id = *mut Object;
26pub const NIL: Id = 0 as Id;
27
28pub struct NSArray<T> {
29    pub _phantom: PhantomData<T>,
30    pub p: StrongPtr,
31}
32
33impl<T> NSArray<T> {
34    pub fn array_with_objects(objects: Vec<Id>) -> NSArray<T> {
35        unsafe {
36            let p = StrongPtr::new(
37                msg_send![class!(NSArray), arrayWithObjects:objects.as_slice().as_ptr() count:objects.len()],
38            );
39            NSArray {
40                p: p,
41                _phantom: PhantomData,
42            }
43        }
44    }
45
46    pub fn count(&self) -> usize {
47        unsafe { msg_send![*self.p, count] }
48    }
49}
50
51impl<T: From<StrongPtr>> NSArray<T> {
52    pub fn object_at_index(&self, index: usize) -> T {
53        debug_assert!(index < self.count());
54        unsafe { T::from(StrongPtr::retain(msg_send![*self.p, objectAtIndex: index])) }
55    }
56}
57
58const UTF8_ENCODING: usize = 4;
59pub struct NSString(pub StrongPtr);
60
61impl NSString {
62    pub fn new(string: &str) -> NSString {
63        unsafe {
64            let alloc: Id = msg_send![class!(NSString), alloc];
65            let p = StrongPtr::new(
66                msg_send![alloc, initWithBytes:string.as_ptr() length:string.len() encoding:UTF8_ENCODING as Id],
67            );
68            NSString(p)
69        }
70    }
71
72    pub fn len(&self) -> usize {
73        unsafe { msg_send![*self.0, lengthOfBytesUsingEncoding: UTF8_ENCODING] }
74    }
75
76    pub fn as_str(&self) -> &str {
77        unsafe {
78            let bytes = {
79                let bytes: *const libc::c_char = msg_send![*self.0, UTF8String];
80                bytes as *const u8
81            };
82            let len = self.len();
83            let bytes = slice::from_raw_parts(bytes, len);
84            str::from_utf8(bytes).unwrap()
85        }
86    }
87}
88
89impl From<StrongPtr> for NSString {
90    fn from(p: StrongPtr) -> Self {
91        NSString(p)
92    }
93}
94
95pub struct NSURL(pub StrongPtr);
96
97impl NSURL {
98    pub fn url_with_string(url: &str) -> NSURL {
99        unsafe {
100            let url_nsstring = NSString::new(url);
101            let p = StrongPtr::retain(msg_send![class!(NSURL), URLWithString: url_nsstring]);
102            NSURL(p)
103        }
104    }
105
106    pub fn file_url_with_path(path: &str, is_directory: bool) -> NSURL {
107        unsafe {
108            let path_nsstring = NSString::new(path);
109            let is_directory_ = if is_directory { YES } else { NO };
110            let p = StrongPtr::retain(
111                msg_send![class!(NSURL), fileURLWithPath:path_nsstring isDirectory:is_directory_],
112            );
113            NSURL(p)
114        }
115    }
116
117    pub fn check_resource_is_reachable_and_return_error(&self) -> bool {
118        let b = unsafe {
119            let obj: Id = msg_send![*self.0, checkResourceIsReachableAndReturnError: NIL];
120            obj as BOOL
121        };
122        b == YES
123    }
124
125    pub fn absolute_url(&self) -> NSURL {
126        unsafe {
127            let p = StrongPtr::retain(msg_send![*self.0, absoluteURL]);
128            NSURL(p)
129        }
130    }
131}
132
133pub struct NSFileHandle(pub StrongPtr);
134
135impl NSFileHandle {
136    pub fn new() -> NSFileHandle {
137        unsafe {
138            let p = StrongPtr::new(msg_send![class!(NSFileHandle), new]);
139            NSFileHandle(p)
140        }
141    }
142
143    pub fn file_handle_with_standard_input() -> NSFileHandle {
144        unsafe {
145            let p = StrongPtr::retain(msg_send![class!(NSFileHandle), fileHandleWithStandardInput]);
146            NSFileHandle(p)
147        }
148    }
149
150    pub fn file_handle_with_standard_output() -> NSFileHandle {
151        unsafe {
152            let p = StrongPtr::retain(msg_send![
153                class!(NSFileHandle),
154                fileHandleWithStandardOutput
155            ]);
156            NSFileHandle(p)
157        }
158    }
159}
160
161pub struct NSDictionary(pub StrongPtr);
162
163impl NSDictionary {
164    pub fn all_keys<T>(&self) -> NSArray<T> {
165        unsafe {
166            NSArray {
167                p: StrongPtr::retain(msg_send![*self.0, allKeys]),
168                _phantom: PhantomData,
169            }
170        }
171    }
172
173    pub fn all_values<T>(&self) -> NSArray<T> {
174        unsafe {
175            NSArray {
176                p: StrongPtr::retain(msg_send![*self.0, allValues]),
177                _phantom: PhantomData,
178            }
179        }
180    }
181}
182
183pub struct NSError(pub StrongPtr);
184
185impl NSError {
186    pub fn nil() -> NSError {
187        unsafe {
188            let p = StrongPtr::new(NIL);
189            NSError(p)
190        }
191    }
192
193    pub fn code(&self) -> isize {
194        unsafe { msg_send![*self.0, code] }
195    }
196
197    pub fn localized_description(&self) -> NSString {
198        unsafe { NSString(StrongPtr::retain(msg_send![*self.0, localizedDescription])) }
199    }
200
201    pub fn localized_failure_reason(&self) -> NSString {
202        unsafe {
203            NSString(StrongPtr::retain(msg_send![
204                *self.0,
205                localizedFailureReason
206            ]))
207        }
208    }
209
210    pub fn localized_recovery_suggestion(&self) -> NSString {
211        unsafe {
212            NSString(StrongPtr::retain(msg_send![
213                *self.0,
214                localizedRecoverySuggestion
215            ]))
216        }
217    }
218
219    pub fn help_anchor(&self) -> NSString {
220        unsafe { NSString(StrongPtr::retain(msg_send![*self.0, helpAnchor])) }
221    }
222
223    pub fn user_info(&self) -> NSDictionary {
224        unsafe { NSDictionary(StrongPtr::retain(msg_send![*self.0, userInfo])) }
225    }
226
227    pub fn dump(&self) {
228        let code = self.code();
229        println!("code: {}", code);
230        let localized_description = self.localized_description();
231        println!("localizedDescription : {}", localized_description.as_str());
232        let localized_failure_reason = self.localized_failure_reason();
233        println!(
234            "localizedFailureReason : {}",
235            localized_failure_reason.as_str()
236        );
237        let localized_recovery_suggestion = self.localized_recovery_suggestion();
238        println!(
239            "localizedRecoverySuggestion : {}",
240            localized_recovery_suggestion.as_str()
241        );
242        let help_anchor = self.help_anchor();
243        println!("helpAnchor : {}", help_anchor.as_str());
244        let user_info = self.user_info();
245        println!("userInfo :");
246        let keys: NSArray<NSString> = user_info.all_keys();
247        let values: NSArray<NSString> = user_info.all_values();
248        let cnt = keys.count();
249        for i in 0..cnt {
250            let k = keys.object_at_index(i);
251            let o = values.object_at_index(i);
252            println!("    key: {}, value: {}", k.as_str(), o.as_str());
253        }
254    }
255}