diff --git a/objc2_foundation/examples/basic_usage.rs b/objc2_foundation/examples/basic_usage.rs index 6af8fb83c..b6af189b5 100644 --- a/objc2_foundation/examples/basic_usage.rs +++ b/objc2_foundation/examples/basic_usage.rs @@ -1,3 +1,4 @@ +use objc2::rc::{FromId, Id, IntoId}; use objc2_foundation::{ INSArray, INSCopying, INSDictionary, INSObject, INSString, NSArray, NSDictionary, NSObject, NSString, @@ -13,14 +14,14 @@ fn main() { // Create an NSArray from a Vec let objs = vec![obj, obj2]; - let array = NSArray::from_vec(objs); + let array: Id, _> = objs.into_id(); for obj in array.object_enumerator() { println!("{:?}", obj); } println!("{}", array.count()); // Turn the NSArray back into a Vec - let mut objs = NSArray::into_vec(array); + let mut objs = Vec::from_id(array); let obj = objs.pop().unwrap(); // Create an NSString from a str slice diff --git a/objc2_foundation/src/array.rs b/objc2_foundation/src/array.rs index d1b6dcb97..2e705b58b 100644 --- a/objc2_foundation/src/array.rs +++ b/objc2_foundation/src/array.rs @@ -5,7 +5,7 @@ use core::marker::PhantomData; use core::ops::{Index, Range}; use core::ptr::NonNull; -use objc2::rc::{Id, Owned, Ownership, Shared, SliceId}; +use objc2::rc::{FromId, Id, IntoId, Owned, Ownership, Shared, SliceId}; use objc2::runtime::{Class, Object}; use objc2::{class, msg_send}; use objc2::{Encode, Encoding}; @@ -129,10 +129,6 @@ pub trait INSArray: INSObject { } } - fn from_vec(vec: Vec>) -> Id { - unsafe { from_refs(vec.as_slice_ref()) } - } - fn objects_in_range(&self, range: Range) -> Vec<&Self::Item> { let range = NSRange::from_range(range); let mut vec = Vec::with_capacity(range.length); @@ -143,18 +139,6 @@ pub trait INSArray: INSObject { vec } - fn to_vec(&self) -> Vec<&Self::Item> { - self.objects_in_range(0..self.count()) - } - - fn into_vec(array: Id) -> Vec> { - array - .to_vec() - .into_iter() - .map(|obj| unsafe { Id::retain(obj.into()) }) - .collect() - } - fn mut_object_at(&mut self, index: usize) -> &mut Self::Item where Self: INSArray, @@ -179,16 +163,6 @@ pub trait INSArray: INSObject { { unsafe { from_refs(slice.as_slice_ref()) } } - - fn to_shared_vec(&self) -> Vec> - where - Self: INSArray, - { - self.to_vec() - .into_iter() - .map(|obj| unsafe { Id::retain(obj.into()) }) - .collect() - } } pub struct NSArray { @@ -250,6 +224,52 @@ where } } +impl FromId, Owned> for Vec> +where + T: INSObject, + O: Ownership, +{ + fn from_id(array: Id, Owned>) -> Self { + let vec: Vec<&T> = (&*array).into(); + vec.into_iter() + .map(|obj| unsafe { Id::retain(obj.into()) }) + .collect() + } +} + +impl IntoId, Owned> for Vec> +where + T: INSObject, + O: Ownership, +{ + fn into_id(self) -> Id, Owned> { + unsafe { from_refs(self.as_slice_ref()) } + } +} + +impl<'a, T, O> From<&'a NSArray> for Vec<&'a T> +where + T: INSObject, + O: Ownership, +{ + fn from(array: &'a NSArray) -> Self { + array.objects_in_range(0..array.count()) + } +} + +impl From<&'_ NSArray> for Vec> +where + T: INSObject, +{ + fn from(array: &NSArray) -> Self { + array + .objects_in_range(0..array.count()) + .into_iter() + .map(|obj| unsafe { Id::retain(obj.into()) }) + .collect() + } +} + pub type NSSharedArray = NSArray; pub trait INSMutableArray: INSArray { @@ -410,6 +430,16 @@ where } } +impl IntoId, Owned> for Vec> +where + T: INSObject, + O: Ownership, +{ + fn into_id(self) -> Id, Owned> { + unsafe { from_refs(self.as_slice_ref()) } + } +} + pub type NSMutableSharedArray = NSMutableArray; #[cfg(test)] @@ -419,14 +449,14 @@ mod tests { use super::{INSArray, INSMutableArray, NSArray, NSMutableArray}; use crate::{INSObject, INSString, NSObject, NSString}; - use objc2::rc::{Id, Owned}; + use objc2::rc::{FromId, Id, IntoId, Owned}; fn sample_array(len: usize) -> Id, Owned> { let mut vec = Vec::with_capacity(len); for _ in 0..len { vec.push(NSObject::new()); } - NSArray::from_vec(vec) + vec.into_id() } #[test] @@ -481,7 +511,7 @@ mod tests { fn test_into_vec() { let array = sample_array(4); - let vec = INSArray::into_vec(array); + let vec = Vec::from_id(array); assert!(vec.len() == 4); } @@ -530,7 +560,7 @@ mod tests { #[test] fn test_sort() { let strings = vec![NSString::from_str("hello"), NSString::from_str("hi")]; - let mut strings = NSMutableArray::from_vec(strings); + let mut strings: Vec<_> = strings.into(); strings.sort_by(|s1, s2| s1.as_str().len().cmp(&s2.as_str().len())); assert!(strings[0].as_str() == "hi"); diff --git a/objc2_foundation/src/enumerator.rs b/objc2_foundation/src/enumerator.rs index b1d1fedfe..d0b012932 100644 --- a/objc2_foundation/src/enumerator.rs +++ b/objc2_foundation/src/enumerator.rs @@ -184,13 +184,16 @@ impl<'a, C: INSFastEnumeration> Iterator for NSFastEnumerator<'a, C> { #[cfg(test)] mod tests { + use alloc::vec::Vec; + use objc2::rc::{Id, IntoId}; + use super::INSFastEnumeration; use crate::{INSArray, INSValue, NSArray, NSValue}; #[test] fn test_enumerator() { - let vec = (0u32..4).map(NSValue::from_value).collect(); - let array = NSArray::from_vec(vec); + let vec: Vec<_> = (0u32..4).map(NSValue::from_value).collect(); + let array: Id, _> = vec.into_id(); let enumerator = array.object_enumerator(); assert!(enumerator.count() == 4); @@ -203,8 +206,8 @@ mod tests { #[test] fn test_fast_enumerator() { - let vec = (0u32..4).map(NSValue::from_value).collect(); - let array = NSArray::from_vec(vec); + let vec: Vec<_> = (0u32..4).map(NSValue::from_value).collect(); + let array: Id, _> = vec.into_id(); let enumerator = array.enumerator(); assert!(enumerator.count() == 4);