Skip to content

extern_class! macro #188

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

Merged
merged 3 commits into from
Jul 6, 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
5 changes: 5 additions & 0 deletions objc2-foundation/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
* Added `MainThreadMarker` to help with designing APIs where a method is only
safe to call on the main thread.
* Added `NSException` object.
* Added `extern_class!` macro to help with defining other classes.
* Expose the `objc2` version that this uses in the crate root.

### Changed
* Changed a few `Debug` impls.


## 0.2.0-alpha.5 - 2022-06-13
Expand Down
8 changes: 6 additions & 2 deletions objc2-foundation/src/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use super::{
NSRange,
};

object! {
__inner_extern_class! {
/// TODO
///
/// You can have a `Id<NSArray<T, Owned>, Owned>`, which allows mutable access
Expand All @@ -25,6 +25,9 @@ object! {
/// TODO: Can we make it impossible? Should we?
///
/// What about `Id<NSArray<T, Shared>, Owned>`?
// `T: PartialEq` bound correct because `NSArray` does deep (instead of
// shallow) equality comparisons.
#[derive(Debug, PartialEq, Eq, Hash)]
unsafe pub struct NSArray<T, O: Ownership>: NSObject {
item: PhantomData<Id<T, O>>,
}
Expand All @@ -40,9 +43,10 @@ unsafe impl<T: Sync + Send> Send for NSArray<T, Shared> {}
unsafe impl<T: Sync> Sync for NSArray<T, Owned> {}
unsafe impl<T: Send> Send for NSArray<T, Owned> {}

object! {
__inner_extern_class! {
// TODO: Ensure that this deref to NSArray is safe!
// This "inherits" NSArray, and has the same `Send`/`Sync` impls as that.
#[derive(Debug, PartialEq, Eq, Hash)]
unsafe pub struct NSMutableArray<T, O: Ownership>: NSArray<T, O>, NSObject {}
}

Expand Down
3 changes: 2 additions & 1 deletion objc2-foundation/src/attributed_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
NSCopying, NSDictionary, NSMutableAttributedString, NSMutableCopying, NSObject, NSString,
};

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

Expand Down
6 changes: 4 additions & 2 deletions objc2-foundation/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,29 @@ use objc2::{msg_send, msg_send_id};

use super::{NSCopying, NSMutableCopying, NSObject, NSRange};

object! {
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(Debug, PartialEq, Eq, Hash)]
unsafe pub struct NSData: NSObject;
}

// TODO: SAFETY
unsafe impl Sync for NSData {}
unsafe impl Send for NSData {}

object! {
extern_class! {
/// A dynamic byte buffer in memory.
///
/// This is the Objective-C equivalent of a [`Vec`] containing [`u8`].
///
/// See [Apple's documentation](https://developer.apple.com/documentation/foundation/nsmutabledata?language=objc).
///
/// [`Vec`]: std::vec::Vec
#[derive(Debug, PartialEq, Eq, Hash)]
unsafe pub struct NSMutableData: NSData, NSObject;
}

Expand Down
3 changes: 2 additions & 1 deletion objc2-foundation/src/dictionary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ use objc2::{msg_send, msg_send_id, Message};

use super::{NSArray, NSCopying, NSEnumerator, NSFastEnumeration, NSObject};

object! {
__inner_extern_class! {
#[derive(Debug, PartialEq, Eq, Hash)]
unsafe pub struct NSDictionary<K, V>: NSObject {
key: PhantomData<Id<K, Shared>>,
obj: PhantomData<Id<V, Owned>>,
Expand Down
27 changes: 19 additions & 8 deletions objc2-foundation/src/exception.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use core::fmt;
use core::hint::unreachable_unchecked;
use core::panic::{RefUnwindSafe, UnwindSafe};

Expand All @@ -8,7 +9,7 @@ use objc2::{msg_send, msg_send_id, sel};

use crate::{NSCopying, NSDictionary, NSObject, NSString};

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

Expand Down Expand Up @@ -120,7 +122,18 @@ impl alloc::borrow::ToOwned for NSException {
}
}

// TODO: Better Debug impl
impl fmt::Debug for NSException {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let obj: &Object = self.as_ref();
write!(f, "{:?} '{}'", obj, self.name())?;
if let Some(reason) = self.reason() {
write!(f, " reason:{}", reason)?;
} else {
write!(f, " reason:(NULL)")?;
}
Ok(())
}
}

#[cfg(test)]
mod tests {
Expand Down Expand Up @@ -148,15 +161,13 @@ mod tests {
};

assert_eq!(exc.description(), NSString::from_str(&description));
assert_eq!(format!("{:?}", exc), format!("\"{}\"", description));

let debug = format!("<NSException: {:p}> 'abc' reason:def", exc);
assert_eq!(format!("{:?}", exc), debug);
}

#[test]
#[cfg_attr(
feature = "apple",
should_panic = "called `Result::unwrap()` on an `Err` value: \"def\""
)]
#[cfg_attr(feature = "gnustep-1-7", should_panic = "> NAME:abc REASON:def")]
#[should_panic = "'abc' reason:def"]
fn unwrap() {
let exc = NSException::new(
&NSString::from_str("abc"),
Expand Down
6 changes: 6 additions & 0 deletions objc2-foundation/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ pub use self::value::NSValue;
#[doc(no_inline)]
pub use objc2::ffi::{NSInteger, NSUInteger};

#[doc(hidden)]
pub use core as __core;

// Expose the version of objc2 that this crate uses
pub use objc2;

#[cfg(feature = "apple")]
#[link(name = "Foundation", kind = "framework")]
extern "C" {}
Expand Down
Loading