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