Skip to content

Commit

Permalink
Fix a few remaining compilation errors
Browse files Browse the repository at this point in the history
  • Loading branch information
madsmtm committed Apr 2, 2023
1 parent effb6cc commit 708cef4
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 162 deletions.
23 changes: 9 additions & 14 deletions crates/icrate/src/Foundation/additions/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,12 @@ use core::ops::{Index, IndexMut, Range};
use core::panic::{RefUnwindSafe, UnwindSafe};

use objc2::kind::{Foo, MutableKind, RetainableKind};
use objc2::msg_send;
use objc2::rc::{DefaultId, SliceId};
use objc2::{msg_send, msg_send_id};

use crate::common::*;
use crate::Foundation::{self, NSArray};

#[track_caller]
pub(crate) unsafe fn with_objects<T: Message + ?Sized, R: ClassType>(objects: &[&T]) -> Id<R> {
unsafe {
msg_send_id![
R::alloc(),
initWithObjects: objects.as_ptr(),
count: objects.len(),
]
}
}

extern_methods!(
/// Creation methods.
unsafe impl<T: Message> NSArray<T> {
Expand All @@ -37,6 +26,7 @@ extern_methods!(
pub fn new() -> Id<Self>;

pub fn from_vec(vec: Vec<Id<T>>) -> Id<Self> {
let objects = vec.as_slice_ref();
// SAFETY:
// `initWithObjects:` may choose to deduplicate arrays (I could
// imagine it having a special case for arrays with one `NSNumber`
Expand All @@ -50,20 +40,25 @@ extern_methods!(
// or `Id<T, O>`, and the latter is probably the most useful, as we
// would like to know when we're the only owner of the array, to
// allow mutation of the array's items.
unsafe { with_objects(vec.as_slice_ref()) }
unsafe {
Self::initWithObjects_count(Self::alloc(), objects.as_ptr() as _, objects.len())
}
}

pub fn from_slice(slice: &[Id<T>]) -> Id<Self>
where
T::Kind: RetainableKind, // Or CloneableKind?
{
let objects = slice.as_slice_ref();
// SAFETY: Taking `&T` would not be sound, since the `&T` could come
// from an `Id<T, Owned>` that would now no longer be owned!
//
// (Note that NSArray internally retains all the objects it is given,
// effectively making the safety requirements the same as
// `Id::retain`).
unsafe { with_objects(slice.as_slice_ref()) }
unsafe {
Self::initWithObjects_count(Self::alloc(), objects.as_ptr() as _, objects.len())
}
}
}

Expand Down
18 changes: 4 additions & 14 deletions crates/icrate/src/Foundation/additions/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use core::ops::Index;
use core::panic::{RefUnwindSafe, UnwindSafe};
use core::slice::{self, SliceIndex};

use objc2::msg_send_id;
use objc2::rc::DefaultId;

use crate::common::*;
Expand All @@ -27,7 +26,8 @@ extern_methods!(
pub fn new() -> Id<Self>;

pub fn with_bytes(bytes: &[u8]) -> Id<Self> {
unsafe { Id::cast(with_slice(Self::class(), bytes)) }
let bytes_ptr = bytes.as_ptr() as *mut c_void;
unsafe { Self::initWithBytes_length(Self::alloc(), bytes_ptr, bytes.len()) }
}

#[cfg(feature = "block")]
Expand Down Expand Up @@ -117,28 +117,18 @@ impl<'a> IntoIterator for &'a NSData {
}
}

pub(crate) unsafe fn with_slice(cls: &Class, bytes: &[u8]) -> Id<Object> {
let bytes_ptr: *const c_void = bytes.as_ptr().cast();
unsafe {
msg_send_id![
msg_send_id![cls, alloc],
initWithBytes: bytes_ptr,
length: bytes.len(),
]
}
}

#[cfg(feature = "block")]
pub(crate) unsafe fn with_vec(cls: &Class, bytes: Vec<u8>) -> Id<Object> {
use core::mem::ManuallyDrop;

use block2::{Block, ConcreteBlock};
use objc2::msg_send_id;

let capacity = bytes.capacity();

let dealloc = ConcreteBlock::new(move |bytes: *mut c_void, len: usize| unsafe {
// Recreate the Vec and let it drop
let _ = Vec::<u8>::from_raw_parts(bytes.cast(), len, capacity);
let _ = <Vec<u8>>::from_raw_parts(bytes.cast(), len, capacity);
});
let dealloc = dealloc.copy();
let dealloc: &Block<(*mut c_void, usize), ()> = &dealloc;
Expand Down
11 changes: 8 additions & 3 deletions crates/icrate/src/Foundation/additions/mutable_array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use core::ops::{Index, IndexMut};
use objc2::kind::{MutableKind, RetainableKind};
use objc2::rc::{DefaultId, SliceId};

use super::array::with_objects;
use crate::common::*;
use crate::Foundation::{self, NSArray, NSComparisonResult, NSInteger, NSMutableArray};

Expand All @@ -18,16 +17,22 @@ extern_methods!(
pub fn new() -> Id<Self>;

pub fn from_vec(vec: Vec<Id<T>>) -> Id<Self> {
let objects = vec.as_slice_ref();
// SAFETY: Same as `NSArray::from_vec`.
unsafe { with_objects(vec.as_slice_ref()) }
unsafe {
Self::initWithObjects_count(Self::alloc(), objects.as_ptr() as _, objects.len())
}
}

pub fn from_slice(slice: &[Id<T>]) -> Id<Self>
where
T::Kind: RetainableKind,
{
let objects = slice.as_slice_ref();
// SAFETY: Same as `NSArray::from_slice`.
unsafe { with_objects(slice.as_slice_ref()) }
unsafe {
Self::initWithObjects_count(Self::alloc(), objects.as_ptr() as _, objects.len())
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions crates/icrate/src/Foundation/additions/mutable_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use std::io;

use objc2::rc::DefaultId;

use super::data::with_slice;
use crate::common::*;
use crate::Foundation::{NSMutableData, NSRange};

Expand All @@ -18,7 +17,8 @@ extern_methods!(
pub fn new() -> Id<Self>;

pub fn with_bytes(bytes: &[u8]) -> Id<Self> {
unsafe { Id::cast(with_slice(Self::class(), bytes)) }
let bytes_ptr = bytes.as_ptr() as *mut c_void;
unsafe { Self::initWithBytes_length(Self::alloc(), bytes_ptr, bytes.len()) }
}

#[cfg(feature = "block")]
Expand Down
80 changes: 40 additions & 40 deletions crates/icrate/src/Foundation/additions/mutable_set.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
#![cfg(feature = "Foundation_NSMutableSet")]
use alloc::vec::Vec;

use objc2::kind::RetainableKind;
use objc2::rc::{DefaultId, SliceId};

use super::set::with_objects;
use crate::common::*;
use crate::Foundation::{self, NSMutableSet};

extern_methods!(
unsafe impl<T: Message, O: Ownership> NSMutableSet<T, O> {
unsafe impl<T: Message> NSMutableSet<T> {
/// Creates an empty [`NSMutableSet`].
///
/// # Examples
Expand All @@ -19,9 +19,9 @@ extern_methods!(
/// let set = NSMutableSet::<NSString>::new();
/// ```
// SAFETY:
// Same as `NSSet::new`, except mutable sets are always unique.
// Same as `NSSet::new`.
#[method_id(new)]
pub fn new() -> Id<Self, Owned>;
pub fn new() -> Id<Self>;

/// Creates an [`NSMutableSet`] from a vector.
///
Expand All @@ -33,11 +33,33 @@ extern_methods!(
/// let strs = ["one", "two", "three"].map(NSString::from_str).to_vec();
/// let set = NSMutableSet::from_vec(strs);
/// ```
pub fn from_vec(vec: Vec<Id<T, O>>) -> Id<Self, Owned> {
// SAFETY:
// We always return `Id<NSMutableSet<T, O>, Owned>` because mutable
// sets are always unique.
unsafe { with_objects(vec.as_slice_ref()) }
pub fn from_vec(vec: Vec<Id<T>>) -> Id<Self> {
let objects = vec.as_slice_ref();
// SAFETY: Same as `NSSet::from_vec`.
unsafe {
Self::initWithObjects_count(Self::alloc(), objects.as_ptr() as _, objects.len())
}
}

/// Creates an [`NSMutableSet`] from a slice.
///
/// # Examples
///
/// ```
/// use icrate::Foundation::{NSMutableSet, NSString};
///
/// let strs = ["one", "two", "three"].map(NSString::from_str);
/// let set = NSMutableSet::from_slice(&strs);
/// ```
pub fn from_slice(slice: &[Id<T>]) -> Id<Self>
where
T::Kind: RetainableKind,
{
let objects = slice.as_slice_ref();
// SAFETY: Same as `NSSet::from_slice`.
unsafe {
Self::initWithObjects_count(Self::alloc(), objects.as_ptr() as _, objects.len())
}
}

/// Returns a [`Vec`] containing the set's elements, consuming the set.
Expand All @@ -56,39 +78,17 @@ extern_methods!(
/// let vec = NSMutableSet::into_vec(set);
/// assert_eq!(vec.len(), 3);
/// ```
pub fn into_vec(set: Id<Self, Owned>) -> Vec<Id<T, O>> {
pub fn into_vec(set: Id<Self>) -> Vec<Id<T>> {
set.into_iter()
.map(|obj| unsafe { Id::retain(obj as *const T as *mut T).unwrap_unchecked() })
.collect()
}
}

unsafe impl<T: Message> NSMutableSet<T, Shared> {
/// Creates an [`NSMutableSet`] from a slice.
///
/// # Examples
///
/// ```
/// use icrate::Foundation::{NSMutableSet, NSString};
///
/// let strs = ["one", "two", "three"].map(NSString::from_str);
/// let set = NSMutableSet::from_slice(&strs);
/// ```
pub fn from_slice(slice: &[Id<T, Shared>]) -> Id<Self, Owned> {
// SAFETY:
// Taking `&T` would not be sound, since the `&T` could come from
// an `Id<T, Owned>` that would now no longer be owned!
//
// We always return `Id<NSMutableSet<T, Shared>, Owned>` because
// the elements are shared and mutable sets are always unique.
unsafe { with_objects(slice.as_slice_ref()) }
}
}

// We're explicit about `T` being `PartialEq` for these methods because the
// set compares the input value with elements in the set
// For comparison: Rust's HashSet requires similar methods to be `Hash` + `Eq`
unsafe impl<T: Message + PartialEq, O: Ownership> NSMutableSet<T, O> {
unsafe impl<T: Message + PartialEq> NSMutableSet<T> {
#[method(addObject:)]
fn add_object(&mut self, value: &T);

Expand All @@ -107,7 +107,7 @@ extern_methods!(
/// assert_eq!(set.len(), 1);
/// ```
#[doc(alias = "addObject:")]
pub fn insert(&mut self, value: Id<T, O>) -> bool {
pub fn insert(&mut self, value: Id<T>) -> bool {
// SAFETY:
// We take `Id<T, O>` instead of `&T` because `&T` could be a
// reference to an owned object which would cause us to have a copy
Expand Down Expand Up @@ -146,29 +146,29 @@ extern_methods!(
}
);

unsafe impl<T: Message, O: Ownership> Foundation::NSFastEnumeration2 for NSMutableSet<T, O> {
unsafe impl<T: Message> Foundation::NSFastEnumeration2 for NSMutableSet<T> {
type Item = T;
}

impl<'a, T: Message, O: Ownership> IntoIterator for &'a NSMutableSet<T, O> {
impl<'a, T: Message> IntoIterator for &'a NSMutableSet<T> {
type Item = &'a T;
type IntoIter = Foundation::NSFastEnumerator2<'a, NSMutableSet<T, O>>;
type IntoIter = Foundation::NSFastEnumerator2<'a, NSMutableSet<T>>;

fn into_iter(self) -> Self::IntoIter {
use Foundation::NSFastEnumeration2;
self.iter_fast()
}
}

impl<T: Message + PartialEq, O: Ownership> Extend<Id<T, O>> for NSMutableSet<T, O> {
fn extend<I: IntoIterator<Item = Id<T, O>>>(&mut self, iter: I) {
impl<T: Message + PartialEq> Extend<Id<T>> for NSMutableSet<T> {
fn extend<I: IntoIterator<Item = Id<T>>>(&mut self, iter: I) {
for item in iter {
self.insert(item);
}
}
}

impl<T: Message, O: Ownership> DefaultId for NSMutableSet<T, O> {
impl<T: Message> DefaultId for NSMutableSet<T> {
#[inline]
fn default_id() -> Id<Self> {
Self::new()
Expand Down
Loading

0 comments on commit 708cef4

Please sign in to comment.