diff --git a/objc2/README.md b/objc2/README.md index 2e3af7584..12bf52be4 100644 --- a/objc2/README.md +++ b/objc2/README.md @@ -19,7 +19,7 @@ let cls = class!(NSObject); unsafe { let obj: *mut Object = msg_send![cls, new]; let hash: usize = msg_send![obj, hash]; - let is_kind: BOOL = msg_send![obj, isKindOfClass:cls]; + let is_kind: BOOL = msg_send![obj, isKindOfClass: cls]; // Even void methods must have their return type annotated let _: () = msg_send![obj, release]; } diff --git a/objc2/src/declare.rs b/objc2/src/declare.rs index f2ab27497..c6c2506a8 100644 --- a/objc2/src/declare.rs +++ b/objc2/src/declare.rs @@ -372,7 +372,7 @@ mod tests { // Registering the custom class is in test_utils let obj = test_utils::custom_object(); unsafe { - let _: () = msg_send![obj, setFoo:13u32]; + let _: () = msg_send![obj, setFoo: 13u32]; let result: u32 = msg_send![obj, foo]; assert!(result == 13); } diff --git a/objc2/src/exception.rs b/objc2/src/exception.rs index 50013c70c..2465e3aa0 100644 --- a/objc2/src/exception.rs +++ b/objc2/src/exception.rs @@ -1,8 +1,8 @@ use core::ptr::NonNull; -use crate::rc::Id; +use crate::rc::{Id, Shared}; use crate::runtime::Object; -use objc2_exception::{r#try, Exception}; +use objc2_exception::r#try; // Comment copied from `objc2_exception` @@ -21,6 +21,8 @@ use objc2_exception::{r#try, Exception}; /// undefined behaviour until `C-unwind` is stabilized, see [RFC-2945]. /// /// [RFC-2945]: https://rust-lang.github.io/rfcs/2945-c-unwind-abi.html -pub unsafe fn catch_exception(closure: impl FnOnce() -> R) -> Result> { - r#try(closure).map_err(|e| Id::new(NonNull::new(e).unwrap())) +pub unsafe fn catch_exception( + closure: impl FnOnce() -> R, +) -> Result>> { + r#try(closure).map_err(|e| NonNull::new(e).map(|e| Id::new(e.cast()))) } diff --git a/objc2/src/lib.rs b/objc2/src/lib.rs index 02df9997d..dcd49adad 100644 --- a/objc2/src/lib.rs +++ b/objc2/src/lib.rs @@ -12,7 +12,7 @@ Objective-C objects can be messaged using the [`msg_send!`](macro.msg_send!.html let cls = class!(NSObject); let obj: *mut Object = msg_send![cls, new]; let hash: usize = msg_send![obj, hash]; -let is_kind: BOOL = msg_send![obj, isKindOfClass:cls]; +let is_kind: BOOL = msg_send![obj, isKindOfClass: cls]; // Even void methods must have their return type annotated let _: () = msg_send![obj, release]; # } @@ -81,12 +81,10 @@ extern "C" {} pub use objc2_encode::{Encode, EncodeArguments, Encoding, RefEncode}; -pub use crate::message::{Message, MessageArguments, MessageError}; +pub use crate::message::{Message, MessageArguments, MessageError, MessageReceiver}; pub use crate::cache::CachedClass as __CachedClass; pub use crate::cache::CachedSel as __CachedSel; -pub use crate::message::send_message as __send_message; -pub use crate::message::send_super_message as __send_super_message; #[macro_use] mod macros; diff --git a/objc2/src/macros.rs b/objc2/src/macros.rs index fb9214d44..282498d29 100644 --- a/objc2/src/macros.rs +++ b/objc2/src/macros.rs @@ -93,7 +93,9 @@ method's argument's encoding does not match the encoding of the given arguments. let obj: *mut Object; # let obj: *mut Object = 0 as *mut Object; let description: *const Object = msg_send![obj, description]; -let _: () = msg_send![obj, setArg1:1 arg2:2]; +let _: () = msg_send![obj, setArg1: 1 arg2: 2]; +// Or with an optional comma between arguments: +let _: () = msg_send![obj, setArg1: 1, arg2: 2]; # } ``` */ @@ -102,16 +104,16 @@ macro_rules! msg_send { (super($obj:expr, $superclass:expr), $name:ident) => ({ let sel = $crate::sel!($name); let result; - match $crate::__send_super_message(&*$obj, $superclass, sel, ()) { + match $crate::MessageReceiver::send_super_message(&$obj, $superclass, sel, ()) { Err(s) => panic!("{}", s), Ok(r) => result = r, } result }); - (super($obj:expr, $superclass:expr), $($name:ident : $arg:expr)+) => ({ + (super($obj:expr, $superclass:expr), $($name:ident : $arg:expr $(,)?)+) => ({ let sel = $crate::sel!($($name:)+); let result; - match $crate::__send_super_message(&*$obj, $superclass, sel, ($($arg,)*)) { + match $crate::MessageReceiver::send_super_message(&$obj, $superclass, sel, ($($arg,)+)) { Err(s) => panic!("{}", s), Ok(r) => result = r, } @@ -120,16 +122,16 @@ macro_rules! msg_send { ($obj:expr, $name:ident) => ({ let sel = $crate::sel!($name); let result; - match $crate::__send_message(&*$obj, sel, ()) { + match $crate::MessageReceiver::send_message(&$obj, sel, ()) { Err(s) => panic!("{}", s), Ok(r) => result = r, } result }); - ($obj:expr, $($name:ident : $arg:expr)+) => ({ + ($obj:expr, $($name:ident : $arg:expr $(,)?)+) => ({ let sel = $crate::sel!($($name:)+); let result; - match $crate::__send_message(&*$obj, sel, ($($arg,)*)) { + match $crate::MessageReceiver::send_message(&$obj, sel, ($($arg,)+)) { Err(s) => panic!("{}", s), Ok(r) => result = r, } diff --git a/objc2/src/message/apple/mod.rs b/objc2/src/message/apple/mod.rs index e62dca5c2..a243f8fa3 100644 --- a/objc2/src/message/apple/mod.rs +++ b/objc2/src/message/apple/mod.rs @@ -1,6 +1,6 @@ use objc2_sys::objc_super; -use super::{Encode, Message, MessageArguments, MessageError}; +use super::{conditional_try, Encode, MessageArguments, MessageError}; use crate::runtime::{Class, Imp, Object, Sel}; #[cfg(target_arch = "x86")] @@ -23,33 +23,36 @@ trait MsgSendFn: Encode { const MSG_SEND_SUPER: Imp; } -pub unsafe fn send_unverified(obj: *const T, sel: Sel, args: A) -> Result +#[inline(always)] +pub unsafe fn send_unverified( + receiver: *mut Object, + sel: Sel, + args: A, +) -> Result where - T: Message, A: MessageArguments, R: Encode, { - let receiver = obj as *mut T as *mut Object; let msg_send_fn = R::MSG_SEND; - objc_try!({ A::invoke(msg_send_fn, receiver, sel, args) }) + conditional_try(|| A::invoke(msg_send_fn, receiver, sel, args)) } -pub unsafe fn send_super_unverified( - obj: *const T, +#[inline] +pub unsafe fn send_super_unverified( + receiver: *mut Object, superclass: &Class, sel: Sel, args: A, ) -> Result where - T: Message, A: MessageArguments, R: Encode, { let sup = objc_super { - receiver: obj as *mut T as *mut Object as *mut _, + receiver: receiver as *mut _, super_class: superclass as *const Class as *const _, }; let receiver = &sup as *const objc_super as *mut Object; let msg_send_fn = R::MSG_SEND_SUPER; - objc_try!({ A::invoke(msg_send_fn, receiver, sel, args) }) + conditional_try(|| A::invoke(msg_send_fn, receiver, sel, args)) } diff --git a/objc2/src/message/gnustep.rs b/objc2/src/message/gnustep.rs index 19fbe4df0..0f8168107 100644 --- a/objc2/src/message/gnustep.rs +++ b/objc2/src/message/gnustep.rs @@ -1,40 +1,40 @@ use core::mem; use objc2_sys::{objc_msg_lookup, objc_msg_lookup_super, objc_super}; -use super::{Encode, Message, MessageArguments, MessageError}; +use super::{conditional_try, Encode, MessageArguments, MessageError}; use crate::runtime::{Class, Object, Sel}; -pub unsafe fn send_unverified(obj: *const T, sel: Sel, args: A) -> Result +pub unsafe fn send_unverified( + receiver: *mut Object, + sel: Sel, + args: A, +) -> Result where - T: Message, A: MessageArguments, R: Encode, { - if obj.is_null() { + if receiver.is_null() { return mem::zeroed(); } - let receiver = obj as *mut T as *mut Object; let msg_send_fn = objc_msg_lookup(receiver as *mut _, sel.as_ptr() as *const _); - objc_try!({ A::invoke(msg_send_fn.expect("Null IMP"), receiver, sel, args) }) + conditional_try(|| A::invoke(msg_send_fn.expect("Null IMP"), receiver, sel, args)) } -pub unsafe fn send_super_unverified( - obj: *const T, +pub unsafe fn send_super_unverified( + receiver: *mut Object, superclass: &Class, sel: Sel, args: A, ) -> Result where - T: Message, A: MessageArguments, R: Encode, { - let receiver = obj as *mut T as *mut Object; let sup = objc_super { receiver: receiver as *mut _, super_class: superclass as *const Class as *const _, }; let msg_send_fn = objc_msg_lookup_super(&sup, sel.as_ptr() as *const _); - objc_try!({ A::invoke(msg_send_fn.expect("Null IMP"), receiver, sel, args) }) + conditional_try(|| A::invoke(msg_send_fn.expect("Null IMP"), receiver, sel, args)) } diff --git a/objc2/src/message/mod.rs b/objc2/src/message/mod.rs index a36c78b80..94daec505 100644 --- a/objc2/src/message/mod.rs +++ b/objc2/src/message/mod.rs @@ -1,30 +1,29 @@ use alloc::string::{String, ToString}; use core::fmt; use core::mem; +use core::ptr::NonNull; use std::error::Error; +use crate::rc::{Id, Ownership}; use crate::runtime::{Class, Imp, Object, Sel}; use crate::{Encode, EncodeArguments, RefEncode}; #[cfg(feature = "exception")] -macro_rules! objc_try { - ($b:block) => { - $crate::exception::catch_exception(|| $b).map_err(|exception| { - use alloc::borrow::ToOwned; - if exception.is_null() { - MessageError("Uncaught exception nil".to_owned()) - } else { - MessageError(alloc::format!("Uncaught exception {:?}", &**exception)) - } - }) - }; +unsafe fn conditional_try(f: impl FnOnce() -> R) -> Result { + use alloc::borrow::ToOwned; + crate::exception::catch_exception(f).map_err(|exception| { + if let Some(exception) = exception { + MessageError(alloc::format!("Uncaught exception {:?}", exception)) + } else { + MessageError("Uncaught exception nil".to_owned()) + } + }) } #[cfg(not(feature = "exception"))] -macro_rules! objc_try { - ($b:block) => { - Ok($b) - }; +#[inline(always)] +unsafe fn conditional_try(f: impl FnOnce() -> R) -> Result { + Ok(f()) } mod verify; @@ -39,94 +38,218 @@ mod platform; use self::platform::{send_super_unverified, send_unverified}; use self::verify::{verify_message_signature, VerificationError}; -/// This trait marks types that can be sent Objective-C messages. +/// Types that can be sent Objective-C messages. /// /// Examples include objects, classes, and blocks. /// -/// Implementing this allows using pointers and references to the type as the +/// Implementing this provides [`MessageReceiver`] implementations for common +/// pointer types and references to the type, which allows using them as the /// receiver (first argument) in the [`msg_send!`][`crate::msg_send`] macro. /// /// # Safety /// -/// The type must implement [`RefEncode`] and adhere to the safety guidelines -/// therein. -/// /// A pointer to the type must be able to be the receiver of an Objective-C /// message sent with [`objc_msgSend`] or similar. /// +/// Additionally, the type must implement [`RefEncode`] and adhere to the +/// safety requirements therein. +/// /// [`objc_msgSend`]: https://developer.apple.com/documentation/objectivec/1456712-objc_msgsend -pub unsafe trait Message: RefEncode { - /** - Sends a message to self with the given selector and arguments. +pub unsafe trait Message: RefEncode {} + +unsafe impl Message for Object {} + +unsafe impl Message for Class {} + +// TODO: Make this fully private +pub(crate) mod private { + use super::{Id, Message, NonNull, Ownership}; + + pub trait Sealed {} - The correct version of `objc_msgSend` will be chosen based on the - return type. For more information, see Apple's documentation: - + impl Sealed for *const T {} + impl Sealed for *mut T {} + + impl<'a, T: Message + ?Sized> Sealed for &'a T {} + impl<'a, T: Message + ?Sized> Sealed for &'a mut T {} + impl Sealed for NonNull {} + impl Sealed for Id {} +} - If the selector is known at compile-time, it is recommended to use the - `msg_send!` macro rather than this method. - */ +/// Types that can directly be used as the receiver of Objective-C messages. +/// +/// This is a sealed trait (for now) that is automatically implemented for +/// pointers to types implementing [`Message`], so that code can be generic +/// over the message receiver. +/// +/// This is mostly an implementation detail; you'll want to implement +/// [`Message`] for your type instead. +/// +/// # Safety +/// +/// [`Self::as_raw_receiver`] must be implemented correctly. +pub unsafe trait MessageReceiver: private::Sealed { + /// Get a raw pointer to the receiver of the message. + fn as_raw_receiver(&self) -> *mut Object; + + /// Sends a message to self with the given selector and arguments. + /// + /// The correct version of `objc_msgSend` will be chosen based on the + /// return type. For more information, see the section on "Sending + /// Messages" in Apple's [documentation][runtime]. + /// + /// If the selector is known at compile-time, it is recommended to use the + /// [`msg_send!`][`crate::msg_send`] macro rather than this method. + /// + /// [runtime]: https://developer.apple.com/documentation/objectivec/objective-c_runtime?language=objc + #[cfg_attr(feature = "verify_message", inline(always))] unsafe fn send_message(&self, sel: Sel, args: A) -> Result where - Self: Sized, - A: MessageArguments + EncodeArguments, + A: MessageArguments, R: Encode, { - send_message(self, sel, args) + let this = self.as_raw_receiver(); + #[cfg(feature = "verify_message")] + { + let cls = if this.is_null() { + return Err(VerificationError::NilReceiver(sel).into()); + } else { + (*(this as *const Object)).class() + }; + + verify_message_signature::(cls, sel)?; + } + send_unverified(this, sel, args) } - /** - Verifies that the argument and return types match the encoding of the - method for the given selector. - - This will look up the encoding of the method for the given selector, `sel`, - and return a [`MessageError`] if any encodings differ for the arguments `A` - and return type `R`. - - # Example - ``` no_run - # use objc2::{class, msg_send, sel}; - # use objc2::runtime::{BOOL, Class, Object}; - # use objc2::Message; - let obj: &Object; - # obj = unsafe { msg_send![class!(NSObject), new] }; - let sel = sel!(isKindOfClass:); - // Verify isKindOfClass: takes one Class and returns a BOOL - let result = obj.verify_message::<(&Class,), BOOL>(sel); - assert!(result.is_ok()); - ``` - */ + /// Sends a message to self's superclass with the given selector and + /// arguments. + /// + /// The correct version of `objc_msgSend_super` will be chosen based on the + /// return type. For more information, see the section on "Sending + /// Messages" in Apple's [documentation][runtime]. + /// + /// If the selector is known at compile-time, it is recommended to use the + /// [`msg_send!(super)`][`crate::msg_send`] macro rather than this method. + /// + /// [runtime]: https://developer.apple.com/documentation/objectivec/objective-c_runtime?language=objc + #[cfg_attr(feature = "verify_message", inline(always))] + unsafe fn send_super_message( + &self, + superclass: &Class, + sel: Sel, + args: A, + ) -> Result + where + A: MessageArguments, + R: Encode, + { + let this = self.as_raw_receiver(); + #[cfg(feature = "verify_message")] + { + if this.is_null() { + return Err(VerificationError::NilReceiver(sel).into()); + } + verify_message_signature::(superclass, sel)?; + } + send_super_unverified(this, superclass, sel, args) + } + + /// Verify that the argument and return types match the encoding of the + /// method for the given selector. + /// + /// This will look up the encoding of the method for the given selector, + /// `sel`, and return a [`MessageError`] if any encodings differ for the + /// arguments `A` and return type `R`. + /// + /// # Example + /// ``` no_run + /// # use objc2::{class, msg_send, sel}; + /// # use objc2::runtime::{BOOL, Class, Object}; + /// # use objc2::MessageReceiver; + /// let obj: &Object; + /// # obj = unsafe { msg_send![class!(NSObject), new] }; + /// let sel = sel!(isKindOfClass:); + /// // Verify isKindOfClass: takes one Class and returns a BOOL + /// let result = obj.verify_message::<(&Class,), BOOL>(sel); + /// assert!(result.is_ok()); + /// ``` fn verify_message(&self, sel: Sel) -> Result<(), MessageError> where - Self: Sized, A: EncodeArguments, R: Encode, { - let obj = unsafe { &*(self as *const _ as *const Object) }; + let obj = unsafe { &*self.as_raw_receiver() }; verify_message_signature::(obj.class(), sel).map_err(MessageError::from) } } -unsafe impl Message for Object {} +// Note that we implement MessageReceiver for unsized types as well, this is +// to support `extern type`s in the future, not because we want to allow DSTs. -unsafe impl Message for Class {} +unsafe impl MessageReceiver for *const T { + #[inline] + fn as_raw_receiver(&self) -> *mut Object { + *self as *mut T as *mut Object + } +} + +unsafe impl MessageReceiver for *mut T { + #[inline] + fn as_raw_receiver(&self) -> *mut Object { + *self as *mut Object + } +} + +unsafe impl<'a, T: Message + ?Sized> MessageReceiver for &'a T { + #[inline] + fn as_raw_receiver(&self) -> *mut Object { + *self as *const T as *mut T as *mut Object + } +} + +unsafe impl<'a, T: Message + ?Sized> MessageReceiver for &'a mut T { + #[inline] + fn as_raw_receiver(&self) -> *mut Object { + *self as *const T as *mut T as *mut Object + } +} + +unsafe impl MessageReceiver for NonNull { + #[inline] + fn as_raw_receiver(&self) -> *mut Object { + self.as_ptr() as *mut Object + } +} + +unsafe impl MessageReceiver for Id { + #[inline] + fn as_raw_receiver(&self) -> *mut Object { + // TODO: Maybe don't dereference here, just to be safe? + (&**self).as_raw_receiver() + } +} /// Types that may be used as the arguments of an Objective-C message. -pub trait MessageArguments: Sized { +pub trait MessageArguments: EncodeArguments { /// Invoke an [`Imp`] with the given object, selector, and arguments. /// /// This method is the primitive used when sending messages and should not /// be called directly; instead, use the `msg_send!` macro or, in cases - /// with a dynamic selector, the [`Message::send_message`] method. - unsafe fn invoke(imp: Imp, obj: *mut Object, sel: Sel, args: Self) -> R; + /// with a dynamic selector, the [`MessageReceiver::send_message`] method. + unsafe fn invoke(imp: Imp, obj: *mut Object, sel: Sel, args: Self) -> R; } macro_rules! message_args_impl { ($($a:ident : $t:ident),*) => ( - impl<$($t),*> MessageArguments for ($($t,)*) { - unsafe fn invoke(imp: Imp, obj: *mut Object, sel: Sel, ($($a,)*): Self) -> R { - let imp: unsafe extern fn(*mut Object, Sel $(, $t)*) -> R = - mem::transmute(imp); + impl<$($t: Encode),*> MessageArguments for ($($t,)*) { + #[inline] + unsafe fn invoke(imp: Imp, obj: *mut Object, sel: Sel, ($($a,)*): Self) -> R { + // The imp must be cast to the appropriate function pointer + // type before being called; the msgSend functions are not + // parametric, but instead "trampolines" to the actual + // method implementations. + let imp: unsafe extern "C" fn(*mut Object, Sel $(, $t)*) -> R = mem::transmute(imp); imp(obj, sel $(, $a)*) } } @@ -202,50 +325,6 @@ impl<'a> From> for MessageError { } } -#[doc(hidden)] -#[cfg_attr(feature = "verify_message", inline(always))] -pub unsafe fn send_message(obj: *const T, sel: Sel, args: A) -> Result -where - T: Message, - A: MessageArguments + EncodeArguments, - R: Encode, -{ - #[cfg(feature = "verify_message")] - { - let cls = if obj.is_null() { - return Err(VerificationError::NilReceiver(sel).into()); - } else { - (*(obj as *const Object)).class() - }; - - verify_message_signature::(cls, sel)?; - } - send_unverified(obj, sel, args) -} - -#[doc(hidden)] -#[cfg_attr(feature = "verify_message", inline(always))] -pub unsafe fn send_super_message( - obj: *const T, - superclass: &Class, - sel: Sel, - args: A, -) -> Result -where - T: Message, - A: MessageArguments + EncodeArguments, - R: Encode, -{ - #[cfg(feature = "verify_message")] - { - if obj.is_null() { - return Err(VerificationError::NilReceiver(sel).into()); - } - verify_message_signature::(superclass, sel)?; - } - send_super_unverified(obj, superclass, sel, args) -} - #[cfg(test)] mod tests { use super::*; @@ -255,7 +334,7 @@ mod tests { fn test_send_message() { let obj = test_utils::custom_object(); let result: u32 = unsafe { - let _: () = msg_send![obj, setFoo:4u32]; + let _: () = msg_send![obj, setFoo: 4u32]; msg_send![obj, foo] }; assert!(result == 4); @@ -293,7 +372,7 @@ mod tests { let obj = test_utils::custom_subclass_object(); let superclass = test_utils::custom_class(); unsafe { - let _: () = msg_send![obj, setFoo:4u32]; + let _: () = msg_send![obj, setFoo: 4u32]; let foo: u32 = msg_send![super(obj, superclass), foo]; assert!(foo == 4); diff --git a/objc2/src/runtime.rs b/objc2/src/runtime.rs index 374663771..428a2ab67 100644 --- a/objc2/src/runtime.rs +++ b/objc2/src/runtime.rs @@ -533,7 +533,7 @@ mod tests { #[test] fn test_protocol_method() { let class = test_utils::custom_class(); - let result: i32 = unsafe { msg_send![class, addNumber:1 toNumber:2] }; + let result: i32 = unsafe { msg_send![class, addNumber: 1, toNumber: 2] }; assert_eq!(result, 3); } diff --git a/objc2/src/test_utils.rs b/objc2/src/test_utils.rs index b7be60377..3d33b6794 100644 --- a/objc2/src/test_utils.rs +++ b/objc2/src/test_utils.rs @@ -4,7 +4,7 @@ use std::sync::Once; use crate::declare::{ClassDecl, ProtocolDecl}; use crate::runtime::{self, Class, Object, Protocol, Sel}; -use crate::{Encode, Encoding}; +use crate::{Encode, Encoding, MessageReceiver}; pub struct CustomObject { obj: *mut Object, @@ -18,6 +18,16 @@ impl CustomObject { } } +// TODO: Remove the need for this hack +impl crate::message::private::Sealed for CustomObject {} + +unsafe impl MessageReceiver for CustomObject { + #[inline] + fn as_raw_receiver(&self) -> *mut Object { + self.obj + } +} + impl Deref for CustomObject { type Target = Object; diff --git a/objc2_foundation/examples/custom_class.rs b/objc2_foundation/examples/custom_class.rs index 907cef8a1..e1f3916b1 100644 --- a/objc2_foundation/examples/custom_class.rs +++ b/objc2_foundation/examples/custom_class.rs @@ -82,7 +82,7 @@ fn main() { }); unsafe { - let _: () = msg_send![obj, setNumber:12u32]; + let _: () = msg_send![obj, setNumber: 12u32]; } println!("Number: {}", obj.number()); } diff --git a/objc2_foundation/src/array.rs b/objc2_foundation/src/array.rs index 94c15bc21..b78b13add 100644 --- a/objc2_foundation/src/array.rs +++ b/objc2_foundation/src/array.rs @@ -77,8 +77,11 @@ where { let cls = A::class(); let obj: *mut A = msg_send![cls, alloc]; - let obj: *mut A = msg_send![obj, initWithObjects:refs.as_ptr() - count:refs.len()]; + let obj: *mut A = msg_send![ + obj, + initWithObjects: refs.as_ptr(), + count: refs.len(), + ]; Id::new(NonNull::new_unchecked(obj)) } @@ -135,7 +138,7 @@ pub trait INSArray: INSObject { let range = NSRange::from_range(range); let mut vec = Vec::with_capacity(range.length); unsafe { - let _: () = msg_send![self, getObjects:vec.as_ptr() range:range]; + let _: () = msg_send![self, getObjects: vec.as_ptr(), range: range]; vec.set_len(range.length); } vec @@ -254,13 +257,13 @@ pub type NSSharedArray = NSArray; pub trait INSMutableArray: INSArray { fn add_object(&mut self, obj: Id) { unsafe { - let _: () = msg_send![self, addObject:&*obj]; + let _: () = msg_send![self, addObject: &*obj]; } } fn insert_object_at(&mut self, index: usize, obj: Id) { unsafe { - let _: () = msg_send![self, insertObject:&*obj atIndex:index]; + let _: () = msg_send![self, insertObject: &*obj, atIndex: index]; } } @@ -274,8 +277,11 @@ pub trait INSMutableArray: INSArray { Id::retain(obj.into()) }; unsafe { - let _: () = msg_send![self, replaceObjectAtIndex:index - withObject:&*obj]; + let _: () = msg_send![ + self, + replaceObjectAtIndex: index, + withObject: &*obj, + ]; } old_obj } @@ -333,7 +339,7 @@ pub trait INSMutableArray: INSArray { let context = &mut closure as *mut F as *mut c_void; unsafe { - let _: () = msg_send![self, sortUsingFunction:f context:context]; + let _: () = msg_send![self, sortUsingFunction: f, context: context]; } // Keep the closure alive until the function has run. drop(closure); diff --git a/objc2_foundation/src/data.rs b/objc2_foundation/src/data.rs index 422d69f8e..33cb925e6 100644 --- a/objc2_foundation/src/data.rs +++ b/objc2_foundation/src/data.rs @@ -35,8 +35,11 @@ pub trait INSData: INSObject { let bytes_ptr = bytes.as_ptr() as *const c_void; unsafe { let obj: *mut Self = msg_send![cls, alloc]; - let obj: *mut Self = msg_send![obj, initWithBytes:bytes_ptr - length:bytes.len()]; + let obj: *mut Self = msg_send![ + obj, + initWithBytes: bytes_ptr, + length: bytes.len(), + ]; Id::new(NonNull::new_unchecked(obj)) } } @@ -56,9 +59,12 @@ pub trait INSData: INSObject { let cls = Self::class(); unsafe { let obj: *mut Self = msg_send![cls, alloc]; - let obj: *mut Self = msg_send![obj, initWithBytesNoCopy:bytes_ptr - length:bytes.len() - deallocator:dealloc]; + let obj: *mut Self = msg_send![ + obj, + initWithBytesNoCopy: bytes_ptr, + length: bytes.len(), + deallocator: dealloc, + ]; core::mem::forget(bytes); Id::new(NonNull::new_unchecked(obj)) } @@ -98,8 +104,11 @@ pub trait INSMutableData: INSData { fn append(&mut self, bytes: &[u8]) { let bytes_ptr = bytes.as_ptr() as *const c_void; unsafe { - let _: () = msg_send![self, appendBytes:bytes_ptr - length:bytes.len()]; + let _: () = msg_send![ + self, + appendBytes: bytes_ptr, + length:bytes.len(), + ]; } } @@ -107,9 +116,12 @@ pub trait INSMutableData: INSData { let range = NSRange::from_range(range); let bytes_ptr = bytes.as_ptr() as *const c_void; unsafe { - let _: () = msg_send![self, replaceBytesInRange:range - withBytes:bytes_ptr - length:bytes.len()]; + let _: () = msg_send![ + self, + replaceBytesInRange:range, + withBytes:bytes_ptr, + length:bytes.len(), + ]; } } diff --git a/objc2_foundation/src/dictionary.rs b/objc2_foundation/src/dictionary.rs index 180f2b27e..5151494a1 100644 --- a/objc2_foundation/src/dictionary.rs +++ b/objc2_foundation/src/dictionary.rs @@ -18,9 +18,12 @@ where let cls = D::class(); let count = min(keys.len(), vals.len()); let obj: *mut D = msg_send![cls, alloc]; - let obj: *mut D = msg_send![obj, initWithObjects:vals.as_ptr() - forKeys:keys.as_ptr() - count:count]; + let obj: *mut D = msg_send![ + obj, + initWithObjects: vals.as_ptr(), + forKeys: keys.as_ptr(), + count: count, + ]; Id::new(NonNull::new_unchecked(obj)) } @@ -48,8 +51,11 @@ pub trait INSDictionary: INSObject { let len = self.count(); let mut keys = Vec::with_capacity(len); unsafe { - let _: () = msg_send![self, getObjects:ptr::null_mut::<&Self::Value>() - andKeys:keys.as_mut_ptr()]; + let _: () = msg_send![ + self, + getObjects: ptr::null_mut::<&Self::Value>(), + andKeys: keys.as_mut_ptr(), + ]; keys.set_len(len); } keys @@ -59,8 +65,11 @@ pub trait INSDictionary: INSObject { let len = self.count(); let mut vals = Vec::with_capacity(len); unsafe { - let _: () = msg_send![self, getObjects:vals.as_mut_ptr() - andKeys:ptr::null_mut::<&Self::Key>()]; + let _: () = msg_send![ + self, + getObjects: vals.as_mut_ptr(), + andKeys: ptr::null_mut::<&Self::Key>(), + ]; vals.set_len(len); } vals @@ -71,8 +80,11 @@ pub trait INSDictionary: INSObject { let mut keys = Vec::with_capacity(len); let mut objs = Vec::with_capacity(len); unsafe { - let _: () = msg_send![self, getObjects:objs.as_mut_ptr() - andKeys:keys.as_mut_ptr()]; + let _: () = msg_send![ + self, + getObjects: objs.as_mut_ptr(), + andKeys: keys.as_mut_ptr(), + ]; keys.set_len(len); objs.set_len(len); } @@ -100,7 +112,10 @@ pub trait INSDictionary: INSObject { } } - fn from_keys_and_objects(keys: &[&T], vals: Vec>) -> Id + fn from_keys_and_objects( + keys: &[&T], + vals: Vec>, + ) -> Id where T: INSCopying, { @@ -166,7 +181,7 @@ where #[cfg(test)] mod tests { use alloc::vec; - use objc2::rc::{Owned, Id}; + use objc2::rc::{Id, Owned}; use super::{INSDictionary, NSDictionary}; use crate::{INSArray, INSObject, INSString, NSObject, NSString}; diff --git a/objc2_foundation/src/enumerator.rs b/objc2_foundation/src/enumerator.rs index 8bd3fe9c9..b1d1fedfe 100644 --- a/objc2_foundation/src/enumerator.rs +++ b/objc2_foundation/src/enumerator.rs @@ -95,9 +95,12 @@ fn enumerate<'a, 'b: 'a, C: INSFastEnumeration>( let count: usize = unsafe { // Reborrow state so that we don't move it let state = &mut *state; - msg_send![object, countByEnumeratingWithState:state - objects:buf.as_mut_ptr() - count:buf.len()] + msg_send![ + object, + countByEnumeratingWithState: state, + objects: buf.as_mut_ptr(), + count: buf.len(), + ] }; if count > 0 { diff --git a/objc2_foundation/src/string.rs b/objc2_foundation/src/string.rs index 5e98a8b9d..ba7c3534a 100644 --- a/objc2_foundation/src/string.rs +++ b/objc2_foundation/src/string.rs @@ -63,9 +63,12 @@ pub trait INSString: INSObject { let bytes = string.as_ptr() as *const c_void; unsafe { let obj: *mut Self = msg_send![cls, alloc]; - let obj: *mut Self = msg_send![obj, initWithBytes:bytes - length:string.len() - encoding:UTF8_ENCODING]; + let obj: *mut Self = msg_send![ + obj, + initWithBytes: bytes, + length: string.len(), + encoding: UTF8_ENCODING, + ]; Id::new(NonNull::new_unchecked(obj)) } } diff --git a/objc2_foundation/src/value.rs b/objc2_foundation/src/value.rs index 9f844aa7e..339e0065d 100644 --- a/objc2_foundation/src/value.rs +++ b/objc2_foundation/src/value.rs @@ -43,8 +43,11 @@ pub trait INSValue: INSObject { let encoding = CString::new(Self::Value::ENCODING.to_string()).unwrap(); unsafe { let obj: *mut Self = msg_send![cls, alloc]; - let obj: *mut Self = msg_send![obj, initWithBytes:bytes - objCType:encoding.as_ptr()]; + let obj: *mut Self = msg_send![ + obj, + initWithBytes: bytes, + objCType: encoding.as_ptr(), + ]; Id::new(NonNull::new_unchecked(obj)) } }