1use std::any::Any;
2use std::error::Error;
3use std::fmt;
4use std::mem;
5
6use crate::runtime::{Class, Imp, Object, Sel};
7use crate::{Encode, EncodeArguments};
8
9#[cfg(feature = "exception")]
10macro_rules! objc_try {
11 ($b:block) => {
12 $crate::exception::r#try(|| $b).map_err(|exception| {
13 if exception.is_null() {
14 MessageError("Uncaught exception nil".to_owned())
15 } else {
16 MessageError(format!("Uncaught exception {:?}", &**exception))
17 }
18 })
19 };
20}
21
22#[cfg(not(feature = "exception"))]
23macro_rules! objc_try {
24 ($b:block) => {
25 Ok($b)
26 };
27}
28
29mod verify;
30
31#[cfg(any(target_os = "macos", target_os = "ios"))]
32#[path = "apple/mod.rs"]
33mod platform;
34#[cfg(not(any(target_os = "macos", target_os = "ios")))]
35#[path = "gnustep.rs"]
36mod platform;
37
38use self::platform::{send_super_unverified, send_unverified};
39use self::verify::verify_message_signature;
40
41#[repr(C)]
43pub struct Super {
44 pub receiver: *mut Object,
46 pub superclass: *const Class,
48}
49
50pub unsafe trait Message {
53 #[cfg(not(feature = "verify_message"))]
64 unsafe fn send_message<A, R>(&self, sel: Sel, args: A) -> Result<R, MessageError>
65 where
66 Self: Sized,
67 A: MessageArguments,
68 R: Any,
69 {
70 unsafe { send_message(self, sel, args) }
71 }
72
73 #[cfg(feature = "verify_message")]
74 unsafe fn send_message<A, R>(&self, sel: Sel, args: A) -> Result<R, MessageError>
75 where
76 Self: Sized,
77 A: MessageArguments + EncodeArguments,
78 R: Any + Encode,
79 {
80 unsafe { send_message(self, sel, args) }
81 }
82
83 fn verify_message<A, R>(&self, sel: Sel) -> Result<(), MessageError>
107 where
108 Self: Sized,
109 A: EncodeArguments,
110 R: Encode,
111 {
112 let obj = unsafe { &*(self as *const _ as *const Object) };
113 verify_message_signature::<A, R>(obj.class(), sel)
114 }
115}
116
117unsafe impl Message for Object {}
118
119unsafe impl Message for Class {}
120
121pub trait MessageArguments: Sized {
123 unsafe fn invoke<R>(imp: Imp, obj: *mut Object, sel: Sel, args: Self) -> R
129 where
130 R: Any;
131}
132
133macro_rules! message_args_impl {
134 ($($a:ident : $t:ident),*) => (
135 impl<$($t),*> MessageArguments for ($($t,)*) {
136 unsafe fn invoke<R>(imp: Imp, obj: *mut Object, sel: Sel, ($($a,)*): Self) -> R
137 where R: Any {
138 unsafe {
139 let imp: unsafe extern "C" fn(*mut Object, Sel $(, $t)*) -> R =
140 mem::transmute(imp);
141 imp(obj, sel $(, $a)*)
142 }
143 }
144 }
145 );
146}
147
148message_args_impl!();
149message_args_impl!(a: A);
150message_args_impl!(a: A, b: B);
151message_args_impl!(a: A, b: B, c: C);
152message_args_impl!(a: A, b: B, c: C, d: D);
153message_args_impl!(a: A, b: B, c: C, d: D, e: E);
154message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F);
155message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G);
156message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H);
157message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I);
158message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J);
159message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K);
160message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L);
161
162#[derive(Debug)]
172pub struct MessageError(String);
173
174impl fmt::Display for MessageError {
175 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
176 fmt::Display::fmt(&self.0, f)
177 }
178}
179
180impl Error for MessageError {
181 fn description(&self) -> &str {
182 &self.0
183 }
184}
185
186#[doc(hidden)]
187#[inline(always)]
188#[cfg(not(feature = "verify_message"))]
189pub unsafe fn send_message<T, A, R>(obj: *const T, sel: Sel, args: A) -> Result<R, MessageError>
190where
191 T: Message,
192 A: MessageArguments,
193 R: Any,
194{
195 unsafe { send_unverified(obj, sel, args) }
196}
197
198#[doc(hidden)]
199#[inline(always)]
200#[cfg(feature = "verify_message")]
201pub unsafe fn send_message<T, A, R>(obj: *const T, sel: Sel, args: A) -> Result<R, MessageError>
202where
203 T: Message,
204 A: MessageArguments + EncodeArguments,
205 R: Any + Encode,
206{
207 let cls = if obj.is_null() {
208 return Err(MessageError(format!("Messaging {:?} to nil", sel)));
209 } else {
210 unsafe { (*(obj as *const Object)).class() }
211 };
212
213 verify_message_signature::<A, R>(cls, sel)
214 .and_then(|_| unsafe { send_unverified(obj, sel, args) })
215}
216
217#[doc(hidden)]
218#[inline(always)]
219#[cfg(not(feature = "verify_message"))]
220pub unsafe fn send_super_message<T, A, R>(
221 obj: *const T,
222 superclass: &Class,
223 sel: Sel,
224 args: A,
225) -> Result<R, MessageError>
226where
227 T: Message,
228 A: MessageArguments,
229 R: Any,
230{
231 unsafe { send_super_unverified(obj, superclass, sel, args) }
232}
233
234#[doc(hidden)]
235#[inline(always)]
236#[cfg(feature = "verify_message")]
237pub unsafe fn send_super_message<T, A, R>(
238 obj: *const T,
239 superclass: &Class,
240 sel: Sel,
241 args: A,
242) -> Result<R, MessageError>
243where
244 T: Message,
245 A: MessageArguments + EncodeArguments,
246 R: Any + Encode,
247{
248 if obj.is_null() {
249 return Err(MessageError(format!("Messaging {:?} to nil", sel)));
250 }
251
252 verify_message_signature::<A, R>(superclass, sel)
253 .and_then(|_| unsafe { send_super_unverified(obj, superclass, sel, args) })
254}
255
256#[cfg(test)]
257mod tests {
258 use super::Message;
259 use crate::runtime::Object;
260 use crate::test_utils;
261
262 #[test]
263 fn test_send_message() {
264 let obj = test_utils::custom_object();
265 let result: u32 = unsafe {
266 let _: () = msg_send![obj, setFoo:4u32];
267 msg_send![obj, foo]
268 };
269 assert!(result == 4);
270 }
271
272 #[test]
273 fn test_send_message_stret() {
274 let obj = test_utils::custom_object();
275 let result: test_utils::CustomStruct = unsafe { msg_send![obj, customStruct] };
276 let expected = test_utils::CustomStruct {
277 a: 1,
278 b: 2,
279 c: 3,
280 d: 4,
281 };
282 assert!(result == expected);
283 }
284
285 #[cfg(not(feature = "verify_message"))]
286 #[test]
287 fn test_send_message_nil() {
288 let nil: *mut Object = ::std::ptr::null_mut();
289 let result: usize = unsafe { msg_send![nil, hash] };
290 assert!(result == 0);
291
292 let result: *mut Object = unsafe { msg_send![nil, description] };
293 assert!(result.is_null());
294
295 let result: f64 = unsafe { msg_send![nil, doubleValue] };
296 assert!(result == 0.0);
297 }
298
299 #[test]
300 fn test_send_message_super() {
301 let obj = test_utils::custom_subclass_object();
302 let superclass = test_utils::custom_class();
303 unsafe {
304 let _: () = msg_send![obj, setFoo:4u32];
305 let foo: u32 = msg_send![super(obj, superclass), foo];
306 assert!(foo == 4);
307
308 let foo: u32 = msg_send![obj, foo];
310 assert!(foo == 6);
311 }
312 }
313
314 #[test]
315 fn test_verify_message() {
316 let obj = test_utils::custom_object();
317 assert!(obj.verify_message::<(), u32>(sel!(foo)).is_ok());
318 assert!(obj.verify_message::<(u32,), ()>(sel!(setFoo:)).is_ok());
319
320 assert!(obj.verify_message::<(), u64>(sel!(setFoo:)).is_err());
322 assert!(obj.verify_message::<(u32,), ()>(sel!(setFoo)).is_err());
324 }
325}