From b6bca4ba26e2c1430a96f44ffd44a4a5f9c43241 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Tue, 5 Oct 2021 16:43:45 +0200 Subject: [PATCH] Re-add IdSlice trait Removed previously in 4118e96b23786b24f0915aca2c44ab21b80fa550, but embedded drop flags are gone so this is no longer an issue. Fixes https://github.com/SSheldon/rust-objc-id/issues/1 Co-authored-by: Steven Sheldon --- objc2/src/rc/id_slice.rs | 54 ++++++++++++++++++++++++++++++ objc2/src/rc/mod.rs | 2 ++ objc2_foundation/src/array.rs | 8 ++--- objc2_foundation/src/dictionary.rs | 5 ++- 4 files changed, 61 insertions(+), 8 deletions(-) create mode 100644 objc2/src/rc/id_slice.rs diff --git a/objc2/src/rc/id_slice.rs b/objc2/src/rc/id_slice.rs new file mode 100644 index 000000000..8d7874290 --- /dev/null +++ b/objc2/src/rc/id_slice.rs @@ -0,0 +1,54 @@ +use super::{Id, Owned, Ownership}; +use crate::Message; + +/// Helper trait for functionality on slices containing [`Id`]s. +pub trait IdSlice { + /// The type of the items in the slice. + type Item; + + /// Convert a slice of [`Id`]s into a slice of references. + fn as_slice_ref(&self) -> &[&Self::Item]; + + /// Convert a mutable slice of [`Id`]s into a mutable slice of references. + fn as_slice_mut_ref(&mut self) -> &mut [&Self::Item]; +} + +/// Helper trait for functionality on slices containing owned [`Id`]s. +pub trait IdSliceMut { + /// The type of the items in the slice. + type Item; + + /// Convert a mutable slice of mutable [`Id`]s into a mutable slice of + /// mutable references. + fn as_mut_slice_mut_ref(&mut self) -> &mut [&mut Self::Item]; +} + +impl IdSlice for [Id] { + type Item = T; + + fn as_slice_ref(&self) -> &[&T] { + let ptr = self as *const Self as *const [&T]; + // SAFETY: Id and &T have the same memory layout. Further safety + // follows from `Deref` impl. + unsafe { &*ptr } + } + + fn as_slice_mut_ref(&mut self) -> &mut [&T] { + let ptr = self as *mut Self as *mut [&T]; + // SAFETY: Id and &T have the same memory layout. Further safety + // follows from `Deref` impl. + unsafe { &mut *ptr } + } +} + +impl IdSliceMut for [Id] { + type Item = T; + + fn as_mut_slice_mut_ref(&mut self) -> &mut [&mut T] { + let ptr = self as *mut Self as *mut [&mut T]; + // SAFETY: Id and &mut T have the same memory layout, and the + // `Id` is `Owned` so we're allowed to hand out mutable references. + // Further safety follows from `DerefMut` impl. + unsafe { &mut *ptr } + } +} diff --git a/objc2/src/rc/mod.rs b/objc2/src/rc/mod.rs index da20300dc..5736e0377 100644 --- a/objc2/src/rc/mod.rs +++ b/objc2/src/rc/mod.rs @@ -28,11 +28,13 @@ mod autorelease; mod id; +mod id_slice; mod ownership; mod weak_id; pub use self::autorelease::{autoreleasepool, AutoreleasePool, AutoreleaseSafe}; pub use self::id::Id; +pub use self::id_slice::{IdSlice, IdSliceMut}; pub use self::ownership::{Owned, Ownership, Shared}; pub use self::weak_id::WeakId; diff --git a/objc2_foundation/src/array.rs b/objc2_foundation/src/array.rs index b78b13add..cd5feaea2 100644 --- a/objc2_foundation/src/array.rs +++ b/objc2_foundation/src/array.rs @@ -5,7 +5,7 @@ use core::marker::PhantomData; use core::ops::{Index, Range}; use core::ptr::NonNull; -use objc2::rc::{Id, Owned, Ownership, Shared}; +use objc2::rc::{Id, IdSlice, Owned, Ownership, Shared}; use objc2::runtime::{Class, Object}; use objc2::{class, msg_send}; use objc2::{Encode, Encoding}; @@ -130,8 +130,7 @@ pub trait INSArray: INSObject { } fn from_vec(vec: Vec>) -> Id { - let refs: Vec<&Self::Item> = vec.iter().map(|obj| &**obj).collect(); - unsafe { from_refs(&refs) } + unsafe { from_refs(vec.as_slice_ref()) } } fn objects_in_range(&self, range: Range) -> Vec<&Self::Item> { @@ -178,8 +177,7 @@ pub trait INSArray: INSObject { where Self: INSArray, { - let refs: Vec<&Self::Item> = slice.iter().map(|obj| &**obj).collect(); - unsafe { from_refs(&refs) } + unsafe { from_refs(slice.as_slice_ref()) } } fn to_shared_vec(&self) -> Vec> diff --git a/objc2_foundation/src/dictionary.rs b/objc2_foundation/src/dictionary.rs index 5151494a1..b2d436b2e 100644 --- a/objc2_foundation/src/dictionary.rs +++ b/objc2_foundation/src/dictionary.rs @@ -4,7 +4,7 @@ use core::marker::PhantomData; use core::ops::Index; use core::ptr::{self, NonNull}; -use objc2::rc::{Id, Owned, Ownership, Shared}; +use objc2::rc::{Id, IdSlice, Owned, Ownership, Shared}; use objc2::runtime::Class; use objc2::{class, msg_send}; @@ -119,8 +119,7 @@ pub trait INSDictionary: INSObject { where T: INSCopying, { - let vals_refs: Vec<&Self::Value> = vals.iter().map(|obj| &**obj).collect(); - unsafe { from_refs(keys, &vals_refs) } + unsafe { from_refs(keys, &vals.as_slice_ref()) } } fn into_values_array(dict: Id) -> Id, Owned> {