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