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