use std::marker::PhantomData; use std::mem::size_of; use std::ops::{Deref, DerefMut}; 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. #[repr(transparent)] #[derive(Debug)] pub struct UniquePtr(Option<&'static mut T>) where T: Delete; 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) { self.0.take().map(Delete::delete); } } /// Reference to object allocated on the C++ heap, similar to UniquePtr, /// but guaranteed to never contain a nullptr. #[repr(transparent)] pub struct UniqueRef(&'static mut T) where T: Delete; 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 ptr: &'static mut T = unsafe { std::mem::transmute_copy(self.0) }; ptr.delete(); } } #[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(embedder_addr - field_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() } }