13
13
//! - [Exception Programming Topics for Cocoa](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Exceptions/Exceptions.html)
14
14
//! - [The Objective-C Programming Language - Exception Handling](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocExceptionHandling.html)
15
15
//! - [Exception Handling in LLVM](https://llvm.org/docs/ExceptionHandling.html)
16
+ //!
17
+ //! [`msg_send!`]: crate::msg_send
16
18
17
19
// TODO: Test this with panic=abort, and ensure that the code-size is
18
20
// reasonable in that case.
19
21
20
- use alloc:: string:: String ;
21
- use alloc:: string:: ToString ;
22
22
#[ cfg( feature = "exception" ) ]
23
23
use core:: ffi:: c_void;
24
24
use core:: fmt;
@@ -29,41 +29,16 @@ use core::panic::RefUnwindSafe;
29
29
use core:: panic:: UnwindSafe ;
30
30
#[ cfg( feature = "exception" ) ]
31
31
use core:: ptr;
32
- use core:: slice;
33
32
use objc2_encode:: Encoding ;
34
33
use objc2_encode:: RefEncode ;
35
34
use std:: error:: Error ;
36
- use std:: os:: raw:: c_char;
37
35
38
36
#[ cfg( feature = "exception" ) ]
39
37
use crate :: ffi;
40
- use crate :: rc :: autoreleasepool ;
38
+ # [ cfg ( feature = "exception" ) ]
41
39
use crate :: rc:: { Id , Shared } ;
42
- use crate :: runtime:: Class ;
43
40
use crate :: runtime:: Object ;
44
41
use crate :: Message ;
45
- use crate :: { msg_send, msg_send_bool, msg_send_id, sel} ;
46
-
47
- /// Unfortunate reimplementation of `objc2::foundation::NSString`.
48
- ///
49
- /// I guess this is the price of wanting to do things "right"...
50
- unsafe fn to_string_hack ( obj : Id < Object , Shared > ) -> String {
51
- #[ cfg( feature = "apple" ) ]
52
- const UTF8_ENCODING : usize = 4 ;
53
- #[ cfg( feature = "gnustep-1-7" ) ]
54
- const UTF8_ENCODING : i32 = 4 ;
55
-
56
- autoreleasepool ( |_| {
57
- let len: usize = unsafe { msg_send ! [ & obj, lengthOfBytesUsingEncoding: UTF8_ENCODING ] } ;
58
-
59
- let bytes: * const c_char = unsafe { msg_send ! [ & obj, UTF8String ] } ;
60
- let bytes: * const u8 = bytes. cast ( ) ;
61
- let bytes: & [ u8 ] = unsafe { slice:: from_raw_parts ( bytes, len) } ;
62
-
63
- // Use lossy to avoid panic in error situations
64
- String :: from_utf8_lossy ( bytes) . to_string ( )
65
- } )
66
- }
67
42
68
43
/// An Objective-C exception.
69
44
///
@@ -100,78 +75,45 @@ impl AsRef<Object> for Exception {
100
75
// Note: We can't implement `Send` nor `Sync` since the exception could be
101
76
// anything!
102
77
103
- impl Exception {
104
- /// Checks whether this is an instance of `NSException`.
105
- ///
106
- /// This should be considered a hint; it may return `false` in very, very
107
- /// few cases where it is actually `true`, but if it returns `true`, then
108
- /// it is definitely an instance of `NSException`.
109
- fn is_nsexception ( & self ) -> bool {
110
- // If `NSException` class is present
111
- if let Some ( cls) = Class :: get ( "NSException" ) {
112
- if self . 0 . class ( ) . responds_to ( sel ! ( isKindOfClass: ) ) {
113
- unsafe { msg_send_bool ! [ self , isKindOfClass: cls] }
114
- } else {
115
- false
116
- }
117
- } else {
118
- false
119
- }
120
- }
121
-
122
- // SAFETY: Must ensure that self is NSException
123
- unsafe fn name ( & self ) -> Option < String > {
124
- let obj: Option < Id < Object , Shared > > = unsafe { msg_send_id ! [ self , name] } ;
125
- obj. map ( |obj| unsafe { to_string_hack ( obj) } )
126
- }
127
-
128
- // SAFETY: Must ensure that self is NSException
129
- unsafe fn reason ( & self ) -> Option < String > {
130
- let obj: Option < Id < Object , Shared > > = unsafe { msg_send_id ! [ self , reason] } ;
131
- obj. map ( |obj| unsafe { to_string_hack ( obj) } )
132
- }
133
- }
134
-
135
- // This is not in any way efficient, but that's not really the point!
136
- //
137
- // We mostly just want to present a somewhat usable error message when the
138
- // `catch-all` feature is enabled!
139
78
impl fmt:: Debug for Exception {
140
79
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
141
- write ! ( f, "exception {:?}" , self . 0 ) ?;
142
-
143
- // Attempt to provide better error message
144
- if self . is_nsexception ( ) {
145
- // SAFETY: We know that these are safe to call since this is an
146
- // instance of `NSException`.
147
- let name = unsafe { self . name ( ) } ;
148
- let reason = unsafe { self . reason ( ) } ;
149
-
150
- if let Some ( name) = name {
151
- write ! ( f, " '{}'" , name) ?;
152
- } else {
153
- write ! ( f, " (NULL)" ) ?;
154
- }
155
-
156
- if let Some ( reason) = reason {
157
- write ! ( f, " reason:{}" , reason) ?;
158
- } else {
159
- write ! ( f, " reason:(NULL)" ) ?;
160
- }
80
+ write ! ( f, "exception " ) ?;
81
+
82
+ // Attempt to present a somewhat usable error message if the
83
+ // `foundation` feature is enabled
84
+ #[ cfg( feature = "foundation" ) ]
85
+ if crate :: foundation:: NSException :: is_nsexception ( self ) {
86
+ // SAFETY: Just checked that object is an NSException
87
+ let obj: * const Self = self ;
88
+ let obj = unsafe {
89
+ obj. cast :: < crate :: foundation:: NSException > ( )
90
+ . as_ref ( )
91
+ . unwrap ( )
92
+ } ;
93
+ return write ! ( f, "{:?}" , obj) ;
161
94
}
162
95
163
- Ok ( ( ) )
96
+ // Fall back to `Object` Debug
97
+ write ! ( f, "{:?}" , self . 0 )
164
98
}
165
99
}
166
100
167
101
impl fmt:: Display for Exception {
168
102
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
169
- if self . is_nsexception ( ) {
170
- // SAFETY: Just checked that this is NSException.
171
- if let Some ( reason) = unsafe { self . reason ( ) } {
103
+ #[ cfg( feature = "foundation" ) ]
104
+ if crate :: foundation:: NSException :: is_nsexception ( self ) {
105
+ // SAFETY: Just checked that object is an NSException
106
+ let obj: * const Self = self ;
107
+ let obj = unsafe {
108
+ obj. cast :: < crate :: foundation:: NSException > ( )
109
+ . as_ref ( )
110
+ . unwrap ( )
111
+ } ;
112
+ if let Some ( reason) = obj. reason ( ) {
172
113
return write ! ( f, "{}" , reason) ;
173
114
}
174
115
}
116
+
175
117
write ! ( f, "unknown exception" )
176
118
}
177
119
}
0 commit comments