summaryrefslogtreecommitdiffstats
path: root/vendor/cxx/src/result.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/cxx/src/result.rs')
-rw-r--r--vendor/cxx/src/result.rs70
1 files changed, 70 insertions, 0 deletions
diff --git a/vendor/cxx/src/result.rs b/vendor/cxx/src/result.rs
new file mode 100644
index 000000000..ba77858e3
--- /dev/null
+++ b/vendor/cxx/src/result.rs
@@ -0,0 +1,70 @@
+#![cfg(feature = "alloc")]
+#![allow(missing_docs)]
+
+use crate::exception::Exception;
+use alloc::boxed::Box;
+use alloc::string::{String, ToString};
+use core::fmt::Display;
+use core::ptr::{self, NonNull};
+use core::result::Result as StdResult;
+use core::slice;
+use core::str;
+
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct PtrLen {
+ pub ptr: NonNull<u8>,
+ pub len: usize,
+}
+
+#[repr(C)]
+pub union Result {
+ err: PtrLen,
+ ok: *const u8, // null
+}
+
+pub unsafe fn r#try<T, E>(ret: *mut T, result: StdResult<T, E>) -> Result
+where
+ E: Display,
+{
+ match result {
+ Ok(ok) => {
+ unsafe { ptr::write(ret, ok) }
+ Result { ok: ptr::null() }
+ }
+ Err(err) => unsafe { to_c_error(err.to_string()) },
+ }
+}
+
+unsafe fn to_c_error(msg: String) -> Result {
+ let mut msg = msg;
+ unsafe { msg.as_mut_vec() }.push(b'\0');
+ let ptr = msg.as_ptr();
+ let len = msg.len();
+
+ extern "C" {
+ #[link_name = "cxxbridge1$error"]
+ fn error(ptr: *const u8, len: usize) -> NonNull<u8>;
+ }
+
+ let copy = unsafe { error(ptr, len) };
+ let err = PtrLen { ptr: copy, len };
+ Result { err }
+}
+
+impl Result {
+ pub unsafe fn exception(self) -> StdResult<(), Exception> {
+ unsafe {
+ if self.ok.is_null() {
+ Ok(())
+ } else {
+ let err = self.err;
+ let slice = slice::from_raw_parts_mut(err.ptr.as_ptr(), err.len);
+ let s = str::from_utf8_unchecked_mut(slice);
+ Err(Exception {
+ what: Box::from_raw(s),
+ })
+ }
+ }
+ }
+}