Skip to content

Commit

Permalink
Merge pull request #237 from madsmtm/macro-syntax
Browse files Browse the repository at this point in the history
Change `extern_class!` and `declare_class!` macro syntax
  • Loading branch information
madsmtm authored Aug 9, 2022
2 parents b97bcbb + 0949941 commit 54be2ce
Show file tree
Hide file tree
Showing 30 changed files with 642 additions and 347 deletions.
3 changes: 2 additions & 1 deletion objc2/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
* Added `Id::into_superclass`.

### Changed
* **BREAKING**: Change selector syntax in `declare_class!` macro to be more Rust-like.
* **BREAKING**: Change syntax in `extern_class!` macro to be more Rust-like.
* **BREAKING**: Change syntax in `declare_class!` macro to be more Rust-like.
* **BREAKING**: Renamed `Id::from_owned` to `Id::into_shared`.


Expand Down
35 changes: 19 additions & 16 deletions objc2/examples/delegate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,30 @@ use objc2::{declare_class, extern_class, msg_send, msg_send_id, ClassType};
extern "C" {}

#[cfg(all(feature = "apple", target_os = "macos"))]
extern_class! {
unsafe struct NSResponder: NSObject;
}
extern_class!(
struct NSResponder;

unsafe impl ClassType for NSResponder {
type Superclass = NSObject;
}
);

