Skip to content

objc2::foundation additions for winit #257

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 6 commits into from
Aug 31, 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
13 changes: 13 additions & 0 deletions objc2/CHANGELOG_FOUNDATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,19 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## Unreleased - YYYY-MM-DD

### Added
* Added `NSSet`.
* Added `NSMutableSet`.
* Added `NSMutableDictionary`.
* Added `NSNotFound`.
* Added `NSBundle`.
* Added `NSTimeInterval`.
* Added `NSString::len_utf16` and `NSAttributedString::len_utf16`.
* Added `NSString::concat` and `NSString::join_path`.


## objc2 0.3.0-beta.2 - 2022-08-28

### Added
* Added `NSNumber`.
* Added `NSError`.
Expand Down
4 changes: 1 addition & 3 deletions objc2/src/foundation/attributed_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,7 @@ extern_methods!(
/// Alias for `self.string().len_utf16()`.
#[doc(alias = "length")]
#[sel(length)]
#[allow(unused)]
// TODO: Finish this
fn len_utf16(&self) -> usize;
pub fn len_utf16(&self) -> usize;

// /// TODO
// ///
Expand Down
73 changes: 73 additions & 0 deletions objc2/src/foundation/bundle.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use core::fmt;
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, ns_string, ClassType};

extern_class!(
/// A representation of the code and resources stored in a bundle
/// directory on disk.
///
/// See [Apple's documentation](https://developer.apple.com/documentation/foundation/nsbundle?language=objc).
#[derive(PartialEq, Eq, Hash)]
pub struct NSBundle;

unsafe impl ClassType for NSBundle {
type Super = NSObject;
}
);

// SAFETY: Bundles are documented as thread-safe.
unsafe impl Sync for NSBundle {}
unsafe impl Send for NSBundle {}

impl UnwindSafe for NSBundle {}
impl RefUnwindSafe for NSBundle {}

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

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

pub fn name(&self) -> Option<Id<NSString, Shared>> {
self.info().get(ns_string!("CFBundleName")).map(|name| {
let ptr: *const NSObject = name;
let ptr: *const NSString = ptr.cast();
// SAFETY: TODO
let name = unsafe { ptr.as_ref().unwrap_unchecked() };
name.copy()
})
}
}
);

impl fmt::Debug for NSBundle {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// Delegate to NSObject
(**self).fmt(f)
}
}

#[cfg(test)]
mod tests {
use super::*;
use alloc::format;
use std::println;

#[test]
#[cfg_attr(not(target_os = "macos"), ignore = "varies between platforms")]
fn try_running_functions() {
// This is mostly empty since cargo doesn't bundle the application
// before executing.
let bundle = NSBundle::main();
println!("{:?}", bundle);
assert_eq!(format!("{:?}", bundle.info()), "{}");
assert_eq!(bundle.name(), None);
}
}
15 changes: 15 additions & 0 deletions objc2/src/foundation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,11 @@
#![allow(missing_docs)]
#![allow(clippy::missing_safety_doc)]

use std::os::raw::c_double;

pub use self::array::NSArray;
pub use self::attributed_string::{NSAttributedString, NSAttributedStringKey};
pub use self::bundle::NSBundle;
pub use self::comparison_result::NSComparisonResult;
pub use self::copying::{NSCopying, NSMutableCopying};
pub use self::data::NSData;
Expand Down Expand Up @@ -84,6 +87,17 @@ pub use self::zone::NSZone;
#[doc(no_inline)]
pub use crate::ffi::{NSInteger, NSUInteger};

/// A value indicating that a requested item couldn’t be found or doesn’t exist.
///
/// See [Apple's documentation](https://developer.apple.com/documentation/foundation/nsnotfound?language=objc).
#[allow(non_upper_case_globals)]
pub const NSNotFound: NSInteger = crate::ffi::NSIntegerMax;

/// A number of seconds.
///
/// See [Apple's documentation](https://developer.apple.com/documentation/foundation/nstimeinterval?language=objc).
pub type NSTimeInterval = c_double;

#[cfg(feature = "apple")]
#[link(name = "Foundation", kind = "framework")]
extern "C" {}
Expand All @@ -96,6 +110,7 @@ extern "C" {}
pub mod __ns_string;
mod array;
mod attributed_string;
mod bundle;
mod comparison_result;
mod copying;
mod data;
Expand Down
61 changes: 53 additions & 8 deletions objc2/src/foundation/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use core::str;
use std::os::raw::c_char;

use super::{NSComparisonResult, NSCopying, NSMutableCopying, NSMutableString, NSObject};
use crate::ffi;
use crate::rc::{autoreleasepool, AutoreleasePool, DefaultId, Id, Shared};
use crate::runtime::{Class, Object};
use crate::{extern_class, extern_methods, msg_send, msg_send_id, ClassType};
Expand All @@ -20,10 +19,6 @@ const UTF8_ENCODING: usize = 4;
#[cfg(feature = "gnustep-1-7")]
const UTF8_ENCODING: i32 = 4;

#[allow(unused)]
#[allow(non_upper_case_globals)]
const NSNotFound: ffi::NSInteger = ffi::NSIntegerMax;

