Skip to content

Commit

Permalink
Added a verify_message_signature function.
Browse files Browse the repository at this point in the history
  • Loading branch information
SSheldon committed Nov 7, 2015
1 parent 06cb282 commit c6756b5
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ mod exception;
#[cfg(any(test, feature = "exception"))]
mod id;
mod message;
mod verify;

#[cfg(test)]
mod test_utils;
68 changes: 68 additions & 0 deletions src/verify.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use runtime::{Class, Object, Sel};
use {Encode, Encoding};

pub trait EncodeArguments {
fn encodings() -> Box<[Encoding]>;
}

macro_rules! encode_args_impl {
($($t:ident),*) => (
impl<$($t: Encode),*> EncodeArguments for ($($t,)*) {
fn encodings() -> Box<[Encoding]> {
Box::new([
<*mut Object>::encode(),
Sel::encode(),
$($t::encode()),*
])
}
}
);
}

encode_args_impl!();
encode_args_impl!(A);
encode_args_impl!(A, B);
encode_args_impl!(A, B, C);
encode_args_impl!(A, B, C, D);
encode_args_impl!(A, B, C, D, E);
encode_args_impl!(A, B, C, D, E, F);
encode_args_impl!(A, B, C, D, E, F, G);
encode_args_impl!(A, B, C, D, E, F, G, H);
encode_args_impl!(A, B, C, D, E, F, G, H, I);
encode_args_impl!(A, B, C, D, E, F, G, H, I, J);
encode_args_impl!(A, B, C, D, E, F, G, H, I, J, K);
encode_args_impl!(A, B, C, D, E, F, G, H, I, J, K, L);

pub fn verify_message_signature<A, R>(cls: &Class, sel: Sel) -> Result<(), String>
where A: EncodeArguments, R: Encode {
let method = match cls.instance_method(sel) {
Some(method) => method,
None => return Err(format!("Method {:?} not found on class {:?}",
sel, cls)),
};

let ret = R::encode();
let expected_ret = method.return_type();
if ret != expected_ret {
return Err(format!("Return type code {:?} does not match expected {:?} for method {:?}",
ret, expected_ret, method.name()));
}

let args = A::encodings();
let count = args.len();
let expected_count = method.arguments_count();
if count != expected_count {
return Err(format!("Method {:?} accepts {} arguments, but {} were given",
method.name(), expected_count, count));
}

for (i, arg) in args.iter().enumerate() {
let expected = method.argument_type(i).unwrap();
if *arg != expected {
return Err(format!("Method {:?} expected argument at index {} with type code {:?} but was given {:?}",
method.name(), i, expected, arg));
}
}

Ok(())
}

0 comments on commit c6756b5

Please sign in to comment.