Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow returning Id from extern_methods! #244

Merged
merged 3 commits into from
Nov 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions objc2/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
* Added the ability to specify an extra parameter at the end of the selector
in methods declared with `extern_methods!`, and let that be the `NSError**`
parameter.
* Added `#[method_id(...)]` attribute to `extern_methods!`.

### Changed
* Allow other types than `&Class` as the receiver in `msg_send_id!` methods
Expand All @@ -45,6 +46,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
associated functions whoose first parameter is called `this`, is treated as
instance methods instead of class methods.

### Fixed
* Fixed duplicate selector extraction in `extern_methods!`.


## 0.3.0-beta.3 - 2022-09-01

Expand Down
17 changes: 8 additions & 9 deletions objc2/src/foundation/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,14 @@ extern_methods!(
/// Generic creation methods.
unsafe impl<T: Message, O: Ownership> NSArray<T, O> {
/// Get an empty array.
pub fn new() -> Id<Self, Shared> {
// SAFETY:
// - `new` may not create a new object, but instead return a shared
// instance. We remedy this by returning `Id<Self, Shared>`.
// - `O` don't actually matter here! E.g. `NSArray<T, Owned>` is
// perfectly legal, since the array doesn't have any elements, and
// hence the notion of ownership over the elements is void.
unsafe { msg_send_id![Self::class(), new] }
}
// SAFETY:
// - `new` may not create a new object, but instead return a shared
// instance. We remedy this by returning `Id<Self, Shared>`.
// - `O` don't actually matter here! E.g. `NSArray<T, Owned>` is
// perfectly legal, since the array doesn't have any elements, and
// hence the notion of ownership over the elements is void.
#[method_id(new)]
pub fn new() -> Id<Self, Shared>;

pub fn from_vec(vec: Vec<Id<T, O>>) -> Id<Self, O> {
// SAFETY:
Expand Down
34 changes: 18 additions & 16 deletions objc2/src/foundation/attributed_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ use core::panic::{RefUnwindSafe, UnwindSafe};
use super::{
NSCopying, NSDictionary, NSMutableAttributedString, NSMutableCopying, NSObject, NSString,
};
use crate::rc::{DefaultId, Id, Shared};
use crate::rc::{Allocated, DefaultId, Id, Shared};
use crate::runtime::Object;
use crate::{extern_class, extern_methods, msg_send_id, ClassType};
use crate::{extern_class, extern_methods, ClassType};

extern_class!(
/// A string that has associated attributes for portions of its text.
Expand Down Expand Up @@ -45,9 +45,18 @@ extern_methods!(
/// Creating attributed strings.
unsafe impl NSAttributedString {
/// Construct an empty attributed string.
pub fn new() -> Id<Self, Shared> {
unsafe { msg_send_id![Self::class(), new] }
}
#[method_id(new)]
pub fn new() -> Id<Self, Shared>;

#[method_id(initWithString:attributes:)]
fn init_with_attributes(
this: Option<Allocated<Self>>,
string: &NSString,
attributes: &NSDictionary<NSAttributedStringKey, Object>,
) -> Id<Self, Shared>;

#[method_id(initWithString:)]
fn init_with_string(this: Option<Allocated<Self>>, string: &NSString) -> Id<Self, Shared>;

/// Creates a new attributed string from the given string and attributes.
///
Expand All @@ -59,28 +68,21 @@ extern_methods!(
// TODO: Mutability of the dictionary should be (Shared, Shared)
attributes: &NSDictionary<NSAttributedStringKey, Object>,
) -> Id<Self, Shared> {
unsafe {
msg_send_id![
Self::alloc(),
initWithString: string,
attributes: attributes,
]
}
Self::init_with_attributes(Self::alloc(), string, attributes)
}

/// Creates a new attributed string without any attributes.
#[doc(alias = "initWithString:")]
pub fn from_nsstring(string: &NSString) -> Id<Self, Shared> {
unsafe { msg_send_id![Self::alloc(), initWithString: string] }
Self::init_with_string(Self::alloc(), string)
}
}

/// Querying.
unsafe impl NSAttributedString {
// TODO: Lifetimes?
pub fn string(&self) -> Id<NSString, Shared> {
unsafe { msg_send_id![self, string] }
}
#[method_id(string)]
pub fn string(&self) -> Id<NSString, Shared>;

/// Alias for `self.string().len_utf16()`.
#[doc(alias = "length")]
Expand Down
12 changes: 5 additions & 7 deletions objc2/src/foundation/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use core::panic::{RefUnwindSafe, UnwindSafe};

use super::{NSCopying, NSDictionary, NSObject, NSString};
use crate::rc::{Id, Shared};
use crate::{extern_class, extern_methods, msg_send_id, ClassType};
use crate::{extern_class, extern_methods, ClassType};

extern_class!(
/// A representation of the code and resources stored in a bundle
Expand All @@ -27,13 +27,11 @@ impl RefUnwindSafe for NSBundle {}

extern_methods!(
unsafe impl NSBundle {
pub fn main() -> Id<Self, Shared> {
unsafe { msg_send_id![Self::class(), mainBundle] }
}
#[method_id(mainBundle)]
pub fn main() -> Id<Self, Shared>;

pub fn info(&self) -> Id<NSDictionary<NSString, NSObject>, Shared> {
unsafe { msg_send_id![self, infoDictionary] }
}
#[method_id(infoDictionary)]
pub fn info(&self) -> Id<NSDictionary<NSString, NSObject>, Shared>;

pub fn name(&self) -> Option<Id<NSString, Shared>> {
// TODO: Use ns_string!
Expand Down
5 changes: 2 additions & 3 deletions objc2/src/foundation/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,8 @@ impl RefUnwindSafe for NSData {}
extern_methods!(
/// Creation methods.
unsafe impl NSData {
pub fn new() -> Id<Self, Shared> {
unsafe { msg_send_id![Self::class(), new] }
}
#[method_id(new)]
pub fn new() -> Id<Self, Shared>;

pub fn with_bytes(bytes: &[u8]) -> Id<Self, Shared> {
unsafe { Id::cast(with_slice(Self::class(), bytes)) }
Expand Down
10 changes: 4 additions & 6 deletions objc2/src/foundation/dictionary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,8 @@ impl<K: Message + UnwindSafe, V: Message + UnwindSafe> UnwindSafe for NSDictiona
impl<K: Message + RefUnwindSafe, V: Message + RefUnwindSafe> RefUnwindSafe for NSDictionary<K, V> {}
extern_methods!(
unsafe impl<K: Message, V: Message> NSDictionary<K, V> {
pub fn new() -> Id<Self, Shared> {
unsafe { msg_send_id![Self::class(), new] }
}
#[method_id(new)]
pub fn new() -> Id<Self, Shared>;

#[doc(alias = "count")]
#[method(count)]
Expand Down Expand Up @@ -102,9 +101,8 @@ extern_methods!(
}
}

pub fn keys_array(&self) -> Id<NSArray<K, Shared>, Shared> {
unsafe { msg_send_id![self, allKeys] }
}
#[method_id(allKeys)]
pub fn keys_array(&self) -> Id<NSArray<K, Shared>, Shared>;

pub fn from_keys_and_objects<T>(keys: &[&T], vals: Vec<Id<V, Owned>>) -> Id<Self, Shared>
where
Expand Down
10 changes: 4 additions & 6 deletions objc2/src/foundation/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,14 @@ extern_methods!(

/// Accessor methods.
unsafe impl NSError {
pub fn domain(&self) -> Id<NSString, Shared> {
unsafe { msg_send_id![self, domain] }
}
#[method_id(domain)]
pub fn domain(&self) -> Id<NSString, Shared>;

#[method(code)]
pub fn code(&self) -> NSInteger;

pub fn user_info(&self) -> Option<Id<NSDictionary<NSErrorUserInfoKey, NSObject>, Shared>> {
unsafe { msg_send_id![self, userInfo] }
}
#[method_id(userInfo)]
pub fn user_info(&self) -> Option<Id<NSDictionary<NSErrorUserInfoKey, NSObject>, Shared>>;

pub fn localized_description(&self) -> Id<NSString, Shared> {
// TODO: For some reason this leaks a lot?
Expand Down
17 changes: 7 additions & 10 deletions objc2/src/foundation/exception.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,20 +83,17 @@ extern_methods!(
/// can take.
///
/// [doc]: https://developer.apple.com/documentation/foundation/nsexceptionname?language=objc
pub fn name(&self) -> Id<NSExceptionName, Shared> {
// Nullability not documented, but a name is expected in most places.
unsafe { msg_send_id![self, name] }
}
#[method_id(name)]
// Nullability not documented, but a name is expected in most places.
pub fn name(&self) -> Id<NSExceptionName, Shared>;

/// A human-readable message summarizing the reason for the exception.
pub fn reason(&self) -> Option<Id<NSString, Shared>> {
unsafe { msg_send_id![self, reason] }
}
#[method_id(reason)]
pub fn reason(&self) -> Option<Id<NSString, Shared>>;

/// Application-specific data pertaining to the exception.
pub fn user_info(&self) -> Option<Id<NSDictionary<Object, Object>, Shared>> {
unsafe { msg_send_id![self, userInfo] }
}
#[method_id(userInfo)]
pub fn user_info(&self) -> Option<Id<NSDictionary<Object, Object>, Shared>>;

/// Convert this into an [`Exception`] object.
pub fn into_exception(this: Id<Self, Shared>) -> Id<Exception, Shared> {
Expand Down
11 changes: 5 additions & 6 deletions objc2/src/foundation/mutable_array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use super::{
NSObject,
};
use crate::rc::{DefaultId, Id, Owned, Ownership, Shared, SliceId};
use crate::{ClassType, Message, __inner_extern_class, extern_methods, msg_send, msg_send_id};
use crate::{ClassType, Message, __inner_extern_class, extern_methods, msg_send};

__inner_extern_class!(
/// A growable ordered collection of objects.
Expand Down Expand Up @@ -42,11 +42,10 @@ unsafe impl<T: Message + Send> Send for NSMutableArray<T, Owned> {}
extern_methods!(
/// Generic creation methods.
unsafe impl<T: Message, O: Ownership> NSMutableArray<T, O> {
pub fn new() -> Id<Self, Owned> {
// SAFETY: Same as `NSArray::new`, except mutable arrays are always
// unique.
unsafe { msg_send_id![Self::class(), new] }
}
// SAFETY: Same as `NSArray::new`, except mutable arrays are always
// unique.
#[method_id(new)]
pub fn new() -> Id<Self, Owned>;

pub fn from_vec(vec: Vec<Id<T, O>>) -> Id<Self, Owned> {
// SAFETY: Same as `NSArray::from_vec`, except mutable arrays are
Expand Down
5 changes: 2 additions & 3 deletions objc2/src/foundation/mutable_attributed_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@ extern_methods!(
/// Creating mutable attributed strings.
unsafe impl NSMutableAttributedString {
/// Construct an empty mutable attributed string.
pub fn new() -> Id<Self, Owned> {
unsafe { msg_send_id![Self::class(), new] }
}
#[method_id(new)]
pub fn new() -> Id<Self, Owned>;

// TODO: new_with_attributes

Expand Down
5 changes: 2 additions & 3 deletions objc2/src/foundation/mutable_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,8 @@ extern_class!(
extern_methods!(
/// Creation methods
unsafe impl NSMutableData {
pub fn new() -> Id<Self, Owned> {
unsafe { msg_send_id![Self::class(), new] }
}
#[method_id(new)]
pub fn new() -> Id<Self, Owned>;

pub fn with_bytes(bytes: &[u8]) -> Id<Self, Owned> {
unsafe { Id::from_shared(Id::cast(with_slice(Self::class(), bytes))) }
Expand Down
11 changes: 5 additions & 6 deletions objc2/src/foundation/mutable_dictionary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,11 @@ extern_methods!(
///
/// let dict = NSMutableDictionary::<NSString, NSObject>::new();
/// ```
pub fn new() -> Id<Self, Owned> {
// SAFETY:
// Mutable dictionaries are always unique, so it's safe to return
// `Id<Self, Owned>`
unsafe { msg_send_id![Self::class(), new] }
}
// SAFETY:
// Mutable dictionaries are always unique, so it's safe to return
// `Id<Self, Owned>`
#[method_id(new)]
pub fn new() -> Id<Self, Owned>;

#[method(setDictionary:)]
fn set_dictionary(&mut self, dict: &NSDictionary<K, V>);
Expand Down
11 changes: 5 additions & 6 deletions objc2/src/foundation/mutable_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use core::marker::PhantomData;
use super::set::with_objects;
use super::{NSCopying, NSFastEnumeration, NSFastEnumerator, NSMutableCopying, NSObject, NSSet};
use crate::rc::{DefaultId, Id, Owned, Ownership, Shared, SliceId};
use crate::{ClassType, Message, __inner_extern_class, extern_methods, msg_send_id};
use crate::{ClassType, Message, __inner_extern_class, extern_methods};

__inner_extern_class!(
/// A growable unordered collection of unique objects.
Expand Down Expand Up @@ -44,11 +44,10 @@ extern_methods!(
///
/// let set = NSMutableSet::<NSString>::new();
/// ```
pub fn new() -> Id<Self, Owned> {
// SAFETY:
// Same as `NSSet::new`, except mutable sets are always unique.
unsafe { msg_send_id![Self::class(), new] }
}
// SAFETY:
// Same as `NSSet::new`, except mutable sets are always unique.
#[method_id(new)]
pub fn new() -> Id<Self, Owned>;

/// Creates an [`NSMutableSet`] from a vector.
///
Expand Down
5 changes: 2 additions & 3 deletions objc2/src/foundation/mutable_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@ extern_methods!(
/// Creating mutable strings.
unsafe impl NSMutableString {
/// Construct an empty [`NSMutableString`].
pub fn new() -> Id<Self, Owned> {
unsafe { msg_send_id![Self::class(), new] }
}
#[method_id(new)]
pub fn new() -> Id<Self, Owned>;

/// Creates a new [`NSMutableString`] by copying the given string slice.
#[doc(alias = "initWithBytes:length:encoding:")]
Expand Down
5 changes: 2 additions & 3 deletions objc2/src/foundation/number.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,9 +244,8 @@ extern_methods!(
#[method(isEqualToNumber:)]
fn is_equal_to_number(&self, other: &Self) -> bool;

fn string(&self) -> Id<NSString, Shared> {
unsafe { msg_send_id![self, stringValue] }
}
#[method_id(stringValue)]
fn string(&self) -> Id<NSString, Shared>;
}
);

Expand Down
5 changes: 2 additions & 3 deletions objc2/src/foundation/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,8 @@ unsafe impl ClassType for NSObject {

extern_methods!(
unsafe impl NSObject {
pub fn new() -> Id<Self, Owned> {
unsafe { msg_send_id![Self::class(), new] }
}
#[method_id(new)]
pub fn new() -> Id<Self, Owned>;

#[method(isKindOfClass:)]
fn is_kind_of_inner(&self, cls: &Class) -> bool;
Expand Down
12 changes: 5 additions & 7 deletions objc2/src/foundation/process_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use core::panic::{RefUnwindSafe, UnwindSafe};

use super::{NSObject, NSString};
use crate::rc::{Id, Shared};
use crate::{extern_class, extern_methods, msg_send_id, ClassType};
use crate::{extern_class, extern_methods, ClassType};

extern_class!(
/// A collection of information about the current process.
Expand All @@ -27,13 +27,11 @@ impl RefUnwindSafe for NSProcessInfo {}

extern_methods!(
unsafe impl NSProcessInfo {
pub fn process_info() -> Id<NSProcessInfo, Shared> {
unsafe { msg_send_id![Self::class(), processInfo] }
}
#[method_id(processInfo)]
pub fn process_info() -> Id<NSProcessInfo, Shared>;

pub fn process_name(&self) -> Id<NSString, Shared> {
unsafe { msg_send_id![self, processName] }
}
#[method_id(processName)]
pub fn process_name(&self) -> Id<NSString, Shared>;

// TODO: This contains a lot more important functionality!
}
Expand Down
Loading