objc2_foundation/
array.rs1use alloc::vec::Vec;
3#[cfg(feature = "NSEnumerator")]
4use core::fmt;
5use core::mem;
6use core::ptr::NonNull;
7
8use objc2::rc::{Retained, RetainedFromIterator};
9use objc2::{msg_send, AnyThread, Message};
10
11#[cfg(feature = "NSEnumerator")]
12use crate::iter;
13use crate::{util, NSArray, NSMutableArray};
14
15impl<ObjectType: Message> NSArray<ObjectType> {
17 #[doc(alias = "initWithObjects:count:")]
33 pub fn from_slice(slice: &[&ObjectType]) -> Retained<Self> {
34 let len = slice.len();
35 let ptr = util::ref_ptr_cast_const(slice.as_ptr());
36 unsafe { Self::initWithObjects_count(Self::alloc(), ptr, len) }
43 }
44
45 #[doc(alias = "initWithObjects:count:")]
61 pub fn from_retained_slice(slice: &[Retained<ObjectType>]) -> Retained<Self> {
62 let len = slice.len();
63 let ptr = util::retained_ptr_cast_const(slice.as_ptr());
64 unsafe { Self::initWithObjects_count(Self::alloc(), ptr, len) }
70 }
71}
72
73impl<ObjectType: Message> NSMutableArray<ObjectType> {
75 #[doc(alias = "initWithObjects:count:")]
76 pub fn from_slice(slice: &[&ObjectType]) -> Retained<Self> {
77 let len = slice.len();
78 let ptr = util::ref_ptr_cast_const(slice.as_ptr());
79 unsafe { Self::initWithObjects_count(Self::alloc(), ptr, len) }
81 }
82
83 #[doc(alias = "initWithObjects:count:")]
84 pub fn from_retained_slice(slice: &[Retained<ObjectType>]) -> Retained<Self> {
85 let len = slice.len();
86 let ptr = util::retained_ptr_cast_const(slice.as_ptr());
87 unsafe { Self::initWithObjects_count(Self::alloc(), ptr, len) }
89 }
90}
91
92impl<ObjectType: Message> NSArray<ObjectType> {
104 #[doc(alias = "objectAtIndex:")]
115 #[inline]
116 pub unsafe fn objectAtIndex_unchecked(&self, index: usize) -> &ObjectType {
117 unsafe { msg_send![self, objectAtIndex: index] }
119 }
120
121 #[doc(alias = "firstObject")]
130 #[inline]
131 pub unsafe fn firstObject_unchecked(&self) -> Option<&ObjectType> {
132 unsafe { msg_send![self, firstObject] }
134 }
135
136 #[doc(alias = "lastObject")]
145 #[inline]
146 pub unsafe fn lastObject_unchecked(&self) -> Option<&ObjectType> {
147 unsafe { msg_send![self, lastObject] }
149 }
150
151 #[doc(alias = "getObjects:")]
160 pub unsafe fn to_vec_unchecked(&self) -> Vec<&ObjectType> {
161 let len = self.count();
162 let mut vec: Vec<NonNull<ObjectType>> = Vec::with_capacity(len);
163 let ptr: NonNull<NonNull<ObjectType>> = NonNull::new(vec.as_mut_ptr()).unwrap();
164
165 unsafe {
168 #[allow(deprecated)]
169 self.getObjects(ptr)
170 };
171
172 unsafe { vec.set_len(len) };
178
179 unsafe { mem::transmute::<Vec<NonNull<ObjectType>>, Vec<&ObjectType>>(vec) }
183 }
184
185 #[cfg(feature = "NSEnumerator")]
195 #[doc(alias = "objectEnumerator")]
196 #[inline]
197 pub unsafe fn iter_unchecked(&self) -> IterUnchecked<'_, ObjectType> {
198 IterUnchecked(iter::IterUnchecked::new(self))
199 }
200}
201
202impl<ObjectType: Message> NSArray<ObjectType> {
204 #[doc(alias = "count")]
206 #[inline]
207 pub fn len(&self) -> usize {
208 self.count()
209 }
210
211 #[inline]
213 pub fn is_empty(&self) -> bool {
214 self.len() == 0
215 }
216
217 #[doc(alias = "getObjects:")]
219 pub fn to_vec(&self) -> Vec<Retained<ObjectType>> {
220 let vec = unsafe { self.to_vec_unchecked() };
228 vec.into_iter().map(ObjectType::retain).collect()
229 }
230
231 #[cfg(feature = "NSEnumerator")]
233 #[doc(alias = "objectEnumerator")]
234 #[inline]
235 pub fn iter(&self) -> Iter<'_, ObjectType> {
236 Iter(iter::Iter::new(self))
237 }
238
239 #[doc(alias = "getObjects:range:")]
245 #[cfg(feature = "NSRange")]
246 pub fn objects_in_range(&self, range: core::ops::Range<usize>) -> Vec<Retained<ObjectType>> {
247 let count = self.count();
248
249 if range.end > count {
251 panic!(
252 "range end index {} out of range for array of length {}",
253 range.end, count
254 );
255 }
256
257 let range = crate::NSRange::from(range);
258 let mut vec: Vec<NonNull<ObjectType>> = Vec::with_capacity(range.length);
259 let ptr: NonNull<NonNull<ObjectType>> = NonNull::new(vec.as_mut_ptr()).unwrap();
260
261 unsafe { self.getObjects_range(ptr, range) };
263 unsafe { vec.set_len(range.length) };
264 let vec = unsafe { mem::transmute::<Vec<NonNull<ObjectType>>, Vec<&ObjectType>>(vec) };
265
266 vec.into_iter().map(ObjectType::retain).collect()
267 }
268}
269
270impl<ObjectType: Message> NSMutableArray<ObjectType> {
272 #[doc(alias = "insertObject:atIndex:")]
278 pub fn insert(&self, index: usize, obj: &ObjectType) {
279 let len = self.len();
281 if index <= len {
282 self.insertObject_atIndex(obj, index)
283 } else {
284 panic!(
285 "insertion index (is {}) should be <= len (is {})",
286 index, len
287 );
288 }
289 }
290
291 #[cfg(feature = "NSObjCRuntime")]
293 #[doc(alias = "sortUsingFunction:context:")]
294 pub fn sort_by<F: FnMut(&ObjectType, &ObjectType) -> core::cmp::Ordering>(&self, compare: F) {
295 unsafe extern "C-unwind" fn compare_with_closure<
296 ObjectType,
297 F: FnMut(&ObjectType, &ObjectType) -> core::cmp::Ordering,
298 >(
299 obj1: core::ptr::NonNull<ObjectType>,
300 obj2: core::ptr::NonNull<ObjectType>,
301 context: *mut core::ffi::c_void,
302 ) -> isize {
303 let context: *mut F = context.cast();
304 let closure: &mut F = unsafe { context.as_mut().unwrap_unchecked() };
308
309 let (obj1, obj2) = unsafe { (obj1.as_ref(), obj2.as_ref()) };
311
312 crate::NSComparisonResult::from((*closure)(obj1, obj2)) as _
313 }
314
315 let f: unsafe extern "C-unwind" fn(_, _, _) -> _ = compare_with_closure::<ObjectType, F>;
317
318 let mut closure = compare;
320 let context: *mut F = &mut closure;
321
322 unsafe { self.sortUsingFunction_context(f, context.cast()) };
323 drop(closure);
325 }
326}
327
328#[cfg(feature = "NSEnumerator")]
329unsafe impl<ObjectType: Message> iter::FastEnumerationHelper for NSArray<ObjectType> {
330 type Item = ObjectType;
331
332 #[inline]
333 fn maybe_len(&self) -> Option<usize> {
334 Some(self.len())
335 }
336}
337
338#[cfg(feature = "NSEnumerator")]
339unsafe impl<ObjectType: Message> iter::FastEnumerationHelper for NSMutableArray<ObjectType> {
340 type Item = ObjectType;
341
342 #[inline]
343 fn maybe_len(&self) -> Option<usize> {
344 Some(self.len())
345 }
346}
347
348#[derive(Debug)]
350#[cfg(feature = "NSEnumerator")]
351pub struct Iter<'a, ObjectType: Message>(iter::Iter<'a, NSArray<ObjectType>>);
352
353#[cfg(feature = "NSEnumerator")]
354__impl_iter! {
355 impl<'a, ObjectType: Message> Iterator<Item = Retained<ObjectType>> for Iter<'a, ObjectType> { ... }
356}
357
358#[derive(Debug)]
364#[cfg(feature = "NSEnumerator")]
365pub struct IterUnchecked<'a, ObjectType: Message>(iter::IterUnchecked<'a, NSArray<ObjectType>>);
366
367#[cfg(feature = "NSEnumerator")]
368__impl_iter! {
369 impl<'a, ObjectType: Message> Iterator<Item = &'a ObjectType> for IterUnchecked<'a, ObjectType> { ... }
370}
371
372#[derive(Debug)]
374#[cfg(feature = "NSEnumerator")]
375pub struct IntoIter<ObjectType: Message>(iter::IntoIter<NSArray<ObjectType>>);
376
377#[cfg(feature = "NSEnumerator")]
378__impl_iter! {
379 impl<ObjectType: Message> Iterator<Item = Retained<ObjectType>> for IntoIter<ObjectType> { ... }
380}
381
382#[cfg(feature = "NSEnumerator")]
383__impl_into_iter! {
384 impl<ObjectType: Message> IntoIterator for &NSArray<ObjectType> {
385 type IntoIter = Iter<'_, ObjectType>;
386 }
387
388 impl<ObjectType: Message> IntoIterator for &NSMutableArray<ObjectType> {
389 type IntoIter = Iter<'_, ObjectType>;
390 }
391
392 impl<ObjectType: Message> IntoIterator for Retained<NSArray<ObjectType>> {
393 #[uses(new)]
394 type IntoIter = IntoIter<ObjectType>;
395 }
396
397 impl<ObjectType: Message> IntoIterator for Retained<NSMutableArray<ObjectType>> {
398 #[uses(new_mutable)]
399 type IntoIter = IntoIter<ObjectType>;
400 }
401}
402
403#[cfg(feature = "NSEnumerator")]
404impl<ObjectType: fmt::Debug + Message> fmt::Debug for NSArray<ObjectType> {
405 #[inline]
406 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
407 f.debug_list().entries(self).finish()
408 }
409}
410
411#[cfg(feature = "NSEnumerator")]
412impl<ObjectType: fmt::Debug + Message> fmt::Debug for NSMutableArray<ObjectType> {
413 #[inline]
414 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
415 fmt::Debug::fmt(&**self, f)
416 }
417}
418
419impl<ObjectType: Message> Extend<Retained<ObjectType>> for &NSMutableArray<ObjectType> {
420 fn extend<I: IntoIterator<Item = Retained<ObjectType>>>(&mut self, iter: I) {
421 iter.into_iter().for_each(move |item| self.addObject(&item));
422 }
423}
424
425impl<'a, ObjectType: Message> Extend<&'a ObjectType> for &NSMutableArray<ObjectType> {
426 fn extend<I: IntoIterator<Item = &'a ObjectType>>(&mut self, iter: I) {
427 iter.into_iter().for_each(move |item| self.addObject(item));
428 }
429}
430
431impl<'a, ObjectType: Message + 'a> RetainedFromIterator<&'a ObjectType> for NSArray<ObjectType> {
432 fn retained_from_iter<I: IntoIterator<Item = &'a ObjectType>>(iter: I) -> Retained<Self> {
433 let vec = Vec::from_iter(iter);
434 Self::from_slice(&vec)
435 }
436}
437
438impl<ObjectType: Message> RetainedFromIterator<Retained<ObjectType>> for NSArray<ObjectType> {
439 fn retained_from_iter<I: IntoIterator<Item = Retained<ObjectType>>>(iter: I) -> Retained<Self> {
440 let vec = Vec::from_iter(iter);
441 Self::from_retained_slice(&vec)
442 }
443}
444
445impl<'a, ObjectType: Message + 'a> RetainedFromIterator<&'a ObjectType>
446 for NSMutableArray<ObjectType>
447{
448 fn retained_from_iter<I: IntoIterator<Item = &'a ObjectType>>(iter: I) -> Retained<Self> {
449 let vec = Vec::from_iter(iter);
451 Self::from_slice(&vec)
452 }
453}
454
455impl<ObjectType: Message> RetainedFromIterator<Retained<ObjectType>>
456 for NSMutableArray<ObjectType>
457{
458 fn retained_from_iter<I: IntoIterator<Item = Retained<ObjectType>>>(iter: I) -> Retained<Self> {
459 let vec = Vec::from_iter(iter);
461 Self::from_retained_slice(&vec)
462 }
463}