#[cfg(all(feature = "apple", target_os = "macos"))]
declare_class! {
unsafe struct CustomAppDelegate: NSResponder, NSObject {
declare_class!(
struct CustomAppDelegate {
pub ivar: u8,
another_ivar: Bool,
}

unsafe impl {
unsafe impl ClassType for CustomAppDelegate {
#[inherits(NSObject)]
type Superclass = NSResponder;
}

unsafe impl CustomAppDelegate {
#[sel(initWith:another:)]
fn init_with(
self: &mut Self,
ivar: u8,
another_ivar: Bool,
) -> *mut Self {
let this: *mut Self = unsafe {
msg_send![super(self, NSResponder::class()), init]
};
fn init_with(self: &mut Self, ivar: u8, another_ivar: Bool) -> *mut Self {
let this: *mut Self = unsafe { msg_send![super(self, NSResponder::class()), init] };
if let Some(this) = unsafe { this.as_mut() } {
// TODO: Allow initialization through MaybeUninit
*this.ivar = ivar;
Expand All @@ -49,7 +52,7 @@ declare_class! {
// `clang` only when used in Objective-C...
//
// TODO: Investigate this!
unsafe impl {
unsafe impl CustomAppDelegate {
/// This is `unsafe` because it expects `sender` to be valid
#[sel(applicationDidFinishLaunching:)]
unsafe fn did_finish_launching(&self, sender: *mut Object) {
Expand All @@ -65,7 +68,7 @@ declare_class! {
println!("Will terminate!");
}
}
}
);

#[cfg(all(feature = "apple", target_os = "macos"))]
impl CustomAppDelegate {
Expand Down
10 changes: 7 additions & 3 deletions objc2/examples/nspasteboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,15 @@ extern "C" {
}

#[cfg(all(feature = "apple", target_os = "macos"))]
extern_class! {
extern_class!(
/// <https://developer.apple.com/documentation/appkit/nspasteboard?language=objc>
pub struct NSPasteboard;

// SAFETY: NSPasteboard actually inherits from NSObject.
unsafe pub struct NSPasteboard: NSObject;
}
unsafe impl ClassType for NSPasteboard {
type Superclass = NSObject;
}
);

#[cfg(all(feature = "apple", target_os = "macos"))]
impl NSPasteboard {
Expand Down
30 changes: 21 additions & 9 deletions objc2/examples/speech_synthethis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,14 @@ mod appkit {
#[link(name = "AppKit", kind = "framework")]
extern "C" {}

extern_class! {
extern_class!(
/// <https://developer.apple.com/documentation/appkit/nsspeechsynthesizer?language=objc>
unsafe pub struct NSSpeechSynthesizer: NSObject;
}
pub struct NSSpeechSynthesizer;

unsafe impl ClassType for NSSpeechSynthesizer {
type Superclass = NSObject;
}
);

impl NSSpeechSynthesizer {
// Uses default voice
Expand Down Expand Up @@ -100,11 +104,15 @@ mod avfaudio {
#[link(name = "AVFoundation", kind = "framework")]
extern "C" {}

extern_class! {
extern_class!(
/// <https://developer.apple.com/documentation/avfaudio/avspeechsynthesizer?language=objc>
#[derive(Debug)]
unsafe pub struct AVSpeechSynthesizer: NSObject;
}
pub struct AVSpeechSynthesizer;

unsafe impl ClassType for AVSpeechSynthesizer {
type Superclass = NSObject;
}
);

impl AVSpeechSynthesizer {
pub fn new() -> Id<Self, Owned> {
Expand All @@ -122,11 +130,15 @@ mod avfaudio {
}
}

extern_class! {
extern_class!(
/// <https://developer.apple.com/documentation/avfaudio/avspeechutterance?language=objc>
#[derive(Debug)]
unsafe pub struct AVSpeechUtterance: NSObject;
}
pub struct AVSpeechUtterance;

unsafe impl ClassType for AVSpeechUtterance {
type Superclass = NSObject;
}
);

impl AVSpeechUtterance {
pub fn new(string: &NSString) -> Id<Self, Owned> {
Expand Down
2 changes: 1 addition & 1 deletion objc2/src/__macro_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ pub const fn in_selector_family(mut selector: &[u8], mut family: &[u8]) -> bool
// Skip leading underscores from selector
loop {
selector = match selector {
[b'_', selector @ ..] => (selector),
[b'_', rest @ ..] => rest,
_ => break,
}
}
Expand Down
10 changes: 7 additions & 3 deletions objc2/src/class_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,13 @@ use crate::Message;
/// ```ignore
/// use objc2::{extern_class, ClassType};
///
/// extern_class! {
/// unsafe struct MyClass: NSObject;
/// }
/// extern_class!(
/// struct MyClass;
///
/// unsafe impl ClassType for MyClass {
/// type Superclass = NSObject;
/// }
/// );
///
/// let cls = MyClass::class();
/// ```
Expand Down
10 changes: 7 additions & 3 deletions objc2/src/foundation/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::rc::{DefaultId, Id, Owned, Ownership, Shared, SliceId};
use crate::runtime::{Class, Object};
use crate::{ClassType, Message, __inner_extern_class, msg_send, msg_send_id};

__inner_extern_class! {
__inner_extern_class!(
/// An immutable ordered collection of objects.
///
/// This is the Objective-C equivalent of a "boxed slice" (`Box<[T]>`),
Expand Down Expand Up @@ -52,11 +52,15 @@ __inner_extern_class! {
// `T: PartialEq` bound correct because `NSArray` does deep (instead of
// shallow) equality comparisons.
#[derive(PartialEq, Eq, Hash)]
unsafe pub struct NSArray<T: Message, O: Ownership = Shared>: NSObject {
pub struct NSArray<T: Message, O: Ownership = Shared> {
item: PhantomData<Id<T, O>>,
notunwindsafe: PhantomData<&'static mut ()>,
}
}

unsafe impl<T: Message, O: Ownership> ClassType for NSArray<T, O> {
type Superclass = NSObject;
}
);

// SAFETY: Same as Id<T, O> (which is what NSArray effectively stores).
unsafe impl<T: Message + Sync + Send> Sync for NSArray<T, Shared> {}
Expand Down
10 changes: 7 additions & 3 deletions objc2/src/foundation/attributed_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::rc::{DefaultId, Id, Shared};
use crate::runtime::Object;
use crate::{extern_class, msg_send, msg_send_id, ClassType};

extern_class! {
extern_class!(
/// A string that has associated attributes for portions of its text.
///
/// Examples of attributes could be: Visual style, hyperlinks, or
Expand All @@ -22,8 +22,12 @@ extern_class! {
///
/// See [Apple's documentation](https://developer.apple.com/documentation/foundation/nsattributedstring?language=objc).
#[derive(PartialEq, Eq, Hash)]
unsafe pub struct NSAttributedString: NSObject;
}
pub struct NSAttributedString;

unsafe impl ClassType for NSAttributedString {
type Superclass = NSObject;
}
);

// SAFETY: `NSAttributedString` is immutable and `NSMutableAttributedString`
// can only be mutated from `&mut` methods.
Expand Down
10 changes: 7 additions & 3 deletions objc2/src/foundation/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,19 @@ use crate::rc::{DefaultId, Id, Shared};
use crate::runtime::{Class, Object};
use crate::{extern_class, msg_send, msg_send_id, ClassType};

extern_class! {
extern_class!(
/// A static byte buffer in memory.
///
/// This is similar to a [`slice`][`prim@slice`] of [`u8`].
///
/// See [Apple's documentation](https://developer.apple.com/documentation/foundation/nsdata?language=objc).
#[derive(PartialEq, Eq, Hash)]
unsafe pub struct NSData: NSObject;
}
pub struct NSData;

unsafe impl ClassType for NSData {
type Superclass = NSObject;
}
);

// SAFETY: `NSData` is immutable and `NSMutableData` can only be mutated from
// `&mut` methods.
Expand Down
10 changes: 7 additions & 3 deletions objc2/src/foundation/dictionary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,17 @@ use super::{NSArray, NSCopying, NSEnumerator, NSFastEnumeration, NSObject};
use crate::rc::{DefaultId, Id, Owned, Shared, SliceId};
use crate::{ClassType, __inner_extern_class, msg_send, msg_send_id, Message};

__inner_extern_class! {
__inner_extern_class!(
#[derive(PartialEq, Eq, Hash)]
unsafe pub struct NSDictionary<K: Message, V: Message>: NSObject {
pub struct NSDictionary<K: Message, V: Message> {
key: PhantomData<Id<K, Shared>>,
obj: PhantomData<Id<V, Owned>>,
}
}

unsafe impl<K: Message, V: Message> ClassType for NSDictionary<K, V> {
type Superclass = NSObject;
}
);

// TODO: SAFETY
// Approximately same as `NSArray<T, Shared>`
Expand Down
10 changes: 7 additions & 3 deletions objc2/src/foundation/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::ffi::NSInteger;
use crate::rc::{Id, Shared};
use crate::{extern_class, msg_send, msg_send_id, ClassType};

extern_class! {
extern_class!(
/// Information about an error condition including a domain, a
/// domain-specific error code, and application-specific information.
///
Expand All @@ -16,8 +16,12 @@ extern_class! {
/// [err]: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ErrorHandlingCocoa/ErrorHandling/ErrorHandling.html#//apple_ref/doc/uid/TP40001806-CH201-SW1
/// [api]: https://developer.apple.com/documentation/foundation/nserror?language=objc
#[derive(PartialEq, Eq, Hash)]
unsafe pub struct NSError: NSObject;
}
pub struct NSError;

unsafe impl ClassType for NSError {
type Superclass = NSObject;
}
);

// SAFETY: Error objects are immutable data containers.
unsafe impl Sync for NSError {}
Expand Down
10 changes: 7 additions & 3 deletions objc2/src/foundation/exception.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::rc::{Id, Shared};
use crate::runtime::Object;
use crate::{extern_class, msg_send, msg_send_id, sel, ClassType};

extern_class! {
extern_class!(
/// A special condition that interrupts the normal flow of program
/// execution.
///
Expand All @@ -19,8 +19,12 @@ extern_class! {
///
/// [doc]: https://developer.apple.com/documentation/foundation/nsexception?language=objc
#[derive(PartialEq, Eq, Hash)]
unsafe pub struct NSException: NSObject;
}
pub struct NSException;

unsafe impl ClassType for NSException {
type Superclass = NSObject;
}
);

// SAFETY: Exception objects are immutable data containers, and documented as
// thread safe.
Expand Down
11 changes: 8 additions & 3 deletions objc2/src/foundation/mutable_array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,23 @@ use super::{
use crate::rc::{DefaultId, Id, Owned, Ownership, Shared, SliceId};
use crate::{ClassType, Message, __inner_extern_class, msg_send, msg_send_id};

__inner_extern_class! {
__inner_extern_class!(
/// A growable ordered collection of objects.
///
/// See the documentation for [`NSArray`] and/or [Apple's
/// documentation][apple-doc] for more information.
///
/// [apple-doc]: https://developer.apple.com/documentation/foundation/nsmutablearray?language=objc
#[derive(PartialEq, Eq, Hash)]
unsafe pub struct NSMutableArray<T: Message, O: Ownership = Owned>: NSArray<T, O>, NSObject {
pub struct NSMutableArray<T: Message, O: Ownership = Owned> {
p: PhantomData<*mut ()>,
}
}

unsafe impl<T: Message, O: Ownership> ClassType for NSMutableArray<T, O> {
#[inherits(NSObject)]
type Superclass = NSArray<T, O>;
}
);

// SAFETY: Same as NSArray<T, O>
//
Expand Down
11 changes: 8 additions & 3 deletions objc2/src/foundation/mutable_attributed_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@ use super::{NSAttributedString, NSCopying, NSMutableCopying, NSObject, NSString}
use crate::rc::{DefaultId, Id, Owned, Shared};
use crate::{extern_class, msg_send, msg_send_id, ClassType};

extern_class! {
extern_class!(
/// A mutable string that has associated attributes.
///
/// See [Apple's documentation](https://developer.apple.com/documentation/foundation/nsmutableattributedstring?language=objc).
#[derive(PartialEq, Eq, Hash)]
unsafe pub struct NSMutableAttributedString: NSAttributedString, NSObject;
}
pub struct NSMutableAttributedString;

unsafe impl ClassType for NSMutableAttributedString {
#[inherits(NSObject)]
type Superclass = NSAttributedString;
}
);

/// Creating mutable attributed strings.
impl NSMutableAttributedString {
Expand Down
11 changes: 8 additions & 3 deletions objc2/src/foundation/mutable_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use super::{NSCopying, NSData, NSMutableCopying, NSObject, NSRange};
use crate::rc::{DefaultId, Id, Owned, Shared};
use crate::{extern_class, msg_send, msg_send_id, ClassType};

extern_class! {
extern_class!(
/// A dynamic byte buffer in memory.
///
/// This is the Objective-C equivalent of a [`Vec`] containing [`u8`].
Expand All @@ -20,8 +20,13 @@ extern_class! {
///
/// [`Vec`]: std::vec::Vec
#[derive(PartialEq, Eq, Hash)]
unsafe pub struct NSMutableData: NSData, NSObject;
}
pub struct NSMutableData;

unsafe impl ClassType for NSMutableData {
#[inherits(NSObject)]
type Superclass = NSData;
}
);

/// Creation methods
impl NSMutableData {
Expand Down
Loading

0 comments on commit 54be2ce

Please sign in to comment.