2020-01-22 22:29:03 +01:00
|
|
|
use std::cell::UnsafeCell;
|
2019-10-16 15:47:34 -07:00
|
|
|
use std::marker::PhantomData;
|
2020-04-16 03:59:08 +02:00
|
|
|
use std::mem::align_of;
|
2020-04-16 03:01:16 +02:00
|
|
|
use std::mem::forget;
|
2020-04-16 03:59:08 +02:00
|
|
|
use std::mem::needs_drop;
|
2019-10-16 15:47:34 -07:00
|
|
|
use std::mem::size_of;
|
2019-10-22 14:52:43 -07:00
|
|
|
use std::ops::Deref;
|
|
|
|
use std::ops::DerefMut;
|
2020-04-16 03:59:08 +02:00
|
|
|
use std::ptr::drop_in_place;
|
2020-04-16 03:01:16 +02:00
|
|
|
use std::ptr::null_mut;
|
2019-11-20 13:34:32 -08:00
|
|
|
use std::ptr::NonNull;
|
2019-10-16 15:47:34 -07:00
|
|
|
|
2019-12-27 09:12:16 -05:00
|
|
|
// 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;
|
|
|
|
|
2019-12-04 08:03:17 +01:00
|
|
|
pub use std::os::raw::c_char as char;
|
2019-10-19 17:15:23 -07:00
|
|
|
pub use std::os::raw::c_int as int;
|
2019-12-26 03:32:22 +01:00
|
|
|
pub use std::os::raw::c_long as long;
|
2019-10-19 17:15:23 -07:00
|
|
|
|
2020-01-14 21:06:41 +01:00
|
|
|
pub type Opaque = [u8; 0];
|
2019-10-16 15:47:34 -07:00
|
|
|
|
2019-11-20 13:34:32 -08:00
|
|
|
/// Pointer to object allocated on the C++ heap. The pointer may be null.
|
2019-10-17 16:46:54 -07:00
|
|
|
#[repr(transparent)]
|
2020-04-16 03:59:08 +02:00
|
|
|
pub struct UniquePtr<T>(Option<UniqueRef<T>>);
|
2019-10-17 16:46:54 -07:00
|
|
|
|
2020-04-16 03:59:08 +02:00
|
|
|
impl<T> UniquePtr<T> {
|
2019-10-22 14:52:43 -07:00
|
|
|
pub fn null() -> Self {
|
2020-04-16 03:59:08 +02:00
|
|
|
assert_unique_type_compatible::<Self, T>();
|
2019-10-22 14:52:43 -07:00
|
|
|
Self(None)
|
2019-10-17 16:46:54 -07:00
|
|
|
}
|
|
|
|
|
2020-04-16 03:01:16 +02:00
|
|
|
pub unsafe fn from_raw(ptr: *mut T) -> Self {
|
2020-04-16 03:59:08 +02:00
|
|
|
assert_unique_type_compatible::<Self, T>();
|
2020-04-16 03:01:16 +02:00
|
|
|
Self(UniqueRef::try_from_raw(ptr))
|
2019-10-17 16:46:54 -07:00
|
|
|
}
|
2019-11-15 16:21:34 -08:00
|
|
|
|
|
|
|
pub fn into_raw(self) -> *mut T {
|
2020-04-16 03:01:16 +02:00
|
|
|
self
|
|
|
|
.0
|
|
|
|
.map(|unique_ref| unique_ref.into_raw())
|
|
|
|
.unwrap_or_else(null_mut)
|
2019-11-15 16:21:34 -08:00
|
|
|
}
|
2019-11-20 13:34:32 -08:00
|
|
|
|
|
|
|
pub fn unwrap(self) -> UniqueRef<T> {
|
2020-04-16 03:01:16 +02:00
|
|
|
self.0.unwrap()
|
|
|
|
}
|
2019-10-17 16:46:54 -07:00
|
|
|
}
|
|
|
|
|
2020-04-16 03:59:08 +02:00
|
|
|
impl<T> From<UniqueRef<T>> for UniquePtr<T> {
|
2020-01-21 16:03:42 +01:00
|
|
|
fn from(unique_ref: UniqueRef<T>) -> Self {
|
2020-04-16 03:01:16 +02:00
|
|
|
Self(Some(unique_ref))
|
2020-01-21 16:03:42 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-16 03:59:08 +02:00
|
|
|
impl<T> Deref for UniquePtr<T> {
|
2020-04-16 03:01:16 +02:00
|
|
|
type Target = Option<UniqueRef<T>>;
|
2019-10-17 16:46:54 -07:00
|
|
|
fn deref(&self) -> &Self::Target {
|
2019-10-22 14:52:43 -07:00
|
|
|
&self.0
|
2019-10-17 16:46:54 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-16 03:59:08 +02:00
|
|
|
impl<T> DerefMut for UniquePtr<T> {
|
2019-10-17 16:46:54 -07:00
|
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
2019-10-22 14:52:43 -07:00
|
|
|
&mut self.0
|
2019-10-17 16:46:54 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-20 13:34:32 -08:00
|
|
|
/// Pointer to object allocated on the C++ heap. The pointer may not be null.
|
|
|
|
#[repr(transparent)]
|
2020-04-16 03:59:08 +02:00
|
|
|
pub struct UniqueRef<T>(NonNull<T>);
|
2019-11-20 13:34:32 -08:00
|
|
|
|
2020-04-16 03:59:08 +02:00
|
|
|
impl<T> UniqueRef<T> {
|
|
|
|
unsafe fn try_from_raw(ptr: *mut T) -> Option<Self> {
|
|
|
|
assert_unique_type_compatible::<Self, T>();
|
|
|
|
NonNull::new(ptr).map(Self)
|
2020-01-21 16:03:42 +01:00
|
|
|
}
|
|
|
|
|
2020-04-16 03:01:16 +02:00
|
|
|
pub unsafe fn from_raw(ptr: *mut T) -> Self {
|
|
|
|
Self::try_from_raw(ptr).unwrap()
|
2019-11-20 13:34:32 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn into_raw(self) -> *mut T {
|
2020-04-16 03:01:16 +02:00
|
|
|
let ptr = self.0.as_ptr();
|
|
|
|
forget(self);
|
|
|
|
ptr
|
|
|
|
}
|
|
|
|
|
2020-04-16 03:59:08 +02:00
|
|
|
pub fn make_shared(self) -> SharedRef<T>
|
|
|
|
where
|
|
|
|
T: Shared,
|
|
|
|
{
|
|
|
|
self.into()
|
2019-11-20 13:34:32 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-16 03:59:08 +02:00
|
|
|
impl<T> Deref for UniqueRef<T> {
|
2020-01-21 16:03:42 +01:00
|
|
|
type Target = T;
|
2019-11-20 13:34:32 -08:00
|
|
|
fn deref(&self) -> &Self::Target {
|
2020-04-16 03:01:16 +02:00
|
|
|
unsafe { self.0.as_ref() }
|
2019-11-20 13:34:32 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-16 03:59:08 +02:00
|
|
|
impl<T> DerefMut for UniqueRef<T> {
|
2019-11-20 13:34:32 -08:00
|
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
2020-04-16 03:01:16 +02:00
|
|
|
unsafe { self.0.as_mut() }
|
2019-11-20 13:34:32 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-16 03:59:08 +02:00
|
|
|
impl<T> Drop for UniqueRef<T> {
|
2019-11-20 13:34:32 -08:00
|
|
|
fn drop(&mut self) {
|
2020-04-16 03:59:08 +02:00
|
|
|
unsafe { drop_in_place(self.0.as_ptr()) }
|
2019-11-20 13:34:32 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-16 03:59:08 +02:00
|
|
|
fn assert_unique_type_compatible<U, T>() {
|
|
|
|
// Assert that `U` (a `UniqueRef` or `UniquePtr`) has the same memory layout
|
|
|
|
// as a pointer to `T`.
|
|
|
|
assert_eq!(size_of::<U>(), size_of::<*mut T>());
|
|
|
|
assert_eq!(align_of::<U>(), align_of::<*mut T>());
|
|
|
|
|
|
|
|
// Assert that `T` (probably) implements `Drop`. If it doesn't, a regular
|
|
|
|
// reference should be used instead of UniquePtr/UniqueRef.
|
|
|
|
assert!(needs_drop::<T>());
|
|
|
|
}
|
|
|
|
|
2019-12-26 03:32:22 +01:00
|
|
|
pub trait Shared
|
|
|
|
where
|
2020-04-16 03:59:08 +02:00
|
|
|
Self: Sized,
|
2019-12-26 03:32:22 +01:00
|
|
|
{
|
2020-01-22 21:53:19 +01:00
|
|
|
fn clone(shared_ptr: *const SharedRef<Self>) -> SharedRef<Self>;
|
2020-01-21 16:03:42 +01:00
|
|
|
fn from_unique(unique: UniqueRef<Self>) -> SharedRef<Self>;
|
2019-12-26 03:32:22 +01:00
|
|
|
fn deref(shared_ptr: *const SharedRef<Self>) -> *mut Self;
|
|
|
|
fn reset(shared_ptr: *mut SharedRef<Self>);
|
|
|
|
fn use_count(shared_ptr: *const SharedRef<Self>) -> 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<T>([*mut Opaque; 2], PhantomData<T>)
|
|
|
|
where
|
|
|
|
T: Shared;
|
|
|
|
|
2020-01-21 16:03:42 +01:00
|
|
|
unsafe impl<T> Send for SharedRef<T> where T: Shared + Send {}
|
|
|
|
|
2019-12-26 03:32:22 +01:00
|
|
|
impl<T> SharedRef<T>
|
|
|
|
where
|
|
|
|
T: Shared,
|
|
|
|
{
|
|
|
|
pub fn use_count(&self) -> long {
|
|
|
|
<T as Shared>::use_count(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-22 21:53:19 +01:00
|
|
|
impl<T> Clone for SharedRef<T>
|
|
|
|
where
|
|
|
|
T: Shared,
|
|
|
|
{
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
<T as Shared>::clone(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-21 16:03:42 +01:00
|
|
|
impl<T> From<UniqueRef<T>> for SharedRef<T>
|
|
|
|
where
|
2020-04-16 03:59:08 +02:00
|
|
|
T: Shared,
|
2020-01-21 16:03:42 +01:00
|
|
|
{
|
|
|
|
fn from(unique: UniqueRef<T>) -> Self {
|
|
|
|
<T as Shared>::from_unique(unique)
|
|
|
|
}
|
|
|
|
}
|
2019-12-30 22:48:08 +01:00
|
|
|
|
2019-12-26 03:32:22 +01:00
|
|
|
impl<T> Deref for SharedRef<T>
|
|
|
|
where
|
|
|
|
T: Shared,
|
|
|
|
{
|
2020-01-22 22:29:03 +01:00
|
|
|
type Target = UnsafeCell<T>;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
unsafe { &*(<T as Shared>::deref(self) as *const UnsafeCell<T>) }
|
2019-12-26 03:32:22 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> DerefMut for SharedRef<T>
|
|
|
|
where
|
|
|
|
T: Shared,
|
|
|
|
{
|
2020-01-22 22:29:03 +01:00
|
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
|
|
unsafe { &mut *(<T as Shared>::deref(self) as *mut UnsafeCell<T>) }
|
2019-12-26 03:32:22 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Drop for SharedRef<T>
|
|
|
|
where
|
|
|
|
T: Shared,
|
|
|
|
{
|
|
|
|
fn drop(&mut self) {
|
|
|
|
<T as Shared>::reset(self);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-18 15:05:33 +01:00
|
|
|
#[repr(C)]
|
2019-12-24 16:10:40 -05:00
|
|
|
#[derive(Debug, PartialEq)]
|
2020-01-22 22:58:31 +01:00
|
|
|
pub(crate) enum MaybeBool {
|
2019-12-18 15:05:33 +01:00
|
|
|
JustFalse = 0,
|
|
|
|
JustTrue = 1,
|
|
|
|
Nothing = 2,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Into<Option<bool>> for MaybeBool {
|
|
|
|
fn into(self) -> Option<bool> {
|
|
|
|
match self {
|
|
|
|
MaybeBool::JustFalse => Some(false),
|
|
|
|
MaybeBool::JustTrue => Some(true),
|
|
|
|
MaybeBool::Nothing => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-06 14:57:15 -05:00
|
|
|
#[derive(Copy, Clone)]
|
2019-10-17 16:46:54 -07:00
|
|
|
#[repr(transparent)]
|
|
|
|
pub struct CxxVTable(pub *const Opaque);
|
|
|
|
|
2020-01-06 14:57:15 -05:00
|
|
|
#[derive(Copy, Clone)]
|
2019-10-16 15:47:34 -07:00
|
|
|
pub struct RustVTable<DynT>(pub *const Opaque, pub PhantomData<DynT>);
|
|
|
|
|
|
|
|
pub struct FieldOffset<F>(usize, PhantomData<F>);
|
|
|
|
|
|
|
|
unsafe impl<F> Send for FieldOffset<F> where F: Send {}
|
|
|
|
unsafe impl<F> Sync for FieldOffset<F> where F: Sync {}
|
2019-10-20 16:10:40 -07:00
|
|
|
|
2019-10-16 15:47:34 -07:00
|
|
|
impl<F> Copy for FieldOffset<F> {}
|
|
|
|
|
|
|
|
impl<F> Clone for FieldOffset<F> {
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
Self(self.0, self.1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<F> FieldOffset<F> {
|
|
|
|
pub fn from_ptrs<E>(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::<F>()) <= (embedder_addr + size_of::<E>()));
|
2019-10-22 15:46:42 -07:00
|
|
|
Self(field_addr - embedder_addr, PhantomData)
|
2019-10-16 15:47:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
pub unsafe fn to_embedder<E>(self, field: &F) -> &E {
|
|
|
|
(((field as *const _ as usize) - self.0) as *const E)
|
|
|
|
.as_ref()
|
|
|
|
.unwrap()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub unsafe fn to_embedder_mut<E>(self, field: &mut F) -> &mut E {
|
|
|
|
(((field as *mut _ as usize) - self.0) as *mut E)
|
|
|
|
.as_mut()
|
|
|
|
.unwrap()
|
|
|
|
}
|
|
|
|
}
|
2020-01-03 12:17:11 -05:00
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
#[derive(Default)]
|
|
|
|
pub struct Maybe<T> {
|
|
|
|
has_value: bool,
|
|
|
|
value: T,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Into<Option<T>> for Maybe<T> {
|
|
|
|
fn into(self) -> Option<T> {
|
|
|
|
if self.has_value {
|
|
|
|
Some(self.value)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-01-14 21:06:41 +01:00
|
|
|
|
|
|
|
pub trait UnitType
|
|
|
|
where
|
|
|
|
Self: Copy + Sized,
|
|
|
|
{
|
|
|
|
#[inline(always)]
|
|
|
|
fn get() -> Self {
|
|
|
|
UnitValue::<Self>::get()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> UnitType for T where T: Copy + Sized {}
|
|
|
|
|
|
|
|
#[derive(Copy, Clone)]
|
|
|
|
struct UnitValue<T>(PhantomData<T>)
|
|
|
|
where
|
|
|
|
Self: Sized;
|
|
|
|
|
|
|
|
impl<T> UnitValue<T>
|
|
|
|
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::<T>();
|
|
|
|
let s = Self(PhantomData::<T>);
|
|
|
|
[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::<T>(), 0);
|
|
|
|
unsafe { std::mem::MaybeUninit::<T>::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<F, Tag = DefaultTag>
|
|
|
|
where
|
|
|
|
F: UnitType,
|
|
|
|
Self: Sized,
|
|
|
|
{
|
|
|
|
fn mapping() -> Self;
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
fn map_fn_from(_: F) -> Self {
|
|
|
|
Self::mapping()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<F> MapFnFrom<F, IdenticalConversionTag> for F
|
|
|
|
where
|
|
|
|
Self: UnitType,
|
|
|
|
{
|
|
|
|
#[inline(always)]
|
|
|
|
fn mapping() -> Self {
|
|
|
|
Self::get()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait MapFnTo<T, Tag = DefaultTag>
|
|
|
|
where
|
|
|
|
Self: UnitType,
|
|
|
|
T: Sized,
|
|
|
|
{
|
|
|
|
fn mapping() -> T;
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
fn map_fn_to(self) -> T {
|
|
|
|
Self::mapping()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<F, T, Tag> MapFnTo<T, Tag> for F
|
|
|
|
where
|
|
|
|
Self: UnitType,
|
|
|
|
T: MapFnFrom<F, Tag>,
|
|
|
|
{
|
|
|
|
#[inline(always)]
|
|
|
|
fn mapping() -> T {
|
|
|
|
T::map_fn_from(F::get())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait CFnFrom<F>
|
|
|
|
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<F, R, $($ty),*> CFnFrom<F> for extern "C" fn($($ty),*) -> R
|
|
|
|
where
|
|
|
|
F: UnitType + Fn($($ty),*) -> R,
|
|
|
|
{
|
|
|
|
#[inline(always)]
|
|
|
|
fn mapping() -> Self {
|
|
|
|
extern "C" fn c_fn<F, R, $($ty),*>($($arg: $ty),*) -> R
|
|
|
|
where
|
|
|
|
F: UnitType + Fn($($ty),*) -> R,
|
|
|
|
{
|
|
|
|
(F::get())($($arg),*)
|
|
|
|
};
|
|
|
|
c_fn::<F, R, $($ty),*>
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
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<T>
|
|
|
|
where
|
|
|
|
Self: UnitType,
|
|
|
|
T: Sized,
|
|
|
|
{
|
|
|
|
fn mapping() -> T;
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
fn to_c_fn(self) -> T {
|
|
|
|
Self::mapping()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<F, T> ToCFn<T> for F
|
|
|
|
where
|
|
|
|
Self: UnitType,
|
|
|
|
T: CFnFrom<F>,
|
|
|
|
{
|
|
|
|
#[inline(always)]
|
|
|
|
fn mapping() -> T {
|
|
|
|
T::c_fn_from(F::get())
|
|
|
|
}
|
|
|
|
}
|