83 lines
2.7 KiB
Rust
83 lines
2.7 KiB
Rust
|
//! A wrapper type for `NSArray`. This is abstracted out as we need to use `NSArray` in a ton of
|
||
|
//! instances in this framework, and down the road I'd like to investigate using `CFArray` instead
|
||
|
//! of `NSArray` (i.e, if the ObjC runtime is ever pulled or something - perhaps those types would
|
||
|
//! stick around).
|
||
|
//!
|
||
|
//! Essentially, consider this some sanity/cleanliness/future-proofing. End users should never need
|
||
|
//! to touch this.
|
||
|
|
||
|
use objc::{class, msg_send, sel, sel_impl};
|
||
|
use objc::runtime::Object;
|
||
|
use objc_id::Id;
|
||
|
|
||
|
use crate::foundation::id;
|
||
|
|
||
|
/// A wrapper for `NSArray` that makes common operations in our framework a bit easier to handle
|
||
|
/// and reason about.
|
||
|
#[derive(Debug)]
|
||
|
pub struct NSArray(pub Id<Object>);
|
||
|
|
||
|
impl From<Vec<&Object>> for NSArray {
|
||
|
/// Given a set of `Object`s, creates an `NSArray` that holds them.
|
||
|
fn from(objects: Vec<&Object>) -> Self {
|
||
|
NSArray(unsafe {
|
||
|
Id::from_ptr(msg_send![class!(NSArray), arrayWithObjects:objects.as_ptr() count:objects.len()])
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl From<Vec<id>> for NSArray {
|
||
|
/// Given a set of `*mut Object`s, creates an `NSArray` that holds them.
|
||
|
fn from(objects: Vec<id>) -> Self {
|
||
|
NSArray(unsafe {
|
||
|
Id::from_ptr(msg_send![class!(NSArray), arrayWithObjects:objects.as_ptr() count:objects.len()])
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl NSArray {
|
||
|
/// Given a set of `Object`s, creates an `NSArray` that holds them.
|
||
|
pub fn new(objects: &[id]) -> Self {
|
||
|
NSArray(unsafe {
|
||
|
Id::from_ptr(msg_send![class!(NSArray), arrayWithObjects:objects.as_ptr() count:objects.len()])
|
||
|
})
|
||
|
}
|
||
|
|
||
|
/// In some cases, we're vended an `NSArray` by the system, and it's ideal to not retain that.
|
||
|
/// This handles that edge case.
|
||
|
pub fn wrap(array: id) -> Self {
|
||
|
NSArray(unsafe {
|
||
|
Id::from_retained_ptr(array)
|
||
|
})
|
||
|
}
|
||
|
|
||
|
/// Consumes and returns the underlying Objective-C value.
|
||
|
pub fn into_inner(mut self) -> id {
|
||
|
&mut *self.0
|
||
|
}
|
||
|
|
||
|
/// Returns the `count` (`len()` equivalent) for the backing `NSArray`.
|
||
|
pub fn count(&self) -> usize {
|
||
|
unsafe { msg_send![self.0, count] }
|
||
|
}
|
||
|
|
||
|
/// A helper method for mapping over the backing `NSArray` items.
|
||
|
/// Often times we need to map in this framework to convert between Rust types, so isolating
|
||
|
/// this out makes life much easier.
|
||
|
pub fn map<T, F: Fn(id) -> T>(&self, transform: F) -> Vec<T> {
|
||
|
let count = self.count();
|
||
|
let mut ret: Vec<T> = Vec::with_capacity(count);
|
||
|
let mut index = 0;
|
||
|
|
||
|
loop {
|
||
|
let item: id = unsafe { msg_send![&*self.0, objectAtIndex:index] };
|
||
|
ret.push(transform(item));
|
||
|
|
||
|
index += 1;
|
||
|
if index == count { break }
|
||
|
}
|
||
|
|
||
|
ret
|
||
|
}
|
||
|
}
|