• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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