Skip to content

Commit

Permalink
Properly use extern_methods! macro
Browse files Browse the repository at this point in the history
  • Loading branch information
madsmtm committed Aug 14, 2022
1 parent da73029 commit b86c94b
Show file tree
Hide file tree
Showing 14 changed files with 124 additions and 127 deletions.
35 changes: 18 additions & 17 deletions objc2/src/foundation/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,34 +136,34 @@ extern_methods!(
/// Generic accessor methods.
unsafe impl<T: Message, O: Ownership> NSArray<T, O> {
#[doc(alias = "count")]
pub fn len(&self) -> usize {
unsafe { msg_send![self, count] }
}
#[sel(count)]
pub fn len(&self) -> usize;

pub fn is_empty(&self) -> bool {
self.len() == 0
}

#[sel(objectAtIndex:)]
unsafe fn get_unchecked(&self, index: usize) -> &T;

#[doc(alias = "objectAtIndex:")]
pub fn get(&self, index: usize) -> Option<&T> {
// 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.get_unchecked(index) })
} else {
None
}
}

#[doc(alias = "firstObject")]
pub fn first(&self) -> Option<&T> {
unsafe { msg_send![self, firstObject] }
}
#[sel(firstObject)]
pub fn first(&self) -> Option<&T>;

#[doc(alias = "lastObject")]
pub fn last(&self) -> Option<&T> {
unsafe { msg_send![self, lastObject] }
}
#[sel(lastObject)]
pub fn last(&self) -> Option<&T>;

#[doc(alias = "objectEnumerator")]
pub fn iter(&self) -> NSEnumerator<'_, T> {
Expand All @@ -173,11 +173,14 @@ extern_methods!(
}
}

#[sel(getObjects:range:)]
unsafe fn get_objects(&self, ptr: *mut &T, range: NSRange);

pub fn objects_in_range(&self, range: Range<usize>) -> Vec<&T> {
let range = NSRange::from(range);
let mut vec = Vec::with_capacity(range.length);
unsafe {
let _: () = msg_send![self, getObjects: vec.as_ptr(), range: range];
self.get_objects(vec.as_mut_ptr(), range);
vec.set_len(range.length);
}
vec
Expand Down Expand Up @@ -228,14 +231,12 @@ extern_methods!(
}

#[doc(alias = "firstObject")]
pub fn first_mut(&mut self) -> Option<&mut T> {
unsafe { msg_send![self, firstObject] }
}
#[sel(firstObject)]
pub fn first_mut(&mut self) -> Option<&mut T>;

#[doc(alias = "lastObject")]
pub fn last_mut(&mut self) -> Option<&mut T> {
unsafe { msg_send![self, lastObject] }
}
#[sel(lastObject)]
pub fn last_mut(&mut self) -> Option<&mut T>;
}
);

Expand Down
7 changes: 3 additions & 4 deletions objc2/src/foundation/attributed_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use super::{
};
use crate::rc::{DefaultId, Id, Shared};
use crate::runtime::Object;
use crate::{extern_class, extern_methods, msg_send, msg_send_id, ClassType};
use crate::{extern_class, extern_methods, msg_send_id, ClassType};

