icrate/additions/Foundation/
array.rs1#![cfg(feature = "Foundation_NSArray")]
3use alloc::vec::Vec;
4use core::fmt;
5use core::mem;
6use core::ops::{Index, IndexMut, Range};
7use core::panic::{RefUnwindSafe, UnwindSafe};
8
9use objc2::mutability::{IsMutable, IsRetainable};
10use objc2::rc::IdFromIterator;
11
12use super::iter;
13use super::util;
14use crate::common::*;
15#[cfg(feature = "Foundation_NSMutableArray")]
16use crate::Foundation::NSMutableArray;
17use crate::Foundation::{self, NSArray};
18
19impl<T: Message> NSArray<T> {
20 pub fn from_vec(mut vec: Vec<Id<T>>) -> Id<Self> {
21 let len = vec.len();
24 let ptr = util::id_ptr_cast(vec.as_mut_ptr());
25 unsafe { Self::initWithObjects_count(Self::alloc(), ptr, len) }
28 }
31
32 pub fn from_id_slice(slice: &[Id<T>]) -> Id<Self>
33 where
34 T: IsIdCloneable,
35 {
36 let len = slice.len();
37 let ptr = util::id_ptr_cast_const(slice.as_ptr());
38 unsafe { Self::initWithObjects_count(Self::alloc(), ptr, len) }
45 }
46
47 pub fn from_slice(slice: &[&T]) -> Id<Self>
48 where
49 T: IsRetainable,
50 {
51 let len = slice.len();
52 let ptr = util::ref_ptr_cast_const(slice.as_ptr());
53 unsafe { Self::initWithObjects_count(Self::alloc(), ptr, len) }
60 }
61
62 #[doc(alias = "getObjects:range:")]
63 pub fn to_vec(&self) -> Vec<&T> {
64 unsafe { self.objects_in_range_unchecked(0..self.len()) }
66 }
67
68 #[doc(alias = "getObjects:range:")]
69 pub fn to_vec_retained(&self) -> Vec<Id<T>>
70 where
71 T: IsIdCloneable,
72 {
73 self.to_vec()
75 .into_iter()
76 .map(|obj| unsafe { util::collection_retain_id(obj) })
77 .collect()
78 }
79
80 }
85
86#[cfg(feature = "Foundation_NSMutableArray")]
87impl<T: Message> NSMutableArray<T> {
88 pub fn from_vec(mut vec: Vec<Id<T>>) -> Id<Self> {
89 let len = vec.len();
90 let ptr = util::id_ptr_cast(vec.as_mut_ptr());
91 unsafe { Self::initWithObjects_count(Self::alloc(), ptr, len) }
93 }
94
95 pub fn from_id_slice(slice: &[Id<T>]) -> Id<Self>
96 where
97 T: IsIdCloneable,
98 {
99 let len = slice.len();
100 let ptr = util::id_ptr_cast_const(slice.as_ptr());
101 unsafe { Self::initWithObjects_count(Self::alloc(), ptr, len) }
103 }
104
105 pub fn from_slice(slice: &[&T]) -> Id<Self>
106 where
107 T: IsRetainable,
108 {
109 let len = slice.len();
110 let ptr = util::ref_ptr_cast_const(slice.as_ptr());
111 unsafe { Self::initWithObjects_count(Self::alloc(), ptr, len) }
113 }
114
115 pub fn into_vec(array: Id<Self>) -> Vec<Id<T>> {
116 array
119 .to_vec()
120 .into_iter()
121 .map(|obj| unsafe { util::mutable_collection_retain_removed_id(obj) })
122 .collect()
123 }
124}
125
126impl<T: Message> NSArray<T> {
127 #[doc(alias = "count")]
128 pub fn len(&self) -> usize {
129 self.count()
130 }
131
132 pub fn is_empty(&self) -> bool {
133 self.len() == 0
134 }
135}
136
137extern_methods!(
138 unsafe impl<T: Message> NSArray<T> {
139 #[method(objectAtIndex:)]
140 unsafe fn get_unchecked(&self, index: usize) -> &T;
141
142 #[doc(alias = "objectAtIndex:")]
143 pub fn get(&self, index: usize) -> Option<&T> {
144 if index < self.len() {
146 Some(unsafe { self.get_unchecked(index) })
148 } else {
149 None
150 }
151 }
152
153 #[doc(alias = "objectAtIndex:")]
154 pub fn get_retained(&self, index: usize) -> Option<Id<T>>
155 where
156 T: IsIdCloneable,
157 {
158 self.get(index)
160 .map(|obj| unsafe { util::collection_retain_id(obj) })
161 }
162
163 #[method(objectAtIndex:)]
164 unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut T;
165
166 #[doc(alias = "objectAtIndex:")]
167 pub fn get_mut(&mut self, index: usize) -> Option<&mut T>
168 where
169 T: IsMutable,
170 {
171 if index < self.len() {
173 Some(unsafe { self.get_unchecked_mut(index) })
177 } else {
178 None
179 }
180 }
181
182 #[doc(alias = "firstObject")]
183 #[method(firstObject)]
184 pub fn first(&self) -> Option<&T>;
185
186 #[doc(alias = "firstObject")]
187 pub fn first_retained(&self) -> Option<Id<T>>
188 where
189 T: IsIdCloneable,
190 {
191 self.first()
193 .map(|obj| unsafe { util::collection_retain_id(obj) })
194 }
195
196 #[doc(alias = "firstObject")]
197 #[method(firstObject)]
198 pub fn first_mut(&mut self) -> Option<&mut T>
199 where
200 T: IsMutable;
201
202 #[doc(alias = "lastObject")]
203 #[method(lastObject)]
204 pub fn last(&self) -> Option<&T>;
205
206 #[doc(alias = "lastObject")]
207 pub fn last_retained(&self) -> Option<Id<T>>
208 where
209 T: IsIdCloneable,
210 {
211 self.last()
213 .map(|obj| unsafe { util::collection_retain_id(obj) })
214 }
215
216 #[doc(alias = "lastObject")]
217 #[method(lastObject)]
218 pub fn last_mut(&mut self) -> Option<&mut T>
219 where
220 T: IsMutable;
221 }
222);
223
224impl<T: Message> NSArray<T> {
225 unsafe fn objects_in_range_unchecked(&self, range: Range<usize>) -> Vec<&T> {
226 let range = Foundation::NSRange::from(range);
227 let mut vec: Vec<NonNull<T>> = Vec::with_capacity(range.length);
228 unsafe {
229 self.getObjects_range(NonNull::new(vec.as_mut_ptr()).unwrap(), range);
230 vec.set_len(range.length);
231 mem::transmute(vec)
232 }
233 }
234
235 #[doc(alias = "getObjects:range:")]
236 pub fn objects_in_range(&self, range: Range<usize>) -> Option<Vec<&T>> {
237 if range.end > self.len() {
238 return None;
239 }
240 Some(unsafe { self.objects_in_range_unchecked(range) })
242 }
243}
244
245#[cfg(feature = "Foundation_NSMutableArray")]
246impl<T: Message> NSMutableArray<T> {
247 #[doc(alias = "addObject:")]
248 pub fn push(&mut self, obj: Id<T>) {
249 unsafe { self.addObject(&obj) }
251 }
252
253 #[doc(alias = "insertObject:atIndex:")]
254 pub fn insert(&mut self, index: usize, obj: Id<T>) {
255 let len = self.len();
257 if index < len {
258 unsafe { self.insertObject_atIndex(&obj, index) }
261 } else {
262 panic!(
263 "insertion index (is {}) should be <= len (is {})",
264 index, len
265 );
266 }
267 }
268
269 #[doc(alias = "replaceObjectAtIndex:withObject:")]
270 pub fn replace(&mut self, index: usize, obj: Id<T>) -> Result<Id<T>, Id<T>> {
271 if let Some(old_obj) = self.get(index) {
272 let old_obj = unsafe { util::mutable_collection_retain_removed_id(old_obj) };
274 unsafe { self.replaceObjectAtIndex_withObject(index, &obj) };
277 Ok(old_obj)
278 } else {
279 Err(obj)
280 }
281 }
282
283 #[doc(alias = "removeObjectAtIndex:")]
284 pub fn remove(&mut self, index: usize) -> Option<Id<T>> {
285 let obj = self.get(index)?;
286 let obj = unsafe { util::mutable_collection_retain_removed_id(obj) };
288 unsafe { self.removeObjectAtIndex(index) };
290 Some(obj)
291 }
292
293 #[doc(alias = "removeLastObject")]
294 pub fn pop(&mut self) -> Option<Id<T>> {
295 let obj = self.last()?;
296 let obj = unsafe { util::mutable_collection_retain_removed_id(obj) };
298 unsafe { self.removeLastObject() };
300 Some(obj)
301 }
302
303 #[doc(alias = "sortUsingFunction:context:")]
304 pub fn sort_by<F: FnMut(&T, &T) -> core::cmp::Ordering>(&mut self, compare: F) {
305 unsafe extern "C" fn compare_with_closure<T, F: FnMut(&T, &T) -> core::cmp::Ordering>(
307 obj1: NonNull<T>,
308 obj2: NonNull<T>,
309 context: *mut c_void,
310 ) -> isize {
311 let context: *mut F = context.cast();
312 let closure: &mut F = unsafe { context.as_mut().unwrap_unchecked() };
316
317 let (obj1, obj2) = unsafe { (obj1.as_ref(), obj2.as_ref()) };
319
320 Foundation::NSComparisonResult::from((*closure)(obj1, obj2)) as _
321 }
322
323 let f: unsafe extern "C" fn(_, _, _) -> _ = compare_with_closure::<T, F>;
325
326 let mut closure = compare;
328 let context: *mut F = &mut closure;
329
330 unsafe { self.sortUsingFunction_context(f, context.cast()) };
331 drop(closure);
333 }
334}
335
336impl<T: Message> NSArray<T> {
337 #[doc(alias = "objectEnumerator")]
338 #[inline]
339 pub fn iter(&self) -> Iter<'_, T> {
340 Iter(super::iter::Iter::new(self))
341 }
342
343 #[doc(alias = "objectEnumerator")]
344 #[inline]
345 pub fn iter_mut(&mut self) -> IterMut<'_, T>
346 where
347 T: IsMutable,
348 {
349 IterMut(super::iter::IterMut::new(self))
350 }
351
352 #[doc(alias = "objectEnumerator")]
353 #[inline]
354 pub fn iter_retained(&self) -> IterRetained<'_, T>
355 where
356 T: IsIdCloneable,
357 {
358 IterRetained(super::iter::IterRetained::new(self))
359 }
360}
361
362unsafe impl<T: Message> iter::FastEnumerationHelper for NSArray<T> {
363 type Item = T;
364
365 #[inline]
366 fn maybe_len(&self) -> Option<usize> {
367 Some(self.len())
368 }
369}
370
371#[cfg(feature = "Foundation_NSMutableArray")]
372unsafe impl<T: Message> iter::FastEnumerationHelper for NSMutableArray<T> {
373 type Item = T;
374
375 #[inline]
376 fn maybe_len(&self) -> Option<usize> {
377 Some(self.len())
378 }
379}
380
381#[derive(Debug)]
383pub struct Iter<'a, T: Message>(iter::Iter<'a, NSArray<T>>);
384
385__impl_iter! {
386 impl<'a, T: Message> Iterator<Item = &'a T> for Iter<'a, T> { ... }
387}
388
389#[derive(Debug)]
391pub struct IterMut<'a, T: Message>(iter::IterMut<'a, NSArray<T>>);
392
393__impl_iter! {
394 impl<'a, T: Message + IsMutable> Iterator<Item = &'a mut T> for IterMut<'a, T> { ... }
395}
396
397#[derive(Debug)]
399pub struct IterRetained<'a, T: Message>(iter::IterRetained<'a, NSArray<T>>);
400
401__impl_iter! {
402 impl<'a, T: Message + IsIdCloneable> Iterator<Item = Id<T>> for IterRetained<'a, T> { ... }
403}
404
405#[derive(Debug)]
407pub struct IntoIter<T: Message>(iter::IntoIter<NSArray<T>>);
408
409__impl_iter! {
410 impl<'a, T: Message> Iterator<Item = Id<T>> for IntoIter<T> { ... }
411}
412
413__impl_into_iter! {
414 impl<T: Message> IntoIterator for &NSArray<T> {
415 type IntoIter = Iter<'_, T>;
416 }
417
418 #[cfg(feature = "Foundation_NSMutableArray")]
419 impl<T: Message> IntoIterator for &NSMutableArray<T> {
420 type IntoIter = Iter<'_, T>;
421 }
422
423 impl<T: Message + IsMutable> IntoIterator for &mut NSArray<T> {
424 type IntoIter = IterMut<'_, T>;
425 }
426
427 #[cfg(feature = "Foundation_NSMutableArray")]
428 impl<T: Message + IsMutable> IntoIterator for &mut NSMutableArray<T> {
429 type IntoIter = IterMut<'_, T>;
430 }
431
432 impl<T: Message + IsIdCloneable> IntoIterator for Id<NSArray<T>> {
433 type IntoIter = IntoIter<T>;
434 }
435
436 #[cfg(feature = "Foundation_NSMutableArray")]
437 impl<T: Message> IntoIterator for Id<NSMutableArray<T>> {
438 type IntoIter = IntoIter<T>;
439 }
440}
441
442impl<T: Message> Index<usize> for NSArray<T> {
443 type Output = T;
444
445 fn index(&self, index: usize) -> &T {
446 self.get(index).unwrap()
447 }
448}
449
450#[cfg(feature = "Foundation_NSMutableArray")]
451impl<T: Message> Index<usize> for NSMutableArray<T> {
452 type Output = T;
453
454 fn index(&self, index: usize) -> &T {
455 self.get(index).unwrap()
456 }
457}
458
459impl<T: Message + IsMutable> IndexMut<usize> for NSArray<T> {
460 fn index_mut(&mut self, index: usize) -> &mut T {
461 self.get_mut(index).unwrap()
462 }
463}
464
465#[cfg(feature = "Foundation_NSMutableArray")]
466impl<T: Message + IsMutable> IndexMut<usize> for NSMutableArray<T> {
467 fn index_mut(&mut self, index: usize) -> &mut T {
468 self.get_mut(index).unwrap()
469 }
470}
471
472impl<T: fmt::Debug + Message> fmt::Debug for NSArray<T> {
473 #[inline]
474 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
475 f.debug_list().entries(self).finish()
476 }
477}
478
479#[cfg(feature = "Foundation_NSMutableArray")]
480impl<T: Message> Extend<Id<T>> for NSMutableArray<T> {
481 fn extend<I: IntoIterator<Item = Id<T>>>(&mut self, iter: I) {
482 iter.into_iter().for_each(move |item| self.push(item))
483 }
484}
485
486#[cfg(feature = "Foundation_NSMutableArray")]
487impl<'a, T: Message + IsRetainable> Extend<&'a T> for NSMutableArray<T> {
488 fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
489 iter.into_iter()
492 .for_each(move |item| unsafe { self.addObject(item) })
493 }
494}
495
496impl<'a, T: Message + IsRetainable + 'a> IdFromIterator<&'a T> for NSArray<T> {
497 fn id_from_iter<I: IntoIterator<Item = &'a T>>(iter: I) -> Id<Self> {
498 let vec = Vec::from_iter(iter);
499 Self::from_slice(&vec)
500 }
501}
502
503impl<T: Message> IdFromIterator<Id<T>> for NSArray<T> {
504 fn id_from_iter<I: IntoIterator<Item = Id<T>>>(iter: I) -> Id<Self> {
505 let vec = Vec::from_iter(iter);
506 Self::from_vec(vec)
507 }
508}
509
510#[cfg(feature = "Foundation_NSMutableArray")]
511impl<'a, T: Message + IsRetainable + 'a> IdFromIterator<&'a T> for NSMutableArray<T> {
512 fn id_from_iter<I: IntoIterator<Item = &'a T>>(iter: I) -> Id<Self> {
513 let vec = Vec::from_iter(iter);
514 Self::from_slice(&vec)
515 }
516}
517
518#[cfg(feature = "Foundation_NSMutableArray")]
519impl<T: Message> IdFromIterator<Id<T>> for NSMutableArray<T> {
520 fn id_from_iter<I: IntoIterator<Item = Id<T>>>(iter: I) -> Id<Self> {
521 let vec = Vec::from_iter(iter);
522 Self::from_vec(vec)
523 }
524}