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(Copy, Clone)] 15pub 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 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 55impl Result { 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