Skip to content

Commit b8dc92e

Browse files
committed
Added VerificationError to replace formatted Strings
1 parent 7358162 commit b8dc92e

File tree

2 files changed

+61
-31
lines changed

2 files changed

+61
-31
lines changed

src/message/mod.rs

+14-9
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ mod platform;
3434
mod platform;
3535

3636
use self::platform::{send_unverified, send_super_unverified};
37-
use self::verify::verify_message_signature;
37+
use self::verify::{VerificationError, verify_message_signature};
3838

3939
/// Specifies the superclass of an instance.
4040
#[repr(C)]
@@ -100,6 +100,7 @@ pub unsafe trait Message {
100100
where Self: Sized, A: EncodeArguments, R: Encode {
101101
let obj = unsafe { &*(self as *const _ as *const Object) };
102102
verify_message_signature::<A, R>(obj.class(), sel)
103+
.map_err(MessageError::from)
103104
}
104105
}
105106

@@ -169,6 +170,12 @@ impl Error for MessageError {
169170
}
170171
}
171172

173+
impl<'a> From<VerificationError<'a>> for MessageError {
174+
fn from(err: VerificationError) -> MessageError {
175+
MessageError(err.to_string())
176+
}
177+
}
178+
172179
#[doc(hidden)]
173180
#[inline(always)]
174181
#[cfg(not(feature = "verify_message"))]
@@ -186,14 +193,13 @@ pub unsafe fn send_message<T, A, R>(obj: *const T, sel: Sel, args: A)
186193
where T: Message, A: MessageArguments + EncodeArguments,
187194
R: Any + Encode {
188195
let cls = if obj.is_null() {
189-
return Err(MessageError(format!("Messaging {:?} to nil", sel)));
196+
return Err(VerificationError::NilReceiver(sel).into());
190197
} else {
191198
(*(obj as *const Object)).class()
192199
};
193200

194-
verify_message_signature::<A, R>(cls, sel).and_then(|_| {
195-
send_unverified(obj, sel, args)
196-
})
201+
verify_message_signature::<A, R>(cls, sel)?;
202+
send_unverified(obj, sel, args)
197203
}
198204

199205
#[doc(hidden)]
@@ -213,12 +219,11 @@ pub unsafe fn send_super_message<T, A, R>(obj: *const T, superclass: &Class,
213219
where T: Message, A: MessageArguments + EncodeArguments,
214220
R: Any + Encode {
215221
if obj.is_null() {
216-
return Err(MessageError(format!("Messaging {:?} to nil", sel)));
222+
return Err(VerificationError::NilReceiver(sel).into());
217223
}
218224

219-
verify_message_signature::<A, R>(superclass, sel).and_then(|_| {
220-
send_super_unverified(obj, superclass, sel, args)
221-
})
225+
verify_message_signature::<A, R>(superclass, sel)?;
226+
send_super_unverified(obj, superclass, sel, args)
222227
}
223228

224229
#[cfg(test)]

src/message/verify.rs

+47-22
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,56 @@
1-
use crate::runtime::{Class, Object, Sel};
2-
use crate::{Encode, EncodeArguments};
3-
use super::MessageError;
1+
use std::fmt;
2+
3+
use crate::runtime::{Class, Method, Object, Sel};
4+
use crate::{Encode, Encoding, EncodeArguments};
5+
6+
pub enum VerificationError<'a> {
7+
NilReceiver(Sel),
8+
MethodNotFound(&'a Class, Sel),
9+
MismatchedReturn(&'a Method, Encoding<'static>),
10+
MismatchedArgumentsCount(&'a Method, usize),
11+
MismatchedArgument(&'a Method, usize, Encoding<'static>),
12+
}
13+
14+
impl<'a> fmt::Display for VerificationError<'a> {
15+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
16+
match *self {
17+
VerificationError::NilReceiver(sel) => {
18+
write!(f, "Messsaging {:?} to nil", sel)
19+
}
20+
VerificationError::MethodNotFound(cls, sel) => {
21+
write!(f, "Method {:?} not found on class {:?}", sel, cls)
22+
}
23+
VerificationError::MismatchedReturn(method, ret) => {
24+
let expected_ret = method.return_type();
25+
write!(f, "Return type code {} does not match expected {} for method {:?}",
26+
ret, expected_ret, method.name())
27+
}
28+
VerificationError::MismatchedArgumentsCount(method, count) => {
29+
let expected_count = method.arguments_count();
30+
write!(f, "Method {:?} accepts {} arguments, but {} were given",
31+
method.name(), expected_count, count)
32+
}
33+
VerificationError::MismatchedArgument(method, i, arg) => {
34+
let expected = method.argument_type(i).unwrap();
35+
write!(f, "Method {:?} expected argument at index {} with type code {:?} but was given {:?}",
36+
method.name(), i, expected, arg)
37+
}
38+
}
39+
}
40+
}
441

542
pub fn verify_message_signature<A, R>(cls: &Class, sel: Sel)
6-
-> Result<(), MessageError>
43+
-> Result<(), VerificationError>
744
where A: EncodeArguments, R: Encode {
845
let method = match cls.instance_method(sel) {
946
Some(method) => method,
10-
None => return Err(MessageError(
11-
format!("Method {:?} not found on class {:?}",
12-
sel, cls)
13-
)),
47+
None => return Err(VerificationError::MethodNotFound(cls, sel)),
1448
};
1549

1650
let ret = R::ENCODING;
1751
let expected_ret = method.return_type();
1852
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-
));
53+
return Err(VerificationError::MismatchedReturn(method, ret));
2354
}
2455

2556
let self_and_cmd = [<*mut Object>::ENCODING, Sel::ENCODING];
@@ -28,19 +59,13 @@ pub fn verify_message_signature<A, R>(cls: &Class, sel: Sel)
2859
let count = self_and_cmd.len() + args.len();
2960
let expected_count = method.arguments_count();
3061
if count != expected_count {
31-
return Err(MessageError(
32-
format!("Method {:?} accepts {} arguments, but {} were given",
33-
method.name(), expected_count, count)
34-
));
62+
return Err(VerificationError::MismatchedArgumentsCount(method, count));
3563
}
3664

37-
for (i, arg) in self_and_cmd.iter().chain(args).enumerate() {
65+
for (i, arg) in self_and_cmd.iter().chain(args).copied().enumerate() {
3866
let expected = method.argument_type(i).unwrap();
39-
if *arg != *expected {
40-
return Err(MessageError(
41-
format!("Method {:?} expected argument at index {} with type code {:?} but was given {:?}",
42-
method.name(), i, expected, arg)
43-
));
67+
if arg != *expected {
68+
return Err(VerificationError::MismatchedArgument(method, i, arg));
4469
}
4570
}
4671

0 commit comments

Comments
 (0)