Skip to content

Commit

Permalink
Implement From for Id<NSArray> as an example
Browse files Browse the repository at this point in the history
  • Loading branch information
madsmtm committed Oct 29, 2021
1 parent 56a112f commit 116be04
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 35 deletions.
5 changes: 3 additions & 2 deletions objc2_foundation/examples/basic_usage.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use objc2::rc::Id;
use objc2_foundation::{
INSArray, INSCopying, INSDictionary, INSObject, INSString, NSArray, NSDictionary, NSObject,
NSString,
Expand All @@ -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<NSArray<_, _>, _> = objs.into();
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(array);
let obj = objs.pop().unwrap();

// Create an NSString from a str slice
Expand Down
88 changes: 59 additions & 29 deletions objc2_foundation/src/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,6 @@ pub trait INSArray: INSObject {
}
}

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

fn objects_in_range(&self, range: Range<usize>) -> Vec<&Self::Item> {
let range = NSRange::from_range(range);
let mut vec = Vec::with_capacity(range.length);
Expand All @@ -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<Self, Owned>) -> Vec<Id<Self::Item, Self::Own>> {
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<Own = Owned>,
Expand All @@ -179,16 +163,6 @@ pub trait INSArray: INSObject {
{
unsafe { from_refs(slice.as_slice_ref()) }
}

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

pub struct NSArray<T, O: Ownership = Owned> {
Expand Down Expand Up @@ -250,6 +224,52 @@ where
}
}

impl<T, O> From<Id<NSArray<T, O>, Owned>> for Vec<Id<T, O>>
where
T: INSObject,
O: Ownership,
{
fn from(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> From<Vec<Id<T, O>>> for Id<NSArray<T, O>, Owned>
where
T: INSObject,
O: Ownership,
{
fn from(vec: Vec<Id<T, O>>) -> Self {
unsafe { from_refs(vec.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 type NSSharedArray<T> = NSArray<T, Shared>;

pub trait INSMutableArray: INSArray {
Expand Down Expand Up @@ -410,6 +430,16 @@ where
}
}

impl<T, O> From<Vec<Id<T, O>>> for Id<NSMutableArray<T, O>, Owned>
where
T: INSObject,
O: Ownership,
{
fn from(vec: Vec<Id<T, O>>) -> Self {
unsafe { from_refs(vec.as_slice_ref()) }
}
}

pub type NSMutableSharedArray<T> = NSMutableArray<T, Shared>;

#[cfg(test)]
Expand All @@ -426,7 +456,7 @@ mod tests {
for _ in 0..len {
vec.push(NSObject::new());
}
NSArray::from_vec(vec)
vec.into()
}

#[test]
Expand Down Expand Up @@ -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(array);
assert!(vec.len() == 4);
}

Expand Down Expand Up @@ -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");
Expand Down
11 changes: 7 additions & 4 deletions objc2_foundation/src/enumerator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

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<NSArray<_, _>, _> = vec.into();

let enumerator = array.object_enumerator();
assert!(enumerator.count() == 4);
Expand All @@ -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<NSArray<_, _>, _> = vec.into();

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

0 comments on commit 116be04

Please sign in to comment.