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 = [u8; 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)] 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 From> for UniquePtr where T: Delete, { fn from(unique_ref: UniqueRef) -> Self { unsafe { Self::from_raw(unique_ref.into_raw()) } } } 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)] 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 fn make_shared(self) -> SharedRef where T: Shared, { self.into() } 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 = T; fn deref(&self) -> &Self::Target { self.0 } } impl DerefMut for UniqueRef where T: Delete, { fn deref_mut(&mut self) -> &mut Self::Target { 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: Delete + 'static, { fn clone(shared_ptr: *const SharedRef) -> SharedRef; fn from_unique(unique: UniqueRef) -> SharedRef; 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)] pub struct SharedRef([*mut Opaque; 2], PhantomData) where T: Shared; unsafe impl Send for SharedRef where T: Shared + Send {} impl SharedRef where T: Shared, { pub fn use_count(&self) -> long { ::use_count(self) } } impl Clone for SharedRef where T: Shared, { fn clone(&self) -> Self { ::clone(self) } } impl From> for SharedRef where T: Delete + Shared, { fn from(unique: UniqueRef) -> Self { ::from_unique(unique) } } 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)] #[repr(transparent)] pub struct CxxVTable(pub *const Opaque); #[derive(Copy, Clone)] pub struct RustVTable(pub *const Opaque, pub PhantomData); 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() } } #[repr(C)] #[derive(Default)] pub struct Maybe { has_value: bool, value: T, } impl Into> for Maybe { fn into(self) -> Option { if self.has_value { Some(self.value) } else { None } } } pub trait UnitType where Self: Copy + Sized, { #[inline(always)] fn get() -> Self { UnitValue::::get() } } impl UnitType for T where T: Copy + Sized {} #[derive(Copy, Clone)] struct UnitValue(PhantomData) where Self: Sized; impl UnitValue where Self: Copy + Sized, { const SELF: Self = Self::new_checked(); const fn new_checked() -> Self { // Statically assert that T is indeed a unit type. let size_must_be_0 = size_of::(); let s = Self(PhantomData::); [s][size_must_be_0] } #[inline(always)] fn get_checked(self) -> T { // This run-time check serves just as a backup for the compile-time // check when Self::SELF is initialized. assert_eq!(size_of::(), 0); unsafe { std::mem::MaybeUninit::::zeroed().assume_init() } } #[inline(always)] pub fn get() -> T { // Accessing the Self::SELF is necessary to make the compile-time type check // work. Self::SELF.get_checked() } } pub struct DefaultTag; pub struct IdenticalConversionTag; pub trait MapFnFrom where F: UnitType, Self: Sized, { fn mapping() -> Self; #[inline(always)] fn map_fn_from(_: F) -> Self { Self::mapping() } } impl MapFnFrom for F where Self: UnitType, { #[inline(always)] fn mapping() -> Self { Self::get() } } pub trait MapFnTo where Self: UnitType, T: Sized, { fn mapping() -> T; #[inline(always)] fn map_fn_to(self) -> T { Self::mapping() } } impl MapFnTo for F where Self: UnitType, T: MapFnFrom, { #[inline(always)] fn mapping() -> T { T::map_fn_from(F::get()) } } pub trait CFnFrom where Self: Sized, F: UnitType, { fn mapping() -> Self; #[inline(always)] fn c_fn_from(_: F) -> Self { Self::mapping() } } macro_rules! impl_c_fn_from { ($($arg:ident: $ty:ident),*) => { impl CFnFrom for extern "C" fn($($ty),*) -> R where F: UnitType + Fn($($ty),*) -> R, { #[inline(always)] fn mapping() -> Self { extern "C" fn c_fn($($arg: $ty),*) -> R where F: UnitType + Fn($($ty),*) -> R, { (F::get())($($arg),*) }; c_fn:: } } }; } impl_c_fn_from!(); impl_c_fn_from!(a0: A0); impl_c_fn_from!(a0: A0, a1: A1); impl_c_fn_from!(a0: A0, a1: A1, a2: A2); impl_c_fn_from!(a0: A0, a1: A1, a2: A2, a3: A3); impl_c_fn_from!(a0: A0, a1: A1, a2: A2, a3: A3, a4: A4); impl_c_fn_from!(a0: A0, a1: A1, a2: A2, a3: A3, a4: A4, a5: A5); impl_c_fn_from!(a0: A0, a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, a6: A6); pub trait ToCFn where Self: UnitType, T: Sized, { fn mapping() -> T; #[inline(always)] fn to_c_fn(self) -> T { Self::mapping() } } impl ToCFn for F where Self: UnitType, T: CFnFrom, { #[inline(always)] fn mapping() -> T { T::c_fn_from(F::get()) } }