1use std::{marker::PhantomData, slice};
2
3use libc::c_char;
4use objc::{class, msg_send, runtime::Object, sel, sel_impl};
5
6use crate::{
7 foundation::NSString,
8 object,
9 objective_c_runtime::{
10 id,
11 traits::{FromId, PNSObject},
12 },
13 utils::to_bool,
14};
15
16use self::iter::Iter;
17
18use super::{ns_mutable_array::NSMutableArray, NSLocale, NSNumber, NSRange, UInt, UInt8};
19
20pub mod iter;
22
23object! {
24 unsafe pub struct NSArray<T> {
26 _marker: PhantomData<T>,
27 }
28}
29
30impl<T> NSArray<T> {
31 pub fn iter(&self) -> Iter<'_, T>
33 where
34 T: PNSObject,
35 {
36 Iter {
37 array: self,
38 index: 0,
39 }
40 }
41}
42
43impl<T> NSArray<T> {
44 pub fn new() -> Self {
46 NSArray::m_new()
47 }
48
49 pub fn contains(&self, object: T) -> bool
51 where
52 T: PNSObject,
53 {
54 self.m_contains_object(object)
55 }
56
57 pub fn count(&self) -> u64 {
59 self.p_count()
60 }
61}
62
63pub trait INSArray<T>: PNSObject {
65 fn m_contains_object(&self, object: T) -> bool {
79 unsafe { to_bool(msg_send![self.m_self(), containsObject: object]) }
80 }
81
82 fn p_count(&self) -> UInt {
84 unsafe { msg_send![self.m_self(), count] }
85 }
86
87 fn p_first_object(&self) -> Option<T>
89 where
90 T: PNSObject + FromId,
91 {
92 unsafe {
93 let id: id = msg_send![self.m_self(), firstObject];
94 if id.is_null() {
95 None
96 } else {
97 Some(T::from_id(id))
98 }
99 }
100 }
101
102 fn p_last_object(&self) -> Option<T>
104 where
105 T: PNSObject + FromId,
106 {
107 unsafe {
108 let id: id = msg_send![self.m_self(), lastObject];
109 if id.is_null() {
110 None
111 } else {
112 Some(T::from_id(id))
113 }
114 }
115 }
116
117 fn m_object_at_index(&self, index: UInt) -> T
119 where
120 T: PNSObject + FromId,
121 {
122 unsafe { T::from_id(msg_send![self.m_self(), objectAtIndex: index]) }
123 }
124
125 fn m_object_at_indexed_subscript(&self, index: UInt) -> Option<id> {
127 unsafe {
128 let id: id = msg_send![self.m_self(), objectAtIndexedSubscript: index];
129 if id.is_null() {
130 None
131 } else {
132 Some(id)
133 }
134 }
135 }
136
137 fn m_index_of_object(&self, object: T) -> UInt {
142 unsafe { msg_send![self.m_self(), indexOfObject: object] }
143 }
144
145 fn m_index_of_object_in_range(&self, object: T, range: NSRange) -> UInt {
147 unsafe { msg_send![self.m_self(), indexOfObject: object inRange: range] }
148 }
149
150 fn m_index_of_object_identical_to(&self, object: T) -> UInt {
152 unsafe { msg_send![self.m_self(), indexOfObjectIdenticalTo: object] }
153 }
154
155 fn m_index_of_object_identical_to_in_range(&self, object: T, range: NSRange) -> UInt {
157 unsafe { msg_send![self.m_self(), indexOfObjectIdenticalTo: object inRange: range] }
158 }
159
160 fn m_first_object_common_with_array(&self, other: &NSArray<T>) -> Option<T>
165 where
166 T: PNSObject + FromId,
167 {
168 unsafe {
169 let id: id = msg_send![self.m_self(), firstObjectCommonWithArray: other.m_self()];
170 if id.is_null() {
171 None
172 } else {
173 Some(T::from_id(id))
174 }
175 }
176 }
177
178 fn m_is_equal_to_array(&self, other: &NSArray<T>) -> bool {
180 unsafe { to_bool(msg_send![self.m_self(), isEqualToArray: other.m_self()]) }
181 }
182
183 unsafe fn m_array_by_adding_object(&self, object: T) -> NSArray<T> {
192 NSArray::from_id(msg_send![self.m_self(), arrayByAddingObject: object])
193 }
194
195 unsafe fn m_array_by_adding_objects_from_array<A>(&self, objects: A) -> NSArray<T>
201 where
202 A: INSArray<T>,
203 {
204 NSArray::from_id(msg_send![self.m_self(), arrayByAddingObjectsFromArray: objects.m_self()])
205 }
206
207 unsafe fn m_subarray_with_range(&self, range: NSRange) -> NSArray<T> {
213 NSArray::from_id(msg_send![self.m_self(), subarrayWithRange: range])
214 }
215 fn m_description_with_locale(&self, locale: &NSLocale) -> NSString {
222 unsafe { msg_send![self.m_self(), descriptionWithLocale: locale.m_self()] }
223 }
224
225 fn m_description_with_locale_indent(&self, locale: &NSLocale, indent: UInt) -> NSString {
227 unsafe { msg_send![self.m_self(), descriptionWithLocale: locale.m_self() indent: indent] }
228 }
229}
230
231impl<T> INSArray<T> for NSArray<T> {}
232
233impl<T> Default for NSArray<T> {
234 fn default() -> Self {
235 Self::m_new()
236 }
237}
238
239impl<'a, T> IntoIterator for &'a NSArray<T>
240where
241 T: PNSObject + FromId,
242{
243 type Item = T;
244 type IntoIter = Iter<'a, T>;
245
246 fn into_iter(self) -> Self::IntoIter {
247 self.iter()
248 }
249}
250
251impl From<(*const c_char, usize)> for NSArray<UInt8> {
252 fn from((s, i): (*const c_char, usize)) -> Self {
253 let v = unsafe { slice::from_raw_parts(s as *const u8, i) };
254 NSArray::from(v)
255 }
256}
257
258impl<T> From<id> for NSArray<T> {
259 #[allow(clippy::not_unsafe_ptr_arg_deref)]
260 fn from(obj: id) -> Self {
261 unsafe { NSArray::from_id(obj) }
262 }
263}
264
265impl<T> From<&[T]> for NSArray<T>
266where
267 T: PNSObject,
268{
269 fn from(array: &[T]) -> Self {
270 unsafe {
271 let cls: *mut Object = msg_send![class!(NSArray),
272 arrayWithObjects:array.as_ptr()
273 count:array.len()
274 ];
275 NSArray::from(cls)
276 }
277 }
278}
279
280impl<T> From<Vec<T>> for NSArray<T>
281where
282 T: PNSObject,
283{
284 fn from(objects: Vec<T>) -> Self {
286 unsafe {
287 let cls: id = msg_send![class!(NSArray),
288 arrayWithObjects:objects.as_ptr()
289 count:objects.len()
290 ];
291 NSArray::from(cls)
292 }
293 }
294}
295
296impl From<Vec<i8>> for NSArray<NSNumber> {
297 fn from(objects: Vec<i8>) -> Self {
299 let objects: Vec<NSNumber> = objects.iter().map(|i| NSNumber::from(*i)).collect();
300 unsafe {
301 let cls: id = msg_send![class!(NSArray),
302 arrayWithObjects:objects.as_ptr()
303 count:objects.len()
304 ];
305 NSArray::from(cls)
306 }
307 }
308}
309
310impl From<Vec<i16>> for NSArray<NSNumber> {
311 fn from(objects: Vec<i16>) -> Self {
313 let objects: Vec<NSNumber> = objects.iter().map(|i| NSNumber::from(*i)).collect();
314 unsafe {
315 let cls: id = msg_send![class!(NSArray),
316 arrayWithObjects:objects.as_ptr()
317 count:objects.len()
318 ];
319 NSArray::from(cls)
320 }
321 }
322}
323
324impl From<Vec<i32>> for NSArray<NSNumber> {
325 fn from(objects: Vec<i32>) -> Self {
327 let objects: Vec<NSNumber> = objects.iter().map(|i| NSNumber::from(*i)).collect();
328 unsafe {
329 let cls: id = msg_send![class!(NSArray),
330 arrayWithObjects:objects.as_ptr()
331 count:objects.len()
332 ];
333 NSArray::from(cls)
334 }
335 }
336}
337
338impl From<Vec<i64>> for NSArray<NSNumber> {
339 fn from(objects: Vec<i64>) -> Self {
341 let objects: Vec<NSNumber> = objects.iter().map(|i| NSNumber::from(*i)).collect();
342 unsafe {
343 let cls: id = msg_send![class!(NSArray),
344 arrayWithObjects:objects.as_ptr()
345 count:objects.len()
346 ];
347 NSArray::from(cls)
348 }
349 }
350}
351
352impl From<Vec<u8>> for NSArray<NSNumber> {
353 fn from(objects: Vec<u8>) -> Self {
355 let objects: Vec<NSNumber> = objects.iter().map(|i| NSNumber::from(*i)).collect();
356 unsafe {
357 let cls: id = msg_send![class!(NSArray),
358 arrayWithObjects:objects.as_ptr()
359 count:objects.len()
360 ];
361 NSArray::from(cls)
362 }
363 }
364}
365
366impl From<Vec<u16>> for NSArray<NSNumber> {
367 fn from(objects: Vec<u16>) -> Self {
369 let objects: Vec<NSNumber> = objects.iter().map(|i| NSNumber::from(*i)).collect();
370 unsafe {
371 let cls: id = msg_send![class!(NSArray),
372 arrayWithObjects:objects.as_ptr()
373 count:objects.len()
374 ];
375 NSArray::from(cls)
376 }
377 }
378}
379
380impl From<Vec<u32>> for NSArray<NSNumber> {
381 fn from(objects: Vec<u32>) -> Self {
383 let objects: Vec<NSNumber> = objects.iter().map(|i| NSNumber::from(*i)).collect();
384 unsafe {
385 let cls: id = msg_send![class!(NSArray),
386 arrayWithObjects:objects.as_ptr()
387 count:objects.len()
388 ];
389 NSArray::from(cls)
390 }
391 }
392}
393
394impl From<Vec<u64>> for NSArray<NSNumber> {
395 fn from(objects: Vec<u64>) -> Self {
397 let objects: Vec<NSNumber> = objects.iter().map(|i| NSNumber::from(*i)).collect();
398 unsafe {
399 let cls: id = msg_send![class!(NSArray),
400 arrayWithObjects:objects.as_ptr()
401 count:objects.len()
402 ];
403 NSArray::from(cls)
404 }
405 }
406}
407
408impl From<&[u8]> for NSArray<u8> {
409 fn from(objects: &[u8]) -> Self {
411 unsafe {
412 let cls: id = msg_send![class!(NSArray),
413 arrayWithObjects:objects.as_ptr()
414 count:objects.len()
415 ];
416 NSArray::from(cls)
417 }
418 }
419}
420
421impl From<&[id]> for NSArray<u8> {
422 fn from(objects: &[id]) -> Self {
424 unsafe {
425 let cls: id = msg_send![class!(NSArray),
426 arrayWithObjects:objects.as_ptr()
427 count:objects.len()
428 ];
429 NSArray::from(cls)
430 }
431 }
432}
433
434impl From<Vec<id>> for NSArray<id> {
435 fn from(objects: Vec<id>) -> Self {
437 unsafe {
438 let cls: id = msg_send![class!(NSArray),
439 arrayWithObjects:objects.as_ptr()
440 count:objects.len()
441 ];
442 NSArray::from_id(cls)
443 }
444 }
445}
446
447impl From<Vec<&str>> for NSArray<NSString> {
448 fn from(objects: Vec<&str>) -> Self {
449 let objects: Vec<NSString> = objects.iter().map(|s| NSString::from(*s)).collect();
450 unsafe {
451 let cls: id = msg_send![class!(NSArray),
452 arrayWithObjects:objects.as_ptr()
453 count:objects.len()
454 ];
455 NSArray::from(cls)
456 }
457 }
458}
459
460impl From<Vec<String>> for NSArray<NSString> {
461 fn from(objects: Vec<String>) -> Self {
462 let objects: Vec<NSString> = objects.iter().map(|s| NSString::from(s.clone())).collect();
463 unsafe {
464 let cls: id = msg_send![class!(NSArray),
465 arrayWithObjects:objects.as_ptr()
466 count:objects.len()
467 ];
468 NSArray::from(cls)
469 }
470 }
471}
472
473impl<T> From<NSMutableArray<T>> for NSArray<T>
474where
475 T: PNSObject,
476{
477 fn from(array: NSMutableArray<T>) -> Self {
479 let cls: id = unsafe {
480 {
481 msg_send![class!(NSArray), arrayWithArray: array]
482 }
483 };
484 NSArray::from(cls)
485 }
486}
487
488#[cfg(test)]
489mod tests {
490 use super::*;
491
492 #[test]
493 fn test_array_from_vec() {
494 let array: NSArray<NSString> = vec!["foo", "bar"].into();
495 assert_eq!(array.count(), 2);
496 assert_eq!(array.m_object_at_index(0), NSString::from("foo"));
497 assert_eq!(array.m_object_at_index(1), NSString::from("bar"));
498 }
499
500 #[test]
501 fn test_first_common_object() {
502 let array: NSArray<NSString> = vec!["foo", "bar"].into();
503 let array2: NSArray<NSString> = vec!["foo", "bar"].into();
504 assert_eq!(
505 array.m_first_object_common_with_array(&array2),
506 Some(NSString::from("foo"))
507 );
508 }
509}