From 08a941001ae939a874f6e98b37bb7b8641a15787 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Tue, 21 Dec 2021 02:57:11 +0100 Subject: [PATCH] Add a few NSArray methods --- .../src/generated_nsstring.rs | 3 +- .../src/generated_others_shim.rs | 70 +++++++++++++++++++ objc2-foundation-sys/src/lib.rs | 3 + objc2-foundation/src/array.rs | 41 ++++++----- 4 files changed, 94 insertions(+), 23 deletions(-) create mode 100644 objc2-foundation-sys/src/generated_others_shim.rs diff --git a/objc2-foundation-sys/src/generated_nsstring.rs b/objc2-foundation-sys/src/generated_nsstring.rs index 9260b040a..2df6e5654 100644 --- a/objc2-foundation-sys/src/generated_nsstring.rs +++ b/objc2-foundation-sys/src/generated_nsstring.rs @@ -10,12 +10,11 @@ use objc2::rc::{Id, Unknown}; use objc2::runtime::{Bool, Object}; use objc2::{class, msg_send, Encoding, Message, RefEncode}; -use crate::{Autoreleased, NSObject}; +use crate::{Autoreleased, NSArray, 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; diff --git a/objc2-foundation-sys/src/generated_others_shim.rs b/objc2-foundation-sys/src/generated_others_shim.rs new file mode 100644 index 000000000..d80031f31 --- /dev/null +++ b/objc2-foundation-sys/src/generated_others_shim.rs @@ -0,0 +1,70 @@ +//! Other quick examples + +use core::mem::ManuallyDrop; +use core::ptr::NonNull; + +use std::os::raw::{c_char, c_int, c_longlong, c_schar, c_ulong, c_ushort, c_void}; + +use objc2::ffi::{NSInteger, NSUInteger}; +use objc2::rc::{Id, Unknown}; +use objc2::runtime::{Bool, Object}; +use objc2::{class, msg_send, Encoding, Message, RefEncode}; + +use crate::{Autoreleased, NSCoder, NSObject, NSRange, NSString}; + +#[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::new_null(msg_send![class!(NSArray), alloc]) + } +} +impl NSArray { + pub unsafe fn objectAtIndex_(&self, index: NSUInteger) -> Autoreleased { + msg_send![self, objectAtIndex: index] + } + pub unsafe fn init(this: Id) -> Id { + let this = ManuallyDrop::new(this); + Id::new(msg_send![this, init]) + } + pub unsafe fn initWithObjects_count_( + this: Id, + objects: NonNull<*mut Object>, + cnt: NSUInteger, + ) -> Id { + let this = ManuallyDrop::new(this); + Id::new(msg_send![this, initWithObjects: objects, count: cnt]) + } + pub unsafe fn initWithCoder_(&self, coder: NonNull) -> Option> { + Id::new_null(msg_send![self, initWithCoder: coder]) + } + pub unsafe fn count(&self) -> NSUInteger { + msg_send![self, count] + } + pub unsafe fn firstObject(&self) -> Option> { + msg_send![self, firstObject] + } + pub unsafe fn lastObject(&self) -> Option> { + msg_send![self, lastObject] + } + pub unsafe fn getObjects_range_(&self, objects: NonNull>, range: NSRange) { + msg_send![self, getObjects: objects, range: range] + } +} diff --git a/objc2-foundation-sys/src/lib.rs b/objc2-foundation-sys/src/lib.rs index 6aa93fbc8..3e6083b5c 100644 --- a/objc2-foundation-sys/src/lib.rs +++ b/objc2-foundation-sys/src/lib.rs @@ -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::*; diff --git a/objc2-foundation/src/array.rs b/objc2-foundation/src/array.rs index cfb6637b4..246e43e03 100644 --- a/objc2-foundation/src/array.rs +++ b/objc2-foundation/src/array.rs @@ -10,22 +10,15 @@ use objc2::rc::{Id, Owned, Ownership, Shared, SliceId}; use objc2::runtime::Object; use super::{ - INSCopying, INSFastEnumeration, INSMutableCopying, INSObject, NSComparisonResult, NSEnumerator, - NSRange, + ffi, INSCopying, INSFastEnumeration, INSMutableCopying, INSObject, NSComparisonResult, + NSEnumerator, NSRange, }; unsafe fn from_refs(refs: &[&A::Item]) -> Id { - let cls = A::class(); - let obj: *mut A = unsafe { msg_send![cls, alloc] }; - let obj: *mut A = unsafe { - msg_send![ - obj, - initWithObjects: refs.as_ptr(), - count: refs.len(), - ] - }; - let obj = unsafe { NonNull::new_unchecked(obj) }; - unsafe { Id::new(obj) } + let ptr = unsafe { NonNull::new_unchecked(refs.as_ptr() as *mut _) }; + let obj = unsafe { ffi::NSArray::alloc().unwrap() }; + let obj = unsafe { ffi::NSArray::initWithObjects_count_(obj, ptr, refs.len()) }; + unsafe { obj.cast().into_ownership() } } pub unsafe trait INSArray: INSObject { @@ -33,11 +26,15 @@ pub unsafe trait INSArray: INSObject { type Item: INSObject; type ItemOwnership: Ownership; + fn r(&self) -> &ffi::NSArray { + unsafe { &*(self as *const Self as *const ffi::NSArray) } + } + unsafe_def_fn!(fn new -> Self::Ownership); #[doc(alias = "count")] fn len(&self) -> usize { - unsafe { msg_send![self, count] } + unsafe { self.r().count() } } fn is_empty(&self) -> bool { @@ -49,7 +46,7 @@ pub unsafe trait INSArray: INSObject { // 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 } @@ -63,7 +60,7 @@ pub unsafe trait INSArray: INSObject { // 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 } @@ -81,7 +78,7 @@ pub unsafe trait INSArray: INSObject { #[doc(alias = "firstObject")] fn first(&self) -> Option<&Self::Item> { - unsafe { msg_send![self, firstObject] } + unsafe { self.r().firstObject().map(|ptr| ptr.cast().as_ref()) } } #[doc(alias = "firstObject")] @@ -89,12 +86,12 @@ pub unsafe trait INSArray: INSObject { where Self: INSArray, { - unsafe { msg_send![self, firstObject] } + unsafe { self.r().firstObject().map(|ptr| ptr.cast().as_mut()) } } #[doc(alias = "lastObject")] fn last(&self) -> Option<&Self::Item> { - unsafe { msg_send![self, lastObject] } + unsafe { self.r().lastObject().map(|ptr| ptr.cast().as_ref()) } } #[doc(alias = "lastObject")] @@ -102,7 +99,7 @@ pub unsafe trait INSArray: INSObject { where Self: INSArray, { - unsafe { msg_send![self, lastObject] } + unsafe { self.r().lastObject().map(|ptr| ptr.cast().as_mut()) } } #[doc(alias = "objectEnumerator")] @@ -121,7 +118,9 @@ pub unsafe trait INSArray: INSObject { 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