diff --git a/src/message/mod.rs b/src/message/mod.rs index 53ac67fc0..efc992166 100644 --- a/src/message/mod.rs +++ b/src/message/mod.rs @@ -4,6 +4,7 @@ use std::fmt; use std::mem; use runtime::{Class, Imp, Object, Sel}; +use {Encode, EncodeArguments}; mod verify; @@ -28,6 +29,7 @@ mod platform; mod platform; use self::platform::{msg_send_fn, msg_send_super_fn}; +use self::verify::verify_message_signature; /// Specifies the superclass of an instance. #[repr(C)] @@ -61,10 +63,17 @@ pub unsafe trait Message { #[cfg(feature = "verify_message")] unsafe fn send_message(&self, sel: Sel, args: A) -> Result - where Self: Sized, A: MessageArguments + ::EncodeArguments, - R: Any + ::Encode { + where Self: Sized, A: MessageArguments + EncodeArguments, + R: Any + Encode { send_message(self, sel, args) } + + fn verify_message(&self, sel: Sel) -> Result<(), MessageError> + where Self: Sized, A: MessageArguments + EncodeArguments, + R: Any + Encode { + let obj = unsafe { &*(self as *const _ as *const Object) }; + verify_message_signature::(obj.class(), sel) + } } unsafe impl Message for Object { } @@ -171,10 +180,8 @@ pub unsafe fn send_message(obj: *const T, sel: Sel, args: A) #[cfg(feature = "verify_message")] pub unsafe fn send_message(obj: *const T, sel: Sel, args: A) -> Result - where T: Message, A: MessageArguments + ::EncodeArguments, - R: Any + ::Encode { - use self::verify::verify_message_signature; - + where T: Message, A: MessageArguments + EncodeArguments, + R: Any + Encode { let cls = if obj.is_null() { return Err(MessageError(format!("Messaging {:?} to nil", sel))); } else { @@ -210,10 +217,8 @@ pub unsafe fn send_super_message(obj: *const T, superclass: &Class, #[cfg(feature = "verify_message")] pub unsafe fn send_super_message(obj: *const T, superclass: &Class, sel: Sel, args: A) -> Result - where T: Message, A: MessageArguments + ::EncodeArguments, - R: Any + ::Encode { - use self::verify::verify_message_signature; - + where T: Message, A: MessageArguments + EncodeArguments, + R: Any + Encode { if obj.is_null() { return Err(MessageError(format!("Messaging {:?} to nil", sel))); } @@ -225,8 +230,9 @@ pub unsafe fn send_super_message(obj: *const T, superclass: &Class, #[cfg(test)] mod tests { - use runtime::Object; use test_utils; + use runtime::Object; + use super::Message; #[test] fn test_send_message() { @@ -281,4 +287,16 @@ mod tests { assert!(foo == 6); } } + + #[test] + fn test_verify_message() { + let obj = test_utils::custom_object(); + assert!(obj.verify_message::<(), u32>(sel!(foo)).is_ok()); + assert!(obj.verify_message::<(u32,), ()>(sel!(setFoo:)).is_ok()); + + // Incorrect types + assert!(obj.verify_message::<(), u64>(sel!(setFoo:)).is_err()); + // Unimplemented selector + assert!(obj.verify_message::<(u32,), ()>(sel!(setFoo)).is_err()); + } } diff --git a/src/message/verify.rs b/src/message/verify.rs index 522ce3ff5..f65900acc 100644 --- a/src/message/verify.rs +++ b/src/message/verify.rs @@ -1,5 +1,3 @@ -#![cfg_attr(not(feature = "verify_message"), allow(dead_code))] - use runtime::{Class, Sel}; use {Encode, EncodeArguments}; use super::MessageError;