Skip to content

Commit

Permalink
Add a few NSArray methods
Browse files Browse the repository at this point in the history
  • Loading branch information
madsmtm committed Jul 5, 2022
1 parent 9dd0569 commit f549bf5
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 11 deletions.
1 change: 0 additions & 1 deletion objc2-foundation-sys/src/generated_nsstring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ use crate::NSObject;
pub type NSRange = [NSUInteger; 2];
pub type NSComparisonResult = NSInteger;

pub type NSArray = NSObject;
pub type NSCoder = NSObject;
pub type NSLocale = NSObject;
pub type NSError = NSObject;
Expand Down
68 changes: 68 additions & 0 deletions objc2-foundation-sys/src/generated_others_shim.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//! Other quick examples
use core::ptr::NonNull;

use objc2::ffi::NSUInteger;
use objc2::rc::{Allocated, Id, Unknown};
use objc2::runtime::Object;
use objc2::{class, msg_send, msg_send_id, Encoding, Message, RefEncode};

use crate::{NSCoder, NSObject, NSRange};

#[repr(transparent)]
pub struct NSArray(NSObject);
impl core::ops::Deref for NSArray {
type Target = NSObject;
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl core::ops::DerefMut for NSArray {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
unsafe impl Message for NSArray {}
unsafe impl RefEncode for NSArray {
const ENCODING_REF: Encoding<'static> = Encoding::Object;
}
impl NSArray {
pub unsafe fn alloc() -> Option<Id<Allocated<Self>, Unknown>> {
msg_send_id![class!(NSArray), alloc]
}
}
impl NSArray {
pub unsafe fn objectAtIndex_(&self, index: NSUInteger) -> NonNull<Object> {
msg_send![self, objectAtIndex: index]
}
pub unsafe fn init(this: Option<Id<Allocated<Self>, Unknown>>) -> Id<Self, Unknown> {
msg_send_id![this, init].unwrap_unchecked()
}
pub unsafe fn initWithObjects_count_(
this: Option<Id<Allocated<Self>, Unknown>>,
objects: NonNull<*mut Object>,
cnt: NSUInteger,
) -> Id<Self, Unknown> {
msg_send_id![this, initWithObjects: objects, count: cnt].unwrap_unchecked()
}
pub unsafe fn initWithCoder_(
this: Option<Id<Allocated<Self>, Unknown>>,
coder: NonNull<NSCoder>,
) -> Option<Id<Self, Unknown>> {
msg_send_id![this, initWithCoder: coder]
}
pub unsafe fn count(&self) -> NSUInteger {
msg_send![self, count]
}
pub unsafe fn firstObject(&self) -> Option<NonNull<Object>> {
msg_send![self, firstObject]
}
pub unsafe fn lastObject(&self) -> Option<NonNull<Object>> {
msg_send![self, lastObject]
}
pub unsafe fn getObjects_range_(&self, objects: NonNull<NonNull<Object>>, range: NSRange) {
msg_send![self, getObjects: objects, range: range]
}
}
3 changes: 3 additions & 0 deletions objc2-foundation-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,8 @@ mod generated;
#[allow(improper_ctypes)] // TODO
mod generated_nsstring;

mod generated_others_shim;

pub use generated::*;
pub use generated_nsstring::*;
pub use generated_others_shim::*;
32 changes: 22 additions & 10 deletions objc2-foundation/src/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@ use core::cmp::Ordering;
use core::ffi::c_void;
use core::marker::PhantomData;
use core::ops::{Index, IndexMut, Range};
use core::ptr::NonNull;

use objc2::msg_send;
use objc2::rc::{DefaultId, Id, Owned, Ownership, Shared, SliceId};
use objc2::runtime::{Class, Object};
use objc2::Message;

use super::{
NSComparisonResult, NSCopying, NSEnumerator, NSFastEnumeration, NSMutableCopying, NSObject,
NSRange,
ffi, NSComparisonResult, NSCopying, NSEnumerator, NSFastEnumeration, NSMutableCopying,
NSObject, NSRange,
};

object! {
Expand Down Expand Up @@ -55,6 +56,11 @@ unsafe fn from_refs<T: Message + ?Sized>(cls: &Class, refs: &[&T]) -> *mut Objec
count: refs.len(),
]
}

// let ptr = unsafe { NonNull::new_unchecked(refs.as_ptr() as *mut _) };
// let obj: *mut ffi::NSArray = unsafe { msg_send![cls, alloc] };
// let obj = unsafe { ffi::NSArray::initWithObjects_count_(obj, ptr, refs.len()) };
// unsafe { obj.cast() }
}

impl<T: Message> NSArray<T, Shared> {
Expand All @@ -64,9 +70,13 @@ impl<T: Message> NSArray<T, Shared> {
}

impl<T: Message, O: Ownership> NSArray<T, O> {
fn r(&self) -> &ffi::NSArray {
unsafe { &*(self as *const Self as *const ffi::NSArray) }
}

#[doc(alias = "count")]
pub fn len(&self) -> usize {
unsafe { msg_send![self, count] }
unsafe { self.r().count() }
}

pub fn is_empty(&self) -> bool {
Expand All @@ -78,20 +88,20 @@ impl<T: Message, O: Ownership> NSArray<T, O> {
// TODO: Replace this check with catching the thrown NSRangeException
if index < self.len() {
// SAFETY: The index is checked to be in bounds.
Some(unsafe { msg_send![self, objectAtIndex: index] })
Some(unsafe { self.r().objectAtIndex_(index).cast().as_ref() })
} else {
None
}
}

#[doc(alias = "firstObject")]
pub fn first(&self) -> Option<&T> {
unsafe { msg_send![self, firstObject] }
unsafe { self.r().firstObject().map(|ptr| ptr.cast().as_ref()) }
}

#[doc(alias = "lastObject")]
pub fn last(&self) -> Option<&T> {
unsafe { msg_send![self, lastObject] }
unsafe { self.r().lastObject().map(|ptr| ptr.cast().as_ref()) }
}

#[doc(alias = "objectEnumerator")]
Expand All @@ -113,7 +123,9 @@ impl<T: Message, O: Ownership> NSArray<T, O> {
let range = NSRange::from(range);
let mut vec = Vec::with_capacity(range.length);
unsafe {
let _: () = msg_send![self, getObjects: vec.as_ptr(), range: range];
let tmp = [range.location, range.length]; // TMP
let ptr = NonNull::new_unchecked(vec.as_mut_ptr()).cast();
self.r().getObjects_range_(ptr, tmp);
vec.set_len(range.length);
}
vec
Expand Down Expand Up @@ -159,20 +171,20 @@ impl<T: Message> NSArray<T, Owned> {
// TODO: Replace this check with catching the thrown NSRangeException
if index < self.len() {
// SAFETY: The index is checked to be in bounds.
Some(unsafe { msg_send![self, objectAtIndex: index] })
Some(unsafe { self.r().objectAtIndex_(index).cast().as_mut() })
} else {
None
}
}

#[doc(alias = "firstObject")]
pub fn first_mut(&mut self) -> Option<&mut T> {
unsafe { msg_send![self, firstObject] }
unsafe { self.r().firstObject().map(|ptr| ptr.cast().as_mut()) }
}

#[doc(alias = "lastObject")]
pub fn last_mut(&mut self) -> Option<&mut T> {
unsafe { msg_send![self, lastObject] }
unsafe { self.r().lastObject().map(|ptr| ptr.cast().as_mut()) }
}
}

Expand Down

0 comments on commit f549bf5

Please sign in to comment.