Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use Id conversion traits on NSArray
Browse files Browse the repository at this point in the history
madsmtm committed Nov 2, 2021
1 parent 9c95e19 commit 522f93b
Showing 3 changed files with 69 additions and 37 deletions.
6 changes: 3 additions & 3 deletions objc2-foundation/examples/basic_usage.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use objc2::rc::autoreleasepool;
use objc2::rc::{autoreleasepool, FromId, Id, IntoId};
use objc2_foundation::{
INSArray, INSCopying, INSDictionary, INSString, NSArray, NSDictionary, NSObject, NSString,
};
@@ -13,14 +13,14 @@ fn main() {

// Create an NSArray from a Vec
let objs = vec![obj, obj2];
let array = NSArray::from_vec(objs);
let array: Id<NSArray<_, _>, _> = objs.into_id();
for obj in array.iter() {
println!("{:?}", obj);
}
println!("{}", array.len());

// 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
89 changes: 59 additions & 30 deletions objc2-foundation/src/array.rs
Original file line number Diff line number Diff line change
@@ -112,10 +112,6 @@ pub unsafe trait INSArray: INSObject {
}
}

fn from_vec(vec: Vec<Id<Self::Item, Self::ItemOwnership>>) -> Id<Self, Self::Ownership> {
unsafe { from_refs(vec.as_slice_ref()) }
}

fn objects_in_range(&self, range: Range<usize>) -> Vec<&Self::Item> {
let range = NSRange::from(range);
let mut vec = Vec::with_capacity(range.length);
@@ -126,35 +122,12 @@ pub unsafe trait INSArray: INSObject {
vec
}

fn to_vec(&self) -> Vec<&Self::Item> {
self.objects_in_range(0..self.len())
}

// TODO: Take Id<Self, Self::ItemOwnership> ?
fn into_vec(array: Id<Self, Owned>) -> Vec<Id<Self::Item, Self::ItemOwnership>> {
array
.to_vec()
.into_iter()
.map(|obj| unsafe { Id::retain(obj.into()) })
.collect()
}

fn from_slice(slice: &[Id<Self::Item, Shared>]) -> Id<Self, Self::Ownership>
where
Self: INSArray<ItemOwnership = Shared>,
{
unsafe { from_refs(slice.as_slice_ref()) }
}

fn to_shared_vec(&self) -> Vec<Id<Self::Item, Shared>>
where
Self: INSArray<ItemOwnership = Shared>,
{
self.to_vec()
.into_iter()
.map(|obj| unsafe { Id::retain(obj.into()) })
.collect()
}
}

/// TODO
@@ -211,6 +184,52 @@ impl<T: INSObject, O: Ownership> Index<usize> for NSArray<T, O> {
}
}

impl<T, O> FromId<NSArray<T, O>, Owned> for Vec<Id<T, O>>
where
T: INSObject,
O: Ownership,
{
fn from_id(array: Id<NSArray<T, O>, Owned>) -> Self {
let vec: Vec<&T> = (&*array).into();
vec.into_iter()
.map(|obj| unsafe { Id::retain(obj.into()) })
.collect()
}
}

impl<T, O> IntoId<NSArray<T, O>, Owned> for Vec<Id<T, O>>
where
T: INSObject,
O: Ownership,
{
fn into_id(self) -> Id<NSArray<T, O>, Owned> {
unsafe { from_refs(self.as_slice_ref()) }
}
}

impl<'a, T, O> From<&'a NSArray<T, O>> for Vec<&'a T>
where
T: INSObject,
O: Ownership,
{
fn from(array: &'a NSArray<T, O>) -> Self {
array.objects_in_range(0..array.count())
}
}

impl<T> From<&'_ NSArray<T, Shared>> for Vec<Id<T, Shared>>
where
T: INSObject,
{
fn from(array: &NSArray<T, Shared>) -> Self {
array
.objects_in_range(0..array.count())
.into_iter()
.map(|obj| unsafe { Id::retain(obj.into()) })
.collect()
}
}

pub unsafe trait INSMutableArray: INSArray {
#[doc(alias = "addObject:")]
fn push(&mut self, obj: Id<Self::Item, Self::ItemOwnership>) {
@@ -358,6 +377,16 @@ impl<T: INSObject, O: Ownership> Index<usize> for NSMutableArray<T, O> {
}
}

impl<T, O> IntoId<NSMutableArray<T, O>, Owned> for Vec<Id<T, O>>
where
T: INSObject,
O: Ownership,
{
fn into_id(self) -> Id<NSMutableArray<T, O>, Owned> {
unsafe { from_refs(self.as_slice_ref()) }
}
}

#[cfg(test)]
mod tests {
use alloc::vec;
@@ -374,7 +403,7 @@ mod tests {
for _ in 0..len {
vec.push(NSObject::new());
}
NSArray::from_vec(vec)
vec.into_id()
}

fn retain_count<T: INSObject>(obj: &T) -> usize {
@@ -455,7 +484,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_eq!(vec.len(), 4);
}

@@ -504,7 +533,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: Id<NSMutableArray<_, _>, Owned> = strings.into_id();

autoreleasepool(|pool| {
strings.sort_by(|s1, s2| s1.as_str(pool).len().cmp(&s2.as_str(pool).len()));
11 changes: 7 additions & 4 deletions objc2-foundation/src/enumerator.rs
Original file line number Diff line number Diff line change
@@ -169,13 +169,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::new).collect();
let array = NSArray::from_vec(vec);
let vec: Vec<_> = (0u32..4).map(NSValue::new).collect();
let array: Id<NSArray<_, _>, _> = vec.into_id();

let enumerator = array.iter();
assert!(enumerator.count() == 4);
@@ -186,8 +189,8 @@ mod tests {

#[test]
fn test_fast_enumerator() {
let vec = (0u32..4).map(NSValue::new).collect();
let array = NSArray::from_vec(vec);
let vec: Vec<_> = (0u32..4).map(NSValue::new).collect();
let array: Id<NSArray<_, _>, _> = vec.into_id();

let enumerator = array.enumerator();
assert!(enumerator.count() == 4);

0 comments on commit 522f93b

Please sign in to comment.