1 #![allow(missing_docs)]
2
3 use crate::exception::Exception;
4 use alloc::boxed::Box;
5 use alloc::string::{String, ToString};
6 use core::fmt::Display;
7 use core::ptr::{self, NonNull};
8 use core::result::Result as StdResult;
9 use core::slice;
10 use core::str;
11
12 #[repr(C)]
13 #[derive(Copy, Clone)]
14 struct PtrLen {
15 ptr: NonNull<u8>,
16 len: usize,
17 }
18
19 #[repr(C)]
20 pub union Result {
21 err: PtrLen,
22 ok: *const u8, // null
23 }
24
25 pub unsafe fn r#try<T, E>(ret: *mut T, result: StdResult<T, E>) -> Result
26 where
27 E: Display,
28 {
29 match result {
30 Ok(ok) => {
31 unsafe { ptr::write(ret, ok) }
32 Result { ok: ptr::null() }
33 }
34 Err(err) => unsafe { to_c_error(err.to_string()) },
35 }
36 }
37
to_c_error(msg: String) -> Result38 unsafe fn to_c_error(msg: String) -> Result {
39 let mut msg = msg;
40 unsafe { msg.as_mut_vec() }.push(b'\0');
41 let ptr = msg.as_ptr();
42 let len = msg.len();
43
44 extern "C" {
45 #[link_name = "cxxbridge1$error"]
46 fn error(ptr: *const u8, len: usize) -> NonNull<u8>;
47 }
48
49 let copy = unsafe { error(ptr, len) };
50 let err = PtrLen { ptr: copy, len };
51 Result { err }
52 }
53
54 impl Result {
exception(self) -> StdResult<(), Exception>55 pub unsafe fn exception(self) -> StdResult<(), Exception> {
56 unsafe {
57 if self.ok.is_null() {
58 Ok(())
59 } else {
60 let err = self.err;
61 let slice = slice::from_raw_parts_mut(err.ptr.as_ptr(), err.len);
62 let s = str::from_utf8_unchecked_mut(slice);
63 Err(Exception {
64 what: Box::from_raw(s),
65 })
66 }
67 }
68 }
69 }
70