1 use std::cmp::Ordering;
2 use std::marker::PhantomData;
3 use std::ops::{Index, Range};
4 
5 use objc::runtime::{Class, Object};
6 use objc_id::{Id, Owned, Ownership, Shared, ShareId};
7 
8 use {INSCopying, INSFastEnumeration, INSMutableCopying, INSObject, NSEnumerator};
9 
10 #[repr(isize)]
11 #[derive(Clone, Copy)]
12 pub enum NSComparisonResult {
13     Ascending  = -1,
14     Same       = 0,
number(&self) -> u3215     Descending = 1,
16 }
17 
18 impl NSComparisonResult {
19     pub fn from_ordering(order: Ordering) -> NSComparisonResult {
20         match order {
21             Ordering::Less => NSComparisonResult::Ascending,
22             Ordering::Equal => NSComparisonResult::Same,
23             Ordering::Greater => NSComparisonResult::Descending,
24         }
25     }
26 
27     pub fn as_ordering(&self) -> Ordering {
28         match *self {
29             NSComparisonResult::Ascending => Ordering::Less,
30             NSComparisonResult::Same => Ordering::Equal,
31             NSComparisonResult::Descending => Ordering::Greater,
32         }
33     }
34 }
class() -> &'static Class35 
36 #[repr(C)]
37 #[derive(Clone, Copy)]
38 pub struct NSRange {
39     pub location: usize,
40     pub length: usize,
41 }
my_object_set_number(this: &mut Object, _cmd: Sel, number: u32)42 
43 impl NSRange {
44     pub fn from_range(range: Range<usize>) -> NSRange {
45         assert!(range.end >= range.start);
46         NSRange { location: range.start, length: range.end - range.start }
47     }
48 
49     pub fn as_range(&self) -> Range<usize> {
50         Range { start: self.location, end: self.location + self.length }
51     }
52 }
53 
54 unsafe fn from_refs<A>(refs: &[&A::Item]) -> Id<A> where A: INSArray {
55     let cls = A::class();
56     let obj: *mut A = msg_send![cls, alloc];
57     let obj: *mut A = msg_send![obj, initWithObjects:refs.as_ptr()
58                                                count:refs.len()];
59     Id::from_retained_ptr(obj)
60 }
61 
62 pub trait INSArray : INSObject {
63     type Item: INSObject;
main()64     type Own: Ownership;
65 
66     fn count(&self) -> usize {
67         unsafe {
68             msg_send![self, count]
69         }
70     }
71 
72     fn object_at(&self, index: usize) -> &Self::Item {
73         unsafe {
74             let obj: *const Self::Item = msg_send![self, objectAtIndex:index];
75             &*obj
76         }
77     }
78 
79     fn first_object(&self) -> Option<&Self::Item> {
80         unsafe {
81             let obj: *const Self::Item = msg_send![self, firstObject];
82             if obj.is_null() { None } else { Some(&*obj) }
83         }
84     }
85 
86     fn last_object(&self) -> Option<&Self::Item> {
87         unsafe {
88             let obj: *const Self::Item = msg_send![self, lastObject];
89             if obj.is_null() { None } else { Some(&*obj) }
90         }
91     }
92 
93     fn object_enumerator(&self) -> NSEnumerator<Self::Item> {
94         unsafe {
95             let result: *mut Object = msg_send![self, objectEnumerator];
96             NSEnumerator::from_ptr(result)
97         }
98     }
99 
100     fn from_vec(vec: Vec<Id<Self::Item, Self::Own>>) -> Id<Self> {
101         let refs: Vec<&Self::Item> = vec.iter().map(|obj| &**obj).collect();
102         unsafe {
103             from_refs(&refs)
104         }
105     }
106 
107     fn objects_in_range(&self, range: Range<usize>) -> Vec<&Self::Item> {
108         let range = NSRange::from_range(range);
109         let mut vec = Vec::with_capacity(range.length);
110         unsafe {
111             let _: () = msg_send![self, getObjects:vec.as_ptr() range:range];
112             vec.set_len(range.length);
113         }
114         vec
115     }
116 
117     fn to_vec(&self) -> Vec<&Self::Item> {
118         self.objects_in_range(0..self.count())
119     }
120 
121     fn into_vec(array: Id<Self>) -> Vec<Id<Self::Item, Self::Own>> {
122         array.to_vec().into_iter().map(|obj| unsafe {
123             let obj_ptr: *const Self::Item = obj;
124             Id::from_ptr(obj_ptr as *mut Self::Item)
125         }).collect()
126     }
127 
128     fn mut_object_at(&mut self, index: usize) -> &mut Self::Item
129             where Self: INSArray<Own=Owned> {
130         unsafe {
131             let result: *mut Self::Item = msg_send![self, objectAtIndex:index];
132             &mut *result
133         }
134     }
135 
136     fn shared_object_at(&self, index: usize) -> ShareId<Self::Item>
137             where Self: INSArray<Own=Shared> {
138         let obj = self.object_at(index);
139         unsafe {
140             Id::from_ptr(obj as *const _ as *mut Self::Item)
141         }
142     }
143 
144     fn from_slice(slice: &[ShareId<Self::Item>]) -> Id<Self>
145             where Self: INSArray<Own=Shared> {
146         let refs: Vec<&Self::Item> = slice.iter().map(|obj| &**obj).collect();
147         unsafe {
148             from_refs(&refs)
149         }
150     }
151 
152     fn to_shared_vec(&self) -> Vec<ShareId<Self::Item>>
153             where Self: INSArray<Own=Shared> {
154         self.to_vec().into_iter().map(|obj| unsafe {
155             let obj_ptr: *const Self::Item = obj;
156             Id::from_ptr(obj_ptr as *mut Self::Item)
157         }).collect()
158     }
159 }
160 
161 pub struct NSArray<T, O = Owned> {
162     item: PhantomData<Id<T, O>>,
163 }
164 
165 object_impl!(NSArray<T, O>);
166 
167 impl<T, O> INSObject for NSArray<T, O> where T: INSObject, O: Ownership {
168     fn class() -> &'static Class {
169         Class::get("NSArray").unwrap()
170     }
171 }
172 
173 impl<T, O> INSArray for NSArray<T, O> where T: INSObject, O: Ownership {
174     type Item = T;
175     type Own = O;
176 }
177 
178 impl<T> INSCopying for NSArray<T, Shared> where T: INSObject {
179     type Output = NSSharedArray<T>;
180 }
181 
182 impl<T> INSMutableCopying for NSArray<T, Shared> where T: INSObject {
183     type Output = NSMutableSharedArray<T>;
184 }
185 
186 impl<T, O> INSFastEnumeration for NSArray<T, O>
187         where T: INSObject, O: Ownership {
188     type Item = T;
189 }
190 
191 impl<T, O> Index<usize> for NSArray<T, O> where T: INSObject, O: Ownership {
192     type Output = T;
193 
194     fn index(&self, index: usize) -> &T {
195         self.object_at(index)
196     }
197 }
198 
199 pub type NSSharedArray<T> = NSArray<T, Shared>;
200 
201 pub trait INSMutableArray : INSArray {
202     fn add_object(&mut self, obj: Id<Self::Item, Self::Own>) {
203         unsafe {
204             let _: () = msg_send![self, addObject:&*obj];
205         }
206     }
207 
208     fn insert_object_at(&mut self, index: usize, obj: Id<Self::Item, Self::Own>) {
209         unsafe {
210             let _: () = msg_send![self, insertObject:&*obj atIndex:index];
211         }
212     }
213 
214     fn replace_object_at(&mut self, index: usize, obj: Id<Self::Item, Self::Own>) ->
215             Id<Self::Item, Self::Own> {
216         let old_obj = unsafe {
217             let obj = self.object_at(index);
218             Id::from_ptr(obj as *const _ as *mut Self::Item)
219         };
220         unsafe {
221             let _: () = msg_send![self, replaceObjectAtIndex:index
222                                                   withObject:&*obj];
223         }
224         old_obj
225     }
226 
227     fn remove_object_at(&mut self, index: usize) -> Id<Self::Item, Self::Own> {
228         let obj = unsafe {
229             let obj = self.object_at(index);
230             Id::from_ptr(obj as *const _ as *mut Self::Item)
231         };
232         unsafe {
233             let _: () = msg_send![self, removeObjectAtIndex:index];
234         }
235         obj
236     }
237 
238     fn remove_last_object(&mut self) -> Id<Self::Item, Self::Own> {
239         let obj = self.last_object().map(|obj| unsafe {
240             Id::from_ptr(obj as *const _ as *mut Self::Item)
241         });
242         unsafe {
243             let _: () = msg_send![self, removeLastObject];
244         }
245         // removeLastObject would have failed if the array is empty,
246         // so we know this won't be None
247         obj.unwrap()
248     }
249 
250     fn remove_all_objects(&mut self) {
251         unsafe {
252             let _: () = msg_send![self, removeAllObjects];
253         }
254     }
255 
256     fn sort_by<F>(&mut self, compare: F)
257             where F: FnMut(&Self::Item, &Self::Item) -> Ordering {
258         extern fn compare_with_closure<T, F>(obj1: &T, obj2: &T,
259                 compare: &mut F) -> NSComparisonResult
260                 where F: FnMut(&T, &T) -> Ordering {
261             NSComparisonResult::from_ordering((*compare)(obj1, obj2))
262         }
263 
264         let f: extern fn(&Self::Item, &Self::Item, &mut F) -> NSComparisonResult =
265             compare_with_closure;
266         let mut closure = compare;
267         unsafe {
268             let _: () = msg_send![self, sortUsingFunction:f
269                                                   context:&mut closure];
270         }
271     }
272 }
273 
274 pub struct NSMutableArray<T, O = Owned> {
275     item: PhantomData<Id<T, O>>,
276 }
277 
278 object_impl!(NSMutableArray<T, O>);
279 
280 impl<T, O> INSObject for NSMutableArray<T, O> where T: INSObject, O: Ownership {
281     fn class() -> &'static Class {
282         Class::get("NSMutableArray").unwrap()
283     }
284 }
285 
286 impl<T, O> INSArray for NSMutableArray<T, O> where T: INSObject, O: Ownership {
287     type Item = T;
288     type Own = O;
289 }
290 
291 impl<T, O> INSMutableArray for NSMutableArray<T, O>
292         where T: INSObject, O: Ownership { }
293 
294 impl<T> INSCopying for NSMutableArray<T, Shared> where T: INSObject {
295     type Output = NSSharedArray<T>;
296 }
297 
298 impl<T> INSMutableCopying for NSMutableArray<T, Shared> where T: INSObject {
299     type Output = NSMutableSharedArray<T>;
300 }
301 
302 impl<T, O> INSFastEnumeration for NSMutableArray<T, O>
303         where T: INSObject, O: Ownership {
304     type Item = T;
305 }
306 
307 impl<T, O> Index<usize> for NSMutableArray<T, O>
308         where T: INSObject, O: Ownership {
309     type Output = T;
310 
311     fn index(&self, index: usize) -> &T {
312         self.object_at(index)
313     }
314 }
315 
316 pub type NSMutableSharedArray<T> = NSMutableArray<T, Shared>;
317 
318 #[cfg(test)]
319 mod tests {
320     use objc_id::Id;
321     use {INSObject, INSString, NSObject, NSString};
322     use super::{INSArray, INSMutableArray, NSArray, NSMutableArray};
323 
324     fn sample_array(len: usize) -> Id<NSArray<NSObject>> {
325         let mut vec = Vec::with_capacity(len);
326         for _ in 0..len {
327             vec.push(NSObject::new());
328         }
329         NSArray::from_vec(vec)
330     }
331 
332     #[test]
333     fn test_count() {
334         let empty_array = NSArray::<NSObject>::new();
335         assert!(empty_array.count() == 0);
336 
337         let array = sample_array(4);
338         assert!(array.count() == 4);
339     }
340 
341     #[test]
342     fn test_object_at() {
343         let array = sample_array(4);
344         assert!(array.object_at(0) != array.object_at(3));
345         assert!(array.first_object().unwrap() == array.object_at(0));
346         assert!(array.last_object().unwrap() == array.object_at(3));
347 
348         let empty_array: Id<NSArray<NSObject>> = INSObject::new();
349         assert!(empty_array.first_object().is_none());
350         assert!(empty_array.last_object().is_none());
351     }
352 
353     #[test]
354     fn test_object_enumerator() {
355         let array = sample_array(4);
356 
357         assert!(array.object_enumerator().count() == 4);
358         assert!(array.object_enumerator()
359                      .enumerate()
360                      .all(|(i, obj)| obj == array.object_at(i)));
361     }
362 
363     #[test]
364     fn test_objects_in_range() {
365         let array = sample_array(4);
366 
367         let middle_objs = array.objects_in_range(1..3);
368         assert!(middle_objs.len() == 2);
369         assert!(middle_objs[0] == array.object_at(1));
370         assert!(middle_objs[1] == array.object_at(2));
371 
372         let empty_objs = array.objects_in_range(1..1);
373         assert!(empty_objs.len() == 0);
374 
375         let all_objs = array.objects_in_range(0..4);
376         assert!(all_objs.len() == 4);
377     }
378 
379     #[test]
380     fn test_into_vec() {
381         let array = sample_array(4);
382 
383         let vec = INSArray::into_vec(array);
384         assert!(vec.len() == 4);
385     }
386 
387     #[test]
388     fn test_add_object() {
389         let mut array = NSMutableArray::new();
390         let obj = NSObject::new();
391         array.add_object(obj);
392 
393         assert!(array.count() == 1);
394         assert!(array.object_at(0) == array.object_at(0));
395 
396         let obj = NSObject::new();
397         array.insert_object_at(0, obj);
398         assert!(array.count() == 2);
399     }
400 
401     #[test]
402     fn test_replace_object() {
403         let mut array = NSMutableArray::new();
404         let obj = NSObject::new();
405         array.add_object(obj);
406 
407         let obj = NSObject::new();
408         let old_obj = array.replace_object_at(0, obj);
409         assert!(&*old_obj != array.object_at(0));
410     }
411 
412     #[test]
413     fn test_remove_object() {
414         let mut array = NSMutableArray::new();
415         for _ in 0..4 {
416             array.add_object(NSObject::new());
417         }
418 
419         array.remove_object_at(1);
420         assert!(array.count() == 3);
421 
422         array.remove_last_object();
423         assert!(array.count() == 2);
424 
425         array.remove_all_objects();
426         assert!(array.count() == 0);
427     }
428 
429     #[test]
430     fn test_sort() {
431         let strings = vec![
432             NSString::from_str("hello"),
433             NSString::from_str("hi"),
434         ];
435         let mut strings = NSMutableArray::from_vec(strings);
436 
437         strings.sort_by(|s1, s2| s1.as_str().len().cmp(&s2.as_str().len()));
438         assert!(strings[0].as_str() == "hi");
439         assert!(strings[1].as_str() == "hello");
440     }
441 }
442