use super::*;
use std::fmt;
#[allow(unused_imports)]
use core_extensions::SelfOps;
use crate::{
abi_stability::PrefixStableAbi,
erased_types::{c_functions::adapt_std_fmt, InterfaceType, MakeRequiredTraits},
pointer_trait::{
AsMutPtr, AsPtr, CanTransmuteElement, GetPointerKind, PK_Reference, PK_SmartPointer,
PointerKind, TransmuteElement,
},
sabi_trait::vtable::{BaseVtable_Prefix, BaseVtable_Ref},
sabi_types::{MaybeCmp, RMut, RRef},
std_types::UTypeId,
type_level::{
impl_enum::{Implemented, Unimplemented},
trait_marker,
},
StableAbi,
};
#[repr(C)]
#[derive(StableAbi)]
#[sabi(
not_stableabi(V),
bound(V: PrefixStableAbi),
bound(I: InterfaceType),
extra_checks = <I as MakeRequiredTraits>::MAKE,
)]
pub struct RObject<'lt, P, I, V>
where
P: GetPointerKind,
{
vtable: PrefixRef<V>,
ptr: ManuallyDrop<P>,
_marker: PhantomData<(&'lt (), extern "C" fn() -> I)>,
}
mod clone_impl {
pub trait CloneImpl<PtrKind> {
fn clone_impl(&self) -> Self;
}
}
use self::clone_impl::CloneImpl;
impl<'lt, P, I, V> CloneImpl<PK_SmartPointer> for RObject<'lt, P, I, V>
where
P: AsPtr,
I: InterfaceType<Clone = Implemented<trait_marker::Clone>>,
{
fn clone_impl(&self) -> Self {
let ptr =
unsafe { self.sabi_robject_vtable()._sabi_clone().unwrap()(RRef::new(&self.ptr)) };
Self {
vtable: self.vtable,
ptr: ManuallyDrop::new(ptr),
_marker: PhantomData,
}
}
}
impl<'lt, P, I, V> CloneImpl<PK_Reference> for RObject<'lt, P, I, V>
where
P: AsPtr + Copy,
I: InterfaceType,
{
fn clone_impl(&self) -> Self {
Self {
vtable: self.vtable,
ptr: ManuallyDrop::new(*self.ptr),
_marker: PhantomData,
}
}
}
impl<'lt, P, I, V> Clone for RObject<'lt, P, I, V>
where
P: AsPtr,
I: InterfaceType,
Self: CloneImpl<<P as GetPointerKind>::Kind>,
{
fn clone(&self) -> Self {
self.clone_impl()
}
}
impl<'lt, P, I, V> Debug for RObject<'lt, P, I, V>
where
P: AsPtr<PtrTarget = ()> + AsPtr,
I: InterfaceType<Debug = Implemented<trait_marker::Debug>>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
unsafe {
adapt_std_fmt::<ErasedObject>(
self.sabi_erased_ref(),
self.sabi_robject_vtable()._sabi_debug().unwrap(),
f,
)
}
}
}
impl<'lt, P, I, V> Display for RObject<'lt, P, I, V>
where
P: AsPtr<PtrTarget = ()>,
I: InterfaceType<Display = Implemented<trait_marker::Display>>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
unsafe {
adapt_std_fmt::<ErasedObject>(
self.sabi_erased_ref(),
self.sabi_robject_vtable()._sabi_display().unwrap(),
f,
)
}
}
}
impl<'lt, P, I, V> std::error::Error for RObject<'lt, P, I, V>
where
P: AsPtr<PtrTarget = ()>,
I: InterfaceType<
Display = Implemented<trait_marker::Display>,
Debug = Implemented<trait_marker::Debug>,
Error = Implemented<trait_marker::Error>,
>,
{
}
unsafe impl<'lt, P, I, V> Send for RObject<'lt, P, I, V>
where
P: GetPointerKind,
I: InterfaceType<Send = Implemented<trait_marker::Send>>,
{
}
unsafe impl<'lt, P, I, V> Sync for RObject<'lt, P, I, V>
where
P: GetPointerKind,
I: InterfaceType<Sync = Implemented<trait_marker::Sync>>,
{
}
impl<'lt, P, I, V> Unpin for RObject<'lt, P, I, V>
where
P: GetPointerKind,
I: InterfaceType<Unpin = Implemented<trait_marker::Unpin>>,
{
}
impl<'lt, P, I, V> RObject<'lt, P, I, V>
where
P: AsPtr<PtrTarget = ()>,
{
pub unsafe fn with_vtable<OrigPtr>(ptr: OrigPtr, vtable: PrefixRef<V>) -> RObject<'lt, P, I, V>
where
OrigPtr: CanTransmuteElement<(), TransmutedPtr = P>,
OrigPtr::PtrTarget: Sized + 'lt,
P: AsPtr<PtrTarget = ()>,
{
RObject {
vtable,
ptr: ManuallyDrop::new(unsafe { ptr.transmute_element::<()>() }),
_marker: PhantomData,
}
}
}
impl<'borr, 'a, I, V> RObject<'borr, RRef<'a, ()>, I, V> {
pub const unsafe fn with_vtable_const<T, Downcasting>(ptr: &'a T, vtable: PrefixRef<V>) -> Self
where
T: 'borr,
{
RObject {
vtable,
ptr: {
let x = unsafe { RRef::new(ptr).transmute::<()>() };
ManuallyDrop::new(x)
},
_marker: PhantomData,
}
}
}
impl<'lt, P, I, V> RObject<'lt, P, I, V>
where
P: GetPointerKind,
{
fn sabi_check_same_utypeid<T>(&self) -> Result<(), UneraseError<()>>
where
T: 'static,
{
let expected_typeid = self.sabi_robject_vtable()._sabi_type_id()();
let actual_typeid = UTypeId::new::<T>();
if expected_typeid == MaybeCmp::Just(actual_typeid) {
Ok(())
} else {
Err(UneraseError {
robject: (),
expected_typeid,
actual_typeid,
})
}
}
pub fn downcast_into<T>(self) -> Result<P::TransmutedPtr, UneraseError<Self>>
where
T: 'static,
P: AsPtr<PtrTarget = ()> + CanTransmuteElement<T>,
{
check_unerased!(self, self.sabi_check_same_utypeid::<T>());
unsafe {
let this = ManuallyDrop::new(self);
Ok(ptr::read(&*this.ptr).transmute_element::<T>())
}
}
pub fn downcast_as<T>(&self) -> Result<&T, UneraseError<&Self>>
where
T: 'static,
P: AsPtr<PtrTarget = ()> + CanTransmuteElement<T>,
{
check_unerased!(self, self.sabi_check_same_utypeid::<T>());
unsafe { Ok(&*(self.ptr.as_ptr() as *const T)) }
}
pub fn downcast_as_mut<T>(&mut self) -> Result<&mut T, UneraseError<&mut Self>>
where
T: 'static,
P: AsMutPtr<PtrTarget = ()> + CanTransmuteElement<T>,
{
check_unerased!(self, self.sabi_check_same_utypeid::<T>());
unsafe { Ok(&mut *(self.ptr.as_mut_ptr() as *mut T)) }
}
#[inline]
pub unsafe fn unchecked_downcast_into<T>(self) -> P::TransmutedPtr
where
P: AsPtr<PtrTarget = ()> + CanTransmuteElement<T>,
{
let this = ManuallyDrop::new(self);
unsafe { ptr::read(&*this.ptr).transmute_element::<T>() }
}
#[inline]
pub unsafe fn unchecked_downcast_as<T>(&self) -> &T
where
P: AsPtr<PtrTarget = ()>,
{
unsafe { &*(self.ptr.as_ptr() as *const T) }
}
#[inline]
pub unsafe fn unchecked_downcast_as_mut<T>(&mut self) -> &mut T
where
P: AsMutPtr<PtrTarget = ()>,
{
unsafe { &mut *(self.ptr.as_mut_ptr() as *mut T) }
}
}
mod private_struct {
pub struct PrivStruct;
}
use self::private_struct::PrivStruct;
pub trait ReborrowBounds<SendNess, SyncNess> {}
impl ReborrowBounds<Unimplemented<trait_marker::Send>, Unimplemented<trait_marker::Sync>>
for PrivStruct
{
}
impl ReborrowBounds<Implemented<trait_marker::Send>, Implemented<trait_marker::Sync>>
for PrivStruct
{
}
impl<'lt, P, I, V> RObject<'lt, P, I, V>
where
P: GetPointerKind,
I: InterfaceType,
{
pub fn reborrow<'re>(&'re self) -> RObject<'lt, RRef<'re, ()>, I, V>
where
P: AsPtr<PtrTarget = ()>,
PrivStruct: ReborrowBounds<I::Send, I::Sync>,
{
RObject {
vtable: self.vtable,
ptr: ManuallyDrop::new(self.ptr.as_rref()),
_marker: PhantomData,
}
}
pub fn reborrow_mut<'re>(&'re mut self) -> RObject<'lt, RMut<'re, ()>, I, V>
where
P: AsMutPtr<PtrTarget = ()>,
PrivStruct: ReborrowBounds<I::Send, I::Sync>,
{
RObject {
vtable: self.vtable,
ptr: ManuallyDrop::new(self.ptr.as_rmut()),
_marker: PhantomData,
}
}
}
impl<'lt, P, I, V> RObject<'lt, P, I, V>
where
P: GetPointerKind,
{
#[inline]
pub const fn sabi_et_vtable(&self) -> PrefixRef<V> {
self.vtable
}
#[inline]
pub fn sabi_robject_vtable(&self) -> RObjectVtable_Ref<(), P, I> {
unsafe { BaseVtable_Ref(self.vtable.cast::<BaseVtable_Prefix<(), P, I>>())._sabi_vtable() }
}
#[inline]
fn sabi_into_erased_ptr(self) -> ManuallyDrop<P> {
let __this = ManuallyDrop::new(self);
unsafe { ptr::read(&__this.ptr) }
}
pub fn sabi_erased_ref(&self) -> RRef<'_, ErasedObject<()>>
where
P: AsPtr<PtrTarget = ()>,
{
unsafe { RRef::from_raw(self.ptr.as_ptr() as *const _) }
}
pub fn sabi_erased_mut(&mut self) -> RMut<'_, ErasedObject<()>>
where
P: AsMutPtr<PtrTarget = ()>,
{
unsafe { RMut::from_raw(self.ptr.as_mut_ptr() as *mut _) }
}
pub fn sabi_as_rref(&self) -> RRef<'_, ()>
where
P: AsPtr<PtrTarget = ()>,
{
self.ptr.as_rref()
}
pub fn sabi_as_rmut(&mut self) -> RMut<'_, ()>
where
P: AsMutPtr<PtrTarget = ()>,
{
self.ptr.as_rmut()
}
#[inline]
pub fn sabi_with_value<F, R>(self, f: F) -> R
where
P: OwnedPointer<PtrTarget = ()>,
F: FnOnce(MovePtr<'_, ()>) -> R,
{
OwnedPointer::with_move_ptr(self.sabi_into_erased_ptr(), f)
}
}
impl<'lt, I, V> RObject<'lt, crate::std_types::RArc<()>, I, V> {
pub fn shallow_clone(&self) -> Self {
Self {
vtable: self.vtable,
ptr: self.ptr.clone(),
_marker: PhantomData,
}
}
}
impl<P, I, V> Drop for RObject<'_, P, I, V>
where
P: GetPointerKind,
{
fn drop(&mut self) {
if <P as GetPointerKind>::KIND == PointerKind::SmartPointer {
let destructor = self.sabi_robject_vtable()._sabi_drop();
unsafe {
destructor(RMut::<P>::new(&mut self.ptr));
}
}
}
}
#[derive(Copy, Clone)]
pub struct UneraseError<T> {
robject: T,
expected_typeid: MaybeCmp<UTypeId>,
actual_typeid: UTypeId,
}
#[allow(clippy::missing_const_for_fn)]
impl<T> UneraseError<T> {
fn map<F, U>(self, f: F) -> UneraseError<U>
where
F: FnOnce(T) -> U,
{
UneraseError {
robject: f(self.robject),
expected_typeid: self.expected_typeid,
actual_typeid: self.actual_typeid,
}
}
#[must_use]
pub fn into_inner(self) -> T {
self.robject
}
}
impl<D> fmt::Debug for UneraseError<D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("UneraseError")
.field("dyn_trait", &"<not shown>")
.field("expected_typeid", &self.expected_typeid)
.field("actual_typeid", &self.actual_typeid)
.finish()
}
}
impl<D> fmt::Display for UneraseError<D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self, f)
}
}
impl<D> ::std::error::Error for UneraseError<D> {}