use std::marker::PhantomData; use std::mem::replace; use std::mem::size_of; use std::mem::transmute; use std::ops::Deref; use std::ops::DerefMut; use std::ptr::NonNull; // TODO use libc::intptr_t when stable. // https://doc.rust-lang.org/1.7.0/libc/type.intptr_t.html #[allow(non_camel_case_types)] pub type intptr_t = isize; pub use std::os::raw::c_char as char; pub use std::os::raw::c_int as int; pub use std::os::raw::c_long as long; pub type Opaque = [usize; 0]; pub trait Delete where Self: Sized + 'static, { fn delete(&'static mut self) -> (); } /// Pointer to object allocated on the C++ heap. The pointer may be null. #[repr(transparent)] #[derive(Debug)] pub struct UniquePtr(Option<&'static mut T>) where T: Delete; impl UniquePtr where T: Delete, { pub fn null() -> Self { Self(None) } pub fn new(r: &'static mut T) -> Self { Self(Some(r)) } pub unsafe fn from_raw(p: *mut T) -> Self { transmute(p) } pub fn into_raw(self) -> *mut T { unsafe { transmute(self) } } pub fn unwrap(self) -> UniqueRef { let p = self.into_raw(); assert!(!p.is_null()); unsafe { UniqueRef::from_raw(p) } } } impl Deref for UniquePtr where T: Delete, { type Target = Option<&'static mut T>; fn deref(&self) -> &Self::Target { &self.0 } } impl DerefMut for UniquePtr where T: Delete, { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } impl Drop for UniquePtr where T: Delete, { fn drop(&mut self) { if let Some(v) = self.0.take() { Delete::delete(v) } } } /// Pointer to object allocated on the C++ heap. The pointer may not be null. #[repr(transparent)] #[derive(Debug)] pub struct UniqueRef(&'static mut T) where T: Delete; impl UniqueRef where T: Delete, { pub fn new(r: &'static mut T) -> Self { Self(r) } pub unsafe fn from_raw(p: *mut T) -> Self { transmute(NonNull::new(p)) } pub fn into_raw(self) -> *mut T { unsafe { transmute(self) } } } impl Deref for UniqueRef where T: Delete, { type Target = &'static mut T; fn deref(&self) -> &Self::Target { &self.0 } } impl DerefMut for UniqueRef where T: Delete, { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } impl Drop for UniqueRef where T: Delete, { fn drop(&mut self) { let inner = replace(&mut self.0, unsafe { transmute(NonNull::<&'static mut T>::dangling()) }); Delete::delete(inner) } } pub trait Shared where Self: Sized + 'static, { fn deref(shared_ptr: *const SharedRef) -> *mut Self; fn reset(shared_ptr: *mut SharedRef); fn use_count(shared_ptr: *const SharedRef) -> long; } /// Wrapper around a C++ shared_ptr. The shared_ptr is assumed to contain a /// value and not be null. #[repr(C)] #[derive(Debug)] pub struct SharedRef([*mut Opaque; 2], PhantomData) where T: Shared; impl SharedRef where T: Shared, { pub fn use_count(&self) -> long { ::use_count(self) } } unsafe impl Send for SharedRef where T: Shared + Send {} impl Deref for SharedRef where T: Shared, { // TODO: Maybe this should deref to UnsafeCell? type Target = T; fn deref(&self) -> &T { unsafe { &*::deref(self) } } } impl DerefMut for SharedRef where T: Shared, { fn deref_mut(&mut self) -> &mut T { unsafe { &mut *::deref(self) } } } impl Drop for SharedRef where T: Shared, { fn drop(&mut self) { ::reset(self); } } #[repr(C)] #[derive(Debug, PartialEq)] pub enum MaybeBool { JustFalse = 0, JustTrue = 1, Nothing = 2, } impl Into> for MaybeBool { fn into(self) -> Option { match self { MaybeBool::JustFalse => Some(false), MaybeBool::JustTrue => Some(true), MaybeBool::Nothing => None, } } } #[derive(Copy, Clone, Debug)] #[repr(transparent)] pub struct CxxVTable(pub *const Opaque); #[derive(Copy, Clone, Debug)] pub struct RustVTable(pub *const Opaque, pub PhantomData); #[derive(Debug)] pub struct FieldOffset(usize, PhantomData); unsafe impl Send for FieldOffset where F: Send {} unsafe impl Sync for FieldOffset where F: Sync {} impl Copy for FieldOffset {} impl Clone for FieldOffset { fn clone(&self) -> Self { Self(self.0, self.1) } } impl FieldOffset { pub fn from_ptrs(embedder_ptr: *const E, field_ptr: *const F) -> Self { let embedder_addr = embedder_ptr as usize; let field_addr = field_ptr as usize; assert!(field_addr >= embedder_addr); assert!((field_addr + size_of::()) <= (embedder_addr + size_of::())); Self(field_addr - embedder_addr, PhantomData) } pub unsafe fn to_embedder(self, field: &F) -> &E { (((field as *const _ as usize) - self.0) as *const E) .as_ref() .unwrap() } pub unsafe fn to_embedder_mut(self, field: &mut F) -> &mut E { (((field as *mut _ as usize) - self.0) as *mut E) .as_mut() .unwrap() } }