cxx/
result.rs

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