#![allow(clippy::borrow_as_ptr)]
use core::marker::{PhantomData, Send, Sync};
use std::{
marker::PhantomPinned,
ops::{Deref, DerefMut},
pin::Pin,
ptr::NonNull,
};
pub unsafe trait AbiSafeUnsize<T>: AbiSafeTrait {
fn construct_vtable_for() -> &'static Self::VTable;
}
pub unsafe trait FromReciever {
type Target;
unsafe fn from_raw_ptr(x: *mut ()) -> Self;
}
unsafe impl<'lt, T> FromReciever for &'lt mut T {
type Target = T;
unsafe fn from_raw_ptr(x: *mut ()) -> &'lt mut T {
&mut *(x.cast::<T>())
}
}
unsafe impl<'lt, T> FromReciever for &'lt T {
type Target = T;
unsafe fn from_raw_ptr(x: *mut ()) -> &'lt T {
&*(x.cast::<T>())
}
}
unsafe impl<P: FromReciever> FromReciever for Pin<P>
where
P: Deref<Target = <P as FromReciever>::Target>,
{
type Target = <P as FromReciever>::Target;
unsafe fn from_raw_ptr(x: *mut ()) -> Self {
Self::new_unchecked(P::from_raw_ptr(x))
}
}
pub unsafe trait AbiSafeReciever<T: ?Sized + AbiSafeTrait> {}
unsafe impl<T: ?Sized + AbiSafeTrait> AbiSafeReciever<T> for &mut T {}
unsafe impl<T: ?Sized + AbiSafeTrait> AbiSafeReciever<T> for &T {}
unsafe impl<T: ?Sized + AbiSafeTrait, P: Deref + AbiSafeReciever<T>> AbiSafeReciever<T> for Pin<P> {}
pub unsafe trait AbiSafeTrait {
type VTable: AbiSafeVTable<Self> + 'static;
}
#[repr(C)]
pub struct AbiSafeVTableHead {
pub size: usize,
pub align: usize,
pub destructor: Option<xlang_host::rustcall!(unsafe extern "rustcall" fn(*mut ()))>,
pub reserved_deallocate: Option<xlang_host::rustcall!(unsafe extern "rustcall" fn(*mut ()))>,
}
pub unsafe trait AbiSafeVTable<T: ?Sized>: Sized {
fn size_of(&self) -> usize {
unsafe { (*(self as *const Self).cast::<AbiSafeVTableHead>()).size }
}
fn align_of(&self) -> usize {
unsafe { (*(self as *const Self).cast::<AbiSafeVTableHead>()).align }
}
#[allow(unused_unsafe)]
unsafe fn drop_in_place(&self, ptr: *mut ()) {
if let Some(f) = unsafe { (*(self as *const Self).cast::<AbiSafeVTableHead>()).destructor }
{
unsafe { (f)(ptr) };
}
}
}
#[allow(clippy::doc_markdown)]
pub unsafe trait TrustedVTable<T: ?Sized>: AbiSafeVTable<T> {}
use crate::alloc::{Allocator, XLangAlloc};
#[repr(C)]
pub struct DynPtr<T: ?Sized + AbiSafeTrait> {
pub ptr: *mut (),
pub vtable: &'static <T as AbiSafeTrait>::VTable,
phantom: PhantomData<*const T>,
}
impl<T: ?Sized + AbiSafeTrait> DynPtr<T> {
pub fn unsize_raw<U>(x: *mut U) -> Self
where
T: AbiSafeUnsize<U>,
{
Self {
ptr: x.cast::<()>(),
vtable: T::construct_vtable_for(),
phantom: PhantomData,
}
}
pub fn from_ptr_vtable(ptr: *mut (), vtable: &'static <T as AbiSafeTrait>::VTable) -> Self {
Self {
ptr,
vtable,
phantom: PhantomData,
}
}
#[must_use]
pub unsafe fn into_ref<'lt>(self) -> DynRef<'lt, T> {
DynRef {
inner: self,
phantom: PhantomData,
}
}
#[must_use]
pub unsafe fn into_mut<'lt>(self) -> DynMut<'lt, T> {
DynMut {
inner: self,
phantom: PhantomData,
}
}
}
impl<T: ?Sized + AbiSafeTrait> Clone for DynPtr<T> {
fn clone(&self) -> Self {
Self { ..*self }
}
}
impl<T: ?Sized + AbiSafeTrait> Copy for DynPtr<T> {}
#[repr(C)]
pub struct DynRef<'lt, T: ?Sized + AbiSafeTrait> {
inner: DynPtr<T>,
phantom: PhantomData<&'lt T>,
}
impl<'lt, T: ?Sized + AbiSafeTrait> DynRef<'lt, T> {
#[must_use]
pub fn as_pinned(x: &Pin<Self>) -> Pin<&(dyn DynPtrSafe<T> + 'lt)> {
x.as_ref()
}
pub fn unsize_ref<U>(x: &'lt U) -> Self
where
T: AbiSafeUnsize<U>,
{
Self {
inner: DynPtr::unsize_raw(x as *const U as *mut U),
phantom: PhantomData,
}
}
}
impl<'lt, T: ?Sized + AbiSafeTrait> Clone for DynRef<'lt, T> {
fn clone(&self) -> Self {
Self { ..*self }
}
}
impl<'lt, T: ?Sized + AbiSafeTrait> Copy for DynRef<'lt, T> {}
unsafe impl<'lt, T: ?Sized + AbiSafeTrait + Sync> Send for DynRef<'lt, T> {}
unsafe impl<'lt, T: ?Sized + AbiSafeTrait + Sync> Sync for DynRef<'lt, T> {}
impl<'lt, T: ?Sized + AbiSafeTrait> Deref for DynRef<'lt, T> {
type Target = dyn DynPtrSafe<T> + 'lt;
fn deref(&self) -> &Self::Target {
unsafe { &*((&self.inner as *const DynPtr<T>).cast::<DynPtrSafeWrap<T>>()) }
}
}
pub unsafe trait DynPtrSafe<T: ?Sized + AbiSafeTrait> {
fn as_raw(&self) -> *const ();
fn as_raw_mut(&mut self) -> *mut ();
fn vtable(&self) -> &'static T::VTable;
fn size_of_val(&self) -> usize {
self.vtable().size_of()
}
fn align_of_val(&self) -> usize {
self.vtable().align_of()
}
}
#[repr(transparent)]
struct DynPtrSafeWrap<T: ?Sized + AbiSafeTrait> {
inner: DynPtr<T>,
_pin: PhantomPinned,
phantom: PhantomData<T>,
}
impl<T: ?Sized + AbiSafeTrait + Unpin> Unpin for DynPtrSafeWrap<T> {}
unsafe impl<T: ?Sized + AbiSafeTrait + Send> Send for DynPtrSafeWrap<T> {}
unsafe impl<T: ?Sized + AbiSafeTrait + Sync> Sync for DynPtrSafeWrap<T> {}
unsafe impl<T: ?Sized + AbiSafeTrait> DynPtrSafe<T> for DynPtrSafeWrap<T> {
fn as_raw(&self) -> *const () {
self.inner.ptr
}
fn as_raw_mut(&mut self) -> *mut () {
self.inner.ptr
}
fn vtable(&self) -> &'static T::VTable {
self.inner.vtable
}
}
#[repr(transparent)]
pub struct DynMut<'lt, T: ?Sized + AbiSafeTrait> {
inner: DynPtr<T>,
phantom: PhantomData<&'lt mut T>,
}
impl<'lt, T: ?Sized + AbiSafeTrait> DynMut<'lt, T> {
#[must_use]
pub fn as_ref(&self) -> DynRef<T> {
DynRef {
inner: self.inner,
phantom: PhantomData,
}
}
#[must_use]
pub fn into_ref(self) -> DynRef<'lt, T> {
DynRef {
inner: self.inner,
phantom: PhantomData,
}
}
pub fn unsize_mut<U>(r: &'lt mut U) -> Self
where
T: AbiSafeUnsize<U>,
{
DynMut {
inner: DynPtr::unsize_raw(r),
phantom: PhantomData,
}
}
pub fn as_pinned_mut(x: &mut Pin<Self>) -> Pin<&mut (dyn DynPtrSafe<T> + 'lt)> {
x.as_mut()
}
#[must_use]
pub fn as_pinned(x: &Pin<Self>) -> Pin<&dyn DynPtrSafe<T>> {
x.as_ref()
}
pub fn reborrow_mut(&mut self) -> DynMut<T> {
DynMut {
inner: self.inner,
phantom: PhantomData,
}
}
}
unsafe impl<'lt, T: ?Sized + AbiSafeTrait + Send> Send for DynMut<'lt, T> {}
unsafe impl<'lt, T: ?Sized + AbiSafeTrait + Sync> Sync for DynMut<'lt, T> {}
impl<'lt, T: ?Sized + AbiSafeTrait> Deref for DynMut<'lt, T> {
type Target = dyn DynPtrSafe<T> + 'lt;
fn deref(&self) -> &Self::Target {
unsafe { &*((&self.inner as *const DynPtr<T>).cast::<DynPtrSafeWrap<T>>()) }
}
}
impl<'lt, T: ?Sized + AbiSafeTrait> DerefMut for DynMut<'lt, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *((&mut self.inner as *mut DynPtr<T>).cast::<DynPtrSafeWrap<T>>()) }
}
}
#[repr(C)]
pub struct DynBox<T: ?Sized + AbiSafeTrait, A: Allocator = XLangAlloc> {
ptr: DynPtr<T>,
phantom: PhantomData<T>,
alloc: A,
}
unsafe impl<T: ?Sized + AbiSafeTrait + Send, A: Allocator + Send> Send for DynBox<T, A> {}
unsafe impl<T: ?Sized + AbiSafeTrait + Sync, A: Allocator + Sync> Sync for DynBox<T, A> {}
impl<T: ?Sized + AbiSafeTrait, A: Allocator> DynBox<T, A> {
pub fn unsize_box<U>(x: crate::boxed::Box<U, A>) -> Self
where
T: AbiSafeUnsize<U>,
{
let (ptr, alloc) = crate::boxed::Box::into_raw_with_alloc(x);
let ptr = DynPtr::unsize_raw(ptr);
Self {
ptr,
phantom: PhantomData,
alloc,
}
}
}
impl<T: ?Sized + AbiSafeTrait, A: Allocator> Drop for DynBox<T, A> {
fn drop(&mut self) {
let layout = unsafe {
crate::alloc::Layout::from_size_align_unchecked(
self.ptr.vtable.size_of(),
self.ptr.vtable.align_of(),
)
};
let ptr = self.ptr.ptr;
unsafe {
self.alloc
.deallocate(NonNull::new_unchecked(ptr.cast()), layout);
}
}
}
impl<T: ?Sized + AbiSafeTrait + 'static, A: Allocator> Deref for DynBox<T, A> {
type Target = dyn DynPtrSafe<T>;
fn deref(&self) -> &(dyn DynPtrSafe<T> + 'static) {
unsafe { &*((&self.ptr as *const DynPtr<T>).cast::<DynPtrSafeWrap<T>>()) }
}
}
impl<T: ?Sized + AbiSafeTrait + 'static, A: Allocator> DerefMut for DynBox<T, A> {
fn deref_mut(&mut self) -> &mut (dyn DynPtrSafe<T> + 'static) {
unsafe { &mut *((&mut self.ptr as *mut DynPtr<T>).cast::<DynPtrSafeWrap<T>>()) }
}
}