extern_class!(
/// An immutable, plain-text Unicode string object.
///
Expand Down Expand Up @@ -61,20 +56,70 @@ extern_methods!(
unsafe { msg_send_id![Self::class(), new] }
}

/// Create a new string by appending the given string to self.
///
///
/// # Example
///
/// ```
/// # #[cfg(feature = "gnustep-1-7")]
/// # unsafe { objc2::__gnustep_hack::get_class_to_force_linkage() };
/// use objc2::ns_string;
/// let error_tag = ns_string!("Error: ");
/// let error_string = ns_string!("premature end of file.");
/// let error_message = error_tag.concat(error_string);
/// assert_eq!(&*error_message, ns_string!("Error: premature end of file."));
/// ```
#[doc(alias = "stringByAppendingString")]
#[doc(alias = "stringByAppendingString:")]
pub fn concat(&self, other: &Self) -> Id<Self, Shared> {
// SAFETY: The other string is non-null, and won't be retained
// by the function.
unsafe { msg_send_id![self, stringByAppendingString: other] }
}

/// Create a new string by appending the given string, separated by
/// a path separator.
///
/// This is similar to [`Path::join`][std::path::Path::join].
///
/// Note that this method only works with file paths (not, for
/// example, string representations of URLs).
///
///
/// # Examples
///
/// ```
/// # #[cfg(feature = "gnustep-1-7")]
/// # unsafe { objc2::__gnustep_hack::get_class_to_force_linkage() };
/// use objc2::ns_string;
///
/// let extension = ns_string!("scratch.tiff");
/// assert_eq!(&*ns_string!("/tmp").join_path(extension), ns_string!("/tmp/scratch.tiff"));
/// assert_eq!(&*ns_string!("/tmp/").join_path(extension), ns_string!("/tmp/scratch.tiff"));
/// assert_eq!(&*ns_string!("/").join_path(extension), ns_string!("/scratch.tiff"));
/// assert_eq!(&*ns_string!("").join_path(extension), ns_string!("scratch.tiff"));
/// ```
#[doc(alias = "stringByAppendingPathComponent")]
#[doc(alias = "stringByAppendingPathComponent:")]
pub fn join_path(&self, other: &Self) -> Id<Self, Shared> {
// SAFETY: Same as `Self::concat`.
unsafe { msg_send_id![self, stringByAppendingPathComponent: other] }
}

/// The number of UTF-8 code units in `self`.
#[doc(alias = "lengthOfBytesUsingEncoding")]
#[doc(alias = "lengthOfBytesUsingEncoding:")]
pub fn len(&self) -> usize {
unsafe { msg_send![self, lengthOfBytesUsingEncoding: UTF8_ENCODING] }
}

/// The number of UTF-16 code units in `self`.
/// The number of UTF-16 code units in the string.
///
/// See also [`NSString::len`].
#[doc(alias = "length")]
// TODO: Finish this
#[sel(length)]
fn len_utf16(&self) -> usize;
pub fn len_utf16(&self) -> usize;

pub fn is_empty(&self) -> bool {
// TODO: lengthOfBytesUsingEncoding: might sometimes return 0 for
Expand Down
12 changes: 6 additions & 6 deletions test-ui/ui/msg_send_id_invalid_return.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ error[E0277]: the trait bound `objc2::runtime::Class: Message` is not satisfied
Exception
NSArray<T, O>
NSAttributedString
NSBundle
NSData
NSDictionary<K, V>
NSError
NSException
NSMutableArray<T, O>
and 14 others
and 15 others
= note: required for `RetainSemantics<true, false, false, false>` to implement `MsgSendId<&objc2::runtime::Class, objc2::runtime::Class, Shared>`

error[E0277]: the trait bound `objc2::runtime::Class: Message` is not satisfied
Expand All @@ -48,12 +48,12 @@ error[E0277]: the trait bound `objc2::runtime::Class: Message` is not satisfied
Exception
NSArray<T, O>
NSAttributedString
NSBundle
NSData
NSDictionary<K, V>
NSError
NSException
NSMutableArray<T, O>
and 14 others
and 15 others
= note: required for `RetainSemantics<true, false, false, false>` to implement `MsgSendId<&objc2::runtime::Class, objc2::runtime::Class, Shared>`

error[E0277]: the trait bound `&objc2::runtime::Object: MaybeUnwrap<Allocated<_>, _>` is not satisfied
Expand Down Expand Up @@ -85,12 +85,12 @@ error[E0277]: the trait bound `objc2::runtime::Class: Message` is not satisfied
Exception
NSArray<T, O>
NSAttributedString
NSBundle
NSData
NSDictionary<K, V>
NSError
NSException
NSMutableArray<T, O>
and 14 others
and 15 others
= note: required for `RetainSemantics<false, true, false, false>` to implement `MsgSendId<&objc2::runtime::Class, Allocated<objc2::runtime::Class>, Shared>`

error[E0277]: the trait bound `Id<objc2::runtime::Object, Shared>: MaybeUnwrap<Allocated<_>, _>` is not satisfied
Expand Down
8 changes: 4 additions & 4 deletions test-ui/ui/msg_send_super_not_classtype.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ error[E0277]: the trait bound `objc2::runtime::Object: ClassType` is not satisfi
= help: the following other types implement trait `ClassType`:
NSArray<T, O>
NSAttributedString
NSBundle
NSData
NSDictionary<K, V>
NSError
NSException
NSMutableArray<T, O>
NSMutableAttributedString
and 12 others
and 13 others
note: required by a bound in `__send_super_message_static`
--> $WORKSPACE/objc2/src/message/mod.rs
|
Expand All @@ -35,13 +35,13 @@ error[E0277]: the trait bound `objc2::runtime::Object: ClassType` is not satisfi
= help: the following other types implement trait `ClassType`:
NSArray<T, O>
NSAttributedString
NSBundle
NSData
NSDictionary<K, V>
NSError
NSException
NSMutableArray<T, O>
NSMutableAttributedString
and 12 others
and 13 others
note: required by a bound in `__send_super_message_static`
--> $WORKSPACE/objc2/src/message/mod.rs
|
Expand Down