133d722a9Sopenharmony_ci#![cfg(feature = "alloc")]
233d722a9Sopenharmony_ci#![allow(missing_docs)]
333d722a9Sopenharmony_ci
433d722a9Sopenharmony_ciuse crate::exception::Exception;
533d722a9Sopenharmony_ciuse alloc::boxed::Box;
633d722a9Sopenharmony_ciuse alloc::string::{String, ToString};
733d722a9Sopenharmony_ciuse core::fmt::Display;
833d722a9Sopenharmony_ciuse core::ptr::{self, NonNull};
933d722a9Sopenharmony_ciuse core::result::Result as StdResult;
1033d722a9Sopenharmony_ciuse core::slice;
1133d722a9Sopenharmony_ciuse core::str;
1233d722a9Sopenharmony_ci
1333d722a9Sopenharmony_ci#[repr(C)]
1433d722a9Sopenharmony_ci#[derive(Copy, Clone)]
1533d722a9Sopenharmony_cipub struct PtrLen {
1633d722a9Sopenharmony_ci    pub ptr: NonNull<u8>,
1733d722a9Sopenharmony_ci    pub len: usize,
1833d722a9Sopenharmony_ci}
1933d722a9Sopenharmony_ci
2033d722a9Sopenharmony_ci#[repr(C)]
2133d722a9Sopenharmony_cipub union Result {
2233d722a9Sopenharmony_ci    err: PtrLen,
2333d722a9Sopenharmony_ci    ok: *const u8, // null
2433d722a9Sopenharmony_ci}
2533d722a9Sopenharmony_ci
2633d722a9Sopenharmony_cipub unsafe fn r#try<T, E>(ret: *mut T, result: StdResult<T, E>) -> Result
2733d722a9Sopenharmony_ciwhere
2833d722a9Sopenharmony_ci    E: Display,
2933d722a9Sopenharmony_ci{
3033d722a9Sopenharmony_ci    match result {
3133d722a9Sopenharmony_ci        Ok(ok) => {
3233d722a9Sopenharmony_ci            unsafe { ptr::write(ret, ok) }
3333d722a9Sopenharmony_ci            Result { ok: ptr::null() }
3433d722a9Sopenharmony_ci        }
3533d722a9Sopenharmony_ci        Err(err) => unsafe { to_c_error(err.to_string()) },
3633d722a9Sopenharmony_ci    }
3733d722a9Sopenharmony_ci}
3833d722a9Sopenharmony_ci
3933d722a9Sopenharmony_ciunsafe fn to_c_error(msg: String) -> Result {
4033d722a9Sopenharmony_ci    let mut msg = msg;
4133d722a9Sopenharmony_ci    unsafe { msg.as_mut_vec() }.push(b'\0');
4233d722a9Sopenharmony_ci    let ptr = msg.as_ptr();
4333d722a9Sopenharmony_ci    let len = msg.len();
4433d722a9Sopenharmony_ci
4533d722a9Sopenharmony_ci    extern "C" {
4633d722a9Sopenharmony_ci        #[link_name = "cxxbridge1$error"]
4733d722a9Sopenharmony_ci        fn error(ptr: *const u8, len: usize) -> NonNull<u8>;
4833d722a9Sopenharmony_ci    }
4933d722a9Sopenharmony_ci
5033d722a9Sopenharmony_ci    let copy = unsafe { error(ptr, len) };
5133d722a9Sopenharmony_ci    let err = PtrLen { ptr: copy, len };
5233d722a9Sopenharmony_ci    Result { err }
5333d722a9Sopenharmony_ci}
5433d722a9Sopenharmony_ci
5533d722a9Sopenharmony_ciimpl Result {
5633d722a9Sopenharmony_ci    pub unsafe fn exception(self) -> StdResult<(), Exception> {
5733d722a9Sopenharmony_ci        unsafe {
5833d722a9Sopenharmony_ci            if self.ok.is_null() {
5933d722a9Sopenharmony_ci                Ok(())
6033d722a9Sopenharmony_ci            } else {
6133d722a9Sopenharmony_ci                let err = self.err;
6233d722a9Sopenharmony_ci                let slice = slice::from_raw_parts_mut(err.ptr.as_ptr(), err.len);
6333d722a9Sopenharmony_ci                let s = str::from_utf8_unchecked_mut(slice);
6433d722a9Sopenharmony_ci                Err(Exception {
6533d722a9Sopenharmony_ci                    what: Box::from_raw(s),
6633d722a9Sopenharmony_ci                })
6733d722a9Sopenharmony_ci            }
6833d722a9Sopenharmony_ci        }
6933d722a9Sopenharmony_ci    }
7033d722a9Sopenharmony_ci}
71