wrapped_mono/
exception.rs1use crate::binds::MonoObject;
2use crate::gc::{gc_unsafe_enter, gc_unsafe_exit, GCHandle};
3use crate::{Class, Domain, Image, InteropClass, ObjectTrait};
4use std::ffi::CString;
5pub struct Exception {
7 #[cfg(not(feature = "referneced_objects"))]
8 exc_ptr: *mut crate::binds::MonoException,
9 #[cfg(feature = "referneced_objects")]
10 handle: GCHandle,
11}
12impl Exception {
13 #[allow(clippy::missing_panics_doc)] pub unsafe fn raise(&self) -> ! {
46 unsafe { crate::binds::mono_raise_exception(self.get_ptr().cast()) };
47 panic!("After an exception is thrown, nothing should happen.");
48 }
49 #[must_use]
51 pub fn from_name_domain(
52 domain: &Domain,
53 image: Image,
54 namespace: &str,
55 name: &str,
56 ) -> Option<Self> {
57 let namespace_cstr = CString::new(namespace).expect(crate::STR2CSTR_ERR);
58 let name_cstr = CString::new(name).expect(crate::STR2CSTR_ERR);
59 #[cfg(feature = "referneced_objects")]
60 let marker = gc_unsafe_enter();
61 let res = unsafe {
62 Self::from_ptr(
63 crate::binds::mono_exception_from_name_domain(
64 domain.get_ptr(),
65 image.get_ptr(),
66 namespace_cstr.as_ptr(),
67 name_cstr.as_ptr(),
68 )
69 .cast(),
70 )
71 };
72 #[cfg(feature = "referneced_objects")]
73 gc_unsafe_exit(marker);
74 let _ = namespace_cstr;
75 let _ = name_cstr;
76 res
77 }
78 #[must_use]
80 pub fn from_name(image: Image, namespace: &str, name: &str) -> Option<Self> {
81 let namespace_cstr = CString::new(namespace).expect(crate::STR2CSTR_ERR);
82 let name_cstr = CString::new(name).expect(crate::STR2CSTR_ERR);
83 #[cfg(feature = "referneced_objects")]
84 let marker = gc_unsafe_enter();
85 let res = unsafe {
86 Self::from_ptr(
87 crate::binds::mono_exception_from_name(
88 image.get_ptr(),
89 namespace_cstr.as_ptr(),
90 name_cstr.as_ptr(),
91 )
92 .cast(),
93 )
94 };
95 #[cfg(feature = "referneced_objects")]
96 gc_unsafe_exit(marker);
97 let _ = namespace_cstr;
98 let _ = name_cstr;
99 res
100 }
101 #[must_use]
103 pub fn from_name_msg(image: Image, namespace: &str, name: &str, msg: &str) -> Option<Self> {
104 let namespace_cstr = CString::new(namespace).expect(crate::STR2CSTR_ERR);
105 let name_cstr = CString::new(name).expect(crate::STR2CSTR_ERR);
106 let msg_cstr = CString::new(msg).expect(crate::STR2CSTR_ERR);
107 #[cfg(feature = "referneced_objects")]
108 let marker = gc_unsafe_enter();
109 let res = unsafe {
110 Self::from_ptr(
111 crate::binds::mono_exception_from_name_msg(
112 image.get_ptr(),
113 namespace_cstr.as_ptr(),
114 name_cstr.as_ptr(),
115 msg_cstr.as_ptr(),
116 )
117 .cast(),
118 )
119 };
120 #[cfg(feature = "referneced_objects")]
121 gc_unsafe_exit(marker);
122 let _ = msg_cstr;
123 let _ = namespace_cstr;
124 let _ = name_cstr;
125 res
126 }
127 #[must_use]
129 pub fn argument_exception(arg: &str, msg: &str) -> Self {
130 let arg_cstr = CString::new(arg).expect(crate::STR2CSTR_ERR);
131 let msg_cstr = CString::new(msg).expect(crate::STR2CSTR_ERR);
132 #[cfg(feature = "referneced_objects")]
133 let marker = gc_unsafe_enter();
134 let res = unsafe {
135 Self::from_ptr_unchecked(
136 crate::binds::mono_get_exception_argument(arg_cstr.as_ptr(), msg_cstr.as_ptr())
137 .cast(),
138 )
139 };
140 #[cfg(feature = "referneced_objects")]
141 gc_unsafe_exit(marker);
142 let _ = arg_cstr;
143 let _ = msg_cstr;
144 res
145 }
146 #[must_use]
148 pub fn not_implemented(msg: &str) -> Self {
149 let msg_cstr = CString::new(msg).expect(crate::STR2CSTR_ERR);
150 #[cfg(feature = "referneced_objects")]
151 let marker = gc_unsafe_enter();
152 let res = unsafe {
153 Self::from_ptr_unchecked(
154 crate::binds::mono_get_exception_not_implemented(msg_cstr.as_ptr()).cast(),
155 )
156 };
157 #[cfg(feature = "referneced_objects")]
158 gc_unsafe_exit(marker);
159 let _ = msg_cstr;
160 res
161 }
162 #[must_use]
164 pub fn argument_null(msg: &str) -> Self {
165 let msg_cstr = CString::new(msg).expect(crate::STR2CSTR_ERR);
166 #[cfg(feature = "referneced_objects")]
167 let marker = gc_unsafe_enter();
168 let res = unsafe {
169 Self::from_ptr_unchecked(
170 crate::binds::mono_get_exception_argument_null(msg_cstr.as_ptr()).cast(),
171 )
172 };
173 #[cfg(feature = "referneced_objects")]
174 gc_unsafe_exit(marker);
175 let _ = msg_cstr;
176 res
177 }
178 #[must_use]
180 pub fn argument_out_of_range(msg: &str) -> Self {
181 let msg_cstr = CString::new(msg).expect(crate::STR2CSTR_ERR);
182 #[cfg(feature = "referneced_objects")]
183 let marker = gc_unsafe_enter();
184 let res = unsafe {
185 Self::from_ptr_unchecked(
186 crate::binds::mono_get_exception_argument_out_of_range(msg_cstr.as_ptr()).cast(),
187 )
188 };
189 #[cfg(feature = "referneced_objects")]
190 gc_unsafe_exit(marker);
191 let _ = msg_cstr;
192 res
193 }
194 #[must_use]
196 pub fn arithmetic() -> Self {
197 #[cfg(feature = "referneced_objects")]
198 let marker = gc_unsafe_enter();
199 let res = unsafe {
200 Self::from_ptr_unchecked(crate::binds::mono_get_exception_arithmetic().cast())
201 };
202 #[cfg(feature = "referneced_objects")]
203 gc_unsafe_exit(marker);
204 res
205 }
206 #[must_use]
208 pub fn array_type_mismatch() -> Self {
209 #[cfg(feature = "referneced_objects")]
210 let marker = gc_unsafe_enter();
211 let res = unsafe {
212 Self::from_ptr_unchecked(crate::binds::mono_get_exception_array_type_mismatch().cast())
213 };
214 #[cfg(feature = "referneced_objects")]
215 gc_unsafe_exit(marker);
216 res
217 }
218 #[must_use]
220 pub fn bad_image_format(msg: &str) -> Self {
221 let msg_cstr = CString::new(msg).expect(crate::STR2CSTR_ERR);
222 #[cfg(feature = "referneced_objects")]
223 let marker = gc_unsafe_enter();
224 let res = unsafe {
225 Self::from_ptr_unchecked(
226 crate::binds::mono_get_exception_bad_image_format(msg_cstr.as_ptr()).cast(),
227 )
228 };
229 #[cfg(feature = "referneced_objects")]
230 gc_unsafe_exit(marker);
231 let _ = msg_cstr;
232 res
233 }
234 #[must_use]
236 pub fn cannot_unload_appdomain(msg: &str) -> Self {
237 let msg_cstr = CString::new(msg).expect(crate::STR2CSTR_ERR);
238 #[cfg(feature = "referneced_objects")]
239 let marker = gc_unsafe_enter();
240 let res = unsafe {
241 Self::from_ptr_unchecked(
242 crate::binds::mono_get_exception_cannot_unload_appdomain(msg_cstr.as_ptr()).cast(),
243 )
244 };
245 #[cfg(feature = "referneced_objects")]
246 gc_unsafe_exit(marker);
247 let _ = msg_cstr;
248 res
249 }
250 #[must_use]
252 pub fn domain_unloaded() -> Self {
253 #[cfg(feature = "referneced_objects")]
254 let marker = gc_unsafe_enter();
255 let res = unsafe {
256 Self::from_ptr_unchecked(crate::binds::mono_get_exception_appdomain_unloaded().cast())
257 };
258 #[cfg(feature = "referneced_objects")]
259 gc_unsafe_exit(marker);
260 res
261 }
262 #[must_use]
264 pub fn divide_by_zero() -> Self {
265 #[cfg(feature = "referneced_objects")]
266 let marker = gc_unsafe_enter();
267 let res = unsafe {
268 Self::from_ptr_unchecked(crate::binds::mono_get_exception_divide_by_zero().cast())
269 };
270 #[cfg(feature = "referneced_objects")]
271 gc_unsafe_exit(marker);
272 res
273 }
274 #[must_use]
276 pub fn execution_engine_exception(msg: &str) -> Self {
277 let msg_cstr = CString::new(msg).expect(crate::STR2CSTR_ERR);
278 #[cfg(feature = "referneced_objects")]
279 let marker = gc_unsafe_enter();
280 let res = unsafe {
281 Self::from_ptr_unchecked(
282 crate::binds::mono_get_exception_execution_engine(msg_cstr.as_ptr()).cast(),
283 )
284 };
285 #[cfg(feature = "referneced_objects")]
286 gc_unsafe_exit(marker);
287 let _ = msg_cstr;
288 res
289 }
290 #[must_use]
292 pub fn file_not_found(fname: &str) -> Self {
293 let fname_cstr = CString::new(fname).expect(crate::STR2CSTR_ERR);
294 let ms = unsafe { crate::binds::mono_string_new_wrapper(fname_cstr.as_ptr()) };
295 let _ = fname_cstr;
296 #[cfg(feature = "referneced_objects")]
297 let marker = gc_unsafe_enter();
298 let res = unsafe {
299 Self::from_ptr_unchecked(crate::binds::mono_get_exception_file_not_found(ms).cast())
300 };
301 #[cfg(feature = "referneced_objects")]
302 gc_unsafe_exit(marker);
303 res
304 }
305 #[must_use]
307 pub fn index_out_of_range() -> Self {
308 #[cfg(feature = "referneced_objects")]
309 let marker = gc_unsafe_enter();
310 let res = unsafe {
311 Self::from_ptr_unchecked(crate::binds::mono_get_exception_index_out_of_range().cast())
312 };
313 #[cfg(feature = "referneced_objects")]
314 gc_unsafe_exit(marker);
315 res
316 }
317 #[must_use]
319 pub fn invald_cast() -> Self {
320 #[cfg(feature = "referneced_objects")]
321 let marker = gc_unsafe_enter();
322 let res = unsafe {
323 Self::from_ptr_unchecked(crate::binds::mono_get_exception_invalid_cast().cast())
324 };
325 #[cfg(feature = "referneced_objects")]
326 gc_unsafe_exit(marker);
327 res
328 }
329 #[must_use]
331 pub fn io_exception(msg: &str) -> Self {
332 let msg_cstr = CString::new(msg).expect(crate::STR2CSTR_ERR);
333 #[cfg(feature = "referneced_objects")]
334 let marker = gc_unsafe_enter();
335 let res = unsafe {
336 Self::from_ptr_unchecked(crate::binds::mono_get_exception_io(msg_cstr.as_ptr()).cast())
337 };
338 #[cfg(feature = "referneced_objects")]
339 gc_unsafe_exit(marker);
340 let _ = msg_cstr;
341 res
342 }
343 #[must_use]
345 pub fn missing_method(class_name: &str, member_name: &str) -> Self {
346 let class_name_cstr = CString::new(class_name).expect(crate::STR2CSTR_ERR);
347 let member_name_cstr = CString::new(member_name).expect(crate::STR2CSTR_ERR);
348 #[cfg(feature = "referneced_objects")]
349 let marker = gc_unsafe_enter();
350 let res = unsafe {
351 Self::from_ptr_unchecked(
352 crate::binds::mono_get_exception_missing_method(
353 class_name_cstr.as_ptr(),
354 member_name_cstr.as_ptr(),
355 )
356 .cast(),
357 )
358 };
359 #[cfg(feature = "referneced_objects")]
360 gc_unsafe_exit(marker);
361 let _ = class_name_cstr;
362 let _ = member_name_cstr;
363 res
364 }
365 #[must_use]
367 pub fn null_reference() -> Self {
368 #[cfg(feature = "referneced_objects")]
369 let marker = gc_unsafe_enter();
370 let res = unsafe {
371 Self::from_ptr_unchecked(crate::binds::mono_get_exception_null_reference().cast())
372 };
373 #[cfg(feature = "referneced_objects")]
374 gc_unsafe_exit(marker);
375 res
376 }
377 #[must_use]
379 pub fn overflow() -> Self {
380 #[cfg(feature = "referneced_objects")]
381 let marker = gc_unsafe_enter();
382 let res =
383 unsafe { Self::from_ptr_unchecked(crate::binds::mono_get_exception_overflow().cast()) };
384 #[cfg(feature = "referneced_objects")]
385 gc_unsafe_exit(marker);
386 res
387 }
388 #[must_use]
390 pub fn security() -> Self {
391 #[cfg(feature = "referneced_objects")]
392 let marker = gc_unsafe_enter();
393 let res =
394 unsafe { Self::from_ptr_unchecked(crate::binds::mono_get_exception_security().cast()) };
395 #[cfg(feature = "referneced_objects")]
396 gc_unsafe_exit(marker);
397 res
398 }
399 #[must_use]
401 pub fn serialization_exception(msg: &str) -> Self {
402 let msg_cstr = CString::new(msg).expect(crate::STR2CSTR_ERR);
403 #[cfg(feature = "referneced_objects")]
404 let marker = gc_unsafe_enter();
405 let res = unsafe {
406 Self::from_ptr_unchecked(
407 crate::binds::mono_get_exception_serialization(msg_cstr.as_ptr()).cast(),
408 )
409 };
410 #[cfg(feature = "referneced_objects")]
411 gc_unsafe_exit(marker);
412 let _ = msg_cstr;
413 res
414 }
415 #[must_use]
417 pub fn stack_overflow() -> Self {
418 #[cfg(feature = "referneced_objects")]
419 let marker = gc_unsafe_enter();
420 let res = unsafe {
421 Self::from_ptr_unchecked(crate::binds::mono_get_exception_stack_overflow().cast())
422 };
423 #[cfg(feature = "referneced_objects")]
424 gc_unsafe_exit(marker);
425 res
426 }
427 #[must_use]
429 pub fn synchronization_lock(msg: &str) -> Self {
430 let msg_cstr = CString::new(msg).expect(crate::STR2CSTR_ERR);
431 #[cfg(feature = "referneced_objects")]
432 let marker = gc_unsafe_enter();
433 let res = unsafe {
434 Self::from_ptr_unchecked(
435 crate::binds::mono_get_exception_synchronization_lock(msg_cstr.as_ptr()).cast(),
436 )
437 };
438 #[cfg(feature = "referneced_objects")]
439 gc_unsafe_exit(marker);
440 let _ = msg_cstr;
441 res
442 }
443 #[must_use]
445 pub fn thread_abort() -> Self {
446 #[cfg(feature = "referneced_objects")]
447 let marker = gc_unsafe_enter();
448 let res = unsafe {
449 Self::from_ptr_unchecked(crate::binds::mono_get_exception_thread_abort().cast())
450 };
451 #[cfg(feature = "referneced_objects")]
452 gc_unsafe_exit(marker);
453 res
454 }
455 #[must_use]
457 pub fn thread_sate(msg: &str) -> Self {
458 let msg_cstr = CString::new(msg).expect(crate::STR2CSTR_ERR);
459 #[cfg(feature = "referneced_objects")]
460 let marker = gc_unsafe_enter();
461 let res = unsafe {
462 Self::from_ptr_unchecked(
463 crate::binds::mono_get_exception_thread_state(msg_cstr.as_ptr()).cast(),
464 )
465 };
466 #[cfg(feature = "referneced_objects")]
467 gc_unsafe_exit(marker);
468 let _ = msg_cstr;
469 res
470 }
471 #[must_use]
473 pub fn type_initialization(type_name: &str, inner: &Self) -> Self {
474 let type_name_cstr = CString::new(type_name).expect(crate::STR2CSTR_ERR);
475 #[cfg(feature = "referneced_objects")]
476 let marker = gc_unsafe_enter();
477 let res = unsafe {
478 Self::from_ptr_unchecked(
479 crate::binds::mono_get_exception_type_initialization(
480 type_name_cstr.as_ptr(),
481 inner.get_ptr().cast(),
482 )
483 .cast(),
484 )
485 };
486 #[cfg(feature = "referneced_objects")]
487 gc_unsafe_exit(marker);
488 let _ = type_name_cstr;
489 res
490 }
491 #[must_use]
493 pub fn type_load(class_name: &str, member_name: &str) -> Self {
494 let class_name_cstr = CString::new(class_name).expect(crate::STR2CSTR_ERR);
495 #[cfg(feature = "referneced_objects")]
496 let marker = gc_unsafe_enter();
497 let cn_mono_string =
498 unsafe { crate::binds::mono_string_new_wrapper(class_name_cstr.as_ptr()) };
499 let _ = class_name_cstr;
500 let member_name_cstr = CString::new(member_name).expect(crate::STR2CSTR_ERR);
501 let res = unsafe {
502 Self::from_ptr_unchecked(
503 crate::binds::mono_get_exception_type_load(
504 cn_mono_string,
505 member_name_cstr.as_ptr() as *mut i8,
506 )
507 .cast(),
508 )
509 };
510 #[cfg(feature = "referneced_objects")]
511 gc_unsafe_exit(marker);
512 let _ = member_name_cstr;
513 res
514 }
515 #[must_use]
517 pub fn invalid_operation(msg: &str) -> Self {
518 let msg_cstr = CString::new(msg).expect(crate::STR2CSTR_ERR);
519 #[cfg(feature = "referneced_objects")]
520 let marker = gc_unsafe_enter();
521 let res = unsafe {
522 Self::from_ptr_unchecked(
523 crate::binds::mono_get_exception_invalid_operation(msg_cstr.as_ptr()).cast(),
524 )
525 };
526 #[cfg(feature = "referneced_objects")]
527 gc_unsafe_exit(marker);
528 let _ = msg_cstr;
529 res
530 }
531 #[must_use]
533 pub fn missing_field(class_name: &str, member_name: &str) -> Self {
534 let class_name_cstr = CString::new(class_name).expect(crate::STR2CSTR_ERR);
535 let member_name_cstr = CString::new(member_name).expect(crate::STR2CSTR_ERR);
536 #[cfg(feature = "referneced_objects")]
537 let marker = gc_unsafe_enter();
538 let res = unsafe {
539 Self::from_ptr_unchecked(
540 crate::binds::mono_get_exception_missing_field(
541 class_name_cstr.as_ptr(),
542 member_name_cstr.as_ptr() as *mut i8,
543 )
544 .cast(),
545 )
546 };
547 #[cfg(feature = "referneced_objects")]
548 gc_unsafe_exit(marker);
549 let _ = member_name_cstr;
550 let _ = class_name_cstr;
551 res
552 }
553 #[must_use]
555 pub fn not_supported(msg: &str) -> Self {
556 let msg_cstr = CString::new(msg).expect(crate::STR2CSTR_ERR);
557 #[cfg(feature = "referneced_objects")]
558 let marker = gc_unsafe_enter();
559 let res = unsafe {
560 Self::from_ptr_unchecked(
561 crate::binds::mono_get_exception_not_supported(msg_cstr.as_ptr()).cast(),
562 )
563 };
564 #[cfg(feature = "referneced_objects")]
565 gc_unsafe_exit(marker);
566 let _ = msg_cstr;
567 res
568 }
569 #[must_use]
571 pub fn field_access() -> Self {
572 #[cfg(feature = "referneced_objects")]
573 let marker = gc_unsafe_enter();
574 let res = unsafe {
575 Self::from_ptr_unchecked(crate::binds::mono_get_exception_field_access().cast())
576 };
577 #[cfg(feature = "referneced_objects")]
578 gc_unsafe_exit(marker);
579 res
580 }
581 #[must_use]
583 pub fn method_access() -> Self {
584 #[cfg(feature = "referneced_objects")]
585 let marker = gc_unsafe_enter();
586 let res = unsafe {
587 Self::from_ptr_unchecked(crate::binds::mono_get_exception_method_access().cast())
588 };
589 #[cfg(feature = "referneced_objects")]
590 gc_unsafe_exit(marker);
591 res
592 }
593 #[must_use]
595 pub fn out_of_memory() -> Self {
596 #[cfg(feature = "referneced_objects")]
597 let marker = gc_unsafe_enter();
598 let res = unsafe {
599 Self::from_ptr_unchecked(crate::binds::mono_get_exception_out_of_memory().cast())
600 };
601 #[cfg(feature = "referneced_objects")]
602 gc_unsafe_exit(marker);
603 res
604 }
605 #[must_use]
607 pub fn wrapped(inner: &Self) -> Self {
608 #[cfg(feature = "referneced_objects")]
609 let marker = gc_unsafe_enter();
610 let res = unsafe {
611 Self::from_ptr_unchecked(
612 crate::binds::mono_get_exception_runtime_wrapped(inner.get_ptr().cast()).cast(),
613 )
614 };
615 #[cfg(feature = "referneced_objects")]
616 gc_unsafe_exit(marker);
617 res
618 }
619}
620pub(crate) fn except_managed<T: Sized>(option: Option<T>, msg: &str) -> T {
622 option.map_or_else(
623 || {
624 let exc = Exception::argument_null(&format!(
625 "Value of type: \"{}\" was null!\"{}\"",
626 std::any::type_name::<T>(),
627 &msg
628 ));
629 unsafe {
630 exc.raise();
631 }
632 },
633 |t| t,
634 )
635}
636use core::fmt::Formatter;
650impl core::fmt::Debug for Exception {
651 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
652 let mstr = self
653 .to_mstring()
654 .expect("Got an exception while trying to convert an exception to string!")
655 .expect(
656 "Got null instead of a string while trying to convert an exception to a string!",
657 )
658 .to_string();
659 write!(f, "Exception:\"{mstr}\"")
660 }
661}
662impl crate::object::ObjectTrait for Exception {
663 #[must_use]
664 unsafe fn from_ptr_unchecked(exc_ptr: *mut MonoObject) -> Self {
665 #[cfg(not(feature = "referneced_objects"))]
666 {
667 Self {
668 exc_ptr: exc_ptr.cast(),
669 }
670 }
671 #[cfg(feature = "referneced_objects")]
672 {
673 Self {
674 handle: GCHandle::create_default(exc_ptr.cast()),
675 }
676 }
677 }
678 #[must_use]
679 fn get_ptr(&self) -> *mut MonoObject {
680 #[cfg(not(feature = "referneced_objects"))]
681 {
682 self.exc_ptr.cast()
683 }
684 #[cfg(feature = "referneced_objects")]
685 {
686 self.handle.get_target().cast()
687 }
688 }
689}
690impl InteropClass for Exception {
691 fn get_mono_class() -> Class {
692 Class::get_exception_class()
693 }
694}
695impl Clone for Exception {
696 fn clone(&self) -> Self {
697 unsafe { Self::from_ptr_unchecked(self.get_ptr().cast()) } }
699}
700impl<O: ObjectTrait> PartialEq<O> for Exception {
701 fn eq(&self, other: &O) -> bool {
702 self.get_ptr().cast() == other.get_ptr()
703 }
704}
705impl std::fmt::Display for Exception {
706 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
707 let mstr = self.to_mstring();
708 write!(
709 f,
710 "{}",
711 mstr.expect("Got an exception while converting an exception String!")
712 .expect("Got null from converting exception to string!")
713 .to_string()
714 )
715 }
716}