1use std::any::Any;
2use std::error::Error;
3use std::fmt;
4use std::mem;
5
6use runtime::{Class, Imp, Object, Sel};
7use {Encode, EncodeArguments};
8
9#[cfg(feature = "exception")]
10macro_rules! objc_try {
11 ($b:block) => (
12 $crate::exception::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) => (Ok($b))
25}
26
27mod verify;
28
29#[cfg(any(target_os = "macos", target_os = "ios"))]
30#[path = "apple/mod.rs"]
31mod platform;
32#[cfg(not(any(target_os = "macos", target_os = "ios")))]
33#[path = "gnustep.rs"]
34mod platform;
35
36use self::platform::{send_unverified, send_super_unverified};
37use self::verify::verify_message_signature;
38
39#[repr(C)]
41pub struct Super {
42 pub receiver: *mut Object,
44 pub superclass: *const Class,
46}
47
48pub unsafe trait Message {
51 #[cfg(not(feature = "verify_message"))]
62 unsafe fn send_message<A, R>(&self, sel: Sel, args: A)
63 -> Result<R, MessageError>
64 where Self: Sized, A: MessageArguments, R: Any {
65 send_message(self, sel, args)
66 }
67
68 #[cfg(feature = "verify_message")]
69 unsafe fn send_message<A, R>(&self, sel: Sel, args: A)
70 -> Result<R, MessageError>
71 where Self: Sized, A: MessageArguments + EncodeArguments,
72 R: Any + Encode {
73 send_message(self, sel, args)
74 }
75
76 fn verify_message<A, R>(&self, sel: Sel) -> Result<(), MessageError>
100 where Self: Sized, A: EncodeArguments, R: Encode {
101 let obj = unsafe { &*(self as *const _ as *const Object) };
102 verify_message_signature::<A, R>(obj.class(), sel)
103 }
104}
105
106unsafe impl Message for Object { }
107
108unsafe impl Message for Class { }
109
110pub trait MessageArguments: Sized {
112 unsafe fn invoke<R>(imp: Imp, obj: *mut Object, sel: Sel, args: Self) -> R
118 where R: Any;
119}
120
121macro_rules! message_args_impl {
122 ($($a:ident : $t:ident),*) => (
123 impl<$($t),*> MessageArguments for ($($t,)*) {
124 unsafe fn invoke<R>(imp: Imp, obj: *mut Object, sel: Sel, ($($a,)*): Self) -> R
125 where R: Any {
126 let imp: unsafe extern fn(*mut Object, Sel $(, $t)*) -> R =
127 mem::transmute(imp);
128 imp(obj, sel $(, $a)*)
129 }
130 }
131 );
132}
133
134message_args_impl!();
135message_args_impl!(a: A);
136message_args_impl!(a: A, b: B);
137message_args_impl!(a: A, b: B, c: C);
138message_args_impl!(a: A, b: B, c: C, d: D);
139message_args_impl!(a: A, b: B, c: C, d: D, e: E);
140message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F);
141message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G);
142message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H);
143message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I);
144message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J);
145message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K);
146message_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);
147
148#[derive(Debug)]
158pub struct MessageError(String);
159
160impl fmt::Display for MessageError {
161 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
162 fmt::Display::fmt(&self.0, f)
163 }
164}
165
166impl Error for MessageError {
167 fn description(&self) -> &str {
168 &self.0
169 }
170}
171
172#[doc(hidden)]
173#[inline(always)]
174#[cfg(not(feature = "verify_message"))]
175pub unsafe fn send_message<T, A, R>(obj: *const T, sel: Sel, args: A)
176 -> Result<R, MessageError>
177 where T: Message, A: MessageArguments, R: Any {
178 send_unverified(obj, sel, args)
179}
180
181#[doc(hidden)]
182#[inline(always)]
183#[cfg(feature = "verify_message")]
184pub unsafe fn send_message<T, A, R>(obj: *const T, sel: Sel, args: A)
185 -> Result<R, MessageError>
186 where T: Message, A: MessageArguments + EncodeArguments,
187 R: Any + Encode {
188 let cls = if obj.is_null() {
189 return Err(MessageError(format!("Messaging {:?} to nil", sel)));
190 } else {
191 (*(obj as *const Object)).class()
192 };
193
194 verify_message_signature::<A, R>(cls, sel).and_then(|_| {
195 send_unverified(obj, sel, args)
196 })
197}
198
199#[doc(hidden)]
200#[inline(always)]
201#[cfg(not(feature = "verify_message"))]
202pub unsafe fn send_super_message<T, A, R>(obj: *const T, superclass: &Class,
203 sel: Sel, args: A) -> Result<R, MessageError>
204 where T: Message, A: MessageArguments, R: Any {
205 send_super_unverified(obj, superclass, sel, args)
206}
207
208#[doc(hidden)]
209#[inline(always)]
210#[cfg(feature = "verify_message")]
211pub unsafe fn send_super_message<T, A, R>(obj: *const T, superclass: &Class,
212 sel: Sel, args: A) -> Result<R, MessageError>
213 where T: Message, A: MessageArguments + EncodeArguments,
214 R: Any + Encode {
215 if obj.is_null() {
216 return Err(MessageError(format!("Messaging {:?} to nil", sel)));
217 }
218
219 verify_message_signature::<A, R>(superclass, sel).and_then(|_| {
220 send_super_unverified(obj, superclass, sel, args)
221 })
222}
223
224#[cfg(test)]
225mod tests {
226 use test_utils;
227 use runtime::Object;
228 use super::Message;
229
230 #[test]
231 fn test_send_message() {
232 let obj = test_utils::custom_object();
233 let result: u32 = unsafe {
234 let _: () = msg_send![obj, setFoo:4u32];
235 msg_send![obj, foo]
236 };
237 assert!(result == 4);
238 }
239
240 #[test]
241 fn test_send_message_stret() {
242 let obj = test_utils::custom_object();
243 let result: test_utils::CustomStruct = unsafe {
244 msg_send![obj, customStruct]
245 };
246 let expected = test_utils::CustomStruct { a: 1, b:2, c: 3, d: 4 };
247 assert!(result == expected);
248 }
249
250 #[cfg(not(feature = "verify_message"))]
251 #[test]
252 fn test_send_message_nil() {
253 let nil: *mut Object = ::std::ptr::null_mut();
254 let result: usize = unsafe {
255 msg_send![nil, hash]
256 };
257 assert!(result == 0);
258
259 let result: *mut Object = unsafe {
260 msg_send![nil, description]
261 };
262 assert!(result.is_null());
263
264 let result: f64 = unsafe {
265 msg_send![nil, doubleValue]
266 };
267 assert!(result == 0.0);
268 }
269
270 #[test]
271 fn test_send_message_super() {
272 let obj = test_utils::custom_subclass_object();
273 let superclass = test_utils::custom_class();
274 unsafe {
275 let _: () = msg_send![obj, setFoo:4u32];
276 let foo: u32 = msg_send![super(obj, superclass), foo];
277 assert!(foo == 4);
278
279 let foo: u32 = msg_send![obj, foo];
281 assert!(foo == 6);
282 }
283 }
284
285 #[test]
286 fn test_verify_message() {
287 let obj = test_utils::custom_object();
288 assert!(obj.verify_message::<(), u32>(sel!(foo)).is_ok());
289 assert!(obj.verify_message::<(u32,), ()>(sel!(setFoo:)).is_ok());
290
291 assert!(obj.verify_message::<(), u64>(sel!(setFoo:)).is_err());
293 assert!(obj.verify_message::<(u32,), ()>(sel!(setFoo)).is_err());
295 }
296}