extern_class!(
/// A string that has associated attributes for portions of its text.
Expand Down Expand Up @@ -84,11 +84,10 @@ extern_methods!(

/// Alias for `self.string().len_utf16()`.
#[doc(alias = "length")]
#[sel(length)]
#[allow(unused)]
// TODO: Finish this
fn len_utf16(&self) -> usize {
unsafe { msg_send![self, length] }
}
fn len_utf16(&self) -> usize;

// /// TODO
// ///
Expand Down
48 changes: 27 additions & 21 deletions objc2/src/foundation/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use core::slice::{self, SliceIndex};
use super::{NSCopying, NSMutableCopying, NSMutableData, NSObject};
use crate::rc::{DefaultId, Id, Shared};
use crate::runtime::{Class, Object};
use crate::{extern_class, extern_methods, msg_send, msg_send_id, ClassType};
use crate::{extern_class, extern_methods, msg_send_id, ClassType};

extern_class!(
/// A static byte buffer in memory.
Expand All @@ -34,31 +34,12 @@ impl UnwindSafe for NSData {}
impl RefUnwindSafe for NSData {}

extern_methods!(
/// Creation methods.
unsafe impl NSData {
pub fn new() -> Id<Self, Shared> {
unsafe { msg_send_id![Self::class(), new].unwrap() }
}

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

pub fn is_empty(&self) -> bool {
self.len() == 0
}

pub fn bytes(&self) -> &[u8] {
let ptr: *const c_void = unsafe { msg_send![self, bytes] };
let ptr: *const u8 = ptr.cast();
// The bytes pointer may be null for length zero
if ptr.is_null() {
&[]
} else {
unsafe { slice::from_raw_parts(ptr, self.len()) }
}
}

pub fn with_bytes(bytes: &[u8]) -> Id<Self, Shared> {
unsafe { Id::cast(with_slice(Self::class(), bytes)) }
}
Expand All @@ -80,6 +61,31 @@ extern_methods!(
unsafe { Id::cast(with_vec(cls, bytes)) }
}
}

/// Accessor methods.
unsafe impl NSData {
#[sel(length)]
#[doc(alias = "length")]
pub fn len(&self) -> usize;

pub fn is_empty(&self) -> bool {
self.len() == 0
}

#[sel(bytes)]
fn bytes_raw(&self) -> *const c_void;

pub fn bytes(&self) -> &[u8] {
let ptr = self.bytes_raw();
let ptr: *const u8 = ptr.cast();
// The bytes pointer may be null for length zero
if ptr.is_null() {
&[]
} else {
unsafe { slice::from_raw_parts(ptr, self.len()) }
}
}
}
);

unsafe impl NSCopying for NSData {
Expand Down
31 changes: 10 additions & 21 deletions objc2/src/foundation/dictionary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,29 +37,26 @@ extern_methods!(
}

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

pub fn is_empty(&self) -> bool {
self.len() == 0
}

#[doc(alias = "objectForKey:")]
pub fn get(&self, key: &K) -> Option<&V> {
unsafe { msg_send![self, objectForKey: key] }
}
#[sel(objectForKey:)]
pub fn get(&self, key: &K) -> Option<&V>;

#[sel(getObjects:andKeys:)]
unsafe fn get_objects_and_keys(&self, objects: *mut &V, keys: *mut &K);

#[doc(alias = "getObjects:andKeys:")]
pub fn keys(&self) -> Vec<&K> {
let len = self.len();
let mut keys = Vec::with_capacity(len);
unsafe {
let _: () = msg_send![
self,
getObjects: ptr::null_mut::<&V>(),
andKeys: keys.as_mut_ptr(),
];
self.get_objects_and_keys(ptr::null_mut(), keys.as_mut_ptr());
keys.set_len(len);
}
keys
Expand All @@ -70,11 +67,7 @@ extern_methods!(
let len = self.len();
let mut vals = Vec::with_capacity(len);
unsafe {
let _: () = msg_send![
self,
getObjects: vals.as_mut_ptr(),
andKeys: ptr::null_mut::<&K>(),
];
self.get_objects_and_keys(vals.as_mut_ptr(), ptr::null_mut());
vals.set_len(len);
}
vals
Expand All @@ -86,11 +79,7 @@ extern_methods!(
let mut keys = Vec::with_capacity(len);
let mut objs = Vec::with_capacity(len);
unsafe {
let _: () = msg_send![
self,
getObjects: objs.as_mut_ptr(),
andKeys: keys.as_mut_ptr(),
];
self.get_objects_and_keys(objs.as_mut_ptr(), keys.as_mut_ptr());
keys.set_len(len);
objs.set_len(len);
}
Expand Down
7 changes: 3 additions & 4 deletions objc2/src/foundation/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use core::panic::{RefUnwindSafe, UnwindSafe};
use super::{NSCopying, NSDictionary, NSObject, NSString};
use crate::ffi::NSInteger;
use crate::rc::{Id, Shared};
use crate::{extern_class, extern_methods, msg_send, msg_send_id, ClassType};
use crate::{extern_class, extern_methods, msg_send_id, ClassType};

extern_class!(
/// Information about an error condition including a domain, a
Expand Down Expand Up @@ -68,9 +68,8 @@ extern_methods!(
unsafe { msg_send_id![self, domain].expect("unexpected NULL NSError domain") }
}

pub fn code(&self) -> NSInteger {
unsafe { msg_send![self, code] }
}
#[sel(code)]
pub fn code(&self) -> NSInteger;

pub fn user_info(&self) -> Option<Id<NSDictionary<NSErrorUserInfoKey, NSObject>, Shared>> {
unsafe { msg_send_id![self, userInfo] }
Expand Down
9 changes: 7 additions & 2 deletions objc2/src/foundation/exception.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use super::{NSCopying, NSDictionary, NSObject, NSString};
use crate::exception::Exception;
use crate::rc::{Id, Shared};
use crate::runtime::Object;
use crate::{extern_class, extern_methods, msg_send, msg_send_id, sel, ClassType};
use crate::{extern_class, extern_methods, msg_send_id, sel, ClassType};

extern_class!(
/// A special condition that interrupts the normal flow of program
Expand Down Expand Up @@ -50,6 +50,9 @@ extern_methods!(
unsafe { msg_send_id![obj, initWithName: name, reason: reason, userInfo: user_info] }
}

#[sel(raise)]
unsafe fn raise_raw(&self);

/// Raises the exception, causing program flow to jump to the local
/// exception handler.
///
Expand All @@ -62,7 +65,9 @@ extern_methods!(
pub unsafe fn raise(&self) -> ! {
// SAFETY: We only create `Shared` NSExceptions, so it is safe to give
// to the place where `@catch` receives it.
let _: () = unsafe { msg_send![self, raise] };
unsafe { self.raise_raw() };
// SAFETY: `raise` will throw an exception, or abort if something
// unexpected happened.
unsafe { unreachable_unchecked() }
}

Expand Down
24 changes: 15 additions & 9 deletions objc2/src/foundation/mutable_array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,22 +104,22 @@ extern_methods!(
old_obj
}

#[sel(removeObjectAtIndex:)]
unsafe fn remove_at(&mut self, index: usize);

#[doc(alias = "removeObjectAtIndex:")]
pub fn remove(&mut self, index: usize) -> Id<T, O> {
let obj = if let Some(obj) = self.get(index) {
unsafe { Id::retain_autoreleased(obj as *const T as *mut T).unwrap_unchecked() }
} else {
panic!("removal index should be < len");
};
unsafe {
let _: () = msg_send![self, removeObjectAtIndex: index];
}
unsafe { self.remove_at(index) };
obj
}

fn remove_last(&mut self) {
unsafe { msg_send![self, removeLastObject] }
}
#[sel(removeLastObject)]
fn remove_last(&mut self);

#[doc(alias = "removeLastObject")]
pub fn pop(&mut self) -> Option<Id<T, O>> {
Expand All @@ -132,9 +132,8 @@ extern_methods!(
}

#[doc(alias = "removeAllObjects")]
pub fn clear(&mut self) {
unsafe { msg_send![self, removeAllObjects] }
}
#[sel(removeAllObjects)]
pub fn clear(&mut self);

#[doc(alias = "sortUsingFunction:context:")]
pub fn sort_by<F: FnMut(&T, &T) -> Ordering>(&mut self, compare: F) {
Expand Down Expand Up @@ -312,6 +311,13 @@ mod tests {
assert_eq!(array.len(), 0);
}

#[test]
fn empty_remove_last_noop() {
let mut array = NSMutableArray::<NSObject>::new();
array.remove_last();
assert_eq!(array.len(), 0);
}

#[test]
fn test_sort() {
let strings = vec![NSString::from_str("hello"), NSString::from_str("hi")];
Expand Down
7 changes: 3 additions & 4 deletions objc2/src/foundation/mutable_attributed_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use core::fmt;

use super::{NSAttributedString, NSCopying, NSMutableCopying, NSObject, NSString};
use crate::rc::{DefaultId, Id, Owned, Shared};
use crate::{extern_class, extern_methods, msg_send, msg_send_id, ClassType};
use crate::{extern_class, extern_methods, msg_send_id, ClassType};

extern_class!(
/// A mutable string that has associated attributes.
Expand Down Expand Up @@ -53,9 +53,8 @@ extern_methods!(

/// Replaces the entire attributed string.
#[doc(alias = "setAttributedString:")]
pub fn replace(&mut self, attributed_string: &NSAttributedString) {
unsafe { msg_send![self, setAttributedString: attributed_string] }
}
#[sel(setAttributedString:)]
pub fn replace(&mut self, attributed_string: &NSAttributedString);
}
);

Expand Down
Loading

0 comments on commit b86c94b

Please sign in to comment.