1 use runtime::{Class, Object, Sel};
2 use {Encode, EncodeArguments};
3 use super::MessageError;
4 
verify_message_signature<A, R>(cls: &Class, sel: Sel) -> Result<(), MessageError> where A: EncodeArguments, R: Encode5 pub fn verify_message_signature<A, R>(cls: &Class, sel: Sel)
6         -> Result<(), MessageError>
7         where A: EncodeArguments, R: Encode {
8     let method = match cls.instance_method(sel) {
9         Some(method) => method,
10         None => return Err(MessageError(
11             format!("Method {:?} not found on class {:?}",
12                 sel, cls)
13         )),
14     };
15 
16     let ret = R::encode();
17     let expected_ret = method.return_type();
18     if ret != expected_ret {
19         return Err(MessageError(
20             format!("Return type code {:?} does not match expected {:?} for method {:?}",
21                 ret, expected_ret, method.name())
22         ));
23     }
24 
25     let self_and_cmd = [<*mut Object>::encode(), Sel::encode()];
26     let args = A::encodings();
27     let args = args.as_ref();
28 
29     let count = self_and_cmd.len() + args.len();
30     let expected_count = method.arguments_count();
31     if count != expected_count {
32         return Err(MessageError(
33             format!("Method {:?} accepts {} arguments, but {} were given",
34                 method.name(), expected_count, count)
35         ));
36     }
37 
38     for (i, arg) in self_and_cmd.iter().chain(args).enumerate() {
39         let expected = method.argument_type(i).unwrap();
40         if *arg != expected {
41             return Err(MessageError(
42                 format!("Method {:?} expected argument at index {} with type code {:?} but was given {:?}",
43                     method.name(), i, expected, arg)
44             ));
45         }
46     }
47 
48     Ok(())
49 }
50